群组行为是指多个对象组队同时行进的情况,我们可以坐下来,告诉每一个对象它该如何移动,但这样做的工作量太大。取而代之的是,我们去创建一个群组的领导,让它来为我们做这些,
 这样我们所要做的就只是设置一些规则,然后群组中的boid就会自行组队。在本章中,我们将学习如何在unity3d中实现这种群组行为。
每个boid都可以应用一下三个基本的规则:
分离(seperation):群组中的每个个体都与相邻个体保持一定距离
列队(alignment):群组以相同速度,向相同方向移动

凝聚(cohesion):群组中心保持最小距离

在本节中我们将创建自己的场景,场景里会有一群对象,并使用C#实现群组行为。有两个主要的组成部分:每个boid行为,以及维持并领导整个群组的主要控制者。我们的场景层级如图,在一个名为UnityFlockController的控制器下面有一些boid实体----UnityFlock。每一个UnityFlock实体都是一个boid对象,它们会引用其父对象UnityFlockController实体作为它们的领导者。UnityFlockController将会在到达目标位置后,随机的更新下一个目标位置。UnityFlock是一个预制体,这个预制体仅仅是一个立方体网格,并拥有UnityFlock脚本。我们可以使用任何更有意思的其他的网格标识这个预制体,比如小鸟。

个体行为

boid是Craig Reynold创造的术语,用以表示类似小鸟这样的对象。我们将使用这个术语描述群组中的每个个体对象。UnityFlock这个脚本控制群组中每一个boid的行为。

using UnityEngine;
using System.Collections;public class UnityFlock : MonoBehaviour {public float minSpeed = 20;//最小移动速度public float turnSpeed = 20;//旋转速度public float randomFreq = 20;//用来确定更新randomPush变量的次数public float randomForce = 20;//这个力产生出一个随机增长和降低的速度,并使得群组的移动看上去更加真实//alignment variables列队变量public float toOriginForce = 50;//用这个来保持所有boid在一个范围内,并与群组的原点保持一定距离public float toOriginRange = 100;//群组扩展的程度public float gravity = 2;//seperation variables分离变量public float avoidanceRadius = 50;public float avoidanceForce = 20;//这两个变量可以让每个boid个体之间保持最小距离//cohesion variables凝聚变量,这两个变量可用来与群组的领导者或群组的原点保持最小距离。public float followVelocity = 4;public float followRadius = 40;//这些变量控制了boid的移动private Transform origin;//设为父对象,以控制整个群组中的对象。private Vector3 velocity;private Vector3 normalizeedVelocity;private Vector3 randomPush;//更新基于randomFore的值private Vector3 originPush;//以下两个变量存储相邻boid的信息,当前boid需要知道群组中其他boid的信息private Transform[] objects;private UnityFlock[] otherFlocks;private Transform transformComponent;/**/void Start () {randomFreq = 1.0f / randomFreq;//将父类指定为originorigin = transform.parent;//Flock transformtransformComponent = transform;//Temporary components临时Component[] tempFlocks = null;//Get all the unity flock omponents from the parent transform in the groupif (transform.parent ){tempFlocks = transform.parent.GetComponentsInChildren<UnityFlock>();}//Assign and store all the flock objects in this groupobjects = new Transform[tempFlocks.Length];otherFlocks = new UnityFlock[tempFlocks.Length];for (int i = 0; i < tempFlocks.Length; i++){objects[i] = tempFlocks[i].transform;otherFlocks[i] = (UnityFlock)tempFlocks[i];}//Null Parent as the flok leader will be UnityFlockController objecttransform.parent = null;//Calculate random push depends on the random frequency providedStartCoroutine(UpdateRandom());}IEnumerator UpdateRandom(){while (true){randomPush = Random.insideUnitSphere * randomForce;yield return new WaitForSeconds(randomFreq + Random.Range(-randomFreq / 2.0f, randomFreq / 2.0f));}}void Update () {//internal variablesfloat speed = velocity.magnitude;//获取速度大小Vector3 avgVelocity = Vector3.zero;Vector3 avgPosition = Vector3.zero;float count = 0;float f = 0.0f;float d = 0.0f;Vector3 myPosition = transformComponent.position;Vector3 forceV;Vector3 toAvg;Vector3 wantedVel;for (int i = 0; i < objects.Length; i++){Transform transform = objects[i];if (transform != transformComponent){Vector3 otherPosition = transform.position;//Average position to calculate cohesionavgPosition += otherPosition;count++;//Directional vector from other flock to this flockforceV = myPosition - otherPosition;//Magnitude of that diretional vector(length)d = forceV.magnitude;//Add push value if the magnitude,the length of the vetor,is less than followRadius to the leaderif (d < followRadius){//calculate the velocity,the speed of the object,based current magnitude is less than the specified avoidance radiusif (d < avoidanceRadius){f = 1.0f - (d / avoidanceRadius);if (d > 0){avgVelocity += (forceV / d) * f * avoidanceForce;}}//just keep the current distance with the leaderf = d / followRadius;UnityFlock otherSealgull = otherFlocks[i];//we normalize the otherSealgull veloity vector to get the direction of movement,then wo set a new veloityavgVelocity += otherSealgull.normalizeedVelocity * f * followVelocity;}}}//上述代码实现了分离规则,首先,检查当前boid与其他boid之间的距离,并相应的更新速度,接下来,用当前速度除以群组中的boid的数目,计算出群组的平均速度if (count > 0){//Calculate the aveage flock veloity(Alignment)avgVelocity /= count;//Calculate Center value of the flock(Cohesion)toAvg = (avgPosition / count) - myPosition;}else{toAvg = Vector3.zero;}//Directional Vector to the leaderforceV = origin.position - myPosition;d = forceV.magnitude;f = d / toOriginRange;//Calculate the velocity of the flok to the leaderif (d > 0){originPush = (forceV / d) * f * toOriginForce;}if (speed < minSpeed && speed > 0){velocity = (velocity / speed) * minSpeed;}wantedVel = velocity;//Calculate final velocitywantedVel -= wantedVel * Time.deltaTime;wantedVel += randomPush * Time.deltaTime;wantedVel += originPush * Time.deltaTime;wantedVel += avgVelocity * Time.deltaTime;wantedVel += toAvg.normalized * gravity * Time.deltaTime;//Final Velocity to rotate the flock intovelocity = Vector3.RotateTowards(velocity, wantedVel, turnSpeed * Time.deltaTime, 100.0f);transformComponent.rotation = Quaternion.LookRotation(velocity);transformComponent.Translate(velocity * Time.deltaTime, Space.World);normalizeedVelocity = velocity.normalized;}
}

现在是时候创建控制器了,这个类会更新自己的位置,这样其他的boid个体对象就知道该去哪里,这个对象由前面的UnityFlock脚本中的origin变量引用而来。

using UnityEngine;
using System.Collections;public class UnityFlockController : MonoBehaviour {public Vector3 offset;public Vector3 bound;public float speed = 100.0f;private Vector3 initialPosition;private Vector3 nextMovementPoint;void Start () {initialPosition = transform.position;CalculateNextMovementPoint();}void Update () {transform.Translate(Vector3.forward * speed * Time.deltaTime);transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(nextMovementPoint - transform.position), 1.0f * Time.deltaTime);if (Vector3.Distance(nextMovementPoint,transform.position) <= 10.0f){CalculateNextMovementPoint();}}/*在我们的Update()方法中,检查控制器对象是否在最终目标位置附近,如果在,使用我们刚刚讨论过的CalculatNextMovementPoint()方法再次更新nextMovementPoint变量*/void CalculateNextMovementPoint(){float posX = Random.Range(initialPosition.x - bound.x, initialPosition.x + bound.x);float posY = Random.Range(initialPosition.y - bound.y, initialPosition.y + bound.y);float posZ = Random.Range(initialPosition.z - bound.z, initialPosition.z + bound.z);nextMovementPoint = initialPosition + new Vector3(posX, posY, posZ);}
}

UnityAI行为------群组行为相关推荐

  1. UnityAI行为-----群组行为之群集动画

    一.群集动画的简介 群落运动是自然界中非常有趣的现象.在天空中,我们可以看见大群的候鸟南飞,在陆地上,我们可以看见羚羊群,牛群在飞快的奔跑,在海洋里,鱼群的运动更是壮观.群落和其他相关的群体,他们运动 ...

  2. groupadd - 建 立 新 群 组

    GROUPADD(8)                                                        GROUPADD(8) 名称 groupadd - 建 立 新 群 ...

  3. 电脑修改ip地址方法cmd_Mac系统如何创建用户群组?苹果电脑修改用户名方法

    群组允许多个用户拥有相同的访问权限.例如,您可以将文件夹或文件的特定访问权限授予群组,这样该群组的所有成员都可以进行访问.您还可以将每个共享文件夹的特定访问权限分配给群组. Mac系统如何创建用户群组 ...

  4. Linux 的账号与群组(转)

    Linux 的账号与群组 管理员的工作中,相当重要的一环就是『管理账号』啦!因为整个系统都是你在管理的, 并且所有一般用户的账号申请,都必须要透过你的协助才行!所以你就必须要了解一下如何管理好一个服务 ...

  5. Zulip 2.0.3 发布,功能强大的群组聊天软件

    百度智能云 云生态狂欢季 热门云产品1折起>>>   Zulip 2.0.3 发布了,Zulip 是一个强大的开源群组聊天软件. 用 Python 编写,使用 Django 框架,支 ...

  6. Omad群组部署、依赖部署一键解决

    本文来自网易云社区 作者:李培斌 前言 基于omad部署平台实现一键部署的实践已有很多成功的经验,杭研QA的技术先锋们也在ks圈里有很多不同的文章去阐述关于这类需求的实现和思路,当然包括我们金融事业部 ...

  7. Linux 群组管理

    一.用户的主要群组和次要群组. goups  命令查看当前用户所属群组 第一个为主要群组,往后的为次要群组 小结:那个用户创建的那个目录(文件),这个目录(文件)的默认群组就是这个用户 二.用户的管理 ...

  8. php new httprequest,php安装HTTP_Request2及引用介绍(通过HTTP_Request创建微软人脸识别的群组 为例)...

    // This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents ...

  9. Linux用户、群组管理

    2019独角兽企业重金招聘Python工程师标准>>> 用户管理: 例1:useradd -u 510 -g 500 -d /home/user1 -s /bin/bash -p 1 ...

最新文章

  1. Matlab怎么计算信号的能量,用Matlab求离散讯号的能量与功率怎么编程
  2. vue axios 配置上服务器后报错'Access-Control-Allow-Origin' header](亲测)
  3. redis cluster集群模式简述
  4. cpu使用率_线程CPU使用率到底该如何计算?
  5. sendmail接收,转发权限控制文件access配置详解
  6. opencv图像像素操作方法
  7. 【雷达通信】基于matlab GUI多算法雷达一维恒虚警检测CFAR【含Matlab源码 874期】
  8. 整理一下CCF推荐期刊会议(A类)
  9. 法兰克机械手手动操作_学习FANUC机器人编程设定,必懂这2个技巧!
  10. oracle分页优化
  11. C语言求三角形斜边长
  12. linux文件系统ram,Linux常用文件系统概述-RAM篇
  13. 张家港python培训_张的解释|张的意思|汉典“张”字的基本解释
  14. microapp微前端基础使用
  15. 归一法的计算方法讲解_初三化学计算题中归一法,XY法,拆分法,分配法,K值法是怎样的,最好有具体的例子...
  16. mac小技巧之打印文件
  17. 火车头图片储存-火车头采集图片储存插件及教程
  18. 2020年8月试题分析-计算机网络原理
  19. 绝世唐门漫画的王秋儿
  20. 利用MRTG进行网络流量监控

热门文章

  1. Windows7 Update 无法更新补丁解决方法,IE11浏览器也可以通过更新系统自动安装
  2. java d 配置不生效_Tomcat启动失败问题 (指定的主资源集 [D:\java\apache-tomcat-9.0.35\webapps\AppManageSystem] 无效)...
  3. WPS解决编辑受限却忘记密码文件办法
  4. 基于萤火虫算法优化的lssvm回归预测附matlab代码
  5. MPAndroidChart 折线图动态设置不同折点的颜色
  6. 问卷调查(20145326蔡馨熠)
  7. 【C语言】程序阅读题
  8. excel中英文互译
  9. 国内优秀的java开源saas项目分享
  10. 【我的算法笔记】后序非递归遍历模板及其应用