Unity中实现控制人物模型按照轨迹点漫游(多个人物在同一轨迹点漫游)

本人在项目开发中原创脚本,转载请注明来源,谢谢!!

 

脚本说明

     此脚本的编辑是为了实现3D场景中多个人物模型(物体)按照同一轨迹点进行漫游移动并旋转的功能。

  1. 所有人物模型在同一轨迹上的不同位置点(开始漫游点位置)
  2. 所有人物模型朝着同一个目标点漫游,且按照同一轨迹点进行漫游并旋转

 

具体脚本内容如下所示:

脚本中的有两种获取漫游点坐标的方式,根据个人喜好选择使用。

wayPiontsParent.GetChild(wayIndex).position    直接获取漫游点坐标

wayPointsList[wayIndex].position     将所有漫游点存储在List中然后再去获取对应的漫游点坐标

(脚本可以根据自己的项目内容进一步优化)

(漫游效果可以根据需求进一步优化脚本逻辑)

方法一:在人物(物体)模型上手动添加脚本及修改相应参数

  1. 3D场景布置漫游的轨迹点
  2. 场景中在漫游点开始处添加人物(物体)模型
  3. 脚本挂载到需要漫游的人物(物体)模型上
  4. 修改挂载脚本中开始漫游点的值和添加所有漫游点的父类,挂载后人物(物体)模型上显示如下图所示:

方法一具体脚本如下所示:

    [SerializeField]
    private int wayIndex = 0;//人物初始点位置
    [SerializeField]
    private Transform wayPiontsParent;//所有漫游点的父类
    private List<Transform> wayPointsList = new List<Transform>();//存储所有漫游点

    private float normal_moveSpeed = 3f;//移动速度
    private float normal_rotateSpeed = 2f;//旋转速度
    float rotateProgress = 0;
    Quaternion targetQuaternion;//目标
    Quaternion lastQuaternion;//人物
    void Start()
    {

        InitWayPoints();
        CaculateRotateData(wayIndex);
        transform.position = wayPiontsParent.GetChild(wayIndex).position/* wayPointsList[wayIndex].position*/;
    }
    /// <summary>
    /// 初始化轨迹点
    /// </summary>
    void InitWayPoints()
    {
        wayPointsList.Clear();
        if (wayPiontsParent != null && wayPiontsParent.childCount > 0)
        {
            for (int i = 0; i < wayPiontsParent.childCount; i++)
            {
                wayPointsList.Add(wayPiontsParent.GetChild(i));
            }
        }
    }
   
    void Update()
    {
        NormalMove();

    }
    /// <summary>
    /// 正常漫游
    /// </summary>
    private void NormalMove()
    {
        if (peopleMoveStatus == PeopleMoveStatus.Move)
        {
            float nextPointDistance = 0;
            if (wayIndex < wayPiontsParent.childCount - 1/* wayPointsList.Count - 1*/)//没有到最后一个点
            {

                nextPointDistance = Vector3.Distance(transform.position, wayPiontsParent.GetChild(wayIndex + 1).position);
                Vector3 direction = (wayPiontsParent.GetChild(wayIndex + 1).position - wayPiontsParent.GetChild(wayIndex).position).normalized;
                transform.position += Time.deltaTime * direction * normal_moveSpeed;

                //nextPointDistance = Vector3.Distance(transform.position, wayPointsList[wayIndex + 1].position);
                //Vector3 direction = (wayPointsList[wayIndex + 1].position - wayPointsList[wayIndex].position).normalized;
                //transform.position += Time.deltaTime * direction * normal_moveSpeed;

            }
            if (wayIndex.Equals(wayPiontsParent.childCount - 1/*wayPointsList.Count - 1*/))//最后一个点
            {

                Destroy(this.gameObject);
            }
            if (nextPointDistance <= 0.15f)//换到下一个点进行旋转
            {
                peopleMoveStatus = PeopleMoveStatus.Rotate;
                rotateProgress = 0;
                wayIndex++;
                CaculateRotateData(wayIndex);
            }
        }

        if (peopleMoveStatus == PeopleMoveStatus.Rotate && lastQuaternion != targetQuaternion)
        {
            transform.rotation = Quaternion.Lerp(lastQuaternion, targetQuaternion, rotateProgress);
            rotateProgress += Time.deltaTime * normal_rotateSpeed;
            if (lastQuaternion == targetQuaternion || rotateProgress >= 1)
            {
                peopleMoveStatus = PeopleMoveStatus.Move;//转完了,开始移动
            }
        }
    }
  
    /// <summary>
    /// 计算旋转方向数据
    /// </summary>
    /// <param name="index"></param>
    void CaculateRotateData(int index)
    {
        lastQuaternion = transform.rotation;
        Vector3 dir = Vector3.zero;
        if (wayIndex < wayPiontsParent.childCount - 1 /*wayPointsList.Count - 1*/)
        {
            dir = wayPiontsParent.GetChild(index + 1).position - wayPiontsParent.GetChild(index).position;
            //dir = wayPointsList[index + 1].position - wayPointsList[index].position;
        }
       
        targetQuaternion = Quaternion.LookRotation(dir);
    }

    PeopleMoveStatus peopleMoveStatus = PeopleMoveStatus.Move;
    /// <summary>
    /// 人物模型移动状态
    /// </summary>
    enum PeopleMoveStatus
    {
        Move,
        Rotate,
        End
    }

方法二:在人物(物体)上动态添加脚本及修改相应参数

初始化轨迹点的方法添加到控制动态生成人物模型的脚本中,脚本如下所示:

    /// <summary>
    /// 初始化轨迹点
    /// </summary>
    void InitWayPoints()
    {
        wayPointsList.Clear();
        if (wayRoot != null && wayRoot.childCount > 0)
        {
            for (int i = 0; i < wayRoot.childCount; i++)
            {
                wayPointsList.Add(wayRoot.GetChild(i).position);
            }
        }
    }

控制动态生成人物模型的脚本中添加如下脚本:

    /// <summary>
    /// 初始化多个人物模型
    /// </summary>
    private void InitSomePeople()
    {
       
        for (int i = 0; i < 30; i += 2)
        {
            GameObject peopleWalk = Instantiate(peoplePrefab, peopleParent.position, peopleParent.rotation);
            peopleWalk.transform.SetParent(peopleParent);
            peopleWalk.AddComponent<SomePeopleWalkControl>().SetWayIndex(i);
        }
    }

控制人物模型按照轨迹点移动的脚本如下所示:


    private int wayIndex = 0;//人物初始点位置
    private float normal_moveSpeed = 0.5f;//移动速度
    private float normal_rotateSpeed = 5f;//旋转速度
    float rotateProgress = 0;
    Quaternion targetQuaternion;//目标
    Quaternion lastQuaternion;//人物
    void Start()
    {

        transform.position = BornPeople.Instance.wayPointsList[wayIndex];
        CaculateRotateData(wayIndex);
        transform.rotation = Quaternion.LookRotation(initDir);//初始化物体朝向下一漫游点方向
    }

    /// <summary>
    /// 给人物模型初始漫游点赋值
    /// </summary>
    public void SetWayIndex(int _index)
    {
        wayIndex = _index;
    }
    void Update()
    {
        NormalMove();
    }
    /// <summary>
    /// 正常漫游
    /// </summary>
    private void NormalMove()
    {
        if (peopleMoveStatus == PeopleMoveStatus.Move)
        {
            float nextPointDistance = 0;
            if (wayIndex < BornPeople.Instance.wayPointsList.Count - 1)//没有到最后一个点
            {

                //nextPointDistance = Vector3.Distance(transform.position, wayPiontsParent.GetChild(wayIndex + 1).position);
                //Vector3 direction = (wayPiontsParent.GetChild(wayIndex + 1).position - wayPiontsParent.GetChild(wayIndex).position).normalized;
                //transform.position += Time.deltaTime * direction * normal_moveSpeed;

                nextPointDistance = Vector3.Distance(transform.position, BornPeople.Instance.wayPointsList[wayIndex + 1]);
                Vector3 direction = (BornPeople.Instance.wayPointsList[wayIndex + 1] - BornPeople.Instance.wayPointsList[wayIndex]).normalized;
                transform.position += Time.deltaTime * direction * normal_moveSpeed;

            }
            if (wayIndex.Equals(BornPeople_14.Instance.wayPointsList.Count - 1/*wayPointsList.Count - 1*/))//最后一个点
            {

                Destroy(this.gameObject);
            }
            if (nextPointDistance <= 0.15f)//换到下一个点进行旋转
            {
                peopleMoveStatus = PeopleMoveStatus.Rotate;
                rotateProgress = 0;
                wayIndex++;
                CaculateRotateData(wayIndex);
            }
        }

        if (peopleMoveStatus == PeopleMoveStatus.Rotate && lastQuaternion != targetQuaternion)
        {
            transform.rotation = Quaternion.Lerp(lastQuaternion, targetQuaternion, rotateProgress);
            rotateProgress += Time.deltaTime * normal_rotateSpeed;
            if (lastQuaternion == targetQuaternion || rotateProgress >= 1)
            {
                peopleMoveStatus = PeopleMoveStatus.Move;//转完了,开始移动
            }
        }
    }

    Vector3 initDir = Vector3.zero;
    /// <summary>
    /// 计算旋转方向数据
    /// </summary>
    /// <param name="index"></param>
    public void CaculateRotateData(int index)
    {
        lastQuaternion = transform.rotation;
        Vector3 dir = Vector3.zero;
        if (index < BornPeople.Instance.wayPointsList.Count - 1 /*wayPointsList.Count - 1*/)
        {
            //dir = wayPiontsParent.GetChild(index + 1).position - wayPiontsParent.GetChild(index).position;
            dir = BornPeople.Instance.wayPointsList[index + 1] - BornPeople.Instance.wayPointsList[index];
        }
        initDir = dir;
        targetQuaternion = Quaternion.LookRotation(dir);
    }

    PeopleMoveStatus peopleMoveStatus = PeopleMoveStatus.Move;
    /// <summary>
    /// 人物模型移动状态
    /// </summary>
    enum PeopleMoveStatus
    {
        Move,
        Rotate,
        End
    }

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页