Add new Boundary rules

This commit is contained in:
Xevion
2020-05-18 12:48:41 -05:00
parent ceebb7c974
commit 87da645dcd
4 changed files with 73 additions and 32 deletions

View File

@@ -27,10 +27,10 @@ public class Boid : MonoBehaviour {
transform.name = $"Boid {transform.GetSiblingIndex()}"; // Name the Game Object so Boids can be tracked somewhat
}
void OnDrawGizmos() {
void OnDrawGizmos() {
var transform_ = transform;
Handles.Label(transform_.position, $"{transform_.name} {_latestNeighborhoodCount}");
}
}
void Update() {
// Updates the rotation of the object based on the Velocity
@@ -47,11 +47,17 @@ void OnDrawGizmos() {
_latestNeighborhoodCount = flock.Count;
// Calculate all offsets and multiple by magnitudes given
Vector2 r1, r2, r3, r4;
r4 = _parent.Boundary.Contains(_position) ? Vector2.zero : RuleBound() * _parent.boundaryBias;
if (flock.Count > 0) {
Vector2 r1 = Rule1(flock) * _parent.cohesionBias;
Vector2 r2 = Rule2(flock) * _parent.separationBias;
Vector2 r3 = Rule3(flock) * _parent.alignmentBias;
_velocity += r1 + r2 + r3;
r1 = Rule1(flock) * _parent.cohesionBias;
r2 = Rule2(flock) * _parent.separationBias;
r3 = Rule3(flock) * _parent.alignmentBias;
_velocity += r1 + r2 + r3 + r4;
}
else {
_velocity += r4;
}
// Limit the Velocity Vector to a certain Magnitude
@@ -61,10 +67,11 @@ void OnDrawGizmos() {
transform.position = new Vector3(_position.x, _position.y, 0);
}
Wrapping();
if (_parent.edgeWrapping)
Wrapping();
}
void Wrapping() {
private void Wrapping() {
if (!_parent.Space.Contains(_position)) {
// Activate Wrap, Move
Vector2 newPosition = transform.position;
@@ -93,20 +100,20 @@ void OnDrawGizmos() {
}
// When Wrapping, this Velocity directs the Boid to the center of the Rectangle
void UpdateCenteringVelocity() {
private void UpdateCenteringVelocity() {
_centeringVelocity = Util.RotateBy(new Vector2(_parent.boidVelocityLimit, _parent.boidVelocityLimit),
Vector2.Angle(_position, _parent.Space.center));
_centeringVelocity = Util.LimitVelocity(_parent.Space.center - _position, _parent.boidVelocityLimit / 2.0f);
}
// Returns a velocity (Vector2) at a random angle with a specific overall magnitude
Vector2 GetRandomVelocity(float magnitude) {
private Vector2 GetRandomVelocity(float magnitude) {
Vector2 vector = new Vector2(magnitude, magnitude);
return Util.RotateBy(vector, Random.Range(0, 180));
}
// Cohesion: Steer towards center of mass of flock
Vector2 Rule1(List<Boid> flock) {
private Vector2 Rule1(List<Boid> flock) {
Vector2 center = Vector2.zero;
foreach (Boid boid in flock)
center += boid._position;
@@ -115,7 +122,7 @@ void OnDrawGizmos() {
}
// Separation: Steer to avoid other Boids within flock
Vector2 Rule2(List<Boid> flock) {
private Vector2 Rule2(List<Boid> flock) {
Vector2 c = Vector2.zero;
foreach (Boid boid in flock) {
Vector2 diff = boid._position - this._position;
@@ -127,7 +134,7 @@ void OnDrawGizmos() {
}
// Alignment: Steer to align with the average heading of the flock
Vector3 Rule3(List<Boid> flock) {
public Vector2 Rule3(List<Boid> flock) {
if (flock.Count == 0)
return Vector2.zero;
@@ -138,8 +145,27 @@ void OnDrawGizmos() {
return (perceived - _velocity) / 8.0f;
}
// Asks Boids to stay within the Boundaries set
private Vector2 RuleBound() {
Vector2 vector = Vector2.zero;
// Boundary X Force
if (_position.x < _parent.Boundary.xMin)
vector.x = _parent.boundaryForce;
else if (_position.x > _parent.Boundary.xMax)
vector.x = -_parent.boundaryForce;
// Boundary Y Force
if (_position.y < _parent.Boundary.yMin)
vector.y = _parent.boundaryForce;
else if (_position.y > _parent.Boundary.yMax)
vector.y = -_parent.boundaryForce;
return vector;
}
// Returns a list of boids within a certain radius of the Boid, representing it's local 'flock'
List<Boid> GetFlock(List<Boid> boids, float radius) {
private List<Boid> GetFlock(List<Boid> boids, float radius) {
return boids.Where(boid => boid != this && Vector2.Distance(this._position, boid._position) <= radius).ToList();
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Debug = System.Diagnostics.Debug;
using Random = UnityEngine.Random;
@@ -7,6 +8,7 @@ using Random = UnityEngine.Random;
public class BoidController : MonoBehaviour {
// Controller Attributes
[NonSerialized] public Rect Space;
[NonSerialized] public Rect Boundary;
// Swarm Attributes
public int boidCount = 50;
@@ -16,10 +18,13 @@ public class BoidController : MonoBehaviour {
public float boidSeparationRange = 2.3f;
// Bias changes how different rules influence individual Boids more or less
public float separationBias = 0.05f;
public float alignmentBias = 0.05f;
public float cohesionBias = 0.05f;
public bool localFlocks = true;
[SerializeField] public float separationBias = 0.05f;
[SerializeField] public float alignmentBias = 0.05f;
[SerializeField] public float cohesionBias = 0.05f;
[SerializeField] public float boundaryBias = 1f;
[SerializeField] public float boundaryForce = 10f;
[SerializeField] public bool localFlocks = true;
[SerializeField] public bool edgeWrapping = true;
public Boid focusedBoid; // A focused Boid has special rendering
public GameObject boidObject; // Boid Object Prefab
@@ -29,12 +34,16 @@ public class BoidController : MonoBehaviour {
private void OnDrawGizmos() {
// Draw a Wire Cube for the Rectangle Area
Gizmos.DrawWireCube(Space.center, Space.size);
Gizmos.DrawWireCube(Boundary.center, Boundary.size);
if (focusedBoid != null)
Handles.DrawWireDisc(focusedBoid.transform.position, Vector3.forward, boidGroupRange);
if (Cam == null)
return;
// Draw a Wire Cube for the Cam's Viewport Area
var position = transform.position;
Vector3 position = transform.position;
Vector3 screenBottomLeft = Cam.ViewportToWorldPoint(new Vector3(0, 0, position.z));
Vector3 screenTopRight = Cam.ViewportToWorldPoint(new Vector3(1, 1, position.z));
var screenWidth = screenTopRight.x - screenBottomLeft.x;
@@ -48,9 +57,11 @@ public class BoidController : MonoBehaviour {
// Size the Rectangle based on the Camera's Orthographic View
float height = 2f * Cam.orthographicSize;
Vector2 size = new Vector2(height * Cam.aspect, height);
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;
AddBoids(boidCount);
}
@@ -89,7 +100,7 @@ public class BoidController : MonoBehaviour {
private Vector2 RandomPosition() {
return new Vector2(
Random.Range(-Space.size.x, Space.size.x) / 2,
Random.Range(-Space.size.y, Space.size.y) / 2);
Random.Range(-Boundary.size.x, Boundary.size.x) / 2,
Random.Range(-Boundary.size.y, Boundary.size.y) / 2);
}
}

View File

@@ -20,16 +20,19 @@ public class BoidControllerEditor : Editor {
}
// Basic Boid Controller Attributes
controller.boidGroupRange = EditorGUILayout.Slider("Group Range", controller.boidGroupRange, 0.01f, 25.0f);
controller.boidGroupRange = EditorGUILayout.Slider("Group Range", controller.boidGroupRange, 0.01f, 10.0f);
controller.boidStartVelocity = EditorGUILayout.Slider("Start Velocity", controller.boidStartVelocity, 0.01f, 5.0f);
controller.boidVelocityLimit = EditorGUILayout.Slider("Max Velocity", controller.boidVelocityLimit, 0.01f, 7.5f);
controller.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 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.5f, 5.0f);
// Boid Bias Attributes
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.alignmentBias = EditorGUILayout.Slider("Alignment Bias", controller.alignmentBias, 0.001f, 0.75f);
controller.cohesionBias = EditorGUILayout.Slider("Cohesion Bias", controller.cohesionBias, 0.001f, 0.75f);
controller.separationBias = EditorGUILayout.Slider("Separation Bias", controller.separationBias, 0.001f, 0.75f);
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);
}
}

View File

@@ -1,10 +1,11 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Triangle : MonoBehaviour {
public Color fillColor = Color.blue;
[NonSerialized] public Color FillColor = Color.red;
private void Start () {
// Create Vector2 vertices
@@ -21,7 +22,7 @@ public class Triangle : MonoBehaviour {
var indices = triangulator.Triangulate();
// Generate a color for each vertex
var colors = Enumerable.Repeat(fillColor, vertices3D.Length).ToArray();
var colors = Enumerable.Repeat(FillColor, vertices3D.Length).ToArray();
// Create the mesh
var mesh = new Mesh {