unity3d:保持V字型队形,按路径点移动

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luoyikun/article/details/88872313

思路:
1.分为领导者,追随者,追随点。
2.先创建领导者。根据剩下人数的多少,再在左右创建追随者和追随点,成v字排列。追随点是领导者的子物体
3.领导者按照路径点移动
4.追随者追的追随点移动,如果距离过远,要提高速度

创建队形脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SanJiao : MonoBehaviour {

    public GameObject m_tmp;
    public List<Transform> m_listPos;
    public Transform m_pointPar;
    public int m_tankCnt;
    public Dictionary<int, List<Vector3>> m_dicPos = new Dictionary<int, List<Vector3>>();
    public List<Transform> m_listTank;
	// Use this for initialization
	void Start () {
        m_dicPos[0] = new List<Vector3>();
        for (int i = 0; i < m_pointPar.childCount; i++)
        {
            m_listPos.Add(m_pointPar.GetChild(i));

           
        }

        for (int i = 0; i < m_listPos.Count; i++)
        {
            m_dicPos[0].Add(m_listPos[i].transform.position);


            GameObject objPos = Instantiate(m_tmp);
            objPos.transform.position = m_listPos[i].transform.position;

            if (i < m_listPos.Count - 1)
            {

                Vector3 dir = m_listPos[i + 1].transform.position - m_listPos[i].transform.position;
                objPos.transform.rotation = Quaternion.LookRotation(dir.normalized);
            }

            if (i == m_listPos.Count - 1)
            {
                Vector3 dir = m_listPos[i].transform.position - m_listPos[i-1].transform.position;
                objPos.transform.rotation = Quaternion.LookRotation(dir.normalized);
            }

            if (m_tankCnt > 1)
            {
                Sector(objPos.transform, objPos.transform.position, 60, 5, m_tankCnt-1);
            }
        }

        CreateTank();
    }
	
	// Update is called once per frame
	void Update () {
		
	}

    void CreateTank()
    {
        Transform par = null;
        Quaternion qua = Quaternion.identity;
        for (int i = 0; i < m_tankCnt; i++)
        {
            GameObject tank;
            //m_listTank.Add(tank.transform);

            if (i == 0)
            {
                tank = Instantiate(m_tmp);
                tank.transform.position = m_dicPos[i][0];
                tank.transform.GetComponent<FollowPath>().SetLeader(m_dicPos[i]);

                Vector3 dir = m_dicPos[i][1] - m_dicPos[i][0];
                tank.transform.rotation = Quaternion.LookRotation(dir.normalized); // 一开始就要确定leader 的方向
                qua = tank.transform.rotation;
                par = tank.transform;
            }
            else {
                GameObject follow = new GameObject();
                follow.transform.position = m_dicPos[i][0];
                follow.transform.SetParent(par, true);

                tank = Instantiate(m_tmp);
                tank.transform.position = m_dicPos[i][0];
                tank.transform.GetComponent<FollowPath>().SetFollow(follow.transform);
                tank.transform.rotation = qua;
                //tank.transform.SetParent(par, false);
            }
        }
    }


    public void Sector(Transform t, Vector3 center, float angle, float radius,int cnt)
    {
        Vector3 forward = -t.forward;

        int sign = -1;
        for (int i = 0; i < cnt; i++)
        {

            if (i % 2 == 0)
            {
                sign = -1; 
            }
            else
            {
                sign = 1;
            }

            Vector3 pos = Quaternion.Euler(0f, sign * angle / 2, 0f) * forward * radius * (1 + i / 2) + center;

            //GameObject obj = Instantiate(m_tmp);
            //obj.transform.position = pos;

            if (m_dicPos.ContainsKey(i+1) == false)
            {
                m_dicPos[1 + i] = new List<Vector3>();
            }
            m_dicPos[1 + i].Add(pos);
        }

       

    }


    void OnDrawGizmos()
    {
        Gizmos.color = Color.white;

        for (int i = 0; i < m_pointPar.transform.childCount; i++)
        {
            Vector3 position = m_pointPar.transform.GetChild(i).position;
            if (i > 0)
            {
                Vector3 previous = m_pointPar.transform.GetChild(i-1).position;
                Gizmos.DrawLine(previous, position);
                Gizmos.DrawWireSphere(position, 0.3f);
            }
        }

    }

}

追随脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowPath : MonoBehaviour {

    public int CurrentWayPointID = 0;
    public float Speed;//移动速度
    public float reachDistance = 0.01f;//里路径点的最大范围

    public List<Vector3> m_listPos = new List<Vector3>();
    public bool m_isCanFollow = false;

    public bool m_isLeader = false;

    public Transform m_followTrans;
    public Transform m_leaderTrans;
    void Start()
    {

    }

    public void SetLeader(List<Vector3> listPos)
    {
        m_isLeader = true;
        m_listPos = listPos;
        m_isCanFollow = true;
        CurrentWayPointID = 0;

    }

    public void SetFollow(Transform trans)
    {
        m_isLeader = false;
        m_followTrans = trans;

        m_isCanFollow = true;
        CurrentWayPointID = 0;

    }

    void Update()
    {
        if (!m_isCanFollow)
            return;

        if (m_isLeader == true)
        {
            if (CurrentWayPointID >= m_listPos.Count)
            {
                return;
            }
            float distance = Vector3.Distance(m_listPos[CurrentWayPointID], transform.position);
            transform.position = Vector3.MoveTowards(transform.position, m_listPos[CurrentWayPointID], Time.deltaTime * Speed);

            Vector3 LookDirection = m_listPos[CurrentWayPointID] - transform.position;
            Quaternion targetlook = Quaternion.LookRotation(LookDirection);

            if (distance <= reachDistance)
            {
                CurrentWayPointID++;
                if (CurrentWayPointID < m_listPos.Count)
                {
                    playerRotate(m_listPos[CurrentWayPointID], gameObject/*transform.Find("Tank").gameObject*/);
                }

            }
        }

        else if (m_isLeader == false)
        {
            float distance = Vector3.Distance(m_followTrans.position, transform.position);

            if (distance > 3)
            {
                transform.position = Vector3.MoveTowards(transform.position, m_followTrans.position, Time.deltaTime * Speed * 1.25f);
            }
            else {
                transform.position = Vector3.MoveTowards(transform.position, m_followTrans.position, Time.deltaTime * Speed );
            }

            //Vector3 LookDirection = m_listPos[CurrentWayPointID] - transform.position;
            //Quaternion targetlook = Quaternion.LookRotation(LookDirection);
            //playerRotate(m_followTrans.position, gameObject/*transform.Find("Tank").gameObject*/);
            transform.LookAt(m_followTrans);
        }
    }


    void playerRotate(Vector3 target, GameObject rot)
    {
        //向量的叉乘
        if (Vector3.Cross(rot.transform.forward, target - this.transform.position).y > 0)
        {
            //计算角度
            rot.transform.Rotate(Vector3.up * Vector3.Angle(rot.transform.forward, target - this.transform.position));
        }
        else
        {
            rot.transform.Rotate(Vector3.down * Vector3.Angle(rot.transform.forward, target - this.transform.position));
        }
    }

}

效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/luoyikun/article/details/88872313