2026-05-20 무기습득
This commit is contained in:
@@ -163,6 +163,33 @@ public @GameInput()
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
},
|
||||
{
|
||||
""name"": ""WeaponSlot1"",
|
||||
""type"": ""Button"",
|
||||
""id"": ""a1b2c3d4-1111-1111-1111-111111111111"",
|
||||
""expectedControlType"": """",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
},
|
||||
{
|
||||
""name"": ""WeaponSlot2"",
|
||||
""type"": ""Button"",
|
||||
""id"": ""a1b2c3d4-2222-2222-2222-222222222222"",
|
||||
""expectedControlType"": """",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
},
|
||||
{
|
||||
""name"": ""WeaponSlot3"",
|
||||
""type"": ""Button"",
|
||||
""id"": ""a1b2c3d4-3333-3333-3333-333333333333"",
|
||||
""expectedControlType"": """",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
}
|
||||
],
|
||||
""bindings"": [
|
||||
@@ -297,6 +324,39 @@ public @GameInput()
|
||||
""action"": ""GrabSmash"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""b1c2d3e4-1111-1111-1111-111111111111"",
|
||||
""path"": ""<Keyboard>/1"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""WeaponSlot1"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""b1c2d3e4-2222-2222-2222-222222222222"",
|
||||
""path"": ""<Keyboard>/2"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""WeaponSlot2"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""b1c2d3e4-3333-3333-3333-333333333333"",
|
||||
""path"": ""<Keyboard>/3"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""WeaponSlot3"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -313,6 +373,9 @@ public @GameInput()
|
||||
m_Player_Roll = m_Player.FindAction("Roll", throwIfNotFound: true);
|
||||
m_Player_BackDash = m_Player.FindAction("BackDash", throwIfNotFound: true);
|
||||
m_Player_GrabSmash = m_Player.FindAction("GrabSmash", throwIfNotFound: true);
|
||||
m_Player_WeaponSlot1 = m_Player.FindAction("WeaponSlot1", throwIfNotFound: true);
|
||||
m_Player_WeaponSlot2 = m_Player.FindAction("WeaponSlot2", throwIfNotFound: true);
|
||||
m_Player_WeaponSlot3 = m_Player.FindAction("WeaponSlot3", throwIfNotFound: true);
|
||||
}
|
||||
|
||||
~@GameInput()
|
||||
@@ -401,6 +464,9 @@ public int FindBinding(InputBinding bindingMask, out InputAction action)
|
||||
private readonly InputAction m_Player_Roll;
|
||||
private readonly InputAction m_Player_BackDash;
|
||||
private readonly InputAction m_Player_GrabSmash;
|
||||
private readonly InputAction m_Player_WeaponSlot1;
|
||||
private readonly InputAction m_Player_WeaponSlot2;
|
||||
private readonly InputAction m_Player_WeaponSlot3;
|
||||
/// <summary>
|
||||
/// Provides access to input actions defined in input action map "Player".
|
||||
/// </summary>
|
||||
@@ -445,6 +511,18 @@ public struct PlayerActions
|
||||
/// </summary>
|
||||
public InputAction @GrabSmash => m_Wrapper.m_Player_GrabSmash;
|
||||
/// <summary>
|
||||
/// Provides access to the underlying input action "Player/WeaponSlot1".
|
||||
/// </summary>
|
||||
public InputAction @WeaponSlot1 => m_Wrapper.m_Player_WeaponSlot1;
|
||||
/// <summary>
|
||||
/// Provides access to the underlying input action "Player/WeaponSlot2".
|
||||
/// </summary>
|
||||
public InputAction @WeaponSlot2 => m_Wrapper.m_Player_WeaponSlot2;
|
||||
/// <summary>
|
||||
/// Provides access to the underlying input action "Player/WeaponSlot3".
|
||||
/// </summary>
|
||||
public InputAction @WeaponSlot3 => m_Wrapper.m_Player_WeaponSlot3;
|
||||
/// <summary>
|
||||
/// Provides access to the underlying input action map instance.
|
||||
/// </summary>
|
||||
public InputActionMap Get() { return m_Wrapper.m_Player; }
|
||||
@@ -494,6 +572,15 @@ public void AddCallbacks(IPlayerActions instance)
|
||||
@GrabSmash.started += instance.OnGrabSmash;
|
||||
@GrabSmash.performed += instance.OnGrabSmash;
|
||||
@GrabSmash.canceled += instance.OnGrabSmash;
|
||||
@WeaponSlot1.started += instance.OnWeaponSlot1;
|
||||
@WeaponSlot1.performed += instance.OnWeaponSlot1;
|
||||
@WeaponSlot1.canceled += instance.OnWeaponSlot1;
|
||||
@WeaponSlot2.started += instance.OnWeaponSlot2;
|
||||
@WeaponSlot2.performed += instance.OnWeaponSlot2;
|
||||
@WeaponSlot2.canceled += instance.OnWeaponSlot2;
|
||||
@WeaponSlot3.started += instance.OnWeaponSlot3;
|
||||
@WeaponSlot3.performed += instance.OnWeaponSlot3;
|
||||
@WeaponSlot3.canceled += instance.OnWeaponSlot3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -529,6 +616,15 @@ private void UnregisterCallbacks(IPlayerActions instance)
|
||||
@GrabSmash.started -= instance.OnGrabSmash;
|
||||
@GrabSmash.performed -= instance.OnGrabSmash;
|
||||
@GrabSmash.canceled -= instance.OnGrabSmash;
|
||||
@WeaponSlot1.started -= instance.OnWeaponSlot1;
|
||||
@WeaponSlot1.performed -= instance.OnWeaponSlot1;
|
||||
@WeaponSlot1.canceled -= instance.OnWeaponSlot1;
|
||||
@WeaponSlot2.started -= instance.OnWeaponSlot2;
|
||||
@WeaponSlot2.performed -= instance.OnWeaponSlot2;
|
||||
@WeaponSlot2.canceled -= instance.OnWeaponSlot2;
|
||||
@WeaponSlot3.started -= instance.OnWeaponSlot3;
|
||||
@WeaponSlot3.performed -= instance.OnWeaponSlot3;
|
||||
@WeaponSlot3.canceled -= instance.OnWeaponSlot3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -625,5 +721,26 @@ public interface IPlayerActions
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
|
||||
void OnGrabSmash(InputAction.CallbackContext context);
|
||||
/// <summary>
|
||||
/// Method invoked when associated input action "WeaponSlot1" is either <see cref="UnityEngine.InputSystem.InputAction.started" />, <see cref="UnityEngine.InputSystem.InputAction.performed" /> or <see cref="UnityEngine.InputSystem.InputAction.canceled" />.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.started" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
|
||||
void OnWeaponSlot1(InputAction.CallbackContext context);
|
||||
/// <summary>
|
||||
/// Method invoked when associated input action "WeaponSlot2" is either <see cref="UnityEngine.InputSystem.InputAction.started" />, <see cref="UnityEngine.InputSystem.InputAction.performed" /> or <see cref="UnityEngine.InputSystem.InputAction.canceled" />.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.started" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
|
||||
void OnWeaponSlot2(InputAction.CallbackContext context);
|
||||
/// <summary>
|
||||
/// Method invoked when associated input action "WeaponSlot3" is either <see cref="UnityEngine.InputSystem.InputAction.started" />, <see cref="UnityEngine.InputSystem.InputAction.performed" /> or <see cref="UnityEngine.InputSystem.InputAction.canceled" />.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.started" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
|
||||
void OnWeaponSlot3(InputAction.CallbackContext context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ public class InputManager : MonoBehaviour, GameInput.IPlayerActions
|
||||
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()
|
||||
@@ -104,4 +107,22 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,11 @@ public class PlayerController : MonoBehaviour,IDamageable
|
||||
private Animator _anim;
|
||||
private SpriteRenderer _spriteRenderer; // 좌우 반전 + flipX 페이싱용
|
||||
|
||||
// ─── 무기 시스템 ────────────────────────────────────────────────────
|
||||
// PlayerWeaponInventory가 현재 장착 무기 관리. 무기 교체 시 OnWeaponChanged 이벤트 발화.
|
||||
// 무장 시 idle/walk 애니메이션과 Punch 콤보 root가 무기 데이터로 교체됨.
|
||||
private PlayerWeaponInventory _weaponInventory;
|
||||
|
||||
// 컴포넌트 캐싱 + 자식 AttackHitbox 자동 보장 + hit 이벤트 구독.
|
||||
private void Awake()
|
||||
{
|
||||
@@ -130,6 +135,12 @@ private void Awake()
|
||||
EnsureAttackHitbox();
|
||||
// 공격이 enemy를 hit하면 _lastHitEnemy를 기억 → 다음 잡기에서 그 enemy를 우선 타겟팅.
|
||||
_attackHitbox.OnHit += OnAttackHit;
|
||||
|
||||
// 무기 인벤토리: 같은 GameObject에 컴포넌트가 없으면 자동 부착.
|
||||
_weaponInventory = GetComponent<PlayerWeaponInventory>();
|
||||
if (_weaponInventory == null)
|
||||
_weaponInventory = gameObject.AddComponent<PlayerWeaponInventory>();
|
||||
_weaponInventory.OnWeaponChanged += OnWeaponChanged;
|
||||
}
|
||||
|
||||
private void ResolveBodyColliderReference()
|
||||
@@ -159,6 +170,9 @@ private void Start()
|
||||
InputManager.Instance.OnRoll_Event += OnRollInput;
|
||||
InputManager.Instance.OnBackDash_Event += OnBackDashInput;
|
||||
InputManager.Instance.OnGrabSmash_Event += OnGrabSmashInput;
|
||||
InputManager.Instance.OnWeaponSlot1_Event += OnWeaponSlot1Input;
|
||||
InputManager.Instance.OnWeaponSlot2_Event += OnWeaponSlot2Input;
|
||||
InputManager.Instance.OnWeaponSlot3_Event += OnWeaponSlot3Input;
|
||||
}
|
||||
|
||||
// 이벤트 구독 해제 + 진행 중인 async 작업 모두 취소.
|
||||
@@ -175,6 +189,9 @@ private void OnDestroy()
|
||||
InputManager.Instance.OnRoll_Event -= OnRollInput;
|
||||
InputManager.Instance.OnBackDash_Event -= OnBackDashInput;
|
||||
InputManager.Instance.OnGrabSmash_Event -= OnGrabSmashInput;
|
||||
InputManager.Instance.OnWeaponSlot1_Event -= OnWeaponSlot1Input;
|
||||
InputManager.Instance.OnWeaponSlot2_Event -= OnWeaponSlot2Input;
|
||||
InputManager.Instance.OnWeaponSlot3_Event -= OnWeaponSlot3Input;
|
||||
}
|
||||
|
||||
CancelAndDispose(ref _attackCts);
|
||||
@@ -184,6 +201,25 @@ private void OnDestroy()
|
||||
|
||||
if (_attackHitbox != null)
|
||||
_attackHitbox.OnHit -= OnAttackHit;
|
||||
if (_weaponInventory != null)
|
||||
_weaponInventory.OnWeaponChanged -= OnWeaponChanged;
|
||||
}
|
||||
|
||||
// ─── 무기 슬롯 입력 핸들러 ───────────────────────────────────────────
|
||||
// Key 1 → 맨손, Key 2 → 첫 픽업 무기, Key 3 → 두 번째 픽업 무기.
|
||||
private void OnWeaponSlot1Input() => _weaponInventory.EquipUnarmed();
|
||||
private void OnWeaponSlot2Input() => _weaponInventory.EquipSlot(0);
|
||||
private void OnWeaponSlot3Input() => _weaponInventory.EquipSlot(1);
|
||||
|
||||
// 무기 교체 이벤트 콜백.
|
||||
// 콤보 상태를 리셋하고 locomotion 애니메이션을 즉시 갱신.
|
||||
private void OnWeaponChanged(WeaponData weapon)
|
||||
{
|
||||
_currentNode = null;
|
||||
_comboWindowTimer = 0f;
|
||||
_pendingInput = null;
|
||||
_activeBaseState = null; // 강제 재평가
|
||||
PlayLocomotionState();
|
||||
}
|
||||
|
||||
// 매 물리 프레임의 메인 흐름:
|
||||
@@ -346,9 +382,10 @@ private void ExecuteComboInput(ComboInputType input)
|
||||
}
|
||||
|
||||
// 이어갈 연계가 없으면 입력에 맞는 루트 노드부터 새로 시작한다.
|
||||
// Punch 입력은 무기 장착 시 무기의 AttackRootNode로 분기 (맨손이면 기본 _punchRootNode).
|
||||
ComboNode root = input switch
|
||||
{
|
||||
ComboInputType.Punch => _punchRootNode,
|
||||
ComboInputType.Punch => GetPunchRootNode(),
|
||||
ComboInputType.Kick => _kickRootNode,
|
||||
ComboInputType.Grab => _grabSmashRootNode,
|
||||
_ => null
|
||||
@@ -361,6 +398,15 @@ private void ExecuteComboInput(ComboInputType input)
|
||||
_comboWindowTimer = root.ComboWindow;
|
||||
}
|
||||
|
||||
// 무장 시 무기 데이터의 AttackRootNode 사용 (비어있으면 기본 _punchRootNode 폴백).
|
||||
private ComboNode GetPunchRootNode()
|
||||
{
|
||||
WeaponData equipped = _weaponInventory != null ? _weaponInventory.CurrentWeapon : null;
|
||||
if (equipped != null && equipped.AttackRootNode != null)
|
||||
return equipped.AttackRootNode;
|
||||
return _punchRootNode;
|
||||
}
|
||||
|
||||
private bool CanPerformAction(ActionData data)
|
||||
{
|
||||
if (data == null) return false;
|
||||
@@ -889,10 +935,19 @@ private string ChooseLocomotionState()
|
||||
return _jumpMidAnimationState;
|
||||
}
|
||||
|
||||
if (_moveInputX != 0f && !string.IsNullOrEmpty(_walkAnimationState))
|
||||
return _walkAnimationState;
|
||||
// 무기 장착 시 무기 데이터의 idle/walk를 우선 사용 (비어있으면 기본값으로 폴백).
|
||||
WeaponData equipped = _weaponInventory != null ? _weaponInventory.CurrentWeapon : null;
|
||||
string walk = equipped != null && !string.IsNullOrEmpty(equipped.WalkAnimationState)
|
||||
? equipped.WalkAnimationState
|
||||
: _walkAnimationState;
|
||||
string idle = equipped != null && !string.IsNullOrEmpty(equipped.IdleAnimationState)
|
||||
? equipped.IdleAnimationState
|
||||
: _idleAnimationState;
|
||||
|
||||
return _idleAnimationState;
|
||||
if (_moveInputX != 0f && !string.IsNullOrEmpty(walk))
|
||||
return walk;
|
||||
|
||||
return idle;
|
||||
}
|
||||
|
||||
private void UpdateLocomotionAnimation()
|
||||
|
||||
Reference in New Issue
Block a user