群体的操控行为

9 篇文章 1 订阅
7 篇文章 0 订阅

目录

组行为

检测附近的AI角色

分离

队列

聚集


组行为

组行为的复杂性来源于个体间的交互,并遵守一些简单的规则。

模仿群体行为需要下面几种操控行为

  • 分离:避免个体在局部过于拥挤的操控力
  • 队列:朝向附近同伴的平均朝向的操控力
  • 聚集:向附近的同伴的平均位置移动的操控力

检测附近的AI角色

从上面的几种操控行为可以看出,每种操控行为都取决于附近的同伴。为了实现组行为,首先需要检测当前AI角色附近的其他AI角色,这要用一个雷达脚本来实现。

一般来说,角色的领域由一个距离和一个角度来定义。有时为了简化,用一个圆来定义。

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

public class Radar : MonoBehaviour
{
    private Collider[] colliders;//碰撞体的组数
    private float timer = 0;//计时器
    public List<GameObject> neighbors;
    public float checkInterval = 0.3f;//设置检测的时间间隔
    public float detectRadius = 10f;//设置邻域半径
    public LayMask layersChecked;//设置检测哪一层的游戏对象

    void Start()
    {
        neighbors = new List<GameObject>();
    }

    void Update()
    {
        timer += Time.deltaTime;
        if(timer > checkInterval)
        {
            neighbors.Clear();
            colliders = Physics.OverlapSphere(transform.position, detectRadius, layersChecked);//查找当前AI角色邻域内的所有碰撞体
            for(int i = 0; i < colliders.Length; i++)//对于每个检测到的碰撞体,获取Vehicle组件,并且加入邻居列表钟
            {
                if (colliders[i].GetComponent<Vehicle>())
                    neighbors.Add(colliders[i].gameObject);
            }
            timer = 0;
        }
    }
}

分离

分离的目的是使角色与周围其他角色保持一定距离。实现时,为了计算分离行为所需的操控力,需要搜索指定领域内的其他邻居,然后对每个邻居计算与角色的距离向量,进行一系列处理得到操控力

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

public class SteeringForSeparation : Steering
{
    public float comforDistance = 1;//可接受的距离
    public float multiplierInsideComfortDistance = 2;//当AI角色与邻居距离过近时的惩罚因子
 public override Vector3 Force()
    {
        Vector3 steeringForce = new Vector3(0, 0, 0);
        foreach(GameObject s in GetComponent<Radar>().neighbors)//遍历这个AI角色的邻居列表中的每个邻居
        {
            if ((s != null) && (s != this.gameObject))
            {
                Vector3 toNeighbor = transform.position - s.transform.position;//计算当前AI角色与邻居s之间的距离
                float length=toNeighbor.magnitude;
                steeringForce += toNeighbor.normalized / length;//计算这个邻居引起的操控力
                if (length < comforDistance)
                    steeringForce *= multiplierInsideComfortDistance;
            }
        }
        return steeringForce;
    }
}

队列

队列的目的是保持AI角色的运动朝向与邻居一致

通过迭代所有邻居,可以求出AI角色平均朝向向量以及速度平均向量,得到想要的朝向,然后减去AI当前朝向,就可以得到队列操控力

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

public class SteeringForAlignment : Steering
{
    public override Vector3 Force()
    {
        Vector3 averageDirection = new Vector3(0, 0, 0);//当前AI角色的邻居平均朝向
        int neighborCount = 0;
        foreach(GameObject s in GetComponent<Radar>().neighbors)//遍历邻居
        {
            if ((s != null) && (s != this.gameObject))
            {
                averageDirection += s.transform.forward;
                neighborCount++;
            }
        }
        if(neighborCount > 0)
        {
            averageDirection/=(float)neighborCount;//求出平均朝向向量
            averageDirection -= transform.forward;//求出操控向量
        }
        return averageDirection;
    }
}

聚集

聚集的目的是使多个AI角色聚到一起。实现时,迭代所有邻居求出AI角色位置的平均值,然后利用靠近行为,将这个平均值作为目标位置。

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

public class SteeringForCohesion :Steering
{
    private Vector3 desiredVelocity;
    private Vehicle m_vehicle;
    private float maxSpeed;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
    }

    public override Vector3 Force()
    {
        Vector3 steeringForce = new Vector3(0, 0, 0);//操控向量
        Vector3 centerOfMass = new Vector3(0, 0, 0);//AI角色的所有邻居的质心
        int neighborCount = 0;
        foreach (GameObject s in GetComponent<Radar>().neighbors)//遍历邻居
        {
            if ((s != null) && (s != this.gameObject))
            {
                centerOfMass += s.transform.position;
                neighborCount++;
            }
        }
        if (neighborCount > 0)
        {
            centerOfMass /= (float)neighborCount;//求出平均位置向量
            desiredVelocity = (centerOfMass - transform.position).normalized * maxSpeed;//与其速度为邻居平均位置与当前位置之差
            steeringForce = desiredVelocity - m_vehicle.velocity;
       }
        return steeringForce;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七七喝椰奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值