指导行为:为什么我的漫游算法无法按预期运行?

时间:2019-02-12 23:23:21

标签: c# algorithm unity3d

我们正在学习游戏类人工智能中的转向行为,我认为我会尽力实现其中的一些行为。我主要阅读The Nature of Code以使自己熟悉这些主题。

Here是我的Unity项目的存储库。相关场景在Assets/Scenes/Wandering.unity下。

以下是关联的脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Wandering : MonoBehaviour
{
    public float maxSpeed;
    private float speed;
    public float maxForce;
    public float radius;
    private Rigidbody body;


    void Awake()
    {
        body = gameObject.GetComponent<Rigidbody>();
        speed = maxSpeed;
        body.velocity = new Vector3(5, 0, 5);
    }


    void Update()
    {
        // Get future position
        Vector3 futurePosition = GetFuturePosition();

        // Select random point on circle of radius "radius" around the future position
        Vector3 target = GeneratePointOnCircle(futurePosition);

        // Compute desired velocity as one pointing there
        Vector3 desiredVelocity = GetDesiredVelocity(target);

        // Get the steering force vector
        Vector3 steerForce = desiredVelocity - body.velocity;
        steerForce.y = 0;

        // Cap the force that can be applied (lower max force = more difficult to turn)
        if (Vector3.Magnitude(steerForce) > maxForce)
        {
            steerForce = Vector3.Normalize(steerForce) * maxForce;
        }

        // Apply the force to the body
        body.AddForce(steerForce);
    }


    /* Returns a random point on a circle positioned at the given center and radius.
     */ 
    Vector3 GeneratePointOnCircle(Vector3 center)
    {
        Vector3 point = center;

        float angle = Random.Range(0, 360) * Mathf.Deg2Rad;
        point.x += radius * Mathf.Cos(angle);
        point.z += radius * Mathf.Sin(angle);

        return point;
    }


    /* Computes and returns the future, predicted position of this object, assuming
     * it continues traveling in its current direction at its current speed.
     */
    Vector3 GetFuturePosition()
    {
        // We have a current velocity
        // We have a time elapsed
        // We have a current position
        // Future position = current position + current velocity * delta time

        return transform.position + body.velocity * Time.deltaTime;
    }


    /* The desired velocity is simply the unit vector in the direction of the target
     * scaled by the speed of the object.
     */
    Vector3 GetDesiredVelocity(Vector3 target)
    {
        return Vector3.Normalize(target - transform.position) * speed;
    }
}

在编辑器中设置的值:

  • maxSpeed:40
  • maxForce:20
  • radius:60

运行此命令时,代理的行为不符合预期。主要问题是,它没有平稳地行驶,而是突然停顿了一下,似乎停了下来,然后又开始运动。这种随机行为仍然很整洁,并且有点像迷失方向的啮齿动物的行为,但是我正在寻找更智能的行为。

我的脚本或逻辑中是否存在迫使代理以这种不稳定方式运行的缺陷?任何建议将不胜感激。

1 个答案:

答案 0 :(得分:2)

问题似乎出在我是否使用Time.deltaTime来计算代理是否以当前速度继续​​运行的情况下的预测点。

因为这实际上是自上一帧更新以来经过的时间,所以它是一个很小的数字。因此,将其用于预测未来点会产生误导,并且会产生非常接近代理的点(因此会出现“口吃”行为)。

相反,我选择使用固定的“超前”时间(例如2)来预测未来。