CreateDefaultSubobject
1. CreateDefaultSubobject
的核心作用
CreateDefaultSubobject
是 UE 中用于在 构造函数 中创建并注册子对象(Subobject)的核心函数,通常用于以下场景:
- 创建组件(如
UActorComponent
、USceneComponent
等),作为 Actor 的一部分。 - 定义默认子对象(如默认的网格、碰撞体等),这些子对象在 Actor 实例化时会自动生成。
- 确保子对象被正确序列化(保存到蓝图或关卡中)和网络复制。
基本语法
template<class T>
T* CreateDefaultSubobject<FName SubobjectName, bool bTransient = false>(
FName SubobjectName,
bool bTransient = false
);
- 模板参数
T
:要创建的子对象类型(如USkeletalMeshComponent
)。 - 参数
SubobjectName
:子对象的唯一名称(需通过FName
指定)。 - 参数
bTransient
:若为true
,子对象不会被序列化(仅在运行时存在)。
2. 使用场景与示例
(1) 在 Actor 中创建组件
// 在自定义 Actor 的构造函数中创建组件
AMyActor::AMyActor()
{
// 创建根组件(必须)
// 当未显式设置根组件时,第一个创建的 USceneComponent 及其派生类(如 UStaticMeshComponent)会被自动设置为根组件
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
// 创建网格组件并附加到根组件
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
}
(2) 定义默认子对象
// 在 UObject 派生类中创建默认子对象
UMyObject::UMyObject()
{
// 创建一个默认的子对象(如配置类)
Config = CreateDefaultSubobject<UMyConfig>(TEXT("Config"));
}
3. 注意事项
(1) 只能在构造函数中使用
CreateDefaultSubobject
只能在类的构造函数中调用,如果在其他函数(如BeginPlay
)中使用,会导致编译错误。- 错误示例:
void AMyActor::BeginPlay() { // 编译错误:不能在构造函数外使用 CreateDefaultSubobject MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent")); }
(2) 子对象名称必须唯一
- 同一父对象内的子对象名称(
SubobjectName
)必须唯一,否则会导致断言错误。 - 错误示例:
AMyActor::AMyActor() { // 两个同名的子对象会触发崩溃 Comp1 = CreateDefaultSubobject<USceneComponent>(TEXT("Component")); Comp2 = CreateDefaultSubobject<USceneComponent>(TEXT("Component")); }
(3) 子对象的生命周期
- 子对象随父对象一起创建和销毁,无法单独释放。
- 子对象默认会被序列化(保存到蓝图/关卡),若不需要序列化,设置
bTransient = true
。
(4) 模板类型必须匹配
-
模板类型必须与返回值类型一致,否则会编译失败。
-
错误示例:
// 错误:类型不匹配 UStaticMeshComponent* Mesh = CreateDefaultSubobject<USceneComponent>(TEXT("Mesh"));
4. 相关函数对比:CreateDefaultSubobject
vs NewObject
特性 | CreateDefaultSubobject | NewObject |
---|---|---|
调用场景 | 只能在构造函数中使用 | 可在任何地方(构造函数、运行时函数)使用 |
生命周期 | 随父对象自动销毁 | 可手动管理,或依赖 UE 垃圾回收(GC) |
序列化 | 默认序列化(除非bTransient=true ) |
默认不序列化(除非手动标记) |
用途 | 定义默认子对象(组件、配置等) | 运行时动态创建对象(如生成实例、临时对象) |
示例场景 | Actor 的默认组件 | 动态生成一个特效对象 |
NewObject
示例
// 在运行时动态创建一个对象
UMyObject* DynamicObj = NewObject<UMyObject>(this, TEXT("DynamicObject"));