【Unity开发】控制手机移动端的震动

article/2025/6/7 14:32:22

请添加图片描述

🐾 个人主页 🐾

阿松爱睡觉,横竖醒不来
🏅你可以不屠龙,但不能不磨剑🗡

目录

  • 一、前言
  • 二、Unity的Handheld.Vibrate()
  • 三、调用Android原生代码
  • 四、NiceVibrations插件
  • 五、DeviceVibration插件
  • 六、控制游戏手柄震动
  • 七、结语

一、前言

最近开发了一个新的功能——特定情况下让手机震动,例如点击界面中的按钮,手机震动一下。这也是第一次写移动端的震动的功能,虽然unity有自带的控制移动设备震动的API,但是API太过于单一不太符合功能要求,因为他只有最简单的0.5秒的震动,不能控制震动的时长和强度。然而对于一个按钮的震动反馈来讲,0.5秒的时长有点长了。

上网查阅了大量的相关的资料,最终还不错的解决的功能的开发,所以在这里就罗列出我找到的所有能控制手机震动的API插件。

最后还有控制游戏手柄震动的API

二、Unity的Handheld.Vibrate()

这是Unity自带的API,这个方法可以触发移动设备的震动。我们直接看下使用的示例

// 判断当前设备是否支持震动(最好检查一下,万一手机不支持或者马达坏了有可能报错)
if (SystemInfo.supportsVibration)
{Handheld.Vibrate();
}
else
{Debug.Log("设备不支持震动");
}

哦对了,一般是Unity自带的API的话,也是同时支持IOS系统的,但是下面说的这个就只支持安卓系统。

三、调用Android原生代码

这个方法是直接通过调用Android的Java API来控制震动时长的,所以为什么说只支持安卓系统不支持IOS系统,就是因为直接用的Android的Java API。直接来看下下如何使用吧。

方法还是比较简单的,先创建一个用于调用Android原生代码的C#脚本:

using UnityEngine;
public class VibrationManager : MonoBehaviour
{public static void Vibrate(long milliseconds){if (Application.platform == RuntimePlatform.Android){try{using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")){using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")){using (AndroidJavaObject vibrator = currentActivity.Call<AndroidJavaObject>("getSystemService", "vibrator")){if (vibrator != null){vibrator.Call("vibrate", milliseconds);}}}}}catch (System.Exception e){Debug.LogError("VibrationManager: Error while trying to vibrate - " e.Message);}}}
}

然后就可以在需要震动的地方调用这个方法:

VibrationManager.Vibrate(1000); // 震动1000毫秒

当然你也可以直接把 Vibrate() 方法写在要使用的脚本文件中,就不用单独写一个脚本弄一个静态函数了。使用的时候就直接 Vibrate(1000) 就可以,简介明了!

四、NiceVibrations插件

我在项目中使用的插件就是这个,这个插件灵活性很高,且简单易操作,而且支持Android和IOS。
直接来说一下插件导入之后如何使用

首先要引入命名空间

using MoreMountains.NiceVibrations

然后就是在需要的地方调用代码了。

// 普通的振动
MMVibrationManager.Vibrate();// 不同模式的振动
MMVibrationManager.Haptic(HapticTypes.Selection);1.HapticTypes.Selection:极轻微振动——可用于点击按钮2.HapticTypes.Success:普通振动——可用于游戏胜利3.HapticTypes.Warning:普通振动——可用于游戏提示4.HapticTypes.Failure:普通振动——可用于游戏失败5.HapticTypes.LightImpact:轻微振动6.HapticTypes.MediumImpact:中度振动7.HapticTypes.HeavyImpact:重度振动8.HapticTypes.RigidImpact:强硬而时间稍长一些的振动9.HapticTypes.SoftImpact:柔软而时间稍长一些的振动// 瞬间振动,震动时长大致只有0.1s左右
MMVibrationManager.TransientHaptic(float intensity, float sharpness);参数:float			intensity 		强度0-1float 			sharpness		感知度0-1//还有几个默认的参数,bool 			alsoRumble = falseMonoBehaviour 	coroutineSupport = nullint 			controllerID = -1//连续的振动
MMVibrationManager.ContinuousHaptic(float intensity, float sharpness, float duration, HapticTypes fallbackOldiOS, this);
参数:float			intensity 							强度0-1float 			sharpness							感知度0-1float 			duration							持续时间HapticTypes 	fallbackOldiOS = HapticTypes.None	振动类型//控制全局的Haptic振动开启或关闭
MMVibrationManager.SetHapticsActive(true);
MMVibrationManager.SetHapticsActive(false);//获取设备是否支持Haptic振动
bool isSupported = MMVibrationManager.HapticsSupported();

除了上面的一下触发震动的操作,还有一下事件的回调可以绑定,但是仅限于 MMVibrationManager.Haptic 的震动

//OnEnable进行绑定
private void OnEnable()
{MMNViOSCoreHaptics.OnHapticPatternStopped += OnHapticsStopped;MMNViOSCoreHaptics.OnHapticPatternError += OnHapticsError;MMNViOSCoreHaptics.OnHapticPatternReset += OnHapticsReset;
}//OnDisable时解除绑定
private void OnDisable()
{MMNViOSCoreHaptics.OnHapticPatternStopped -= OnHapticsStopped;MMNViOSCoreHaptics.OnHapticPatternError -= OnHapticsError;MMNViOSCoreHaptics.OnHapticPatternReset -= OnHapticsReset;
}//振动结束
protected virtual void OnHapticsStopped()
{//一些处理逻辑
}//振动错误
protected virtual void OnHapticsError()
{//一些处理逻辑
}//振动重置
protected virtual void OnHapticsReset()
{//一些处理逻辑
}

MMVibrationManager.TransientHapticMMVibrationManager.ContinuousHaptic 的事件也有,但是比较少,只有结束事件

private void OnEnable()
{MMNViOSCoreHaptics.OnHapticPatternStopped += OnHapticsStopped;
}private void OnDisable()
{MMNViOSCoreHaptics.OnHapticPatternStopped -= OnHapticsStopped;
}//振动结束
protected virtual void OnHapticsStopped()
{}

五、DeviceVibration插件

插件的灵活度还可以,对于日常简单的开发就够用了,但是导入的时候需要自己处理一下意外情况(比如报错)。

插件里面也自带使用的示例,有一个Scene示例场景,可以打包成移动端自己测试一下,下面就是它的示例代码,看起来还是比较简介的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;namespace BrainCheck {public enum VibrationIntensity {vibrationIntensity_1,vibrationIntensity_2,vibrationIntensity_3,vibrationIntensity_4,vibrationIntensity_5,vibrationIntensity_6,vibrationWithDelay}public class DemoScript : MonoBehaviour{public VibrationIntensity myOption;void OnMouseUp() {StartCoroutine(BtnAnimation());}private IEnumerator BtnAnimation(){Vector3 originalScale = gameObject.transform.localScale;gameObject.transform.localScale = 0.9f * gameObject.transform.localScale;yield return new WaitForSeconds(0.2f);gameObject.transform.localScale = originalScale;ButtonAction();}private void ButtonAction() {switch(myOption) {case VibrationIntensity.vibrationIntensity_1:BrainCheck.VibrationIntensityBridge.vibrationIntensity_1();break;case VibrationIntensity.vibrationIntensity_2:BrainCheck.VibrationIntensityBridge.vibrationIntensity_2();break;case VibrationIntensity.vibrationIntensity_3:BrainCheck.VibrationIntensityBridge.vibrationIntensity_3();break;case VibrationIntensity.vibrationIntensity_4:BrainCheck.VibrationIntensityBridge.vibrationIntensity_4();break;case VibrationIntensity.vibrationIntensity_5:BrainCheck.VibrationIntensityBridge.vibrationIntensity_5();break;case VibrationIntensity.vibrationIntensity_6:BrainCheck.VibrationIntensityBridge.vibrationIntensity_6();break;case VibrationIntensity.vibrationWithDelay:#if UNITY_IOSBrainCheck.VibrationIntensityBridge.vibrationWithDelay(4, 6);#endif#if UNITY_ANDROIDBrainCheck.VibrationIntensityBridge.vibrationWithDelay(6000, 400);#endifbreak;}}}
}

六、控制游戏手柄震动

这个相对来说比较简单,没必要另外单独一篇文章进行讲述了,索性直接放在了一起说。

unity中的 Input.SetVibration 方法可以设置手柄的左右震动马达强度。震动强度是一个0到1之间的浮点数,其中0表示无震动,1表示最大震动强度。

直接看下示例:(以Xbox手柄为例)

using UnityEngine;
public class GamepadVibrationExample : MonoBehaviour
{void Update(){// 检测手柄按钮输入,例如按下"A"键时震动if (Input.GetKeyDown(KeyCode.JoystickButton0)) // Xbox手柄的"A"键通常对应JoystickButton0{// 设置手柄震动,左马达和右马达的震动强度分别为0.5和1.0Input.SetVibration(0, 0.5f, 1.0f);}// 检测手柄按钮输入,例如按下"B"键时停止震动if (Input.GetKeyDown(KeyCode.JoystickButton1)) // Xbox手柄的"B"键通常对应JoystickButton1{// 停止手柄震动Input.SetVibration(0, 0.0f, 0.0f);}}
}

七、结语

插件就这么多,仅供交流学习,有什么问题也欢迎再评论区留言或者私信,我看到的话会及时回复,下期见,拜拜。

请添加图片描述

请添加图片描述


http://www.hkcw.cn/article/vUBDFQVfOx.shtml

相关文章

ES101系列07 | 分布式系统和分页

本篇文章主要讲解 ElasticSearch 中分布式系统的概念&#xff0c;包括节点、分片和并发控制等&#xff0c;同时还会提到分页遍历和深度遍历问题的解决方案。 节点 节点是一个 ElasticSearch 示例 其本质就是一个 Java 进程一个机器上可以运行多个示例但生产环境推荐只运行一个…

RabbitMQ在SpringBoot中的应用

1.简单模式 P:生产者,要发送消息的程序. C:消费者,消息的接收者. Queue:消息队列,类似于一个邮箱,生产者向其中投递消息,消费者从其中取出消息. 特点:一个生产者P,一个消费者C,消息只能被消费一次,也成为点对点模式. 适用场景:消息只能被单个消费者处理. 设置队列的名称为…

基于python写的目录/文件递归检索工具

核心功能 1. 目录结构检索 递归扫描 &#xff1a;深度遍历指定目录及其所有子目录 多种检索模式 &#xff1a; 仅文件夹模式&#xff1a;只显示目录结构仅文件模式&#xff1a;只显示文件列表文件文件夹模式&#xff1a;完整显示目录树结构&#xff08;默认模式&#xff09; …

Qwen3高效微调

高效微调 场景、模型、数据、算力 高效微调的应用场景 对话风格微调&#xff1a;高效微调可以用于根据特定需求调整模型的对话风格。例如&#xff0c;针对客服系统、虚拟助理等场景&#xff0c;模型可以通过微调来适应不同的 语气、礼貌程度 或 回答方式&#xff0c;从而在与…

不动产登记区块链系统(Vue3 + Go + Gin + Hyperledger Fabric)

好久没有介绍过新项目的制作了&#xff0c;之前做的一直都是Fisco Bcos的项目&#xff0c;没有介绍过Hyperledger Fabric的项目&#xff0c;这次来给大家分享下。 系统概述 不动产登记与交易平台是一个基于Hyperledger Fabric的综合性管理系统&#xff0c;旨在实现不动产登记…

深度学习学习率调度器指南:PyTorch 四大 scheduler 对决

在深度学习模型训练中&#xff0c;学习率调度器&#xff08;Learning Rate Scheduler&#xff09;是影响模型收敛效果和训练稳定性的关键因素。选择合适的学习率调度策略&#xff0c;往往能让模型性能产生质的飞跃。本文将深入对比PyTorch中最常用的四种学习率调度器&#xff0…

ERP学习-AP

业务需要。持续更新学习进度 借助网上零搭建平台上手实操 这个是简道云平台页面链接&#xff0c;登录的化去手机号登录 目前开始对应付模块进行学习

基于 ZYNQ UltraScale+ OV5640的高速图像传输系统设计,支持国产替代

引 言 随着电子信息技术的不断进步&#xff0c;人工智能、医 疗器械、机器视觉等领域都在高速发展 [1] &#xff0c;工业相机 是机器视觉系统中的一部分 [2] &#xff0c;对工业相机而言&#xff0c;传 输图像的速率、传输过程的抗干扰能力是其关键&#xff0c; 工业相…

smartGit 试用突破30天

1 下载 选择19.1版本 2 运行 我是linux环境 解压后, cd bin ./smartgit.sh 选择使用30天. 然后退出 3 绿色软件 破解步骤 下载破解文件&#xff1a;访问 Gitee 链接 goto下载下载破解文件 解压文件&#xff1a;下载后解压得到 crackSmartGit.jar 和 license.zip 用编辑…

一、基础环境配置

一、虚拟机 主&#xff1a;192.168.200.200 从&#xff1a;192.168.200.201 从&#xff1a;192.168.200.202 二、docker docker基础搭建&#xff0c;有不会的自行百度。 1.目录结构 /opt/software&#xff1a;软件包/opt/module&#xff1a;解压包&#xff0c;自定义脚本…

Java面试八股--08-数据结构和算法篇

1、怎么理解时间复杂度和空间复杂度 时间复杂度和空间复杂度一般是针对算法而言&#xff0c;是衡量一个算法是否高效的重要标准。先纠正一个误区&#xff0c;时间复杂度并不是算法执行的时间&#xff0c;在纠正一个误区&#xff0c;算法不单单指冒泡排序之类的&#xff0c;一个…

Oracle中的循环——FOR循环、WHILE循环和LOOP循环

目录 一、FOR循环 1.FOR循环语法结构 二、WHILE循环 1.WHILE循环语法结构 三、LOOP循环 1.LOOP循环语法结构 四、三个循环的区别(重要) Oracle中的循环常用的有&#xff1a;FOR循环、WHILE循环和LOOP循环 一、FOR循环 1.FOR循环语法结构 DECLARE --不声明变量&…

ubuntu 20.04挂载固态硬盘

我们有个工控机&#xff0c;可以接入一个固态硬盘。将固态硬盘插好后&#xff0c;就要进行挂载。在AI的指导下&#xff0c;过程并不顺利。记录如下&#xff1a; 1、检查硬盘是否被识别 安装好硬盘后&#xff0c;运行以下命令来检查Linux系统是否已识别新硬盘&#xff1a; …

SAP 自动编号的使用

1、NUMBER_RANGE_ENQUEUE用于锁定编号范围对象&#xff0c;防止多用户并发访问冲突 2、NUMBER_RANGE_DEQUEUE用于解锁已维护的编号范围对象。 3、此外&#xff0c;还提到了NUMBER_GET_NEXT函数模块&#xff0c;用于获取编号范围内的下一个号码。 文章目录 创建编号范围程序实现…

Python趣学篇:从零打造智能AI井字棋游戏(Python + Tkinter + Minimax算法)

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏介绍&#xff1a;《Python星球日记》 目录 &#x1f3ae; 前言一、项目概述与技术…

[定昌linux开发板]设置密码策略

找到etc/pam.d/目录下的common-password 2.先把common-password给复制一份&#xff0c;避免改错了 可以看到新增了一个common-password.bak文件 3.打开common-password,增加密码策略 输入&#xff1a; sudo vi /etc/pam.d/common-passwod 打开common-password文件 点击&…

Godot 敌人生成半径和围墙不匹配,导致敌人错误的生成在围墙外的解决代码

一、原视频 3. Preventing Invalid Spawning 二、原代码 func get_spawn_position():var player get_tree().get_first_node_in_group("player") as Node2Dif player null:return Vector2.ZEROvar spawn_position Vector2.ZEROvar random_direction Vector2.RIG…

LabVIEW磁悬浮轴承传感器故障识别

针对工业高端装备中主动磁悬浮轴承&#xff08;AMB&#xff09;的位移传感器故障检测需求&#xff0c;基于 LabVIEW 平台构建了一套高精度故障识别系统。通过集成品牌硬件与 LabVIEW 的信号处理能力&#xff0c;实现了传感器探头故障的实时监测与精准定位&#xff0c;解决了传统…

Qt开发:QThreadPool的介绍和使用

文章目录 一、QThreadPool 简介二、常用函数简介三、完整示例 一、QThreadPool 简介 QThreadPool 是 Qt 提供的用于高效管理线程资源的类。它通过线程池的方式管理和复用线程&#xff0c;适合处理大量、短时间运行的任务&#xff0c;避免频繁创建和销毁线程带来的性能开销。 常…

蚂蚁感冒--思维

1.相遇后不用考虑转头&#xff0c;继续走就可以 2.思维&#xff0c;不只是傻傻的模拟&#xff0c;要总结出规律&#xff0c;什么情况一定可以感染&#xff0c;然后感染之后再怎么这么样 P8611 [蓝桥杯 2014 省 AB] 蚂蚁感冒 - 洛谷 #include<bits/stdc.h> using names…