728x90
반응형
개요
기존 Unity Input System을 사용하기엔 너무 다양한 것들을 요구하기에 그냥 새로 구상
조건
- MLB Press (X); 마우스 왼쪽 클릭
- MRB Press (Y); 마우스 오른쪽 클릭
- Combine WASD (WASD+); 조합키
- Hold (~); 키 홀드
- Repeat (+); 키 반복입력
- Delay (_); 입력 없음, 이후 재입력 가능
- Check Button Release; 버튼 떼기 확인
- Input Stream; Input 저장
- Reset Inputs; 일정 시간 이후 Input Stream 초기화
- Check Available Command; Input Stream이 사용가능한지 확인
================================
이후 String 비교 방식이 아닌 Command Tree을 이용하여 다시 구현할 예정
InputManager
Variable
private
- bool grounded
현재 지상에 있는지 공중에 있는지 저장하는 테스트 변수 - List<string> g_commandList
지상에서 사용가능한 command 목록 - List<string> a_commandList
공중에서 사용가능한 command 목록 - string inputStream
Input을 저장하는 Stream - string rawInput
MLB, MRB 입력을 저장 - string combineKey
WASD 입력을 저장 - string complexInput
hold, repeat를 저장 - string currentInput
rawInput, combineInput, complexInput이 조합되어 나오는 현재 입력 - float resetTime
InputStream이 초기화되는 최소 시간 - float resetTimer
InputStream 초기화를 위한 내부변수 - float holdTime
hold로 판단되는 최소 시간 - float holdTimer
hold 판단을 위한 내부변수 - float delayTime
delay로 판단되는 최소 시간 - float delayTimer
delay 판단을 위한 내부변수 - float repeatTime
repeat으로 판단되는 최소 반복 주기 - float clickTime
현재 시간과 클릭한 시간을 비교하여 repeatTime과 비교하여 repeat를 판단하는 내부변수 - bool pressed
rawInput이 들어온 순간 true가 되는 클릭 확인용 변수 - bool released
rawInput이 끝나는 순간 true가 되는 떼기 확인용 변수 - bool holding
hold하고 있는 동안 true가 되는 내부변수 - bool held
hold로 판단되면 Reset 전까지 true가 되는 확인용 변수 - bool repeating
repeat하고 있는 동안 true가 되는 내부변수 - bool repeated
repeat으로 판단되면 Reset 전까지 true가 되는 확인용 변수 - bool delaying
delay동안 Reset true가 되는 내부변수 - bool delayed
delay로 판단되면 Reset 전까지 true가 되는 확인용 변수
Method
private
- void ResetInputs()
=Input과 관련된 것을 모두 초기화하는 함수
[ResetPrevInputs()]
holding, delaying, repeating를 false로 초기화
rawInput과 combineKey를 ""로 초기화 - void ResetPrevInputs()
=확인용 변수들을 초기화하는 함수
pressed, released 등 확인용 변수 초기화 - void RestTimers()
=Timer들을 초기화하는 함수
resetTimer, holdTimer, delayTimer를 0으로 초기화 - void ResetStream()
=inputStream을 초기화하는 함수 - void CheckReset()
=inputStream 초기화 여부를 판단하는 함수
holding이 true인 경우 resetTimer는 0으로 고정
delayed 이후 resetTimer가 동작하며 resetTimer가 resetTime을 넘어가면 resetTimer를 0으로 초기화
[ResetInputs]
[ResetTimers]
[ResetStream] - void CheckInput()
=Input을 처리하는 모든 함수를 한번에 호출하는 함수
[CheckCombineKey()]; WASD 입력 처리
[CheckRawInput(1)]; 마우스 오른쪽 클릭 처리
[CheckRawInput(0)]; 마우스 왼쪽 클릭 처리
[CheckComplexInput()]; 홀드, 반복 입력 처리
[CheckInputDelay()]; 입력 없음 처리
[UpdateCurrentInput()]; currentInput 갱신 - void CheckCombineKey()
=WASD 입력을 처리하는 함수 - void CheckRawInput(int button)
=마우스 입력을 처리하는 함수
MLB 입력일 경우 combineKey를 ""로 초기화한다.
1. MouseButtonDown이 되면 rawInput에 정보를 저장하고 확인용변수들을 설정
[CheckRepeat]
[ResetTimers]
[AddToStream(rawInput)]
2. MouseButton이 되면 pressed를 false로 설정
holdTimer로 hold를 판단
3. MouseButtonUp이 되면
holding을 false로 설정
released를 true로 설정 - void CheckInputDelay()
=입력 없음을 판단하는 함수
released 이후 delayTimer가 동작
delayTimer가 delayTime을 넘어가면 delaying,delayed를 true로 설정하고 rawInput을 ""로 초기화
[AddDelayToStream()] - void CheckRepeat()
=반복 입력을 판단하는 함수
현재 시간과 마지막으로 클릭한 시간을 비교하여 repeatTime보다 작다면 반복입력으로 판단
repeating, repeated를 true로 설정 - void CheckComplexInput()
=홀드와 반복입력을 처리하는 함수
1. holding일 때 complexInput을 "~"로 설정하고 InputStream에 추가
[AddHoldToStream()]
2. repeating이고 delaying이 아닐때 complexInput을 "+"로 설정하고 InputStream에 추가
[AddRepeatToStream()]
3. 아닐 때 complexInput을 ""로 초기화하고 holding, repeating을 false로 설정 - void UpdateCurrentInput()
=combineKey, complexInput, rawInput을 조합하여 currentInput을 갱신 - void AddToStream(string input)
=입력을 inputStream에 추가하는 함수
repeating이 false일 때 combineKey 여부에 따라 inputStream에 추가
이후 사용가능한 command인지 확인
[CheckAvailableCommand()] - void AddHoldToStream()
=Hold를 inputStream에 추가하는 함수
중복 추가와 repeat과의 충돌을 방지 - void AddRepeatToStream()
=Repeat를 inputStream에 추가하는 함수
중복 추가와 hold와의 충돌을 방지 - void AddDelayToStream()
=Delay를 inputStream에 추가하는 함수
중복 추가 방지 - void CheckAvailableCommand()
=현재 inputStream에 추가된 command가 사용가능한지 확인하는 함수
inputStream이 null인 경우 return
지상에 있는지에 따라 [CheckAvailableFromList()]를 호출 - void CheckAvailableFromList(List<string> list)
=list로부터 inputStream이 사용가능한 command인지 판단하는 함수
inputStream으로 시작하는 command가 있다면 사용가능으로 판단
아니라면 inputStream에 rawInput를 추가
[ResetInputs]
전체 코드
더보기
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using Unity.VisualScripting.Antlr3.Runtime;
using UnityEngine;
public class InputTest : MonoBehaviour
{
[Header("For Test")]
[SerializeField] private bool grounded = true;
[Space(20)]
[SerializeField] private List<string> g_commandList = new List<string>();
[SerializeField] private List<string> a_commandList = new List<string>();
[Space(20)]
[SerializeField] private string inputStream;
[Space(20)]
[SerializeField] private string rawInput;
[SerializeField] private string combineKey;
[SerializeField] private string complexInput;
[SerializeField] private string currentInput;
[SerializeField] private float resetTime;
private float resetTimer;
[SerializeField] private float holdTime;
private float holdTimer;
[SerializeField] private float delayTime;
private float delayTimer;
[SerializeField] private float repeatTime;
private float clickTime;
[SerializeField] private bool pressed;
[SerializeField] private bool released;
[SerializeField] private bool holding;
private bool held;
[SerializeField] private bool repeating;
private bool repeated;
[SerializeField] private bool delaying;
private bool delayed;
private void Awake()
{
ResetStream();
ResetInputs();
ResetTimers();
clickTime = -1.0f;
}
void Update()
{
CheckInput();
CheckReset();
//DebugInputs();
}
private void DebugInputs()
{
if(pressed)
{
Debug.Log("Press");
}
if(holding)
{
Debug.Log("Hold");
}
if(released)
{
Debug.Log("Release");
}
if(delaying)
{
Debug.Log("delay");
}
if(repeating)
{
Debug.Log("Repeat");
}
}
private void CheckInput()
{
CheckCombineKey();
CheckRawInput(1);
CheckRawInput(0);
CheckComplexInput();
CheckInputDelay();
UpdateCurrentInput();
}
private void UpdateCurrentInput()
{
if(combineKey != "")
{
currentInput = combineKey + "+" + rawInput + complexInput;
}
else
{
currentInput = rawInput + complexInput;
}
}
private void CheckRawInput(int button)
{
if(button == 0)
{
combineKey = "";
}
if(Input.GetMouseButtonDown(button))
{
rawInput = (button==0) ? "X" : "Y";
pressed = true;
holding = false;
released = false;
CheckRepeat();
ResetTimers();
AddToStream(rawInput);
}
else if(Input.GetMouseButton(button))
{
pressed = false;
holdTimer += Time.deltaTime;
if(holdTimer > holdTime)
{
holding = true;
held = true;
}
//release = false;
}
else if(Input.GetMouseButtonUp(button))
{
//press = false;
holding = false;
released = true;
}
}
private void CheckInputDelay()
{
if(released == true)
{
delayTimer += Time.deltaTime;
if(delayTimer >= delayTime)
{
delaying = true;
delayed = true;
rawInput = "";
AddDelayToStream();
}
else
{
delaying = false;
//repeat = false;
}
}
}
private void CheckRepeat()
{
if((Time.time - clickTime) < repeatTime)
{
repeating = true;
repeated = true;
}
else
{
clickTime = Time.time;
}
}
private void CheckCombineKey()
{
if(Input.GetKey(KeyCode.W))
{
combineKey = "W";
}
else if(Input.GetKey(KeyCode.S))
{
combineKey = "S";
}
else if(Input.GetKey(KeyCode.A))
{
combineKey = "A";
}
else if(Input.GetKey(KeyCode.D))
{
combineKey = "D";
}
else
{
combineKey = "";
}
}
private void CheckComplexInput()
{
if(holding)
{
complexInput = "~";
AddHoldToStream();
}
else if(repeating && !delaying)
{
complexInput = "+";
AddRepeatToStream();
}
else
{
complexInput = "";
holding = false;
repeating = false;
}
}
private void CheckReset()
{
if(holding == true)
{
resetTimer = 0;
return;
}
if(delayed == true)
{
resetTimer += Time.deltaTime;
if(resetTimer > resetTime)
{
resetTimer = 0;
ResetInputs();
ResetTimers();
ResetStream();
}
}
}
private void ResetInputs()
{
Debug.Log("Reset");
ResetPrevInputs();
holding = false;
delaying = false;
repeating = false;
rawInput = "";
combineKey = "";
}
private void ResetPrevInputs()
{
pressed = false;
released = false;
held = false;
delayed = false;
repeated = false;
}
private void ResetTimers()
{
resetTimer = 0;
holdTimer = 0;
delayTimer = 0;
}
private void ResetStream()
{
inputStream = "";
}
private void AddToStream(string input)
{
if (repeating == false)
{
if(combineKey == "")
{
inputStream += input;
}
else
{
Debug.Log("CombineKey");
inputStream += combineKey + "+" + input;
}
}
CheckAvailableCommand();
}
private void AddHoldToStream()
{
if (inputStream.EndsWith("~"))
{
return;
}
repeating = false;
inputStream += "~";
CheckAvailableCommand();
}
private void AddRepeatToStream()
{
if (inputStream.EndsWith("+"))
{
return;
}
holding = false;
inputStream += "+";
CheckAvailableCommand();
}
private void AddDelayToStream()
{
if (inputStream.EndsWith("_"))
{
return;
}
inputStream += "_";
CheckAvailableCommand();
}
private void CheckAvailableCommand()
{
if(string.IsNullOrEmpty(inputStream))
{
return;
}
if(grounded)
{
CheckAvailableFromList(g_commandList);
}
else
{
CheckAvailableFromList(a_commandList);
}
}
private void CheckAvailableFromList(List<string> list)
{
for(int i = 0; i < list.Count; i++)
{
if (list[i].StartsWith(inputStream))
{
//Debug.Log("Available: [" + g_commandList[i] + "=" + inputStream + "]");
Debug.Log("Available");
return;
}
else
{
//Debug.Log("Unavailable input");
//Debug.Log("Not Available: [" + inputStream + "]");
}
}
inputStream = rawInput;
ResetInputs();
}
}
'작업일지 > Unity' 카테고리의 다른 글
[Unity] Android Build에서 streamingAssetPath 파일 접근하기 (0) | 2024.05.13 |
---|---|
[Unity] Command Tree System for Stylish Action Game (0) | 2024.03.04 |
[Unity] Hexagon TileMap 만들기 (0) | 2023.05.10 |
[Unity] New Input System 테스트 (0) | 2023.01.02 |
[Unity] Netcode for Gameobject 테스트 (0) | 2022.11.19 |