diff --git a/Boids/Assets/Scripts/Boid.cs b/Boids/Assets/Scripts/Boid.cs index 2f18707..62e2680 100644 --- a/Boids/Assets/Scripts/Boid.cs +++ b/Boids/Assets/Scripts/Boid.cs @@ -1,18 +1,20 @@ using System; using System.Collections.Generic; + using UnityEditor; using UnityEngine; // Boids are represented by a moving, rotating triangle. // Boids should communicate with sibling Boids via the parental BoidController object public class Boid : MonoBehaviour { [NonSerialized] private Vector2 _position = Vector2.zero; - [NonSerialized] private Vector2 _velocity; + [NonSerialized] public Vector2 _velocity; [NonSerialized] private bool _isWrappingX = false; [NonSerialized] private bool _isWrappingY = false; [NonSerialized] private Vector2 _centeringVelocity; [NonSerialized] public int latestNeighborhoodCount = 0; + [NonSerialized] public List latestNeighborhood; [NonSerialized] private BoidController _parent; - [NonSerialized] private bool _isFocused = false; + [NonSerialized] public bool _isFocused = false; private void Start() { _parent = transform.parent @@ -37,6 +39,10 @@ public class Boid : MonoBehaviour { List flock = _parent.localFlocks ? GetFlock(_parent.boids, _parent.boidGroupRange) : _parent.boids; latestNeighborhoodCount = flock.Count; + // Only update latest neighborhood when we need it for focused boid gizmo draws + if (_isFocused) + latestNeighborhood = flock; + // Calculate all offsets and multiple by magnitudes given if (flock.Count > 0) { if (_parent.enableCohesion) @@ -173,10 +179,13 @@ public class Boid : MonoBehaviour { // FOV Check if (_parent.enableFOVChecks) { - float angle1 = Mathf.Rad2Deg * -Mathf.Atan2(_velocity.x, _velocity.y); - float angle2 = Mathf.Rad2Deg * -Mathf.Atan2(boid._velocity.x, boid._velocity.y); - if (Mathf.Abs(angle2 - angle1) > _parent.boidFOV / 2) + float angle1 = Util.Vector2ToAngle(_velocity); // Current Heading + float angle2 = Util.AngleBetween(transform.position, boid.transform.position); // Angle between Boid and other Boid + + // Outside of FOV range, skip + if (Mathf.Abs(Mathf.DeltaAngle(angle1, angle2)) > _parent.boidFOV / 2) continue; + } flock.Add(boid); @@ -224,7 +233,7 @@ public class Boid : MonoBehaviour { DrawCircle(_parent.boidGroupRange, "Group Range Circle"); // Draw FOV Line - DrawArcCentered((_parent.boidSeparationRange + _parent.boidGroupRange) / 2f, transform.eulerAngles.z, + DrawArcCentered(_parent.boidGroupRange, Util.Vector2ToAngle(_velocity), _parent.boidFOV, "FOV Arc"); } @@ -254,7 +263,8 @@ public class Boid : MonoBehaviour { } private void DrawArcCentered(float radius, float centerAngle, float angleWidth, string childName) { - DrawArc(radius, centerAngle - angleWidth / 2f, centerAngle + angleWidth / 2f, childName); + float half = angleWidth / 2f; + DrawArc(radius, Util.AddAngle(centerAngle, -half), Util.AddAngle(centerAngle, half), childName); } private void DrawArc(float radius, float from, float to, string childName) { @@ -275,10 +285,11 @@ public class Boid : MonoBehaviour { // Calculate points for circle var pointCount = vertexCount + 1; var points = new Vector3[pointCount + 2]; + for (int i = 0; i < pointCount; i++) { // Magic '180 - angle' - var rad = Mathf.Deg2Rad * (180 - Mathf.LerpAngle(from, to, i / (float) pointCount)); - points[i + 1] = new Vector3(Mathf.Sin(rad) * radius, Mathf.Cos(rad) * radius, 0); + var rad = Mathf.Deg2Rad * Mathf.LerpAngle(from, to, i / (float) pointCount); + points[i + 1] = new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0) * radius; } points[0] = new Vector3(0, 0, 0); diff --git a/Boids/Assets/Scripts/Util.cs b/Boids/Assets/Scripts/Util.cs index d859b41..572a62b 100644 --- a/Boids/Assets/Scripts/Util.cs +++ b/Boids/Assets/Scripts/Util.cs @@ -6,13 +6,13 @@ public class Util { var sa = Mathf.Sin(a); var rx = v.x * ca - v.y * sa; - return new Vector2((float) rx, (float) (v.x * sa + v.y * ca)); + return new Vector2(rx, v.x * sa + v.y * ca); } // Returns a velocity (Vector2) at a random angle with a specific overall magnitude public static Vector2 GetRandomVelocity(float magnitude) { var vector = new Vector2(magnitude, magnitude); - return Util.RotateBy(vector, Random.Range(0, 180)); + return RotateBy(vector, Random.Range(0, 180)); } public static Vector2 MaxVelocity(Vector2 v, float max) { @@ -27,24 +27,25 @@ public class Util { return v; } - public static Vector2 AbsVector(Vector2 vector) { - return new Vector2(vector.x, vector.y); + public static float Vector2ToAngle(Vector2 velocity) { + float result = Mathf.Rad2Deg * Mathf.Atan2(velocity.y, velocity.x); + return (result < 0) ? (360f + result) : result; } -} -public class Scale { - private Vector2 _original; - private Vector2 _new; - private Vector2 _ratio; + public static float AngleBetween(Vector2 from, Vector2 to) { + Vector2 diff = to - from; + float result = Mathf.Rad2Deg * Mathf.Atan2(diff.y, diff.x); + return (result < 0) ? (360f + result) : result; + } - public float X => _ratio.x; - public float Y => _ratio.y; + public static float AngleDifference(float angle1, float angle2) { + return Mathf.Abs((angle1 > 180 ? 360 - angle1 : angle1) - (angle2 > 180 ? 360 - angle2 : angle2)); + } - public Scale(Vector2 original, Canvas canvas) : this(original, canvas.pixelRect.size) { } - - public Scale(Vector2 original, Vector2 resized) { - _original = original; - _new = resized; - _ratio = _original / _new; + public static float AddAngle(float angle, float add) { + float result = angle + add; + if (result > 360) return result - 360; + if (result < 0) return 360 + result; + return result; } } \ No newline at end of file