下载 App
求助

Bug 反馈:Web 平台无法输入中文(IME 组合事件未到达 SDL)

06/0464 浏览BUG反馈

问题描述

我在开发一款 DND 风格的回合制策略 RPG,项目中有一个 F9 快捷键调出的 UI 编辑器(NanoVG 即时模式渲染),编辑器中有文本输入功能(备注字段、重命名等)。
遇到的问题是:在 Web 平台上,所有文本输入框(包括自定义 NanoVG 编辑器和引擎自带的 urhox-libs/UITextField 组件)都无法输入中文。英文字符输入正常,但切换到中文输入法后,无论使用何种 IME(微软拼音、搜狗等),都没有任何字符被输入。粘贴中文内容同样无效。
关键事实:此功能以前是正常工作的。在某次引擎构建更新后失效。
horizontal linehorizontal line

排查过程

第一步:排除编辑器代码问题

最初怀疑是 F9 编辑器代码拆分时引入的 bug(编辑器从单文件拆为 UIEditor.lua / UIEditorDraw.lua / UIEditorInput.lua / UIEditorData.lua 四文件)。
为了验证,编写了独立的 IME 测试脚本,仅使用引擎自带的 UI.TextField 组件,完全不涉及 F9 编辑器代码:
lua复制
lua
local UI = require("urhox-libs/UI") local textField = UI.TextField { placeholder = "在此输入中文测试...", onChange = function(self, value) print("onChange: " .. value) end, }
测试结果UI.TextField 同样无法输入中文。英文正常、粘贴英文正常、粘贴中文无效、中文输入法无效。
结论:不是编辑器代码的问题,是引擎平台层面的问题。

第二步:编写运行时诊断工具

由于 Web 平台无法同时打开 F12 DevTools 和游戏页面(打开 DevTools 会关闭游戏),编写了屏幕叠加诊断工具 scripts/tools/IMEDiag.lua,使用 NanoVG 在游戏画面上直接渲染输入事件日志。
诊断工具订阅了以下引擎事件:
  • KeyDown — 按键按下
  • KeyUp — 按键抬起
  • TextInput — 文本输入(已提交的字符)
  • TextEditing — IME 组合文本(拼音候选等)

第三步:采集诊断数据

通过诊断工具在运行时实际观察到以下行为:
horizontal linehorizontal line

诊断数据与发现

运行时环境状态

screenKeyboardSupport = false    (平台报告不支持屏幕键盘)
screenKeyboardVisible = true     (SDL 认为 TextInput 已激活)
GetPlatform() = "Web"

发现 1:英文输入完全正常

当系统输入法处于英文模式时,每次按键都会产生一对完整事件:
KeyDown: key=100 scancode=7 qual=0    (D键按下)
TextInput: "d" [64]                    (收到字符 'd')
英文字母、数字、符号、退格、回车均正常工作。

发现 2:Ctrl+Space IME 切换组合键被浏览器拦截

按下 Ctrl+Space 切换输入法时,诊断工具只收到 Ctrl 的 KeyDown 事件:
KeyDown: key=1073742048 scancode=224 qual=2 (左Ctrl按下)
Space 的 KeyDown 事件从未出现。浏览器在操作系统层面拦截了 Ctrl+Space 组合键用于 IME 切换,不会将 Space 传递给 Canvas/SDL。
但用户确认:系统任务栏的输入法图标确实发生了变化,说明 OS 层面的 IME 切换成功了。

发现 3:IME 激活后所有事件消失

切换到中文输入法后,在游戏中按任何键:
  • 没有 KeyDown 事件
  • 没有 TextInput 事件
  • 没有 TextEditing 事件(IME 组合事件)
完全静默。诊断日志不再有任何新条目。
即使切回英文模式(通过 Shift 或再次 Ctrl+Space),英文字符也不再出现,直到重新点击 Canvas 获取焦点。

发现 4:SetScreenKeyboardVisible 是空操作

lua复制
lua
input:SetScreenKeyboardVisible(true) -- 无效果 input:SetScreenKeyboardVisible(false) -- 无效果
由于 screenKeyboardSupport = false,这两个调用在 Web 平台上是完全空操作。SDL 层面的 SDL_StartTextInput() / SDL_StopTextInput() 实际上没有执行(或执行了但没有效果)。

发现 5:UI.TextField 组件同样受影响

引擎自带的 urhox-libs/UI/Widgets/TextField.lua 内部调用的也是 input:SetScreenKeyboardVisible(true),因此同样无法触发 IME。这排除了任何应用层代码的问题。
horizontal linehorizontal line

我尝试过的修复

尝试 1:移除所有 SetScreenKeyboardVisible(false) 调用

理论:可能某处代码调用了 SetScreenKeyboardVisible(false) 导致 SDL_StopTextInput 永久关闭了 IME。
结果:移除所有 false 调用后,问题不变。

尝试 2:在文本框获得焦点时仅调用一次 SetScreenKeyboardVisible(true)

理论:可能需要主动触发 SDL_StartTextInput 来聚焦隐藏的 textarea。
结果:问题不变。screenKeyboardSupport=false 导致此调用是空操作。

尝试 3:从 Lua 层寻找 JavaScript 互操作 API

搜索了 .emmylua/engine-docs/urhox-libs/ 所有目录,查找任何 JS 桥接、eval、emscripten 相关 API。
结果:引擎不暴露任何 JavaScript 互操作接口到 Lua 层。无法从 Lua 代码手动创建/聚焦 HTML input 元素。
horizontal linehorizontal line

问题根因分析

基于以上诊断数据,问题的根因是:
SDL/Emscripten 层的隐藏 textarea 没有正确接收浏览器的 IME 组合事件。
在 Web 平台上,IME 组合事件(compositionstart / compositionupdate / compositionend)只会发送给当前 focused 的 <input><textarea> 元素。SDL 的 Emscripten 后端通常会创建一个隐藏的 textarea 来接收这些事件,然后转化为 SDL 的 SDL_TEXTEDITINGSDL_TEXTINPUT 事件。
当前的表现说明以下情况之一:
  1. SDL 的隐藏 textarea 没有被创建
  2. 或创建了但没有获得浏览器 focus
  3. SDL_StartTextInput() 因为某种原因没有被调用(screenKeyboardSupport=false 可能导致跳过了 textarea 创建逻辑)
  4. 或浏览器/Emscripten SDK 更新后改变了事件传递行为
证据支持urhox-libs/UI/Widgets/TextField.lua 第 593-598 行有以下注释:
lua复制
lua
-- Web + touch: browser paste event via hidden input already injects TextInput, -- skip DoPaste to avoid double-paste.
这说明引擎设计上确实依赖一个隐藏 input 元素来桥接浏览器事件。但当前这个机制失效了。
horizontal linehorizontal line

这个问题的更广泛影响

对所有 Web 项目的影响:这不是个别项目的问题。任何在 Web 平台上需要中文输入的 UrhoX 项目都会受到影响,包括使用引擎自带 UI.TextField 组件的项目。
对开发者的影响
  • 需要中文输入的游戏功能(聊天、角色命名、编辑器文本字段等)在 Web 平台完全不可用
  • 此问题在 Lua 层面没有 workaround — 没有 JS 互操作接口可以手动修复
  • 排查成本高 — 需要编写自定义运行时诊断工具才能确认原因(Web 平台无法同时使用 DevTools)
对玩家的影响:任何需要输入中文的交互(角色命名、聊天等)对中文用户完全不可用。
horizontal linehorizontal line

期望的修复方向

  1. 确认 Emscripten 后端是否正确创建了隐藏 textarea 用于 IME 输入
  2. 确认 SDL_StartTextInput() 在 Web 平台是否正确聚焦该 textarea
  3. 检查 screenKeyboardSupport 返回 false 是否错误地跳过了 textarea 创建/聚焦逻辑
  4. 验证浏览器 compositionstart / compositionupdate / compositionend 事件是否能正确触发 SDL_TEXTEDITING / SDL_TEXTINPUT
horizontal linehorizontal line

诊断脚本说明

诊断工具位于 scripts/tools/IMEDiag.lua,在游戏运行时通过 NanoVG 在屏幕左下角渲染半透明日志面板,实时显示所有输入事件(KeyDown/KeyUp/TextInput/TextEditing)。进入 F9 编辑器时自动激活。
IME 功能验证测试脚本位于 scripts/tools/IMETest.lua,使用 UI.TextField 组件提供独立的输入测试环境。

03:06
为了不被斩杀,我只能做到这些了截图
为了不被斩杀,我只能做到这些了
之前一直申请不到计划3,之前说太花哨,后面说体量完成度不足,在我一番小作文下,编辑终于给了我解答,什么原生质感,玩家开局体验啥的。 本来计划2也够用,准备以后再优化了,结果计划2赠送的积分要砍半了,学生党实在消费不起,于是只能再冲一波计划3了 从周六中午到现在一天半时间,优化了一遍角色卡,战斗卡,还有抽卡界面,优化了新手教程,该说不说确实比之前要舒服些。 前半部分为新版,后半部分为旧版。 明天再次
25 赞
6 回复
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
65 赞
20 回复
01:27
《大二暑假,我用AI做了一款属于自己的游戏》截图
《大二暑假,我用AI做了一款属于自己的游戏》
本人自制游戏现已加入taptap封闭测试(仅适配安卓机型)欢迎大家前来尝试(八月十号可以正式开始游玩) 如果有建议或者bug反馈可以加入qq群928501443 #发现好游戏 #游戏日常 #浅评一下 #今天游戏圈发生了啥
3 赞
【创作资源申请】冒险日记截图
【创作资源申请】冒险日记
冒险日记 — 游戏简介 类型:3D 战棋策略 RPG 视角:俯视 平台:TapTap(横屏) 游戏链接: 一、游戏定位 D&D世界观的慢节奏跑团模拟器。玩家扮演一名冒险者队长,经营佣兵小队,在五年的职业生涯中从无名新手成长为传奇英雄。 ----------------------------------------------------------------------------------
7 赞
3 回复
如何提升你游戏中的UI美术水平截图
如何提升你游戏中的UI美术水平
一、请为你的游戏挑选一款合适的字体 很多开发者没有注意到其实UI界面中最重要的元素是字体,一款合适的字体能给整个游戏的界面感官带来蜕变。 请看案例 那么如何挑选适合自己的字体呢? 我总结出了一些小经验可供参考: 黑体:通用 宋体:古风、武侠、修仙 楷体:古风、武侠、修仙 圆体:卡通、动漫、Q版 科技:科幻、未来、电子 顺手分享一个免费可商用字体网站: 当然 如果你不知道自己的游戏适合什么风格
精华
121 赞
44 回复
AI 生成的 NPC 太假?那是你没给它注入“灵魂” | TapTap 制造截图
AI 生成的 NPC 太假?那是你没给它注入“灵魂” | TapTap 制造
在多人或竞技游戏中,如何让 AI 队友不呆板?如何在高延迟下实现丝滑的竞技体验?本期我们采访了《猛攻兄弟》与《飞驰登山拉力赛车》的作者,分享他们的经验之谈~ 2026/03/30 - 2026/4/6 本期核心看点: 数据概览:该周上架游戏中动作策略模拟类持续领跑优质分发榜,占比均达 43.08%。 重点关注:让 AI 像活人,让同步“零延迟” —— 多人竞技开发实战 避坑指南:人工测评准入与分
精华
26 赞
6 回复
开发第六天截图
开发第六天
重新改了玩法,并对46%内容细节进行了设定。 后台跑模拟了,玩法看似能走通。 但是考虑到数据本身的问题。 明天开始制造第一个demo。
2 赞
1 回复
开发心得-界面布局心得截图
开发心得-界面布局心得
大家好,我正在用 TapTap 制造制作一款2D 治愈林间徒步旅行游戏《徒步荒野》。 我分享一下我的开发心得,希望能有用,下面是一些界面布局的心得。 第一步:定版式、操作 先确定游戏是横版还是竖版、需要哪些操作按钮,敲定整体玩法思路。 我的玩法灵感参考《边境之旅》,主打散步看风景、沿途触发随机事件。 原版是 3D,考虑到自己是新手,选择2D 横版街机式来做,制作更简单、好上手。 第二步:敲定全局美
6 赞
2 回复
「游戏上新」秦王的游戏截图
「游戏上新」秦王的游戏
你是秦王嬴政身边的廷臣。 方士徐福献上一匣【帝王卡牌】,四张凶牌封死命运: 屠戮|淫欲|奢华|征伐 七日死限,必须一一折断卡牌对应的欲望任务。 办不成? 秦王殿上长剑出鞘,君臣性命,顷刻倾覆。 ⚔游戏核心玩法 ▪回合卡牌策略,抉择牵动秦廷朝堂势力 ▪朝堂派系博弈:王权、法家、军功贵族、方士暗流角力 ▪多重结局:功成辅秦王一统,或是任务失败血染咸阳宫 ▪随机事件触发,每一局嬴政的猜忌程度截然
4 赞
2 回复
01:13
【游戏自荐】《王朝崛起》——一个人做的2D骑马砍杀,但真的上头截图
【游戏自荐】《王朝崛起》——一个人做的2D骑马砍杀,但真的上头
略沙盒,玩法硬核,还在修bug,但真的上头 先声明:我不是托,是开发者自己来安利的。如果你喜欢《骑马与砍杀》那种从零拉起部队、跑商、招降将领、攻城叛变的玩法,那这款游戏大概率会对你的胃口。 一、这游戏玩什么? · 超大的2D沙盒地图:64座城市 + 128个村庄,四大势力割据,满地图的蛮族部落。· 动态世界 & AI:AI势力之间会自己宣战、结盟、叛变;武将忠诚度低了会自立为王,最多能冒出8个新势
9 赞
7 回复