From c6556338cd6d40600676437ec4e05ed941192b74 Mon Sep 17 00:00:00 2001 From: Xevion Date: Mon, 25 May 2020 09:45:21 -0500 Subject: [PATCH 1/4] implement seblague's acceleration based formulas, requires tweaking --- Boids/Assets/Scripts/Boid.cs | 24 ++++++++++++++------ Boids/Assets/Scripts/BoidController.cs | 10 ++++---- Boids/Assets/Scripts/BoidControllerEditor.cs | 3 ++- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Boids/Assets/Scripts/Boid.cs b/Boids/Assets/Scripts/Boid.cs index b9cbe37..2a57668 100644 --- a/Boids/Assets/Scripts/Boid.cs +++ b/Boids/Assets/Scripts/Boid.cs @@ -38,24 +38,29 @@ public class Boid : MonoBehaviour { transform.position = _position; } else { + Vector2 acceleration = Vector2.zero; List flock = _parent.localFlocks ? GetFlock(_parent.boids, _parent.boidGroupRange) : _parent.boids; _latestNeighborhoodCount = flock.Count; // Calculate all offsets and multiple by magnitudes given if (flock.Count > 0) { if (_parent.enableCohesion) - _velocity += Rule1(flock) * _parent.cohesionBias; + acceleration += SteerTowards(Rule1(flock)) * _parent.cohesionBias; if (_parent.enableSeparation) - _velocity += Rule2(flock) * _parent.separationBias; + acceleration += SteerTowards(Rule2(flock)) * _parent.separationBias; if (_parent.enableAlignment) - _velocity += Rule3(flock) * _parent.alignmentBias; + acceleration += SteerTowards(Rule3(flock)) * _parent.alignmentBias; } if (_parent.enableBoundary && _parent.Boundary.Contains(_position)) - _velocity += RuleBound() * _parent.boundaryBias; + acceleration += SteerTowards(RuleBound()) * _parent.boundaryBias; // Limit the Velocity Vector to a certain Magnitude - _velocity = Util.MaxVelocity(_velocity, _parent.boidVelocityLimit); + _velocity += acceleration; + float speed = _velocity.magnitude; + Vector2 dir = _velocity / speed; + speed = Mathf.Clamp(speed, _parent.minSpeed, _parent.maxSpeed); + _velocity = dir * speed; _position += _velocity; transform.position = new Vector3(_position.x, _position.y, 0); @@ -65,6 +70,11 @@ public class Boid : MonoBehaviour { Wrapping(); } + private Vector2 SteerTowards(Vector2 vector) { + Vector2 v = vector.normalized * _parent.maxSpeed - _velocity; + return Vector2.ClampMagnitude(v, _parent.maxSteerForce); + } + private void Wrapping() { if (!_parent.Space.Contains(_position)) { // Activate Wrap, Move @@ -95,9 +105,9 @@ public class Boid : MonoBehaviour { // When Wrapping, this Velocity directs the Boid to the center of the Rectangle private void UpdateCenteringVelocity() { - _centeringVelocity = Util.RotateBy(new Vector2(_parent.boidVelocityLimit, _parent.boidVelocityLimit), + _centeringVelocity = Util.RotateBy(new Vector2(_parent.maxSpeed, _parent.maxSpeed), Vector2.Angle(_position, _parent.Space.center)); - _centeringVelocity = Util.MaxVelocity(_parent.Space.center - _position, _parent.boidVelocityLimit / 2.0f); + _centeringVelocity = Util.MaxVelocity(_parent.Space.center - _position, _parent.maxSpeed / 2.0f); } // Cohesion: Steer towards center of mass of flock diff --git a/Boids/Assets/Scripts/BoidController.cs b/Boids/Assets/Scripts/BoidController.cs index 482d4d9..4cc13e1 100644 --- a/Boids/Assets/Scripts/BoidController.cs +++ b/Boids/Assets/Scripts/BoidController.cs @@ -11,10 +11,11 @@ public class BoidController : MonoBehaviour { [NonSerialized] public Rect Boundary; // Swarm Attributes - public int boidCount = 50; - public float boidGroupRange = 1.0f; - public float boidStartVelocity = 0.005f; - [SerializeField] public float boidVelocityLimit = 1.0f; + [SerializeField] public int boidCount = 50; + [SerializeField] public float boidGroupRange = 1.0f; + [SerializeField] public float boidStartVelocity = 0.005f; + [SerializeField] public float minSpeed; + [SerializeField] public float maxSpeed; // Boid Rules are multiplied by this to allow rule 'tweaking' [SerializeField] public float globalBias = 1.0f; @@ -35,6 +36,7 @@ public class BoidController : MonoBehaviour { [SerializeField] public bool edgeWrapping = true; // Enforce Edge Wrapping [SerializeField] public int circleVertexCount = 40; // The number of vertices for circles displayed [SerializeField] public float circleWidth = 0.1f; // Width of circle + [SerializeField] public float maxSteerForce = 1f; public Boid focusedBoid; // A focused Boid has special rendering diff --git a/Boids/Assets/Scripts/BoidControllerEditor.cs b/Boids/Assets/Scripts/BoidControllerEditor.cs index c69e856..021d0cf 100644 --- a/Boids/Assets/Scripts/BoidControllerEditor.cs +++ b/Boids/Assets/Scripts/BoidControllerEditor.cs @@ -22,7 +22,8 @@ public class BoidControllerEditor : Editor { // Basic Boid Controller Attributes controller.boidGroupRange = EditorGUILayout.Slider("Group Range", controller.boidGroupRange, 0.01f, 7.5f); controller.boidStartVelocity = EditorGUILayout.Slider("Start Velocity", controller.boidStartVelocity, 0.01f, 5.0f); - controller.boidVelocityLimit = EditorGUILayout.Slider("Max Velocity", controller.boidVelocityLimit, 0.01f, 5.0f); + controller.minSpeed = EditorGUILayout.Slider("Minimum Speed", controller.minSpeed, 0.01f, 5.0f); + controller.maxSpeed = EditorGUILayout.Slider("Maximum Speed", controller.maxSpeed, 0.01f, 5.0f); controller.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 0.01f, 5.0f); controller.boundaryForce = EditorGUILayout.Slider("Boundary Force", controller.boundaryForce, 0.25f, 1f); From 2ed2fa11162695f89ef6b63f8272ef854acc256e Mon Sep 17 00:00:00 2001 From: Xevion Date: Mon, 25 May 2020 13:18:16 -0500 Subject: [PATCH 2/4] implement seblague's acceleration based formulas, may require tweaking --- Boids/Assets/Scripts/Boid.cs | 5 +++-- Boids/Assets/Scripts/BoidController.cs | 2 +- Boids/Assets/Scripts/BoidControllerEditor.cs | 15 ++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Boids/Assets/Scripts/Boid.cs b/Boids/Assets/Scripts/Boid.cs index 2a57668..34c04b6 100644 --- a/Boids/Assets/Scripts/Boid.cs +++ b/Boids/Assets/Scripts/Boid.cs @@ -56,14 +56,15 @@ public class Boid : MonoBehaviour { acceleration += SteerTowards(RuleBound()) * _parent.boundaryBias; // Limit the Velocity Vector to a certain Magnitude - _velocity += acceleration; + _velocity += acceleration * Time.deltaTime; float speed = _velocity.magnitude; Vector2 dir = _velocity / speed; speed = Mathf.Clamp(speed, _parent.minSpeed, _parent.maxSpeed); _velocity = dir * speed; - _position += _velocity; + _position += _velocity * Time.deltaTime; transform.position = new Vector3(_position.x, _position.y, 0); + // transform.forward = dir; } if (_parent.edgeWrapping) diff --git a/Boids/Assets/Scripts/BoidController.cs b/Boids/Assets/Scripts/BoidController.cs index 4cc13e1..211cfc5 100644 --- a/Boids/Assets/Scripts/BoidController.cs +++ b/Boids/Assets/Scripts/BoidController.cs @@ -36,7 +36,7 @@ public class BoidController : MonoBehaviour { [SerializeField] public bool edgeWrapping = true; // Enforce Edge Wrapping [SerializeField] public int circleVertexCount = 40; // The number of vertices for circles displayed [SerializeField] public float circleWidth = 0.1f; // Width of circle - [SerializeField] public float maxSteerForce = 1f; + [SerializeField] public float maxSteerForce = 10f; public Boid focusedBoid; // A focused Boid has special rendering diff --git a/Boids/Assets/Scripts/BoidControllerEditor.cs b/Boids/Assets/Scripts/BoidControllerEditor.cs index 021d0cf..05a323f 100644 --- a/Boids/Assets/Scripts/BoidControllerEditor.cs +++ b/Boids/Assets/Scripts/BoidControllerEditor.cs @@ -21,17 +21,18 @@ public class BoidControllerEditor : Editor { // Basic Boid Controller Attributes controller.boidGroupRange = EditorGUILayout.Slider("Group Range", controller.boidGroupRange, 0.01f, 7.5f); - controller.boidStartVelocity = EditorGUILayout.Slider("Start Velocity", controller.boidStartVelocity, 0.01f, 5.0f); - controller.minSpeed = EditorGUILayout.Slider("Minimum Speed", controller.minSpeed, 0.01f, 5.0f); - controller.maxSpeed = EditorGUILayout.Slider("Maximum Speed", controller.maxSpeed, 0.01f, 5.0f); + controller.boidStartVelocity = EditorGUILayout.Slider("Start Velocity", controller.boidStartVelocity, 0.01f, 25.0f); + controller.minSpeed = EditorGUILayout.Slider("Minimum Speed", controller.minSpeed, 0.01f, 25.0f); + controller.maxSpeed = EditorGUILayout.Slider("Maximum Speed", controller.maxSpeed, 0.01f, 25.0f); controller.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 0.01f, 5.0f); controller.boundaryForce = EditorGUILayout.Slider("Boundary Force", controller.boundaryForce, 0.25f, 1f); + controller.maxSteerForce = EditorGUILayout.Slider("Max Steer Force", controller.maxSteerForce, 1f, 100f); // Boid Bias Attributes - controller.alignmentBias = EditorGUILayout.Slider("Alignment Bias", controller.alignmentBias, 0.001f, 0.5f); - controller.cohesionBias = EditorGUILayout.Slider("Cohesion Bias", controller.cohesionBias, 0.001f, 0.5f); - controller.separationBias = EditorGUILayout.Slider("Separation Bias", controller.separationBias, 0.001f, 0.5f); - controller.boundaryBias = EditorGUILayout.Slider("Boundary Bias", controller.boundaryBias, 0.01f, 0.5f); + controller.alignmentBias = EditorGUILayout.Slider("Alignment Bias", controller.alignmentBias, 0.001f, 1.5f); + controller.cohesionBias = EditorGUILayout.Slider("Cohesion Bias", controller.cohesionBias, 0.001f, 1.5f); + controller.separationBias = EditorGUILayout.Slider("Separation Bias", controller.separationBias, 0.001f, 1.5f); + controller.boundaryBias = EditorGUILayout.Slider("Boundary Bias", controller.boundaryBias, 0.01f, 1.5f); controller.localFlocks = EditorGUILayout.Toggle("Use Groups?", controller.localFlocks); controller.edgeWrapping = EditorGUILayout.Toggle("Enforce Wrapping?", controller.edgeWrapping); From f8e2a7edfe7b8b47b6ce4f929633ae4f409d5b11 Mon Sep 17 00:00:00 2001 From: Xevion Date: Wed, 27 May 2020 01:24:00 -0500 Subject: [PATCH 3/4] tweaked algorithm values, fixed centering velocity breaking wrapping erratically due to improperly scaled velocities --- Boids/Assets/Scenes/Project.unity | 22 ++++++++++++---------- Boids/Assets/Scripts/Boid.cs | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Boids/Assets/Scenes/Project.unity b/Boids/Assets/Scenes/Project.unity index 0af8bb5..edcffc1 100644 --- a/Boids/Assets/Scenes/Project.unity +++ b/Boids/Assets/Scenes/Project.unity @@ -1252,25 +1252,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 7d72224fef7a4fb4a998b0980fe0eb77, type: 3} m_Name: m_EditorClassIdentifier: - boidCount: 153 - boidGroupRange: 2.69 - boidStartVelocity: 0.05 - boidVelocityLimit: 0.3 + boidCount: 205 + boidGroupRange: 5.9 + boidStartVelocity: 9.7 + minSpeed: 13.3 + maxSpeed: 17.2 globalBias: 1 - separationBias: 0.014 - alignmentBias: 0.194 - cohesionBias: 0.05 - boundaryBias: 0.063 + separationBias: 1.5 + alignmentBias: 0.599 + cohesionBias: 0.558 + boundaryBias: 1.085 enableSeparation: 1 enableAlignment: 1 enableCohesion: 1 enableBoundary: 1 - boidSeparationRange: 5 + boidSeparationRange: 1.67 boundaryForce: 0.352 localFlocks: 1 edgeWrapping: 1 circleVertexCount: 360 circleWidth: 0.1 + maxSteerForce: 100 focusedBoid: {fileID: 0} boidObject: {fileID: 1737515784064720040, guid: 23e1eaaf69d4ef342ac3ef9590f6c642, type: 3} @@ -4121,7 +4123,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1165952970} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -2.3479285, y: -7.3538084, z: -1779.8757} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} diff --git a/Boids/Assets/Scripts/Boid.cs b/Boids/Assets/Scripts/Boid.cs index 34c04b6..d31ece5 100644 --- a/Boids/Assets/Scripts/Boid.cs +++ b/Boids/Assets/Scripts/Boid.cs @@ -34,7 +34,7 @@ public class Boid : MonoBehaviour { // Skip Flock Calculations if wrapping in progress if (_isWrappingX || _isWrappingY) { UpdateCenteringVelocity(); - _position += _centeringVelocity; + _position += _centeringVelocity * Time.deltaTime; transform.position = _position; } else { @@ -63,7 +63,7 @@ public class Boid : MonoBehaviour { _velocity = dir * speed; _position += _velocity * Time.deltaTime; - transform.position = new Vector3(_position.x, _position.y, 0); + transform.position = _position; // transform.forward = dir; } From 1941534360adc3b70cfcaf28c0c2e18ae2daf1a6 Mon Sep 17 00:00:00 2001 From: Xevion Date: Wed, 27 May 2020 01:54:50 -0500 Subject: [PATCH 4/4] increase boundary/steering force limits, update inspector slider max values --- Boids/Assets/Scenes/Project.unity | 24 ++++++++++---------- Boids/Assets/Scripts/BoidControllerEditor.cs | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Boids/Assets/Scenes/Project.unity b/Boids/Assets/Scenes/Project.unity index edcffc1..16309aa 100644 --- a/Boids/Assets/Scenes/Project.unity +++ b/Boids/Assets/Scenes/Project.unity @@ -1252,27 +1252,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 7d72224fef7a4fb4a998b0980fe0eb77, type: 3} m_Name: m_EditorClassIdentifier: - boidCount: 205 - boidGroupRange: 5.9 - boidStartVelocity: 9.7 - minSpeed: 13.3 - maxSpeed: 17.2 + boidCount: 372 + boidGroupRange: 3.03 + boidStartVelocity: 14.8 + minSpeed: 12 + maxSpeed: 12 globalBias: 1 separationBias: 1.5 - alignmentBias: 0.599 - cohesionBias: 0.558 - boundaryBias: 1.085 + alignmentBias: 0.517 + cohesionBias: 0.451 + boundaryBias: 1.492 enableSeparation: 1 enableAlignment: 1 enableCohesion: 1 enableBoundary: 1 - boidSeparationRange: 1.67 - boundaryForce: 0.352 + boidSeparationRange: 2.3 + boundaryForce: 7.6 localFlocks: 1 edgeWrapping: 1 circleVertexCount: 360 circleWidth: 0.1 - maxSteerForce: 100 + maxSteerForce: 138 focusedBoid: {fileID: 0} boidObject: {fileID: 1737515784064720040, guid: 23e1eaaf69d4ef342ac3ef9590f6c642, type: 3} @@ -3524,7 +3524,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 1, y: 1} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -22.099976, y: -23.8} + m_AnchoredPosition: {x: -22.099976, y: -23.800049} m_SizeDelta: {x: 25, y: 25} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &945635207 diff --git a/Boids/Assets/Scripts/BoidControllerEditor.cs b/Boids/Assets/Scripts/BoidControllerEditor.cs index 05a323f..1ff1fbf 100644 --- a/Boids/Assets/Scripts/BoidControllerEditor.cs +++ b/Boids/Assets/Scripts/BoidControllerEditor.cs @@ -25,8 +25,8 @@ public class BoidControllerEditor : Editor { controller.minSpeed = EditorGUILayout.Slider("Minimum Speed", controller.minSpeed, 0.01f, 25.0f); controller.maxSpeed = EditorGUILayout.Slider("Maximum Speed", controller.maxSpeed, 0.01f, 25.0f); controller.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 0.01f, 5.0f); - controller.boundaryForce = EditorGUILayout.Slider("Boundary Force", controller.boundaryForce, 0.25f, 1f); - controller.maxSteerForce = EditorGUILayout.Slider("Max Steer Force", controller.maxSteerForce, 1f, 100f); + controller.boundaryForce = EditorGUILayout.Slider("Boundary Force", controller.boundaryForce, 0.25f, 50f); + controller.maxSteerForce = EditorGUILayout.Slider("Max Steer Force", controller.maxSteerForce, 1f, 200f); // Boid Bias Attributes controller.alignmentBias = EditorGUILayout.Slider("Alignment Bias", controller.alignmentBias, 0.001f, 1.5f);