通过虚幻控件Slate了解虚幻GC(Garbage Collection, GC)的垃圾回收系统

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

Unreal Engine 的垃圾回收(Garbage Collection, GC)机制主要用于管理 UObject 及其派生类的生命周期,包括 UMG 控件(如 UWidget)。其核心是 基于根集(Root Set)的标记-清扫(Mark and Sweep)算法。以下是详细流程及代码示例:


提示:以下是本篇文章正文内容,下面案例可供参考

一、GC 的核心机制

1.1 根集(Root Set)

根集是 GC 的起点,包含所有不会被自动回收的对象,例如:

全局对象(GameInstance, World, PlayerController)
当前活跃的 Actor 和组件
通过 AddToRoot() 显式标记的对象

1.2 标记阶段(Marking)

GC 从根集出发,递归遍历所有被引用的 UObject,标记为“活跃”。

1.3 清扫阶段(Sweeping)

未被标记的对象会被销毁,内存被回收。

二、控件生命周期管理

UMG 控件(如 UUserWidget)继承自 UObject,生命周期由 GC 管理,其存活与否取决于是否被根集引用。
关键流程:

2.1 控件创建

件通常通过 CreateWidget 创建,此时未被根集引用,需手动添加到父容器或视口:

UUserWidget* MyWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);

2.2 添加到视口(成为根集)

当控件被添加到视口时,会被 Viewport 引用,从而成为根集的一部分:

MyWidget->AddToViewport(); // 控件被根集引用,GC 不会回收

2.3 移除视口(断开根集)

调用 RemoveFromParent() 后,控件不再被视口引用。若没有其他 UPROPERTY 或根引用,将在下次 GC 时被回收:

MyWidget->RemoveFromParent(); // 断开与根集的连接

2.4 显式销毁

可手动调用 ConditionalBeginDestroy() 触发销毁逻辑:

MyWidget->ConditionalBeginDestroy(); // 立即标记为待销毁

三、代码示例与流程分析

3.1 控件创建与添加

// 创建控件(未被根集引用)
UUserWidget* MyWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);

// 添加到视口(成为根集一部分)
MyWidget->AddToViewport();

此时 MyWidget 被 Viewport 引用,GC 不会回收。

3.2 控件移除与 GC 回收

// 从视口移除(断开根集引用)
MyWidget->RemoveFromParent();

// 触发 GC(通常在下一帧自动执行)
GetWorld()->ForceGarbageCollection(true);

移除后若没有其他引用,MyWidget 会被 GC 回收。

3.3防止误回收:使用 UPROPERTY

通过 UPROPERTY 声明强引用:

UPROPERTY()
UUserWidget* MyWidget; // 强引用,阻止 GC 回收

void CreateWidget()
{
    MyWidget = CreateWidget<UUserWidget>(...);
    MyWidget->AddToViewport();
}

当 MyWidget 被移除视口时,由于 UPROPERTY 存在,仍不会被 GC 回收,需手动置空:

MyWidget->RemoveFromParent();
MyWidget = nullptr; // 允许 GC 回收

四、GC触发时机

自动触发:每 60 秒或内存压力较大时。
手动触发:通过 GetWorld()->ForceGarbageCollection(true);。

五、调试与注意事项

5.1 检查引用链

使用 GUObjectArray 或控制台命令 OBJ REFS 查看对象引用关系。

5.2 弱引用

使用 TWeakObjectPtr 避免强引用导致内存泄漏:

TWeakObjectPtr<UUserWidget> WeakWidgetPtr = MyWidget;

5.3 异步加载

异步加载的控件需确保在销毁前取消加载任务,避免野指针。

总结

Unreal 的 GC 通过根集引用链管理控件生命周期,关键点在于:

控件添加到视口时被根集保护。
移除视口后若无其他引用,GC 自动回收。
使用 UPROPERTY 或 TWeakObjectPtr 精确控制引用关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值