using System; using UnityEngine; using UnityEngine.InputSystem; // ============================================================================ // InputManager // ---------------------------------------------------------------------------- // Unity Input System의 자동 생성된 GameInput을 직접 인스턴스화해서 관리. // PlayerInput 컴포넌트 안 쓰고 코드로만 처리 → 씬 세팅 의존성 최소화. // // 동작: // - 싱글톤 (Instance 정적 참조) // - Awake에서 GameInput 생성 + IPlayerActions 인터페이스로 콜백 등록 // - 각 InputAction이 발화되면 해당 C# event 발화 // - PlayerController 등 외부에서 event 구독해서 처리 // // 모든 액션은 InputActionPhase.Started 시점에만 발화 (눌렀을 때 1회). // Move만 ctx.ReadValue로 매 프레임 값 전달 (analog 입력). // ============================================================================ public class InputManager : MonoBehaviour, GameInput.IPlayerActions { // 외부에서 InputManager.Instance.OnXxx_Event += handler 형태로 구독. public static InputManager Instance { get; private set; } private GameInput _input; // ─── 입력 이벤트들 (PlayerController 등이 구독) ────────────────────── public event Action OnMove_Event; // 매 프레임 (방향키 값) public event Action OnJump_Event; // 한 번씩 (눌렀을 때) public event Action OnPunch_Event; public event Action OnKick_Event; public event Action OnDash_Event; public event Action OnRoll_Event; public event Action OnBackDash_Event; public event Action OnGrabSmash_Event; public event Action OnWeaponSlot1_Event; public event Action OnWeaponSlot2_Event; public event Action OnWeaponSlot3_Event; // 싱글톤 초기화 + GameInput 생성 + 콜백 등록. private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; _input = new GameInput(); // IPlayerActions의 OnMove/OnJump/... 메서드를 인풋 액션의 콜백으로 자동 연결. _input.Player.SetCallbacks(this); } // GameInput은 활성/비활성 토글이 필요한 자원. ?. 처리로 Awake보다 OnEnable이 먼저 호출되는 경우 보호. private void OnEnable() => _input?.Player.Enable(); private void OnDisable() => _input?.Player.Disable(); private void OnDestroy() => _input?.Dispose(); // ─── 콜백 구현 (IPlayerActions 인터페이스) ─────────────────────────── // Move는 값을 그대로 전달 (정규화/디지털화는 PlayerController가 결정). public void OnMove(InputAction.CallbackContext ctx) { OnMove_Event?.Invoke(ctx.ReadValue()); } // 버튼 타입 입력들은 Started phase에서만 발화 → "눌렀을 때 1회". // 계속 누르고 있어도 추가 발화 안 됨. canceled (뗌)는 무시. public void OnJump(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnJump_Event?.Invoke(); } public void OnPunch(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnPunch_Event?.Invoke(); } public void OnKick(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnKick_Event?.Invoke(); } public void OnDash(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnDash_Event?.Invoke(); } public void OnRoll(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnRoll_Event?.Invoke(); } public void OnBackDash(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnBackDash_Event?.Invoke(); } public void OnGrabSmash(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnGrabSmash_Event?.Invoke(); } public void OnWeaponSlot1(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnWeaponSlot1_Event?.Invoke(); } public void OnWeaponSlot2(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnWeaponSlot2_Event?.Invoke(); } public void OnWeaponSlot3(InputAction.CallbackContext ctx) { if (ctx.phase == InputActionPhase.Started) OnWeaponSlot3_Event?.Invoke(); } }