Unity3D AI行为之避开障碍物简单实现

发表于2018-09-30
评论0 3.9k浏览
前面做给大家介绍了这么多知识点方面的介绍,下面就通过避开障碍物的实现案例来帮助大家去了解。

代码如下:
  public float speed = 20.0f;
    public float mass = 5.0f;
    public float force = 50.0f;
    public float minimumDistToAvoid = 20.0f;
    private float curSpeed;
    private Vector3 targetPoint;
	// Use this for initialization
	void Start () {
        targetPoint = Vector3.zero;
        mass = 5.0f;
	}
在Update方法中,我们基于AvoidObstacles方法返回的方向向量更新agent实体的位置并对其进行旋转。我们在update方法中所做的第一件事就是获取鼠标点击的位置,以移动我们的AI实体,我们向它正在观察的方向发出一条射线,然后获取这条射线

与地平面的交点,作为目标位置,一旦获取到了目标位置向量,就可以用目标位置向量减去当前位置的向量来计算出目标向量。最后调用AvoidObstacles方法,并将这个目标向量作为参数传入。
 void Update () {
        RaycastHit hit;
        var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Input.GetMouseButtonDown(0) && Physics.Raycast(ray,out hit,100.0f))
        {
            targetPoint = hit.point;
        }
        Vector3 dir = targetPoint - transform.position;
        dir.Normalize();
        AvoidObstacles(ref dir);
        if (Vector3.Distance(targetPoint,transform.position) <3.0f)
        {
            return;
        }
        curSpeed = speed * Time.deltaTime;
        var rot = Quaternion.LookRotation(dir);
        transform.rotation = Quaternion.Slerp(transform.rotation, rot, 5.0f * Time.deltaTime);
        transform.position += transform.forward * curSpeed;
	}

AvoidObstacles方法也非常简单,这里唯一需要注意的技巧就是光线投射会选择性的与障碍物所在的图层相互作用,这个图层已经在Unity3D的标签管理器中标记为User Layer8,Raycast方法接收一个图层掩码参数,

Unity3D使用一个32位的整数来代表这个图层掩码参数,例如,以下表示32位全是零:
0000 0000 0000 0000 0000 0000 0000 0000

默认情况下Unity使用前8层作为内置的图层。所以,当你不使用任何图层掩码参数的情况下调用光线投射方法时,它会对所有默认的这8层进行光线投射,可以用如下位掩码表示:
0000 0000 0000 0000 0000 0000 1111 1111

我们的障碍物所在的层被设置为第8层(下标为9),我们只希望对这个层进行光线投射,所以我们将位掩码设置为:
0000 0000 0000 0000 0000 0001 0000 0000

设置这个位掩码最简单的办法是使用位移操作,我们只需要将下标为9的位置设置为1,这意味着我们只需左移8位即可:
int layerMask = 1<<8;

一旦设置好了图层掩码,我们就可以调用Physics.Raycast方法,从当前实体的位置的方向投射一条射线。射线的长度使用变量minimumDistToAvoid,这样我们就可以只避开在这个距离内射线遇到的障碍。

然后我们获取到射线的法向量,用其乘以力的向量,再把它与当前实体方向的向量相加,得出合成方向向量,并将其从方法中返回。接着在Update方法中,在避开障碍物之后,我们使用这个新的方向对AI实体进行旋转并根据速度值更新位置。
 public void AvoidObstacles(ref Vector3 dir)
    {
        RaycastHit hit;
        int layerMask = 1 << 8;
        if (Physics.Raycast(transform.position,transform.forward,out hit, minimumDistToAvoid, layerMask))
        {
            Vector3 hitNormal = hit.normal;
            hitNormal.y = 0;
            dir = transform.forward + hitNormal * force;
        }
    }
来自:https://blog.csdn.net/qq_27880427/article/details/72781269

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

标签: