一句话速览
团结引擎 1.8 打包到 iOS 26 上时,若 TMP InputField 开启了 Hide Mobile Input,输入字符后 InputField 会先失活再重新获得焦点,此时文本被全选,再输入任意字符,开头的第一个字符变成乱码。这是 Unity 2021 时代的老 Bug 在团结引擎上的复现。
一、场景:一个"本不该出问题"的输入框
故事从一个非常常规的需求开始:给 iOS 端的用户做个输入框,需要屏蔽掉系统键盘自带的输入预览条(就是那个键盘上方悬浮的白色条)。
做法也很常规——勾上 TMP_InputField 的 Hide Mobile Input(代码里就是 shouldHideMobileInput = true)。
在编辑器里测试一切正常。打包上 iOS 26 真机之后,Bug 出现了。
二、现象:精确到每一步的复现路径
预期的行为
| 步骤 | 正常应发生的事 |
|---|---|
| ① 点击输入框 | 聚焦,弹出键盘 |
| ② 输入若干字符 | 输入框正常展示字符 |
| ③ 点击输入框外部再点回来 | 光标定位到最后,继续输入正常 |
| ④ 多轮输入 | 全文无乱码,一切正常 |
实际的行为(Bug 复现路径)
| 步骤 | 实际发生的事 |
|---|---|
| ① 点击输入框 | ✅ 聚焦,键盘弹出 |
| ② 输入若干字符(如 “Hello”) | ✅ 显示正常 |
| ③ 输入框失活 → 再激活(获得焦点) | ⚠️ 文本被全选(全部高亮) |
| ④ 再输入任意字符(如 “X”) | ❌ 开头的字符变成乱码,如 “䮙ello” 或类似不可识别字符 |
这个 Bug 不是偶发——稳定复现,只要 Hide Mobile Input + 输入框经历"失活→重新聚焦"这个流程,必现。
定位线索:Unity 2021 的老 Bug
查了一圈,在 Unity 的 Bug 修复记录里找到了相似案例。这是 Unity 2021 以前版本的一个已知 Bug:Toggle 隐藏原生键盘输入显示时,TMP_InputField 的文本选择状态和键盘监听器之间存在竞态条件,导致文本缓冲区在 OnFocus 回调中被错误地部分覆盖。
按说这个 Bug 在 Unity 2021 LTS 里已经被修复了。团结引擎是基于 Unity 2021 LTS 做的二次开发,理论上不应该有这个问题。但事实就是——它在团结引擎 1.8 上复现了。
🤔 猜测:团结引擎在 iOS 键盘交互层(TouchScreenKeyboard 相关部分)做了自定义改动来适配国内分发环境,可能是这些改动把已经修好的 Bug 又带回来了。不过这只是我的推测,没有深入源码验证。
三、实战:三条应对方案及其取舍
既然 Bug 是真的,就只能找绕行方案。以下是实测可用的三条路:
方案一:不 Hide Mobile Input
最简单的,把 shouldHideMobileInput 设回 false,回归系统默认行为:
// InputField 上取消勾选 Hide Mobile Input
// 或代码里:
inputField.shouldHideMobileInput = false;
- ✅ 优点:Bug 从根源消失,代码改动最小,不需要额外引入任何库
- ❌ 代价:iOS 键盘上方那条白色的输入预览条又回来了。如果你的 UI 布局紧凑,预览条会挡住后面的内容,视觉上也不够干净
适用场景:对键盘预览条没有强烈洁癖的项目,或者布局上有足够余量避开遮挡。
方案二:不要 Select All on Reselect
保持 Hide Mobile Input 勾选,但在 InputField 上关掉 On Focus Select All(或者代码里 inputField.onFocusSelectAll = false)。
- ✅ 优点:降低问题触发概率。聚焦时不再自动全选,能绕过部分竞态路径
- ❌ 代价:“Select All” 在很多输入场景下是符合用户预期的行为(比如清空旧内容快速重输),关掉它等于牺牲了一部分交互习惯
适用场景:紧急修复、临时上线,配合定期的 DeactivateInputField / ActivateInputField 调用来降低触发率。
方案三:使用 UMI(原生输入插件)
引入 UMI(Unity Native Input Plugin / 原生输入插件),让 TMP InputField 走原生键盘通道,完全绕过 Unity 的 TouchScreenKeyboard 管理层。
- ✅ 优点:从底层规避整类问题,输入体验最贴近原生 iOS
- ❌ 代价:UMI 的原生视图会绘制在所有 Unity UI 之上。如果你的 UI 里还有全屏盖层、弹窗、动画切换,UMI 输入框会"穿模"到它们上面,视觉效果非常突兀
适用场景:可以接受"原生输入覆盖一切"的产品形态,或者输入框所在页面几乎没有层叠 UI。
方案对照表
| 方案 | 改动量 | 副作用 | 根治概率 |
|---|---|---|---|
| ① 不 Hide Mobile Input | 极小 | 键盘预览条显示 | 100% |
| ② 关 Select All on Reselect | 小 | 聚焦不自动全选,仍有残留风险 | ≈80% |
| ③ 换 UMI 插件 | 中 | 原生视图覆盖所有 Unity UI | 99% |
四、误区复盘:我踩过的坑
误区一:“Unity 2021 修过的 Bug 团结引擎肯定也有”
这件事给我最大的教训。团结引擎不是 Unity 2021 的"纯净版"——它在底层做了很多本地化修改,尤其是 iOS 适配层和国内分发通道。信任"原版已修复"等于假设团结引擎完全没有改过相关代码。基于"如果没改就别动"的假设来判断 Bug 是否存在,在 fork 类引擎上不成立。
误区二:“Hide Mobile Input 该不会是这个 Bug 的根因吧?”
我第一反应是 shouldHideMobileInput 属性本身有缺陷,考虑过用反射 Hack 它的内部字段。但仔细看了 Unity 官方的修复记录后发现——这个属性的逻辑本身是对的,问题是它触发了 TouchScreenKeyboard 内部状态机的某个边缘路径,导致文本选择与键盘缓冲区不同步。根因不在这个属性,而在属性触发的连锁反应。不要急于杀死"嫌疑人"——有时候问题出在它触发的下游,不是它自己。
误区三:“用 UMI 就万事大吉了”
UMI 解决了输入本身的问题,却引入了新的渲染层问题。“原生视图在所有 Unity UI 之上"意味着你的弹窗、Toast、全屏过渡都可能被输入框"刺穿”。在采纳第三方插件之前,一定要先跑一个"UI 层叠 + 弹窗 + 动画"的综合测试用例,确认插件在你的 UI 体系里不会引起更大的视觉问题。
五、后续
目前我选了方案二(关 Select All on Reselect)作为临时方案上线,同时在跟进团结引擎官方对这个 Bug 的修复状态。如果你的项目也遇到了,建议先记一笔、走方案一或方案二绕过,等团结引擎下一个补丁再看能否切回原生行为。
如果你在做跨引擎项目(Unity → 团结),强烈建议建立一张"已知已在原版修复、但团结上仍需验证"的清单。像这类"老 Bug 复现"坑,一次就够了。
如果你遇到过类似的"被修好又重新出现"的 Bug,欢迎在评论区分享你的经历。毕竟有些 Bug 就像老游戏的 Boss——你以为通关了,续作里换了身皮肤又回来了。