Unity에서 특정 순서로 키를 입력했는지 여부를 결정합니다.
개요
특정 순서로 키를 입력한 구조를 탐지해 봤다.
중간에 잘못되면 리셋되며 1부터 입력해야 합니다.
또한 첫 번째 문자를 입력한 후 일정 시간이 지나면 초기화하는 시간 초과 기능도 있다.
TypeChecker.cs
몸짓
입력하십시오
nekomimi
.5초 초과.키 입력 자체는 표시되지 않았지만, 이렇게 입력했다.
nekomi k
및 입력입력
ne
5초 대기nekomimi
및 입력구조기의 매개 변수로 교부
IProgress<(int numerator, int denominator)>
를 중도에 거쳐 typeChecker.OnComplete
에 등록된 활동.using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
namespace Nekomimi.Daimao
{
public class TypeCheckerExample : MonoBehaviour, IProgress<(int numerator, int denominator)>
{
private static readonly KeyCode[] Command =
{
KeyCode.N,
KeyCode.E,
KeyCode.K,
KeyCode.O,
KeyCode.M,
KeyCode.I,
KeyCode.M,
KeyCode.I,
};
[SerializeField]
private Slider _slider = default;
[SerializeField]
private Text _textSlider = default;
[SerializeField]
private Text _textComplete = default;
private void Start()
{
var typeChecker = new TypeChecker(Command, 5f, this, this.GetCancellationTokenOnDestroy());
typeChecker.OnComplete += () =>
{
_textComplete.text = "COMPLETE!";
Debug.Log("COMPLETE!");
};
}
public void Report((int numerator, int denominator) value)
{
var (numerator, denominator) = value;
_slider.maxValue = denominator;
_slider.value = numerator;
_textSlider.text = $"{numerator} / {denominator}";
Debug.Log($"progress {numerator} / {denominator}");
}
}
}
그나저나 UniTask
.v2
그런데 특별히 새로운 기능이 없어서 v1
도 갈 수 있어요.TypeChecker 컨텐트에 대한 설명
CurrentPressed
우선 가장 간단한 현재의 입력 키를 얻는 것부터 시작한다.
유니티는 기준을 얻지 못해 현재 어떤 키
API
를 눌렀는지 스스로 만들어야 한다.[1] 다소
Enum
의 배열이라고는 하지만 Update
마다 포환을 돌리면 저항력이 강해 가장 적합한 해결 방안이다.InputSystem
새로워진 것 같은데 이 근처에서도 살 수 있을까요?Enum
에서 None
에 속하지 않는 기본값이 끊겼으면 좋겠습니다.예의입니다./// <summary>
/// <see cref="KeyCodeAlphabet"/>に含まれている現在押されているキーを返す.
/// </summary>
/// <returns><see cref="KeyCode"/></returns>
private static KeyCode CurrentPressed()
{
if (!Input.anyKeyDown)
{
return KeyCode.None;
}
// every Update, no LINQ
foreach (var keyCode in KeyCodeAlphabet)
{
if (Input.GetKeyDown(keyCode))
{
return keyCode;
}
}
return KeyCode.None;
}
TypeCommandAsync
이것은 정확한 키를 연속으로 입력했는지 확인하는 데 쓰이는 것이다.
시간 초과 카운트다운을 시작하는 관계에 대해서는 첫 번째 자모만 이 방법 외에 판정된다.
그리고 1부터
KeyCode
의 for 순환을 시작합니다. 키 입력이 있을 때 기대하면 for 순환을 계속하고 다른 키라면 for 순환을 중지합니다.즉 for 순환을 종료할 때 = 필요한 모든 키를 입력할 때다.
for Loop에서 while Loop을 회전하는 것도 저한테는 촉감이 있지만 이것도 가장 적합한 해결 방법이라고 할 수 있겠죠...?
사용
goto
은 피하지만 이런 다중순환을 사용할 수밖에 없는 상황에서goto
는 오히려 이해하기 쉽다.근데 안 써봐서 싫어./// <summary>
/// キー入力を監視して正しく入力されたかを判定する.
/// 最初の1文字は判定しない.
/// </summary>
/// <param name="progress"><see cref="IProgress{T}"/> (分子/分母)</param>
/// <param name="token"><see cref="CancellationToken"/></param>
/// <returns>true/false = 成功/失敗</returns>
private async UniTask<bool> TypeCommandAsync(
IProgress<(int numerator, int denominator)> progress, CancellationToken token)
{
for (var count = 1; count < Command.Length; count++)
{
while (true)
{
await UniTask.Yield();
if (token.IsCancellationRequested)
{
return false;
}
var current = CurrentPressed();
if (current == KeyCode.None)
{
// 何も入力していない場合は判定しない
continue;
}
if (Command[count] != current)
{
// 違うキーが入力されたので中断する
return false;
}
// 求めているキーが入力されたので進捗を通知して次のキーに進む
progress?.Report((count + 1, Command.Length));
break;
}
}
return !token.IsCancellationRequested;
}
CheckTypeLoop
이것은 내가 이번에 가장 고민하는 곳이다.
UniTask.WhenAny
으로 단순한 시간 경과와 시간 초과 대상이 되는 처분 경쟁을 하고 시간 경과가 먼저 오면 처분을 멈추는 느낌.CancellationTokenSource
시간 초과 설정은 원래 이렇죠. 그런데 저는 아무렇게나 던지는 걸 싫어해요Exception
[2]. 그래서 시간초과UniTask.WhenAny
로 해결하기로 했어요.private async UniTaskVoid CheckTypeLoop(IProgress<(int numerator, int denominator)> progress, CancellationToken baseToken)
{
var first = Command[0];
while (true)
{
await UniTask.Yield();
if (baseToken.IsCancellationRequested)
{
return;
}
if (CurrentPressed() != first)
{
// 最初の1文字が入力されるまではタイムアウトも以後の判定も行わない
progress?.Report((0, Command.Length));
continue;
}
// 最初の1文字が入力された
progress?.Report((1, Command.Length));
var cancelSource = CancellationTokenSource.CreateLinkedTokenSource(baseToken);
var token = cancelSource.Token;
bool result;
// 1文字目以降のキーが順番に入力されたら完了する
var type = TypeCommandAsync(progress, token);
if (TimeoutSecond > 0f)
{
// タイムアウトが設定されている場合はカウントする
var timeout = UniTask.Delay(TimeSpan.FromSeconds(TimeoutSecond), cancellationToken: token);
var (hasResultLeft, ret) = await UniTask.WhenAny(type, timeout);
// キー入力のtaskが先に完了してかつそれがtrue
result = hasResultLeft && ret;
}
else
{
// タイムアウトを待たない場合はキー入力の結果だけを待つ
result = await type;
}
if (result)
{
OnComplete?.Invoke();
}
if (!cancelSource.IsCancellationRequested)
{
cancelSource.Cancel();
}
}
}
호출 시스템 같은 거.
나도 분명히 구조기의 매개 변수에서
IProgress
를 얻으면 완성된다고 생각하지 않는다Action OnComplete
이후에 등록하는 것이 어떻고 어느 것으로 통일되겠는가. 그러나 대부분 용례에서 완성하면 된다. 구조기의 매개 변수가 너무 많아서 매일 따뜻하다.그나저나
IProgress
에서도 움직인다.총결산
디버그 기능을 몰래 시작하는 데 사용되는 숨겨진 명령 제조사입니다.
null
방법주위밖에아무것도 안보고했는데,이건타자게임같은코드참고해야하는거 아닌가...?하고 생각해 보니까"강아지가 쓴 건가?"💕」이런 코드에 계속 탔는데 요즘'기다리고 있나...?'이런 마음이지만 자신이 생각하는 예쁜 코드를 적으면'정의'를 되찾을 수 있다.이것은 메인 요리다.
그렇긴 한데 한 1~2주 정도 지났어요.💕」이렇게 말하면서 자신의 전선에 토마토를 넣었죠.진보는 이렇다.
끝.
각주
여자, 농담이야... ↩︎
시간 초과와 취소는 똑같다
Input
,투척된 C# 언어 규격은 도대체 어떻게 생각하는가...?↩︎ Reference
이 문제에 관하여(Unity에서 특정 순서로 키를 입력했는지 여부를 결정합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/nekomimi_daimao/articles/01a07dfe1e3754텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)