using UnityEngine; public class Boid : MonoBehaviour { public float speed = 0.2f; public int neighbourCount = 0; public float inertia = 0.2f; public float alignmentForce = 1.0f; public float cohesionForce = 1.0f; public float separationForce = 1.0f; public float separationDistance = 0.5f; public float bodyForce = 1; public SwarmControl sc; public Vector3 velocity = Vector3.zero; public Vector3 acceleration = Vector3.zero; readonly Collider[] results = new Collider[10]; public NeuroidNetwork neuroidNet = new(); public Neuroid bodyVector; public Neuroid cohesion; public Neuroid alignment; public Neuroid separation; public Neuroid target; public Neuroid totalForce; public int id; void Awake() { this.id = this.GetInstanceID(); sc = FindFirstObjectByType(); cohesion = new(neuroidNet) { name = "Cohesion", mode = Neuroid.Mode.Sum }; alignment = new(neuroidNet) { name = "Alignment", mode = Neuroid.Mode.Average }; separation = new(neuroidNet) { name = "Separation", mode = Neuroid.Mode.Sum }; target = new(neuroidNet) { name = "Target", mode = Neuroid.Mode.Sum }; totalForce = new(neuroidNet) { name = "Total force", mode = Neuroid.Mode.Sum }; totalForce.GetInputFrom(alignment, sc.alignmentForce); totalForce.GetInputFrom(cohesion, sc.cohesionForce); totalForce.GetInputFrom(separation, sc.separationForce); totalForce.GetInputFrom(target, sc.bodyForce); } void Update() { Physics.OverlapSphereNonAlloc(this.transform.position, 10, results); neighbourCount = 0; cohesion.ResetWeights(); alignment.ResetWeights(); separation.ResetWeights(); foreach (Collider c in results) { if (c == null || c as CapsuleCollider == null) continue; Boid neighbour = c.GetComponentInParent(); if (neighbour == null || neighbour == this) continue; Vector3 localPosition = neighbour.transform.position - this.transform.position; Vector3 relativeVelocity = neighbour.velocity - this.velocity; int id = neighbour.GetInstanceID(); Vector3 separationForce = -localPosition / localPosition.sqrMagnitude; // which is equivalent to -(localPosition.normalized / localPosition.magnitude) separation.SetInput(id, separationForce, sc.separationDistance); cohesion.SetInput(id, localPosition); alignment.SetInput(id, relativeVelocity); neighbourCount++; } Vector3 totalForceVector = totalForce.outputValue; //Debug.DrawRay(this.transform.position, totalForceVector, Color.magenta); this.velocity = (1 - sc.inertia) * (totalForceVector * Time.deltaTime) + sc.inertia * velocity + (sc.speed * transform.forward); //this.velocity = Vector3.ClampMagnitude(this.velocity, sc.speed); this.transform.position += this.velocity * Time.deltaTime; if (this.velocity != Vector3.zero) { Quaternion targetRotation = Quaternion.LookRotation(this.velocity); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f); // Adjust the speed of rotation } } }