(애써 외면해 본다...)
UI쪽과 관련된 일은 정말정말 노가다성이 많긴 하구나...(사실 다 그럴지도?)
Phase.Started / Phase.Performed
어제에 이어 InputSystem을 조금더 알아보자.
플레이어의 인풋을 받아오는 과정에서 Invoke Unity Events 방식의 다른 점 중, phase 부분에서 의문이 생겼다.
public void OnMoveInput(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
{
_curMovementInput = context.ReadValue<Vector2>();
}
else if(context.phase == InputActionPhase.Canceled)
{
_curMovementInput = Vector2.zero;
}
}
public void OnJumpInput(InputAction.CallbackContext context)
{
if(context.phase == InputActionPhase.Started && IsGrounded())
{
_rigidbody.AddForce(Vector2.up * _jumpForce, ForceMode.Impulse);
}
}
자 이 부분이다.
움직일 때와 점프 할 때, 조건을 보면 다음과 같은 것이 있다.
context.phase == InputActionPhase.Started
context.phase == InputActionPhase.Performed
context.phase == InputActionPhase.Canceled
사실 두 개 더 있는데 일단 위 세 가지만 보도록 하자.
유니티 공식문서에는 이렇게 나와있다.
Disabled: 액션이 비활성화되어 있으며 입력을 받을 수 없습니다.
Waiting: 액션이 활성화되었으며 활성화된 상태에서 입력을 기다리고 있습니다.
Started: 입력 시스템이 액션을 시작하는 입력을 받았습니다.
Performed: 액션과의 상호 작용이 완료되었습니다.
Canceled: 액션과의 상호 작용이 취소되었습니다.
어제 내가 적은 TIL 에선
Performed = KeyDown
Canceled = KeyUp
라고 했다.
몇 가지 실험을 하던 중 이상한 낌새가 들어 튜터님에게 질문하였고
알려주신 답변의 내용은 내가 이해한 것 과는 전혀 달랐다.
이래서 어설픈 지식이 무서운거다. 어제 적은 건 완전히 틀린 정보다.(이 전에 썼던 것들에도 있을 걸 생각하니 무섭네...)
일단 InputAction을 확인 해보자.
먼저 Move에는 W,S,A,D 키보드의 키가 바인딩 되어있다.
Interactions 의 + 를 눌러보면 네가지 프리셋이 들어있다. 일단 Hold를 넣어보자.
0.4초동안 키를 누르고 있으면 Interactions가 발동이 된다.
확실한 결과를 위해 1초로 바꿔봤다.
이제 플레이어 이동방향을 받는 로직에 Debug.Log를 임시로 다음과 같이 추가해주자.
public void OnMoveInput(InputAction.CallbackContext context)
{
if (context.started)
Debug.Log("started");
if (context.performed)
Debug.Log("performed");
if (context.canceled)
Debug.Log("canceled");
if (context.phase == InputActionPhase.Performed)
{
_curMovementInput = context.ReadValue<Vector2>();
}
else if(context.phase == InputActionPhase.Canceled)
{
_curMovementInput = Vector2.zero;
}
}
started 일 때, "started" 를
performed 일 때, "performed" 를
canceled 일 때, "canceled " 를
로그에 띄우도록 해주고 이제 결과를 보도록 하자.
키를 입력한 순간, "started" 가 1회 호출됐다.
이동을 시작한 순간, "performed" 가 1회 호출됐다.
키를 뗀 순간, "canceled" 가 1회 호출됐다.
여기서 알 수 있는 사실은,
Started: 입력 시스템이 액션을 시작하는 입력을 받았습니다.
키가 바인딩 된 W를 눌렀으므로 '액션을 시작하는 입력' 을 받은 KeyDown 이다.
Performed: 액션과의 상호 작용이 완료되었습니다.
Interactions 에서 설정한 '1초간 키를 입력 후 Hold 했을 때' 이다.
Canceled: 액션과의 상호 작용이 취소되었습니다.
키가 바인딩 된 W를 뗐으므로 '상호 작용이 취소' 된 KeyUp 이다.
Interactions 를 따로 설정하지 않았을 땐 단순히 키를 입력 한 순간이 performed 이므로
Started 와 Performed 의 발동 시점이 같을 뿐이다.
그럼 여기서 두 번째 의문이 생긴다.
"그렇다면 Interactions를 설정 안 했다면 Started 와 Perfomed는 동일한 동작을 할까?"
그 문제는 동시 키 입력을 했을 때 알 수 있다.
Interactions를 없애고 다시 해보도록 하자.
단,
W 입력 (전진) -> W 입력 유지 및 D 입력 (대각선 이동) -> W를 떼고 D입력 유지 (오른쪽 이동)
이렇게 해보자.
절대 같은 동작이 아니다.
일단 Move의 키 바인딩이 W,S,A,D 라는 사실을 알고 있어야한다.
실제 키 입력은 다음과 같이 이루어졌다.
W -> W+D -> D -> None
위에서 말했듯이 Interactions 가 없으니 바인딩된 키를 입력 받은 시점과 같아
첫 started 와 performed 는 동시에 호출된다. (W 키 입력)
W 입력 중 D 키를 입력 시, 같은 Action 의 다른 바인드된 키를 입력 했고,
이 또한 Move 액션 상호작용이므로 performed 가 호출된다. (W + D 키 입력) : started 는 호출 되지 않는다.
W + D 키 입력 중 W 키를 뗐다. 그러나 아직 D 키가 상호작용 중이고, W + D 키가 아닌 D 키 입력이므로
performed 가 호출된다. (D 키 입력) : 키를 뗐다고 해서 canceled 가 아니다.
마지막으로 D 키를 뗐고, 더 이상 상호작용하는 키가 없으므로 canceled 가 호출된다.
위 사실을 토대로 만약
if (context.phase == InputActionPhase.Performed)
{
_curMovementInput = context.ReadValue<Vector2>();
}
이 부분을 Performed 에서
if (context.phase == InputActionPhase.Started)
{
_curMovementInput = context.ReadValue<Vector2>();
}
Started 로 바꾼다면
위 에서 말한 키 입력을 똑같이 한다고 했을 땐,
started는 'W키를 입력 받았을때' 만 1회 호출 되므로
W -> W + D -> D 를 입력한다 해도 W 키를 누른 시점만 호출돼,
_curMovementInput = ( 0 , 1 ) 단 한 번만 할당된다.
즉 중간에 canceled 가 일어나지 않은 위 와 같은 상황에선 계속해서 전진한다.
요약
- 찜찜하면 Debug.Log 로 로그를 찍어봐라.
- 유니티 공식문서를 자세히 봐라.
- 모르겠으면 튜터님께 가라.
- 자신이 이해한 것은 대체로 이해한 것이 아닐 수 있다.
'스파르타 내배캠' 카테고리의 다른 글
스파르타 내배캠 Unity 3기 32일차 (1) | 2024.02.07 |
---|---|
스파르타 내배캠 Unity 3기 31일차 (0) | 2024.02.05 |
스파르타 내배캠 Unity 3기 29일차 (0) | 2024.02.01 |
스파르타 내배캠 Unity 3기 28일차 (0) | 2024.01.31 |
스파르타 내배캠 Unity 3기 26일차 (0) | 2024.01.29 |