鱼群算法又称为群组行为,比如说走路,但是不能很规律的执行走路,要有人工智能的感觉的去执行走路,更加真实的去模拟现实,并且人与人之间不能拥挤到一起。常用与鸟群,鱼群,人群等 鱼群算法的规则: ——组的总控制器 ——控制组中的每个成员自身 一:前言
——分隔规则: 尽量避免与临近成员过于拥挤
——对准规则: 尽量与临近成员的平均方向一致
——内聚规则: 尽量朝临近成员的中心移动
二:效果演示
三:代码
using UnityEngine; using System.Collections.Generic; /// <summary> /// 组的总控制器(挂载到组长身上,可以是玩家也可以是要跟随的物体) /// </summary> public class GroupController : MonoBehaviour { private static List<GroupController> groups;//所有组 [Header("组中成员的层")] public LayerMask mask; [Header("组中成员的ID")] public int groupID = 0; [Header("组中成员始终保持的距离")] public float keepDis; [Header("组中成员始终保持的距离的权重")] public float keepWeight; [Header("多少距离算离得太近")] public float targetCloseDistance; [Header("组中成员停止移动的距离")] public float stopDis; /// <summary> /// 得到成员属于哪个组 /// </summary> /// <param name="index">成员ID</param> /// <returns></returns> public static GroupController GetGroup(int index) { if (groups == null) { groups = new List<GroupController>(FindObjectsOfType(typeof(GroupController)) as GroupController[]); } for (int i = 0; i < groups.Count; i++) { if (groups[i].groupID == index) { return groups[i]; } } throw new System.Exception("没有找到相同ID的组"); } }
using UnityEngine; /// <summary> /// 挂载到组中的每个成员身上 /// </summary> public class GroupMember : MonoBehaviour { private GroupController myGroup;//当前成员的GroupController组件 //速度和移动相关参数 private float targetSpeed; private float speed; private float currentSpeed; private Vector3 myMovement; [Header("属于的组ID")] public int groupId; [Header("移动速度")] public float moveSpeed; [Header("旋转速度")] public float rotateSpeed; private void Start() { myGroup = GroupController.GetGroup(groupId); } void Update() { Vector3 dis = myGroup.transform.position - transform.position; Vector3 dir = dis.normalized; //重新计算目的地距离权重 if (dis.magnitude < myGroup.targetCloseDistance) { dir *= dis.magnitude / myGroup.targetCloseDistance; } dir += GetAroundMemberInfo();//获取周围组的移动 //计算移动速度 if ((myGroup.transform.position - transform.position).magnitude < myGroup.stopDis) { targetSpeed = 0; } else { targetSpeed = moveSpeed; } speed = Mathf.Lerp(speed, targetSpeed, 2 * Time.deltaTime); //————————————————————移动 transform.right = -dir; Move(dir, speed); } /// <summary> /// 得到周围成员的信息 /// </summary> /// <returns></returns> private Vector3 GetAroundMemberInfo() { Collider2D[] c = Physics2D.OverlapCircleAll(transform.position, myGroup.keepDis, myGroup.mask);//获取周围成员 Vector3 dis; Vector3 v1 = Vector3.zero; Vector3 v2 = Vector3.zero; for (int i = 0; i < c.Length; i++) { GroupMember otherMember = c[i].GetComponent<GroupMember>(); dis = transform.position - otherMember.transform.position;//距离 v1 += dis.normalized * (1 - dis.magnitude / myGroup.keepDis);//查看与周围成员的距离 v2 += otherMember.myMovement;//查看周围成员移动方向 Debug.DrawLine(transform.position, otherMember.transform.position, Color.yellow); } return v1.normalized * myGroup.keepWeight + v2.normalized;//添加权重因素 } /// <summary> /// 移动 /// </summary> /// <param name="_dir">方向</param> /// <param name="_speed">速度</param> private void Move(Vector3 _dir, float _speed) { Vector3 finialDirection = _dir.normalized; float finialSpeed = _speed, finialRotate = 0; float rotateDir = Vector3.Dot(finialDirection, transform.right); float forwardDir = Vector3.Dot(finialDirection, transform.forward); if (forwardDir < 0) { rotateDir = Mathf.Sign(rotateDir); } if (forwardDir < -0.2f) { finialSpeed = Mathf.Lerp(currentSpeed, -_speed * 8, 4 * Time.deltaTime); } //——————————防抖 if (forwardDir < 0.98f) { finialRotate = Mathf.Clamp(rotateDir * 180, -rotateSpeed, rotateSpeed); } finialSpeed *= Mathf.Clamp01(_dir.magnitude); finialSpeed *= Mathf.Clamp01(1 - Mathf.Abs(rotateDir) * 0.8f); transform.Translate(Vector3.left * finialSpeed * Time.deltaTime); transform.Rotate(Vector3.forward * finialRotate * Time.deltaTime); currentSpeed = finialSpeed; myMovement = _dir * finialSpeed; } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算