From f5bfa7ace820a4990c1002cb705cb429616b5c94 Mon Sep 17 00:00:00 2001 From: Xevion Date: Sat, 6 Jun 2020 01:17:19 -0500 Subject: [PATCH] rename fov vars, add documentation & better comements to BoidController class, fix BoidControllerEditor redraw and implement circle/arc vertex/width attributes (no serialization with static class) --- Boids/Assets/Editor/BoidControllerEditor.cs | 28 ++++++----- Boids/Assets/Scripts/Boid.cs | 12 ++--- Boids/Assets/Scripts/BoidController.cs | 52 +++++++++++++++------ Boids/Assets/Scripts/ShapeDraw.cs | 14 +++--- 4 files changed, 67 insertions(+), 39 deletions(-) diff --git a/Boids/Assets/Editor/BoidControllerEditor.cs b/Boids/Assets/Editor/BoidControllerEditor.cs index eb2050f..2e4b6ed 100644 --- a/Boids/Assets/Editor/BoidControllerEditor.cs +++ b/Boids/Assets/Editor/BoidControllerEditor.cs @@ -9,7 +9,7 @@ public class BoidControllerEditor : UnityEditor.Editor { // Boid Count update EditorGUI.BeginChangeCheck(); - controller.boidCount = EditorGUILayout.IntSlider("Boid Count", controller.boidCount, 1, 500); + controller.boidCount = EditorGUILayout.IntSlider("Boid Count", controller.boidCount, -1, 500); // Check must be performed or Boids will be added outside of gameplay if (EditorGUI.EndChangeCheck() && Application.isPlaying) { int diff = controller.boidCount - controller.boids.Count; @@ -32,7 +32,7 @@ public class BoidControllerEditor : UnityEditor.Editor { controller.boidGroupRange = EditorGUILayout.Slider("Group Range", controller.boidGroupRange, 0.01f, 7.5f); controller.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 0.01f, 5.0f); - controller.boidFOV = EditorGUILayout.Slider("Boid FOV", controller.boidFOV, 1f, 360f); + controller.boidFov = EditorGUILayout.Slider("Boid FOV", controller.boidFov, 1f, 360f); redraw = redraw || EditorGUI.EndChangeCheck(); // Boid Bias Attributes @@ -47,20 +47,24 @@ public class BoidControllerEditor : UnityEditor.Editor { controller.enableAlignment = EditorGUILayout.Toggle("Enable Alignment?", controller.enableAlignment); controller.enableCohesion = EditorGUILayout.Toggle("Enable Cohesion?", controller.enableCohesion); controller.enableSeparation = EditorGUILayout.Toggle("Enable Separation?", controller.enableSeparation); - controller.enableBoundary = EditorGUILayout.Toggle("Enable Boundary?", controller.enableBoundary); - controller.enableFOVChecks = EditorGUILayout.Toggle("Enable FOV?", controller.enableFOVChecks); - - // Boid Rendering + + // Relevant to Focused Boid Rendering EditorGUI.BeginChangeCheck(); - controller.circleVertexCount = - EditorGUILayout.IntSlider("Circle Vertex Count", controller.circleVertexCount, 4, 360); - // controller.arcVertexCount = - // EditorGUILayout.IntSlider("Arc Vertex Count", controller.arcVertexCount, -1, 360); - controller.circleWidth = EditorGUILayout.Slider("Circle Line Width", controller.circleWidth, 0.01f, 1f); + controller.enableFovChecks = EditorGUILayout.Toggle("Enable FOV?", controller.enableFovChecks); + redraw = redraw || EditorGUI.EndChangeCheck(); + + controller.enableBoundary = EditorGUILayout.Toggle("Enable Boundary?", controller.enableBoundary); + + // Focused Boid Rendering Attributes + EditorGUI.BeginChangeCheck(); + ShapeDraw.CircleVertexCount = EditorGUILayout.IntSlider("Circle Vertex Count", ShapeDraw.CircleVertexCount, 4, 360); + ShapeDraw.ArcVertexCount = EditorGUILayout.IntSlider("Arc Vertex Count", ShapeDraw.ArcVertexCount + 2, 3, 360) - 2; + ShapeDraw.CircleWidth = EditorGUILayout.Slider("Circle Line Width", ShapeDraw.CircleWidth, 0.01f, 1f); + ShapeDraw.ArcWidth = EditorGUILayout.Slider("Arc Line Width", ShapeDraw.ArcWidth, 0.01f, 1f); redraw = redraw || EditorGUI.EndChangeCheck(); // Inspector elements related to Boid Focusing have changed - redraw! - if (redraw) + if (redraw && controller.focusedBoid != null) controller.focusedBoid.Draw(true); } } \ No newline at end of file diff --git a/Boids/Assets/Scripts/Boid.cs b/Boids/Assets/Scripts/Boid.cs index 20c4082..7fe24f1 100644 --- a/Boids/Assets/Scripts/Boid.cs +++ b/Boids/Assets/Scripts/Boid.cs @@ -180,12 +180,12 @@ public class Boid : MonoBehaviour { continue; // FOV Check - if (_parent.enableFOVChecks) { + if (_parent.enableFovChecks) { 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) + if (Mathf.Abs(Mathf.DeltaAngle(angle1, angle2)) > _parent.boidFov / 2) continue; } @@ -258,16 +258,16 @@ public class Boid : MonoBehaviour { lineRenderer.positionCount = 0; // Add a LineRenderer for Radius Drawing - if(_parent.enableFOVChecks) - ShapeDraw.DrawArc(_lineRenderers[2], _parent.boidFOV, _parent.boidGroupRange); // FOV Arc + if(_parent.enableFovChecks) + ShapeDraw.DrawArc(_lineRenderers[2], _parent.boidFov, _parent.boidGroupRange); // FOV Arc else ShapeDraw.DrawCircle(_lineRenderers[0], _parent.boidGroupRange); // Group Circle ShapeDraw.DrawCircle(_lineRenderers[1], _parent.boidSeparationRange); // Separation Circle - if (_parent.enableFOVChecks) { + if (_parent.enableFovChecks) { // Set FOV Arc rotation to mimic Boid transform rotation _lineRenderers[2].transform.rotation = transform.rotation; - _lineRenderers[2].transform.Rotate(0, 0, _parent.boidFOV / 2f); + _lineRenderers[2].transform.Rotate(0, 0, _parent.boidFov / 2f); } } } \ No newline at end of file diff --git a/Boids/Assets/Scripts/BoidController.cs b/Boids/Assets/Scripts/BoidController.cs index 1b7b711..5b0a320 100644 --- a/Boids/Assets/Scripts/BoidController.cs +++ b/Boids/Assets/Scripts/BoidController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using UnityEditor; using UnityEngine; +using Debug = System.Diagnostics.Debug; using Random = UnityEngine.Random; public class BoidController : MonoBehaviour { @@ -28,17 +29,17 @@ public class BoidController : MonoBehaviour { [SerializeField] public bool enableAlignment = true; [SerializeField] public bool enableCohesion = true; [SerializeField] public bool enableBoundary = true; - [SerializeField] public bool enableFOVChecks = true; + [SerializeField] public bool enableFovChecks = true; [SerializeField] public float boidSeparationRange = 2.3f; // Boid Separation rule's activation distance [SerializeField] public float boundaryForce = 10f; // The force applied when a Boid hits the boundary [SerializeField] public bool localFlocks = true; // Calculate Local 'Neighborhood' for flocks? [SerializeField] public bool edgeWrapping = true; // Enforce Edge Wrapping [SerializeField] public int circleVertexCount = 360; // The number of vertices for circles displayed - [SerializeField] public int arcVertexCount = -1; // The number of vertices for arcs displayed, -1 for auto + [SerializeField] public int arcVertexCount = 180; // The number of vertices for arcs displayed, -1 for auto [SerializeField] public float circleWidth = 0.1f; // Width of circle [SerializeField] public float maxSteerForce = 10f; - [SerializeField] public float boidFOV = 160; + [SerializeField] public float boidFov = 220; public Boid focusedBoid; // A focused Boid has special rendering @@ -51,11 +52,6 @@ public class BoidController : MonoBehaviour { Gizmos.DrawWireCube(Space.center, Space.size); Gizmos.DrawWireCube(Boundary.center, Boundary.size); -#if UNITY_EDITOR - if (focusedBoid != null) - Handles.DrawWireDisc(focusedBoid.transform.position, Vector3.forward, boidGroupRange); -#endif - if (Cam == null) return; @@ -75,6 +71,7 @@ public class BoidController : MonoBehaviour { if (focusedBoid != null) focusedBoid.DisableFocusing(); + // Pick a Boid randomly and enable focusing focusedBoid = boids[Random.Range(0, boids.Count)]; focusedBoid.EnableFocusing(); } @@ -87,25 +84,37 @@ public class BoidController : MonoBehaviour { } private void Start() { + SetupCamera(); + AddBoids(boidCount); + } + + /// + /// Utility function for setting up Camera and Boundary related variables. + /// + private void SetupCamera() { // Setup Camera Cam = Camera.main; + // Assert that there is an active camera + Debug.Assert(Cam != null, nameof(Cam) + " != null"); + // Size the Rectangle based on the Camera's Orthographic View float height = 2f * Cam.orthographicSize; var size = new Vector2(height * Cam.aspect, height); Space = new Rect((Vector2) transform.position - size / 2, size); Boundary = new Rect(Vector2.zero, Space.size * 0.95f); Boundary.center = Space.center; - - ShapeDraw.CircleWidth = circleWidth; - ShapeDraw.ArcWidth = circleWidth; - ShapeDraw.CircleVertexCount = circleVertexCount; - // ShapeDraw.ArcVertexCount = arcVertexCount; - - AddBoids(boidCount); } + /// + /// Adds a number of boids. + /// + /// public void AddBoids(int n) { + // Skip if negative or zero + if (n <= 0) + return; + for (int i = 0; i < n; i++) { // Instantiate a Boid prefab within the boundaries randomly Vector2 position = RandomPosition() * 0.95f; @@ -117,7 +126,12 @@ public class BoidController : MonoBehaviour { } } + /// + /// Removes a number of boids. + /// + /// Number of Boids to Remove public void RemoveBoids(int n) { + // If there are still Boids to remove and the number left to remove is more than 1 (post-decrementing) while (n-- > 0 && boids.Count >= 1) { int index = Random.Range(0, boids.Count - 1); @@ -132,12 +146,20 @@ public class BoidController : MonoBehaviour { } } + /// + /// Remove a Boid at a specific index in the Boids array. + /// + /// private void RemoveBoid(int index) { Boid boid = boids[index]; boids.RemoveAt(index); Destroy(boid.transform.gameObject); } + /// + /// Returns a random valid Boid position + /// + /// A Vector2 position within the Boid boundary area private Vector2 RandomPosition() { return new Vector2( Random.Range(-Boundary.size.x, Boundary.size.x) / 2, diff --git a/Boids/Assets/Scripts/ShapeDraw.cs b/Boids/Assets/Scripts/ShapeDraw.cs index 9707b03..77bd48c 100644 --- a/Boids/Assets/Scripts/ShapeDraw.cs +++ b/Boids/Assets/Scripts/ShapeDraw.cs @@ -4,12 +4,14 @@ /// A simple static utility class that assists with drawing shapes using the LineRenderer class. /// public static class ShapeDraw { - public static float CircleWidth = 1f; - public static float ArcWidth = 1f; - public static int CircleVertexCount = 360; - public static int ArcVertexCount = 77; - - + // Line width of the Circle and Arc + public static float CircleWidth = 0.1f; + public static float ArcWidth = 0.1f; + // Vertex count for Circle and Arc - the precision or detail level the curves have + // Low vertex counts are mostly unnoticeable until < 30 vertexes, where eventually squares and triangles appear + public static int CircleVertexCount = 180; + public static int ArcVertexCount = 90; + /// /// Draw a Arc aimed straight up with a certain angle width and radius. /// This Arc is not direct at any specific angle and start from 0 degrees and ends at angle degrees.