Merge pull request #19 from Xevion/algorithm-improvements

Algorithm Improvements
This commit is contained in:
Xevion
2020-05-27 09:14:26 -05:00
committed by GitHub
4 changed files with 50 additions and 33 deletions

View File

@@ -1252,25 +1252,27 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7d72224fef7a4fb4a998b0980fe0eb77, type: 3} m_Script: {fileID: 11500000, guid: 7d72224fef7a4fb4a998b0980fe0eb77, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
boidCount: 153 boidCount: 372
boidGroupRange: 2.69 boidGroupRange: 3.03
boidStartVelocity: 0.05 boidStartVelocity: 14.8
boidVelocityLimit: 0.3 minSpeed: 12
maxSpeed: 12
globalBias: 1 globalBias: 1
separationBias: 0.014 separationBias: 1.5
alignmentBias: 0.194 alignmentBias: 0.517
cohesionBias: 0.05 cohesionBias: 0.451
boundaryBias: 0.063 boundaryBias: 1.492
enableSeparation: 1 enableSeparation: 1
enableAlignment: 1 enableAlignment: 1
enableCohesion: 1 enableCohesion: 1
enableBoundary: 1 enableBoundary: 1
boidSeparationRange: 5 boidSeparationRange: 2.3
boundaryForce: 0.352 boundaryForce: 7.6
localFlocks: 1 localFlocks: 1
edgeWrapping: 1 edgeWrapping: 1
circleVertexCount: 360 circleVertexCount: 360
circleWidth: 0.1 circleWidth: 0.1
maxSteerForce: 138
focusedBoid: {fileID: 0} focusedBoid: {fileID: 0}
boidObject: {fileID: 1737515784064720040, guid: 23e1eaaf69d4ef342ac3ef9590f6c642, boidObject: {fileID: 1737515784064720040, guid: 23e1eaaf69d4ef342ac3ef9590f6c642,
type: 3} type: 3}
@@ -3522,7 +3524,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 1} m_AnchorMin: {x: 1, y: 1}
m_AnchorMax: {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_SizeDelta: {x: 25, y: 25}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &945635207 --- !u!114 &945635207
@@ -4121,7 +4123,7 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1165952970} m_GameObject: {fileID: 1165952970}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 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_LocalScale: {x: 1, y: 1, z: 1}
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}

View File

@@ -34,37 +34,48 @@ public class Boid : MonoBehaviour {
// Skip Flock Calculations if wrapping in progress // Skip Flock Calculations if wrapping in progress
if (_isWrappingX || _isWrappingY) { if (_isWrappingX || _isWrappingY) {
UpdateCenteringVelocity(); UpdateCenteringVelocity();
_position += _centeringVelocity; _position += _centeringVelocity * Time.deltaTime;
transform.position = _position; transform.position = _position;
} }
else { else {
Vector2 acceleration = Vector2.zero;
List<Boid> flock = _parent.localFlocks ? GetFlock(_parent.boids, _parent.boidGroupRange) : _parent.boids; List<Boid> flock = _parent.localFlocks ? GetFlock(_parent.boids, _parent.boidGroupRange) : _parent.boids;
_latestNeighborhoodCount = flock.Count; _latestNeighborhoodCount = flock.Count;
// Calculate all offsets and multiple by magnitudes given // Calculate all offsets and multiple by magnitudes given
if (flock.Count > 0) { if (flock.Count > 0) {
if (_parent.enableCohesion) if (_parent.enableCohesion)
_velocity += Rule1(flock) * _parent.cohesionBias; acceleration += SteerTowards(Rule1(flock)) * _parent.cohesionBias;
if (_parent.enableSeparation) if (_parent.enableSeparation)
_velocity += Rule2(flock) * _parent.separationBias; acceleration += SteerTowards(Rule2(flock)) * _parent.separationBias;
if (_parent.enableAlignment) if (_parent.enableAlignment)
_velocity += Rule3(flock) * _parent.alignmentBias; acceleration += SteerTowards(Rule3(flock)) * _parent.alignmentBias;
} }
if (_parent.enableBoundary && _parent.Boundary.Contains(_position)) if (_parent.enableBoundary && _parent.Boundary.Contains(_position))
_velocity += RuleBound() * _parent.boundaryBias; acceleration += SteerTowards(RuleBound()) * _parent.boundaryBias;
// Limit the Velocity Vector to a certain Magnitude // Limit the Velocity Vector to a certain Magnitude
_velocity = Util.MaxVelocity(_velocity, _parent.boidVelocityLimit); _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.position = _position;
// transform.forward = dir;
} }
if (_parent.edgeWrapping) if (_parent.edgeWrapping)
Wrapping(); Wrapping();
} }
private Vector2 SteerTowards(Vector2 vector) {
Vector2 v = vector.normalized * _parent.maxSpeed - _velocity;
return Vector2.ClampMagnitude(v, _parent.maxSteerForce);
}
private void Wrapping() { private void Wrapping() {
if (!_parent.Space.Contains(_position)) { if (!_parent.Space.Contains(_position)) {
// Activate Wrap, Move // Activate Wrap, Move
@@ -95,9 +106,9 @@ public class Boid : MonoBehaviour {
// When Wrapping, this Velocity directs the Boid to the center of the Rectangle // When Wrapping, this Velocity directs the Boid to the center of the Rectangle
private void UpdateCenteringVelocity() { 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)); 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 // Cohesion: Steer towards center of mass of flock

View File

@@ -11,10 +11,11 @@ public class BoidController : MonoBehaviour {
[NonSerialized] public Rect Boundary; [NonSerialized] public Rect Boundary;
// Swarm Attributes // Swarm Attributes
public int boidCount = 50; [SerializeField] public int boidCount = 50;
public float boidGroupRange = 1.0f; [SerializeField] public float boidGroupRange = 1.0f;
public float boidStartVelocity = 0.005f; [SerializeField] public float boidStartVelocity = 0.005f;
[SerializeField] public float boidVelocityLimit = 1.0f; [SerializeField] public float minSpeed;
[SerializeField] public float maxSpeed;
// Boid Rules are multiplied by this to allow rule 'tweaking' // Boid Rules are multiplied by this to allow rule 'tweaking'
[SerializeField] public float globalBias = 1.0f; [SerializeField] public float globalBias = 1.0f;
@@ -35,6 +36,7 @@ public class BoidController : MonoBehaviour {
[SerializeField] public bool edgeWrapping = true; // Enforce Edge Wrapping [SerializeField] public bool edgeWrapping = true; // Enforce Edge Wrapping
[SerializeField] public int circleVertexCount = 40; // The number of vertices for circles displayed [SerializeField] public int circleVertexCount = 40; // The number of vertices for circles displayed
[SerializeField] public float circleWidth = 0.1f; // Width of circle [SerializeField] public float circleWidth = 0.1f; // Width of circle
[SerializeField] public float maxSteerForce = 10f;
public Boid focusedBoid; // A focused Boid has special rendering public Boid focusedBoid; // A focused Boid has special rendering

View File

@@ -21,16 +21,18 @@ public class BoidControllerEditor : Editor {
// Basic Boid Controller Attributes // Basic Boid Controller Attributes
controller.boidGroupRange = EditorGUILayout.Slider("Group Range", controller.boidGroupRange, 0.01f, 7.5f); 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.boidStartVelocity = EditorGUILayout.Slider("Start Velocity", controller.boidStartVelocity, 0.01f, 25.0f);
controller.boidVelocityLimit = EditorGUILayout.Slider("Max Velocity", controller.boidVelocityLimit, 0.01f, 5.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.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 0.01f, 5.0f);
controller.boundaryForce = EditorGUILayout.Slider("Boundary Force", controller.boundaryForce, 0.25f, 1f); 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 // Boid Bias Attributes
controller.alignmentBias = EditorGUILayout.Slider("Alignment Bias", controller.alignmentBias, 0.001f, 0.5f); controller.alignmentBias = EditorGUILayout.Slider("Alignment Bias", controller.alignmentBias, 0.001f, 1.5f);
controller.cohesionBias = EditorGUILayout.Slider("Cohesion Bias", controller.cohesionBias, 0.001f, 0.5f); controller.cohesionBias = EditorGUILayout.Slider("Cohesion Bias", controller.cohesionBias, 0.001f, 1.5f);
controller.separationBias = EditorGUILayout.Slider("Separation Bias", controller.separationBias, 0.001f, 0.5f); controller.separationBias = EditorGUILayout.Slider("Separation Bias", controller.separationBias, 0.001f, 1.5f);
controller.boundaryBias = EditorGUILayout.Slider("Boundary Bias", controller.boundaryBias, 0.01f, 0.5f); controller.boundaryBias = EditorGUILayout.Slider("Boundary Bias", controller.boundaryBias, 0.01f, 1.5f);
controller.localFlocks = EditorGUILayout.Toggle("Use Groups?", controller.localFlocks); controller.localFlocks = EditorGUILayout.Toggle("Use Groups?", controller.localFlocks);
controller.edgeWrapping = EditorGUILayout.Toggle("Enforce Wrapping?", controller.edgeWrapping); controller.edgeWrapping = EditorGUILayout.Toggle("Enforce Wrapping?", controller.edgeWrapping);