유니티/유니티 C#

유니티 입력 처리 심화 - (6) Action에 대한 추가적인 정보

monstro 2024. 12. 26. 01:20
728x90
반응형

이번 포스트에서는 이전에 알아본 Action의 Interaction과 Processor 외에도,

Action에 대한 추가적인 정보를 한번 다뤄보겠습니다.

Interaction이나 Processor 만큼 무거운 내용이 아니니 가볍게 알아보겠습니다.

 

 1) Started VS Perform

Input System에서 입력을 하는 경우에 함수를 호출하는 것은 2가지 방식으로 분리가 가능합니다.

바로 started와 performed로 구분할 수 있습니다.

 

이 둘을 구분하는 기준이 바로 Interaction입니다.

둘은 다음을 기준으로 진행합니다.

  • Started : Action에 연결된 키를 누르는 경우 진행
  • Performed : Action에 연결된 모든 Interaction이 완료되는 경우 진행

따라서 Started 이후에 Performed가 진행됩니다.
그러므로 Started에 연결된 콜백 함수가 먼저 호출되고

이후 Performed에 연결된 콜백 함수가 호출됩니다.

 

기존의 코드를 다음과 같이 수정해보겠습니다.

public class ActionAssetClassRef : MonoBehaviour
{
    private ActionAsset actionAsset;

    private void Awake()
    {
        actionAsset = new ActionAsset();
    }

    private void OnEnable()
    {
        actionAsset.InGround.Press.performed += PressExample;
        actionAsset.InGround.Press.started += PressStartExample;

        actionAsset.Enable();
    }

    private void OnDisable()
    {
        actionAsset.InGround.Press.performed -= PressExample;
        actionAsset.InGround.Press.started -= PressStartExample;

        actionAsset.Disable();
    }

    private void PressExample(InputAction.CallbackContext value)
    {
        Debug.Log("Performed Binded Event");
    }

    private void PressStartExample(InputAction.CallbackContext value)
    {
        Debug.Log("Started Binded Event");
    }
}

 

Action Asset은 다음과 같이 설정하였습니다.

 

이제 실행 결과를 확인해보겠습니다.

 

실행 결과를 살펴보면 started에 연결된 함수의 로그가 먼저 출력되고

이어서 performed에 연결된 함수의 로그가 출력되는 것을 확인할 수 있습니다.

 

2) 입력 여부를 판단하는 다른 방법

Input System에서는 이벤트 말고도 입력을 처리하는 방식이 존재합니다.

다음의 메서드를 사용하여 이를 수행할 수 있습니다.

  • WasPressedThisFrame : 이번 프레임에 입력을 했는지를 판단한다 == Started와 동등하다
  • WasPerformedThisFrame : 입력이 완전히 계산되었지는지를 판단한다 == Performed와 동등하다
  • WasReleasedThisFrame : 이번 프레임에 입력에서 뗐는지를 판단한다 == Performed와 동등하다
  • IsPressed : 매 프레임마다 입력 중인지를 판단한다

기존의 코드를 다음과 같이 수정하였습니다.

public class ActionAssetClassRef : MonoBehaviour
{
    // 생성된 InputAsset의 클래스를 인스턴스로 가져옴
    private ActionAsset actionAsset;

    private void Awake()
    {
        actionAsset = new ActionAsset();
    }

    private void OnEnable()
    {
        actionAsset.Enable();
    }

    private void OnDisable()
    {
        actionAsset.Disable();
    }

    private void Update()
    {
        if (actionAsset.InGround.Press.WasPressedThisFrame())
        {
            Debug.Log("Was Pressed This Frame");     
        }
        if (actionAsset.InGround.Press.WasPerformedThisFrame())
        {
            Debug.Log("Was Performed This Frame");
        }
        if (actionAsset.InGround.Press.WasReleasedThisFrame())
        {
            Debug.Log("Was Released This Frame");
        }
        if (actionAsset.InGround.Press.IsPressed())
        {
            Debug.Log("Is Pressed This Frame");
        }
    }
}

 

실제 실행결과는 다음과 같습니다.

 

의도한 대로 매 프레임마다 IsPressed를 수행하고

누른 경우 WasPressed, 그 다음에 WasPerformed가 수행되고

입력을 뗀 후 WasReleased가 수행하는 것을 확인하였습니다.

 

따라서 정리하면 순서상으로 

WasPressedThisFrame - WasPerformedThisFrame - WasReleasedThisFrame 순서로 진행되며, 

IsPressed는 매 프레임마다 진행하는 것을 알 수 있습니다.

 

3) Button Modifier

Action Type이 Button으로 설정된 입력의 경우에 사용할 수 있습니다.

 

 

Button으로 동작하는 Action을 우클릭하여 해당 Action에 모디파이어를 설정할 수 있습니다.

일반적으로 shift / ctrl / alt 키와 같이 사용됩니다.

 

Modifier를 사용하는 경우Action을 트리거하는 입력 Modifier의 입력이 같이 이뤄저야 동작합니다.

 

이때 Modifier를 사용하는 입력과 사용하지 않는 입력이 같은 키를 사용할 수 있습니다.

이런 경우 중복 입력되는 문제가 발생할 수 있는데,

edit - project settings - Input System Package - enable Input Consumption을 체크하면 해결됩니다.
체크하면 동일한 키를 사용하는 경우Modifier가 적용된 Input을 처리합니다.

 

아래와 같이 Input Asset을 설정해보겠습니다.

 

코드도 다음과 같이 수정하였습니다.

public class ActionAssetClassRef : MonoBehaviour
{
    // 생성된 InputAsset의 클래스를 인스턴스로 가져옴
    private ActionAsset actionAsset;

    private void Awake()
    {
        actionAsset = new ActionAsset();
    }

    private void OnEnable()
    {
        actionAsset.InGround.Press.performed += PressExample;
        actionAsset.InGround.Press.canceled += PressStopExample;

        actionAsset.InGround.PressWithModifier.performed += PressModiExample;
        actionAsset.InGround.PressWithModifier.performed += PressModiStopExample;

        actionAsset.Enable();
    }

    private void OnDisable()
    {
        actionAsset.InGround.Press.performed -= PressExample;
        actionAsset.InGround.Press.canceled -= PressStopExample;

        actionAsset.InGround.PressWithModifier.performed -= PressModiExample;
        actionAsset.InGround.PressWithModifier.performed -= PressModiStopExample;

        actionAsset.Disable();
    }

    private void PressExample(InputAction.CallbackContext value)
    {
        Debug.Log("Perform Press without Modi");
    }

    private void PressStopExample(InputAction.CallbackContext value)
    {
        Debug.Log("Stop Press without Modi");
    }

    private void PressModiExample(InputAction.CallbackContext value)
    {
        Debug.Log("Perform Press with Modi");
    }

    private void PressModiStopExample(InputAction.CallbackContext value)
    {
        Debug.Log("Stop Press with Modi");
    }
}

 

이제 실행결과를 살펴보겠습니다.

 

스페이스바를 그냥 누른 경우, Press 액션을 수행하지만,

스페이스바에 쉬프트 키를 같이 누른 경우, PressWithModifier 액션을 수행하는 것을 확인하였습니다.

728x90
반응형