Unity游戏实时翻译插件XUnity.AutoTranslator:从原理到实战应用

📅 2026/7/18 8:13:09 👁️ 阅读次数 📝 编程学习
Unity游戏实时翻译插件XUnity.AutoTranslator:从原理到实战应用

1. 项目概述:XUnity.AutoTranslator 是什么?

如果你是一名喜欢玩各种独立游戏、视觉小说或者日系RPG的玩家,肯定遇到过这样的烦恼:游戏本身质量很高,但偏偏没有官方中文,或者官方翻译质量一言难尽。传统的汉化补丁虽然能解决问题,但往往需要等待汉化组发布,而且一旦游戏更新,补丁就可能失效。有没有一种方法,能让我们在游戏运行时,实时、自动地将游戏内的文本翻译成我们熟悉的语言呢?

XUnity.AutoTranslator(以下简称 XUA)就是为解决这个问题而生的神器。它本质上是一个高级的、可高度定制的翻译插件,专门为基于 Unity 引擎开发的游戏设计。简单来说,它就像给你的游戏安装了一个“同声传译”,能够拦截游戏运行时显示的所有文本,调用你指定的翻译服务(如谷歌翻译、DeepL等)进行实时翻译,并将结果无缝替换回游戏界面。它的强大之处在于,它不修改游戏原始文件,而是通过内存注入和资源重定向的技术,在游戏运行时动态地“偷梁换柱”,因此兼容性极强,对游戏更新也不敏感。

从技术角度看,XUA 不仅仅是一个简单的文本替换工具。它集成了文本钩子(Hooking)、资源重定向(Resource Redirection)、翻译聚合、字体替换、UI自适应调整等一整套复杂机制。它支持通过 BepInEx、IPA、ReiPatcher 等多种流行的 Unity 游戏 Mod 框架加载,这意味着它对绝大多数使用 Unity 引擎的 PC 游戏都具备潜在的兼容性。无论是 Steam 上的热门作品,还是一些小众的独立游戏,只要它是 Unity 开发的,XUA 就有很大概率能派上用场。

这个项目的核心价值在于“自动化”和“可定制化”。对于普通玩家,它提供了开箱即用的体验,配置好翻译引擎和语言,就能立刻享受游戏。对于高级用户和 Mod 开发者,它提供了详尽的配置选项和强大的 API,允许你进行精细的翻译规则控制、自定义字体、甚至开发自己的翻译后端。它打破了玩家与外语游戏之间的语言壁垒,让“生肉”游戏变得“可食用”,极大地扩展了玩家的游戏库和体验范围。

2. 核心工作机制与架构拆解

要理解 XUA 如何工作,我们需要深入到它的技术架构层面。它并非一个简单的“翻译器”,而是一个运行在游戏进程内、拥有复杂工作流的中间件系统。

2.1 文本拦截与钩子(Hooking)机制

这是 XUA 最核心的一步。游戏在屏幕上显示任何文字,最终都会调用 Unity 引擎中用于渲染文本的组件(如UnityEngine.UI.TextTextMeshPro等)的文本设置方法(例如set_text)。XUA 利用 Harmony(一个.NET运行时补丁库)或 MonoMod Runtime Detours,在这些关键方法被调用前进行“拦截”(Hook)。

当游戏试图设置一个文本字符串时(比如textComponent.text = “こんにちは”),XUA 的钩子会先一步捕获到这个调用。它拿到原始的、未经翻译的文本(“こんにちは”),然后暂停游戏原本的设置流程,启动自己的翻译流水线。这个过程对游戏本身是透明的,游戏引擎并不知道自己设置的文本已经被“调包”了。

这里有一个技术细节:不同的游戏和 UI 框架(如传统的 UGUI、NGUI,或更现代的 TextMeshPro)调用文本设置的方式可能有细微差别。XUA 的钩子需要足够智能和全面,才能覆盖大多数情况。这也是为什么其配置文件中会有EnableSpriteRendererHookingTextGetterCompatibilityMode等选项,用于应对一些特殊或老旧的文本渲染方式。

2.2 翻译查询与缓存流水线

拦截到文本后,XUA 并不会立刻发送给在线翻译服务。那样效率太低,且容易因网络问题导致游戏卡顿。它的处理流程是一个精心设计的多级流水线:

  1. 文本预处理:首先,原始文本会经过一系列预处理。这包括根据配置处理空白字符(例如,忽略对话文本开头/结尾的空白,合并内部换行周围的空白),以及应用“替换规则”(Substitutions)。替换规则文件允许你手动定义一些固定翻译,比如将经常被误译的特定角色名或专有名词直接替换掉,这能显著提升翻译准确率和一致性。

  2. 多级缓存查找:预处理后的文本会进入一个高效的缓存字典进行查找。这个字典的内容来自几个地方:

    • 手动翻译文件:用户或汉化组预先准备好的、精准的翻译对。
    • 自动生成的翻译文件_AutoGeneratedTranslations.txt):之前通过在线翻译服务获取并保存下来的结果。
    • 内部静态词典:插件内置的一些常见词汇对照。 XUA 会进行最多四次查找,分别对应原始文本、去除首尾空格、处理内部换行等不同变体,以确保最大程度地匹配缓存。如果缓存命中,则立即返回结果,速度极快。
  3. 在线翻译请求:如果所有缓存都未命中,文本才会被送入在线翻译流程。XUA 支持众多翻译后端(Endpoint),如 Google Translate、Bing Translator、DeepL、Yandex.Translate、百度翻译等。你可以配置 API 密钥(对于需要认证的服务),也可以使用一些免费的、无需密钥的公共接口(但可能有速率限制或稳定性问题)。插件会负责构建网络请求、处理响应和错误重试。

  4. 结果后处理与缓存:从在线服务获取到翻译结果后,会进行后处理。这可能包括应用“后处理规则”(Postprocessors),比如调整标点符号格式、修复一些翻译引擎特有的怪癖。处理完成后,翻译结果不仅会返回给游戏进行显示,还会被自动写入到_AutoGeneratedTranslations.txt文件中。这样,下次再遇到相同的句子时,就可以直接从缓存读取,无需再次联网,既加快了速度,又减少了对翻译服务的调用。

2.3 资源重定向(Resource Redirector)模块

这是 XUA 另一个强大的子系统,它相对独立于文本翻译。有些游戏的文本并非动态设置,而是直接写在游戏的资源文件(如.assets文件、AssetBundle包)里。对于这种情况,单纯的运行时文本钩子可能无法捕获。

资源重定向模块允许 XUA(或其他插件)在游戏加载资源(如图片、文本资源、音频等)时进行拦截和替换。例如,游戏要加载一张日文的 UI 图片button_jp.png,该模块可以将其重定向到你自己准备的、已经汉化好的button_cn.png文件。这对于替换游戏内的图片文字(如菜单、图标)至关重要。

该模块通过钩住 Unity 的Resources.LoadAssetBundle.LoadAsset等核心资源加载 API 来实现。它允许开发者注册前缀(Prefix)和后缀(Postfix)回调,在资源加载前后进行操作,可以读取、修改甚至完全替换即将加载到内存中的资源对象。XUA 自带的TextAssetRedirector就是利用这个功能,将游戏内的文本资源文件导出到磁盘,允许用户直接修改,修改后的版本会在游戏运行时被加载,从而实现更彻底的“静态”汉化。

2.4 UI 自适应与字体管理

直接将英文或日文翻译成中文,一个常见的问题是文字长度变化。一个简短的英文单词翻译成中文可能变成两个汉字,而一个长句日文翻译成中文后可能变短。这会导致游戏原本的文本框(Text Component)出现显示不全(溢出)或留白过多的问题。

XUA 提供了多种 UI 自适应方案:

  • 自动调整:通过EnableUIResizingForceUIResizing选项,插件可以尝试自动修改文本框的“溢出”(Overflow)处理方式,比如将Overflow模式从Truncate(截断)改为Overflow(溢出),或者调整Horizontal OverflowVertical Overflow设置,让长文本能够显示出来。
  • 手动字体缩放:用户可以创建resizer.txt文件,为特定的 UI 元素路径指定缩放命令,例如ChangeFontSizeByPercentage(0.8)将字体缩小到 80%。这需要借助其他工具(如 Runtime Unity Editor)来获取游戏中 UI 元素的完整路径。
  • 字体替换:许多游戏的默认字体不包含中文字符集,导致中文显示为方框(□□□)。XUA 允许通过OverrideFontFallbackFontTextMeshPro配置项,指定一个包含中文字符的字体文件(通常是打包成 AssetBundle 的 TMP 字体资源)。插件会在运行时加载并使用这个字体来渲染翻译后的文本。

这套组合拳确保了翻译结果不仅在内容上准确,在视觉呈现上也能尽可能地融入游戏原版 UI,提升整体体验。

3. 从零开始:安装、配置与基础使用

了解了原理,我们来看看如何实际使用它。整个过程可以分为安装、基础配置、高级调优三个阶段。

3.1 环境准备与插件安装

首先,你需要确定目标游戏使用的 Mod 框架。目前 XUA 主要支持 BepInEx(最通用)、IPA(主要用于日本发行的游戏)和 ReiPatcher(较老)。以最流行的 BepInEx 5.x 为例:

  1. 安装 BepInEx:前往 BepInEx 的 GitHub 发布页,下载对应你游戏位数(x86 或 x64)的版本。通常是一个压缩包,将其解压到游戏根目录(即包含游戏主.exe文件的文件夹)。运行一次游戏,BepInEx 会自动完成初始化,在游戏目录下生成BepInEx文件夹及其子目录。
  2. 安装 XUnity.AutoTranslator:从 XUA 的 GitHub 发布页下载XUnity.AutoTranslator-BepInEx-{VERSION}.zip。将其解压,你会看到BepInEx文件夹。将这个BepInEx文件夹整体拖拽到你的游戏根目录,与之前安装的 BepInEx 文件合并。通常,XUA 的核心插件文件XUnity.AutoTranslator.dll和资源重定向库XUnity.ResourceRedirector.dll会被放置到BepInEx\plugins目录下。
  3. 验证安装:启动游戏。如果安装成功,你通常会在游戏画面的一角看到 XUA 的初始化信息(例如 “XUnity Auto Translator initialized”),或者按Alt+0可以呼出翻译配置窗口。首次运行后,在BepInEx\config目录下会生成AutoTranslatorConfig.ini配置文件,在BepInEx\translation目录下会生成对应语言(如zh-CN)的文件夹和_AutoGeneratedTranslations.txt文件。

注意:有些游戏可能有反修改或反作弊机制,可能会阻止 BepInEx 或 Harmony 正常工作。这种情况下需要寻找针对该游戏的特定破解或绕过方法,这超出了 XUA 本身的范围。安装前最好在游戏社区或 Mod 站查看是否有其他玩家成功案例。

3.2 核心配置文件详解

AutoTranslatorConfig.ini是 XUA 的大脑,所有行为都由它控制。我们打开它,看看几个最关键的配置区块:

[General]区块 - 基础设置

[General] Language=zh-CN FromLanguage=ja Endpoint=GoogleTranslate
  • Language: 目标语言,即你想翻译成的语言。例如zh-CN(简体中文)、en(英文)。
  • FromLanguage: 源语言,即游戏文本的原始语言。插件会尝试自动检测,但手动指定(如ja代表日文)能提高翻译准确率。
  • Endpoint: 翻译后端。这是最重要的设置之一。GoogleTranslate是默认的免费后端(但可能受网络环境影响)。其他选项包括BaiduTranslate(需要配置 AppID/密钥)、DeepLLegitimate(需要 API 密钥,质量高但收费)等。如果留空或设为None,则禁用自动翻译,仅使用本地翻译文件。

[Behaviour]区块 - 插件行为

[Behaviour] EnableTranslation=True EnableIMGUI=False MaxCharactersPerTranslation=150 DelaySeconds=0.5
  • EnableTranslation: 总开关。
  • EnableIMGUI: 是否翻译由 IMGUI(Unity 旧版即时模式 GUI)绘制的界面。许多游戏 Mod 的配置窗口使用 IMGUI,开启此项可能会翻译这些 Mod 界面,但有时会导致冲突或显示异常,默认关闭。
  • MaxCharactersPerTranslation: 单次发送给翻译服务的最大字符数。设置得太高(如超过 400)可能被翻译服务拒绝或导致超时。建议保持在 150-300 之间。
  • DelaySeconds: 翻译请求之间的延迟秒数,用于避免对免费翻译服务请求过快导致 IP 被暂时封锁。对于 DeepL 等付费 API,可以设置得更小。

[Google]/[Baidu]/[DeepL]等区块 - 翻译服务配置如果你选择了需要认证的翻译后端,需要在这里填写相应的 API 密钥。例如使用 DeepL:

[DeepLLegitimate] ApiKey=your-deepl-api-key-here Free=False

你需要去 DeepL 官网注册账号并获取 API 密钥。Free=False表示你使用的是 DeepL 的付费 API 套餐,拥有更高的速率限制。

[Texture]区块 - 图片翻译(高级功能)这个功能允许替换游戏内的图片资源(如带文字的按钮、图标)。

[Texture] EnableTextureTranslation=False EnableTextureDumping=False TextureDirectory=Translation\Texture TextureHashGenerationStrategy=FromImageName
  • EnableTextureTranslation=True会启用图片替换。启用后,插件会尝试从TextureDirectory目录加载与游戏内图片哈希值匹配的图片文件来替换原图。
  • EnableTextureDumping=True会让插件在运行时将游戏内检测到的所有纹理图片导出到TextureDirectory这是一个调试功能,导出后务必将其改回False,否则每次运行游戏都会重新导出,严重拖慢性能并占用磁盘空间。
  • TextureHashGenerationStrategy决定如何识别图片。FromImageName是基于游戏内部资源名生成哈希,性能最好,是分发汉化补丁时的推荐选项。FromImageData是基于图片像素数据生成哈希,最准确但性能开销大。

3.3 首次运行与基础调优

配置完成后,启动游戏。进入一个有大量文本的场景(如游戏主菜单、对话界面)。XUA 会开始工作:

  1. 观察控制台/日志:如果通过 BepInEx 的BepInEx_Console启动游戏,你可以在控制台看到 XUA 的日志输出。它会显示拦截到的文本、翻译状态(缓存命中/在线翻译)、以及可能的错误信息。
  2. 使用热键
    • Alt+0: 打开/关闭翻译配置窗口。在这里可以快速切换翻译引擎、目标语言、启用/禁用翻译。
    • Alt+T: 全局切换翻译功能的开启/关闭。这是最快的“开关”。
    • Alt+R: 重新加载所有翻译文件。如果你手动修改了_AutoGeneratedTranslations.txt或其他翻译文件,按此键无需重启游戏即可生效。
  3. 检查生成的文件:进入BepInEx\translation\zh-CN\Text目录,打开_AutoGeneratedTranslations.txt。你会看到类似这样的内容:
    こんにちは=你好 開始=开始
    左边是游戏原始文本,右边是自动翻译的结果。你可以直接编辑这个文件来修正机器翻译的错误。例如,如果“開始”被错误地翻译成了“启动”,你可以手动将其改为“开始”。保存文件后,在游戏中按Alt+R重载,修改就会立即生效。

基础调优技巧

  • 解决翻译延迟:如果感觉文本出现后有明显的延迟才被翻译,可以尝试调小[Behaviour]下的DelaySeconds(如从 1.0 改为 0.3),但注意不要太小以免触发翻译服务的限流。
  • 解决翻译不完整:有些游戏文本是逐字或分块显示的。如果发现翻译只覆盖了部分文本,可以尝试开启[Behaviour]下的GeneratePartialTranslations=True。但注意,这可能会在某些游戏中导致文本重复显示,需要根据实际情况调整。
  • 解决字体显示为方框:这是最常见的问题。你需要为游戏提供中文字体。通常的步骤是:找到一个支持中文的 TMP 字体 AssetBundle 文件(社区有时会分享),将其放入游戏根目录,然后在配置文件中设置OverrideFontTextMeshPro=字体文件名(不含路径)。更复杂的情况需要自己制作字体 AssetBundle,这涉及到使用 Unity Editor 进行导出。

4. 高级应用:手动翻译、正则表达式与资源替换

当自动翻译无法满足需求,或者你想要制作一个高质量的、可供分发的汉化补丁时,就需要用到 XUA 的高级功能了。

4.1 构建高质量的手动翻译库

自动生成的翻译文件是起点,但最终质量取决于手动修正。一个好的实践是:

  1. 分离自动与手动文件:不要直接在_AutoGeneratedTranslations.txt里进行大量修改。因为这个文件每次游戏运行都可能被插件追加新的自动翻译条目,你的修改可能会被覆盖或弄乱。正确的做法是:将_AutoGeneratedTranslations.txt中翻译质量尚可或需要修正的条目,剪切出来,粘贴到一个新的.txt文件中,例如ManualTranslations.txt,并放在同一个Text文件夹内。
  2. 优先级系统:XUA 会读取Text文件夹下所有的.txt文件(包括.zip压缩包里的)。当同一个原始文本出现在多个文件中时,_AutoGeneratedTranslations.txt的优先级最低。这意味着你放在ManualTranslations.txt里的翻译会覆盖自动生成的翻译。你可以创建多个手动翻译文件来分类管理,比如Items.txt(物品)、Dialogue.txt(对话)、UI.txt(界面)。
  3. 翻译作用域(Scoping):一个翻译可能只在游戏的某个特定场景或由某个特定可执行文件触发时才适用。XUA 支持通过文件内的指令来限定翻译的作用域。
    #set level 5 ワールドマップ=世界地图 #unset level 5
    上面这段表示“ワールドマップ”翻译成“世界地图”只在地图场景(ID 为 5)生效。场景 ID 可以通过游戏内按Ctrl+Alt+NumPad7热键查看。这能有效避免翻译冲突,比如同一个词在不同上下文中含义不同。

4.2 使用正则表达式处理复杂文本

游戏文本有时并非简单的“原文=译文”一一对应。例如,一个装备描述可能是“攻击力+{value}”,其中{value}是一个动态数字。或者游戏会将多个文本片段拼接后再显示。这时就需要正则表达式(Regex)出场。

XUA 支持两种正则表达式用法:

1. 标准正则翻译(r:)直接在翻译文件中使用,用于匹配带有模式变化的文本。

r:"^獲得経験値 ([0-9]+)$"=获得经验值 $1 r:"^(.+)の攻撃!$"=$1 的攻击!

第一行匹配“獲得経験値 100”这样的文本,并将其翻译为“获得经验值 100”,其中$1代表正则捕获的第一个组(即数字部分)。 第二行匹配“スライムの攻撃!”,翻译为“史莱姆 的攻击!”。这让你可以用一条规则处理同一模式下的无数种情况。

2. 分割器正则(sr:)用于在翻译前,先将复合文本拆分成独立的片段,分别翻译后再组合回去。这对于处理游戏将物品名和数量拼接在一起的情况特别有用。

# 假设我们有一个基础翻译:ポーション=药水 ポーション=药水 # 然后我们用一个分割器正则来处理“数量 + 物品名”的格式 sr:"^([0-9]+) (.+)$"=$1 $2

当游戏显示“5 ポーション”时,插件会先用分割器正则将其拆成“5”和“ポーション”。然后“ポーション”被翻译成“药水”,最后再组合成“5 药水”。这样,你只需要定义一次“ポーション=药水”,就能应对“1 ポーション”、“10 ポーション”等各种情况,无需为每个数量都写一条规则。

警告:正则表达式非常强大,但滥用会严重拖慢翻译查找速度。务必确保正则表达式尽可能精确,避免使用过于宽泛的匹配模式(如.*),并尽量将其放在独立的、作用域明确的翻译文件中。

4.3 资源重定向实现深度汉化

对于嵌入在图片、音频或预制体(Prefab)中的文字,文本钩子无能为力。这时就需要使用资源重定向功能进行“静态替换”。

替换图片纹理:

  1. 在配置中启用[Texture]相关功能,并设置EnableTextureDumping=True
  2. 启动游戏,遍历所有游戏场景,让插件将游戏内的纹理图片导出到Translation\Texture目录。导出的图片文件名会包含哈希值,如title_logo [ABCD1234-EF567890].png
  3. 关闭EnableTextureDumping。用图像处理软件(如 Photoshop、GIMP)打开导出的图片,将其中的外文文字修改为中文。保存时务必保留原始文件名和哈希值部分
  4. 将修改后的图片放回原目录。在配置中开启EnableTextureTranslation=True
  5. 重启游戏,修改后的中文图片就会替换游戏原图。

替换文本资源(TextAsset):

  1. 在配置中启用[ResourceRedirector]下的EnableTextAssetRedirector=TrueEnableDumping=True
  2. 启动游戏,插件会将游戏加载的文本资源(如.json,.txt,.xml等配置文件)导出到Translation\{Lang}\RedirectedResources目录。
  3. 关闭EnableDumping。找到包含需要翻译文字的文本资源文件,直接编辑它们。
  4. 将编辑好的文件放回原路径(保持目录结构)。重启游戏,游戏就会加载你修改后的文本资源。

资源重定向是实现完美汉化的终极手段,因为它直接修改了游戏加载的原始数据。但操作相对复杂,且需要你对游戏的文件结构有一定了解。分发此类汉化补丁时,务必只包含你修改过的文件,并清晰地说明安装路径。

5. 开发者视角:扩展插件与二次开发

XUA 不仅仅是一个终端用户工具,它还是一个强大的开发平台,允许 Mod 作者深度集成或扩展其功能。

5.1 为其他 Mod 提供插件特定翻译

如果你开发了一个为游戏添加新物品、新对话的 Mod,你自然希望这些新内容也能被 XUA 翻译。你不需要修改 XUA 本身,而是可以利用其“插件特定翻译”功能。

  1. 创建翻译文件:在BepInEx\translation\zh-CN\Text目录下,创建一个名为Plugins的文件夹。在这个文件夹内,为你 Mod 的 DLL 文件(不含.dll扩展名)创建一个同名的文件夹。例如,如果你的 Mod 是MyAwesomeMod.dll,就创建BepInEx\translation\zh-CN\Text\Plugins\MyAwesomeMod\
  2. 放置翻译文件:将你的 Mod 的翻译文件(格式与主翻译文件相同)放入这个文件夹。你还可以在文件中添加#enable fallback指令,这表示如果在这个插件特定翻译文件中找不到某个词的翻译,可以回退到全局的(自动或手动)翻译中去查找。
  3. 通过代码注册(可选):如果你的 Mod 是动态生成文本,或者希望将翻译文件打包在 DLL 内,你可以通过 XUA 提供的 API 在运行时注册翻译包。
    // 在你的插件初始化代码中(如 Start 方法) using XUnity.AutoTranslator.Plugin.Core; // ... Stream translationStream = GetEmbeddedTranslationStream(); // 从程序集资源中获取流 var package = new StreamTranslationPackage(translationStream); TranslationRegistry.Default.RegisterPluginSpecificTranslations(typeof(MyPlugin).Assembly, package); TranslationRegistry.Default.EnablePluginTranslationFallback(typeof(MyPlugin).Assembly);
    这样,你的 Mod 就能与 XUA 无缝协作,共享翻译生态。

5.2 实现自定义翻译端点(Endpoint)

也许你对现有的翻译服务都不满意,或者有一个私有的翻译 API。XUA 允许你开发自己的翻译后端。

你需要创建一个新的 .NET 类库项目(目标框架建议 .NET 3.5 以兼容旧版 Unity),引用XUnity.AutoTranslator.Plugin.Core.dll,然后实现ITranslateEndpoint接口或继承HttpEndpoint等基类。

一个最简单的“反向翻译”示例如下:

public class ReverseTranslatorEndpoint : ITranslateEndpoint { public string Id => "ReverseTranslator"; // 配置中使用的标识符 public string FriendlyName => "文本反转器"; // 在UI中显示的名称 public int MaxConcurrency => 10; // 最大并发请求数 public int MaxTranslationsPerRequest => 1; // 单次请求最大翻译条数 public void Initialize(IInitializationContext context) { // 初始化,可以在这里读取配置、验证API密钥等 bool isEnabled = context.GetOrCreateSetting("ReverseTranslator", "Enabled", true); if (!isEnabled) throw new Exception("此翻译器已被禁用。"); } public IEnumerator Translate(ITranslationContext context) { // 模拟一个简单的翻译过程:将文本反转 string original = context.UntranslatedText; char[] charArray = original.ToCharArray(); Array.Reverse(charArray); string reversedText = new string(charArray); // 完成翻译 context.Complete(reversedText); yield break; // 因为是同步操作,直接返回 } }

编译生成的 DLL 文件,将其放入游戏目录下的BepInEx\translators文件夹(可能需要手动创建)。然后在配置文件中将Endpoint设置为ReverseTranslator,就可以使用你这个自定义的“翻译器”了。

对于需要调用 HTTP API 的翻译服务,继承HttpEndpoint基类会更方便,它帮你处理了网络请求的异步和证书验证等问题。你只需要重写OnCreateRequest来构建请求,和OnExtractTranslation来解析响应即可。

5.3 利用资源重定向 API 进行高级 Mod 开发

资源重定向器(Resource Redirector)是一个独立的库,其 API 非常强大。你可以利用它做很多事情,远不止于翻译:

  • 模型/贴图替换:拦截 3D 模型或贴图的加载,替换成自定义的版本。
  • 音频替换:替换游戏内的音效或背景音乐。
  • 动态资源修改:在资源加载到内存后,实时修改其属性。例如,修改某个材质的颜色,或者调整某个动画剪辑的速度。

基本的使用模式是注册一个钩子(Hook):

public class MyResourceMod : BaseUnityPlugin { void Awake() { // 注册一个资源加载后的钩子 ResourceRedirection.RegisterResourceLoadedHook( HookBehaviour.OneCallbackPerResourceLoaded, 100, // 优先级 OnResourceLoaded); } private void OnResourceLoaded(ResourceLoadedContext context) { // 检查加载的资源类型和路径 if (context.Parameters.Type == typeof(Texture2D) && context.Parameters.Path.Contains("special_icon")) { // 加载我们自己的纹理 Texture2D myTexture = LoadMyCustomTexture(); // 替换游戏原本要加载的纹理 context.Asset = myTexture; // 告诉重定向器我们已经处理完毕,跳过后续的钩子 context.Complete(skipRemainingPostfixes: true); } } private Texture2D LoadMyCustomTexture() { /* ... */ } }

这为游戏 Mod 开发打开了新世界的大门,允许进行深度、动态的资源定制。

6. 实战排坑:常见问题与解决方案

即使有了完善的文档,在实际使用中还是会遇到各种稀奇古怪的问题。下面是我在多年使用和帮助他人过程中总结的一些典型“坑”及其解决方法。

6.1 翻译不生效或时有时无

这是最普遍的问题。排查步骤应遵循从简到繁:

  1. 检查基础配置:确认[General]下的LanguageFromLanguage设置正确,Endpoint不是空值或None。按Alt+0确认翻译功能已启用。
  2. 查看日志:通过 BepInEx 控制台或日志文件查看 XUA 的输出。关键信息包括:“Initialized successfully”(初始化成功)、“Loaded X translations from cache”(从缓存加载了多少翻译)、“Translating ‘XXX’ via YYY”(正在通过 YYY 服务翻译 XXX)。如果没有任何日志,可能是插件根本没加载成功。
  3. 检查文本钩子兼容性:有些游戏使用非常规的文本渲染方式。尝试在配置文件中将[Behaviour]下的TextGetterCompatibilityMode设为True。这个模式会尝试用另一种方式欺骗游戏,使其认为显示的文本是未翻译的,对于某些依赖文本内容进行逻辑判断的游戏有效。
  4. 检查字体问题:如果翻译后文本区域变成空白或显示乱码,很可能是字体缺失。尝试在游戏中按Alt+0打开设置窗口,临时切换到一个非常简单的目标语言(如英语),看英文是否能显示。如果不能,基本确定是字体问题。你需要为游戏配置一个支持目标语言字符的 TMP 字体。
  5. 场景与作用域:某些翻译可能只在特定场景生效。使用Ctrl+Alt+NumPad7热键查看当前场景 ID,并检查你的翻译文件是否使用了#set level指令错误地限制了作用域。

6.2 性能问题与游戏卡顿

自动翻译是运行时操作,处理不当会影响游戏流畅度。

  1. 优化缓存:确保[Behaviour]下的EnableBatchingTrue(默认),这会将多个翻译请求合并后发送,减少网络请求次数。首次游玩时卡顿是正常的,因为所有文本都需要在线翻译并写入缓存。玩过一段时间后,缓存文件丰富起来,性能会大幅提升。
  2. 限制翻译长度:检查MaxCharactersPerTranslation值,过长的文本(如整本日记)发送到翻译服务会导致响应慢,甚至超时。建议设置在 150-300 之间。过长的文本对于游戏体验本身也意义不大,可以考虑忽略。
  3. 关闭调试功能:确保[Texture]下的EnableTextureDumpingEnableTextureScanOnSceneLoadLoadUnmodifiedTextures以及[Debug]下的EnableLog都为False。这些都是开发/调试功能,会严重消耗性能。
  4. 选择低延迟的翻译服务:如果使用免费谷歌翻译且网络不佳,可以尝试更换为BaiduTranslateLingoCloud(有道智云),它们的国内节点通常延迟更低。付费的 DeepL API 速度和稳定性都极佳。

6.3 翻译质量不佳与乱码

机器翻译毕竟不是人工。

  1. 善用替换文件(Substitutions):在_Substitutions.txt文件中,你可以定义简单的“查找-替换”规则。例如,如果游戏角色名“アリス”总是被翻译成“爱丽丝”(但你可能想要“艾莉丝”),或者“MP”被翻译成“国会议员”而不是“魔法值”,就在这里修正。格式和翻译文件一样:アリス=艾莉丝MP=魔法值。这个文件中的规则会在文本发送给翻译引擎之前应用,能从根本上纠正一些系统性误译。
  2. 后处理(Postprocessors):对于翻译引擎返回结果的一些通病,可以在_Postprocessors.txt中进行修正。例如,DeepL 翻译中文时喜欢用“—”作为破折号,但游戏字体可能显示不好,你可以添加规则将其替换为“-”。或者统一调整标点符号的全角/半角。
  3. 手动翻译优先:对于核心词汇、物品名、技能名、角色名等,务必进行精细的手动翻译,并放入独立的高优先级手动翻译文件中。这能极大提升整体翻译体验的一致性。
  4. 处理特殊编码:如果翻译后的中文显示为乱码(如“浣犲ソ”),这通常是编码问题。确保你的翻译文件以UTF-8 with BOM格式保存。大多数现代代码编辑器(如 VSCode、Notepad++)都可以在保存时选择编码格式。

6.4 分发汉化补丁的注意事项

如果你想将自己精心调校的翻译分享给其他玩家:

  1. 清理自动生成文件绝对不要直接分享包含大量自动生成条目的_AutoGeneratedTranslations.txt文件。里面可能包含你的游戏进度相关的私人文本,且未经润色,质量参差不齐。只分享你确认过、修改过的手动翻译文件(.txt或打包成.zip)。
  2. 禁用危险配置:在分享的配置文件中,务必确保以下选项为False
    • EnableTextureDumping
    • LoadUnmodifiedTextures
    • DetectDuplicateTextureNames
    • OutputUntranslatableText
    • [Debug]下的所有选项 将MaxCharactersPerTranslation设置回默认值(如 150),不要超过 400。
  3. 包含字体文件:如果你使用了自定义字体,需要将字体 AssetBundle 文件一并打包,并在说明中清晰指示放置路径和配置方法。
  4. 测试与说明:在不同游戏版本上测试你的补丁。撰写清晰的README.txt,说明安装步骤、配置方法、已知问题以及如何反馈错误。

XUnity.AutoTranslator 是一个将“不可能”变为“可能”的工具。它从底层解构了 Unity 游戏的文本和资源呈现机制,并搭建了一个高度可扩展的翻译框架。从玩家角度,它提供了即时消除语言障碍的能力;从 Modder 和开发者角度,它提供了一个强大的、可用于深度定制游戏内容的平台。掌握它,不仅意味着能玩到更多游戏,更意味着你拥有了改造游戏、创造个性化体验的钥匙。它的魅力在于,你投入的每一分精力去完善翻译、调整 UI,最终都会转化为更沉浸、更舒适的游戏时光。