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

news2025/7/23 16:45:53

请添加图片描述

🐾 个人主页 🐾

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

目录

  • 一、前言
  • 二、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-1
		float 			sharpness		感知度0-1
		//还有几个默认的参数,
		bool 			alsoRumble = false
		MonoBehaviour 	coroutineSupport = null
		int 			controllerID = -1

//连续的振动
MMVibrationManager.ContinuousHaptic(float intensity, float sharpness, float duration, HapticTypes fallbackOldiOS, this);
参数:
		float			intensity 							强度0-1
		float 			sharpness							感知度0-1
		float 			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_IOS
				  BrainCheck.VibrationIntensityBridge.vibrationWithDelay(4, 6);
				#endif
				#if UNITY_ANDROID
				  BrainCheck.VibrationIntensityBridge.vibrationWithDelay(6000, 400);
				#endif
			      break;
			}
	    }
	}
}

六、控制游戏手柄震动

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

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.0
            Input.SetVibration(0, 0.5f, 1.0f);
        }
        // 检测手柄按钮输入,例如按下"B"键时停止震动
        if (Input.GetKeyDown(KeyCode.JoystickButton1)) // Xbox手柄的"B"键通常对应JoystickButton1
        {
            // 停止手柄震动
            Input.SetVibration(0, 0.0f, 0.0f);
        }
    }
}

七、结语

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

请添加图片描述

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2399158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cesium快速入门到精通系列教程二:添加地形与添加自定义地形、相机控制

一、添加地形与添加自定义地形 在 Cesium 1.93 中添加地形可以通过配置terrainProvider实现。Cesium 支持多种地形数据源&#xff0c;包括 Cesium Ion 提供的全球地形、自定义地形服务以及开源地形数据。下面介绍几种常见的添加地形的方法&#xff1a; 使用 Cesium Ion 全球地…

python学习打卡day43

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 浙大疏锦行 数据集使用猫狗数据集&#xff0c;训练集中包含猫图像4000张、狗图像4005张。测试集包含猫图像1012张&#xff0c;狗图像1013张。以下是数据集的下…

Microsoft Word使用技巧分享(本科毕业论文版)

小铃铛最近终于完成了毕业答辩后空闲下来了&#xff0c;但是由于学校没有给出准确地参考模板&#xff0c;相信诸位朋友们也在调整排版时感到头疼&#xff0c;接下来小铃铛就自己使用到的一些排版技巧分享给大家。 注&#xff1a;以下某些设置是根据哈尔滨工业大学&#xff08;威…

windows安装多个版本composer

一、需求场景 公司存在多个项目&#xff0c;有的项目比较老&#xff0c;需要composer 1.X版本才能使用 新的项目又需要composer 2.X版本才能使用 所以需要同时安装多个版本的composer二、下载多个版本composer #composer官网 https://getcomposer.org/download/三、放到指定目…

【办公类-22-05】20250601Python模拟点击鼠标上传CSDN12篇

、 背景需求: 每周为了获取流量券,每天上传2篇,获得1500流量券,每周共上传12篇,才能获得3000和500的券。之前我用UIBOT模拟上传12篇。 【办公类-22-04】20240418 UIBOT模拟上传每天两篇,获取流量券,并删除内容_csdn 每日任务流量券-CSDN博客文章浏览阅读863次,点赞18…

贪心算法应用:边着色问题详解

贪心算法应用&#xff1a;边着色问题详解 贪心算法是一种在每一步选择中都采取当前状态下最优的选择&#xff0c;从而希望导致结果是全局最优的算法策略。边着色问题是图论中的一个经典问题&#xff0c;贪心算法可以有效地解决它。下面我将从基础概念到具体实现&#xff0c;全…

ck-editor5的研究 (2):对 CKEditor5 进行设计,并封装成一个可用的 vue 组件

前言 在上一篇文章中—— ck-editor5的研究&#xff08;1&#xff09;&#xff1a;快速把 CKEditor5 集成到 nuxt 中 &#xff0c;我仅仅是把 ckeditor5 引入到了 nuxt 中&#xff0c;功能还不算通用。 这一篇内容将会对其进行设计&#xff0c;并封装成可复用的 vue 组件&…

Java-redis实现限时在线秒杀功能

1.使用redisson pom文件添加redisson <!--redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.4</version></dependency> 2.mysql数据库表设…

simulink mask、sfunction和tlc的联动、接口

这里全部是讲的level2 sfunction&#xff08;用m语言编写&#xff09;&#xff0c;基于matlab 2020a。 1.mask的参数操作 1&#xff09;mask通过set_param和get_param这2个函数接口对mask里面定义的Parameters&Dialog的参数的大部分属性进行读写&#xff0c;一般是Value值…

VMWare安装常见问题

如果之前安装过VMWare软件&#xff0c;只要是 15/16 版本的&#xff0c;可以正常使用的&#xff0c;不用卸载&#xff01;&#xff01;&#xff01; 如果之前安装过&#xff0c;卸载了&#xff0c;一定要保证通过正常的渠道去卸载&#xff08;通过控制面板卸载软件&#xff09…

【北邮 操作系统】第十二章 文件系统实现

一、文件的物理结构 1.1 文件块、磁盘块 类似于内存分页&#xff0c;磁盘中的存储单元也会被分为一个个“块/磁盘块/物理块”。很多操作系统中&#xff0c;磁盘块的大小与内存块、页面的大小相同 内存与磁盘之间的数据交换(即读/写操作、磁盘I/0)都是以“块”为单位进行的。即…

Docker 插件生态:从网络插件到存储插件的扩展能力解析

Docker 容器技术以其轻量、快速、可移植的特性,迅速成为构建和部署现代应用的核心工具。然而,尽管 Docker Engine 自身功能强大,但在面对多样化的生产环境和复杂业务需求时,仅靠核心功能往往无法满足所有场景。 例如,跨主机的容器网络通信、异构存储系统的持久化数据管理…

WordPress搜索引擎优化的最佳重定向插件:进阶指南

在管理网站时&#xff0c;我们经常需要调整网页地址或修复错误链接。这时&#xff0c;通过重定向不仅能有效解决这些问题&#xff0c;还能显著提升网站在搜索引擎中的排名。对于熟悉基础重定向插件的用户来说&#xff0c;一些功能更强大的工具可以帮助你更全面地管理网站&#…

org.junit.runners.model.InvalidTestClassError:此类问题的解决

不知道大家是否遇见过以上这种情况&#xff0c;我也是今天被这个错误搞得很烦&#xff0c;后来通过网上查找资料终于找到了问题所在————就是简单的Test注解的错误使用 Test注解的注意情况 &#xff1a;1 权限必须是public 2 不能有参数 3 返回值类型是void 4 本类的其他的…

用户管理页面(解决toggleRowSelection在dialog用不了的隐患,包含el-table的plus版本的组件)

新增/编辑/删除/分配角色&#xff0c;图片上传在此文章分类下另一个文章 1.重点分配角色&#xff1a; <template><!-- 客户资料 --><div class"pageBox"><elPlusTable :tableData"tableData" :tablePage"tablePage" onSi…

Linux-GCC、makefile、GDB

GCC gcc -E test.c -o test.i预处理(-o指定文件名) gcc -S test.i -o test.s编译gcc -c test.s -o test.o汇编gcc test.o -o test链接(生成一个可执行程序的软连接) gcc test.c -o test一条指令可以完成以上所有内容 gcc *.c -I(大写的i) include由于在main.c中找不到当前文件…

[MySQL初阶]MySQL(7) 表的内外连接

标题&#xff1a;[MySQL初阶]MySQL(7)表的内外连接 水墨不写bug 文章目录 一. 内连接 (INNER JOIN)二. 外连接 (OUTER JOIN)关键区别总结 三、 如何选择 在 MySQL 中&#xff0c;连接&#xff08;JOIN&#xff09;用于根据两个或多个表之间的相关列组合行。内连接&#xff08;I…

【R语言编程绘图-mlbench】

mlbench库简介 mlbench是一个用于机器学习的R语言扩展包&#xff0c;主要用于提供经典的基准数据集和工具&#xff0c;常用于算法测试、教学演示或研究场景。该库包含多个知名数据集&#xff0c;涵盖分类、回归、聚类等任务。 包含的主要数据集 BostonHousing 波士顿房价数据…

检索器组件深入学习与使用技巧 BaseRetriever 检索器基类

1. BaseRetriever 检索器基类 在 LangChain 中&#xff0c;传递一段 query 并返回与这段文本相关联文档的组件被称为 检索器&#xff0c;并且 LangChain 为所有检索器设计了一个基类——BaseRetriever&#xff0c;该类继承了 RunnableSerializable&#xff0c;所以该类是一个 …

【Doris基础】Doris中的Replica详解:Replica原理、架构

目录 1 Replica基础概念 1.1 什么是Replica 1.2 Doris中的副本类型 2 Doris副本架构设计 2.1 副本分布机制 2.2 副本一致性模型 3 副本生命周期管理 3.1 副本创建流程 3.2 副本恢复机制 4 副本读写流程详解 4.1 写入流程与副本同步 4.2 查询流程与副本选择 5 副本…