本工具支持:锚点移动,行动动画,路径循环
使用本工具前,需要先引用DoTween插件
Flag文件夹本身也是有坐标的,使用时记得不要把position弄飞
0701增加了循环功能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using System;
using UnityEditor;
/*
* 使用方法
* 首先,创建一个空物体作为锚点的集合,内含数个子物体,子物体只记录坐标,作为行动路径
* 然后,将空物体文件夹拖动到Flags中
*
* 如果你要使用动画功能,请参考AnimatorMoving功能.内置了一个修改布尔值的简单动画机
* 如果不需要动画功能,请移除animatorMoving方法避免空引用,并删除所有飘红部分
*/
public class NPCMoveing : MonoBehaviour
{
[Header("要移动的物体")]
public GameObject Father;
[Header("待机锚点,在第几个锚点位置待机?")]
public int[] _StayFlag;
[Header("待机时间"), Range(0f, 120f)]
public int[] _Stay;
[Header("锚点")]
public GameObject Flags;
Transform[] Flag;
[Header("移动速度"),Range(0.3f,3f)]
public float Movespeed;
[Header("循环?")]
public bool IsLoop;
bool Looping;//当值为false时.正常路径行动,为true时,从最后一个路径点往回走
int _step = 1;//因为第一个Transform是空物体文件夹
int _StayStep=0;//第一次待机
public void Start()
{
Flag = Flags.GetComponentsInChildren<Transform>();
if (_step < Flag.Length)
StartCoroutine(NextStep(ComputeMoveTime(Flag[_step-1].position, Flag[_step].position)));
}
/// <summary>
/// 移动脚本 递归
/// </summary>
/// <param name="waittime">等待时间,由computemovetime计算</param>
/// <returns></returns>
IEnumerator NextStep(float waittime)
{
Debug.Log(Looping);
if (_step == 1) Looping = false;
Debug.Log("当前步骤》》》" + _step + "下个静止步骤>>>" + _StayFlag[_StayStep]);
#region 静止,朝向与移动速度控制
if (_step == _StayFlag[_StayStep])
{
AnimatorMoving(false);
yield return new WaitForSeconds(_Stay[_StayStep]);
if (!Looping)
_StayStep++;
else _StayStep--;
}
if (_step != 1)//因为是延迟后必定行动,而第一步是静止,本步比较特殊
{
Debug.Log("等待时间>>" + waittime);
if(!Looping)
Father.transform.LookAt(Flag[_step]);
else Father.transform.LookAt(Flag[_step-1]);
Father.transform.DOMove(Flag[_step-1].position, waittime);
AnimatorMoving(true);
}
#endregion
if (!Looping)
_step++;
else _step--;
yield return new WaitForSeconds(waittime);
#region 根据循环状态递归
if (_step < Flag.Length && !Looping)
StartCoroutine(NextStep(ComputeMoveTime(Flag[_step - 1].position, Flag[_step].position)));
else if (IsLoop && !Looping) { Looping = true; StartCoroutine(NextStep(ComputeMoveTime(Flag[_step-1].position, Flag[_step - 2].position))); }
else if (Looping) StartCoroutine(NextStep(ComputeMoveTime(Flag[_step].position, Flag[_step - 1].position)));
else Debug.Log("Moving Compelete");
#endregion
}
#region 工具
/// <summary>
/// 根据移动速度返回需要的时间
/// </summary>
/// <param name="AfterStep"></param>
/// <param name="BeforeStep"></param>
/// <returns></returns>
float ComputeMoveTime(Vector3 AfterStep,Vector3 BeforeStep)
{
Debug.Log((Mathf.Abs(BeforeStep.x - AfterStep.x) + Mathf.Abs(BeforeStep.z - AfterStep.z)) / Movespeed);
return (Mathf.Abs(BeforeStep.x - AfterStep.x) + Mathf.Abs(BeforeStep.z - AfterStep.z))/Movespeed;
}
/// <summary>
/// 修改动画
/// </summary>
/// <param name="a">是否行走</param>
void AnimatorMoving(bool a)
{
Father.GetComponent<Animator>().SetBool("IsMoving", a);
}
#endregion
}