群组行为(群集行为)与视觉的实现

实现群组行为需要三个力:分离力,队列力,聚集力

image.png

资料:http://www.red3d.com/cwr/boids/
根据牛顿第二定律可算出加速度: A(加速度)=F(力)/M(质量)这里的力就是前面三个力的合力.
下面我们用代码实现

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

public class CrowAI : MonoBehaviour
{
    public float speed = 3;
    public Vector3 velocity = Vector3.forward;//当前速度
    private Vector3 startVelocity;

    public Transform target;

    public Vector3 sumForce = Vector3.zero;//和力
    public float m = 1;//质量


    public float separationDistance = 3;
    public List<GameObject> separationNeighbors = new List<GameObject>();//在separationDistance半径内的所有物体
    public float separationWeight = 1;
    public Vector3 separationForce = Vector3.zero;//分离的力

    public float alignmentDistance = 6;
    public Vector3 alignmentForce = Vector3.zero;//队列的力
    public float alignmentWeight = 1;
    public List<GameObject> alignmentNeighbors = new List<GameObject>();

    public Vector3 cohesionForce = Vector3.zero;//聚集的力
    public float cohesionWeight = 1;

    public float checkInterval = 0.2f;//多久计算一次合力


    public float animRandowTime = 2f;
    private Animation ani;

    private void  Start()
    {
        target = GameObject.Find("Target").transform;
        startVelocity = velocity;

        InvokeRepeating("CalcForce", 0, checkInterval);
        ani = GetComponentInChildren<Animation>();
        Invoke("playAnim", Random.Range(0, animRandowTime));
    }

    void playAnim()
    {
        ani.Play();
    }
    //计算合力
    void CalcForce()
    {
         sumForce = Vector3.zero;

         separationForce = Vector3.zero;//分离的力
         alignmentForce = Vector3.zero;//队列的力
         cohesionForce = Vector3.zero;//聚集的力
        separationNeighbors.Clear();
        //返回一个Collider数组,以transform.position为中心以separationDistance为半径发射一个球体, 其中所有碰撞到球体都包含在这个数组中(包含它自己)。
        Collider[] colliders = Physics.OverlapSphere(transform.position, separationDistance);
        foreach (Collider c in colliders)
        {
            if (c != null && c.gameObject != this.gameObject)
            {
                separationNeighbors.Add(c.gameObject);
            }
        }
        //计算分离的力
        foreach (GameObject neighbor in separationNeighbors)
        {
            Vector3 dir = transform.position - neighbor.transform.position;
            separationForce += dir.normalized.normalized/dir.magnitude;
        }
        if (separationNeighbors.Count > 0)
        {
            separationForce *= separationWeight;
            sumForce += separationForce;
        }
        //计算队列的力
        alignmentNeighbors.Clear();
        colliders = Physics.OverlapSphere(transform.position, alignmentDistance);
        foreach (Collider c in colliders)
        {
            if (c != null && c.gameObject != this.gameObject)
            {
                alignmentNeighbors.Add(c.gameObject);
            }
        }
        Vector3 avgDir = Vector3.zero;
        foreach (GameObject n in alignmentNeighbors)
        {
            avgDir += n.transform.forward;
        }
        if (alignmentNeighbors.Count > 0)
        {
            avgDir /= alignmentNeighbors.Count;
            alignmentForce = avgDir - transform.forward;
            alignmentForce *= alignmentWeight;
            sumForce += alignmentForce;
        }
        //聚集的力
        if ( alignmentNeighbors.Count > 0)
        {
            Vector3 center = Vector3.zero;

            foreach (GameObject n in alignmentNeighbors)
            {
                center += n.transform.position;
            }
            center /= alignmentNeighbors.Count;
            Vector3 dirToCenter = center - transform.position;
            cohesionForce += dirToCenter;
            cohesionForce *= cohesionWeight;
            sumForce += cohesionForce;
        }


        //保持恒定飞行速度的力
        Vector3 engineForce = velocity.normalized * startVelocity.magnitude;
        sumForce += engineForce * 0.1f;

        Vector3 targetDir = target.position - transform.position;
        sumForce += (targetDir.normalized - transform.forward) * speed;
    }
    private void Update()
    {  //A(加速度)=F(力)/M(质量)
        Vector3 a = sumForce / m;
        velocity += a * Time.deltaTime;

        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime * 3);


        transform.Translate(transform.forward * Time.deltaTime * velocity.magnitude, Space.World);

    }
}

这样鸟群飞起来比较凌乱,就有了AI鸟群的感觉.


image.png

image.png
视觉感知
public class Soldier : MonoBehaviour {
    public float ViewDistance = 5;
    public float ViewAngle=120;
    private Transform PlyerTrans;
    void Start () {
        PlyerTrans = GameObject.Find("Player").transform;
    }
    

    void Update () {
        if (Vector3.Distance(transform.position, PlyerTrans.position) <= ViewDistance)
        {
            //取得方向
            Vector3 playerDir = PlyerTrans.position - transform.position;
            //取得两个向量夹角
            float angle=Vector3.Angle(playerDir,transform.forward);
            if (angle <= ViewAngle/2)
            {
                Debug.Log("在视野范围内");
            }
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • 陈式太极拳手型、步型、步法、腿法 转载▼ 手型 1.拳型 四指并拢,向内卷屈于手心处,拇指屈压于中指和食指的...
    阿德乐阅读 2,450评论 0 0
  • 设计量子链的目的和意义:实现区块链与现实商业的无缝对接,取长补短,并且将其广泛的运用在移动客户端当中。共识机制:公...
    蜗牛说事阅读 310评论 0 0
  • 每天在手机上看到各种意外交通事故,觉得没什么,觉得这些情况离自己很远,但这几个月我发生两起骑车事故后,觉得交...
    灵台神矢阅读 92评论 0 0
  • 就是那棵老白杨 星空下孤独的站在那里 头发蓬乱瘦骨嶙峋 仰头一声长啸 划过寂静的夜空 却没有一丝回应 于是更加寂寞...
    尚善若心阅读 143评论 0 3