요약
Mover로 보행 중인 캐릭터가 step-up에 성공하고 같은 시뮬레이션 틱에서 walkable 바닥을 찾지 못해 Falling으로 전환되면, 낙하 모드로 넘겨지는 속도가 비정상적으로 커져 캐릭터가 공중으로 튕겨 나갑니다. 분석 결과 UWalkingMode::SimulationTick_Implementation의 step-up 성공 경로에서 PercentTimeAppliedSoFar를 갱신하지 않는 것이 원인으로 보입니다.
원인 분석 (5.7.4 기준)
- 출력 속도 = RelevantMoveDelta / TotalDeltaSeconds — FMovementRecord::GetRelevantVelocity() (MovementRecord.h ~50). CaptureFinalState가 이 값을 액터 속도로 기록.
- step-up 성공 시 수평 전진량(forward/slide)은 relevant로 적립(분자 증가), up/down은 non-relevant — UGroundMovementUtils::TryMoveToStepUp (GroundMovementUtils.cpp ~153/205/214/333).
- PercentTimeAppliedSoFar는 초기 이동(~188)·램프(~201)·step-up 실패 시 슬라이드(~221) 등 모든 경로에서 갱신되지만, if (!TryMoveToStepUp(…))(~215)에 else가 없어 step-up 성공 시에는 갱신되지 않음.
- 직후 바닥이 walkable이 아니면(~243) Falling 전환(~246–249)
RemainingMs = StepMs - StepMs * PercentTimeAppliedSoFar;
SetDeltaSeconds((StepMs - RemainingMs) * 0.001f); // = DeltaSeconds * PercentTimeAppliedSoFar
PercentTimeAppliedSoFar 가 작은 값(예: ~0.02)으로 남아 있으면 분모가 0에 가까워져 속도가 약 50배로 폭발.
실측 로그(step-up 성공 지점, 보정 전 값):
PercentTimeAppliedSoFar = 0.019378 , StepUpFraction = 0.980622
PercentTimeAppliedSoFar = 0.028127 , StepUpFraction = 0.971873
→ step-up이 남은 이동분을 거의 전부 전진했는데도 분모는 작은 값 그대로라 폭발.
근거 — async 버전은 이미 처리함
동일 알고리즘인 UAsyncWalkingMode::SimulationTick_Implementation (AsyncWalkingMode.cpp)은 step-up 성공 시 명시적으로 갱신합니다:
if (UGroundMovementUtils::TestMoveToStepOver(...)) { // 성공
PercentTimeAppliedSoFar = 1.0f; // ~243
}
그리고 동일한 Falling 전환 공식(~287–288)을 사용합니다. 두 구현이 step-up 성공 경로에서만 갈라지며, async에는 갱신이 있고 sync에는 없다는 점에서 동기 WalkingMode의 누락(버그)으로 판단됩니다.
임시 수정 (확인용)
- UWalkingMode::SimulationTick_Implementation 에서 UGroundMovementUtils::TryMoveToStepUp 성공 시, 처리
if에 else를 추가해 step-up이 실제 전진한 수평 거리 비율만큼 보정하면 런치가 사라집니다:
else { // step-up 성공
const float StepUpHoriz = FVector::VectorPlaneProject(UpdatedComponent->GetComponentLocation() - PreStepUpLocation, UpDirection).Size();
const float IntendedHoriz = FVector::VectorPlaneProject(OrigMoveDelta, UpDirection).Size();
const float StepUpPct = (IntendedHoriz > UE_KINDA_SMALL_NUMBER) ? (StepUpHoriz / IntendedHoriz) : (1.f - PercentTimeAppliedSoFar);
PercentTimeAppliedSoFar = FMath::Clamp(PercentTimeAppliedSoFar + StepUpPct, 0.f, 1.f);
}
(async처럼 = 1.0f로 둬도 폭발은 사라지나, 부분 step-up에서는 속도를 과소평가함.)
질문
- 재현 가능한지, 그리고 기존에 확인된 이슈인지(트래킹 번호 / UE-XXXXX)?
- UWalkingMode의 step-up 성공 경로에서 PercentTimeAppliedSoFar 미갱신이 버그가 맞는지?
- UWalkingMode(미갱신)와 UAsyncWalkingMode(= 1.0f)의 차이가 의도된 것인지, 동기 경로의 누락인지?
- 권장 수정 방향은? (async와 동일하게 = 1.0f vs 실제 수평 이동 비율 보정)
[Attachment Removed]