个体AI角色的操控行为de实现
2.7 FollowPath 路径跟随
using System.Collections; using System.Collections.Generic; using UnityEngine; /*路径跟随 * 将当前路点设置为路点列表中的第一个路点,用靠近行为产生操控力来靠近这个路点,然后寻找下一个路点 * 需要设置一个“路点半径”参数,即AI角色距离当前路点多远时,可以认为它已经到达当前路点 */ public class SteeringFollowPath : Steering{ //有节点数组表示的路径 public GameObject[] waypoints = new GameObject[4]; //目标点 private Transform target; //当前路点 private int currentNode; //与路点的距离小于这个值时,认为已经到达,可以向下一个路点触发; private float arriveDistance; private float sqrArriveDistance; //路点的数量 private int numberOfNodes; //操控力 private Vector3 force; //预期速度 private Vector3 desiredVelocity; private Vehicle m_vehicle; private float maxSpeed; private bool isPlanar; //当与目标小于这个距离时,开始减速 public float slowDownDistance; // Use this for initialization void Start () { //存储路点数组中的路点个数 numberOfNodes = waypoints.Length; m_vehicle = GetComponent<Vehicle>(); maxSpeed = m_vehicle.maxSpeed; isPlanar = m_vehicle.isPlanar; //设置当前路点为第0个路点 currentNode = 0; //设置当前路点为目标点 target = waypoints[currentNode].transform; arriveDistance = 1.0f; sqrArriveDistance = arriveDistance * arriveDistance; } public override Vector3 Force() { force = new Vector3(0, 0, 0); Vector3 dist = target.position - transform.position; if (isPlanar) dist.y = 0; //如果当前路点已经是路点数组中的最后一个; if (currentNode == numberOfNodes - 1) { //如果与当前路点的距离大于减速距离 if (dist.magnitude > slowDownDistance) { //取出预期速度 desiredVelocity = dist.normalized * maxSpeed; //计算操纵向量 force = desiredVelocity - m_vehicle.velocity; } else { //与当前路点距离小于减速距离,开始减速,计算操控向量 desiredVelocity = dist - m_vehicle.velocity; force = desiredVelocity - m_vehicle.velocity; } } else { //当前路点不是路点数组中的最后一个,即正走向中间路点 if (dist.sqrMagnitude < slowDownDistance) { //如果与当前路点距离的平方小于到达距离的平方 //可以开始靠近下一个路点,将下一个路点设置为目标点 currentNode++; target = waypoints[currentNode].transform; } //计算预期速度与操控向量 desiredVelocity = dist.normalized * maxSpeed; force = desiredVelocity - m_vehicle.velocity; } return force; } // Update is called once per frame void Update () { } }
2.8 CollisionAvoidance 避开障碍
using System.Collections; using System.Collections.Generic; using UnityEngine; /*避开障碍 * AI行进路线发现比较近的障碍时,产生一个“排斥了力”,使AI角色远离这个障碍物 * 计算方法: * 与计算除一条静态可行路线的寻路算法不同,操控行为使一种动态路线,对躲避L或T形障碍物效果不是很好,而合力的作用使得任何操控力都不能 * 单独决定AI角色的运动,虽然概率较小,但如果游戏中要保证完全不发生碰撞,更好的选择使采用寻路算法 */ public class SteeringForCollisionAvoidance : Steering { public bool isPlaner; private Vector3 desiredVelocity; private Vehicle m_vehicle; private float maxSpeed; private float maxForce; //避免障碍所产生的操控力 public float avoidanceForce; //能向前看到的最大距离 public float MAX_SEE_AHEAD = 2.0f; //场景中的所有碰撞体组成的数组 private GameObject[] allColliders; // Use this for initialization void Start () { m_vehicle = GetComponent<Vehicle>(); maxSpeed = m_vehicle.maxSpeed; maxForce = m_vehicle.maxForce; isPlaner = m_vehicle.isPlanar; //如果避免障碍所产生的操控力大于最大操控力,将它截断到最大操控力 if (avoidanceForce > maxForce) avoidanceForce = maxForce; //存储场景中的所有碰撞体,即Tag为obstacle的那些游戏体 allColliders = GameObject.FindGameObjectsWithTag("obstacle"); } public override Vector3 Force() { RaycastHit hit; Vector3 force = new Vector3(0, 0, 0); Vector3 velocity = m_vehicle.velocity; Vector3 normalizedVelocity = velocity.normalized; //画出一条射线,需要考查与这条射线相交的碰撞体 Debug.DrawLine(transform.position, transform.position + normalizedVelocity * MAX_SEE_AHEAD * (velocity.magnitude / maxSpeed)); if (Physics.Raycast(transform.position, normalizedVelocity, out hit, MAX_SEE_AHEAD * velocity.magnitude / maxSpeed)) { //如果射线与某个碰撞体相交,表示可能与该碰撞体发生碰撞 Vector3 ahead = transform.position + normalizedVelocity * MAX_SEE_AHEAD * (velocity.magnitude / maxSpeed); //计算避免碰撞所需的操控力 force = ahead - hit.collider.transform.position; force *= avoidanceForce; if (isPlaner) { force.y = 0; } //将这个碰撞体的颜色变为绿色,其他的都变为灰色 foreach(GameObject c in allColliders) { if (hit.collider.gameObject == c) { c.GetComponent<Renderer>().material.color = Color.black; } else c.GetComponent<Renderer>().material.color = Color.white; } } else { //如果向前看的有限范围内,没有发生碰撞的可能 //将所有碰撞体设为灰色 foreach(GameObject c in allColliders) { c.GetComponent<Renderer>().material.color = Color.white; } } return force; } // Update is called once per frame void Update () { } }