UE_C++ —— Objects

目录

一,UCLASS 宏

二,Properties 和 Function 类型

三,UObject 创建

四,UObjects 提供的功能

五,Unreal Header Tool

六,头文件格式

七,Updating Objects

八,Destroying Objects


        引擎所有对象的基类都是UObjectUCLASS宏用于标记UObject的子类,以便UObject handling system识别它们;

一,UCLASS 宏

        UCLASS 宏为 UObject 提供了一个 UCLASS 引用,用于描述它在虚幻引擎中的类型(Unreal-based typ);每个 UCLASS 都保留一个CDO(Class Default Object)的对象;CDO 本质上是一个默认"模板"对象,由类构建函数生成,之后就不再修改;

        可为指定对象获取其 UCLASS 和 CDO,通常它们都是只读类型;使用 GetClass() 函数即可随时访问对象实例的 UCLASS ;

        UCLASS 包含定义类的属性properties和函数functions,是标准C++代码可用的普通C++变量和函数,但被引擎特定的元数据所标记(控制在对象系统中的行为);

注,UObject 类还可包括仅限本地的属性(没有用 UFUNCTION 或者 UPROPERTY 标识符标记用于反射),仅被specifier宏标记的函数和属性会被列举在对应的 UCLASS 中;

二,Properties 和 Function 类型

        UObjects 可有成员变量(properties)或任意类型的函数,为便于引擎识别和操纵这些变量和函数,需以特殊的宏来标记并符合一定类型的标准;

三,UObject 创建

        UObjects 不支持构造器参数,所有的C++ UObject都会在引擎启动的时候初始化,引擎会调用其默认构造器;如没有默认的构造器,那么 UObject 将不会编译;

        UObject 构造器应该轻量化,仅用于设置默认值和子对象,构造时不应该调用其它功能;对于Actor和Actor组件,初始化功能应该输入 BeginPlay() 方法;

        UObjects 应该仅在运行时使用 NewObject 构建,或者将 CreateDefaultSubobject 用于构造器;

NewObject<class>使用所有可用创建选项的可选参数创建一个新实例;
CreateDefaultSubobject<class>创建一个组件或者子对象,可提供创建子类和返回父类的方法;

注,UObjects不要使用new操作符,所有的UObjects都应由引擎管理内存和垃圾回收;

四,UObjects 提供的功能

此系统的使用不强制要求,甚至有时不适合使用,但却存在以下益处:

  • 垃圾回收
  • 引用更新
  • 反射
  • 序列化
  • 默认属性变化自动更新
  • 自动属性初始化
  • 自动编辑器整合
  • 运行时类型信息可用
  • 网络复制

注,大部分益处适用于 UStructs(有与UObject 一样的反射和序列化能力);UStruct 被当作数值类型处理并且不会垃圾回收;

五,Unreal Header Tool

        为利用 UObject 派生类型所提供的功能,需要在头文件上为这些类型执行一个预处理步骤,以核对需要的信息;该预处理步骤由 UnrealHeaderTool(简称 UHT)执行;UObject 派生的类型需要遵守特定的结构;

六,头文件格式

        UObject 在源(.cpp)文件中的实现与其他 C++ 类相似,其在头(.h)文件中的定义必须遵守特定的基础结构,以便在引擎中正常使用;使用编辑器的"New C++ Class"命令是设置格式正确头文件的最简单方法;

        UObject 派生类的基础头文件可能看起来与此相似,假定 UObject 派生物被称为 UMyObject,其创建时所在的项目被称为 MyProject:

#pragma once

#include 'Object.h'
#include 'MyObject.generated.h' //此行预计为最后一个#include指令,如头文件需要知道其他类,可在文件中的任意位置提前声明或在 MyObject.generated.h 上;

UCLASS() //使引擎能识别 UMyObject,支持大量参数类说明符(确定类功能开关);
class MYPROJECT_API UMyObject : public UObject //将UMyObject类公开到其他模块,则需要指定 MYPROJECT_API
{
	GENERATED_BODY() //此宏不获取参数,但会对类进行设置,以支持引擎要求的基础结构;所有UCLASS和USTRUCT均有此要求

};

七,Updating Objects

        Ticking 代表虚幻引擎中对象的更新方式,所有Actors均可在每帧被 tick,便于执行必要的更新计算或操作;

        Actor 和 Actor组件在注册时会自动调用它们的 Tick 函数,然而,UObjects 不具有内建的更新能力;在必须的时候,可以使用 inherits 类说明符从 FTickableGameObject 继承即可添加此能力; 这样即可实现 Tick() 函数,引擎每帧都将调用此函数;

注,大部分游戏内对象都是Actor ,可以按用户设置的最短间隔tick,而不是每帧tick;

八,Destroying Objects

        对象不被引用后,垃圾回收系统将自动进行对象销毁;这意味着没有任何 UPROPERTY 指针、引擎容器、TStrongObjectPtr 或类实例会拥有任何对它的强引用;

        垃圾回收器运行时,未引用对象将被从内存中移除;此外,函数MarkPendingKill() 可在对象上直接调用。此函数将把指向对象的所有指针设为 NULL,并从全局搜索中移除对象;对象将在下一次垃圾回收过程中被完全删除;

  • Object->MarkPendingKill() 已被 Obj->MarkAsGarbage() 所替代;这个新的函数现在仅用于追踪旧对象;如果 gc.PendingKillEnabled=true ,那么所有标记为 PendingKill 的对象会被垃圾回收器自动清空并销毁;

  • 强引用会将 UObject 保留;如果不想让这些引用保留 UObject,那么这些引用应该转换来使用弱指针,或者变为一个普通指针由程序员手动清除(如对性能有较高要求的话);

  • IsValid() 用于检查它是 null 还是垃圾,但是大部分情况下 IsValid 可以被更正规的编程规则替换,比如在调用 OnDestroy 事件时将指针清除至 Actor;

  • 如禁用了 PendingKill(), MarkGarbage() 将会提醒对象的所有者该对象将要被销毁,但是对象本身直到所有对它的引用都解除之后才会被垃圾回收;

  • 对于 Actor,即使 Actor 被调用了 Destroy(),并且被从关卡中移除,它还是会等到所有对它的引用都解除之后才会被垃圾回收;

  • 已有的用于 nullptr 的检查应该被 IsValid() 调用所替代,除非进行手动清除,因为指针不再会被垃圾回收器通过 MarkPendingKill() 自动清除;

<think> 在虚幻引擎(Unreal Engine)的C++中,使用UE_LOG打印布尔值需要将布尔值转换为字符串或整数,因为UE_LOG没有直接支持布尔类型的格式化符号。 通常的做法是将布尔值转换为字符串(如"true"或"false")或者转换为整数(0或1)来打印。 我们可以使用三元运算符来将布尔值转换为字符串,然后使用`TCHAR_TO_ANSI`将字符串转换为ANSI字符串(因为UE_LOG的格式化字符串是ANSI字符串)。 注意:在UE_LOG中,我们使用`%s`来打印字符串。 以下是一个示例代码,展示如何打印布尔值: </think> 在虚幻引擎 C++ 中,使用 `UE_LOG` 打印布尔值时需要手动转换类型,因为 `UE_LOG` 没有直接支持布尔值的格式化符。以下是解决方案: ### 解决方案代码 ```cpp #include "YourClassName.h" // 替换为实际头文件名 // 在函数内部使用: bool bIsActive = true; UE_LOG(LogTemp, Warning, TEXT("布尔值状态:%s"), bIsActive ? TEXT("true") : TEXT("false")); ``` ### 代码解释: 1. **三元运算符转换** `bIsActive ? TEXT("true") : TEXT("false")` 将布尔值转换为 `FString` 对应的字符串字面量 2. **TEXT 宏** 使用 `TEXT()` 包裹字符串确保跨平台兼容性 3. **格式化符** `%s` 用于输出转换后的字符串 4. **日志类别** `LogTemp` 是临时日志通道,也可创建自定义日志类别 ### 进阶封装(可选) 创建通用打印函数: ```cpp // 头文件声明 void PrintBool(const FString& Message, bool bValue); // CPP文件实现 void PrintBool(const FString& Message, bool bValue) { UE_LOG(LogTemp, Warning, TEXT("%s: %s"), *Message, bValue ? TEXT("true") : TEXT("false")); } // 使用示例 PrintBool(TEXT("角色死亡状态"), bIsCharacterDead); ``` ### 注意事项: 1. 避免在性能敏感循环中频繁调用 2. 正式版本中应移除调试日志 3. 使用 `LogVerbosity` 控制日志级别(如 `Warning`, `Error`)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值