2026-05-18 GroundSlam
This commit is contained in:
BIN
Assets/01_Scenes/GameScene.unity
LFS
BIN
Assets/01_Scenes/GameScene.unity
LFS
Binary file not shown.
@@ -6,7 +6,7 @@ public class PlayerController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
[Header("Movement")]
|
[Header("Movement")]
|
||||||
[SerializeField] private float _moveSpeed = 5f;
|
[SerializeField] private float _moveSpeed = 5f;
|
||||||
[SerializeField] private string _walkAnimationState = "Walk";
|
[SerializeField] private string _walkAnimationState = "Run";
|
||||||
private float _moveInputX = 0f;
|
private float _moveInputX = 0f;
|
||||||
private string _activeBaseState;
|
private string _activeBaseState;
|
||||||
private bool _isInActionAnimation;
|
private bool _isInActionAnimation;
|
||||||
@@ -44,6 +44,14 @@ public class PlayerController : MonoBehaviour
|
|||||||
private ActionData _movementLockAction;
|
private ActionData _movementLockAction;
|
||||||
private ActionData _facingLockAction;
|
private ActionData _facingLockAction;
|
||||||
|
|
||||||
|
[Header("Ground Pound")]
|
||||||
|
[SerializeField] private ActionData _groundPoundData;
|
||||||
|
[SerializeField] private string _groundPoundFallAnimationState = "GroundSlamLoop";
|
||||||
|
[SerializeField] private string _groundPoundImpactAnimationState = "GroundSlamEnd";
|
||||||
|
[SerializeField] private float _groundPoundWindupDuration = 0.15f;
|
||||||
|
[SerializeField] private float _groundPoundFallSpeed = 25f;
|
||||||
|
private bool _isGroundPounding;
|
||||||
|
|
||||||
[Header("Motion")]
|
[Header("Motion")]
|
||||||
[SerializeField] private ComboNode _dashRootNode;
|
[SerializeField] private ComboNode _dashRootNode;
|
||||||
[SerializeField] private ComboNode _rollRootNode;
|
[SerializeField] private ComboNode _rollRootNode;
|
||||||
@@ -218,7 +226,15 @@ private void OnJumpInput()
|
|||||||
|
|
||||||
private void OnPunchInput() => HandleComboInput(ComboInputType.Punch);
|
private void OnPunchInput() => HandleComboInput(ComboInputType.Punch);
|
||||||
private void OnKickInput() => HandleComboInput(ComboInputType.Kick);
|
private void OnKickInput() => HandleComboInput(ComboInputType.Kick);
|
||||||
private void OnGrabSmashInput() => HandleComboInput(ComboInputType.Grab);
|
private void OnGrabSmashInput()
|
||||||
|
{
|
||||||
|
if (!_isGrounded && _groundPoundData != null)
|
||||||
|
{
|
||||||
|
PerformGroundPound();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HandleComboInput(ComboInputType.Grab);
|
||||||
|
}
|
||||||
private void OnDashInput() => ExecuteMotionNode(_dashRootNode);
|
private void OnDashInput() => ExecuteMotionNode(_dashRootNode);
|
||||||
private void OnRollInput() => ExecuteMotionNode(_rollRootNode);
|
private void OnRollInput() => ExecuteMotionNode(_rollRootNode);
|
||||||
private void OnBackDashInput() => ExecuteMotionNode(_backDashRootNode);
|
private void OnBackDashInput() => ExecuteMotionNode(_backDashRootNode);
|
||||||
@@ -400,6 +416,100 @@ private async Awaitable MotionRoutine(ActionData data, CancellationToken token)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void PerformGroundPound()
|
||||||
|
{
|
||||||
|
if (_groundPoundData == null) return;
|
||||||
|
|
||||||
|
CancelAttack();
|
||||||
|
CancelAndDispose(ref _motionCts);
|
||||||
|
_motionCts = CancellationTokenSource.CreateLinkedTokenSource(destroyCancellationToken);
|
||||||
|
CancellationToken token = _motionCts.Token;
|
||||||
|
|
||||||
|
_isMotionActive = true;
|
||||||
|
_isGroundPounding = true;
|
||||||
|
_attackStartTime = Time.time;
|
||||||
|
_lastAttackGizmoData = _groundPoundData;
|
||||||
|
_hitFired = false;
|
||||||
|
|
||||||
|
ClearActionLocks();
|
||||||
|
FaceMotionDirection(_groundPoundData);
|
||||||
|
PlayActionAnimation(_groundPoundData);
|
||||||
|
LockMovementIfNeeded(_groundPoundData);
|
||||||
|
LockFacingIfNeeded(_groundPoundData);
|
||||||
|
|
||||||
|
float fallSpeed = _groundPoundFallSpeed > 0f
|
||||||
|
? _groundPoundFallSpeed
|
||||||
|
: Mathf.Max(Mathf.Abs(_groundPoundData.Velocity.y), 25f);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1) 윈드업: 짧게 공중 정지 후 슬램. ApplyGravity는 _isGroundPounding 플래그로 우회.
|
||||||
|
float windupElapsed = 0f;
|
||||||
|
while (windupElapsed < _groundPoundWindupDuration && !_isGrounded)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
_rb.linearVelocity = Vector2.zero;
|
||||||
|
windupElapsed += Time.deltaTime;
|
||||||
|
await Awaitable.NextFrameAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) 낙하 애니메이션으로 전환 (루프). 윈드업이 끝났을 때만 실행.
|
||||||
|
if (_anim != null && !string.IsNullOrEmpty(_groundPoundFallAnimationState) && !_isGrounded)
|
||||||
|
{
|
||||||
|
CancelAndDispose(ref _animationSpeedCts);
|
||||||
|
_anim.speed = 1f;
|
||||||
|
_anim.Play(_groundPoundFallAnimationState);
|
||||||
|
_anim.Update(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) 지면 닿을 때까지 강제 낙하.
|
||||||
|
while (!_isGrounded)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
_rb.linearVelocity = new Vector2(0f, -fallSpeed);
|
||||||
|
await Awaitable.NextFrameAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) 착지 순간 임팩트 애니메이션으로 전환 (낙하 거리 불일치 해소)
|
||||||
|
if (_anim != null && !string.IsNullOrEmpty(_groundPoundImpactAnimationState))
|
||||||
|
{
|
||||||
|
CancelAndDispose(ref _animationSpeedCts);
|
||||||
|
_anim.speed = 1f;
|
||||||
|
_anim.Play(_groundPoundImpactAnimationState);
|
||||||
|
_anim.Update(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 착지 임팩트
|
||||||
|
if (_groundPoundData.HasHit && _attackHitbox != null)
|
||||||
|
{
|
||||||
|
ActivateAttackHitbox(_groundPoundData);
|
||||||
|
|
||||||
|
float hitDuration = Mathf.Max(_groundPoundData.HitDuration, 0.05f);
|
||||||
|
await Awaitable.WaitForSecondsAsync(hitDuration, token);
|
||||||
|
|
||||||
|
_attackHitbox.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 후딜
|
||||||
|
float recovery = Mathf.Max(_groundPoundData.MotionDuration, 0.15f);
|
||||||
|
await Awaitable.WaitForSecondsAsync(recovery, token);
|
||||||
|
|
||||||
|
PlayIdleAnimation();
|
||||||
|
}
|
||||||
|
catch (System.OperationCanceledException)
|
||||||
|
{
|
||||||
|
_attackHitbox?.Deactivate();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isGroundPounding = false;
|
||||||
|
_isMotionActive = false;
|
||||||
|
ClearActionLocks();
|
||||||
|
// 그라운드 파운드 직후 Land 애니메이션 중복 재생 방지
|
||||||
|
_wasGroundedLastFrame = _isGrounded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void CancelAttack()
|
private void CancelAttack()
|
||||||
{
|
{
|
||||||
CancelAndDispose(ref _attackCts);
|
CancelAndDispose(ref _attackCts);
|
||||||
@@ -996,6 +1106,9 @@ private async Awaitable WaitForActionEnd(ActionData data, CancellationToken toke
|
|||||||
|
|
||||||
private void ApplyGravity()
|
private void ApplyGravity()
|
||||||
{
|
{
|
||||||
|
// 그라운드 파운드는 _maxFallSpeed에 막히지 않도록 자체 속도를 그대로 유지한다.
|
||||||
|
if (_isGroundPounding) return;
|
||||||
|
|
||||||
float vy = _rb.linearVelocity.y;
|
float vy = _rb.linearVelocity.y;
|
||||||
|
|
||||||
if (_isGrounded && vy <= 0f)
|
if (_isGrounded && vy <= 0f)
|
||||||
|
|||||||
@@ -26,6 +26,32 @@ AnimatorState:
|
|||||||
m_MirrorParameter:
|
m_MirrorParameter:
|
||||||
m_CycleOffsetParameter:
|
m_CycleOffsetParameter:
|
||||||
m_TimeParameter:
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &-9013432840856765531
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: GroundSlamEnd
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions: []
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 43a3597f5e5a1b646b018598197b92a6, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
--- !u!1102 &-8997814140322552695
|
--- !u!1102 &-8997814140322552695
|
||||||
AnimatorState:
|
AnimatorState:
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
@@ -832,6 +858,32 @@ AnimatorState:
|
|||||||
m_MirrorParameter:
|
m_MirrorParameter:
|
||||||
m_CycleOffsetParameter:
|
m_CycleOffsetParameter:
|
||||||
m_TimeParameter:
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &-3426527744796024442
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: GroundSlamLoop
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions: []
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: dfe5fd923a41a494399e84b126452f41, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
--- !u!1102 &-3380229326876372857
|
--- !u!1102 &-3380229326876372857
|
||||||
AnimatorState:
|
AnimatorState:
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
@@ -2076,6 +2128,32 @@ AnimatorState:
|
|||||||
m_MirrorParameter:
|
m_MirrorParameter:
|
||||||
m_CycleOffsetParameter:
|
m_CycleOffsetParameter:
|
||||||
m_TimeParameter:
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &4277843955758000149
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: GroundSlamStart
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions: []
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 97161820e52e20b40bedabdf43c7d6f5, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
--- !u!1102 &4302945159732726270
|
--- !u!1102 &4302945159732726270
|
||||||
AnimatorState:
|
AnimatorState:
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
@@ -3150,6 +3228,15 @@ AnimatorStateMachine:
|
|||||||
- serializedVersion: 1
|
- serializedVersion: 1
|
||||||
m_State: {fileID: -4203153932972611291}
|
m_State: {fileID: -4203153932972611291}
|
||||||
m_Position: {x: 5280, y: 90, z: 0}
|
m_Position: {x: 5280, y: 90, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: 4277843955758000149}
|
||||||
|
m_Position: {x: 2480, y: 440, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -3426527744796024442}
|
||||||
|
m_Position: {x: 2690, y: 440, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -9013432840856765531}
|
||||||
|
m_Position: {x: 2900, y: 440, z: 0}
|
||||||
m_ChildStateMachines: []
|
m_ChildStateMachines: []
|
||||||
m_AnyStateTransitions: []
|
m_AnyStateTransitions: []
|
||||||
m_EntryTransitions: []
|
m_EntryTransitions: []
|
||||||
|
|||||||
Binary file not shown.
BIN
Assets/03_Character/WhiteMan/Animations/GroundSlam_End.anim
LFS
Normal file
BIN
Assets/03_Character/WhiteMan/Animations/GroundSlam_End.anim
LFS
Normal file
Binary file not shown.
BIN
Assets/03_Character/WhiteMan/Animations/GroundSlam_Loop.anim
LFS
Normal file
BIN
Assets/03_Character/WhiteMan/Animations/GroundSlam_Loop.anim
LFS
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dfe5fd923a41a494399e84b126452f41
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 7400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/03_Character/WhiteMan/Animations/GroundSlam_Start.anim
LFS
Normal file
BIN
Assets/03_Character/WhiteMan/Animations/GroundSlam_Start.anim
LFS
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 97161820e52e20b40bedabdf43c7d6f5
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 7400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
BIN
Assets/05_Data/Attack/GroundSlam.asset
LFS
Normal file
BIN
Assets/05_Data/Attack/GroundSlam.asset
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user