Unity3D AI行为之路径跟随

发表于2018-09-30
评论0 1.6k浏览
下面给大家介绍的这个路径跟随脚本很简单,它有一个Length属性,如果发起请求,就可以返回航点数组的长度和大小。GetPoint方法返回数组中指定下标位置的特定航点的位置。然后,Unity调用OnDrawGizmos方法,以在编辑器环境中绘制出组件,在游戏视图中,如果不打开gizmos,那么这些绘图是不会渲染的。

代码如下:
public class Path : MonoBehaviour {
    public bool bDebug = true;
    public float Radius = 2.0f;
    public Vector3[] pointA;
    public float Length
    {
        get
        {
            return pointA.Length;
        }
    }
    public Vector3 GetPoint(int index)
    {
        return pointA[index];
    }
    private void OnDrawGizmos()
    {
        if (!bDebug)
        {
            return;
        }
        for (int i = 0; i < pointA.Length; i++)
        {
            if (i + 1< pointA.Length)
            {
                Debug.DrawLine(pointA[i], pointA[i + 1], Color.red);
            }
        }
    }
}

接下来,我们有了车辆实体,在本例中它只是一个简单的立方体对象,创建完脚本后,我们将添加VehicleFollowing脚本组件。该脚本接受几个参数,首先是它需要跟随的路径的引用对象,其次是在正确计算它的加速度时需要用到的速度(Speed)属性和质量(Mass)属性。选中是否循环(IsLooping)这个标志,会让实体一直沿着路径循环行进。
 public Path path;
    public float speed = 20.0f;
    public float mass = 5.0f;
    public bool isLooping = true;
    private float curSpeed;
    private int curPathIndex;
    private float pathLength;
    private Vector3 targetPoint;
    Vector3 velocity;
    private void Start()
    {
        pathLength = path.Length;
        curPathIndex = 0;
        velocity = transform.forward;
    }
    private void Update()
    {
        curSpeed = speed * Time.deltaTime;
        targetPoint = path.GetPoint(curPathIndex);
        if (Vector3.Distance(transform.position,targetPoint)<path.Radius)
        {
            if (curPathIndex < pathLength - 1)
            {
                curPathIndex++;
            }
            else if (isLooping)
            {
                curPathIndex = 0;
            }
            else
            {
                return;
            }
        }
        if (curPathIndex >= pathLength)
        {
            return;
        }
        if (curPathIndex >= pathLength -1 && !isLooping)
        {
            velocity += Steer(targetPoint,true);
        }else
        {
            velocity += Steer(targetPoint);
        }
        transform.position += velocity;
        transform.rotation = Quaternion.LookRotation(velocity);
    }

首先我们对属性进行初始化,并在Start方法中将我们的velocity向量设置为向前的方向。在Update方法中,我们通过计算实体的当前位置和与特定航点的距离是否在其半径范围内,来判断它是否已经到达了特定的航点。如果它在范围内,我们只需将下表递增,来找到数组中的下一个航点,如果已经是最后一个航点,我们就需要检查IsLooping标签是否已设置,如果已经设置,我们就将目标设为起始点,否则,我们只需停止在那个点即可。不过,我们也可以让对象转过来,沿着它过来的路线原路返回。

再接下来,我们将在Steer方法中计算加速度,然后旋转我们的实体,并根据速度和方向相应的更新它的位置。Steer方法接收参数,需要移动到Vector3类型的目标位置,无论这个点是否是在最终的航点。我们需要做的第一件事就是计算当前位置与目标位置的剩余距离。用目标位置向量减去当前位置的向量,得出向目标位置移动的向量。这个向量的模就是剩余的距离。我们然后将这个向量规格化以保持其方向属性。现在,如果这是最后一个航点,并且距离小于我们刚刚决定使用的数字10,我们就随着距离越来越近逐渐降低速度,直到速度最终降为零。否则,我们就以刚刚的速度值更新目标速度。通过从目标速度向量中减去当前速度向量,我们可以计算出新的引导向量。然后用这个向量除以实体的质量,就得出了加速度。
    public Vector3 Steer(Vector3 target,bool bFinalPoint = false)
    {
        Vector3 desiredVelocity = target - transform.position;
        float dist = desiredVelocity.magnitude;
        desiredVelocity.Normalize();
        if (bFinalPoint && dist < 10.0f)
        {
            desiredVelocity *= (curSpeed * (dist / 10.0f));
        }
        Vector3 steeringForce = desiredVelocity - velocity;
        Vector3 acceleration = steeringForce / mass;
        return acceleration;
    }
来自:https://blog.csdn.net/qq_27880427/article/details/72779871

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引