지금 현재 InputManager에서는 다양한 플랫폼에 대응하거나, 키를 변경하는 리바인딩하는 그런 부분이 부족함
사실 InputManager 자체의 문제로 보기는 어렵지만, 해당 버전에서는 구현했던 내용들이 모두 한 클래스들에 모여있어 클래스에 대한 확장성과 유지보수성이 많이 떨어지는 문제가 있음
기능별로 클래스를 나누는 것은 설계에 많은 도움을 줌
-> 단일 책임 원칙(Single Responsibility Principle)
New Input System의 핵심 개념들
New Input System의 장점
컨트롤러는 어떤 오브젝트의 상황에 따라 행동을 결정하고, 이를 TopDownMovement와 같이 실제 로직을 수행하는 컴포넌트들에 이벤트들을 전달하는 역할을 함
이러한 컨트롤러는 플레이어에만 들어가는 것이 아니므로, 이번에는 PlayerInputController를 만들겠지만,
적에게도 사용되는 공통적 기능들은 TopDownController에 정의하여 이를 재활용할 수 있게 해야 함
이번 강의에서 TopDownController에서는
이동과 관련된 액션들을 모두 실행하는 CallMoveEvent,
마우스와 관련된 이벤트를 모두 실행하는 OnLookEvent를 정의하고 이를 호출하는 기능만 추가함
- 움직이는 것, 조준하는 것 말고 오브젝트들이 가지는 다른 이벤트 -> 공격관련 이벤트
Pakages : unity Registry -> input system 검색 -> install
Package 추가하기
New Input Sytem 준비하기
Input System의 다양한 옵션들 배워두기
Input Action 수정하기
InputAction 더블클릭
No Control Schemes → Add Control Scheme
이름 수정 → + 버튼 → Keyboard 와 Mouse 추가
Action Maps → + → Player
Actions → Move, Look, Fire 추가
Action Type
Value Control Type
Vector2Action Type
Value Control Type
Any -> float 같은 느낌수정 → Add Up Down Left Right Composite
추가 → WASD 설정
W/S/A/D를 합쳐서 Vector2를 만드는 것이기 때문에 특별한 바인딩 활용해야 함
Look Action 수정
마우스 위치 하나가 Vector2를 만드는 것이기 때문에 그냥 수정만 하면 됨
Fire Action 수정
using System;
using UnityEngine;
public class TopDownController : MonoBehaviour
{
public event Action<Vector2> OnMoveEvent; // Vector2를 인자로 받는 함수
public event Action<Vector2> OnLookEvent; // Action은 무조건 void만 반환
public void CallMoveEvent(Vector2 direction)
{// move 이벤트가 발생했을 때 Invoke 하는 함수
OnMoveEvent?.Invoke(direction); // ?. 없으면 말고, 있으면 실행한다
}
public void CallLookEvent(Vector2 direction)
{
OnLookEvent?.Invoke(direction);
}
}
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerInputController : TopDownController
{
private Camera _camera;
private void Awake()
{
_camera = Camera.main; // 메인 카메라 라는 태그를 붙은 카메라를 가져온다
}
public void OnMove(InputValue value) // W input 값 같은 애들이 여기로 들어온다
{
// Debug.Log("OnMove" + value.ToString());
Vector2 moveInput = value.Get<Vector2>().normalized;
CallMoveEvent(moveInput); // TopDownController에서 상속 받아옴
// 실제 움직이는 것은 여기서 하는 것이 아니라, PlayerMovement에서 함
}
public void OnLook(InputValue value) // W input 값 같은 애들이 여기로 들어온다
{
// Debug.Log("OnLook" + value.ToString());
Vector2 newAim = value.Get<Vector2>(); // 마우스 위치 이기 떄문에 normalized 하면 안된다.
Vector2 worldPos = _camera.ScreenToWorldPoint(newAim);
newAim = (worldPos - (Vector2)transform.position).normalized;
// transform.position 에서 월드가 어느 방향에 있는지 묻고 값을 얻는 것
// 마우스(카메라)가 찍고 있는 방향을 월드좌표로 바꿔준다
if (newAim.magnitude >= .9f)
// Vector 값을 실수로 변환
{
CallLookEvent(newAim);
}
}
public void OnFire(InputValue value)
{
Debug.Log("OnFire" + value.ToString());
}
}
PlayerInputController
는 지시만 하고 실제로 행동은 전혀 하지 않는 관리자 TopDownMovement
는 실무를 하는 실무자using UnityEngine;
// TopDownMovement는 캐릭터와 몬스터의 이동에 사용될 예정입니다.
public class TopDownMovement : MonoBehaviour
{
// 실제로 이동이 일어날 컴포넌트
private TopDownController movementController;
private Rigidbody2D movementRigidbody;
private Vector2 movementDirection = Vector2.zero;
private void Awake()
{
// 주로 내 컴포넌트 안에서 끝나는 거를 많이 함
// 같은 게임오브젝트의 TopDownController, Rigidbody를 가져올 것
movementController = GetComponent<TopDownController>();
movementRigidbody = GetComponent<Rigidbody2D>();
}
private void Start()
{
// OnMoveEvent에 Move를 호출하라고 등록함
movementController.OnMoveEvent += Move;
}
private void FixedUpdate()
{
// 물리 업데이트에서 움직임 적용
// FixedUpdate는 물리업데이트 관련
// rigidebody의 값을 바꾸니까 FixedUpdate
ApplyMovement(movementDirection);
}
private void Move(Vector2 direction)
{
// 이동방향만 정해두고 실제로 움직이지는 않음.
// 움직이는 것은 물리 업데이트에서 진행(rigidbody가 물리니까)
movementDirection = direction;
}
private void ApplyMovement(Vector2 direction)
{
direction = direction * 5;
movementRigidbody.velocity = direction;
}
}
플레이어 오브젝트 만들기
Player Hierarchy
Player Inspector