其实自动寻径的功能,在unity已经完美封装好了,我们应该做的就是对其中封装好的属性函数进行完美的使用。
using UnityEngine;
using System.Collections;
public class Locomotion
{
private Animator m_Animator = null;
private int m_SpeedId = 0;
private int m_AgularSpeedId = 0;
private int m_DirectionId = 0;
public float m_SpeedDampTime = 0.1f;//设置动画参数speed时的插值时间
public float m_AnguarSpeedDampTime = 0.25f;//Teddy对象旋转一定方向的时候小号的时间,用于计算运动时的角速度。
public float m_DirectionResponseTime = 0.2f;
public Locomotion(Animator animator)
{
m_Animator = animator;
m_SpeedId = Animator.StringToHash("Speed");
m_AgularSpeedId = Animator.StringToHash("AngularSpeed");
m_DirectionId = Animator.StringToHash("Direction");
}
public void Do(float speed, float direction)
{
//是否处于两个动画状态的国度状态上
AnimatorStateInfo state = m_Animator.GetCurrentAnimatorStateInfo(0);
bool inTransition = m_Animator.IsInTransition(0);
bool inIdle = state.IsName("Locomotion.Idle");
bool inTurn = state.IsName("Locomotion.TurnOnSpot") || state.IsName("Locomotion.PlantNTurnLeft") || state.IsName("Locomotion.PlantNTurnRight");
bool inWalkRun = state.IsName("Locomotion.WalkRun");
float speedDampTime = inIdle ? 0 : m_SpeedDampTime;
float angularSpeedDampTime = inWalkRun || inTransition ? m_AnguarSpeedDampTime : 0;
float directionDampTime = inTurn || inTransition ? 1000000 : 0;
float angularSpeed = direction / m_DirectionResponseTime;
m_Animator.SetFloat(m_SpeedId, speed, speedDampTime, Time.deltaTime);
m_Animator.SetFloat(m_AgularSpeedId, angularSpeed, angularSpeedDampTime, Time.deltaTime);
m_Animator.SetFloat(m_DirectionId, direction, directionDampTime, Time.deltaTime);
}
}
第一个类,作为工具类进行使用。
using UnityEngine;
using System.Collections;
public class Agent : MonoBehaviour {
public GameObject particle;
protected NavMeshAgent agent;
protected Animator animator;
protected Locomotion locomotion;
protected Object particleClone;
// Use this for initialization
void Start () {
agent = GetComponent<NavMeshAgent>();
agent.updateRotation = false;
animator = GetComponent<Animator>();
locomotion = new Locomotion(animator);
particleClone = null;
}
protected void SetDestination()
{
// Construct a ray from the current mouse coordinates
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(ray, out hit))
{
if (particleClone != null)
{
GameObject.Destroy(particleClone);
particleClone = null;
}
// Create a particle if hit
Quaternion q = new Quaternion();
q.SetLookRotation(hit.normal, Vector3.forward);
particleClone = Instantiate(particle, hit.point, q);
agent.destination = hit.point;
}
}
protected void SetupAgentLocomotion()
{
if (AgentDone())
{
locomotion.Do(0, 0);
if (particleClone != null)
{
GameObject.Destroy(particleClone);
particleClone = null;
}
}
else
{
float speed = agent.desiredVelocity.magnitude;
Vector3 velocity = Quaternion.Inverse(transform.rotation) * agent.desiredVelocity;
float angle = Mathf.Atan2(velocity.x, velocity.z) * 180.0f / 3.14159f;
locomotion.Do(speed, angle);
}
}
void OnAnimatorMove()
{
agent.velocity = animator.deltaPosition / Time.deltaTime;
transform.rotation = animator.rootRotation;
}
protected bool AgentDone()
{
return !agent.pathPending && AgentStopping();
}
protected bool AgentStopping()
{
return agent.remainingDistance <= agent.stoppingDistance;
}
// Update is called once per frame
void Update ()
{
if (Input.GetButtonDown ("Fire1"))
SetDestination();
SetupAgentLocomotion();
}
}
第二个类绑定在人物上。从而实现对地图点击人物自动循径。