Reset Async Trace Time有40ms+的性能消耗

Hi,

我们看了一下,似乎是我们交互系统影响的。

[Image Removed]我们是交互里面是用了overlap

临时修改了一下

const ECollisionChannel TraceChannel_Interaction = ECollisionChannel::ECC_GameTraceChannel1;

const EObjectTypeQuery Cthu_Object_InteractionCollision = EObjectTypeQuery::ObjectTypeQuery11;

`private void QueryInteractables()
{
AActor ActorOwner = GetAvatarActor();

if (ActorOwner != nullptr)
{
FCollisionQueryParams Params(n"UAbilityTask_GrantNearbyInteraction", false, ActorOwner);

FScriptOverlapDelegate Delegate;
Delegate.BindUFunction(this, n"DealwithAsyncOverlapResults");

FCollisionObjectQueryParams ObjectQueryParams = UCollisionProfile::ObjectTypeToQueryParams(CthuCollision::Cthu_Object_InteractionCollision);

System::AsyncOverlapByObjectType(ActorOwner.GetActorLocation(),
FQuat::Identity,
ObjectQueryParams,
FCollisionShape::MakeSphere(InteractionScanRange), Params, InDelegate = Delegate);
}
}`

[Image Removed]修改以后 Reset Async Trace是正常了

[Image Removed]但是还有一点其他的开销。

[Image Removed]应该是这里导致的 (上面的代码是修改的下图中第一个节点的实现)

[Image Removed]这个也是异步的检测

[Image Removed]每帧都进行 先判断是否在范围内 然后再测试能否通过同步的射线检测 异步overlap+同步射线检测

`UCLASS()
class UAbilityTask_WaitForInteractableTargets_Visible_Ex : UAbilityTask_WaitForInteractableTargets_Base
{
default IsTickingTask = true;

FTraceHandle AsyncOverlapHandle;

EObjectTypeQuery ObjectTypeQuery = CthuCollision::Cthu_Object_InteractionCollision;

FGameplayAbilityTargetingLocationInfo StartLocation;

FCollisionShape CollisionShape;

bool bMultiTarget;

FInteractionQuery InteractionQuery;

// float InteractionScanRate = 0.100;
bool bShowDebug = false;

float TestAngle = 12;

UFUNCTION(BlueprintOverride)
void Activate()
{
}

UFUNCTION(BlueprintOverride)
void TickTask(float DeltaTimeSecs)
{
if (!bIsEnableDetection)
{
return;
}

if (!IsValid(AvatarActor))
{
return;
}

// 使用上一帧发起的异步检测的Overlap数据.
FOverlapDatum OverlapData;
if (System::QueryOverlapData(AsyncOverlapHandle, OverlapData))
{
const FVector Pos = StartLocation.GetTargetingTransform().GetLocation();

// 异步检测,存在当前帧已经销毁的情况.
TArray ValidatedOverlapResults = GetValidatedOverlapResults(OverlapData.OutOverlaps);

TArray OverlapResults = ConvertOverlapResultsToSortedHitResults(Pos, ValidatedOverlapResults);

DealwithOverlapResults(OverlapResults);
}
// AsyncTraceHandle = FTraceHandle();

// 开始这一帧的异步检测
FCollisionQueryParams Params(n"UAbilityTask_WaitForInteractableTargets_Visible_Ex", false, AvatarActor);

FVector TraceStart = StartLocation.GetTargetingTransform().GetLocation();
FQuat Rotation = AvatarActor.GetActorQuat();

AsyncOverlapHandle = AsyncDoOverlap(TraceStart, Rotation, ObjectTypeQuery, CollisionShape, Params);
}

void DealwithOverlapResults(TArray InOverlapResults)
{
TArray OverlapResults = InOverlapResults;

RemoveNotGoodHit(OverlapResults);

if (!bMultiTarget)
{
if (OverlapResults.IsValidIndex(0)) // 只使用第一个.也就是最近的那个.
{
auto FirstItem = OverlapResults[0];

OverlapResults.Empty();
OverlapResults.Add(FirstItem);
}
}

UpdateInteractableOptions(InteractionQuery, OverlapResults);
}

UFUNCTION(BlueprintOverride)
void OnDestroy(bool bInOwnerFinished)
{
Super::OnDestroy(bInOwnerFinished);
}

void SetStartLocation(FGameplayAbilityTargetingLocationInfo InStartLocation)
{
StartLocation = InStartLocation;

ThrowIf(!StartLocation.IsValid(), “Seted StartLocation is not valid”);
}

void RemoveNotGoodHit(TArray& HitResults)
{
FVector ViewStart;
FRotator ViewRot;

APlayerController PC = Ability.ActorInfo.PlayerController;
ThrowIf(!IsValid(PC), “PC is not valid”);

PC.GetPlayerViewPoint(ViewStart, ViewRot);

const FVector FaceToDir = ViewRot.Vector();

for (int32 i = HitResults.Num() - 1; i >= 0; i–)
{
const FHitResult& Hit = HitResults[i];
const FVector TestTargetLoc = Hit.Component.GetWorldLocation();
const FVector ViewDirToTarget = (TestTargetLoc - ViewStart).GetSafeNormal();

const float DotProduct = ViewDirToTarget.DotProduct(FaceToDir);
const float FaceTo_Deg = Math::ACosDeg(DotProduct);

float IncludedAngle = TestAngle;

AInteractable_Proxy ProxyActor = Cast<AInteractable_Proxy>(Hit.Actor);
if (ProxyActor != nullptr)
{
if (ProxyActor.bShouldOverrideTraceParam)
{
if (ProxyActor.ViewIncludedAngle > 0)
{
IncludedAngle = ProxyActor.ViewIncludedAngle;
}
}
}

// if (Hit.Actor.GetFullName().Contains(“Ladder”))
// {
// PrintToScreen(f"Ladder FaceTo_Deg: {FaceTo_Deg} IncludedAngle: {IncludedAngle}", 0.12, FLinearColor::Red);
// }

if (!Math::InRange(FaceTo_Deg, 0, IncludedAngle))
{
HitResults.RemoveAt(i);
continue;
}

FCollisionQueryParams QueryParams(n"LineOfSight", true, AvatarActor);

float SweepRadius = 5;
if (ProxyActor != nullptr)
{
if (ProxyActor.bShouldOverrideTraceParam)
{
if (ProxyActor.SweepSphereRadius >= 0)
{
SweepRadius = ProxyActor.SweepSphereRadius;
}
}

QueryParams.AddIgnoredActors(ProxyActor.IgnoreCollisionActors);
}

FHitResult OutHitResult;
DoTrace_Single(OutHitResult, ViewStart, TestTargetLoc, SweepRadius, CthuCollision::TraceChannel_Interaction, QueryParams);

// 在能射线命中InteractableActor的情况下,才合理.
if (OutHitResult.Actor != Hit.Actor)
{
// Print(f"{OutHitResult.Actor}");

HitResults.RemoveAt(i);
continue;
}
}
}
}

UFUNCTION(BlueprintCallable, Category = “as|task”, meta = (HidePin = “OwningAbility”, DefaultToSelf = “OwningAbility”, BlueprintInternalUseOnly = “True”))
UAbilityTask_WaitForInteractableTargets_Visible_Ex WaitForInteractableTargets_Visible_Ex(UGameplayAbility OwningAbility,
FInteractionQuery InteractionQuery, bool bMultiTarget,
FGameplayAbilityTargetingLocationInfo StartLocation, float SphereRadius, float TestAngle = 12,
EInteractableTargetFilterType InTargetFilter = EInteractableTargetFilterType::CanInteractTo,
// float InteractionScanRate = 0.100,
bool bShowDebug = false)
{
UAbilityTask_WaitForInteractableTargets_Visible_Ex MyObj =
UAngelscriptAbilityTask::CreateAbilityTask_Ex(UAbilityTask_WaitForInteractableTargets_Visible_Ex, OwningAbility);

MyObj.CollisionShape = FCollisionShape::MakeSphere(SphereRadius);
// MyObj.InteractionScanRate = InteractionScanRate;

MyObj.bMultiTarget = bMultiTarget;

MyObj.TargetFilter = InTargetFilter;

MyObj.TestAngle = TestAngle;

MyObj.SetStartLocation(StartLocation);

MyObj.InteractionQuery = InteractionQuery;
// MyObj->TraceTypeQuery = TraceTypeQuery;
MyObj.bShowDebug = bShowDebug;

return MyObj;
}` 这里感觉主要也是异步overlap的开销。还能怎么优化么?同步射线检测,进行少量的检测,应该几乎不影响性能。