实现鼠标在屏幕上拖拽,物体或者摄像机惯性滑动的效果:
问题分解:在惯性滑动效果中,鼠标拖动物体移动分为俩个阶段
- drag移动阶段,此时鼠标或者手指未离开屏幕,物体跟随手指移动
- 惯性移动阶段,此时物体继续保持一个速度,并且速度持续衰减直到速度等于0,相当于做一个减速运动
所以有伪代码:
if(drag移动)
{
//获取鼠标位置
//物体移动到鼠标位置
}
else
{
//物体进行减速运动
}
具体代码:
using UnityEngine;
public class Test : MonoBehaviour
{
//上次鼠标位置
Vector2 prevMousePos = Vector3.zero;
//滑动结束时的瞬时速度
Vector3 Speed = Vector3.zero;
//每帧偏差
Vector3 offSet = Vector3.zero;
//鼠标开始位置
Vector3 startMousePosition = Vector3.zero;
//速度衰減率
public float decelerationRate = 0.1f;
public Camera m_camera;
void Update()
{
HandleMouseInput();
}
private void HandleMouseInput()
{
//按下时记录位置
if (Input.GetMouseButtonDown(0))
{
prevMousePos = Input.mousePosition;
startMousePosition = Input.mousePosition;
}
//移动时更新位置
if (Input.GetMouseButton(0))
{
Vector3 curMousePosition = Input.mousePosition; //当前鼠标的屏幕坐标系
//偏差值
offSet = m_camera.ScreenToWorldPoint(curMousePosition) - m_camera.ScreenToWorldPoint(prevMousePos);
//直接移动
transform.localPosition += offSet;
prevMousePos = curMousePosition;
//瞬时速度
Speed = offSet / Time.deltaTime;
}
else //最后递减
{
Speed *= Mathf.Pow(decelerationRate, Time.deltaTime);
Debug.Log("Current Speed" + Vector3.Magnitude(Speed));
if (Mathf.Abs(Vector3.Magnitude(Speed)) < 1)
Speed = Vector3.zero;
transform.localPosition += Speed * Time.deltaTime;
}
}
}
speed表示物体移动的瞬时速度,通过每帧的offset/每帧时间,得到每帧的瞬时速度,
手松开瞬间的速度,之后就要通过速度衰减去实现惯性滑动效果了。
如果想移动摄像机呢,就需要修改下代码
最终代码如下:
using UnityEngine;
public class Test : MonoBehaviour
{
public enum MoveMode
{
cam,
obj,
}
//上次鼠标位置
Vector2 prevMousePos = Vector3.zero;
//滑动结束时的瞬时速度
Vector3 Speed = Vector3.zero;
//每帧偏差
Vector3 offSet = Vector3.zero;
//鼠标开始位置
Vector3 startMousePosition = Vector3.zero;
//速度衰減率
public float decelerationRate = 0.1f;
//摄像机
public Camera m_camera;
//移动模式
public MoveMode m_moveMode = MoveMode.obj;
void Update()
{
HandleMouseInput();
}
private void HandleMouseInput()
{
//按下时记录位置
if (Input.GetMouseButtonDown(0))
{
prevMousePos = Input.mousePosition;
startMousePosition = Input.mousePosition;
}
//移动时更新位置
if (Input.GetMouseButton(0))
{
Vector3 curMousePosition = Input.mousePosition; //当前鼠标的屏幕坐标系
//偏差值
offSet = m_camera.ScreenToWorldPoint(curMousePosition) - m_camera.ScreenToWorldPoint(prevMousePos);
prevMousePos = curMousePosition;
//瞬时速度
Speed = offSet / Time.deltaTime;
}
else //最后递减
{
Speed *= Mathf.Pow(decelerationRate, Time.deltaTime);
if (Mathf.Abs(Vector3.Magnitude(Speed)) < 1)
{
Speed = Vector3.zero;
}
}
Move(Speed);
}
public void Move(Vector3 speed)
{
if (Vector3.Magnitude(Speed) == 0)
{
return;
}
Debug.Log("Current Speed" + Vector3.Magnitude(speed));
if (m_moveMode == MoveMode.obj)
{
transform.localPosition += speed * Time.deltaTime;
}
else
{
m_camera.transform.localPosition -= speed * Time.deltaTime;
}
}
}