You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
[SmartObject] return all possible slots for matching object instead of only the first one
#rb aris.theophanidis #ROBOMERGE-AUTHOR: yoan.stamant #ROBOMERGE-SOURCE: CL 18794203 via CL 18794609 via CL 18795800 #ROBOMERGE-BOT: (v908-18788545) [CL 18801442 by yoan stamant in ue5-release-engine-staging branch]
This commit is contained in:
@@ -85,22 +85,22 @@ USmartObjectSubsystem* USmartObjectSubsystem::GetCurrent(const UWorld* World)
|
||||
return UWorld::GetSubsystem<USmartObjectSubsystem>(World);
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::AddToSimulation(const FSmartObjectHandle ID, const USmartObjectDefinition& Definition, const FTransform& Transform, const FBox& Bounds)
|
||||
void USmartObjectSubsystem::AddToSimulation(const FSmartObjectHandle Handle, const USmartObjectDefinition& Definition, const FTransform& Transform, const FBox& Bounds)
|
||||
{
|
||||
if (!ensureMsgf(ID.IsValid(), TEXT("SmartObject needs a valid ID to be added to the simulation")))
|
||||
if (!ensureMsgf(Handle.IsValid(), TEXT("SmartObject needs a valid Handle to be added to the simulation")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ensureMsgf(RuntimeSmartObjects.Find(ID) == nullptr, TEXT("ID '%s' already registered in runtime simulation"), *LexToString(ID)))
|
||||
if (!ensureMsgf(RuntimeSmartObjects.Find(Handle) == nullptr, TEXT("Handle '%s' already registered in runtime simulation"), *LexToString(Handle)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Verbose, TEXT("Adding SmartObject '%s' to runtime simulation."), *LexToString(ID));
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Verbose, TEXT("Adding SmartObject '%s' to runtime simulation."), *LexToString(Handle));
|
||||
|
||||
FSmartObjectRuntime& Runtime = RuntimeSmartObjects.Emplace(ID, FSmartObjectRuntime(Definition));
|
||||
Runtime.SetRegisteredID(ID);
|
||||
FSmartObjectRuntime& Runtime = RuntimeSmartObjects.Emplace(Handle, FSmartObjectRuntime(Definition));
|
||||
Runtime.SetRegisteredID(Handle);
|
||||
|
||||
// Create runtime data and entity for each slot
|
||||
if (UMassEntitySubsystem* EntitySubsystem = GetWorldRef().GetSubsystem<UMassEntitySubsystem>())
|
||||
@@ -139,7 +139,7 @@ void USmartObjectSubsystem::AddToSimulation(const FSmartObjectHandle ID, const U
|
||||
// Insert instance in the octree
|
||||
const FSmartObjectOctreeIDSharedRef SharedOctreeID = MakeShareable(new FSmartObjectOctreeID());
|
||||
Runtime.SetOctreeID(SharedOctreeID);
|
||||
SmartObjectOctree.AddNode(Bounds, ID, SharedOctreeID);
|
||||
SmartObjectOctree.AddNode(Bounds, Handle, SharedOctreeID);
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::AddToSimulation(const FSmartObjectCollectionEntry& Entry, const USmartObjectDefinition& Definition)
|
||||
@@ -155,14 +155,14 @@ void USmartObjectSubsystem::AddToSimulation(const USmartObjectComponent& Compone
|
||||
}
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::RemoveFromSimulation(const FSmartObjectHandle ID)
|
||||
void USmartObjectSubsystem::RemoveFromSimulation(const FSmartObjectHandle Handle)
|
||||
{
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Verbose, TEXT("Removing SmartObject '%s' from runtime simulation."), *LexToString(ID));
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Verbose, TEXT("Removing SmartObject '%s' from runtime simulation."), *LexToString(Handle));
|
||||
|
||||
FSmartObjectRuntime* SmartObjectRuntime = RuntimeSmartObjects.Find(ID);
|
||||
FSmartObjectRuntime* SmartObjectRuntime = RuntimeSmartObjects.Find(Handle);
|
||||
if (SmartObjectRuntime == nullptr)
|
||||
{
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Warning, TEXT("Failed to remove SmartObject '%s' from runtime simulation. No entry found."), *LexToString(ID));
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Warning, TEXT("Failed to remove SmartObject '%s' from runtime simulation. No entry found."), *LexToString(Handle));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ void USmartObjectSubsystem::RemoveFromSimulation(const FSmartObjectHandle ID)
|
||||
EntitySubsystem->Defer().BatchDestroyEntities(EntitiesToDestroy);
|
||||
}
|
||||
|
||||
RuntimeSmartObjects.Remove(ID);
|
||||
RuntimeSmartObjects.Remove(Handle);
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::RemoveFromSimulation(const FSmartObjectCollectionEntry& Entry)
|
||||
@@ -342,15 +342,15 @@ bool USmartObjectSubsystem::UnregisterSmartObjectActor(const AActor& SmartObject
|
||||
return UnregisterSmartObject(*SOComponent);
|
||||
}
|
||||
|
||||
FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectHandle ID, const FSmartObjectRequestFilter& Filter)
|
||||
FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectHandle Handle, const FSmartObjectRequestFilter& Filter)
|
||||
{
|
||||
if (!ensureMsgf(ID.IsValid(), TEXT("SmartObject ID should be valid: %s"), *LexToString(ID)))
|
||||
if (!ensureMsgf(Handle.IsValid(), TEXT("SmartObject handle should be valid: %s"), *LexToString(Handle)))
|
||||
{
|
||||
return FSmartObjectClaimHandle::InvalidHandle;
|
||||
}
|
||||
|
||||
FSmartObjectRuntime* SORuntime = RuntimeSmartObjects.Find(ID);
|
||||
if (!ensureMsgf(SORuntime != nullptr, TEXT("A SmartObjectRuntime must be created for ID %s"), *LexToString(ID)))
|
||||
FSmartObjectRuntime* SORuntime = RuntimeSmartObjects.Find(Handle);
|
||||
if (!ensureMsgf(SORuntime != nullptr, TEXT("A SmartObjectRuntime must be created for handle %s"), *LexToString(Handle)))
|
||||
{
|
||||
return FSmartObjectClaimHandle::InvalidHandle;
|
||||
}
|
||||
@@ -361,7 +361,7 @@ FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectHandle ID
|
||||
return FSmartObjectClaimHandle::InvalidHandle;
|
||||
}
|
||||
|
||||
return Claim(ID, FoundHandle);
|
||||
return Claim(Handle, FoundHandle);
|
||||
}
|
||||
|
||||
FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectRequestResult& RequestResult)
|
||||
@@ -374,7 +374,7 @@ FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectRequestRe
|
||||
return Claim(RequestResult.SmartObjectHandle, RequestResult.SlotHandle);
|
||||
}
|
||||
|
||||
FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectHandle ID, const FSmartObjectSlotHandle SlotHandle)
|
||||
FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectHandle Handle, const FSmartObjectSlotHandle SlotHandle)
|
||||
{
|
||||
// Slot might be unregistered by the time a result is used so it is possible that it can no longer be found
|
||||
if (FSmartObjectSlotClaimState* SlotState = RuntimeSlotStates.Find(SlotHandle))
|
||||
@@ -382,7 +382,7 @@ FSmartObjectClaimHandle USmartObjectSubsystem::Claim(const FSmartObjectHandle ID
|
||||
const FSmartObjectUserHandle User(NextFreeUserID++);
|
||||
const bool bClaimed = SlotState->Claim(User);
|
||||
|
||||
const FSmartObjectClaimHandle ClaimHandle(ID, SlotHandle, User);
|
||||
const FSmartObjectClaimHandle ClaimHandle(Handle, SlotHandle, User);
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Verbose, TEXT("Claim %s for handle %s"), bClaimed ? TEXT("SUCCEEDED") : TEXT("FAILED"), *LexToString(ClaimHandle));
|
||||
UE_CVLOG_LOCATION(bClaimed, this, LogSmartObject, Display, GetSlotLocation(ClaimHandle).GetValue(), 50.f, FColor::Yellow, TEXT("Claim"));
|
||||
|
||||
@@ -634,19 +634,25 @@ FSmartObjectSlotView USmartObjectSubsystem::GetSlotView(const FSmartObjectSlotHa
|
||||
|
||||
FSmartObjectSlotHandle USmartObjectSubsystem::FindSlot(const FSmartObjectRuntime& SmartObjectRuntime, const FSmartObjectRequestFilter& Filter) const
|
||||
{
|
||||
const FSmartObjectSlotHandle InvalidHandle;
|
||||
TArray<FSmartObjectSlotHandle> Handles;
|
||||
FindSlots(SmartObjectRuntime, Filter, Handles, ESmartObjectSlotSearchMode::FirstMatch);
|
||||
|
||||
return Handles.IsEmpty() ? FSmartObjectSlotHandle() : Handles.Top();
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::FindSlots(const FSmartObjectRuntime& SmartObjectRuntime, const FSmartObjectRequestFilter& Filter, TArray<FSmartObjectSlotHandle>& OutResults, const ESmartObjectSlotSearchMode SearchMode) const
|
||||
{
|
||||
const USmartObjectDefinition& Definition = SmartObjectRuntime.GetDefinition();
|
||||
const int32 NumSlotDefinitions = Definition.GetSlots().Num();
|
||||
if (!ensureMsgf(NumSlotDefinitions > 0, TEXT("Definition should contain slot definitions at this point")))
|
||||
{
|
||||
return InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
const UClass* RequiredDefinitionClass = *Filter.BehaviorDefinitionClass;
|
||||
if (!ensureMsgf(RequiredDefinitionClass != nullptr, TEXT("Filter needs to provide required behavior definition type")))
|
||||
{
|
||||
return InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate if any available slots
|
||||
@@ -667,7 +673,7 @@ FSmartObjectSlotHandle USmartObjectSubsystem::FindSlot(const FSmartObjectRuntime
|
||||
|
||||
if (bAnyFreeSlot == false)
|
||||
{
|
||||
return InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
const FGameplayTagContainer& ObjectTags = SmartObjectRuntime.GetTags();
|
||||
@@ -700,11 +706,13 @@ FSmartObjectSlotHandle USmartObjectSubsystem::FindSlot(const FSmartObjectRuntime
|
||||
continue;
|
||||
}
|
||||
|
||||
return SmartObjectRuntime.SlotHandles[i];
|
||||
OutResults.Add(SmartObjectRuntime.SlotHandles[i]);
|
||||
if (SearchMode == ESmartObjectSlotSearchMode::FirstMatch)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return InvalidHandle;
|
||||
}
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::AbortAll(FSmartObjectRuntime& SmartObjectRuntime)
|
||||
@@ -751,15 +759,15 @@ FSmartObjectRequestResult USmartObjectSubsystem::FindSmartObject(const FSmartObj
|
||||
|
||||
bool USmartObjectSubsystem::FindSmartObjects(const FSmartObjectRequest& Request, TArray<FSmartObjectRequestResult>& OutResults)
|
||||
{
|
||||
FSmartObjectRequestResult Result;
|
||||
const FSmartObjectRequestFilter& Filter = Request.Filter;
|
||||
SmartObjectOctree.FindFirstElementWithBoundsTest(Request.QueryBox,
|
||||
[&Result, &Filter, &OutResults, this](const FSmartObjectOctreeElement& Element)
|
||||
[&Filter, &OutResults, this](const FSmartObjectOctreeElement& Element)
|
||||
{
|
||||
Result = FindSlot(Element.SmartObjectHandle, Filter);
|
||||
if (Result.IsValid())
|
||||
TArray<FSmartObjectSlotHandle> SlotHandles;
|
||||
FindSlots(Element.SmartObjectHandle, Filter, SlotHandles);
|
||||
for (FSmartObjectSlotHandle SlotHandle: SlotHandles)
|
||||
{
|
||||
OutResults.Add(Result);
|
||||
OutResults.Emplace(Element.SmartObjectHandle, SlotHandle);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@@ -767,34 +775,37 @@ bool USmartObjectSubsystem::FindSmartObjects(const FSmartObjectRequest& Request,
|
||||
return (OutResults.Num() > 0);
|
||||
}
|
||||
|
||||
FSmartObjectRequestResult USmartObjectSubsystem::FindSlot(const FSmartObjectHandle ID, const FSmartObjectRequestFilter& Filter) const
|
||||
FSmartObjectRequestResult USmartObjectSubsystem::FindSlot(const FSmartObjectHandle Handle, const FSmartObjectRequestFilter& Filter) const
|
||||
{
|
||||
const FSmartObjectRequestResult InvalidResult;
|
||||
if (!ID.IsValid())
|
||||
TArray<FSmartObjectSlotHandle> SlotHandles;
|
||||
FindSlots(Handle, Filter, SlotHandles, ESmartObjectSlotSearchMode::FirstMatch);
|
||||
return SlotHandles.IsEmpty() ? FSmartObjectRequestResult() : FSmartObjectRequestResult(Handle, SlotHandles.Top());
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::FindSlots(const FSmartObjectHandle Handle,
|
||||
const FSmartObjectRequestFilter& Filter,
|
||||
TArray<FSmartObjectSlotHandle>& OutSlots,
|
||||
const ESmartObjectSlotSearchMode SearchMode) const
|
||||
{
|
||||
if (!Handle.IsValid())
|
||||
{
|
||||
UE_VLOG_UELOG(this, LogSmartObject, Error, TEXT("Requesting a valid use for an invalid smart object."));
|
||||
return InvalidResult;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Filter.Predicate && !Filter.Predicate(ID))
|
||||
if (Filter.Predicate && !Filter.Predicate(Handle))
|
||||
{
|
||||
return InvalidResult;
|
||||
return;
|
||||
}
|
||||
|
||||
const FSmartObjectRuntime* SmartObjectRuntime = RuntimeSmartObjects.Find(ID);
|
||||
const FSmartObjectRuntime* SmartObjectRuntime = RuntimeSmartObjects.Find(Handle);
|
||||
// Runtime data may no longer be available (removed from simulation)
|
||||
if (SmartObjectRuntime == nullptr)
|
||||
{
|
||||
return InvalidResult;
|
||||
return;
|
||||
}
|
||||
|
||||
const FSmartObjectSlotHandle FoundHandle = FindSlot(*SmartObjectRuntime, Filter);
|
||||
if (!FoundHandle.IsValid())
|
||||
{
|
||||
return InvalidResult;
|
||||
}
|
||||
|
||||
return FSmartObjectRequestResult(ID, FoundHandle);
|
||||
FindSlots(*SmartObjectRuntime, Filter, OutSlots, SearchMode);
|
||||
}
|
||||
|
||||
void USmartObjectSubsystem::RegisterCollectionInstances()
|
||||
@@ -911,7 +922,7 @@ void USmartObjectSubsystem::OnWorldBeginPlay(UWorld& World)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a runtime instance of that definition using that ID
|
||||
// Create a runtime instance of that definition using that handle
|
||||
if (Component != nullptr)
|
||||
{
|
||||
Component->SetRegisteredHandle(Entry.GetHandle());
|
||||
|
||||
@@ -132,6 +132,16 @@ enum class ESmartObjectCollectionRegistrationResult
|
||||
Succeeded,
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates how extensive a search for slots should be within a single SmartObject.
|
||||
*/
|
||||
UENUM()
|
||||
enum class ESmartObjectSlotSearchMode
|
||||
{
|
||||
FirstMatch,
|
||||
AllMatches
|
||||
};
|
||||
|
||||
/**
|
||||
* Subsystem that holds all registered smart object instances and offers the API for spatial queries and reservations.
|
||||
*/
|
||||
@@ -181,7 +191,19 @@ public:
|
||||
* Goes through all defined slots of a given smart object and finds the first one matching the filter.
|
||||
* @return Identifier of a valid slot to use. Call IsValid on it to check if the search was successful.
|
||||
*/
|
||||
UE_NODISCARD FSmartObjectRequestResult FindSlot(const FSmartObjectHandle ID, const FSmartObjectRequestFilter& Filter) const;
|
||||
UE_NODISCARD FSmartObjectRequestResult FindSlot(const FSmartObjectHandle Handle, const FSmartObjectRequestFilter& Filter) const;
|
||||
|
||||
/**
|
||||
* Returns slots of a given smart object matching the filter.
|
||||
* @param Handle Handle to the SmartObject
|
||||
* @param Filter Filter to apply on object and slots
|
||||
* @param OutSlots Available slots found that match the filter
|
||||
* @param SearchMode Indicates if the result must include all matching slots or only the first one matching
|
||||
*/
|
||||
void FindSlots(const FSmartObjectHandle Handle,
|
||||
const FSmartObjectRequestFilter& Filter,
|
||||
TArray<FSmartObjectSlotHandle>& OutSlots,
|
||||
ESmartObjectSlotSearchMode SearchMode = ESmartObjectSlotSearchMode::AllMatches) const;
|
||||
|
||||
/**
|
||||
* Claim smart object from a valid request result.
|
||||
@@ -191,7 +213,7 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "SmartObject")
|
||||
FSmartObjectClaimHandle Claim(const FSmartObjectRequestResult& RequestResult);
|
||||
|
||||
UE_NODISCARD FSmartObjectClaimHandle Claim(FSmartObjectHandle ID, const FSmartObjectRequestFilter& Filter = {});
|
||||
UE_NODISCARD FSmartObjectClaimHandle Claim(FSmartObjectHandle Handle, const FSmartObjectRequestFilter& Filter = {});
|
||||
|
||||
/**
|
||||
* Start using a claimed smart object slot.
|
||||
@@ -366,12 +388,13 @@ protected:
|
||||
|
||||
/**
|
||||
* Goes through all defined slots of smart object represented by SmartObjectRuntime
|
||||
* and finds the first one given actor can use.
|
||||
* and finds the first one matching the filter.
|
||||
* @return Handle to a valid slot to use. Call IsValid on it to check if the search was successful.
|
||||
*/
|
||||
FSmartObjectSlotHandle FindSlot(const FSmartObjectRuntime& SmartObjectRuntime, const FSmartObjectRequestFilter& Filter) const;
|
||||
void FindSlots(const FSmartObjectRuntime& SmartObjectRuntime, const FSmartObjectRequestFilter& Filter, TArray<FSmartObjectSlotHandle>& OutResults, ESmartObjectSlotSearchMode SearchMode) const;
|
||||
|
||||
FSmartObjectClaimHandle Claim(FSmartObjectHandle ID, FSmartObjectSlotHandle SlotHandle);
|
||||
FSmartObjectClaimHandle Claim(FSmartObjectHandle Handle, FSmartObjectSlotHandle SlotHandle);
|
||||
|
||||
static const USmartObjectBehaviorDefinition* GetBehaviorDefinition(const FSmartObjectRuntime& SmartObjectRuntime, const FSmartObjectClaimHandle& ClaimHandle, const TSubclassOf<USmartObjectBehaviorDefinition>& DefinitionClass);
|
||||
|
||||
@@ -384,10 +407,10 @@ protected:
|
||||
/** Make sure that all SmartObjectCollection actors from our associated world are registered. */
|
||||
void RegisterCollectionInstances();
|
||||
|
||||
void AddToSimulation(const FSmartObjectHandle ID, const USmartObjectDefinition& Definition, const FTransform& Transform, const FBox& Bounds);
|
||||
void AddToSimulation(const FSmartObjectHandle Handle, const USmartObjectDefinition& Definition, const FTransform& Transform, const FBox& Bounds);
|
||||
void AddToSimulation(const FSmartObjectCollectionEntry& Entry, const USmartObjectDefinition& Definition);
|
||||
void AddToSimulation(const USmartObjectComponent&);
|
||||
void RemoveFromSimulation(const FSmartObjectHandle ID);
|
||||
void RemoveFromSimulation(const FSmartObjectHandle Handle);
|
||||
void RemoveFromSimulation(const FSmartObjectCollectionEntry& Entry);
|
||||
void RemoveFromSimulation(const USmartObjectComponent& SmartObjectComponent);
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "AITestsCommon.h"
|
||||
#include "Engine/World.h"
|
||||
#include "EngineDefines.h"
|
||||
#include "MassExecutor.h"
|
||||
#include "MassEntitySubsystem.h"
|
||||
#include "SmartObjectSubsystem.h"
|
||||
@@ -34,15 +33,17 @@ struct FSmartObjectTestBase : FAITestBase
|
||||
|
||||
// Setup main definition
|
||||
USmartObjectDefinition* Definition = NewAutoDestroyObject<USmartObjectDefinition>();
|
||||
FSmartObjectSlotDefinition& Slot = Definition->DebugAddSlot();
|
||||
FSmartObjectSlotDefinition& FirstSlot = Definition->DebugAddSlot();
|
||||
FSmartObjectSlotDefinition& SecondSlot = Definition->DebugAddSlot();
|
||||
|
||||
// Add some test behavior definition
|
||||
Slot.BehaviorDefinitions.Add(NewAutoDestroyObject<USmartObjectTestBehaviorDefinition>());
|
||||
FirstSlot.BehaviorDefinitions.Add(NewAutoDestroyObject<USmartObjectTestBehaviorDefinition>());
|
||||
SecondSlot.BehaviorDefinitions.Add(NewAutoDestroyObject<USmartObjectTestBehaviorDefinition>());
|
||||
|
||||
// Add some test slot definition data
|
||||
FSmartObjectSlotTestDefinitionData DefinitionData;
|
||||
DefinitionData.SomeSharedFloat = 123.456f;
|
||||
Slot.Data.Add(FInstancedStruct::Make(DefinitionData));
|
||||
FirstSlot.Data.Add(FInstancedStruct::Make(DefinitionData));
|
||||
|
||||
// Setup filter
|
||||
TestFilter.BehaviorDefinitionClass = USmartObjectTestBehaviorDefinition::StaticClass();
|
||||
@@ -118,6 +119,21 @@ struct FFindSmartObject : FSmartObjectTestBase
|
||||
};
|
||||
IMPLEMENT_AI_INSTANT_TEST(FFindSmartObject, "System.AI.SmartObjects.Find");
|
||||
|
||||
struct FFindMultipleSmartObjects : FSmartObjectTestBase
|
||||
{
|
||||
virtual bool InstantTest() override
|
||||
{
|
||||
const FSmartObjectRequest Request(FBox(EForceInit::ForceInit).ExpandBy(FVector(HALF_WORLD_MAX), FVector(HALF_WORLD_MAX)), TestFilter);
|
||||
|
||||
// Find objects
|
||||
TArray<FSmartObjectRequestResult> Results;
|
||||
Subsystem->FindSmartObjects(Request, Results);
|
||||
AITEST_EQUAL("Results is expected to contain 4 elements", Results.Num(), 4);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_AI_INSTANT_TEST(FFindMultipleSmartObjects, "System.AI.SmartObjects.Find multiple");
|
||||
|
||||
struct FClaimAndReleaseSmartObject : FSmartObjectTestBase
|
||||
{
|
||||
virtual bool InstantTest() override
|
||||
|
||||
Reference in New Issue
Block a user