一句话速览

团结引擎 1.8 打包到 iOS 26 上时,若 TMP InputField 开启了 Hide Mobile Input,输入字符后 InputField 会先失活再重新获得焦点,此时文本被全选,再输入任意字符,开头的第一个字符变成乱码。这是 Unity 2021 时代的老 Bug 在团结引擎上的复现。


一、场景:一个"本不该出问题"的输入框

故事从一个非常常规的需求开始:给 iOS 端的用户做个输入框,需要屏蔽掉系统键盘自带的输入预览条(就是那个键盘上方悬浮的白色条)。

做法也很常规——勾上 TMP_InputFieldHide 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 UI99%

四、误区复盘:我踩过的坑

误区一:“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——你以为通关了,续作里换了身皮肤又回来了。