본문 바로가기

내배켐 Unity TIL

Unity 47일차 TIL - Unity InputSystem

저번에 특강을 통해서 강의에서 배웠던 InputSystem이 여러 가지 사용법 중 하나라는 것을 알게 됐다.

 

그래서 추가적으로 다른 사용 방법들에 대해서 정리해 보려고 한다.

 

1. 다이렉트 방식

기존에 사용했었던 Object에 Inspecter 창에서 Player Input을 Component로 추가하지 않고서 사용할 수 있다.

using UnityEngine;
// using InputSystem을 사용해야 Ketboard, Mouse 등의 Class를 사용할 수 있다.
using UnityEngine.InputSystem;

public class PlayerInputManager : MonoBehaviour
{
    public float dir;

    Keyboard keyboard;
    Mouse mouse;
    Gamepad gamepad;
    void Start()
    {
        keyboard = Keyboard.current;    // MainCamera를 가져오는 것 처럼 현재 Keyboard를 가져올 수 있다.
        mouse = Mouse.current;
        gamepad = Gamepad.current;
    }

    // Update is called once per frame
    void Update()
    {
        //혹시라도 연결이 안 돼있는 경우가 있을 수 있으므로 예외 처리 해주는게 좋음
        if (mouse == null) return;
        if (gamepad == null) return;

        //wasPressed : 눌렀을 때 (단 한 번)
        // wasReleased : 땠을 때 (단 한 번)
        // isPressed : 눌려있는 동안
        if (keyboard.aKey.isPressed)
        {
            dir = -1;
        }
        else if (keyboard.dKey.isPressed)
        {
            dir = 1;
        }
        else
        {
            dir = 0;
        }
    }
}

위 예시 코드처럼 사용할 수 있다. 근데 레거시 방식과 큰 차이가 없어서 잘 사용하지 않는다고 한다.

 

2. 임베디드 방식

Action 단위로 받아올 수 있는 방식으로, Instpecter 창에서 바로 키 입력을 받아올 수 있다.

2D로 예시를 들었기 때문에 반환 값이 -1과 1인 1D Axis를 사용했다.

 

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerInputManager : MonoBehaviour
{
    // Action 단위로 받아올 수 있다.
    public float dir;

    public InputAction MoveAction;
    public InputAction JumpAction;

    // started : 누를 때 (단 한 번)
    // performed : 누르고 있는 동안
    // canceled : 땠을 때 (단 한 번)
    // OnEnable : 게임 오브젝트가 활성화 된 직후 호출, 즉 비활성화 상태에서 활성화 상태가 될 때마다 호출되는 함수
    private void OnEnable()
    {
        MoveAction.performed += playerMove;
        MoveAction.canceled += playerStop;

        JumpAction.started += jump;

        // 이 Action을 사용하겠다는 의미.
        MoveAction.Enable();
        JumpAction.Enable();
    }
    // OnDisable : 오브젝트 또는 스크립트가 비활성화 될 때 호출
    private void OnDisable()
    {
        // 이벤트에 함수를 추가하면 제거도 해줘야 된다.
        MoveAction.performed -= playerMove;
        MoveAction.canceled -= playerStop;

        JumpAction.started -= jump;

        MoveAction.Disable();
        JumpAction.Disable();
    }
    // 연결하는 함수는 매개변수로 InputAction.CallbackContext 가 필요하다.
    private void playerMove(InputAction.CallbackContext value)
    {
        // value 값이 float 형태가 아니므로 변환 시켜줘야 함.
        dir = value.ReadValue<float>();
    }
    private void playerStop(InputAction.CallbackContext value)
    {
        dir = 0;
    }
    private void jump(InputAction.CallbackContext value)
    {
        print("점프");
    }
}

위 예시 코드처럼 사용할 수 있다.

장점은 Inspecter 창에서 Key 입력을 받아오므로 Object 별로 입력받는 Key를 다르게 할 수 있다.

예시) 멀티플레이 게임이 아닌 싱글 플레이 게임에서 2P로 진행할 때

단점은 사용하는 Object 별로 Key 입력을 해줘야 된다. 만약에 사용하는 Object들이 모두 동일한 Key로 사용된다면 추천하지 않는다.

 

3. 액션 에셋 방식

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerInputManager : MonoBehaviour
{
    public float dir;

    public InputActionAsset inputAsset;

    InputActionMap basic;
    InputAction move;
    InputAction jump;

    // started : 누를 때 (단 한 번)
    // performed : 누르고 있는 동안
    // canceled : 땠을 때 (단 한 번)
    // OnEnable : 게임 오브젝트가 활성화 된 직후 호출, 즉 비활성화 상태에서 활성화 상태가 될 때마다 호출되는 함수
    private void OnEnable()
    {
        basic = inputAsset.FindActionMap("Basic");
        move = basic.FindAction("Move");
        jump = basic.FindAction("Jump");

        move.performed += playerMove;
        move.canceled += playerStop;

        jump.started += jumped;

        // 전체 Action들 다 켜짐
        basic.Enable();

        // move에 연결해둔 Action만 켜짐
        // move.Enable();
    }
    // OnDisable : 오브젝트 또는 스크립트가 비활성화 될 때 호출
    private void OnDisable()
    {
        move.performed -= playerMove;
        move.canceled -= playerStop;

        jump.started -= jumped;
        basic.Disable();
    }
    // 연결하는 함수는 매개변수로 InputAction.CallbackContext 가 필요하다.
    private void playerMove(InputAction.CallbackContext value)
    {
        // value 값이 float 형태가 아니므로 변환 시켜줘야 함.
        dir = value.ReadValue<float>();
    }
    private void playerStop(InputAction.CallbackContext value)
    {
        dir = 0;
    }
    private void jumped(InputAction.CallbackContext value)
    {
        print("점프");
    }
}

기존에 Input Actions를 만들어서 사용하듯이 Action Maps를 만들고 Actions들을 추가한 뒤 Script에서 InputActionAsset을 통해 만들어둔 Input Actions를 Inspecter 창에서 넣어서 사용하는 방식이다.

음.. 굳이 이 방식을 쓰지는 않을 것 같다.

 

4. C# 제너레이트 방식

기존에 만들어둔 Input Actions를 Class로 받아와서 사용하는 방식이다.

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerInputManager : MonoBehaviour
{
    public float dir;

    PlayerInput input;

    // started : 누를 때 (단 한 번)
    // performed : 누르고 있는 동안
    // canceled : 땠을 때 (단 한 번)
    // OnEnable : 게임 오브젝트가 활성화 된 직후 호출, 즉 비활성화 상태에서 활성화 상태가 될 때마다 호출되는 함수
    private void OnEnable()
    {
        input = new PlayerInput();

        input.Basic.Move.performed += playerMove;
        input.Basic.Move.canceled += playerStop;

        input.Basic.Jump.started += jumped;

        input.Enable();
    }
    // OnDisable : 오브젝트 또는 스크립트가 비활성화 될 때 호출
    private void OnDisable()
    {
        input.Basic.Move.performed -= playerMove;
        input.Basic.Move.canceled -= playerStop;

        input.Basic.Jump.started -= jumped;

        input.Disable();
    }
    // 연결하는 함수는 매개변수로 InputAction.CallbackContext 가 필요하다.
    private void playerMove(InputAction.CallbackContext value)
    {
        // value 값이 float 형태가 아니므로 변환 시켜줘야 함.
        dir = value.ReadValue<float>();
    }
    private void playerStop(InputAction.CallbackContext value)
    {
        dir = 0;
    }
    private void jumped(InputAction.CallbackContext value)
    {
        print("점프");
    }
}

장점 : 참조 찾기가 편하다

 

전체적으로 봤을 때 가장 나은 방법인 것 같다.

왜냐하면 기존에 사용하듯이 Component에 Player Input을 추가하게 됐을 때 SendMessge 방식은 만들어둔 Action 명 앞에 On 을 붙인 함수를 만들어서 사용해야 되고, InvokeUnityEvents는 Button에 기능을 추가하듯이 일일이 추가해 줘야 된다.

근데 제너레이터 방식은 Component를 붙일 필요도 없고, 참조를 찾기도 편해서 사용할 함수들을 연결해 주고, 끊어주기만 하면 되기 때문에 편한 것 같다.