UE_C++ —— 数据类型 目录一基本数据类型二字符串类型三容器类型四向量及变换类型五枚举类型六对象指针一基本数据类型UE对C基本数据类型进行了深度重定义并禁止使用原生的C基本数据类型以保证引擎的跨平台特性布尔类型bool代表布尔值即true或false字符类型TCHAR代表字符型用于支持宽字符如Unicode字符集以保证跨平台兼容性短整形short2个字节无符号和有符号整数类型int标准整形根据系统架构32位或64位的不同其大小可能有所不同32位4字节、64位8字节uint81字节、uint162字节、uint324字节、uint648字节int81字节、int162字节、int324字节、int648字节长整形long4个字节长长整形long long8个字节浮点类型float单精度浮点型4字节在值后加f以提升效率和精度如3.14fdouble双精度浮点型8字节// 基础类型 bool bool_val 1; uint8 byte_val 255; int32 int32_val -32; int64 int64_val -64; double double_val 3.14; // UE_LOG 的第 3 个参数Format必须是格式化字符串字面量便于编译时检查及节省运行时开销 UE_LOG(LogTemp, Error, TEXT(%d), bool_val); UE_LOG(LogTemp, Warning, TEXT(%d), byte_val); UE_LOG(LogTemp, Warning, TEXT(%d), int32_val); UE_LOG(LogTemp, Display, TEXT(%d), int64_val); UE_LOG(LogTemp, Display, TEXT(%f), double_val);二字符串类型FString动态字符数组用于存储可变的字符串必须用TEXT宏包裹字符串开销大于其他类字符串类型是处理字符串的主要类型适用于存储临时数据如文件路径、日志信息、调试文本、配置文件内容等FName资源命名字符串存储不可变的字符串必须用TEXT宏包裹字符串相对轻量级的字符串类型散列存储速度快大小通常为8byte只进行一次字符串哈希映射在比较字符串时不区分大小写且只读主要用于表示引擎中的名称如对象名、资源名、类名等以提高性能FText支持本地化的文本字符串不可变不提供修改函数无法进行内容修改处理用户的显式文本提供了对字符串进行格式化、本地化等操作的功能提供了对文本的多语言支持可以根据不同的语言和文化设置提供不同的显示内容大小为40bytes核心实质是一个TSharedRefITextData即实际文本数据的智能引用拷贝成本非常低只需拷贝指针而不是整个字符串数据主要用于用户界面UI上显示的文本如对话框、按钮文字、任务提示等需要翻译的文本//FString类 //构造与赋值 FString str1; // 创建一个空的FString对象 FString str2(TEXT(Hello)); // 使用TEXT宏创建一个包含Hello的FString对象 FString str3 str2; // 通过拷贝构造函数赋值 FString str4 TEXT(World); // 直接使用TEXT宏进行赋值 //追加 FString str TEXT(Hello, ); str.Append(TEXT(World!)); // 使用Append函数追加字符串结果str为Hello, World! str TEXT( Again!); // 使用运算符追加字符串结果str为Hello, World! Again! //插入 FString str TEXT(Hello); str.InsertAt(5, TEXT( World)); // 在索引5的位置插入字符串 World结果str为Hello World //替换 FString str TEXT(Hello World); str str.Replace(TEXT(World), TEXT(UE)); // 将World替换为UE结果str为Hello UE //查询 FString str TEXT(Hello World); bool containsHello str.Contains(TEXT(Hello)); // 判断是否包含子字符串Hello结果为true int32 index str.Find(TEXT(World)); // 查找子字符串World的索引结果为6 bool startsWithHello str.StartsWith(TEXT(Hello)); // 判断是否以Hello开头结果为true bool endsWithWorld str.EndsWith(TEXT(World)); // 判断是否以World结尾结果为true //格式化 FString playerName TEXT(John); FString greeting FString::Printf(TEXT(Hello, %s!), *playerName); // 使用Printf函数格式化字符串结果greeting为Hello, John! //路径拼接 FString basePath TEXT(C:/Users/Documents/); FString fileName TEXT(example.txt); FString fullPath basePath / fileName; // 使用/运算符进行路径拼接结果fullPath为C:/Users/Documents/example.txt FString fullPath; fullPath.PathAppend(fileName, TEXT(example.txt).Length()); // 将文件名追加到基路径上注意需要传递文件名的长度//FName //创建 FName myFName(TEXT(MyObjectName)); //比较 if (myFName FName(TEXT(MyObjectName)));//FText FText myText TEXT(Hello, World!); FText formattedText FText::Format(TEXT(Hello, {0}!), TEXT(World));// 字符串类型 FString str TEXT(FString!); //内部是TArrayTCHAR的封装并重载了operator*() FName name TEXT(FName!); FText text FText::FromString(TEXT(FText!)); UE_LOG(LogTemp, Display, TEXT(%s), *str); UE_LOG(LogTemp, Display, TEXT(%s), *name.ToString()); UE_LOG(LogTemp, Display, TEXT(%s), *text.ToString());三容器类型TArrayTUE定义的增强数组容器是一个同质容器即其所有元素均完全为相同类型与std::vector类似可动态扩充内存当容量满了会额外分配一个更大的内存并将数据拷到新内存上之后再释放旧的内存提供了比标准C数组更丰富的功能如动态扩展、排序、查找等具有速度快、内存消耗小、安全性高等特点TSetT存储值本身的松散的集合默认不允许元素重复存储唯一元素基于哈希表实现提供了快速的查找、插入和删除操作UE使用两个数组HashArray和ElementArray来实现TSetHashArray中存放着ElementArray的Index而ElementArray中存放着具体的值使用拉链法解决冲突TMapk, Tkey-value类型容器允许通过键来快速查找对应的值适用于需要快速访问数据的场景基于哈希表实现提供了高效的查找性能键必须是唯一的而值可以是任何类型//TArray #include Containers/Array.h TArrayint32 IntArray; //初始化一个空的TArray //添加元素 IntArray.Add(10); IntArray.Add(20); IntArray.Add(30); IntArray.AddUnique(30); //使用索引访问元素 UE_LOG(LogTemp, Warning, TEXT(Element at index 1: %d), IntArray[1]); //输出: Element at index 1: 20 //使用范围for循环迭代元素 for (int32 i : IntArray) { UE_LOG(LogTemp, Warning, TEXT(Element: %d), i); } IntArray.RemoveAt(1); //移除索引为1的元素即20 IntArray.Empty(); //清空数组//TSet #include Containers/Set.h TSetint32 IntSet; //声明一个存储int32的TSet TSetFString StringSet { TEXT(Hello), TEXT(World) }; //使用初始化列表 IntSet.Add(10); IntSet.Add(20); IntSet.Add(10); //这个不会被添加因为10已经存在 IntSet.Contains(20); //检查TSet中是否包含某个元素 IntSet.Remove(10); IntSet.Empty();//TMap #include Containers/Map.h TMapFString, int32 StringToIntMap; // 声明一个存储FString到int32映射的TMap // 初始化通常是通过Add方法 StringToIntMap.Add(TEXT(One), 1); StringToIntMap.Add(TEXT(Two), 2); StringToIntMap.Add(TEXT(Three), 3); StringToIntMap.Add(TEXT(One), 10); // 这会覆盖键为One的值新的值为10 //查找元素 if (StringToIntMap.Contains(TEXT(Two))) { int32 value StringToIntMap[TEXT(Two)]; // 更常见的查找方式但如果键不存在会触发断言在开发构建中 // 或者使用Find来避免断言 int32* valuePtr StringToIntMap.Find(TEXT(Two)); if (valuePtr) { int32 value *valuePtr; } } StringToIntMap.Remove(TEXT(One)); StringToIntMap.Empty();// 容器类型 TArrayint32 arr { 1,2,3,4,5 }; TSetint32 set { 10,20,30,40,50 }; TMapint32, FString map { {1, TEXT(one)}, {2, TEXT(two)} }; FString arr_ret; for (auto num : arr) arr_ret FString::FromInt(num) TEXT( ); GEngine-AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, arr_ret); FString set_ret; for (auto num : set) set_ret FString::FromInt(num) TEXT( ); GEngine-AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, set_ret); FString map_ret; for (auto num : map) map_ret num.Value TEXT( ); GEngine-AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, map_ret);四向量及变换类型FVector表示3D空间点、向量等的三维向量类型包含三个浮点数分量X、Y和Z常用于表示对象的位置、方向、速度等支持向量的基本运算如加法、减法、点积、叉积等可以方便地转换为其他数学类型如四元数FQuat和矩阵FMatrixFRotator表示3D旋转的三维向量类型包含三个浮点数Pitch、Yaw、Roll以角度为单位存储Pitch表示绕右轴Y轴旋转的角度上下0正前方向上-向下的旋转Yaw表示绕上轴Z轴旋转的角度绕圈0东北-南Roll表示绕前向轴X轴旋转的角度歪着头0正直顺时针旋转-逆时针旋转可以转换为四元数FQuat以进行更高效的旋转计算FTransform更高级别的矩阵类型包含三个矩阵Rotation旋转、Translation平移和Scale3D缩放广泛用于表示对象在3D空间中的位置和变换支持矩阵的基本运算如乘法、逆运算等可以方便地转换为其他数学类型如四元数FQuat和向量FVectorFVector Location(10.0f, 20.0f, 30.0f); FRotator Rotation(0.0f, 45.0f, 0.0f); FTransform Transform(FVector(10.0f, 20.0f, 30.0f), FRotator(0.0f, 45.0f, 0.0f), FVector(1.0f, 1.0f, 1.0f));五枚举类型enum使用enum关键字定义枚举类型enum class EMyEnum { Value1, Value2, Value3 }; EMyEnum MyEnumValue EMyEnum::Value1;六对象指针*UPROPERTY标记后支持尽可能使用TObjectPtr† 只有TObjectPtr被UPROPERTY标记后才支持‡ 已弃用改用TSoftObjectPtr§❡ 该类型无法标记UPROPERTY会运行所有位置的GCTObjectPtrT可直接替代原生指针只能用于从UObject派生的类型序列化方式与指向UObject的原始指针相同当被标记为UPROPERTY时是对对象的强引用会阻止垃圾回收销毁目标对象class UMyObject : UObject { UPROPERTY() TObjectPtrUMyOtherObject MyOtherObject; UPROPERTY() TObjectPtrUStaticMeshComponent Mesh; }TSoftObjectPtrT指向对象的弱引用跟踪磁盘上目标对象的路径不影响GC当引用的对象加载到内存和从内存卸载时可能会在有效和挂起状态间来回变化对按需异步加载的资源或防止硬依赖非常有用如目标对象尚未有效则必须以同步或异步方式显式加载它public AMyActor : AActor { // ... UPROPERTY(EditAnywhere) TSoftObjectPtrUNiagaraSystem NiagaraVFX; // Use NiagaraVFX.Get() inside OnLoadComplete void OnLoadComplete(); } // When asset needs to be used... // ...load synchronously UNiagaraSystem* VFX NiagaraVFX.LoadSynchronous(); // ...or, stream asynchronously FStreamableManager StreamableManager UAssetManager::Get().GetStreamableManager(); FStreamableDelegate OnLoadCompleteDelegate FStreamableDelegate::CreateUObject(this, *AMyActor::OnLoadComplete); StreamableManager.RequestAsyncLoad(NiagaraVFX.ToSoftObjectPath(), OnLoadCompleteDelegate);TWeakObjectPtrT指向对象的弱指针无需被标记为UPROPERTY支持序列化并且也支持网络传输通常当明确不希望阻止对象被垃圾回收时使用目标对象被回收或销毁会自动置空使用前应通过TWeakObjectPtr::IsValid检查是否有效或使用TWeakObject::Get不支持作为 TMap 中的键也不支持作为 TSet 中的元素 UObject 作为键使用 TObjectKey// Object Cache TMapTSubclassOfUObject, TWeakObjectPtrUObject CachedObjects; // Get cached object by class, if still valid UObject* GetCachedObject(TSubclassOfUObject CachedObjectClass) { if (TWeakObjectPtrUObject FoundObject *CachedObjects.Find(CachedObjectClass)) { // If running on the game thread, this pattern is permissable: if (FoundObject.IsValid()) { return FoundObject.Get(); } /* If running on any thread other than game thread, use this pattern: if (TStrongObjectPtrUObject FoundObjectPinned FoundObject.Pin()) { return FoundObjectPinned.Get(); } */ } return nullptr; }FSimpleDelegate MyDelegate; TObjectPtrUMyObject MyObject; MyDelegate.BindLambda( [MyWeakObject MakeWeakObjectPtr(MyObject)]() { if (TStrongObjectPtrUMyObject MyStrongObject MyWeakObject.Pin()) { // object safe to access } else { // object already garbage collected } } );TStrongObjectPtrT指向对象的强指针会统计目标对象引用次数并在目标对象处于作用域内时阻止垃圾回收不支持UPROPERTY不适合用于派生自UObject的类中的字段对调试工具的可见性也较低创建和销毁该类型开销较大应尽可能避免对于不常更改的长期引用应使用每个TStrongObjectPtr都会为垃圾回收增加一个被跟踪的引用用于在非 UObject 拥有类如未从 UObject 派生的类或结构体中存储对 UObject 的强引用因为在 UObject 之外无法使用 UPROPERTY对在UObject类内部使用标记为UPROPERTY的TObjectPtr对于资源引用使用TWeakObjectPtrclass FMyClass { // ... // Strong reference to a UObject inside a non-UObject class TStrongObjectPtrUMyObject MyObject; }