UE floating pawn movement Bug Set location 導致速度異常發射

AbandonSky發表於2024-05-07

最近做傳送門的時候發現一個很好玩的問題,當我透過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看看程式碼裡怎麼改比較好

相關文章