文章目录
-
- 背景
- 开工前,先过三项
- 一天的拼装顺序
-
- [1. 先做门,只留下角向运动](#1. 先做门,只留下角向运动)
- [2. 再做抽屉,只留下线性运动](#2. 再做抽屉,只留下线性运动)
- [3. 接工具 Snap 槽,先管接收和占用](#3. 接工具 Snap 槽,先管接收和占用)
- [4. 用最短事件桥接一个提示](#4. 用最短事件桥接一个提示)
- [5. 最后才加移动](#5. 最后才加移动)
- 收工前,我会再走一遍反向操作
- 卡住以后,回到对应专项
- 实用总结

背景
我想先搭一个能推门、拉抽屉、放工具的小房间。
第一轮不用好看的模型。门可以是一块板,抽屉可以是一个盒子,工具也可以先拿方块代替。我想确认的是,手伸过去以后,物体能按预期运动;松开再抓,也能接着操作。
这类小场景容易卡在拼装顺序上。如果门还没转对,我就开始调抽屉;工具还拿不稳,我又给槽位加提示,等到人物开始移动,几个问题就很难分清了。
所以我给自己定了一个顺序:先确认能进头显,再验证近场抓取,然后依次做门、抽屉和工具槽。每完成一项,我都会确认它能稳定操作,再继续往下搭。
这里说的"一天",是给工作范围划线,不是保证任意工程都能当天完工。如果基础环境还没通,我就先处理基础环境,不把问题带进小房间。
本篇只管小场景的拼装次序,目标是在一天的范围内搭出能操作的门、抽屉和工具槽。相关现象按下面这张表去看对应文章:
| 你碰到的现象 | 去看哪篇 |
|---|---|
| 交互配方速查(抓走放转各三招) | 抓走转放系列20|抓走放转各三招速查:交互出问题先对上该查哪一层 |
| 门能推不能回弹 | 抓走转放系列16|门能推开却不回弹:先查转动驱动的限位与阻尼 |
| 抽屉拉一半卡住 | 抓走转放系列17|抽屉拉到一半卡住:先查滑动轴、限位和碰撞 |
| 工具放不进槽 | 抓走转放系列14|工具放不进槽或放歪了:先查过滤、对齐点和占用态 |
开工前,先过三项
我会先把房间放在伸手就能测试的位置,暂时不加移动,先确认三件事。
- 我能在目标运行方式下进入头显,看到场景,正常转动头部,手柄位姿和抓取输入也都可用。编辑器能运行,不等于目标设备这一关已经通过。
- 场景里只有一套负责当前玩家的 XR Origin。我会检查是否在导入示例预制体时,又把示例里的相机和手柄对象带进来了一份。
- 近场抓取能正常使用。我会用一个简单物体测试靠近、抓起、松开和再次抓起,先不拿门来验证,因为门还多了一层运动约束。
按 OpenXR 和 XR Interaction Toolkit(下文简称 XRIT)的分工理解,运行时、输入与交互要先各自接通。门的转轴和抽屉的行程,则是后面要处理的物体行为。
如果连测试物都抓不起来,我就不会先改门轴,也不会先调槽位范围。这一关通过以后,我会保存场景,让后面的改动有一个可以退回的起点。
一天的拼装顺序
1. 先做门,只留下角向运动
做门时,我会先确定转轴,而不是急着加把手。
我会把门框和门扇分开,让门框保持不动,门扇绕铰链位置转动。抓取区域可以放在把手附近,但抓取点并不等于转轴。
我会按下面的顺序检查:
- 先确认轴的位置和方向。门应该绕门边转动,而不是绕门板中心转动。
- 再确认开合范围。我会先把门限制在需要的角度内,不让它整圈翻过去。
- 抓取时,门仍然要遵守约束。即使手向侧面拉,门也不应变成一块可以自由移动的板子。
- 我会把门留在半开的位置,松手后再抓住继续操作,检查它是否突然跳回初始姿态。
实现时,可以用物理关节,也可以用受约束的交互驱动。我会先选定一种做法,避免普通自由抓取、关节和自写姿态脚本同时争着控制门扇。
普通 XR Grab Interactable 不会因为物体长得像门,就自动赋予它铰链行为。
门能正常开合以后,我才决定是否需要回弹。如果需要自动回位,就补上回位驱动和阻尼;如果不需要,就不把"松手后必须关门"当成验收条件。
2. 再做抽屉,只留下线性运动
确认门能正常操作以后,我再加抽屉。
抽屉和门的抓取入口可以相似,但运动约束不能照搬。门需要检查转动角度,抽屉则需要检查它沿指定轴移动的距离。
我会先做一个固定柜体,再放入一个可动抽屉。第一轮只检查下面几件事:
- 抽屉的拉动方向要使用柜体约定的局部轴。即使柜体换了朝向,抽屉也应该沿自己的滑轨移动。
- 关闭端和拉出端都要设好。抽屉推到底时不能穿进柜体,拉到底时也不能脱轨。
- 侧向位移和不需要的旋转要受到限制。手稍微拉歪一点,不应把抽屉拧成一个斜盒子。
- 我会把抽屉拉出后松手,再抓住它推回去。只有拉出和推回都能完成,才算通过这一轮检查。
在这一步,我会先关掉自动关闭、吸附到端点之类的附加效果。手动推拉还没正常工作时,加入自动行为只会让排查多一个判断分支。
门和抽屉各自通过检查以后,我再把它们放进同一个房间,确认两者互不干扰,暂时不接联动。
3. 接工具 Snap 槽,先管接收和占用
工具槽并不是摆上一个触发区域就做完了。
我会拿已经验证过抓取的测试物当工具,槽位也只做一个,先确认工具能放进去、拿出来,再放回去。
在 XRIT 中,可以从 XR Socket Interactor 这类插槽交互器入手。这里说的 Snap,是工具被接收后对齐到目标姿态的行为,不是照搬旧方案里的菜单名称。
我会先定好三条规则:
- 槽位接收什么工具,要先明确下来。我会让它只接收指定工具或指定类别,而不是允许任意可抓物体进入。
- 工具放入后应该是什么姿态,也要提前确定。我会核对槽位的对齐点和工具对应的附着点,不能只看位置对了,就忽略朝向是否正确。
- 槽位的占用状态要能跟着工具变化。工具成功进入后,槽位应记为占用;工具被拿走后,槽位应恢复空闲。
在这个小房间里,我倾向于让工具握在手里时不被槽位直接抢走,等松手后再由槽位接收。我会按这条规则,验证所用版本的选择策略和过滤配置。
工具靠近槽位时出现提示,不等于工具已经放入。进入范围、满足接收条件和实际被槽位选中,是不同的状态,不能混在一起判断。
第一轮我只检查工具是否真正归位,暂时不加声音和粒子效果。
4. 用最短事件桥接一个提示
三个物件各自能用以后,我才开始接事件。
我先不做任务系统,只做一个容易看出结果的提示:工具入槽时,旁边的提示物亮起;工具取出时,提示物恢复原状。
我会按这个顺序连接:
- 先从槽位确认接收和释放的状态变化中取事件,不用单纯的触发区域进入事件代替。
- 再通过一个小桥接脚本或 UnityEvent,把这些事件接到提示物上。
- 最后反复放入、取出工具,检查提示能否跟着状态恢复。
如果连续收到相同状态,重复设置也不应该把结果弄反。因此,我会明确设置"亮起"或"熄灭",而不是每收到一次事件就切换一次。
门和抽屉暂时不参与这个提示。等这一条事件关系确认清楚以后,我再考虑是否需要增加下一条。
5. 最后才加移动
完成前面的操作以后,我才把物件放回房间里应在的位置,并增加移动方式。
第一轮只启用一种移动方式,例如传送。连续移动、转向和其他输入组合,留到后面再加。
移动后,我会重新走一遍靠近门、拉抽屉、取工具和放工具的过程,重点检查站位变化以后,近场交互是否仍然有效,手柄输入是否与移动操作发生冲突。
如果某个问题在原地操作时就已经存在,我不会把它归到移动上。只有移动后才出现的问题,我才回头检查玩家位置和交互范围。
收工前,我会再走一遍反向操作
我不会只测一遍顺利完成的流程。收工前,我主要检查松手以后能否继续操作,以及反过来操作时是否仍然正常。
- 我会让门停在半开的位置,松手后再抓住它继续开合。如果设置了回弹,就检查回弹方向、速度和停止状态;如果没有设置,就检查它是否符合预定的自由运动或保持行为。
- 我会把抽屉从关闭位置拉出,再推回去。中途松手后,也应该能重新抓住继续操作,不能出现只能拉、不能推的情况。
- 工具放入后,槽位应该保持占用。我会再拿一个不允许的物体靠近,确认它不会把原工具挤掉。
- 工具取出后,槽位应该恢复空闲。我会把原工具再次放入,检查它是否仍然能够正确对齐。
- 我会在槽位边缘松开工具。如果工具没有成功入槽,就不应亮起"已放好"的提示,也不应留下错误的占用状态。
- 保存场景后,我会重新运行,核对初始门角度、抽屉位置、工具归属和提示状态是否一致。
这一轮不加世界缩放,XR Origin 的缩放也先保持默认比例。
缩放会让手的可达范围、碰撞尺寸和交互距离一起变得复杂。门、抽屉和槽位都还在拼装时,我不想再引入一个影响全局的变量。
卡住以后,回到对应专项
本篇只管拼装次序,不把每个排错过程重新展开。我会先分清现象,再回到对应文章核对。
- 如果门绕错轴、越过限位或回弹异常,我会去看《抓走转放系列16|门能推开却不回弹:先查转动驱动的限位与阻尼》,核对门的角向驱动。
- 如果抽屉斜着跑、行程不对或无法推回,我会去看《抓走转放系列17|抽屉拉到一半卡住:先查滑动轴、限位和碰撞》,核对抽屉的线性驱动。
- 如果工具不入槽、姿态不对或占用不释放,我会去看《抓走转放系列14|工具放不进槽或放歪了:先查过滤、对齐点和占用态》,核对工具槽的接收规则和状态。
- 如果抓住时正常,只有松手后才出现跳变、掉落或被抢走,我会回到系列中的松手专项,检查释放时的状态交接。
需要核对具体配置组合时,我会看《抓走转放系列20|抓走放转各三招速查:交互出问题先对上该查哪一层》。想理清这些能力在场景里的分工,则可以对照系列的"抓---走---放---转"总览。
如果连头显显示和基础输入都没有通过,我就回到工程与运行时的"先定层"文章,先处理基础环境,不一边排查运行问题,一边继续拼门和抽屉。
实用总结
我给一天定的目标不大:在这个小房间里,门能正常开合,抽屉能来回推拉,工具能放入槽位后再取出,提示也能跟着实际状态恢复。
为了让这些操作接得起来,我会守住前面的顺序:
- 我会先确认目标设备能运行场景,当前玩家只有一套 XR Origin,并且近场抓取已经通过测试。
- 基础交互正常以后,我再依次处理门的角向约束、抽屉的线性约束和工具槽的接收规则,不同时调三个物件。
- 三个物件各自能用以后,我只接一条工具入槽与提示之间的事件关系,最后再加入移动。
- 收工前,我会专门检查松手后的状态、槽位占用和反向操作,暂时不加入世界缩放。
我这里就总结一下:先让一个小房间里的操作从头到尾都能接上,再考虑增加内容。
如果门轴、抽屉行程、槽位规则和移动同时在改,出了问题,我很难判断该退回哪一步。每次只增加一项,并确认原来的操作仍然正常,虽然看起来慢一点,却更容易在收工时留下一个真正能用的小场景。