本文实现一个常见的 Unity 手机交互:检测到摇一摇后,更新提示、通知业务,再调用 Handheld.Vibrate() 提供震动反馈。检测采用 Input.acceleration 的三轴变化量,并用冷却时间减少一次晃动连续触发的问题。
示例使用传统 Input Manager 和 Unity UI(Button、Text),面向 Android / iOS 手机。API 说明按 Unity 2022.3 文档核对;本次没有执行 Unity 编译或真机测试,阈值需要按设备、帧率和握持方式调整。
摇一摇效果
下面是原文保留的效果图,不是本次新增代码的运行结果:

晃动检测原理:比较三轴加速度变化量
Input.acceleration 返回设备加速度计最近一次的三轴读数,单位是 g。它会受到设备姿态与重力影响,不能简单把某个轴的绝对读数当成“正在摇手机”。Unity 移动设备输入说明
这个基础示例比较相邻两次读取的向量差:
1 | Vector3 delta = currentAcceleration - previousAcceleration; |
向量长度可以覆盖三个轴的正反方向变化。若只想检测 y 轴,可以使用 Mathf.Abs(currentAcceleration.y - previousAcceleration.y),但会漏掉其他方向。
shakeThreshold 是晃动检测阈值,不控制震动马达强度,也没有固定的 [0, 1] 范围。相邻读数的差还受传感器采样和帧率影响;此算法不是严格的动作识别,快速转动手机也可能触发。要求更稳定时,需要按采样时间处理数据、加入滤波或分析一段时间内的运动;新 Input System 可参考 传感器文档。
完整 C# 示例:三轴检测与触发冷却
保存为 Test.cs,挂到场景中的 GameObject。BtnShake 和 Tip 都可选:前者用于单独测试震动,后者显示晃动提示。业务代码可订阅 Shaken 事件,或在 OnShake 中接入处理。
1 | using System; |
| 参数 | 初始示例值 | 调整方向 |
|---|---|---|
shakeThreshold |
0.5 |
误触发多时提高;轻晃不触发时降低,需要真机调参 |
cooldownSeconds |
0.5 秒 |
限制两次触发的最小间隔,持续晃动仍可能每隔一段时间触发 |
BtnShake |
可不绑定 | 按钮只触发震动,用于把马达反馈与传感器检测分开排查 |
Tip |
可不绑定 | 使用传统 Unity UI Text;TextMeshPro 项目需替换字段类型 |
第一帧仅保存读数,避免把初始姿态和零向量的差误判成摇动;恢复前台时重新取基准。冷却期间仍更新上次读数,且冷却使用 Time.unscaledTime,不会因 Time.timeScale 改变间隔。
如何接入场景
- 将
Test.cs挂到一个启用的 GameObject。 - 如果要看 UI 提示,创建 Canvas 与 Text,将 Text 拖到
Tip字段;按钮拖到BtnShake字段。 - 此代码使用旧输入接口。使用新版 Unity 时,检查 Player Settings 的 Active Input Handling 包含 Input Manager;若仅启用新 Input System,应改用对应传感器接口。
- 在目标手机上先点击按钮检查震动,再向不同方向晃动检查日志与 UI。编辑器里鼠标操作不能验证手机传感器或马达。
震动反馈与不震动时的排查
Handheld.Vibrate() 不接收阈值、强度或时长参数;摇一摇检测成功,也不代表硬件一定产生可感知的震动。震动细节受平台和系统设置影响,需要定制反馈时通过原生接口实现。Unity Handheld.Vibrate API
| 现象 | 检查顺序 |
|---|---|
| 点击按钮也不震动 | 真机是否支持震动;系统设置;Android 最终 Manifest 的 android.permission.VIBRATE;平台调用日志 |
| 按钮能震动,但摇动没反应 | 组件是否启用;SystemInfo.supportsAccelerometer;输入后端;输出读数和 delta,检查阈值 |
| 正向能触发、反向不能触发 | 是否仍在使用原文的 offset > shakeStrength 单向判断;改用绝对值或向量长度 |
| 一次晃动触发多次 | 增加冷却;确认场景中没有多个检测组件;持续晃动需要额外的动作结束判定 |
| 旋转姿态就误触发 | 加速度读数包含姿态影响;提高阈值或引入滤波,按设备实际采样调试 |
Android 震动权限定义见 Manifest.permission.VIBRATE。权限检查不能替代对目标设备的实际验证。
真机验证要点
记录 Unity 版本、输入后端、手机型号、系统版本、阈值和冷却时间,再检查以下场景:静置、各轴正反方向晃动、连续晃动、慢速转动、切到后台后恢复,以及不绑定 UI 时的行为。本文没有声称这些场景已通过;原效果图也不能作为新示例的验证证据。
相关阅读
- Unity C# 与 Android 原生交互(1)
- Unity C# 与 Android 原生交互(2)
- Unity C# 与 Objective-C 交互
- 目录及资源路径规范整理(03)
- 设计模式-单例模式
附录:原文 y 轴单向检测代码
以下保留原代码及注释用于对照。原注释写“x坐标”,实际读取的是 y;“震动强度为 [0, 1]”的注释也不正确,shakeStrength 在这里是检测阈值。该片段没有取绝对值、没有冷却,不能作为上面改进版的替代实现。两段代码的类名都叫 Test,接入时只使用前面的完整示例。
1 | /// x坐标晃动监听 |