如何在UE C++中获取特定类的实例
最编程
2024-01-08 15:32:02
...
在 Unreal Engine 的蓝图中,可以通过 Get All Actors of Class
来获取指定类的所有实例:
在 C++ 中应该如何获取呢?
AActor 实例数组
双击蓝图中的节点,跳转到工程项目的下面方法中:
UFUNCTION(BlueprintCallable, Category="Actor", meta=(WorldContext="WorldContextObject", DeterminesOutputType="ActorClass", DynamicOutputParam="OutActors"))
static void GetAllActorsOfClass(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass, TArray<AActor*>& OutActors);
所以我们可以通过下面的方法来获取到所有 AActor 实例的数组:
#include "Kismet/GameplayStatics.h"
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), FoundActors);
AActor 子类实例数组
方法一:UGameplayStatics
在获取 C++ 定义的 AActor 子类时,将 GameplayStatics::GetAllActorsOfClas
方法中的参数修改为子类的类型即可:
#include "Kismet/GameplayStatics.h"
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), YourClass::StaticClass(), FoundActors);
获取蓝图定义的 AActor 子类时,需要定义一个方法参数(或者类型属性) TSubclassOf<AActor> ClassToFind
,公开给蓝图使用,并在蓝图中进行设置。
#include "Kismet/GameplayStatics.h"
// Needs to be populated somehow (e.g. by exposing to blueprints as uproperty and setting it there
TSubclassOf<AActor> ClassToFind;
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ClassToFind, FoundActors);
注意,在 GetAllActorsOfClass 方法中,用于接收查询结果的数组类型依然为TArray<AActor*>
,而不是对应的子类数组类型。那如何将TArray<AActor*>
转换为子类数组呢?没有简单的方法,还需要 for 循环进行转换。
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASomeActor::StaticClass(), FoundActors);
TArray<YourClass*> YourClassActors;
for (AActor* UncastedActor : FoundActors) {
YourClassActors.Add(Cast<YourClass>(UncastedActor));
}
方法二:TActorIterator
另外还可以通过迭代器(TActorIterator)来获取 UWorld 中指定类型的实例:
#include "EngineUtils.h"
TArray<YourClass*> YourClassActors;
for (TActorIterator<YourClass> It(World); It; ++It)
{
YourClassActors.Add(*It);
}
写成更通用的模板方法为:
#include "EngineUtils.h"
template <typename ActorClass>
void TGetAllActorsOfClass(UWorld* World, TArray<ActorClass*>& OutActors)
{
OutActors.Reset();
if (World)
{
for (TActorIterator<ActorClass> It(World); It; ++It)
{
OutActors.Add(*It);
}
}
}
示例如下:
void Test(UWorld* World)
{
TArray<APawn*> MyPawns;
TGetAllActorsOfClass(World, MyPawns);
TArray<ACharacter*> MyCharacters;
TGetAllActorsOfClass(World, MyCharacters);
/*
Won't compile because UObject not a sub-class of AActor.
TArray<UObject*> MyObjects;
TGetAllActorsOfClass(World, MyObjects);
*/
}
注意:
在使用TActorIterator<ActorClass> It(World)
时,需要包含头文件 #include "EngineUtils.h"
,否则会报错 无法从“UWorld *”转换为“int”
。
UObjects 的所有实例
如果需要获取某个 UObjects 类的所有实例(不仅仅是 Actors),可以通过下面的方法:
for (TObjectIterator<UserClassObject> It; It; ++It)
{
UMyObject* CurrentObject = *It;
UE_LOG(LogTemp, Log, TEXT("Found UObject named:%s"), *CurrentObject.GetName());
}
另外也可以使用AssetRegistryModule
:
template<typename T>
void GetObjectsOfClass(TArray<T*>& OutArray)
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
TArray<FAssetData> AssetData;
AssetRegistryModule.Get().GetAssetsByClass(T::StaticClass()->GetFName(), AssetData);
for (int i = 0; i < AssetData.Num(); i++) {
T* Object = Cast<T>(AssetData[i].GetAsset());
OutArray.Add(Object);
}
}
示例如下:
TArray<UAnimSequence*> AnimSequences;
GetObjectsOfClass(AnimSequences);
参考
- “Get All Actors Of Class” in C++
- How to get subclass array reference from UGameplaystatistics::GetAllActorsOfClass
推荐阅读