玩过手游崩坏3的应该会发现游戏里面的UI 界面还有一些场景 会根据 玩家手机的平衡状态对UI或者相机进行位移或者旋转。
今天我们要使用移动端的重力感应,做类似的效果,来增加UI界面的流动感。
其实就是通过移动端的重力感应获得一个 三维向量,然后根据这个向量,对目标 UI 进行 旋转,位移 等等操作。
1. 首先我们先了解移动端手机陀螺仪的向量方向。首先,水平拿着手机,有Home键的一端右手拿。然后,由于图可知,绿线X轴就是垂直向上的线,Y轴就是水平向左的线。而Y轴就是伸向手机屏幕里面的线。在你左右前后摇动手机的时候。Unity 可以通过 Input.acceleration
获取一个Vector3,用来记录这三个值的变化。记住,这三个值的取值都在 -1
到 1
.
2. 既然,知道了怎么获取手机的陀螺仪的变化。那么,通过这个值我们用来控制UI或者其他任何对象。
3. 但是,要让Unity 的UI 进行位移,旋转变化的话。还得先设置点东西。
首先找到 UI画布的Canvas
组件。修改Render Mode
为Screen Space-Camera
.并且指定相应的的Camera
。进行这一步操作,你的UI 才可以进行正确的位移和旋转。
4. 其次呢。就是逻辑了。我们在这里是运用手机的X轴
的变化来改变tager
对象的Y轴
旋转,X轴
移动; Y轴
的变化来改变tager
对象的X轴
旋转,Y轴
移动;Z轴
的变化只去改变tager
对象的Z轴
位置。
5. 剩下的就比较简单了,就是代码了,所以老规矩上脚本吧。代码没有优化,比较智障,请平复一下心情再看。
using System;
using UnityEngine;
[Serializable]
public class SetUp
{
[Tooltip("敏感度")]
public float sensitivity = 15f; //敏感度
[Tooltip("最大水平移动速度")]
public float maxturnSpeed = 35f; // 最大移动速度
[Tooltip("最大垂直傾斜角移动速度")]
public float maxTilt = 35f; // 最大倾斜角
[Tooltip("位移加成速率")]
public float posRate = 1.5f;
}
public class MobileScreenOrientation : MonoBehaviour
{
public enum MotionAxial
{
All = 1, //全部轴
None = 2,
x = 3,
y = 4,
z = 5
}
public enum MotionMode
{
Postion = 1, //只是位置辩护
Rotation = 2,
All = 3 //全部变化
}
//就是这里比较笨了。本来使用UnityEditor类库的多选功能。但是这个类库不支持移动平台。
public MotionAxial motionAxial1 = MotionAxial.y;
public MotionAxial motionAxial2 = MotionAxial.None;
public MotionMode motionMode = MotionMode.Rotation; //运动模式
public SetUp setUp;
public GameObject tager; //被移动的对象
Vector3 m_MobileOrientation; //手机陀螺仪变化的值
Vector3 m_tagerTransform;
Vector3 m_tagerPos;
public Vector3 ReversePosition = Vector3.one; //基于陀螺仪方向的取反
void Awake()
{
Screen.orientation = ScreenOrientation.Landscape;
m_tagerTransform = Vector3.zero;
m_tagerPos = Vector3.zero;
}
void LateUpdate()
{
if (tager == null)
return;
m_MobileOrientation = Input.acceleration;
if (motionAxial1 == MotionAxial.None && motionAxial2 == MotionAxial.None) //不操作任何轴
return;
else if (motionAxial1 == MotionAxial.x && motionAxial2 == MotionAxial.None) // X轴
{
m_tagerTransform.x = Mathf.Lerp(m_tagerTransform.x, m_MobileOrientation.y * setUp.maxTilt * ReversePosition.x, 0.2f);
}
else if (motionAxial1 == MotionAxial.y && motionAxial2 == MotionAxial.None) //Y 轴
{
m_tagerTransform.y = Mathf.Lerp(m_tagerTransform.y, -m_MobileOrientation.x * setUp.maxturnSpeed * ReversePosition.y, 0.2f);
}
else if (motionAxial1 == MotionAxial.z && motionAxial2 == MotionAxial.None) // z轴
{
m_tagerTransform.z = Mathf.Lerp(m_tagerTransform.z, -m_MobileOrientation.z * setUp.maxTilt * ReversePosition.z, 0.2f);
}
else if (motionAxial1 == MotionAxial.x && motionAxial2 == MotionAxial.y) // X和Y轴
{
m_tagerTransform.y = Mathf.Lerp(m_tagerTransform.y, -m_MobileOrientation.x * setUp.maxturnSpeed * ReversePosition.y, 0.2f);
m_tagerTransform.x = Mathf.Lerp(m_tagerTransform.x, m_MobileOrientation.y * setUp.maxTilt * ReversePosition.x, 0.2f);
}
else if (motionAxial1 == MotionAxial.y && motionAxial2 == MotionAxial.x) // Y和X轴
{
m_tagerTransform.y = Mathf.Lerp(m_tagerTransform.y, -m_MobileOrientation.x * setUp.maxturnSpeed * ReversePosition.y, 0.2f);
m_tagerTransform.x = Mathf.Lerp(m_tagerTransform.x, m_MobileOrientation.y * setUp.maxTilt * ReversePosition.x, 0.2f);
}
else if (motionAxial1 == MotionAxial.x && motionAxial2 == MotionAxial.z) // x 和 Z 轴
{
m_tagerTransform.x = Mathf.Lerp(m_tagerTransform.x, m_MobileOrientation.y * setUp.maxTilt * ReversePosition.x, 0.2f);
m_tagerTransform.z = Mathf.Lerp(m_tagerTransform.z, -m_MobileOrientation.z * setUp.maxTilt * ReversePosition.z, 0.2f);
}
else if (motionAxial1 == MotionAxial.z && motionAxial2 == MotionAxial.x) // Z 和 X 轴
{
m_tagerTransform.x = Mathf.Lerp(m_tagerTransform.x, m_MobileOrientation.y * setUp.maxTilt * ReversePosition.x, 0.2f);
m_tagerTransform.z = Mathf.Lerp(m_tagerTransform.z, -m_MobileOrientation.z * setUp.maxTilt * ReversePosition.z, 0.2f);
}
else if (motionAxial1 == MotionAxial.y && motionAxial2 == MotionAxial.z) // Y和Z 轴
{
m_tagerTransform.y = Mathf.Lerp(m_tagerTransform.y, -m_MobileOrientation.x * setUp.maxturnSpeed * ReversePosition.y, 0.2f);
m_tagerTransform.z = Mathf.Lerp(m_tagerTransform.z, -m_MobileOrientation.z * setUp.maxTilt * ReversePosition.z, 0.2f);
}
else if (motionAxial1 == MotionAxial.z && motionAxial2 == MotionAxial.y) // Z和 Y轴
{
m_tagerTransform.y = Mathf.Lerp(m_tagerTransform.y, -m_MobileOrientation.x * setUp.maxturnSpeed * ReversePosition.y, 0.2f);
m_tagerTransform.z = Mathf.Lerp(m_tagerTransform.z, -m_MobileOrientation.z * setUp.maxTilt * ReversePosition.z, 0.2f);
}
else if (motionAxial1 == MotionAxial.All && motionAxial2 == MotionAxial.All) // 所有轴向都运动
{
m_tagerTransform.y = Mathf.Lerp(m_tagerTransform.y, -m_MobileOrientation.x * setUp.maxturnSpeed * ReversePosition.y, 0.2f);
m_tagerTransform.x = Mathf.Lerp(m_tagerTransform.x, m_MobileOrientation.y * setUp.maxTilt * ReversePosition.x, 0.2f);
m_tagerTransform.z = Mathf.Lerp(m_tagerTransform.z, m_MobileOrientation.z * setUp.maxTilt * ReversePosition.z, 0.2f);
}
m_tagerPos.x = m_tagerTransform.y;
m_tagerPos.y = -m_tagerTransform.x;
m_tagerPos.z = m_tagerTransform.z;
if (motionMode == MotionMode.Postion)
{
tager.transform.localPosition = Vector3.Lerp(tager.transform.localPosition, m_tagerPos * setUp.posRate, Time.deltaTime * setUp.sensitivity);
}
else if (motionMode == MotionMode.Rotation)
{
tager.transform.localRotation = Quaternion.Lerp(tager.transform.localRotation, Quaternion.Euler(m_tagerTransform), Time.deltaTime * setUp.sensitivity);
}
else
{
tager.transform.localPosition = Vector3.Lerp(tager.transform.localPosition, m_tagerPos * setUp.posRate, Time.deltaTime * setUp.sensitivity);
tager.transform.localRotation = Quaternion.Lerp(tager.transform.localRotation, Quaternion.Euler(m_tagerTransform), Time.deltaTime * setUp.sensitivity);
}
}
}
6. 赶紧把脚本挂在Canvas
对象上面,然后指定tager
。打包到手机上面,测试测试吧。
效果展示:
我是李本心明
首先谢谢大家的支持,其次如果你碰到什么其他问题的话,欢迎来 我自己的一个 讨论群559666429
来(扫扫下面二维码或者点击群链接 Unity3D[ 交流] ),大家一起找答案,共同进步。
由于工作生活太忙了,对于大家的帮助时间已经没有之前那么充裕了。如果有志同道合的朋友,可以接受无偿的帮助别人,可以加我QQ单独联系我,一块经营一下。