[Unity] New Input System (인풋시스템)

⭐ Input Manager (기존의 입력 방식)

● 기존의 키입력 방식으로 Input.GetKeyDown(), Input.GetAxis() 등의 명령어를 통해 Update문에서 키입력을 체크하는 방식

● 매 프레임 키 입력을 검사하기 때문에 불필요한 비용이 발생 → New Input System의 입장에서 불필요한 비용

● 멀티플랫폼, 크로스플랫폼을 지원하는 게임을 제작하기 위해 플랫폼마다 코드를 다르게 만들어야하는 불편함

 

 

● 하나의 플랫폼에서, 혹은 단순한 프로젝트를 제작하거나 이미 Input Manager로 대규모 프로젝트를 하고 있는 경우에는 여전히 사용하는 곳이 많기 때문에 할 줄 알아야 함

 

 

 

 

⭐ New Input System (새로운 입력 방식)

● "매 프레임 Update문에서 키입력을 체크하는 방식을 효율적으로 바꿀 수 없을까" 하는 고민에서 착안된 방식

● 기존의 Input Manager 방식과 처리되는 순서가 다름

    ○ Input Manager: 키를 입력 → 이에 맞는 메서드 호출

    ○ New Input System: 메서드를 먼저 정의해두고 → 이를 수행하기 위한 키나 버튼 연결

● VR, 모바일, 콘솔 등 다양한 플랫폼의 입력에 유연하게 대응 가능

● 유니티 Package Manager에서 Input System을 설치하여 사용 가능

 

 

 

Input Actions


● 모든 입력을 정의해두는 설정 파일 / 매핑 하게 해주는 에디터

● Actions Map: 입력 키를 상황별로 묶어놓은 폴더 같은 개념

● Actions: 어떤 상태(행동)에 대한 키 입력을 받을 것인지에 대한 형태

● Properties: 입력을 어떤 방식으로 할 것인지에 대한 옵션, 속성

 

 

Action Map


● Value: 입력 들어온 값에 따라 결정, 지속적인 입력 값이 필요한 경우 (ex. 이동, 회전 등)

● Button: 입력 여부로 버튼을 눌렀는지, 뗐는지로 결정 (ex. 공격, 점프 등)

● PassThrough: 여러 입력장치로부터 복합적인 값을 받을 때 사용

 

Value와 Pass Through의 차이점

키보드와 게임 패드에서 동시에 이동을 한다고 가정했을 때
Value는 가장 최근에 입력된 정보가 활용되는 반면, Pass Through는 둘 다 발동됩니다.
이렇게 여러 컨트롤러의 입력들이 하나하나 유효해야 할 때 Pass Through을 사용합니다.

 

 

⭐ 플레이어 이동에 적용해보기 (Editor 6000.2.10f1 기준)

● Window - Package Management - Package Manager에서 Input System 설치

    ○ 유니티6 부터는 기본으로 깔려있지만 혹시 안되어있을 경우 위의 경로에서 설치하면 됩니다.

 

 

 

 

● Input Actions 파일을 생성해줍니다

 

 

 

 

● 어떤 입력 장치를 사용할지 정하기 위해 New Control Scheme - Add Control Scheme을 선택합니다.

 

 

 

 

 

● 키보드와 마우스를 사용하기 위해 플러스(+) 버튼을 누르고 Keyboard와 Mouse를 추가해줍니다.

 

 

 

 

 

● Action Maps 옆에 플러스(+) 버튼을 눌러 새로운 Map을 생성해줍니다.

 

 

 

 

● 1. 플러스(+) 버튼을 눌러 어떤 행동에 대한 입력키인지를 위한 Action을 생성합니다.

    ○ 생성한 Action을 눌러 입력 값의 타입을 정합니다.

● 2. Action을 위해 어떤 키를 입력받을 것인지에 대한 binding을 추가해줍니다.

● 3. 키를 지정해주기 위한 binding을 선택합니다.

● 4. Path를 클릭 후 스크롤을 내리거나 검색을 통해 원하는 키를 검색합니다.

● 5. 원하는 키를 찾았으면 선택하여 연결해줍니다.

 

 

 

 

● 입력키를 사용할 오브젝트에 Player Input 컴포넌트를 추가합니다.

● 각각의 속성을 설정합니다.

    ○ Actions: 위에서 생성한 Input Action Asset을 넣습니다.

    ○ Default Scheme: 사용할 입력 장치를 정합니다. <Any>는 어떤 입력장치도 쓸 수 있습니다.

    ○ Default Map: 사용할 Map을 선택합니다.

    ○ Behavior: 입력이 발생했을 때 어떻게 콜백을 호출할지를 정하는 방식입니다.

        ■ 보통 Invoke Unity EventsInvoke C Sharp Events를 많이 사용합니다.

 

Invoke Unity Events:
UGUI에서 인스펙터에서 콜백을 연결하듯 인스펙터를 통해 호출할 콜백을 지정합니다.


Invoke C Sharp Events:
직접 코드를 통해 이벤트 / 델리게이트 형식으로 콜백을 연결합니다.

 

 

 

 

● Invoke C Sharp Events를 사용했을 때 코드

using UnityEngine;
using UnityEngine.InputSystem;

public class Test : MonoBehaviour
{
    [SerializeField] private Rigidbody playerRigid;

    [SerializeField] private PlayerInput playerInput;
    private InputActionMap actionMap;
    private InputAction moveAction;

    [SerializeField] private float moveSpeed = 5f;

    private Vector3 moveDir = Vector3.zero;

    private void Awake()
    {
        //초기화
        playerInput = GetComponent<PlayerInput>();
        actionMap = playerInput.actions.FindActionMap("Player");
        moveAction = actionMap.FindAction("Move");

        MovePlayer();
    }

    private void FixedUpdate()
    {
        if(moveDir != Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(new Vector3(moveDir.x, 0f, moveDir.z));
            playerRigid.linearVelocity = moveDir * moveSpeed;
        }
    }

    private void MovePlayer()
    {
        //키 입력을 시작했을 때
        //ctx: InputAction.CallbackContext 타입의 매개변수
        moveAction.performed += ctx =>
        {
            //입력받은 값을 Vector2 변수에 담기
            var dir = ctx.ReadValue<Vector2>();
            //실제 플레이어의 이동 값인 moveDir을 설정
            moveDir = new Vector3(dir.x, 0, dir.y);
        };

        //키 입력에서 뗐을 때
        moveAction.canceled += ctx =>
        {
            moveDir = new Vector3(0f, playerRigid.linearVelocity.y, 0f);
            playerRigid.linearVelocity = moveDir;
        };
    }
}

● InputAction.CallbackContext 타입의 변수는 입력의 상태를 확인할 수 있습니다.

    ○ .started: 키를 누르는 순간

    ○ .performed: 키가 완전히 눌려서, 액션이 발동되는 순간부터 키를 떼거나 입력 값이 변하기 전까지 주기적으로 실행

    ○ .canceled: 키를 뗄 때

 

 

 

● 결과