最近做傳送門的時候發現一個很好玩的問題,當我透過Collsion觸發帶floatingPawnMovement的Pawn的SetActionLocation時會獲得非常大的速度:
pawn直接彈射到宇宙了ಠ_ಠ
但是當我透過controller按鍵觸發傳送時 卻沒有這個問題
於是我看了下floatingPawnMovement程式碼 發現了問題所在
`void UFloatingPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
if (ShouldSkipUpdate(DeltaTime))
{
return;
}
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (!PawnOwner || !UpdatedComponent)
{
return;
}
const AController* Controller = PawnOwner->GetController();
if (Controller && Controller->IsLocalController())
{
// apply input for local players but also for AI that's not following a navigation path at the moment
if (Controller->IsLocalPlayerController() == true || Controller->IsFollowingAPath() == false || bUseAccelerationForPaths)
{
ApplyControlInputToVelocity(DeltaTime);
}
// if it's not player controller, but we do have a controller, then it's AI
// (that's not following a path) and we need to limit the speed
else if (IsExceedingMaxSpeed(MaxSpeed) == true)
{
Velocity = Velocity.GetUnsafeNormal() * MaxSpeed;
}
LimitWorldBounds();
bPositionCorrected = false;
// Move actor
FVector Delta = Velocity * DeltaTime;
if (!Delta.IsNearlyZero(1e-6f))
{
const FVector OldLocation = UpdatedComponent->GetComponentLocation();
const FQuat Rotation = UpdatedComponent->GetComponentQuat();
FHitResult Hit(1.f);
SafeMoveUpdatedComponent(Delta, Rotation, true, Hit);
if (Hit.IsValidBlockingHit())
{
HandleImpact(Hit, DeltaTime, Delta);
// Try to slide the remaining distance along the surface.
SlideAlongSurface(Delta, 1.f-Hit.Time, Hit.Normal, Hit, true);
}
// Update velocity
// We don't want position changes to vastly reverse our direction (which can happen due to penetration fixups etc)
if (!bPositionCorrected)
{
const FVector NewLocation = UpdatedComponent->GetComponentLocation();
Velocity = ((NewLocation - OldLocation) / DeltaTime);
}
}
// Finalize
UpdateComponentVelocity();
}
};`
可以發現這裡官方也註釋了為了防止突然的位置變換導致速度異常,但是為什麼在Collision觸發的情況下會導致 NewLocation 和OldLocation差值過大就很奇怪。
目前有一個簡單藍圖解決方案:
(在下一幀開始時強制設定速度為0並再次確保位置正確)
後面有時間編譯下原始碼debug看看程式碼裡怎麼改比較好