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 const int BoundaryType = 1; public const int BoidType = 2; public SwarmControl sc; public Vector3 velocity = Vector3.zero; public Vector3 acceleration = Vector3.zero; private Bounds innerBounds; private Bounds outerBounds; public NeuroidNetwork neuroidNet = new(); public Perception perception; public Nucleus behaviour; public Neuroid totalForce; public int id; void Awake() { this.id = this.GetInstanceID(); sc = FindFirstObjectByType(); innerBounds = new(sc.transform.position, sc.spaceSize - 2 * sc.boundaryWidth); outerBounds = new(sc.transform.position, sc.spaceSize); perception = new Perception(neuroidNet); //behaviour = new Roaming(neuroidNet, perception, sc); behaviour = new Swarming(neuroidNet, perception, sc); totalForce = new(neuroidNet, "Total"); behaviour.AddReceiver(totalForce); } void Update() { Collider[] results = Physics.OverlapSphere(this.transform.position, sc.perceptionDistance); foreach (Collider c in results) { if (c as CapsuleCollider != null) { Boid neighbour = c.GetComponentInParent(); if (neighbour == null || neighbour == this) continue; Vector3 localPosition = neighbour.transform.position - this.transform.position; int thingId = neighbour.GetInstanceID(); perception.ProcessStimulus(thingId, BoidType, localPosition); //, neighbour.gameObject.name); } } if (!innerBounds.Contains(this.transform.position)) { Vector3 point = this.transform.position; Vector3 pointOnBounds = innerBounds.ClosestPoint(point); Vector3 desiredWorldSpace = (pointOnBounds - point).normalized * sc.speed; Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace); perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary"); } else { perception.RemoveStimulus(777); } Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue); this.velocity = (1 - sc.inertia) * (worldForce * Time.deltaTime) + sc.inertia * velocity; if (this.velocity.magnitude > 0) this.velocity = this.velocity.normalized * sc.speed; else this.velocity = this.transform.forward * 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 } neuroidNet.Update(); } Vector3 ClosestPointOnBoundsSurface(Bounds b, Vector3 p) { if (!b.Contains(p)) return b.ClosestPoint(p); Vector3 d = p - b.center; Vector3 ext = b.extents; float sx = ext.x / Mathf.Abs(d.x); float sy = ext.y / Mathf.Abs(d.y); float sz = ext.z / Mathf.Abs(d.z); float m = Mathf.Min(sx, Mathf.Min(sy, sz)); return b.center + d * m; } void OnDrawGizmosSelected() { Gizmos.DrawWireSphere(transform.position, sc.perceptionDistance); Gizmos.color = Color.yellow; Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue); Gizmos.DrawRay(transform.position, worldForce * 10); // Gizmos.color = Color.magenta; // Gizmos.DrawRay(transform.position, this.transform.TransformDirection(avoidance.outputValue) * 10); // Debug.Log($"Avoidance {roaming.avoidance.outputValue} Roaming {roaming.output.outputValue} Total {totalForce.outputValue}"); // Debug.Log($"WorldForce {worldForce} velocity {velocity} inertia {sc.inertia}"); Gizmos.color = Color.blue; Gizmos.DrawRay(transform.position, this.velocity * 10); } }