Unity 基础 之 实现简单监听晃动(摇一摇)手机设备震动手机设备的事件的功能
目录
Unity 基础 之 实现简单监听晃动(摇一摇)手机设备震动手机设备的事件的功能
一、简单介绍
二、知识点
三、实现原理
四、注意事项
五、实现步骤
六、关键代码
一、简单介绍
Unity中的一些基础知识点。
本节介绍,在 Unity 种,实现监听手机晃动(摇一摇)触发的事件,并震动手机的功能。
二、知识点
Unity简化了重力感应的开发, 通过访问Input.acceleration属性,取回加速度传感器的值;
Unity3D中重量的取值范围是 -1.0 到 +1.0;
X轴:home按键在下手机面朝天向右旋转90度重力分量为+1.0 向左旋转90度重力分量为-1.0
Y轴:home按键在上手机背朝自己重力分量为+1.0 home按键在下手机面朝自己重力分量为-1.0
Z轴:手机面朝地面重力分量为+1.0 手机面朝天空重力分量为-1.0
unity中使用Input.acceleration的x,y,z属性即可获得重力分量:
Input.acceleration.x; 重力感应X轴的重力分量
Input.acceleration.y; 重力感应Y轴的重力分量
Input.acceleration.z; 重力感应Z轴的重力分量
三、实现原理
1、监听 Input.acceleration.y, 重力感应Y轴的重力分量
2、当 Y轴的重力分量 变化差值查过一定数值,即可判定为晃动,触发晃动事件
四、注意事项
1、这里 监听 Input.acceleration.y, 重力感应Y轴的重力分量,你可以根据需要监听其他轴,或多轴监听产生不同效果
2、变化差值,根据需要进行调整,不唯一
五、实现步骤
1、打开 Unity ,新建工程
2、在工程中新建脚本,ShakePhoneWithVibrateWrapper 实现晃动手机触发震动的功能,MonoSingleton 单例,TestShakePhonrWithVibrateWrapper 测试 ShakePhoneWithVibrateWrapper 脚本功能
3、TestShakePhonrWithVibrateWrapper 挂载到场景中
4、打包到手机设备上测试
5、晃动(摇一摇)手机,触发 震动事件
六、关键代码
1、ShakePhoneWithVibrateWrapper
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace XANTools
{
/// <summary>
/// 摇一摇且震动手机功能
/// 知识点:
/// 1、Unity简化了重力感应的开发, 通过访问Input.acceleration属性,取回加速度传感器的值;
/// 2、首先我们看一下重力传感器的方向问题。Unity3D中重量的取值范围是 -1.0 到 +1.0;
/// </summary>
public class ShakePhoneWithVibrateWrapper : MonoSingleton<ShakePhoneWithVibrateWrapper>
{
//手机晃动的有效距离
public float Distance { get => distance;
set {
distance = Mathf.Clamp01(value);
}
}
/// <summary>
/// 初始化摇一摇功能
/// </summary>
/// <param name="shakeListener">摇一摇触发后的监听事件</param>
/// <param name="shakeSensitive">摇一摇的的敏感度(0,1)</param>
public void Init(Action shakeListener ,float shakeSensitive =0.5f)
{
shakeAction = shakeListener;
Distance = shakeSensitive;
}
void Update()
{
Shake();
}
/// <summary>
/// 摇一摇功能
/// </summary>
void Shake() {
new_y = Input.acceleration.y;
currentShakeDistance = new_y - old_y;
old_y = new_y;
if (currentShakeDistance > Distance)
{
//实现手机晃动震动效果
Handheld.Vibrate();
// 摇一摇事件
if (shakeAction != null) {
shakeAction();
}
}
}
//记录上一次的重力感应的Y值
private float old_y = 0;
//记录当前的重力感应的Y值
private float new_y;
//当前手机晃动的距离
private float currentShakeDistance = 0;
//手机晃动的有效距离
private float distance = 0.75f;
// 触发摇一摇震动后的委托事件
Action shakeAction;
}
}
2、TestShakePhonrWithVibrateWrapper
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XANTools;
public class TestShakePhonrWithVibrateWrapper : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
ShakePhoneWithVibrateWrapper.Instance.Init(() => Debug.Log("触发摇一摇震动事件"));
}
}
3、MonoSingleton
using UnityEngine;
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance = null;
private static readonly object locker = new object();
private static bool bAppQuitting;
public static T Instance
{
get
{
if (bAppQuitting)
{
instance = null;
return instance;
}
lock (locker)
{
if (instance == null)
{
// 保证场景中只有一个 单例
T[] managers = Object.FindObjectsOfType(typeof(T)) as T[];
if (managers.Length != 0)
{
if (managers.Length == 1)
{
instance = managers[0];
instance.gameObject.name = typeof(T).Name;
return instance;
}
else
{
Debug.LogError("Class " + typeof(T).Name + " exists multiple times in violation of singleton pattern. Destroying all copies");
foreach (T manager in managers)
{
Destroy(manager.gameObject);
}
}
}
var singleton = new GameObject();
instance = singleton.AddComponent<T>();
singleton.name = "(singleton)" + typeof(T);
singleton.hideFlags = HideFlags.None;
DontDestroyOnLoad(singleton);
}
instance.hideFlags = HideFlags.None;
return instance;
}
}
}
protected virtual void Awake()
{
bAppQuitting = false;
}
protected virtual void OnDestroy()
{
bAppQuitting = true;
}
}
备注:ShakePhoneWithVibrateWrapper Update 监听可能会监听不到,可以协程监听
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace XANTools
{
/// <summary>
/// 摇一摇且震动手机功能
/// 知识点:
/// 1、Unity简化了重力感应的开发, 通过访问Input.acceleration属性,取回加速度传感器的值;
/// 2、首先我们看一下重力传感器的方向问题。Unity3D中重量的取值范围是 -1.0 到 +1.0;
/// </summary>
public class ShakePhoneWithVibrateWrapper : MonoSingleton<ShakePhoneWithVibrateWrapper>
{
//手机晃动的有效距离
public float Distance { get => distance;
set {
distance = Mathf.Clamp01(value);
}
}
/// <summary>
/// 初始化摇一摇功能
/// </summary>
/// <param name="shakeListener">摇一摇触发后的监听事件</param>
/// <param name="shakeSensitive">摇一摇的的敏感度(0,1)</param>
public void Init(Action shakeListener ,float shakeSensitive =0.5f)
{
shakeAction = shakeListener;
Distance = shakeSensitive;
StartCoroutine(ShakeCor());
}
void Update()
{
//Shake();
}
IEnumerator ShakeCor() {
Debug.Log(GetType()+"/Shake Init OK ,Start to Listen/");
while (true) {
yield return new WaitForEndOfFrame();
Shake();
// 触发一次摇一摇后,间隔一定时间再次监听
if (isShake ==true)
{
yield return new WaitForSeconds(intervalShakeTime);
isShake = false;
}
}
}
/// <summary>
/// 摇一摇功能
/// </summary>
void Shake() {
new_y = Input.acceleration.y;
currentShakeDistance_y = new_y - old_y;
old_y = new_y;
new_x = Input.acceleration.x;
currentShakeDistance_x = new_x - old_x;
old_x = new_x;
if (currentShakeDistance_y > Distance || currentShakeDistance_x > Distance)
{
isShake = true;
// 摇一摇事件
if (shakeAction != null) {
shakeAction();
}
//实现手机晃动震动效果
Handheld.Vibrate();
Debug.Log(GetType() + "/Shake .../");
}
}
//记录上一次的重力感应的Y值
private float old_y = 0;
//记录当前的重力感应的Y值
private float new_y;
//当前手机晃动的距离
private float currentShakeDistance_y = 0;
//记录上一次的重力感应的X值
private float old_x = 0;
//记录当前的重力感应的X值
private float new_x;
//当前手机晃动的距离
private float currentShakeDistance_x = 0;
//手机晃动的有效距离
private float distance = 0.75f;
// 触发摇一摇震动后的委托事件
Action shakeAction;
// 是否触发
bool isShake = false;
// 触发一次的间隔时间
float intervalShakeTime = 0.1f;
}
}