Unity
[Unity] InputSystem을 사용하여 이동하는 4가지 방식
게임 프로그래머
2025. 5. 28. 03:15
InputSystem 4가지 옵션
옵션 | 설명 |
Send Messages | 현재 GameObject에 'On + Action name' 인 함수를 찾아서 호출하는 방식. |
Broadcast Messages | 현재 GameObject와 그 자식들까지 'On + Action name' 인 함수를 모두 호출 |
Invoke Unity Events | UnityEvent로 연결, Inspector 상에서 Action에 함수를 설정하고 키 입력이 들어오면 호출 |
Invoke C# Events | C# 스크립트에서 구독 키 입력 받고 실행 전, 실행 후, 키 입력 해제 등의 상황에 따라 별도의 함수 등록할 수 있다. |
아래 언급되는 내용은 Broadcast Messages를 제외한 내용이 기재되었습니다.
Broadcast Messages은 자식 오브젝트의 메서드까지 모두 호출되므로 사용을 권장하지 않습니다.
✅ 공통 준비 사항
- Input Action Asset 설정
- Move 액션 추가 (Type: Value, Control Type: Vector2)
- WASD, 방향키 바인딩
- PlayerInput 컴포넌트 추가
- Actions에 InputAsset 할당
- Behavior를 각 방식별로 변경
- Rigidbody2D 컴포넌트 추가
- Gravity Scale: 0
- Constraints > Freeze Rotation: Z 체크
① Send Message
using UnityEngine;
using UnityEngine.InputSystem;
public class Player_SendMessage : MonoBehaviour
{
public float moveSpeed = 5f;
private Vector2 moveInput;
private Rigidbody2D rb;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
void OnMove(InputValue value)
{
moveInput = value.Get<Vector2>();
// 아래는 3D
// Vector2 Input = value.Get<Vector2>();
// moveInput = new Vector3(Input.x, 0, Input.y); 또는 그냥 moveInput = value.Get<Vector3>();
// 단 Vector3로 받는경우 게임에 따라 바인딩 제거(위, 아래)
}
void FixedUpdate()
{
rb.velocity = moveInput * moveSpeed;
}
}
PlayerInput의 Behavior를 Send Messages로 설정해야 동작함
② Invoke Unity Event
using UnityEngine;
using UnityEngine.InputSystem;
public class Player_UnityEvent : MonoBehaviour
{
public float moveSpeed = 5f;
private Vector2 moveInput;
private Rigidbody2D rb;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
// PlayerInput의 이벤트에서 Move 액션을 이 함수에 연결 (인스펙터에서)
public void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
void FixedUpdate()
{
rb.velocity = moveInput * moveSpeed;
}
}
또는 조건(Started, Performed, Canceld 등)에 따라 나뉠수도 있음
using UnityEngine;
using UnityEngine.InputSystem;
public class Player_UnityEvent : MonoBehaviour
{
public float moveSpeed = 5f;
private Vector2 moveInput;
private Rigidbody _rigidbody;
void Awake()
{
_rigidbody = GetComponent<Rigidbody>();
}
void Move()
{
Vector3 dir = transform.forward * moveInput.y + transform.right * moveInput.x;
dir *= moveSpeed;
dir.y = _rigidbody.velocity.y;
_rigidbody.velocity = dir;
}
// 또는 조건에 따라 설정할 수도 있음
public void OnMove(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
{
moveInput = context.ReadValue<Vector2>();
}
else if (context.phase == InputActionPhase.Canceled)
{
moveInput = Vector2.zero;
}
}
void FixedUpdate()
{
Move();
}
}
입력 조건(Started, Performed, Canceld 등)에 따라 로직을 달리할 수 있음
PlayerInput의 Behavior를 Invoke Unity Events로 설정하고, Move 이벤트에 함수(OnMove) 연결
외부에서 연결해야 하므로 OnMove 메서드 접근제한자는 Public으로 설정
해당 스크립트 오브젝트를 담아주고 | 메서드를 연결 |
③ Invoke C# Event (InputActionReference 방식)
using UnityEngine;
using UnityEngine.InputSystem;
public class Player_CSharpEvent : MonoBehaviour
{
public InputActionReference moveAction; // InputActions -> Move 액션 drag
public float moveSpeed = 5f;
private Vector2 moveInput;
private Rigidbody2D rb;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
void OnEnable()
{
moveAction.action.Enable(); // 입력 활성화
moveAction.action.performed += OnMove; // 입력 시작
moveAction.action.canceled += OnMove; // 입력 종료 (0,0으로)
}
void OnDisable()
{
moveAction.action.Disable();
moveAction.action.performed -= OnMove;
moveAction.action.canceled -= OnMove;
}
private void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
void FixedUpdate()
{
rb.velocity = moveInput * moveSpeed;
}
}
InputActions -> Playe/Input을 할당해준다.
④ Invoke C# Event ( PlayerInputs 클래스 방식)
전체적으로 비슷하나 차이점이 존재한다.
- Action Map으로의 접근을 위해 Action Map에 Player(이름은 자유, 이후 접근해야 함) 추가
- InputAction 에셋을 선택하고 Inspector 상단 우측에 있는 [Generate C# Class] 체크
- 이 방식은 PlayerInput 컴포넌트 필요 없음( 대신 PlayerInputs를 new로 생성해서 .Enable()로 수동 등록)
Generate 누르면 PlayerInputs.cs 생성된다.
[ActionMap과 동일한 이름(player) 문제 발생으로 인해 우측 사진은 PlayerInput으로 수정]
-------------------------- 일반 이벤트 연결 --------------------------
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMove : MonoBehaviour
{
private PlayerInput playerInput; // 자동 생성된 입력 클래스
private Vector2 moveInput;
private Rigidbody2D rb;
public float moveSpeed = 5f;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
playerInputs = new PlayerInputs(); // 입력 시스템 인스턴스화
}
void OnEnable()
{
playerInputs.Enable();
// 이벤트를 함수로 연결
playerInputs.Player.Move.performed += OnMovePerformed;
playerInputs.Player.Move.canceled += OnMoveCanceled;
}
void OnDisable()
{
// 이벤트 연결 해제
playerInputs.Player.Move.performed -= OnMovePerformed;
playerInputs.Player.Move.canceled -= OnMoveCanceled;
playerInputs.Disable();
}
// 키가 눌렸을 때 실행
private void OnMovePerformed(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
// 키가 떼졌을 때 실행
private void OnMoveCanceled(InputAction.CallbackContext context)
{
moveInput = Vector2.zero;
}
void FixedUpdate()
{
rb.velocity = moveInput * moveSpeed;
}
}