当前位置: 首页 > news >正文

UE_C++ —— UObject Instance Creation

目录

一,UObject Instance Creation

NewObject

NewNamedObject

ConstructObject

Object Flags

二,Unreal Object Handling

Automatic Property Initialization

Automatic Updating of References

Serialization

Updating of Property Values

Editor Integration

Run-Time Type Information and Casting

Garbage Collection

Network Replication


一,UObject Instance Creation

        创建对象新实例的方法;

NewObject

        NewObject() 是最简单的UObject工厂方法;它接受一个可选的外部对象和类,并用自动生成的名称创建一个新实例;

template< class T >
T* NewObject
(
    UObject* Outer = (UObject*)GetTransientPackage(),
    UClass* Class = T::StaticClass()
)
  • Outer,可选,一个待创建对象的外部 UObject
  • Class,可选,一个待创建对象类的 UClass
  • 返回值,指向生成实例(指定类)指针;
NewNamedObject

        NewNamedObject() 是在 NewObject() 上扩展,通过为新实例指定一个名称、对象标记、一个要指定为参数的模板对象;

template< class TClass >
TClass* NewNamedObject
(
    UObject* Outer,
    FName Name,
    EObjectFlags Flags = RF_NoFlags,
    UObject const* Template = NULL
)
  • Outer,一个待创建对象的外部 UObject
  • Name,一个为新对象的 名称 的 FName
  • Flags,可选,描述新对象的 FObjectFlags 枚举值;
  • Template,可选,创建新对象时用作模板的 UObject
  • 返回值,指向生成实例(指定类)指针;
ConstructObject

        为获得完全的灵活性,可以使用 ConstructObject() 函数来创建 UObjects 的新实例;此函数调用 StaticConstructObject() ,它分配对象,执行 ClassConstructor ,并执行任何初始化,如加载配置属性,加载本地化属性和实例化组件;

template< class T >
T* ConstructObject
(
	UClass* Class,
	UObject* Outer = (UObject*)GetTransientPackage(),
	FName Name = NAME_None,
	EObjectFlags SetFlags = RF_NoFlags,
	UObject const* Template = NULL,
	bool bCopyTransientsFromClassDefaults = false,
	struct FObjectInstancingGraph* InstanceGraph = NULL
)
  • Class,一个待创建对象类的 UClass
  • Outer,可选,一个待创建对象的外部 UObject
  • Name,可选,一个为新对象的 名称 的 FName
  • SetFlags,可选,描述新对象的 FObjectFlags 枚举值;
  • Template,可选,创建新对象时用作模板的 UObject
  • bCopyTransientsFromClassDefaults,可选,
  • FObjectInstancingGraph,可选,一个 布尔值 ,决定是否从类默认对象(而不是传入的原型指针)复制瞬态属性;如果 true ,使用类默认对象的瞬态;
  • 返回值,指向生成实例(指定类)指针;
Object Flags

        EObjectFlags 枚举用于快速而简洁地描述对象;有各种的标志来描述对象的类型、垃圾收集如何处理它、对象在其生命周期中所处的阶段等等;还有特殊的全掩码或无掩码和预定义的标记组;

Object Type
FlagValueDescription
RF_Public0x00000001对象在包含它的包外部是可见的;
RF_Standalone0x00000002即使没有被任何东西引用,对象也会被保留以供编辑;
RF_Native0x00000004对象是本地对象,仅用于 UClass 对象;
RF_Transactional0x00000008对象是事务对象;
RF_ClassDefaultObject0x00000010对象是其类的默认对象,即该类的新实例在创建时使用的默认模板;
RF_ArchetypeObject0x00000020对象是另一个对象的模板。它被视为一个类默认对象;
RF_Transient0x00000040对象不保存到磁盘;
Garbage Collection
FlagValueDescription
RF_RootSet0x00000080即使对象没有被任何东西引用,也不被垃圾回收;
RF_IsLazyReferenced0x00000100对象由一个延迟指针引用,删除时需要额外的清理;
RF_Unreachable0x00000400对象图表上不能访问该对象;
RF_TagGarbageTemp0x00000400对象被标记为供使用垃圾回收的各种实用程序所使用;此标记不由垃圾回收器本身解释;
Object Lifetime
FlagValueDescription
RF_NeedLoad0x00000800对象需要加载;
RF_AsyncLoading0x00001000对象是异步加载的;
RF_NeedPostLoad0x00002000对象需要后加载;
RF_NeedPostLoadSubobjects0x00004000对象仍然需要实例化子对象并修复序列化的组件引用;
RF_PendingKill0x00008000对象正在等待销毁;基于游戏目的将对象标记为无效,但仍然是有效的对象;
RF_BeginDestroyed0x00010000对象已经调用了 BeginDestroy()
RF_FinishDestroyed0x00020000对象已经调用了 FinishDestroy() ;
Special Masks
FlagValueDescription
RF_AllFlags0x0003ffff对象具有所有标记,主要用于错误检查;
RF_NoFlags0x00000000对象不具有标记,用于避免类型转换;
Predefined Groups
FlagValueDescription
RF_LoadRF_Public | RF_Standalone | RF_Native | RF_Transactional | RF_ClassDefaultObject | RF_ArchetypeObject从虚幻文件加载的标记;
RF_PropagateToSubobjectsRF_Public | RF_ArchetypeObject | RF_Transactional子对象从其超对象继承的标记;

二,Unreal Object Handling

        使用适当的宏标记类、属性和函数可以将它们转变为UClassesUPropertiesUFunctions;这让虚幻引擎能够访问它们,从而允许实现一些后台处理功能;

Automatic Property Initialization

        在调用构造函数之前,UObject在初始化时自动归零;这针对整个类发生,UProperties和类似的原生成员;成员随后可以使用类构造函数中的自定义值进行初始化;

Automatic Updating of References

       AActorUActorComponent被销毁或从运行中删除时,对反射系统可见的对它的所有引用(UProperty指针和引擎容器类中存储的指针,如TArray)都将自动清空;这样的好处是防止悬挂指针持久存在并导致后续问题,但也意味着如果其他某段代码将AActorUActorComponent指针销毁,这些指针也会变为空;最终的好处是空检查更可靠,因为会检测标准情况空指针和非空指针指向删除内存的情况;

        必须理解的是,这种功能仅适用于标记了UPROPERTY或存储在虚幻引擎容器类中的UActorComponentAActor引用;存储在原始指针中的Object引用对于虚幻引擎将为未知,并且不会自动清空,也不会妨碍垃圾回收;注意,这不意味着所有UObject*变量都必须是UProperties;如需要的Object指针不是UProperty,请考虑使用TWeakObjectPtr;这是"弱"指针,意味着不会妨碍垃圾回收,但可以查询有效性,然后再接受访问,并且它所指向的Object要被销毁时,它将被设置为空;

        另一种被引用UObject UProperty自动清空的情况是对编辑器中的资源使用"强制删除(Force Delete)";因此,作用于属于资源的UObject的所有代码都必须处理这些变为空的指针;

Serialization

        当UObject被序列化时,所有UProperty值都将被自动写入或读取,除非显式标记为"瞬时"或无法从后构造函数默认值进行更改;如,可以在关卡中放入AEnemy实例,将其"Health"设置为500,保存并成功地重新加载,而不必在UClass定义之外编写一行代码;

        当添加或删除UProperties时,系统会无缝处理加载预先存在的内容;新属性从新的CDO复制默认值;删除的属性将会被静默忽略;

        如需要自定义行为,则可以覆盖UObject::Serialize函数;这对于检测数据错误,检查版本号或执行自动转换或更新(如果数据格式有所更改)十分有用;

Updating of Property Values

        当UClass的 类默认对象(CDO)更改,引擎将尝试在加载类的所有实例时对这些实例应用这些更改;对于给定Object实例,如更新的变量值与旧CDO中的值相匹配,则将更新为它在新CDO中保存的值;如变量包含任何其他值,系统会假设这个值是故意设置的,这些更改将会被保留;

        如,假设在一个关卡中放置了多个 AEnemy Object并保存,然后将 AEnemy 构造函数中的默认Health值设置为100;再假设将Enemy_3的Health值设置为500,因为它们特别难对付;现在,假设改变主意,将Health的默认值增加到150;下次加载关卡时,虚幻意识到更改了CDO,并将使用旧默认Health值(100)的所有AEnemy实例更新为使用Health值150。Enemy_3的Health将保持在500,因为它不使用旧的默认值;

Editor Integration

        编辑器理解UObjectUProperties,编辑器可以自动公开这些值以供编辑,而不必编写特殊代码;可以选择在蓝图视觉脚本系统中融入集成,也有许多选项可以控制变量和函数的可访问性和公开;

Run-Time Type Information and Casting

        由于UObject是虚幻引擎反射系统的一部分,它们始终知道它们是哪些UClass,并可以在运行时做出有关类型的决定和类型转换;

        在原生代码中,每个UObject类都将自定义Super类型定义设置为其父类,从而可以轻松控制覆盖行为;

class AEnemy : public ACharacter
{
	virtual void Speak()
	{
		Say("Time to fight!");
	}
};

class AMegaBoss : public AEnemy
{
	virtual void Speak()
	{
		Say("Powering up! ");
		Super::Speak();
	}
};
//调用Speak将会让MegaBoss说"Powering up!Time to fight!"

        此外,可以使用模板化Cast函数或者查询(如Object是使用IsA的特定类)安全地将Object从基类转换为更派生类;

class ALegendaryWeapon : public AWeapon
{
	void SlayMegaBoss()
	{
		TArray<AEnemy> EnemyList = GetEnemyListFromSomewhere();

		// The legendary weapon is only effective against the MegaBoss
		for (AEnemy Enemy : EnemyList)
		{
			AMegaBoss* MegaBoss = Cast<AMegaBoss>(Enemy);
			if (MegaBoss)
			{
				Incinerate(MegaBoss);
			}
		}
	}
};

        使用了Cast来尝试将AEnemy转换为AMegaBoss,如所提及Object实际上不是AMegaBoss(或者其子类),则Cast会返回空指针;在以上代码中,Incinerate将仅对MegaBoss调用;

Garbage Collection

        虚幻实现垃圾回收机制,不再被引用或已被显式标记为销毁的UObject将定期清理;引擎构建一个引用图表以确定哪些UObject仍在使用,哪些是孤立的;在该图表根部是一组指定为"root set"的UObject;任何UObject都可以添加到root set;当进行垃圾回收时,引擎将从root set开始,搜索已知UObject引用树来跟踪所有引用的UObject;任何未被引用的UObject(意味着未在树搜索中找到这些对象)将被假设为不再需要,因此被删除;

        一个实际的影响是,通常需要保持对希望保持活跃的任何Object的UPROPERTY引用,或将指向它的指针存储在TArray或其他引擎容器类中;Actor及其组件通常属于例外情况,因为Actor通常被链接回到根集的Object引用(如它们所属的关卡),而Actor的组件被Actor自身引用;Actor可以显式标记为销毁,方法是调用它们的Destroy函数,这是从进行中游戏移除Actor的标准方法;组件可以使用DestroyComponent函数显式销毁,但它们通常在拥有它们的Actor从游戏中移除时被销毁;

        虚幻引擎中的垃圾回收速度快,效率高,内置大量的优化功能,能够尽量降低开销,如多线程可访问性分析可以标识孤立Object,优化的unhashing代码能够尽快从容器中移除Actor;还有一些其他功能以调节,以更精准地控制如何以及何时执行垃圾回收,大部分都可以在 项目设置(Project Settings) 中的 引擎 - 垃圾回收(Engine - Garbage Collection) 下找到;

Setting(s)Feature Description
Create Garbage Collector UObject Clusters可在项目设置中打开或关闭(默认打开);如打开,相关Object将被分组到一起归入垃圾回收集群,这样只需要检查集群自身即可,而不必检查每个Object;这意味着可以更快速地执行可访问性,因为整个集群将被视为一个对象,但也意味着该集群中的单个项目将被unhashed,并准备在同一帧中删除,如集群足够大,这样可能会导致卡顿;一般而言,集群创建会提高垃圾回收性能,缩短可访问性分析耗费的时间;
Merge GC Clusters可启用集群合并,这样当一个集群的对象引用另一个集群的对象时,让集群合并起来;注意,清空导致合并的引用不会让新合并的集群瓦解或拆散;Create Garbage Collector UObject Clusters 也必须打开,该功能才能工作;这会使垃圾回收器unhashing和销毁对象的频率降低,但一次unhashed和销毁的对象数量会增加;此外,有些情况下不会对合并集群进行垃圾回收,因为对该集群中任何对象的任何引用都会阻止对整个集群进行垃圾回收;
Actor Clustering Enabled通过在 Project Settings 中打开这个选项,并将bCanBeInCluster变量设置为true,或覆盖代码中的CanBeInCluster函数以使其返回true,可以将Actor放入集群中;默认,Actor和组件会将这个选项关闭,但静态网格体Actor和反射捕获组件除外;该功能可用于将应该一次性全部销毁的Actor分组在一起,通常是关卡中放置的不能被销毁的静态网格体,除非卸载包含这些网格体的子关卡;
Blueprint Clustering Enabled蓝图的UBlueprintGeneratedClass和相关数据,如共享UPROPERTY和UFUNCTION数据,可以通过打开该设置来建立集群;必须要认识到的是,该集群引用蓝图生成的类自身,而不是蓝图的单个实例;
Time Between Purging Pending Kill Objects垃圾回收活动的频率可以在项目设置中调整;该高级控制对于防止卡顿尤其有用;通过缩短回收间隔,可以减少将在下一次可访问性分析阶段发现的无法访问的对象的可能数量,并避免同时清除大量Actor时可能会发生的卡顿;

Network Replication

        UObject系统包含一组可靠的功能,能够促进网络通信和多人游戏;

        UProperties可以标记为告诉引擎
在网络游戏期间复制数据;常见模型是一个变量在服务器上发生更改,引擎检测到这个更改,并将其可靠地发送到所有客户端;当变量通过复制发生更改时,客户端可以选择性接收回调函数;

        UFunctions也可以标记为
在远程机器上执行;如,"server"函数在客户端上调用时,将会在服务器上执行这个函数以获取服务器版本的Actor;而另一方面,"client"函数可以从服务器调用,并在拥有这个函数的客户端版本的对应Actor上运行;

相关文章:

  • AcWing——1571. 完美序列
  • 无人机航迹规划:互联银行系统优化(Connected Banking System Optimizer,CBSO)求解无人机路径规划MATLAB
  • JavaScript作用域与闭包
  • 数字内容体验优化策略:全渠道整合与高效转化实践
  • NVIDIA Jetson Orin Nano 刷机过程
  • Unity Shader Graph 2D - Procedural程序化图形循环的箭头
  • 《AI大模型开发笔记》deepseek提示词技巧
  • 易语言写NFC标签URI网址NDEF记录
  • 17.企业级知识图谱中的知识库全景解析(基本概念、 5W2H视角知识库、存储格式分类与技术对比、实践路径与架构设计、案例)
  • 分享一个使用的音频裁剪chrome扩展-Ringtone Maker
  • android 源码切换分支
  • 第 15 天:数据存储,打造存档 读取系统!
  • CAD字体 SHX字体下载
  • Lineageos 22.1(Android 15)更换开机动画
  • Python函数进阶250215
  • 百度智能云—千帆 ModelBuilder API的简单调用(Java)
  • 《AI大模型开发笔记》MoE模型技术对比(Mixtral,Qwen2-MoE,DeepSeek-v3)
  • 刷机维修进阶教程-----MTK芯片机型修改脚本 永久去除系统更新 无视bl锁 无需root权限
  • tcp/ip协议设置参数,tcp/ip协议6设置
  • Linux文件管理:硬链接与软链接
  • 数说母亲节|全球11亿女性进入更年期,“不是忍忍就好”
  • 国际足联女子世界杯再次扩军,2031年起增至48支球队
  • 上海证监局规范辖区私募经营运作,6月15日前完成自评自纠
  • 聆听百年唐调正声:唐文治王蘧常吟诵传习的背后
  • 大四本科生已发14篇SCI论文?重庆大学:成立工作组核实
  • 巴基斯坦信德省首府卡拉奇发生爆炸