<--! 수학 기호 --> [Unity] New Input System #2 | 키 입력을 스크립트에 전달하여 처리하기

새소식

반응형
Game Engine/Unity

[Unity] New Input System #2 | 키 입력을 스크립트에 전달하여 처리하기

  • -

 

저번 글에서 기본적인 셋팅을 끝냈었다. 이번 글에서는 입력값을 스크립트(script)에 전달하는 방식 중 2가지 정도를 사용하여 로직을 제어하는 걸 해보고자 한다. Player 게임 오브젝트에 Player Input 컴포넌트를 부착했었다. 키를 입력했다면, 키보드로 들어온 입력값을 주인공 캐릭터에게 전달해줘야 한다.

 

 

 

1. 로직을 제어할 스크립트(script) 부착하기

 

Player 게임 오브젝트에 키 입력값을 전달받고, 해당 로직을 제어할 스크립트를 만들어서 붙여줬다.

 

입력이 들어왔을 때, 해당 내용을 전달해주는 방법을 설정할 수 있는 'Behavior'

 

  • Send Messages, Broadcast Messages  :  유니티의 Send Message 기능을 사용하여 특정 함수를 호출하는 방식
  • Invoke Unity Events, Invoke C Sharp Events  :  유니티나 C#의 이벤트 기능을 사용하는 방식
  • 위 방식들을 스크립트에서 사용하기 위해서는 다음과 같은 네임스페이스 적용이 필요
using UnityEngine.InputSystem;

 

 

Send Messages 기능을 사용할 경우

 

  • 특정 키가 들어오면, 특정한 함수를 자동으로 호출하는 방식
  • Broadcast Messages의 경우, 하위 계층에 있는 오브젝트들까지 제어를 할 수 있다.
  • 함수명이 "On + Actions name"으로 구성된다.
    • 예를 들어, "Move"라는 Actions가 있다면, 함수명은 "OnMove"
  • 위와 같이 함수명을 구성한 후 해당 Actions의 키 입력이 들어왔을 경우, OnMove() 함수를 찾아간다.

 

현재 Player 캐릭터에 적용하도록 만들어 놓은 Action Map"Move""Jump" 이 있다.

 

 

해당 Actions에서 받는 키를 입력하게 되면, On + Actions name 이름인 함수를 자동으로 호출하게 된다.

void OnMove(InputValue value) // "Move" Actions에 해당하는 키 입력 시 자동 호출
{
   ...
}

void OnJump()                 // "Jump" Actions에 해당하는 키 입력 시 자동 호출
{
  // Jump는 Action Type을 "Button"으로 설정했기 때문에 따로 매개변수가 없다.
  // 함수가 호출되면 키가 입력된 것, 호출되지 않으면 입력되지 않은 것으로 간주한다.
   ...
}

 

 

Tip) Action Type이 "Value"인 키 호출은 입력과 입력되지 않을 때, 이렇게 두 번 호출된다.

더보기
void OnMove(InputValue value)
{
   Vector2 input = value.Get<Vector2>();
   // 이전 게시글을 보면, "Move" Actions에 해당하는 키 리턴은 'Vector2'로 받기로 했다.
   
   Debug.Log($"SEND_MESSAGE : {input}");
}

 

상하좌우 아무 키나 눌러보면 다음과 같이 함수가 두 번 호출된다.

 

Input Actions의 Actions에 대한 키 Properties 중 Mode를 "Digital Normalized"로 설정하면 위와 같이 정규화된 값을 입력 받는다.

 

즉, 키를 누를 때는 해당 키 입력에 대한 함수 호출이 이루어지고, 키를 다시 뗄 때 또한 함수 호출이 이루어진다.

 

실습으로 OnMove() 함수 하나만 로직을 작성해보자.

private Vector3 moveDirection;
private float moveSpeed = 4f;


void Update()
{
   bool hasControl = (moveDirection != Vector3.zero);
   if(hasControl)
   {
      transform.rotation = Quaternion.LookRotation(moveDirection);
      transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
   }
}


void OnMove(InputValue value)
{
     Vector2 input = value.Get<Vector2>();                   
     if(input != null)
     {
         moveDirection = new Vector3(input.x, 0f, input.y);
         Debug.Log($"SEND_MESSAGE : {input.magnitude}");
     }
}

 

이동 로직은 잘 구현됐을 것이다.

 

Send Messages를 사용한 경우 (캐릭터 애니메이션 부분은 제가 따로 설정한 겁니다. 신경쓰지 않으셔도 됩니다.)

 

 

 

Invoke Unity Events 기능을 사용할 경우

 

  • Unity의 Event 방식을 사용
  • 해당 Actions에 대한 키 입력이 들어왔을 경우, 설정한 이벤트 함수를 호출해준다.

 

유니티 이벤트 호출 방식처럼 호출할 함수를 설정해주면 된다.

 

"PlayerActions"에 대한 Actions 이벤트 함수들 설정

 

기존 로직은 똑같으므로 함수만 Invoke Unity Events 방식에 맞게 조금 수정해주었다.

public void OnMove(InputAction.CallbackContext context)
{
   Vector2 input = context.ReadValue<Vector2>();
   if(input != null)
   {
      moveDirection = new Vector3(input.x, 0f, input.y);
      Debug.Log($"UNITY_EVENTS : {input.magnitude}");
   }
}


public void OnJump(InputAction.CallbackContext context)
{
   if(context.performed)  // Action Type이 "Button"일 경우 키가 눌렸는지 체크
   {
      // 점프 로직
   }
}

 

Send Messages와 달리 "On + Actions name"으로 함수명을 지을 필요는 없으나, 이벤트 함수에 대한 네이밍 규칙, On을 적용해주었다. 그리고 인스펙터(Inspector) 창에서 이벤트 함수를 추가해주었다.

주의할 점이 있는데, 함수의 접근지정자를 public으로 해줘야 Inspector 창에서 이벤트 함수 등록을 할 수 있다.

 

이벤트 함수로, Player 스크립트에 있는 OnMove 함수 등록

 

점프도 똑같이 적용해주면 된다. 그리고 한 번 테스트를 해봤다.

 

Invoke Unity Events를 사용한 경우

 

잘 되는 것을 볼 수 있다. 이런 식으로 사용하면 된다.

 

 

 

필요한 분들을 위한 Player 스크립트 전체 코드

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
    private Animator _animator;
    private Vector3 moveDirection;
    private float moveSpeed = 4f;


    void Start()
    {
        _animator = this.GetComponent<Animator>();
    }

    void Update()
    {
        bool hasControl = (moveDirection != Vector3.zero);
        if (hasControl)
        {
            transform.rotation = Quaternion.LookRotation(moveDirection);
            transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed);
        }
    }

    #region SEND_MESSAGE
    void OnMove(InputValue value)
    {
        Vector2 input = value.Get<Vector2>();                 // 입력 받은 값을 가져오기
        if(input != null)
        {
            moveDirection = new Vector3(input.x, 0f, input.y);
            _animator.SetFloat("moveSpeed", input.magnitude);   // magnitude는 벡터의 길이
            Debug.Log($"SEND_MESSAGE : {input.magnitude}");
        }
    }

    void OnJump()
    {
        // 점프에 관한 로직
    }
    #endregion


    #region UNITY_EVENTS
    public void OnMove(InputAction.CallbackContext context)   // Unity Event로 받을 경우
    {
        Vector2 input = context.ReadValue<Vector2>();
        if (input != null)
        {
            moveDirection = new Vector3(input.x, 0f, input.y);
            _animator.SetFloat("moveSpeed", input.magnitude); 
            Debug.Log($"UNITY_EVENTS : {input.magnitude}");
        }
    }

    public void OnJump(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            Debug.Log("Unity Event Jump");
        }
    }
    #endregion
}

 

 

요약

 

  • Actions MapActions에서 설정한 키 입력을 스크립트로 전달해주는 방법으로 Behavior를 사용할 수 있다.
  • Behavior가 지원하는 기능은 Send Messages, Broadcast Messages, Invoke Unity Events, Invoke C sharp Events가 있다.
  • Send Messages, Broadcast Messages를 사용할 경우, 함수명을 On + Actions name으로 설정해줘야 키 입력에 대해 함수가 자동으로 호출된다.
  • 이벤트(Event)를 사용할 경우, 함수의 접근지정자를 public으로 선언해야 한다.
  • 어떤 방식을 고를지는 개인이 선호하는 취향에 따라 선택하면 된다.
    • 개인적으로 Send Messages, Broadcast Messages 방법은 C#의 리플렉션(Reflection) 기능에 의존해서 성능에 그리 좋지 않다고 들었다.

 

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.