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的开销。还能怎么优化么?同步射线检测,进行少量的检测,应该几乎不影响性能。