feat: 플레이어 다운 및 넉백 피격 반응 추가
- HitReactionController로 다운과 넉백 전용 로직을 분리 - 다운 시작, 루프, 회복 애니메이션과 DownEffect를 연결 - 행동 상태와 스킬 취소가 피격 반응과 연동되도록 정리 - 자동 검증 러너에 다운 및 넉백 검증을 추가
This commit is contained in:
@@ -34,6 +34,8 @@ namespace Colosseum.Player
|
||||
private InputSystem_Actions inputActions;
|
||||
private bool isJumping;
|
||||
private bool wasGrounded;
|
||||
private Vector3 forcedMovementVelocity;
|
||||
private float forcedMovementRemaining;
|
||||
|
||||
// 클라이언트가 기록, 서버가 소비하는 월드 스페이스 이동 방향
|
||||
private NetworkVariable<Vector2> netMoveInput = new NetworkVariable<Vector2>(
|
||||
@@ -48,6 +50,7 @@ namespace Colosseum.Player
|
||||
public float CurrentMoveSpeed => netMoveInput.Value.magnitude * moveSpeed * GetMoveSpeedMultiplier();
|
||||
public bool IsGrounded => characterController != null ? characterController.isGrounded : false;
|
||||
public bool IsJumping => isJumping;
|
||||
public bool IsForcedMoving => forcedMovementRemaining > 0f && forcedMovementVelocity.sqrMagnitude > 0.0001f;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
@@ -115,6 +118,7 @@ namespace Colosseum.Player
|
||||
{
|
||||
CleanupInputActions();
|
||||
moveInput = Vector2.zero;
|
||||
ClearForcedMovement();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
@@ -143,6 +147,7 @@ namespace Colosseum.Player
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
CleanupInputActions();
|
||||
ClearForcedMovement();
|
||||
}
|
||||
|
||||
private void OnMovePerformed(InputAction.CallbackContext context) => moveInput = context.ReadValue<Vector2>();
|
||||
@@ -259,10 +264,12 @@ namespace Colosseum.Player
|
||||
{
|
||||
if (characterController == null) return;
|
||||
|
||||
Vector3 forcedDelta = ConsumeForcedMovementDelta(Time.deltaTime);
|
||||
|
||||
if (skillController != null && skillController.IsPlayingAnimation)
|
||||
{
|
||||
if (!skillController.UsesRootMotion)
|
||||
characterController.Move(velocity * Time.deltaTime);
|
||||
characterController.Move(velocity * Time.deltaTime + forcedDelta);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -278,7 +285,7 @@ namespace Colosseum.Player
|
||||
moveDirection = Vector3.zero;
|
||||
|
||||
float actualMoveSpeed = moveSpeed * GetMoveSpeedMultiplier();
|
||||
characterController.Move((moveDirection * actualMoveSpeed + velocity) * Time.deltaTime);
|
||||
characterController.Move((moveDirection * actualMoveSpeed + velocity) * Time.deltaTime + forcedDelta);
|
||||
|
||||
if (moveDirection != Vector3.zero)
|
||||
{
|
||||
@@ -323,6 +330,33 @@ namespace Colosseum.Player
|
||||
return actionState.MoveSpeedMultiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 넉백처럼 입력과 무관한 강제 이동을 적용합니다.
|
||||
/// </summary>
|
||||
public void ApplyForcedMovement(Vector3 worldVelocity, float duration)
|
||||
{
|
||||
if (!IsServer)
|
||||
return;
|
||||
|
||||
if (duration <= 0f || worldVelocity.sqrMagnitude <= 0.0001f)
|
||||
{
|
||||
ClearForcedMovement();
|
||||
return;
|
||||
}
|
||||
|
||||
forcedMovementVelocity = worldVelocity;
|
||||
forcedMovementRemaining = duration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 강제 이동 상태를 즉시 초기화합니다.
|
||||
/// </summary>
|
||||
public void ClearForcedMovement()
|
||||
{
|
||||
forcedMovementVelocity = Vector3.zero;
|
||||
forcedMovementRemaining = 0f;
|
||||
}
|
||||
|
||||
private PlayerActionState GetOrCreateActionState()
|
||||
{
|
||||
var foundState = GetComponent<PlayerActionState>();
|
||||
@@ -343,6 +377,7 @@ namespace Colosseum.Player
|
||||
if (!skillController.UsesRootMotion) return;
|
||||
|
||||
Vector3 deltaPosition = animator.deltaPosition;
|
||||
Vector3 forcedDelta = ConsumeForcedMovementDelta(Time.deltaTime);
|
||||
|
||||
if (blockedDirection != Vector3.zero)
|
||||
{
|
||||
@@ -357,11 +392,11 @@ namespace Colosseum.Player
|
||||
if (skillController.IgnoreRootMotionY)
|
||||
{
|
||||
deltaPosition.y = 0f;
|
||||
characterController.Move(deltaPosition + velocity * Time.deltaTime);
|
||||
characterController.Move(deltaPosition + velocity * Time.deltaTime + forcedDelta);
|
||||
}
|
||||
else
|
||||
{
|
||||
characterController.Move(deltaPosition);
|
||||
characterController.Move(deltaPosition + forcedDelta);
|
||||
}
|
||||
|
||||
if (animator.deltaRotation != Quaternion.identity)
|
||||
@@ -372,5 +407,22 @@ namespace Colosseum.Player
|
||||
|
||||
wasGrounded = characterController.isGrounded;
|
||||
}
|
||||
|
||||
private Vector3 ConsumeForcedMovementDelta(float deltaTime)
|
||||
{
|
||||
if (forcedMovementRemaining <= 0f || forcedMovementVelocity.sqrMagnitude <= 0.0001f)
|
||||
return Vector3.zero;
|
||||
|
||||
float appliedDeltaTime = Mathf.Min(deltaTime, forcedMovementRemaining);
|
||||
forcedMovementRemaining = Mathf.Max(0f, forcedMovementRemaining - appliedDeltaTime);
|
||||
|
||||
Vector3 delta = forcedMovementVelocity * appliedDeltaTime;
|
||||
if (forcedMovementRemaining <= 0f)
|
||||
{
|
||||
forcedMovementVelocity = Vector3.zero;
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user