- 文档
- 教程
- 游戏开发
【免费下载链接】godot-docs
Godot Engine official documentation
导读
TextServerManager是 Godot 引擎中负责加载、枚举与切换 TextServer 文本服务实现的全局单例。无论是想要获取当前正在使用的文本服务接口(例如在自定义 BBCode 特效或字体工具中调用底层排版能力),还是需要在运行时动态切换文本驱动(如切换到不渲染文字的 Dummy 接口以释放内存),都必须通过这个类来完成。读完本文,你将掌握TextServerManager的全部 8 个方法、2 个信号的使用方式,并能在实际项目中安全地切换文本服务。
TextServerManager 是什么
TextServerManager继承自 Object,是 Godot 提供的单例(singleton),在 TextServer 的文档中明确描述其定位为"API backend for loading, enumerating, and switching TextServers",即文本服务后端的统一管理入口。
Godot 的文本排版体系采用可插拔接口设计:TextServer是一个抽象类,负责字体管理与文本渲染的底层 API,而实际工作由若干具体实现完成:
- TextServerAdvanced(默认):使用 HarfBuzz、ICU 与 SIL Graphite,支持 BiDi 双向文本、复杂文本布局与上下文相关 OpenType 特性,是 Godot 默认的主文本服务,详见 TextServerAdvanced;
- TextServerFallback:不支持 RTL 排版与复杂脚本,可作为精简备选(该实现不包含在官方二进制中,需以
module_text_server_fb_enabled=yes自行编译); - TextServerDummy:不渲染文字、不管理字体的占位实现,项目启动时始终可用,适合释放内存或做性能对比,详见 TextServerDummy。
TextServerManager正是统一注册、查询与切换这些实现的枢纽。项目设置中的internationalization/rendering/text_driver(见 ProjectSettings)决定默认使用哪个文本驱动,而管理器负责在运行时对接口进行增删与主接口切换。
方法总览
根据 TextServerManager 的官方类参考,该类共提供 8 个方法:
| 返回值 | 方法签名 | 说明 |
|---|---|---|
void | add_interface(interface: TextServer) | 注册一个 TextServer 接口 |
TextServer | find_interface(name: String) | 按名称查找接口(const,无副作用) |
TextServer | get_interface(idx: int) | 返回指定索引处注册的接口(const) |
int | get_interface_count() | 返回当前已注册的接口数量(const) |
Array[Dictionary] | get_interfaces() | 返回可用接口列表,包含每个接口的索引与名称(const) |
TextServer | get_primary_interface() | 返回当前正在使用的主 TextServer 接口(const) |
void | remove_interface(interface: TextServer) | 移除一个接口 |
void | set_primary_interface(index: TextServer) | 设置主 TextServer 接口 |
add_interface
add_interface(interface: TextServer)将一个新的TextServer实现注册到管理器。注册成功后,该接口即可通过find_interface、get_interface等查询方法被获取。从代码结构可以推断,这类注册通常发生在引擎模块初始化阶段——例如编译期启用的TextServerAdvanced等模块在启动时向管理器注册自身。
find_interface
find_interface(name: String) -> TextServer按名称查找接口。接口名称来自TextServer.get_name()(返回接口的完整名称)与TextServer.get_short_name()(返回可用于--text-driver命令行参数的短名称,见 TextServer)。例如 Dummy 接口的短名即为"Dummy"。若未找到,返回null。
get_interface / get_interface_count / get_interfaces
get_interface(idx: int) -> TextServer get_interface_count() -> int get_interfaces() -> Array[Dictionary]这三个方法共同提供接口枚举能力:
get_interface(idx)按索引访问;get_interface_count()返回注册总数;get_interfaces()返回一个Array[Dictionary],每个字典包含接口的索引与名称,便于遍历或调试输出。
get_primary_interface
get_primary_interface() -> TextServer这是最常用的方法,返回当前引擎实际使用的主文本服务接口。由于TextServer是抽象类,无法直接实例化,官方在 TextServer 文档中给出的标准取用方式就是通过它:
# GDScript var ts = TextServerManager.get_primary_interface()// C# var ts = TextServerManager.GetPrimaryInterface();拿到该接口后,即可调用 TextServer 上的一系列底层字体/字形 API,例如font_get_char_from_glyph_index()、font_get_glyph_index()、create_shaped_text()等。
remove_interface
remove_interface(interface: TextServer)从管理器中移除指定接口。官方文档明确要求:移除接口前应先释放所有字体与已排版(shaped)的文本缓存,否则可能遗留对已销毁资源的引用。
set_primary_interface
set_primary_interface(index: TextServer)将指定接口设为当前主接口,用于运行时切换文本服务。注意参数名虽为index,但实际传入的是TextServer接口对象本身。
信号
管理器提供两个信号,用于监听接口注册状态的变化:
interface_added(interface_name: StringName):当新接口被注册时发出,参数为接口名称;interface_removed(interface_name: StringName):当接口被移除时发出。
例如,当某个模块在运行期动态注册了新的文本服务实现,其他系统可通过连接interface_added信号感知这一变化并作出响应。
实战一:获取并使用当前主文本服务
在需要访问字体度量或字形信息的场景(如自定义 RichText 特效)中,get_primary_interface()是入口。仓库的 bbcode_in_richtextlabel.rst 中,"Matrix" 特效就是一个完整的实际用例——它先通过TextServerManager.get_primary_interface()获取接口,再调用字体相关 API 把字符替换为字形索引、重新查询字形:
# 获取 TextServer,用于检索字体信息 func get_text_server(): return TextServerManager.get_primary_interface() func _process_custom_fx(char_fx): # ... 特效参数处理 ... # 从字形索引反查字符 var value = get_text_server().font_get_char_from_glyph_index(char_fx.font, 1, char_fx.glyph_index) # ... 字符替换逻辑 ... # 按新字符重新查询字形索引 char_fx.glyph_index = get_text_server().font_get_glyph_index(char_fx.font, 1, value, 0) return true可见,管理器在底层文本能力与上层 UI 组件之间扮演了"服务定位器"的角色:上层代码无需关心当前究竟是 Advanced 还是 Fallback 实现,只需通过管理器获取活动接口即可。
实战二:运行时切换文本服务(Dummy 示例)
TextServerDummy的类参考(class_textserverdummy.rst)给出了一个完整的切换流程,集中演示了find_interface、set_primary_interface、get_interface_count、get_interface、remove_interface的组合用法:
var dummy_text_server = TextServerManager.find_interface("Dummy") if dummy_text_server != null: # 将 Dummy 设为主接口,之后所有文字将不再实际渲染 TextServerManager.set_primary_interface(dummy_text_server) # 如果其他文本服务不再需要,可以一并移除: for i in TextServerManager.get_interface_count(): var text_server = TextServerManager.get_interface(i) if text_server != dummy_text_server: TextServerManager.remove_interface(text_server)该用例的业务价值在于:文本服务(尤其是默认的 Advanced 实现)是资源密集型模块。在纯无 UI 的服务器/后台场景,或需要进行复杂 GUI 的文本渲染性能对比时,切换到 Dummy 接口可以释放内存、消除文字渲染开销。
通过项目设置与命令行选择文本驱动
除了在运行时通过 API 切换,文本驱动也可以在项目配置与命令行层面指定:
项目设置:internationalization/rendering/text_driver(默认值为空字符串"",见 ProjectSettings)。留空时使用默认驱动(即 TextServerAdvanced)。可填入"ICU / HarfBuzz / Graphite"(Advanced)或"Fallback"等名称。注意 Dummy 驱动不会出现在项目设置的下拉列表中,只能通过命令行启用。
命令行参数:在运行编辑器或项目时使用--text-driver <driver>(区分大小写),例如--text-driver Dummy可强制任意项目使用 Dummy 驱动。该参数在 command_line_tutorial.rst 的命令行选项表中被描述为 "Text driver (Fonts, BiDi, shaping)"。get_short_name()返回的短名称可直接作为该参数的值;若使用含空格的完整名称,则必须加引号。
导出相关:若项目需要高级文本服务的数据支持,可将internationalization/locale/include_text_server_data设为true,把断行规则、字典等可选数据(约 4 MB,含缅甸语、中文、日语、高棉语、老挝语、泰语词典及 Unicode 标准附件 UAX #14/#29 规则)打入导出包。
运行时切换的重要注意事项
官方在 TextServerManager 的类参考中明确强调:
切换文本服务在运行时是可行的,但会使所有字体和文本缓冲区失效。切换前务必先卸载所有控件、字体和主题。
这是因为不同的TextServer实现内部维护各自的字体资源与字形缓存(RID 体系),切换主接口后,旧接口创建的字体、排版缓冲区在新接口下可能不可用。因此推荐的切换时序是:
- 释放/卸载所有
Control、Font、Theme及其缓存(如TextParagraph、TextLine); - 调用
set_primary_interface()完成切换; - 需要彻底释放旧接口资源时,再调用
remove_interface(),且同样要确保相关字体与排版缓存已先行释放; - 切换后重新加载字体与主题。
遵循这一顺序,可以避免因资源失效导致的崩溃或渲染异常。
小结
TextServerManager是 Godot 文本渲染体系中"管理服务本身"的枢纽单例:get_primary_interface()是最常用的服务获取入口;find_interface/get_interface/get_interface_count/get_interfaces提供完整的枚举与查找能力;add_interface/remove_interface/set_primary_interface支撑运行时的动态注册与切换;interface_added/interface_removed两个信号则让外部系统可以感知服务拓扑变化。配合项目设置internationalization/rendering/text_driver与命令行--text-driver,开发者可以按场景灵活选择文本后端——从默认的全功能 Advanced 实现,到无 UI 场景下省内存的 Dummy 实现。
- 文档
- 教程
- 游戏开发
【免费下载链接】godot-docs
Godot Engine official documentation
相关推荐
PushDeer API详解:掌握推送服务的核心接口
PushDeer API详解:掌握推送服务的核心接口 PushDeer是一个开源的推送服务解决方案,提供了完整的API接口体系,让开发者能够轻松实现消息推送功能
后端消息路由移动开发物联网Spring事务核心:TransactionDefinition接口详解
Spring事务核心:TransactionDefinition接口详解 引言:为什么需要TransactionDefinition? 在复杂的业务系统中,数据
示例工程文档如何 5 分钟解包改包 Android APK?Apktool 逆向工程完整指南
如何 5 分钟解包改包 Android APK?Apktool 逆向工程完整指南 Apktool 是一款专门用来"拆开"和"重组" Android 应用(APK
逆向工程开发工具移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考