You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unreal Engine中动态创建TArray并让垃圾回收追踪的技术问询

问题

我有一个继承自UObject的类,其中包含一个标记为UPROPERTY的TArray:

UCLASS(BlueprintType, Blueprintable)
class SOME_API UClassA : public UObject
{
    GENERATED_BODY()

public:    
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TArray<UObject*> Objects;    
};

尝试用NewObject动态创建TArray并赋值给Objects时触发编译错误:

UClassA* ObjA = NewObject<UClassA>();
TArray<UObject*>* NewArray = NewObject<TArray<UObject*>>(); // 编译错误处
ObjA->Objects = *NewArray;

错误信息:

Error C2039 : 'StaticClass': is not a member of 'TArray<UObject *,FDefaultAllocator>'
Reference C2039 : see declaration of 'TArray<UObject *,FDefaultAllocator>'
Reference C2039 : see reference to function template instantiation 'T *NewObject<TArray<UObject *,FDefaultAllocator>>(UObject *)' being compiled
          with
          [
              T=TArray<UObject *,FDefaultAllocator>
          ]

我的疑问:

  1. 能否用C++的new来创建TArray?这样做是否可行?
  2. 垃圾回收器会追踪这个新创建的数组,而非构造函数中创建的Objects数组吗?

补充:我打算动态创建TArray及其包含的UObject对象,且希望UE垃圾回收器能识别它们,这将是它们唯一的存储位置。


解答

为什么NewObject创建TArray会报错?

NewObject是Unreal Engine专门用来创建UObject派生类实例的函数,它依赖类的StaticClass()方法获取UClass信息。而TArray是UE的容器值类型,并非UObject的子类,没有StaticClass()方法,因此无法用NewObject创建。

能否用C++的new创建TArray?

可以,但完全没必要,还会引入额外问题:

  • TArray是轻量级值类型,设计为直接在栈上或作为对象成员使用,用new会把它分配在堆上,需要手动调用delete释放,否则会造成内存泄漏。
  • 即使你用new创建了TArray,赋值给ObjA->Objects时会执行值拷贝,原堆上的TArray如果没有其他指针引用,就会变成无人管理的内存垃圾。
  • UE的GC不会追踪堆上的TArray本身(因为它不是UObject),但数组中存储的UObject如果被ObjA->Objects(UPROPERTY标记)持有,只要ObjA处于GC追踪链中,这些UObject会被正常管理。

正确实现需求的方式

无需额外创建TArray实例,直接操作ObjA->Objects即可——它本身就是一个初始化完成的TArray,你只需要往里面添加动态创建的UObject:

UClassA* ObjA = NewObject<UClassA>();

// 动态创建UObject并加入数组,将ObjA作为Outer确保GC追踪
UObject* NewObj1 = NewObject<UObject>(ObjA);
ObjA->Objects.Add(NewObj1);

UObject* NewObj2 = NewObject<UObject>(ObjA);
ObjA->Objects.Add(NewObj2);

如果需要替换整个数组,直接用栈上的临时TArray赋值即可:

UClassA* ObjA = NewObject<UClassA>();

TArray<UObject*> TempArray;
TempArray.Add(NewObject<UObject>(ObjA));
TempArray.Add(NewObject<UObject>(ObjA));

// 直接赋值,原Objects数组的内容会被自动清理
ObjA->Objects = TempArray;

关键注意点

  • 动态创建UObject时,必须指定一个有效的Outer(比如上面的ObjA),或者将其加入到UPROPERTY标记的容器中,这样UE的GC才能识别并管理这些对象。
  • ObjA本身需要被GC追踪(比如作为其他UObject的成员、被蓝图引用,或者加入到GetWorld()->GetGameInstance()等全局对象的引用链中),否则ObjA和它的Objects数组中的对象都会被GC回收。

内容的提问来源于stack exchange,提问作者Unicorn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:46:36