mirror of
https://github.com/Xevion/Boids.git
synced 2025-12-14 04:11:04 -06:00
Added new Editor for controlling Boid count, new methods for adding.removing Boids
This commit is contained in:
@@ -15,6 +15,7 @@ public class Boid : MonoBehaviour {
|
|||||||
[NonSerialized] private bool _isWrappingY = false;
|
[NonSerialized] private bool _isWrappingY = false;
|
||||||
[NonSerialized] private Renderer[] _renderers;
|
[NonSerialized] private Renderer[] _renderers;
|
||||||
[NonSerialized] private Vector2 _centeringVelocity;
|
[NonSerialized] private Vector2 _centeringVelocity;
|
||||||
|
[NonSerialized] private int _latestNeighborhoodCount = 0;
|
||||||
private BoidController _parent;
|
private BoidController _parent;
|
||||||
|
|
||||||
void Start() {
|
void Start() {
|
||||||
@@ -27,12 +28,8 @@ public class Boid : MonoBehaviour {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnDrawGizmos() {
|
void OnDrawGizmos() {
|
||||||
// Handles.color = _isWrappingX || _isWrappingY ? Color.red : Color.white;
|
|
||||||
// Vector3 viewportPosition = _parent.cam.WorldToViewportPoint(transform.position);
|
|
||||||
// Handles.Label(transform.position,
|
|
||||||
// $"{(Vector2) viewportPosition} {(_isWrappingX ? "Y" : "N")} {(_isWrappingY ? "Y" : "N")}");
|
|
||||||
var transform_ = transform;
|
var transform_ = transform;
|
||||||
Handles.Label(transform_.position, $"{transform_.name}");
|
Handles.Label(transform_.position, $"{transform_.name} {_latestNeighborhoodCount}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
@@ -47,6 +44,7 @@ public class Boid : MonoBehaviour {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
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;
|
||||||
|
|
||||||
// Calculate all offsets and multiple by magnitudes given
|
// Calculate all offsets and multiple by magnitudes given
|
||||||
if (flock.Count > 0) {
|
if (flock.Count > 0) {
|
||||||
@@ -70,7 +68,7 @@ public class Boid : MonoBehaviour {
|
|||||||
if (!_parent.Space.Contains(_position)) {
|
if (!_parent.Space.Contains(_position)) {
|
||||||
// Activate Wrap, Move
|
// Activate Wrap, Move
|
||||||
Vector2 newPosition = transform.position;
|
Vector2 newPosition = transform.position;
|
||||||
Vector3 viewportPosition = _parent.cam.WorldToViewportPoint(newPosition);
|
Vector3 viewportPosition = _parent.Cam.WorldToViewportPoint(newPosition);
|
||||||
|
|
||||||
if (!_isWrappingX && (viewportPosition.x > 1 || viewportPosition.x < 0)) {
|
if (!_isWrappingX && (viewportPosition.x > 1 || viewportPosition.x < 0)) {
|
||||||
newPosition.x = -newPosition.x;
|
newPosition.x = -newPosition.x;
|
||||||
@@ -101,6 +99,7 @@ public class Boid : MonoBehaviour {
|
|||||||
_centeringVelocity = Util.LimitVelocity(_parent.Space.center - _position, _parent.boidVelocityLimit / 2.0f);
|
_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) {
|
Vector2 GetRandomVelocity(float magnitude) {
|
||||||
Vector2 vector = new Vector2(magnitude, magnitude);
|
Vector2 vector = new Vector2(magnitude, magnitude);
|
||||||
return Util.RotateBy(vector, Random.Range(0, 180));
|
return Util.RotateBy(vector, Random.Range(0, 180));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Debug = System.Diagnostics.Debug;
|
||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
public class BoidController : MonoBehaviour {
|
public class BoidController : MonoBehaviour {
|
||||||
@@ -20,43 +21,43 @@ public class BoidController : MonoBehaviour {
|
|||||||
public float cohesionBias = 0.05f;
|
public float cohesionBias = 0.05f;
|
||||||
public bool localFlocks = true;
|
public bool localFlocks = true;
|
||||||
|
|
||||||
// Boid Object Prefab
|
public Boid focusedBoid; // A focused Boid has special rendering
|
||||||
public GameObject boidObject;
|
public GameObject boidObject; // Boid Object Prefab
|
||||||
|
[NonSerialized] public List<Boid> boids = new List<Boid>(); // Boid Objects for Updates
|
||||||
// Boid Objects for Updates
|
[NonSerialized] public Camera Cam; // Used for wrapping detection
|
||||||
[NonSerialized] [HideInInspector] public List<Boid> boids = new List<Boid>();
|
|
||||||
|
|
||||||
// Used for wrapping
|
|
||||||
public Camera cam;
|
|
||||||
|
|
||||||
private void OnDrawGizmos() {
|
private void OnDrawGizmos() {
|
||||||
// Draw a Wire Cube for the Rectangle Area
|
// Draw a Wire Cube for the Rectangle Area
|
||||||
Gizmos.DrawWireCube(Space.center, Space.size);
|
Gizmos.DrawWireCube(Space.center, Space.size);
|
||||||
|
|
||||||
|
if (Cam == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Draw a Wire Cube for the Cam's Viewport Area
|
// Draw a Wire Cube for the Cam's Viewport Area
|
||||||
Vector3 screenBottomLeft = cam.ViewportToWorldPoint(new Vector3(0, 0, transform.position.z));
|
var position = transform.position;
|
||||||
Vector3 screenTopRight = cam.ViewportToWorldPoint(new Vector3(1, 1, transform.position.z));
|
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;
|
var screenWidth = screenTopRight.x - screenBottomLeft.x;
|
||||||
var screenHeight = screenTopRight.y - screenBottomLeft.y;
|
var screenHeight = screenTopRight.y - screenBottomLeft.y;
|
||||||
Gizmos.DrawWireCube(cam.transform.position, new Vector3(screenWidth, screenHeight, 1));
|
Gizmos.DrawWireCube(Cam.transform.position, new Vector3(screenWidth, screenHeight, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start() {
|
private void Start() {
|
||||||
// Setup Camera
|
// Setup Camera
|
||||||
cam = Camera.main;
|
Cam = Camera.main;
|
||||||
|
|
||||||
// Size the Rectangle based on the Camera's Orthographic View
|
// Size the Rectangle based on the Camera's Orthographic View
|
||||||
float height = 2f * cam.orthographicSize;
|
float height = 2f * Cam.orthographicSize;
|
||||||
Vector2 size = new Vector2(height * cam.aspect, height);
|
Vector2 size = new Vector2(height * Cam.aspect, height);
|
||||||
Space = new Rect((Vector2) transform.position - size / 2, size);
|
Space = new Rect((Vector2) transform.position - size / 2, size);
|
||||||
|
|
||||||
// Add in Boid Objects / Spawn Boid Prefabs
|
AddBoids(boidCount);
|
||||||
for (int i = 0; i < boidCount; i++) {
|
}
|
||||||
// Generate a new position within the Rect boundaries (minus a little)
|
|
||||||
var position = new Vector2(
|
public void AddBoids(int n) {
|
||||||
Random.Range(-Space.size.x, Space.size.x) / 2 * 0.95f,
|
for (int i = 0; i < n; i++) {
|
||||||
Random.Range(-Space.size.y, Space.size.y) / 2 * 0.95f);
|
// Instantiate a Boid prefab within the boundaries randomly
|
||||||
// Spawn a new Boid prefab
|
Vector2 position = RandomPosition() * 0.95f;
|
||||||
GameObject boid = Instantiate(boidObject, position, Quaternion.identity);
|
GameObject boid = Instantiate(boidObject, position, Quaternion.identity);
|
||||||
|
|
||||||
// Set parent, add Boid component to Boids list
|
// Set parent, add Boid component to Boids list
|
||||||
@@ -64,4 +65,32 @@ public class BoidController : MonoBehaviour {
|
|||||||
boids.Add(boid.GetComponent<Boid>());
|
boids.Add(boid.GetComponent<Boid>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RemoveBoids(int n) {
|
||||||
|
print($"Removing {n} boids");
|
||||||
|
while (n-- > 0 && boids.Count >= 1) {
|
||||||
|
int index = Random.Range(0, boids.Count - 1);
|
||||||
|
|
||||||
|
// Only remove the focused Boid if it is the last one
|
||||||
|
if (boids[index] == focusedBoid)
|
||||||
|
if (boids.Count == 1)
|
||||||
|
RemoveBoid(1);
|
||||||
|
else
|
||||||
|
n++;
|
||||||
|
else
|
||||||
|
RemoveBoid(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveBoid(int index) {
|
||||||
|
Boid boid = boids[index];
|
||||||
|
boids.RemoveAt(index);
|
||||||
|
Destroy(boid.transform.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 RandomPosition() {
|
||||||
|
return new Vector2(
|
||||||
|
Random.Range(-Space.size.x, Space.size.x) / 2,
|
||||||
|
Random.Range(-Space.size.y, Space.size.y) / 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
57
Boids/Assets/BoidController.prefab
Normal file
57
Boids/Assets/BoidController.prefab
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &4181400676305357553
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 4181400676305357555}
|
||||||
|
- component: {fileID: 4181400676305357552}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: BoidController
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &4181400676305357555
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4181400676305357553}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &4181400676305357552
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4181400676305357553}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 7d72224fef7a4fb4a998b0980fe0eb77, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
boidCount: 1
|
||||||
|
boidGroupRange: 4.57
|
||||||
|
boidStartVelocity: 0.05
|
||||||
|
boidVelocityLimit: 0.5
|
||||||
|
separationRange: 2.5
|
||||||
|
separationBias: 0.05
|
||||||
|
alignmentBias: 0.5
|
||||||
|
cohesionBias: 0.01
|
||||||
|
localFlocks: 1
|
||||||
|
focusedBoid: {fileID: 0}
|
||||||
|
boidObject: {fileID: 1737515784064720040, guid: 23e1eaaf69d4ef342ac3ef9590f6c642,
|
||||||
|
type: 3}
|
||||||
7
Boids/Assets/BoidController.prefab.meta
Normal file
7
Boids/Assets/BoidController.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 79543cb69dabd5846a1789cccbdeefd8
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
23
Boids/Assets/BoidControllerEditor.cs
Normal file
23
Boids/Assets/BoidControllerEditor.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(BoidController))]
|
||||||
|
public class BoidControllerEditor : Editor {
|
||||||
|
public override void OnInspectorGUI() {
|
||||||
|
BoidController controller = (BoidController) target;
|
||||||
|
|
||||||
|
// Boid Count update
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
controller.boidCount = EditorGUILayout.IntSlider("Boid Count", controller.boidCount, 1, 500);
|
||||||
|
if (EditorGUI.EndChangeCheck() && Application.isPlaying) {
|
||||||
|
int diff = controller.boidCount - controller.boids.Count;
|
||||||
|
Debug.Log($"Difference: {diff}");
|
||||||
|
if (diff > 1)
|
||||||
|
controller.AddBoids(diff);
|
||||||
|
else if (diff < 0)
|
||||||
|
controller.RemoveBoids(Mathf.Abs(diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Boids/Assets/BoidControllerEditor.cs.meta
Normal file
3
Boids/Assets/BoidControllerEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ec8daef16a2459989f9d8b81bb248ea
|
||||||
|
timeCreated: 1589767516
|
||||||
Reference in New Issue
Block a user