Unity中实现巡逻其实是一个非常简单的事情,这里写一下我的实现思路。
public enum WayPointMode
{
Loop,
PingPong,
Once
}
这里的枚举表示的是怪物巡逻的模式,有三种,分别是Loop/PingPang/Once,分别表示循环/来回/一次的意思。
public class WayPointManager : MonoBehaviour
{
//巡逻模式
public WayPointMode mode;
//等待时间
public float waitTime;
//巡逻点队列
public List<Transform> wayPoints;
//是否要改变巡逻点
protected bool m_changing;
//是否正在回
protected bool m_pong;
public Transform m_current;
//目的巡逻点
public Transform current
{
get
{
if (m_current == null)
{
current = wayPoints[0];
}
return m_current;
}
protected set
{
m_current = value;
}
}
}
这里是一些主要的变量,代码中已做详细注释。
由于巡逻点数组是在Inspector面板依次加入的,所以数组索引从小到大也代表着巡逻点的顺序,因此需要一个根据当前巡逻点获取索引的方法,好为计算下一个巡逻点的索引做准备。
//根据巡逻点获取巡逻点队列索引
public int index => wayPoints.IndexOf(current);
最关键的是有没有下一个巡逻点,有的话什么时候切换巡逻点,接下来的Next()函数是核心。
public void Next()
{
if (m_changing)
return;
if (mode == WayPointMode.Loop)
{
if (index + 1 == wayPoints.Count)
{
StartCoroutine(Change(0));
}
else
{
StartCoroutine(Change(index + 1));
}
}
else if (mode == WayPointMode.PingPong)
{
if (!m_pong)//去
{
m_pong = (index + 1 == wayPoints.Count);
}
else//回
{
m_pong = !(index - 1 < 0);
var next = !m_pong ? index + 1 : index - 1;
StartCoroutine(Change(next));
}
else if (mode == WayPointMode.Once)
{
if (index + 1 < wayPoints.Count)
{
StartCoroutine(Change(index + 1));
}
}
}
protected IEnumerator Change(int next)
{
m_changing = true;
yield return new WaitForSeconds(waitTime);
current = wayPoints[next];
m_changing = false;
}
巡逻类写完后,添加到移动对象身上,可以看到Inspector面板是这样的:
下面是测试类
public class MoveToPoint : MonoBehaviour
{
public float speed;
private WayPointManager way;
private void Start()
{
way = GetComponent<WayPointManager>();
}
private void Update()
{
var destination = way.current.position;
destination = new Vector3(destination.x, transform.position.y, destination.z);
if (Vector3.Distance(destination,transform.position) <= 0.1f)
{
way.Next();
}
Vector3 dir = (destination - transform.position).normalized;
transform.position += dir * speed * Time.deltaTime;
}
}