Unity 实现鼠标拖拽物体沿路径移动并且旋转

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;
 }

}

猜你喜欢

转载自blog.csdn.net/weixin_37836657/article/details/122615339