Unity 实现鼠标拖拽物体沿路径移动并且旋转
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragAtPath : MonoBehaviour
{
/// <summary> 是否开始拖拽物体按照轨道移动 </summary>
public bool isStartDragWithPath = true;
private Vector3 mousePos; //鼠标按下的位置
private Vector3 nextMousePos;
public List<Transform> DragPath = new List<Transform>();
private int index = 0;
public List<Vector3> rotate = new List<Vector3>();
private float MaxRotate = 360;
void Start()
{
CacleRotate();
}
private void OnMouseDown()
{
mousePos = Input.mousePosition;
}
/// <summary>
/// 计算各个节点物体的旋转应该是多少
/// </summary>
private void CacleRotate()
{
float pathLenth = 0;
List<float> pathDis = new List<float>();
for (int i = 0; i < DragPath.Count-1; i++)
{
float dis = Vector3.Distance(DragPath[i].position, DragPath[i + 1].position);
pathDis.Add(dis);
pathLenth += dis;
}
for (int i = 0; i < DragPath.Count; i++)
{
if (i==0)
{
rotate.Add(Vector3.zero);
}
else
{
rotate.Add(rotate[i - 1] + new Vector3(0, 0, MaxRotate * (pathDis[i-1]/pathLenth)));
}
}
}
private void OnMouseDrag()
{
ExecuteDragWithPath();
}
/// <summary> 执行按照路径拖拽物体 </summary>
private void ExecuteDragWithPath()
{
if (isStartDragWithPath)
{
nextMousePos = Input.mousePosition;
Vector3 current1 = mousePos - nextMousePos;
Vector3 current = current1.normalized;
current = new Vector3(-current.x, -current.y, current.z);//根据摄像机的方向不同,正负也不同
Vector3 comperLast, compareNext;
comperLast = transform.position - DragPath[index].position;
comperLast = comperLast.normalized;
compareNext = transform.position - DragPath[index + 1].position;
compareNext = compareNext.normalized;
float DotNext = Vector3.Dot(current, compareNext);//计算拖拽向量和下一个目标节点的向量点积
float dotLast = Vector3.Dot(current, comperLast);//计算拖拽向量和上一个目标节点的向量点积
float speed = current1.magnitude;//拖拽的长度
if (speed <= 0.1f)
{
return;
}
if (DotNext < dotLast)//如果上一个的相似度低于下一个,意味着拖拽方向更近似于下一个,所以向下一个节点处移动
{
transform.position = Vector3.MoveTowards(transform.position, DragPath[index + 1].position, Time.deltaTime * speed);
Vector3 rot = CacleNextRotate();
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(rot), 1);
if (Vector3.Distance(transform.position, DragPath[index + 1].position) < 0.01f)
{
transform.rotation = Quaternion.Euler(rotate[index + 1]);
transform.position = DragPath[index + 1].position;
index++;
if (index == DragPath.Count - 1)
{
isStartDragWithPath = false;
}
}
}
else
{
transform.position = Vector3.MoveTowards(transform.position, DragPath[index].position, Time.deltaTime * speed);
Vector3 rot = CacleNextRotate();
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(rot), 1); if (Vector3.Distance(transform.position, DragPath[index].position) < 0.01f)
{
transform.rotation = Quaternion.Euler(rotate[index]);
transform.position = DragPath[index].position;
index--;
if (index == -1)
{
index = 0;
}
}
}
mousePos = nextMousePos;
}
}
/// <summary>
/// 计算下一个旋转
/// </summary>
/// <returns></returns>
private Vector3 CacleNextRotate()
{
float dir = Vector3.Distance(DragPath[index + 1].position, DragPath[index].position);//计算两个位置点的距离
float cur = Vector3.Distance(transform.position, DragPath[index].position);//计算当前位置距离上一个点的距离
Vector3 rot = rotate[index + 1] * (cur / dir) + (1 - (cur / dir)) * rotate[index];
return rot;
}
}