详解虚幻引擎的字符串类型

FName的概念:

在虚幻引擎中,FName 是一种专为高性能标识场景设计的轻量级、不可变、基于全局字符串池的哈希优化字符串类型,是引擎核心基础数据类型之一,用于高效存储和匹配 “标识性字符串”(而非动态文本)。

一、FName 的核心特性

  1. 全局字符串池(String Pool)机制FName 不会直接存储字符串内容,而是将唯一字符串存入引擎的全局哈希池(FNamePool),每个字符串对应一个 FNameEntry(含字符串内容 + 哈希值);FName 实例仅存储指向该条目的索引 + 编号(uint32)。

    • 相同字符串的 FName 复用同一池条目,避免内存冗余(如多次创建 FName("Enemy") 仅存一份字符串);
    • 引擎启动时预加载常用字符串(如资源路径、内置名称),进一步提升效率。
  2. 不可变性FName 创建后内容无法修改,若需变更只能新建实例 —— 保证哈希值稳定,避免查找 / 匹配失效。

  3. 默认大小写不敏感例如 FName("Enemy") 和 FName("enemy") 会被视为同一 FName(可通过项目设置开启大小写敏感,但不推荐),简化标签、名称的匹配逻辑。

  4. 高效比较与查找FName 的比较直接对比池索引(O (1) 时间复杂度),远快于普通字符串的逐字符比较(O (n)),适合作为键值或标识。

二、FName 的典型用途

  • 对象标识:Actor、Component、UObject 的实例名称(如 Actor->GetFName());
  • 标签系统:Actor/Component 的 Tags 属性(TArray<FName>)、GameplayTag 的名称部分;
  • 资源路径:蓝图、纹理、音效等资源的路径标识(如 FName("/Game/Blueprints/BP_Player"));
  • 反射与元数据:标识 UProperty、UFunction 的名称(如 GetPropertyByName(FName("Health")));
  • 高效键值TMap<FName, UObject*> 等容器的键类型(利用快速比较特性)。

三、FName 与其他字符串类型的区别

虚幻引擎中三种核心字符串类型的定位差异:

类型核心特点适用场景
FName不可变、池化、哈希优化、大小写不敏感标识、键值、快速比较 / 查找
FString可变、支持复杂文本操作(拼接 / 格式化)动态文本处理(玩家输入、日志)
FText本地化支持、多语言适配UI 文本、玩家可见的本地化内容
// 创建:从字符串字面量/ FString 转换
FName EnemyTag = FName(TEXT("Enemy"));
FString Str = TEXT("Player");
FName PlayerTag = FName(*Str);

// 比较:O(1) 效率
bool bEqual = (EnemyTag == FName(TEXT("enemy"))); // true(默认大小写不敏感)

// 转换:FName → FString/FText
FString TagStr = EnemyTag.ToString();
FText TagText = FText::FromName(EnemyTag);

// 有效性检查
bool bValid = !EnemyTag.IsNone(); // 空 FName 为 NAME_None

四、如何将普通字符串传入 / 转换为 FName

FName 支持从多种普通字符串类型转换,核心是通过构造函数显式转换,以下是常见场景:

1. 从 C++ 原生字符串(const char*/ 字面量)转换

直接通过 FName 构造函数,建议用TEXT()宏兼容 Unicode(虚幻引擎默认使用宽字符):

// 直接传入字符串字面量(推荐用TEXT宏)
FName TagName = FName(TEXT("Enemy")); 

// 从const char*变量转换
const char* Str = "Player";
FName PlayerName = FName(Str); // 或 FName(TEXT(Str))(需确保Str是宽字符)
2. 从std::string转换

需先将std::string转为const char*(解引用),再传入 FName 构造函数:

std::string StdStr = "Interactable";
FName InteractTag = FName(TCHAR_TO_ANSI(*StdStr.c_str())); // 或直接 FName(StdStr.c_str())
3. 从虚幻 FString 转换

FString 是虚幻的可变字符串类型,转换时需解引用 FString(*FString)获取TCHAR*

FString FStr = TEXT("Frozen");
FName FrozenTag = FName(*FStr); // 核心:用*解引用FString为TCHAR*
4. 函数参数中直接传入普通字符串

若函数参数要求 FName(如ActorHasTag(FName)),可直接传字符串字面量(隐式转换):

// 直接传字符串字面量,引擎自动隐式转为FName
bool bIsEnemy = MyActor->ActorHasTag(TEXT("Enemy"));

五、注意事项

  1. 大小写问题:FName 默认不区分大小写,若需严格区分,需在项目设置中开启 “Case Sensitive FNames”(不推荐,可能破坏引擎逻辑);
  2. 性能开销:转换普通字符串到 FName 时,引擎会检查字符串池(若不存在则添加),频繁转换动态文本(如玩家输入)会导致字符串池膨胀,需避免;
  3. 空值处理:空字符串("")会转为 FName 的NAME_None(空 FName),可通过IsNone()检查:
    FName EmptyName = FName(TEXT(""));
    bool bIsNone = EmptyName.IsNone(); // 返回true

"MyTag"是什么类型?

在 C++ 标准语法和虚幻引擎的编译环境中,"MyTag" 的类型需分场景讨论,核心差异源于字符编码配置引擎的类型定义

一、标准 C++ 中的类型

在原生 C++ 中,双引号包裹的字符串字面量(如 "MyTag")的默认类型是:const char*(指向窄字符数组的常量指针,窄字符 char 通常占 1 字节,对应 ASCII 编码)。

如果是带 L 前缀的字符串(如 L"MyTag"),则类型为:const wchar_t*(指向宽字符数组的常量指针,宽字符 wchar_t 占 2 或 4 字节,对应 Unicode 编码)。

二、虚幻引擎环境中的类型

虚幻引擎默认启用 UNICODE 宏(可在项目设置中确认),并通过 TCHAR 统一字符类型:

  • TCHAR 是虚幻定义的通用字符类型,在 Windows 平台等价于 wchar_t(宽字符),其他平台可能等价于 char(窄字符);
  • 若直接写 "MyTag",在虚幻的编译环境中,它仍会被识别为 const char*,但虚幻的核心 API(如 FName 构造函数)支持从 const char* 隐式转换为 TCHAR*(或直接兼容);
  • 若用 TEXT("MyTag") 包裹(推荐写法),则会根据 UNICODE 宏自动适配:
    • 启用 UNICODE 时,TEXT("MyTag") → L"MyTag" → 类型为 const TCHAR*(即 const wchar_t*);
    • 未启用 UNICODE 时,TEXT("MyTag") → "MyTag" → 类型为 const TCHAR*(即 const char*)。

三、为什么虚幻中传入 "MyTag" 不会报错?

虽然 "MyTag" 本身是 const char*,但 FName 类提供了兼容 const char* 的构造函数(或引擎内部做了隐式转换),同时 GetAllActorsWithTag 的第二个参数要求的 FName 支持从 const char*/const TCHAR* 隐式创建,因此编译器会自动完成类型转换,不会报错。

TEXT()是什么?

在虚幻引擎(以及 Windows API、C++ 跨平台开发场景)中,TEXT() 是一个用于统一字符编码的宏,核心作用是让字符串字面量根据编译环境自动适配窄字符(ANSI/char宽字符(Unicode/WCHAR,最终转换为虚幻引擎的通用字符类型 TCHAR

一、TEXT() 的本质与作用

1. 解决字符编码兼容性问题

C++ 中有两种常见字符类型:

  • 窄字符(char:占 1 字节,通常对应 ASCII 编码(仅支持英文字符);
  • 宽字符(WCHAR/wchar_t:占 2 字节(Windows)或 4 字节(Linux),支持 Unicode 编码(可存储中文、日文等多语言字符)。

虚幻引擎定义了 **TCHAR** 作为 “通用字符类型”:在 Windows 平台默认等价于 WCHAR(Unicode),其他平台可根据配置调整。TEXT() 宏的作用就是将普通字符串字面量(如"Enemy")包装为 TCHAR 类型的字面量,避免编码不匹配导致的编译错误或乱码。

2. 宏的底层定义

在虚幻引擎的源码中,TEXT() 宏的定义简化为:

#ifdef UNICODE
#define TEXT(str) L##str  // 宽字符模式:拼接L前缀(如TEXT("Enemy") → L"Enemy")
#else
#define TEXT(str) str     // 窄字符模式:直接使用原字符串(如TEXT("Enemy") → "Enemy")
#endif
  • L##str 是 C++ 的 “宏拼接” 语法,给字符串加L前缀(表示宽字符字面量);
  • 虚幻引擎默认启用UNICODE宏,因此TEXT("XXX")最终会被解析为宽字符字面量L"XXX"

二、TEXT() 的使用场景

1. 适配虚幻引擎的TCHAR类型

虚幻引擎的核心字符串类型(如FNameFStringFText)均基于TCHAR实现,因此定义字符串字面量时必须用TEXT(),否则会出现 “char*无法转换为TCHAR*” 的编译错误。例如:

// 正确:TEXT()将字符串转为TCHAR类型,匹配FName的构造函数
FName TagName = FName(TEXT("Enemy"));

// 错误:直接传入char*类型,与TCHAR*不兼容(虚幻默认Unicode模式下)
// FName WrongName = FName("Enemy"); 
2. 跨平台 / 多语言兼容

使用TEXT()后,字符串会自动适配目标平台的字符编码,无需手动区分 “宽字符 / 窄字符”,尤其适合需要支持中文、日文等多语言的项目。

三、与TEXT()相关的常见宏

为了处理不同字符类型的转换,虚幻引擎还提供了辅助宏:

  • TCHAR_TO_ANSI:将TCHAR*转为char*(窄字符);
  • ANSI_TO_TCHAR:将char*转为TCHAR*(宽字符);
  • TCHAR_TO_UTF8:将TCHAR*转为 UTF-8 编码的字符串。
FString FStr = TEXT("测试");
// 将TCHAR类型的FString转为UTF-8字符串
const UTF8CHAR* Utf8Str = TCHAR_TO_UTF8(*FStr);

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值