UE垃圾回收-纳入被自动GC机制管理的条件



一、UObject成员变量必须用 UPROPERTY 修饰

如果 UObject 类型的成员变量未被标记为 UPROPERTY,GC 将无法识别其引用,导致对象可能被错误回收。

// MyClass.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyClass.generated.h"

UCLASS()
class UMyClass : public UObject
{
    GENERATED_BODY()

public:
    // 未使用 UPROPERTY 修饰 → 可能被GC回收
    UObject* UnreferencedObject;

    // 使用 UPROPERTY 修饰 → GC会追踪引用
    UPROPERTY()
    TObjectPtr<UObject> ReferencedObject;
};

验证方式

  • UnreferencedObject 未被其他引用持有,其指向的对象可能在GC时被回收。
  • ReferencedObject 会始终被GC追踪,只要 UMyClass 实例存活。

二、实现 AddReferencedObjects 接口

当需要手动管理非 UPROPERTY 成员变量或复杂引用关系时,可重写 AddReferencedObjects 方法。

// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 非 UPROPERTY 成员变量
    UObject* OtherObject;

protected:
    // 重写 AddReferencedObjects 手动添加引用
    virtual void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector) override
    {
        Collector.AddReferencedObject(OtherObject);
        Super::AddReferencedObjects(InThis, Collector);
    }
};

关键点

  • 即使 OtherObject 未被 UPROPERTY 修饰,通过 AddReferencedObjects 手动添加引用,GC 会将其标记为“被引用”。
  • 适用于动态管理对象引用的场景(如对象池、缓存)。

三、结构体继承 FGCObject 并实现 AddReferencedObjects

如果结构体(struct)包含 UObject 指针且需要被GC保护,必须继承 FGCObject 并手动添加引用。

// MyStruct.h
#pragma once
#include "UObject/GCObject.h"

// 自定义结构体继承 FGCObject
class FMyStruct : public FGCObject
{
public:
    // 结构体中持有 UObject 指针
    UObject* MyObject;

    // 必须重写 AddReferencedObjects
    virtual void AddReferencedObjects(FReferenceCollector& Collector) override
    {
        Collector.AddReferencedObject(MyObject);
    }
};

// 使用示例
void ExampleUsage()
{
    FMyStruct MyStructInstance;
    MyStructInstance.MyObject = NewObject<UObject>();
    // 只要 MyStructInstance 存在,MyObject 不会被GC回收
}

关键点

  • 适用场景:非 USTRUCT 的自定义原生结构体(如工具类、独立于UObject系统的模块)。
  • 比 USTRUCT:若结构体是 USTRUCT,且其成员用 UPROPERTY 标记,则无需继承 FGCObject,例如:
USTRUCT()
struct FMySafeStruct
{
    GENERATED_BODY()

    UPROPERTY()
    TObjectPtr<UObject> SafeObject; // 自动被GC追踪
};

总结

场景方法代码示例
UObject成员变量引用使用 UPROPERTY 标记UPROPERTY() TObjectPtr Ref;
手动管理复杂引用重写 AddReferencedObjectsvirtual void AddReferencedObjects(…) { Collector.AddRef(Obj); }
结构体保护UObject引用继承 FGCObject 并实现接口struct FMyStruct : FGCObject { … }

注意事项:

  1. USTRUCT 的特殊性
    • 若结构体是 USTRUCT,其内部 UObject 指针必须用 UPROPERTY 修饰,否则无法自动追踪引用。
    • 原生结构体(非 USTRUCT)必须通过 FGCObject 手动管理引用
  2. 性能影响
    • AddReferencedObjects 在GC时会被频繁调用,确保代码高效,避免复杂逻辑。
  3. 循环引用
    • 即使通过上述方法保护对象,若对象间形成循环引用(如A引用B,B引用A),需手动打破循环(如使用弱指针 TWeakObjectPtr)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值