fix: 드로그 기본기3 Idle 복귀 루트모션 차단
- 기본기3 종료 후 Idle 복귀 블렌드 구간에서 수평 루트모션이 적용되지 않도록 차단 - SkillController가 Idle 복귀 블렌드 상태를 직접 노출하고 EnemyBase가 해당 구간만 별도로 처리하도록 정리 - 원인 추적용 Idle 복귀 좌표 로그는 제거하고 기능만 유지
This commit is contained in:
@@ -216,6 +216,17 @@ namespace Colosseum.Enemy
|
|||||||
deltaPosition.z = 0f;
|
deltaPosition.z = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 패턴 마지막 스킬이 Idle로 복귀하는 짧은 블렌드 구간에서는
|
||||||
|
// Idle 클립의 수평 루트모션이 섞여 뒤로 밀리는 현상을 막습니다.
|
||||||
|
bool shouldSuppressPostPatternIdleHorizontalRootMotion =
|
||||||
|
skillCtrl != null
|
||||||
|
&& skillCtrl.IsSuppressingIdleRecoveryHorizontalRootMotion;
|
||||||
|
if (shouldSuppressPostPatternIdleHorizontalRootMotion)
|
||||||
|
{
|
||||||
|
deltaPosition.x = 0f;
|
||||||
|
deltaPosition.z = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
bool shouldProjectRootMotionToFacing = skillCtrl != null && skillCtrl.ShouldProjectHorizontalRootMotionToFacing;
|
bool shouldProjectRootMotionToFacing = skillCtrl != null && skillCtrl.ShouldProjectHorizontalRootMotionToFacing;
|
||||||
if (shouldProjectRootMotionToFacing)
|
if (shouldProjectRootMotionToFacing)
|
||||||
deltaPosition = ProjectHorizontalDeltaOntoFacing(deltaPosition);
|
deltaPosition = ProjectHorizontalDeltaOntoFacing(deltaPosition);
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ namespace Colosseum.Skills
|
|||||||
private string currentClipDebugName = string.Empty;
|
private string currentClipDebugName = string.Empty;
|
||||||
private int currentClipStartFrame = -1;
|
private int currentClipStartFrame = -1;
|
||||||
private readonly List<Vector3> debugSkillStartPoints = new();
|
private readonly List<Vector3> debugSkillStartPoints = new();
|
||||||
|
private bool isSuppressingIdleRecoveryHorizontalRootMotion = false;
|
||||||
|
private int idleRecoveryStateHash = 0;
|
||||||
|
|
||||||
|
|
||||||
public bool IsExecutingSkill => currentSkill != null;
|
public bool IsExecutingSkill => currentSkill != null;
|
||||||
@@ -143,6 +145,11 @@ namespace Colosseum.Skills
|
|||||||
public bool UsesRootMotion => currentSkill != null && currentSkill.UseRootMotion;
|
public bool UsesRootMotion => currentSkill != null && currentSkill.UseRootMotion;
|
||||||
public bool IgnoreRootMotionY => currentSkill != null && currentSkill.IgnoreRootMotionY;
|
public bool IgnoreRootMotionY => currentSkill != null && currentSkill.IgnoreRootMotionY;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 스킬 종료 후 Idle 복귀 블렌드 중인지 반환합니다.
|
||||||
|
/// 이 구간에서는 Idle 클립의 수평 루트모션이 섞여 위치가 밀리지 않도록 별도 차단에 사용합니다.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSuppressingIdleRecoveryHorizontalRootMotion => isSuppressingIdleRecoveryHorizontalRootMotion;
|
||||||
|
/// <summary>
|
||||||
/// 현재 스킬의 루트 위치를 실제 이동에 반영해도 되는지 반환합니다.
|
/// 현재 스킬의 루트 위치를 실제 이동에 반영해도 되는지 반환합니다.
|
||||||
/// 스킬 시작 직후 아직 Animator가 Skill 상태로 전이되지 않은 프레임에서는
|
/// 스킬 시작 직후 아직 Animator가 Skill 상태로 전이되지 않은 프레임에서는
|
||||||
/// 이전 상태의 루트 XZ가 누적되지 않도록 위치 적용을 잠시 차단합니다.
|
/// 이전 상태의 루트 XZ가 누적되지 않도록 위치 적용을 잠시 차단합니다.
|
||||||
@@ -336,7 +343,13 @@ namespace Colosseum.Skills
|
|||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (currentSkill == null || animator == null) return;
|
if (animator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateIdleRecoverySuppressionState();
|
||||||
|
|
||||||
|
if (currentSkill == null)
|
||||||
|
return;
|
||||||
|
|
||||||
UpdateCastTargetTracking();
|
UpdateCastTargetTracking();
|
||||||
|
|
||||||
@@ -1730,6 +1743,24 @@ namespace Colosseum.Skills
|
|||||||
return Animator.StringToHash($"{BaseLayerName}.{SKILL_STATE_NAME}");
|
return Animator.StringToHash($"{BaseLayerName}.{SKILL_STATE_NAME}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idle 복귀 블렌드가 끝나면 수평 루트모션 차단 플래그를 자동 해제합니다.
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateIdleRecoverySuppressionState()
|
||||||
|
{
|
||||||
|
if (!isSuppressingIdleRecoveryHorizontalRootMotion || animator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (animator.IsInTransition(0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (idleRecoveryStateHash != 0 && animator.GetCurrentAnimatorStateInfo(0).fullPathHash == idleRecoveryStateHash)
|
||||||
|
{
|
||||||
|
isSuppressingIdleRecoveryHorizontalRootMotion = false;
|
||||||
|
idleRecoveryStateHash = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 현재 레이어가 실제 스킬 상태를 재생 중인지 확인합니다.
|
/// 현재 레이어가 실제 스킬 상태를 재생 중인지 확인합니다.
|
||||||
/// 스킬 시작 직후 한 프레임 동안 이전 상태 정보가 남아 조기 종료되는 것을 방지합니다.
|
/// 스킬 시작 직후 한 프레임 동안 이전 상태 정보가 남아 조기 종료되는 것을 방지합니다.
|
||||||
@@ -1792,9 +1823,22 @@ namespace Colosseum.Skills
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
animator.speed = 1f;
|
animator.speed = 1f;
|
||||||
|
isSuppressingIdleRecoveryHorizontalRootMotion = false;
|
||||||
|
idleRecoveryStateHash = 0;
|
||||||
|
|
||||||
if (recoveryStateHash != 0 && animator.HasState(0, recoveryStateHash))
|
if (recoveryStateHash != 0 && animator.HasState(0, recoveryStateHash))
|
||||||
|
{
|
||||||
|
bool isIdleRecoveryState =
|
||||||
|
recoveryStateHash == ResolveBossIdleStateHash()
|
||||||
|
|| recoveryStateHash == Animator.StringToHash($"{BaseLayerName}.{IdleStateName}");
|
||||||
|
if (isIdleRecoveryState)
|
||||||
|
{
|
||||||
|
isSuppressingIdleRecoveryHorizontalRootMotion = true;
|
||||||
|
idleRecoveryStateHash = recoveryStateHash;
|
||||||
|
}
|
||||||
|
|
||||||
animator.CrossFadeInFixedTime(recoveryStateHash, GetSkillExitTransitionDuration(), 0, 0f);
|
animator.CrossFadeInFixedTime(recoveryStateHash, GetSkillExitTransitionDuration(), 0, 0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user