// Copyright 2025 https://yuewu.dev/en All Rights Reserved. #include "Collision/GCS_AsyncAction_CollisionTrace.h" #include "Collision/GCS_TraceSystemComponent.h" #include "Components/PrimitiveComponent.h" #include "Engine/Engine.h" UGCS_AsyncAction_CollisionTrace* UGCS_AsyncAction_CollisionTrace::SetupAndListenForCollisionTraceHit(UGCS_TraceSystemComponent* TraceSystem, const TArray& TraceDefinitions, UPrimitiveComponent* PrimitiveComponent, UObject* OptionalSourceObject) { if (TraceSystem == nullptr) { FFrame::KismetExecutionMessage(TEXT("SetupAndListenForCollisionTraceHit was passed a null TraceSystem"), ELogVerbosity::Error); return nullptr; } if (PrimitiveComponent == nullptr) { FFrame::KismetExecutionMessage(TEXT("SetupAndListenForCollisionTraceHit was passed a null PrimitiveComponent"), ELogVerbosity::Error); return nullptr; } if (TraceDefinitions.IsEmpty()) { FFrame::KismetExecutionMessage(TEXT("SetupAndListenForCollisionTraceHit was passed empty TraceDefinitions"), ELogVerbosity::Error); return nullptr; } UWorld* World = GEngine->GetWorldFromContextObject(TraceSystem, EGetWorldErrorMode::LogAndReturnNull); if (!World) { return nullptr; } UGCS_AsyncAction_CollisionTrace* Action = NewObject(); Action->TraceDefinitions = TraceDefinitions; Action->TraceSystem = TraceSystem; Action->SourceComponent = PrimitiveComponent; Action->SourceObject = OptionalSourceObject; Action->RegisterWithGameInstance(World); return Action; } void UGCS_AsyncAction_CollisionTrace::Activate() { UGCS_TraceSystemComponent* TSC = TraceSystem.Get(); UPrimitiveComponent* Primitive = SourceComponent.Get(); UObject* SourceObj = SourceObject.Get(); if (TSC && Primitive) { TSC->OnTraceHitEvent.AddDynamic(this, &ThisClass::TraceHitCallback); static FHitResult EmptyHitResult; TraceHandles = TSC->AddTraces(TraceDefinitions, Primitive, SourceObj); for (auto& Handle : TraceHandles) { BeforeActive.Broadcast(Handle, EmptyHitResult); TSC->StartTrace(Handle); } } else { SetReadyToDestroy(); } } void UGCS_AsyncAction_CollisionTrace::Cancel() { Super::Cancel(); UGCS_TraceSystemComponent* TSC = TraceSystem.Get(); UPrimitiveComponent* Primitive = SourceComponent.Get(); if (TSC && Primitive) { TSC->OnTraceHitEvent.RemoveAll(this); //Deactivate traces. for (const FGCS_TraceHandle& Handle : TraceHandles) { if (Handle.IsValidHandle()) { TSC->RemoveTrace(Handle); } } TraceHandles.Empty(); SourceComponent = nullptr; TraceSystem = nullptr; SourceObject = nullptr; } } void UGCS_AsyncAction_CollisionTrace::TraceHitCallback(const FGCS_TraceHandle& TraceHandle, const FHitResult& HitResult) { if (ShouldBroadcastDelegates() && TraceHandle.IsValidHandle()) { if (TraceHandles.Contains(TraceHandle)) { OnHit.Broadcast(TraceHandle, HitResult); } } }