public class Boid { public Vector3 velocity; public Vector3 position;// private float cohesionRadius = 10; private float separationDistance = 5; private Boid[] boids; private Vector3 cohesion; private Vector3 separation; private int separationCount; private Vector3 alignment; private float maxSpeed = 15; public Boid(Vector3 pos) { position = pos; } }
public static Boid[] boids; static public Boid[] Sphere(Vector3 position, float radius) { List<Boid> mids = new List<Boid>(); for (int i = 0; i < boids.Length; i++) { if (Vector3.Distance(position, boids[i].position) < radius) mids.Add(boids[i]); } return mids.ToArray(); }
public void CalculateVelocity() { Vector3 newVelocity = Vector3.zero; cohesion = Vector3.zero; separation = Vector3.zero; separationCount = 0; alignment = Vector3.zero; boids = Boids.Sphere(position, cohesionRadius); // Physics.OverlapSphere foreach (Boid boid in boids) { alignment += boid.velocity;// cohesion += boid.position;// Transfom if (boid != this && (position - boid.position).magnitude < separationDistance) { separation += (position - boid.position) / (position - boid.position).magnitude; separationCount++; } } cohesion = cohesion / boids.Length; cohesion = cohesion - position; cohesion = Vector3.ClampMagnitude(cohesion, maxSpeed); if (separationCount > 0) separation = separation / separationCount; separation = Vector3.ClampMagnitude(separation, maxSpeed); alignment = alignment / boids.Length; alignment = Vector3.ClampMagnitude(alignment, maxSpeed); newVelocity += cohesion * 0.5f + separation * 15f + alignment * 1.5f; newVelocity = Vector3.ClampMagnitude(newVelocity, maxSpeed); velocity = (velocity * 2f + newVelocity) / 3f;// if (position.magnitude > 40) { velocity += -position.normalized; } }
public void Update() { position += velocity * Time.deltaTime; Debug.DrawRay(position, separation, Color.green);// Debug.DrawRay(position, cohesion, Color.magenta); Debug.DrawRay(position, alignment, Color.blue); }
using UnityEngine; using System.Collections; using System.Collections.Generic; public class Boids : MonoBehaviour { GameObject[] boidsObjects; // Use this for initialization void Start () { boidsObjects = new GameObject[1500];// 1500 boids = new Boid[boidsObjects.Length]; for (int i = 0; i < boids.Length; i++) { GameObject boid = GameObject.CreatePrimitive(PrimitiveType.Cube);// boid.transform.position = Random.insideUnitSphere * 35f; Destroy(boid.collider);// boidsObjects[i] = boid; boids[i] = new Boid(boid.transform.position);// Boid } StartCoroutine(UpdatePhis());// InvokeRepeating } IEnumerator UpdatePhis() { while (true) { int UpdateCount = 0; for (int i = 0; i < boids.Length; i++) { boids[i].CalculateVelocity(); UpdateCount++; if (UpdateCount > 100)// fps { yield return null; UpdateCount = 0; } } } } // Update is called once per frame void Update () { for (int i = 0; i < boids.Length; i++) { boids[i].Update();// boidsObjects[i].transform.position = boids[i].position; } } // OverlapSphere public static Boid[] boids; static public Boid[] Sphere(Vector3 position, float radius) { List<Boid> mids = new List<Boid>(); for (int i = 0; i < boids.Length; i++) { if (Vector3.Distance(position, boids[i].position) < radius) mids.Add(boids[i]); } return mids.ToArray(); } }
Source: https://habr.com/ru/post/283064/
All Articles