코드 및 공부/입력 관리

Input System을 이용한 움직임 구현

ekrxjvpvj0110 2024. 10. 8. 19:54

유니티 버전 - 2022.3.17f1

 

 

 

 

 

목차


  • Input System 적용하기
  • Input System 생성 및 설정
    • 에셋 만들기
    • Action Type과 Value
  • 완성된 코드 및 실행 결과
    • 완성코드
    • 실행결과
  • 마치며
    • 참고하면 좋은 자료

 

 

 

 

 

Input System 적용하기


1. Window의 Pakage Manager를 선택합니다

2. 들어가게되면 Packages: In Project로 설정되어있을텐데 클릭하여 Unity Registry로 변경합니다

3. 우측의 검색에 input을 검색하거나 직접 찾아서 Install 버튼을 눌러줍니다, 유니티 버전별로 Input System의 버전또한 상이합니다

 

 

 

설치 후 Yes를 눌러 에디터를 재시작합니다

 

 

 

 

 

Input System 생성 및 설정


 

 

 

에셋 만들기


Input Actions 에셋을 만들어 줍니다

 

 

 

No Control Schemes 선택 후 Add Control Scheme... 선택해줍니다

 

 

 

1. 이름을 지어준 후 아래의 + 버튼을 통해 Keyboard 아래의 Keyboard를 선택합니다 (좌클릭 안될시 우클릭으로선택 )

 

2. Mouse 아래의 Mouse를 선택합니다

 

 

 

Required로 선택되어있는지 확인 후 Save합니다

 

Optional은 선택적 입력 장치를 의미합니다, 만약 Mouse를 Optional scheme로 만든다면, 마우스가 없어도 scheme는 여전히 활성화 되어있고, 마우스가 연결되어 있을 때만 마우스 입력을 받게됩니다

 

Required는 필수 입력 장치를 의미합니다, 해당 scheme를 활성화 하려면, 위의 경우에는 키보드와 마우스 모두 연결되어있어야 합니다

 

 

 

1. Action Maps의 이름을 바꾸고 Actions의 이름도 바꾸어줍니다

 

2. Move의 Action Properties의 Action Type은 Value, Control Type은 Vector 2로 하겠습니다

 

 

 

Action Type과 Control Type


그전에 알아볼 것으로는 Action Type과 Control Typed이 있습니다

Action Type에는 세가지 옵션이 있습니다

 

 

 

Button


버튼이 눌리거나 떼어졌을 때의 동작을 정의합니다, 입력이 0 또는 1의 상태를 가집니다

 

Initial State Check : 액션이 활성화될때 입력 장치의 초기 상태를 확인할지 여부를 결정합니다

 

활성화되어있는 경우 액션이 활성화될 때, 입력 장치가 이미 눌린 상태라면 즉시 해당 액션을 트리거 합니다

비활성화되어있는 경우 액션이 활성화될 떄, 입력 장치가 이미 눌려있더라고 그 입력은 무시되고, 버튼을 다시 누르거나 떼는 동작이 발생할 때만 반응합니다

 

예를 들어

이 옵션을 활성화하였을 경우, 게임이 시작되고 플레이어가 이미 이동 키를 누르고 있다면 즉시 캐릭터가 이동을 시작합니다

 

비활성화되어있는 경우, 게임이 시작되고 플레이어가 이미 이동 키를 누르고 있었다면  이것은 무시되고, 다른 입력을 해야만 움직이기 시작합니다

 

 

 

Pass Through


입력을 필터링하거나 처리하지 않고 있는 그대로 전달하는 방식을 정의합나다, 입력 장치에서 들어오는 값을 변환 없이 즉시 액션으로 넘기며 동시 입력 처리가 필요하거나, 입력 값을 따로 관리할 필요가 없을 때 사용됩니다

 

Control Type : 해당 액션이 받을 수 있는 입력 데이터의 유형을 나타냅니다, 입력장치에서 들어오는 값을 Control Type 형식으로 변환하여 InputValue에 저장합니다

 

 

 

Value


연속적인 값을 처리합니다, 입력 장치에서 값의 변화를 받을 수 있고, 주로 방향, 속도, 크기와 같은 값의 변화를 다룹니다

입력 장치로부터 수집된 데이터를 정밀하게 처리해야하는 경우 사용합니다 

 

 

 

다시 돌아와서 + 버튼을 누른 후 Add ~~~ Composite를 선택합니다 Add Binding과의 차이를 간략하게 설명하자면 Binding은 동시 입력을 받을 수 없고(마지막으로 입력된 키 값만 처리), Composite는 가능합니다

 

 

 

좌측의 Up을 누르고 우측에서 Path를 누른 후 검색창이 가려있지만 입력은 가능하기에 W를 입력하여 W[Keyboard]를 찾아 선택합니다

 

 

 

2D Vector의 Composite값 참고

 

나머지도 방향과 대응되도록 키를 설정해주고 Save Asset을 이용하여 저장하여 줍니다

 

 

 

1. 플레이어를 만든 후 컴포넌트로 Player Input을 추가합니다(Player Input Manager가 아닙니다)

2. 에셋을 직접 끌어다 놓거나 버튼을 이용하여 Actions에 추가합니다

 

 

 

Behavior를 Send Messages로 설정합니다

앞으로 PlayerInput의 Actions중 Move의 값은 OnMove 메서드로 받아야하기에, 메서드명을 OnMove로 만들어 주어야만합니다

 

 

 

앞으로 만들 클래스의 관계도를 잠시 설명하겠습니다

첫번째로 PlayerInputController에서 OnMove 메서드를 만들어 Player Input으로부터 값을 전달받고, 그 값을 넘겨주며PlayerEventManager의 OnMoveEvent를 호출합니다

 

두번째로 PlayerEventManager에서는 Player가 가질 수 있는 모든 이벤트를 정의하고 실행합니다

 

세번쨰로 PlayerMovement에서는 실질적인 움직임을 구현하고 Move메서드를 OnMoveEvent에 등록킵니다

 

결과적으로 PlayerMovement의 Move메서드를 PlayerEventManager의 OnMoveEvent에 등록하고 PlayerInputController에서 PlayerInput값에 따라 호출하여 이동하도록 하여줍니다

 

 

 

완성된 코드 및 실행 결과


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerInputController : PlayerEventManager
{
    Vector2 moveInput;

    public void OnMove(InputValue _value)
    {
        moveInput = _value.Get<Vector2>().normalized;

        CallMoveEvent(moveInput);
    }
}

OnMove메서드입니다, 여기서 매개변수로 InputValue를 받는데, 이는 공식같은 것입니다, Input System을 이용하여 등록된 Action의 값을 받아오고자할때, InputValue를 사용하여 주어야만 합니다

 

_value.Get<Vector2>()를 이용하여 입력된 wasd의 값을 Vector2로 변환하여 moveInput에 넣어줍니다, ad는 x축의 -1, 1로 대응된다고 볼 수 있고, ws는 y축의 1, -1로 대응된다고 볼 수 있습니다

 

만약 W와 A를 동시에 누르면 벡터 값은 (1, -1)이라고 할 수 있겠습니다

 

정규화된 moveInput을 이용하여 CallMoveEvent를 호출합니다

 

 

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerEventManager : MonoBehaviour
{
    public event Action<Vector2> OnMoveEvent;

    public void CallMoveEvent(Vector2 _direction)
    {
        OnMoveEvent?.Invoke(_direction);
    }
}

OnMoveEvent에 등록된 메서드들을 실행시켜줍니다 매개변수로는 Vector2 를 이용하고있습니다

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    private PlayerEventManager playerEventManager;
    private Vector2 movementDirection = Vector2.zero;
    private Rigidbody2D myRigid;
    [SerializeField] float speed = 5f;

    private void Awake()
    {
        playerEventManager = GetComponent<PlayerEventManager>();
        myRigid = GetComponent<Rigidbody2D>();
    }

    private void Start()
    {
        playerEventManager.OnMoveEvent += Move;
    }

    private void FixedUpdate()
    {
        ApplyMovement(movementDirection);
    }

    private void Move(Vector2 direction)
    {
        movementDirection = direction;
    }

    private void ApplyMovement(Vector2 direction)
    {
        direction = direction * speed;

        myRigid.velocity = direction;
    }
}

실질적인 움직임을 담당하는 클래스입니다, Move메서드를 OnMoveEvent에 등록시켜 줌으로써 키보드에서 입력값을 받을 때마다 실행될 수 있도록 하여줍니다

 

 

 

Player 오브젝트에 Player Input Controller와 Player Movement를 붙여준 후 Speed를 설정합니다

 

 

 

실행한 후 키보드 입력을 해보면 잘 움직이는 것을 확인 할 수 있습니다, WA를 누르면 좌상단으로, SD를 누르면 우하단으로 잘 움직이는 것을 확인 할 수 있습니다

 

 

 

 

 

마치며


지금까지 Input System을 이용하여 값을 받고, Event를 호출하여 움직이는 법을 알아보았습니다

 

굳이 이벤트로 만드는 이유는, 플레이어가 움직이는 기능뿐만아니라 마우스를 이용하여 공격을 하거나 다른 키를 입력받아 다른 작업을 수행해야 하기때문에, 확장성과 유지보수 측면을 고려한 것입니다

 

액션과 이벤트, Func등의 내용이 더 궁금하시다면 아래를 참고 바랍니다

 

공부할때 정말 도움 많이 받은 케이디님의 유튜브 채널입니다

 

이상입니다