Unity XR Interaction Toolkit实战:HTC Vive Cosmos快速搭建VR交互原型
1. 项目概述与核心价值
如果你正在用Unity开发VR应用,尤其是手头有一台HTC Vive Cosmos这样的设备,那么“如何快速搭建一个能抓、能扔、能交互的原型”这个问题,大概率是你项目启动时遇到的第一个坎。过去,我们可能需要自己写射线检测、写手柄输入映射、写物理抓取逻辑,一套流程下来,几天时间就没了,而且代码耦合度高,后期维护和扩展都是噩梦。现在,Unity官方推出的XR Interaction Toolkit(简称XRI)彻底改变了这个局面。它不是一个简单的插件,而是一套完整的、基于组件和事件驱动的交互框架,专门为Unity的XR开发量身定制。
这个项目的核心,就是利用XRI,在Unity 2023 LTS这个稳定的环境下,为HTC Vive Cosmos快速搭建一个功能完备的交互原型。我们不会去深挖那些晦涩难懂的底层API,而是聚焦于“实战”:如何通过拖拽、配置和少量的脚本,在半小时内让你的Cosmos手柄不仅能指指点点,还能真实地抓起场景中的物体,进行投掷、按压按钮等操作。这对于独立开发者、小型团队或者需要快速验证创意的项目来说,价值巨大。它能让你跳过繁琐的基础设施建设,直接进入核心玩法和体验的打磨阶段。无论是做教育模拟、虚拟展厅还是游戏Demo,一个稳定可靠的交互基础都是成功的起点。
2. 环境准备与项目初始化
2.1 Unity版本与XR插件管理
工欲善其事,必先利其器。首先,确保你使用的是Unity 2023.3 LTS或更高版本。LTS版本意味着长期支持,稳定性有保障,能避免很多因版本迭代带来的兼容性问题。打开Unity Hub,创建新的3D核心项目(Core),项目模板选择3D (Core)即可,我们不需要URP或HDRP的复杂性,标准渲染管线在原型阶段完全够用。
项目创建后,第一件事是打开Package Manager。Unity的插件生态已经全面转向Package Manager管理,我们需要从这里安装所有必要的包。点击左上角的“+”号,选择“Add package by name...”。首先,我们必须安装XR Plugin Management。这是Unity管理所有XR设备(包括Cosmos)的基石。输入com.unity.xr.management并安装。安装完成后,你会在Project Settings里看到一个新的“XR Plug-in Management”选项。
接下来,我们需要为HTC Vive Cosmos安装对应的Provider。在Package Manager中,切换到“Unity Registry”视图,搜索并安装OpenXR Plugin。是的,你没看错,对于HTC Vive Cosmos,在Unity的新架构下,我们主要通过OpenXR这个跨平台的开放标准来对接。安装后,回到Project Settings -> XR Plug-in Management,勾选“Initialize XR on Startup”,然后在“OpenXR”子项下,你需要添加正确的交互配置文件。对于Cosmos手柄,通常选择“Microsoft Motion Controller Profile”或“HTC Vive Controller Profile”都能获得良好的支持,你可以都试试看哪个映射更准确。
2.2 XR Interaction Toolkit的安装与导入
核心主角登场。在Package Manager中,搜索并安装XR Interaction Toolkit。建议安装当前最新的稳定版本(例如2.5.x)。这个包体积不小,因为它包含了从输入系统、射线交互、直接交互(抓取)到UI事件等一系列完整功能。
安装完成后,Unity可能会提示你导入“Starter Assets”。这是一个非常实用的资源包,我强烈建议你点击导入。它包含了预设好的XR Origin预制体、几种常见的手部模型、以及一套已经配置好基本交互功能的示例场景和脚本。对于新手来说,这能节省大量配置时间,让你直观地理解各个组件是如何协同工作的。导入后,你可以在Assets/XR Interaction Toolkit/StarterAssets/路径下找到它们。
注意:如果你在导入Starter Assets或后续操作中,遇到脚本编译错误,提示某些命名空间找不到(比如
UnityEngine.InputSystem),这通常是因为缺少输入系统包。请回到Package Manager,搜索并安装Input System包。XR Interaction Toolkit 2.0之后重度依赖新的Input System来处理输入,安装后根据提示重启编辑器即可。
2.3 连接并测试HTC Vive Cosmos
在软件层面配置好后,就是硬件连接。确保你的HTC Vive Cosmos头显通过串流盒正确连接到PC,基站已通电并覆盖你的游戏区域,手柄也充好电。在Unity编辑器中,点击播放按钮前,先戴上头显。
此时,你应该能在Game视图中看到头显渲染的内容。如果画面是分裂的双屏或者全黑,请检查:
- OpenXR插件是否已启用并选择了正确的运行时(通常SteamVR会自动接管)。
- 电脑上是否安装了最新的SteamVR。
- 确保SteamVR已启动并能正常识别到Cosmos设备。
手柄的输入测试,我们可以用一个简单的方法:在场景中创建一个空的GameObject,挂上XR Controller组件(来自XRI)。在播放模式下,观察该组件上“Input Actions”折叠栏下的各项参数,当你按动手柄上的按键、扳机或摇杆时,对应的值会发生变化。这能快速验证输入系统是否工作正常。
3. 构建可交互的VR角色(XR Origin)
3.1 理解XR Origin的架构
在XRI的体系里,XR Origin是整个VR玩家在虚拟世界中的化身和根节点。它不再是我们过去熟悉的“Camera Rig”那种简单结构,而是一个层次清晰、职责分明的模块化预制体。
一个标准的XR Origin通常包含以下层级:
- XR Origin (GameObject): 根节点,挂载
XROrigin脚本。负责管理整个VR身体的移动范围(如基于基站边界的移动)和坐标系。 - Camera Offset: 一个子物体,通常用于施加额外的垂直偏移(比如模拟身高),或者作为平滑移动的父节点。
- Main Camera: 真正的摄像机物体,挂载
Camera组件和Tracked Pose Driver组件(用于同步头显位置旋转)。 - Left/Right Hand Controller: 分别代表左右手的空物体,各挂载一个
XR Controller组件。这个组件是连接物理手柄和虚拟交互功能的关键桥梁。
Starter Assets里提供的XR Origin (VR)预制体已经为我们搭建好了这个结构。我建议你直接将它拖入场景,并删除场景自带的Main Camera,以避免渲染冲突。
3.2 配置手柄控制器与视觉模型
拖入XR Origin后,展开其子物体,找到LeftHand Controller和RightHand Controller。每个上面的XR Controller组件都需要指定控制器类型(Left/Right)和输入源。在“Input Actions”配置部分,我们需要将物理按键映射到XRI定义的动作上。
这里就是新手容易迷糊的地方。XRI使用Unity的新Input System,其映射关系定义在Input Action Asset中。幸运的是,Starter Assets已经为我们准备好了一个:XRI Default Input Actions.inputactions。你可以在Project Settings -> XR Interaction Toolkit -> Project 中找到它并被默认引用。这意味着,我们XR Controller组件上的“Input Actions”配置,可以直接使用这个Asset中预设好的Action,例如“Select”(抓取/选择)对应手柄的扳机键,“UI Press”对应触摸板点击等。
接下来是为手柄添加视觉模型。单纯的两个XR Controller物体在场景里是不可见的。我们需要代表手的模型。你可以使用Starter Assets提供的Hands_Base模型,也可以从Asset Store下载更精美的手部模型。将手部模型预制体拖拽成为LeftHand Controller或RightHand Controller的子物体。关键一步:需要在这个手部模型物体上添加XR Controller组件吗?不需要!视觉模型只是跟随父级XR Controller运动。你只需要确保手部模型的初始位置和旋转调整正确,使其自然地位于手柄握持的位置。
更高级的做法是添加ActionBasedController组件(它是XR Controller的增强版)和XR ControllerState组件,这样可以更精细地控制手柄的震动(Haptic)反馈和模型动画(例如根据扳机扣压程度驱动手指弯曲)。
3.3 实现基础的射线交互
射线交互是VR中远距离操作UI或物体的标准方式。在XRI中实现它非常简单。
- 选中你的右手控制器物体(
RightHand Controller)。 - 在Inspector中点击“Add Component”,搜索并添加
XR Ray Interactor。 - 同时,为了能看到射线,还需要添加一个
XR Interactor Line Visual组件。
XR Ray Interactor负责从控制器发射一条射线,检测可交互物体。XR Interactor Line Visual则负责渲染这条射线,你可以在这里设置射线的颜色、渐变、宽度,甚至是终点处的光标样式。
现在运行场景,你应该能看到从右手控制器发射出的一条射线。当你用射线指向场景中的物体时,暂时还不会有任何反应,因为我们还没有给物体添加“可被交互”的属性。这引出了XRI的核心交互模式:Interactor(交互器)和Interactable(可交互物)的配对。我们的XR Ray Interactor就是一个交互器,下一步我们来创建可交互物。
4. 创建可抓取与可交互的物体
4.1 理解Interactable与抓取模式
在XRI中,任何想要被交互的物体,都必须挂载XR Grab Interactable组件。这个组件定义了物体如何被交互器(手或射线)“抓取”。
创建一个简单的Cube作为测试物体,为其添加XR Grab Interactable组件。你会看到几个重要的属性:
- Interaction Layer Mask: 交互层掩码。这是一个优化和过滤机制。你可以为Interactor和Interactable分配不同的交互层(在Edit -> Project Settings -> Physics 中定义Layer),只有层匹配时才能交互。在原型阶段,我们可以先设为“Everything”。
- Grab Transform: 抓取变换。当物体被抓起时,这个Transform会与交互器的抓取点对齐。如果不指定,默认使用物体自身的Transform。
- Attach Transform: 附加变换。这是物体上实际与手部“连接”的点。你可以创建一个空的子物体(如“AttachPoint”)并将其拖入这里,这样抓取时物体就会以这个子物体的位置为准与手柄对齐,实现更自然的握持感(比如抓剑柄而不是剑的中心)。
- Movement Type: 移动类型。这是抓取物理的核心,有三种:
- Instantaneous: 瞬时移动。物体瞬间“吸附”到手上,无视物理。简单粗暴,适合UI或轻量级交互,但缺乏真实感。
- Kinematic: 运动学移动。物体通过设置
Rigidbody.isKinematic = true来跟随手部运动,完全受脚本控制,不会与其它运动学或静态物体发生物理碰撞,但会触发触发器。这是最常用、最稳定的方式,能提供不错的抓取手感。 - Velocity Tracking: 速度跟踪。物体保持其
Rigidbody.isKinematic = false,通过计算所需的速度和角速度来尝试跟随手部运动。这能产生最真实的物理效果(比如抓取时会因为惯性晃动),但也最难调优,容易产生抖动或穿透。
对于快速原型,我强烈推荐使用Kinematic模式。它稳定、可靠,并且能很好地与场景中的其他物理物体(非运动学)产生碰撞。
4.2 配置抓取与投掷的物理属性
为了让抓取和投掷感觉自然,我们需要正确配置物体的Rigidbody(刚体)组件。XR Grab Interactable会自动为物体添加刚体,但默认参数可能需要调整。
- Mass(质量): 根据物体的大小和材质感设置。一个木箱可以设为5,一个乒乓球可以设为0.1。质量影响投掷的惯性。
- Drag(阻力)和Angular Drag(角阻力): 这两个值模拟空气阻力。对于希望投掷后快速停下的物体(如纸团),可以设高一些(如3)。对于希望滑动很远的物体(如冰壶),可以设低一些(如0.05)。
- Interpolate(插值): 建议设为“Interpolate”。这能平滑物体在物理更新间的运动,减少视觉上的抖动,尤其是在抓取和投掷时。
- Collision Detection(碰撞检测): 对于快速运动的物体,建议使用“Continuous”或“Continuous Dynamic”,以防止高速穿透薄碰撞体。
XR Grab Interactable组件上还有几个关键属性:
- Throw Velocity Scale和Throw Angular Velocity Scale: 投掷速度/角速度缩放系数。当物体被释放时,XRI会根据手部释放瞬间的速度,乘以这个系数,赋予物体一个初速度。默认值1通常比较合适,如果你想做出“超人投掷”的效果,可以调高。
- Retain Transform Parent: 是否保留父级变换。如果勾选,物体被抓起时会脱离原来的层级父物体;释放时,如果原父物体还在,会尝试回去。这对于从货架上拿取物品很有用。
4.3 实现高级交互:按钮、杠杆与抽屉
除了简单的抓取,XRI还通过XR Simple Interactable组件支持无需抓取的直接交互,例如按压、悬停、选择。这对于制作按钮、开关、拉杆等UI或机关元素非常有用。
制作一个可按压的3D按钮:
- 创建一个扁平的Cylinder作为按钮。
- 移除或禁用其
Rigidbody和XR Grab Interactable(如果不需要被抓取)。 - 添加
XR Simple Interactable组件。 - 在组件的事件(Events)折叠栏下,你会看到
OnHoverEntered,OnHoverExited,OnSelectEntered,OnSelectExited等UnityEvent。 - 例如,我们可以监听
OnSelectEntered事件(当射线指住它并扣下扳机时触发)。点击“+”号,将按钮自身拖入对象框,选择函数“Transform.Translate”,设置一个向下的偏移量(如(0, -0.05, 0)),模拟按下的动画。再为OnSelectExited事件设置一个向上的偏移,让按钮弹回。
制作一个可抓取并旋转的阀门或杠杆:这需要结合抓取和旋转限制。我们可以使用Unity的Configurable Joint(可配置关节)。
- 创建一个阀门模型,添加
Rigidbody和XR Grab Interactable。 - 添加一个
Configurable Joint组件,将其Connected Body设为阀门基座(一个静态的Collider)。 - 在关节的“Angular X/Y/Z Motion”中,锁定不需要旋转的轴(如X和Z),将Y轴设为“Limited”或“Free”,并设置角度限制。这样,抓取阀门旋转时,它就会绕Y轴在限定范围内转动。
制作一个带阻尼滑动的抽屉:同样使用Configurable Joint,但这次控制线性移动。
- 创建抽屉模型和柜体。抽屉添加
Rigidbody和XR Grab Interactable。 - 给抽屉添加
Configurable Joint,Connected Body设为柜体。 - 锁定Y和Z轴的线性移动(Linear Y/Z Motion -> Locked),将X轴设为“Limited”。设置抽屉滑动的最大最小位置。
- 调整关节的
X Drive属性,设置Position Spring(位置弹簧,恢复力)和Position Damper(位置阻尼,阻力)。一个较高的阻尼(如50)能让抽屉滑动起来有真实的阻滞感,不会乱晃。
通过这些组合,你几乎可以构建出任何常见的物理交互物件。
5. 交互反馈与用户体验优化
5.1 视觉反馈:高亮与状态指示
没有反馈的交互是令人困惑的。当用户的手或射线指向一个可交互物体时,它应该给出明确的视觉提示。
悬停高亮:
XR Simple Interactable和XR Grab Interactable都自带悬停事件。最常用的方法是通过改变材质颜色来实现高亮。- 为你的物体创建两个材质:一个默认材质,一个高亮材质(如发光或改变颜色)。
- 在物体的
MeshRenderer组件上,通过脚本或在OnHoverEntered/Exited事件中,动态切换材质。 - 更优雅的方式是使用Shader Graph或可视化脚本工具(如Unity的Visual Scripting)来动态修改材质属性(如
_EmissionColor),性能更好。
抓取状态变化:当物体被抓取时,可以改变其外观。监听
XR Grab Interactable的OnSelectEntered/Exited事件。例如,被抓取时,可以轻微放大物体、改变其透明度,或者在其周围显示一个抓取轮廓。
5.2 触觉(Haptic)反馈
手柄震动是VR沉浸感的重要来源。XRI通过XR Controller组件可以轻松触发震动。 在XR Grab Interactable的OnSelectEntered事件中,我们可以发送一个震动指令:
// 这是一个示例,通常你会写在一个单独的脚本中并挂载到物体上 using UnityEngine.XR.Interaction.Toolkit; public class GrabHapticFeedback : MonoBehaviour { [SerializeField] private XRBaseInteractable interactable; [SerializeField] private float amplitude = 0.5f; // 震动强度 (0~1) [SerializeField] private float duration = 0.2f; // 震动时长 void OnEnable() { if (interactable != null) { interactable.selectEntered.AddListener(OnGrabbed); } } void OnDisable() { if (interactable != null) { interactable.selectEntered.RemoveListener(OnGrabbed); } } private void OnGrabbed(SelectEnterEventArgs args) { if (args.interactorObject is XRBaseControllerInteractor controllerInteractor) { controllerInteractor.xrController.SendHapticImpulse(amplitude, duration); } } }你可以将这段脚本挂到可抓取物体上,并将物体的XR Grab Interactable组件拖拽赋值给interactable变量。这样,每次抓取时,对应的手柄就会产生一次短促的震动。同理,你可以在物体与其他物体碰撞、按钮被按下时触发不同强度和模式的震动。
5.3 音频反馈
声音是另一维度的反馈。为交互动作添加音效能极大提升真实感。
- 抓取/释放音效:在
XR Grab Interactable的OnSelectEntered和OnSelectExited事件上,挂载AudioSource.PlayOneShot()方法,播放对应的抓取和释放音效。 - 碰撞音效:在物体的
Rigidbody组件上,或者通过单独的脚本监听OnCollisionEnter事件,根据碰撞的相对速度来播放不同轻重的撞击声。可以使用AudioSource.PlayClipAtPoint在碰撞点生成一个临时的音源。
5.4 优化交互体验的实用技巧
- 交互距离与角度容差:在
XR Grab Interactable上,调整Grab Distance(抓取距离)和Grab Angle Tolerance(抓取角度容差)。对于大物体,可以增加抓取距离,让用户不需要把手完全伸进物体里。角度容差可以允许用户从稍微倾斜的角度也能成功抓取。 - 双手抓取与缩放:默认情况下,一个
XR Grab Interactable只能被一个交互器抓取。如果你想实现双手抓取并缩放物体(比如放大一张地图),需要启用Allow Multiple Grab选项,并自己编写脚本,根据两个抓取点的位置变化来计算物体的缩放和旋转。 - 交互优先级与屏蔽:通过
Interaction Layer Mask和Interaction Priority(交互优先级)属性,可以控制当多个交互器同时指向一个物体时,谁优先响应。例如,你可以设置直接用手触碰(Direct Interactor)的优先级高于射线交互(Ray Interactor),这样当手靠近物体时,会自动从射线切换为直接抓取。 - 防止手部模型穿模:为手部模型添加一个简单的
Sphere Collider或Capsule Collider,并设置为Trigger。当手部模型与场景物体发生穿透时,可以通过脚本轻微调整手部模型的位置或透明度,提示用户。
6. 调试、打包与性能考量
6.1 利用XR Debug辅助工具
XRI提供了一些内置的调试工具,在开发时非常有用。在Game视图左上角的“Display 1”下拉菜单中,你可以选择“XR Interaction Debugger”。这个调试器窗口会实时显示所有活跃的Interactor和Interactable,以及它们当前的状态(如悬停、选择),是排查交互逻辑问题的利器。
另外,在XR Ray Interactor组件上,你可以启用“Debug Visualizations”,它会在Scene视图中绘制出射线的检测范围和命中点,方便你调整射线参数。
6.2 为HTC Vive Cosmos打包构建
当原型开发完毕,准备打包成可执行文件时,需要注意以下几点:
- 构建设置:打开File -> Build Settings。确保你的场景已被添加到“Scenes In Build”列表中。选择目标平台为“PC, Mac & Linux Standalone”。
- Player Settings:点击“Player Settings”,在“Resolution and Presentation”中,建议取消勾选“Run in Background”,并设置一个合适的默认窗口尺寸。在“XR Plug-in Management”部分,再次确认OpenXR已启用。
- SteamVR兼容性:由于Cosmos通常通过SteamVR运行,确保你的项目中也安装了
SteamVR Plugin(从Asset Store或OpenXR的扩展中获取)可能有助于解决一些特定的输入或渲染问题。但在Unity 2023 + OpenXR的流程下,通常不是必须的。 - 构建与运行:点击Build,生成.exe文件。首次运行时,可能会由SteamVR自动启动。如果遇到手柄输入失灵,检查SteamVR的控制器绑定(Controller Binding)设置,确保为你的应用加载了正确的绑定配置(通常XRI的默认输入Action能自动映射)。
6.3 性能优化要点
VR应用对性能极其敏感,必须保证稳定的高帧率(如90Hz)。
- Draw Call与面数:使用Unity的Profiler(Window -> Analysis -> Profiler)和Frame Debugger监控性能瓶颈。合并静态物体的网格和材质,使用LOD(Level of Detail)组来简化远处物体的面数。
- 物理更新开销:过多的动态刚体和复杂碰撞体会严重消耗CPU。尽量将静态环境设为
Static,使用简单的碰撞体(Box, Sphere)代替Mesh Collider。对于Velocity Tracking抓取模式的物体,数量要严格控制。 - 交互器更新:每个
XR Ray Interactor每帧都会进行射线检测。如果场景中有大量不需要一直交互的物体,可以考虑动态启用/禁用射线交互器,或者使用更高效的检测方法(如Sphere Cast)。 - 脚本优化:避免在
Update方法中进行复杂的计算或频繁的FindGameObjectWithTag等操作。使用事件驱动,将计算结果缓存起来。
7. 常见问题排查与解决方案实录
在实际操作中,你几乎一定会遇到下面这些问题。这里是我踩过坑后总结的速查表:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 手柄在场景中无反应,按键无效 | 1. OpenXR运行时未正确启动或选择。 2. Input System动作映射错误或丢失。 3. XR Controller组件未激活或控制器类型设置错误。 | 1. 检查Project Settings -> XR Plug-in Management,确保OpenXR启用,并尝试重启SteamVR和Unity编辑器。 2. 检查 XR Controller组件上的Input Action引用是否正确指向XRI Default Input Actions中的动作。可以尝试手动拖拽赋值。3. 确认控制器物体本身是Active的,且Controller属性设置为“Left”或“Right”。 |
| 射线可以看见,但无法与物体交互 | 1. 物体未添加XR Grab Interactable或XR Simple Interactable组件。2. Interactor和Interactable的Interaction Layer Mask不匹配。 3. 物体或交互器被其他UI元素遮挡(Canvas的渲染模式)。 | 1. 为需要交互的物体添加对应的Interactable组件。 2. 检查两者Layer Mask设置,在原型阶段可先都设为“Everything”。 3. 如果使用World Space的UI,确保UI Canvas的Event Camera已正确设置。 |
| 物体被抓取时剧烈抖动或穿透 | 1. 抓取模式(Movement Type)选择不当。 2. 物体的Rigidbody属性(尤其是Mass、Drag)设置不合理。 3. 物理更新帧率与渲染帧率不同步。 | 1. 对于需要稳定抓取的物体,优先使用Kinematic模式。 2. 适当增加物体的Mass和Drag值。为Rigidbody启用Interpolation。 3. 在Project Settings -> Time中,尝试将Fixed Timestep调小(如0.008),但注意会增加CPU负担。 |
| 抓取物体后,手部模型与物体穿模 | 1. Attach Transform未设置或位置不对。 2. 手部模型的碰撞体未正确设置。 | 1. 在可抓取物体上创建一个空的子物体作为Attach Point,并将其拖拽到XR Grab Interactable的Attach Transform字段,调整该子物体的位置使其与手部握持点对齐。2. 为手部模型添加一个Trigger碰撞体,并编写简单的脚本,在抓取时轻微调整手部位置或透明度。 |
| 打包后运行,头显内显示不正常(如单眼显示、扭曲) | 1. 玩家设置中的单通道立体渲染未正确启用。 2. SteamVR与OpenXR运行时冲突。 | 1. 在Player Settings -> XR Plug-in Management -> OpenXR下,确保“Stereo Rendering Mode”设置为“Single Pass Instanced”(性能最佳)。 2. 尝试在SteamVR的设置中禁用“SteamVR Home”,或确保Unity项目使用的是OpenXR而非已弃用的“Windows XR”插件。 |
| UI(Canvas)无法用射线点击 | 1. Canvas的渲染模式不是“World Space”。 2. Canvas上没有 XR UI Input Module组件或Tracked Device Graphic Raycaster组件。3. Event Camera未设置。 | 1. 将Canvas的Render Mode改为“World Space”。 2. 为Canvas添加 Tracked Device Graphic Raycaster组件。在场景中创建一个EventSystem对象,并将其上的Input Module替换为XR UI Input Module。3. 将XR Origin中的Main Camera拖拽到Canvas的Event Camera字段。 |
最后,分享一个我个人的调试习惯:在开发初期,我会创建一个简单的“调试面板”,用UI Text实时显示左右手柄的按键状态、位置、旋转以及当前悬停/抓取的物体名。这比单纯看Console日志要直观得多,能帮你快速定位输入和交互逻辑的问题。实现起来也不难,写个脚本挂在Canvas上,从ActionBasedController组件读取输入动作的值即可。这个习惯让我在排查那些“时灵时不灵”的交互问题时,效率提升了不止一倍。
