在unity中如何实现群体行为模拟步骤详解

it2023-03-05  79

版权申明:

本文为“优梦创客”原创文章,您可以自由转载,但必须加入完整的版权声明更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商业项目实战/每周直播/一对一指导)

目标

鱼的摆动鱼群的摆动鱼群的直行鱼群的游动及旋转鱼群被目标体影响方向

鱼的摆动

首先导入鱼的资源包, 点击Import导入(可能有点慢) 选取一条鱼拖入场景中 现在鱼是静止的,我们要让鱼的身体摆动起来: 把鱼的动画swim拖进Animator的Controller中,此时会自动出现一个控制器,我们把它取名为FishCtrl, 双击控制器FishCtrl,双击swim,为了使鱼的身体一直摆动,我们要勾上Looptime: 此时我们来运行一下,鱼已经可以摆动身体了:

鱼群的摆动

首先创建一Empty game object取名为Fishmanager,然后创建一个 Scripe取名为globolFlock,并把脚本拖给Fishmanager且打开脚本编写如下的代码:

using System.Collections; using System.Collections.Generic; public class globolFlock : MonoBehaviour { public GameObject fishPrefab; public static int tankSize = 5; static int numFish = 10; public static GameObject[] allFish = new GameObject[numFish]; // Use this for initialization void Start () { for (int i = 0; i < numFish; i++) { Vector3 pos = new Vector3(Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize)); allFish[i] = (GameObject)Instantiate(fishPrefab, pos, Quaternion.identity); } } // Update is called once per frame void Update(){ } }

把之前拖进来的鱼拖到Assets里面,把之前拖进来的鱼delect掉,因为我们不再需要它。再把鱼拖到Fish Prefab处。 此时运行:

鱼群的直行

创建一个Script取名为flock,并把脚本拖给 fish且打开脚本编写如下的代码:

using System.Collections; using System.Collections.Generic; using UnityEngine; public class flock : MonoBehaviour { public float speed = 0.1f; // Use this for initialization void Start () { speed = Random.Range(0.5f, 1); } // Update is called once per frame void Update () { transform.Translate(0, 0, Time.deltaTime * speed);transform.Translate(0, 0, Time.deltaTime * speed); } }

此时运行,小鱼能直行了:

鱼群的游动及旋转

首先打开我们的globolFlock脚本并把代码更改为以下所示:

using System.Collections; using System.Collections.Generic; using UnityEngine; public class globolFlock : MonoBehaviour { public GameObject fishPrefab; public static int tankSize = 5; static int numFish = 10; public static GameObject[] allFish = new GameObject[numFish]; public static Vector3 goalPos = Vector3.zero; // Use this for initialization void Start () { for (int i = 0; i < numFish; i++) { Vector3 pos = new Vector3(Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize)); allFish[i] = (GameObject)Instantiate(fishPrefab, pos, Quaternion.identity); } } // Update is called once per frame void Update() { if (Random.Range(0, 10000) < 50) { goalPos = new Vector3(Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize)); } } }

再打开我们的flock脚本并把代码更改为以下所示:

using System.Collections; using System.Collections.Generic; using UnityEngine; public class flock : MonoBehaviour { public float speed = 0.0001f; float rotationSpeed = 4.0f; Vector3 averageHeading; Vector3 averagePosition; float neighbourDistance = 3.0f; bool turning = false; // Use this for initialization void Start() { speed = Random.Range(0.5f, 1); } // Update is called once per frame void Update() { if (Vector3.Distance(transform.position, Vector3.zero) >= globolFlock.tankSize) { turning = true; } else turning = false; if (turning) { Vector3 direction = Vector3.zero - transform.position; transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime); speed = Random.Range(0.5f, 1); } else { if (Random.Range(0, 5) < 1) ApplyRules(); } transform.Translate(0, 0, Time.deltaTime * speed); } void ApplyRules() { GameObject[] gos; gos = globolFlock.allFish; Vector3 vcentre = Vector3.zero; Vector3 vavoid = Vector3.zero; float gSpeed = 0.1f; Vector3 goalPos = globolFlock.goalPos; float dist; int groupSize = 0; foreach (GameObject go in gos) { if (go != this.gameObject) { dist = Vector3.Distance(go.transform.position, this.transform.position); if (dist <= neighbourDistance) { vcentre += go.transform.position; groupSize++; if (dist < 1.0f) { vavoid = vavoid + (this.transform.position - go.transform.position); } flock anothrtFlock = go.GetComponent<flock>(); gSpeed = gSpeed + anothrtFlock.speed; } } } if (groupSize > 0) { vcentre = vcentre / groupSize + (goalPos - this.transform.position); speed = gSpeed / groupSize; Vector3 direction = (vcentre + vavoid) - transform.position; if (direction != Vector3.zero) transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime); } } }

此时运行,鱼群可以游动及旋转了:

鱼群被目标影响方向

首先还是先打开我们的globolFlock脚本然后添加以下的代码:

public GameObject goalPrefab; void Update() { if (Random.Range(0, 10000) < 50) { goalPos = new Vector3(Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize), Random.Range(-tankSize, tankSize)); goalPrefab.transform.position = goalPos; } }

现在我们创建一个Sphere,把它修改成适当尺寸并放入恰当位置,然后把Sphere拖到globolFlock的Goal Prefab里,

保存后运行游戏即可看到我们的鱼群朝着目标体游动且被目标体影响游动方向的效果了。
最新回复(0)