TUniqueFunction
TUniqueFunction()
在虚幻引擎(Unreal Engine)中,TUniqueFunction 是一种模板类,用于封装可调用对象(如函数、lambda表达式、仿函数等),并保证这些可调用对象具有唯一所有权。这意味着 TUniqueFunction 类似于 std::unique_ptr,它确保所管理的对象只能由一个 TUniqueFunction 实例拥有。
TUniqueFunction 主要用来处理线程安全任务或延迟执行操作,它的特点是只允许一个实例拥有其封装的可调用对象,防止多个地方同时修改或调用同一个对象导致不安全的行为。它通常用于需要移动语义的场景,不允许拷贝操作。
以下是 TUniqueFunction 的一些关键特点和使用示例:
关键特点
- 唯一所有权:每个
TUniqueFunction实例独占对其内部可调用对象的所有权,不支持复制,只支持移动。 - 类型安全:它是一个模板类,允许存储任何符合签名的可调用对象。
- 线程安全:适用于多线程环境下的延迟执行操作。
示例代码
#include "CoreMinimal.h"
#include <iostream>
// 一个简单的函数,符合 TUniqueFunction 的签名
void SimpleFunction()
{
std::cout << "Hello, Unreal!" << std::endl;
}
void ExampleUsage()
{
// 使用 lambda 表达式创建一个 TUniqueFunction
TUniqueFunction<void()> UniqueFunc = []() {
std::cout << "Lambda function called" << std::endl;
};
// 调用 TUniqueFunction
UniqueFunc();
// 将一个普通函数分配给 TUniqueFunction
TUniqueFunction<void()> UniqueFunc2 = SimpleFunction;
// 调用 TUniqueFunction
UniqueFunc2();
// TUniqueFunction 不能被拷贝,但可以被移动
TUniqueFunction<void()> MovedFunc = MoveTemp(UniqueFunc2);
// 调用移动后的 TUniqueFunction
MovedFunc();
}
int main()
{
ExampleUsage();
return 0;
}
项目中的代码示例
TUniqueFunction<TArray<AActor*>(const FString&, EFurnitureType, bool, bool)> spawnFunc = [&](const FString& furnitureName, EFurnitureType furnitureType, bool bForceCreate, bool bCreateOne)
{
TArray<AActor*> furnitures;
FString FurnitureName = furnitureName;
if (FurnitureName.IsEmpty())
FurnitureName = enumPtr->GetNameStringByIndex(furnitureType);
if (!Context->FurnitureInfoMap.Contains(FurnitureName) && !FurnitureChildMap.Contains(FurnitureName))
return furnitures;
if (!Context->FurnitureMap.Contains(FurnitureName))
Context->FurnitureMap.Add(FurnitureName, {});
if (!bForceCreate && Context->FurnitureMap[FurnitureName].Num() > 0) {
return Context->FurnitureMap[FurnitureName];
}
TUniqueFunction<TArray<AActor*>(const FString&, bool)> SpawnFurniture = [=](const FString& furnitureType, bool bList)
{
TArray<AActor*> actors;
if (Context->FurnitureInfoMap.Contains(furnitureType)) {
TArray<FRoomFurniture>& paramFurnitures = Context->FurnitureInfoMap[furnitureType];
for (FRoomFurniture& furniture : paramFurnitures) {
TArray<FName> tags;
tags.Add(*("type:" + furniture.Type));
tags.Add(*("roomName:" + roomName));
if (furniture.Type.Contains("Door") || furniture.Type.Contains("Window")) {
tags.Add("unSelect:true");
}
AActor* actor = nullptr;
//#if WITH_EDITOR || PLATFORM_WINDOWS
if (furniture.TestActor != nullptr) {
actor = furniture.TestActor;
furniture.TestClass = furniture.TestActor->GetClass();
furniture.TestActor = nullptr;
}
if (actor == nullptr && furniture.TestClass != nullptr) {
actor = World->SpawnActor<AActor>(furniture.TestClass);
if (actor->IsA<AStaticMeshActor>()) {
AStaticMeshActor* staticMeshActor = Cast<AStaticMeshActor>(actor);
staticMeshActor->SetMobility(EComponentMobility::Movable);
}
actor->Tags = tags;
MaskObject(actor, TEXT("soft"));
AddTag(actor, "id", furniture.ID);
}
if (actor == nullptr) {
actor = SpawnActor(furniture.ID, FVector(0, 0, 0), FRotator(0, 0, 0), "", tags);
}
if (actor != nullptr) {
actors.Add(actor);
Context->FurnitureTypeMap.Add(actor, furniture.Type);
Context->FurnitureInfoMap[furnitureType][0].ActorList.Add(actor);
}
if (!bList)
break;
}
}
if (!actors.IsEmpty()) {
if (!Context->FurnitureMap.Contains(furnitureType))
Context->FurnitureMap.Add(furnitureType, {});
Context->FurnitureMap[furnitureType].Append(actors);
}
return actors;
};
if (FurnitureChildMap.Contains(FurnitureName)) {
for (const FString& type : FurnitureChildMap[FurnitureName]) {
furnitures.Append(SpawnFurniture(type, !bCreateOne));
if (!furnitures.IsEmpty() && !bCreateOne)
break;
}
}
else {
furnitures.Append(SpawnFurniture(FurnitureName, !bCreateOne));
}
return furnitures;
};
Context->SpawnFurnitures->SpawnFunc = &spawnFunc;
注意事项
TUniqueFunction不能被复制,只能通过移动操作来转移所有权。这与std::unique_ptr类似。- 它适用于需要确保单一所有权的场景,例如异步任务或延迟执行的函数调用。
- 在多线程环境中使用
TUniqueFunction时,确保线程安全性是很重要的。
通过使用 TUniqueFunction,开发者可以更方便地管理可调用对象的生命周期和所有权,同时确保代码的安全性和简洁性。

浙公网安备 33010602011771号