diff --git a/Boids/Assets/Editor.meta b/Boids/Assets/Editor.meta
new file mode 100644
index 0000000..1c500e2
--- /dev/null
+++ b/Boids/Assets/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1e2b3fe7393f42a592dad4e4c8b3bcf3
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Editor/DisableScriptReload.cs b/Boids/Assets/Editor/DisableScriptReload.cs
new file mode 100644
index 0000000..35b0b4b
--- /dev/null
+++ b/Boids/Assets/Editor/DisableScriptReload.cs
@@ -0,0 +1,37 @@
+ using UnityEditor;
+ using UnityEngine;
+
+ ///
+ /// Prevents script compilation and reload while in play mode.
+ /// The editor will show a the spinning reload icon if there are unapplied changes but will not actually
+ /// apply them until playmode is exited.
+ /// Note: Script compile errors will not be shown while in play mode.
+ /// Derived from the instructions here:
+ /// https://support.unity3d.com/hc/en-us/articles/210452343-How-to-stop-automatic-assembly-compilation-from-script
+ ///
+ [InitializeOnLoad]
+ public class DisableScriptReload
+ {
+ static DisableScriptReload()
+ {
+ EditorApplication.playModeStateChanged
+ += OnPlayModeStateChanged;
+ }
+
+ static void OnPlayModeStateChanged(PlayModeStateChange stateChange)
+ {
+ switch (stateChange) {
+ case (PlayModeStateChange.EnteredPlayMode): {
+ EditorApplication.LockReloadAssemblies();
+ Debug.Log ("Assembly Reload locked as entering play mode");
+ break;
+ }
+ case (PlayModeStateChange.ExitingPlayMode): {
+ Debug.Log ("Assembly Reload unlocked as exiting play mode");
+ EditorApplication.UnlockReloadAssemblies();
+ break;
+ }
+ }
+ }
+
+ }
\ No newline at end of file
diff --git a/Boids/Assets/Editor/DisableScriptReload.cs.meta b/Boids/Assets/Editor/DisableScriptReload.cs.meta
new file mode 100644
index 0000000..b9ed448
--- /dev/null
+++ b/Boids/Assets/Editor/DisableScriptReload.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6a46ee76c3b4473f9aff1b62cf8674dc
+timeCreated: 1589846269
\ No newline at end of file
diff --git a/Boids/Assets/Resources/Boid.prefab b/Boids/Assets/Resources/Boid.prefab
new file mode 100644
index 0000000..e6fab35
--- /dev/null
+++ b/Boids/Assets/Resources/Boid.prefab
@@ -0,0 +1,61 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1737515784064720040
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1737515784064720086}
+ - component: {fileID: 1737515784064720041}
+ - component: {fileID: 1737515784064720087}
+ m_Layer: 0
+ m_Name: Boid
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1737515784064720086
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1737515784064720040}
+ 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 &1737515784064720041
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1737515784064720040}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 39c543193832a9745a8985fb0e672377, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ fillColor: {r: 0, g: 0, b: 1, a: 1}
+--- !u!114 &1737515784064720087
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1737515784064720040}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 8fa9bbc6d9eb4c368be190feba139e7c, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ position: {x: 0, y: 0}
+ velocity: {x: 0.05, y: 0.05}
diff --git a/Boids/Assets/Resources/Boid.prefab.meta b/Boids/Assets/Resources/Boid.prefab.meta
new file mode 100644
index 0000000..a906512
--- /dev/null
+++ b/Boids/Assets/Resources/Boid.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 23e1eaaf69d4ef342ac3ef9590f6c642
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Resources/BoidController.prefab b/Boids/Assets/Resources/BoidController.prefab
new file mode 100644
index 0000000..1715918
--- /dev/null
+++ b/Boids/Assets/Resources/BoidController.prefab
@@ -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}
diff --git a/Boids/Assets/Resources/BoidController.prefab.meta b/Boids/Assets/Resources/BoidController.prefab.meta
new file mode 100644
index 0000000..e5fa322
--- /dev/null
+++ b/Boids/Assets/Resources/BoidController.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 79543cb69dabd5846a1789cccbdeefd8
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Resources/BoidController.preset b/Boids/Assets/Resources/BoidController.preset
new file mode 100644
index 0000000..07b41c9
--- /dev/null
+++ b/Boids/Assets/Resources/BoidController.preset
@@ -0,0 +1,324 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!181963792 &2655988077585873504
+Preset:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: BoidController
+ m_TargetType:
+ m_NativeTypeID: 114
+ m_ManagedTypePPtr: {fileID: 11500000, guid: 7d72224fef7a4fb4a998b0980fe0eb77,
+ type: 3}
+ m_ManagedTypeFallback:
+ m_Properties:
+ - target: {fileID: 0}
+ propertyPath: m_Enabled
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: m_EditorHideFlags
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: m_EditorClassIdentifier
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boidCount
+ value: 62
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boidGroupRange
+ value: 3.68
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boidStartVelocity
+ value: 0.05
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boidVelocityLimit
+ value: 0.3
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: separationRange
+ value: 2.82
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: separationBias
+ value: 0.01
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: alignmentBias
+ value: 0.05
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: cohesionBias
+ value: 0.05
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: localFlocks
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boidObject
+ value:
+ objectReference: {fileID: 1737515784064720040, guid: 23e1eaaf69d4ef342ac3ef9590f6c642,
+ type: 3}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.size
+ value: 62
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[0]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[1]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[2]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[3]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[4]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[5]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[6]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[7]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[8]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[9]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[10]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[11]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[12]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[13]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[14]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[15]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[16]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[17]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[18]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[19]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[20]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[21]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[22]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[23]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[24]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[25]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[26]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[27]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[28]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[29]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[30]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[31]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[32]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[33]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[34]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[35]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[36]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[37]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[38]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[39]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[40]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[41]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[42]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[43]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[44]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[45]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[46]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[47]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[48]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[49]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[50]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[51]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[52]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[53]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[54]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[55]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[56]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[57]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[58]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[59]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[60]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: boids.Array.data[61]
+ value:
+ objectReference: {fileID: 0}
+ - target: {fileID: 0}
+ propertyPath: cam
+ value:
+ objectReference: {fileID: 0}
diff --git a/Boids/Assets/Resources/BoidController.preset.meta b/Boids/Assets/Resources/BoidController.preset.meta
new file mode 100644
index 0000000..4648428
--- /dev/null
+++ b/Boids/Assets/Resources/BoidController.preset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6a61920c5c2f5524dbc2bffcf29fcbc5
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 2655988077585873504
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Scripts.meta b/Boids/Assets/Scripts.meta
new file mode 100644
index 0000000..4021c25
--- /dev/null
+++ b/Boids/Assets/Scripts.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: b50106a18d564518ba59ebb42e02f619
+timeCreated: 1589861330
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/Boid.cs b/Boids/Assets/Scripts/Boid.cs
new file mode 100644
index 0000000..4eccf38
--- /dev/null
+++ b/Boids/Assets/Scripts/Boid.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using UnityEngine;
+using Random = UnityEngine.Random;
+
+// Boids are represented by a moving, rotating triangle.
+// Boids should communicate with sibling Boids
+public class Boid : MonoBehaviour {
+ [NonSerialized] private Vector2 _position = Vector2.zero;
+ [NonSerialized] private Vector2 _velocity;
+ [NonSerialized] private bool _isWrappingX = false;
+ [NonSerialized] private bool _isWrappingY = false;
+ [NonSerialized] private Renderer[] _renderers;
+ [NonSerialized] private Vector2 _centeringVelocity;
+ [NonSerialized] private int _latestNeighborhoodCount = 0;
+ [NonSerialized] private BoidController _parent;
+ [NonSerialized] public bool isFocused = false;
+
+ void Start() {
+ _parent = transform.parent
+ .GetComponent(); // Parent used to perform physics math without caching
+ _renderers = transform.GetComponents(); // Acquire Renderer(s) to check for Boid visibility
+ _velocity = GetRandomVelocity(_parent.boidStartVelocity); // Acquire a Velocity Vector with a magnitude
+ _position = transform.position; // Track 2D position separately
+ transform.name = $"Boid {transform.GetSiblingIndex()}"; // Name the Game Object so Boids can be tracked somewhat
+ }
+
+ // void OnDrawGizmos() {
+ // var transform_ = transform;
+ // Handles.Label(transform_.position, $"{transform_.name} {_latestNeighborhoodCount}");
+ // }
+
+ void Update() {
+ // Updates the rotation of the object based on the Velocity
+ transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * -Mathf.Atan2(_velocity.x, _velocity.y));
+
+ // Skip Flock Calculations if wrapping in progress
+ if (_isWrappingX || _isWrappingY) {
+ UpdateCenteringVelocity();
+ _position += _centeringVelocity;
+ transform.position = _position;
+ }
+ else {
+ List flock = _parent.localFlocks ? GetFlock(_parent.boids, _parent.boidGroupRange) : _parent.boids;
+ _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) {
+ 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
+ _velocity = Util.LimitVelocity(_velocity, _parent.boidVelocityLimit);
+
+ _position += _velocity;
+ transform.position = new Vector3(_position.x, _position.y, 0);
+ }
+
+ if (_parent.edgeWrapping)
+ Wrapping();
+ }
+
+ private void Wrapping() {
+ if (!_parent.Space.Contains(_position)) {
+ // Activate Wrap, Move
+ Vector2 newPosition = transform.position;
+ Vector3 viewportPosition = _parent.Cam.WorldToViewportPoint(newPosition);
+
+ if (!_isWrappingX && (viewportPosition.x > 1 || viewportPosition.x < 0)) {
+ newPosition.x = -newPosition.x;
+ _isWrappingX = true;
+ UpdateCenteringVelocity();
+ }
+
+ if (!_isWrappingY && (viewportPosition.y > 1 || viewportPosition.y < 0)) {
+ newPosition.y = -newPosition.y;
+ _isWrappingY = true;
+ UpdateCenteringVelocity();
+ }
+
+ transform.position = newPosition;
+ _position = newPosition;
+ }
+ else {
+ // Within the rectangle again
+ _isWrappingX = false;
+ _isWrappingY = false;
+ }
+ }
+
+ // 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),
+ 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
+ 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
+ private Vector2 Rule1(List flock) {
+ Vector2 center = Vector2.zero;
+ foreach (Boid boid in flock)
+ center += boid._position;
+ center /= _parent.boids.Count;
+ return (center - this._position) / 100.0f;
+ }
+
+ // Separation: Steer to avoid other Boids within flock
+ private Vector2 Rule2(List flock) {
+ Vector2 c = Vector2.zero;
+ foreach (Boid boid in flock) {
+ Vector2 diff = boid._position - this._position;
+ if (diff.sqrMagnitude < _parent.boidSeparationRange * _parent.boidSeparationRange)
+ c -= diff;
+ }
+
+ return c;
+ }
+
+ // Alignment: Steer to align with the average heading of the flock
+ public Vector2 Rule3(List flock) {
+ if (flock.Count == 0)
+ return Vector2.zero;
+
+ Vector2 perceived = Vector2.zero;
+ foreach (Boid boid in flock)
+ perceived += boid._velocity;
+ perceived /= flock.Count;
+ 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 *
+ Mathf.InverseLerp(_parent.Boundary.xMin, _parent.Space.xMin, _position.x);
+ else if (_position.x > _parent.Boundary.xMax)
+ vector.x = -_parent.boundaryForce *
+ Mathf.InverseLerp(_parent.Boundary.xMax, _parent.Space.xMax, _position.x);
+
+ // Boundary Y Force
+ if (_position.y < _parent.Boundary.yMin)
+ vector.y = _parent.boundaryForce *
+ Mathf.InverseLerp(_parent.Boundary.yMin, _parent.Space.yMin, _position.y);
+ else if (_position.y > _parent.Boundary.yMax)
+ vector.y = -_parent.boundaryForce *
+ Mathf.InverseLerp(_parent.Boundary.yMax, _parent.Space.yMax, _position.y);
+ return vector;
+ }
+
+ // Returns a list of boids within a certain radius of the Boid, representing it's local 'flock'
+ private List GetFlock(List boids, float radius) {
+ return boids.Where(boid => boid != this && Vector2.Distance(this._position, boid._position) <= radius).ToList();
+ }
+
+ // Sets up a Boid to be 'Focused', adds Circles around object and changes color
+ public void enableFocusing() {
+ if (isFocused) {
+ Debug.LogWarning("enableFocusing called on previously focused Boid");
+ return;
+ }
+
+ isFocused = true;
+
+ // Update Mesh Material Color
+ var triangle = transform.GetComponent();
+ triangle.meshRenderer.material.color = Color.red;
+
+ // Add a LineRenderer for Radius Drawing
+ DrawCircle(_parent.boidSeparationRange, "Separation Range Circle");
+ // DrawCircle(_parent.boidGroupRange, "Group Range Circle");
+ }
+
+ // Disable focusing, removing LineRenderers and resetting color
+ public void DisableFocusing() {
+ isFocused = false;
+
+ // Update Mesh Material Color
+ var oldTriangle = transform.GetComponent();
+ oldTriangle.meshRenderer.material.color = new Color32(49, 61, 178, 255);
+
+ // Destroy Line Renderers (and child GameObjects)
+ foreach (Transform child in transform)
+ Destroy(child.gameObject);
+ }
+
+ private void DrawCircle(float radius, string childName) {
+ // Create a new child GameObject to hold the LineRenderer Component
+ var child = new GameObject(childName);
+ child.transform.SetParent(transform);
+ child.transform.position = transform.position;
+ var line = child.AddComponent();
+
+ _parent.circleVertexCount = 360;
+
+ // Setup LineRenderer properties
+ line.useWorldSpace = false;
+ line.startWidth = _parent.circleWidth;
+ line.endWidth = _parent.circleWidth;
+ line.positionCount = _parent.circleVertexCount + 1;
+
+ // Calculate points for circle
+ var pointCount = _parent.circleVertexCount + 1;
+ var points = new Vector3[pointCount];
+ for (int i = 0; i < pointCount; i++) {
+ var rad = Mathf.Deg2Rad * (i * 360f / _parent.circleVertexCount);
+ points[i] = new Vector3(Mathf.Sin(rad) * radius, 0, Mathf.Cos(rad) * radius);
+ }
+
+ // Add points to LineRenderer
+ line.SetPositions(points);
+ }
+}
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/Boid.cs.meta b/Boids/Assets/Scripts/Boid.cs.meta
new file mode 100644
index 0000000..b08e4ca
--- /dev/null
+++ b/Boids/Assets/Scripts/Boid.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8fa9bbc6d9eb4c368be190feba139e7c
+timeCreated: 1589638836
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/BoidController.cs b/Boids/Assets/Scripts/BoidController.cs
new file mode 100644
index 0000000..e912e11
--- /dev/null
+++ b/Boids/Assets/Scripts/BoidController.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using Debug = System.Diagnostics.Debug;
+using Random = UnityEngine.Random;
+
+public class BoidController : MonoBehaviour {
+ // Controller Attributes
+ [NonSerialized] public Rect Space;
+ [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;
+
+ // Boid Rules are multiplied by this to allow rule 'tweaking'
+ [SerializeField] public float globalBias = 1.0f;
+ [SerializeField] public float separationBias = 0.05f;
+ [SerializeField] public float alignmentBias = 0.05f;
+ [SerializeField] public float cohesionBias = 0.05f;
+ [SerializeField] public float boundaryBias = 1f;
+
+ // Enable/Disable Boid Rules
+ [SerializeField] public bool enableSeparation = true;
+ [SerializeField] public bool enableAlignment = true;
+ [SerializeField] public bool enableCohesion = true;
+ [SerializeField] public bool enableBoundary = 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 = 40; // The number of vertices for circles displayed
+ [SerializeField] public float circleWidth = 0.1f; // Width of circle
+
+
+ public Boid focusedBoid; // A focused Boid has special rendering
+ public GameObject boidObject; // Boid Object Prefab
+ [NonSerialized] public List boids = new List(); // Boid Objects for Updates
+ [NonSerialized] public Camera Cam; // Used for wrapping detection
+
+ private void OnDrawGizmos() {
+ // Draw a Wire Cube for the Rectangle Area
+ 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;
+
+ // Draw a Wire Cube for the Cam's Viewport Area
+ 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;
+ var screenHeight = screenTopRight.y - screenBottomLeft.y;
+ Gizmos.DrawWireCube(Cam.transform.position, new Vector3(screenWidth, screenHeight, 1));
+ }
+
+ void Update() {
+ // Focus a different Boid
+ if (Input.GetKeyDown("space")) {
+ // Undo previous Boid's focus
+ if (focusedBoid != null)
+ focusedBoid.DisableFocusing();
+
+ focusedBoid = boids[Random.Range(0, boids.Count)];
+ focusedBoid.enableFocusing();
+ }
+ }
+
+ private void Start() {
+ // Setup Camera
+ Cam = Camera.main;
+
+ // 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;
+
+ AddBoids(boidCount);
+ }
+
+ public void AddBoids(int n) {
+ for (int i = 0; i < n; i++) {
+ // Instantiate a Boid prefab within the boundaries randomly
+ Vector2 position = RandomPosition() * 0.95f;
+ GameObject boid = Instantiate(boidObject, position, Quaternion.identity);
+
+ // Set parent, add Boid component to Boids list
+ boid.transform.parent = transform;
+ boids.Add(boid.GetComponent());
+ }
+ }
+
+ public void RemoveBoids(int n) {
+ 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(-Boundary.size.x, Boundary.size.x) / 2,
+ Random.Range(-Boundary.size.y, Boundary.size.y) / 2);
+ }
+}
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/BoidController.cs.meta b/Boids/Assets/Scripts/BoidController.cs.meta
new file mode 100644
index 0000000..8adc59b
--- /dev/null
+++ b/Boids/Assets/Scripts/BoidController.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7d72224fef7a4fb4a998b0980fe0eb77
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Scripts/BoidControllerEditor.cs b/Boids/Assets/Scripts/BoidControllerEditor.cs
new file mode 100644
index 0000000..877237b
--- /dev/null
+++ b/Boids/Assets/Scripts/BoidControllerEditor.cs
@@ -0,0 +1,46 @@
+using UnityEditor;
+using UnityEngine;
+
+[CustomEditor(typeof(BoidController))]
+public class BoidControllerEditor : Editor {
+ public override void OnInspectorGUI() {
+ var controller = (BoidController) target;
+
+ // Boid Count update
+ EditorGUI.BeginChangeCheck();
+ 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;
+ if (diff > 1)
+ controller.AddBoids(diff);
+ else if (diff < 0)
+ controller.RemoveBoids(Mathf.Abs(diff));
+ }
+
+ // 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.boidSeparationRange = EditorGUILayout.Slider("Separation Range", controller.boidSeparationRange, 0.01f, 5.0f);
+ controller.boundaryForce = EditorGUILayout.Slider("Boundary Force", controller.boundaryForce, 0.25f, 1f);
+
+ // 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.localFlocks = EditorGUILayout.Toggle("Use Groups?", controller.localFlocks);
+ controller.edgeWrapping = EditorGUILayout.Toggle("Enforce Wrapping?", controller.edgeWrapping);
+
+ 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);
+
+ // Boid Rendering
+ controller.circleVertexCount = EditorGUILayout.IntSlider("Circle Vertex Count", controller.circleVertexCount, 4, 360);
+ controller.circleWidth = EditorGUILayout.Slider("Circle Line Width", controller.circleWidth, 0.01f, 1f);
+ }
+}
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/BoidControllerEditor.cs.meta b/Boids/Assets/Scripts/BoidControllerEditor.cs.meta
new file mode 100644
index 0000000..7c1ad9d
--- /dev/null
+++ b/Boids/Assets/Scripts/BoidControllerEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6ec8daef16a2459989f9d8b81bb248ea
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Scripts/Triangle.cs b/Boids/Assets/Scripts/Triangle.cs
new file mode 100644
index 0000000..09cb353
--- /dev/null
+++ b/Boids/Assets/Scripts/Triangle.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Linq;
+using UnityEngine;
+
+public class Triangle : MonoBehaviour {
+ [NonSerialized] public Color FillColor = Color.red;
+ public MeshRenderer meshRenderer;
+
+ private void Start () {
+ // Create Vector2 vertices
+ var vertices2D = new Vector2[] {
+ new Vector2(0,1),
+ new Vector2(0.4f,0),
+ new Vector2(-0.4f,0),
+ };
+
+ var vertices3D = System.Array.ConvertAll(vertices2D, v => v);
+
+ // Use the triangulator to get indices for creating triangles
+ var triangulator = new Triangulator(vertices2D);
+ var indices = triangulator.Triangulate();
+
+ // Generate a color for each vertex
+ var colors = Enumerable.Repeat(FillColor, vertices3D.Length).ToArray();
+
+ // Create the mesh
+ var mesh = new Mesh {
+ vertices = vertices3D,
+ triangles = indices,
+ colors = colors
+ };
+
+ mesh.RecalculateNormals();
+ mesh.RecalculateBounds();
+
+ // Set up game object with mesh;
+ meshRenderer = gameObject.AddComponent();
+ meshRenderer.material = (Material) Resources.Load("BoidMaterial");
+
+ var filter = gameObject.AddComponent();
+ filter.mesh = mesh;
+ }
+}
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/Triangle.cs.meta b/Boids/Assets/Scripts/Triangle.cs.meta
new file mode 100644
index 0000000..193ea0f
--- /dev/null
+++ b/Boids/Assets/Scripts/Triangle.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 39c543193832a9745a8985fb0e672377
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Scripts/Triangulator.cs b/Boids/Assets/Scripts/Triangulator.cs
new file mode 100644
index 0000000..be2d244
--- /dev/null
+++ b/Boids/Assets/Scripts/Triangulator.cs
@@ -0,0 +1,126 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+///
+/// This script can be used to split a 2D polygon into triangles.
+/// The algorithm supports concave polygons, but not polygons with holes,
+/// or multiple polygons at once.
+/// Taken from
+///
+public class Triangulator
+{
+ private readonly List _mPoints;
+
+ public Triangulator(IEnumerable points)
+ {
+ _mPoints = new List(points);
+ }
+
+ public int[] Triangulate()
+ {
+ var indices = new List();
+
+ var n = _mPoints.Count;
+ if (n < 3)
+ return indices.ToArray();
+
+ var V = new int[n];
+ if (Area() > 0) {
+ for (var v = 0; v < n; v++)
+ V[v] = v;
+ } else {
+ for (var v = 0; v < n; v++)
+ V[v] = n - 1 - v;
+ }
+
+ var nv = n;
+ var count = 2 * nv;
+ for (int m = 0, v = nv - 1; nv > 2;) {
+ if (count-- <= 0)
+ return indices.ToArray();
+
+ var u = v;
+ if (nv <= u)
+ u = 0;
+ v = u + 1;
+ if (nv <= v)
+ v = 0;
+ var w = v + 1;
+ if (nv <= w)
+ w = 0;
+
+ if (Snip(u, v, w, nv, V)) {
+ int a, b, c, s, t;
+ a = V[u];
+ b = V[v];
+ c = V[w];
+ indices.Add(a);
+ indices.Add(b);
+ indices.Add(c);
+ m++;
+ for (s = v, t = v + 1; t < nv; s++, t++)
+ V[s] = V[t];
+ nv--;
+ count = 2 * nv;
+ }
+ }
+
+ indices.Reverse();
+ return indices.ToArray();
+ }
+
+ private float Area()
+ {
+ var n = _mPoints.Count;
+ var A = 0.0f;
+ for (int p = n - 1, q = 0; q < n; p = q++) {
+ var pval = _mPoints[p];
+ var qval = _mPoints[q];
+ A += pval.x * qval.y - qval.x * pval.y;
+ }
+ return A * 0.5f;
+ }
+
+ private bool Snip(int u, int v, int w, int n, int[] V)
+ {
+ int p;
+ var A = _mPoints[V[u]];
+ var B = _mPoints[V[v]];
+ var C = _mPoints[V[w]];
+ if (Mathf.Epsilon > (B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x))
+ return false;
+ for (p = 0; p < n; p++) {
+ if (p == u || p == v || p == w)
+ continue;
+ var P = _mPoints[V[p]];
+ if (InsideTriangle(A, B, C, P))
+ return false;
+ }
+ return true;
+ }
+
+ private static bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
+ {
+ float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ float cCROSSap, bCROSScp, aCROSSbp;
+
+ ax = C.x - B.x;
+ ay = C.y - B.y;
+ bx = A.x - C.x;
+ by = A.y - C.y;
+ cx = B.x - A.x;
+ cy = B.y - A.y;
+ apx = P.x - A.x;
+ apy = P.y - A.y;
+ bpx = P.x - B.x;
+ bpy = P.y - B.y;
+ cpx = P.x - C.x;
+ cpy = P.y - C.y;
+
+ aCROSSbp = ax * bpy - ay * bpx;
+ cCROSSap = cx * apy - cy * apx;
+ bCROSScp = bx * cpy - by * cpx;
+
+ return aCROSSbp >= 0.0f && bCROSScp >= 0.0f && cCROSSap >= 0.0f;
+ }
+}
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/Triangulator.cs.meta b/Boids/Assets/Scripts/Triangulator.cs.meta
new file mode 100644
index 0000000..6f27df3
--- /dev/null
+++ b/Boids/Assets/Scripts/Triangulator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 959398144280d9145b8e5c4ec9f36837
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/Assets/Scripts/Util.cs b/Boids/Assets/Scripts/Util.cs
new file mode 100644
index 0000000..4e8cf5a
--- /dev/null
+++ b/Boids/Assets/Scripts/Util.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+
+public class Util {
+ public static Vector2 RotateBy(Vector2 v, float a) {
+ var ca = Mathf.Cos(a);
+ var sa = Mathf.Sin(a);
+ var rx = v.x * ca - v.y * sa;
+
+ return new Vector2((float) rx, (float) (v.x * sa + v.y * ca));
+ }
+
+ public static Vector2 LimitVelocity(Vector2 v, float max) {
+ if (v.magnitude > max) {
+ v = (v / v.magnitude) * max;
+ }
+
+ return v;
+ }
+
+ public static Vector2 AbsVector(Vector2 vector) {
+ return new Vector2(vector.x, vector.y);
+ }
+}
\ No newline at end of file
diff --git a/Boids/Assets/Scripts/Util.cs.meta b/Boids/Assets/Scripts/Util.cs.meta
new file mode 100644
index 0000000..f2b1332
--- /dev/null
+++ b/Boids/Assets/Scripts/Util.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9a91db8d912fd1d4dbebfaf69dad59e3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Boids/ProjectSettings/ProjectSettings.asset b/Boids/ProjectSettings/ProjectSettings.asset
index 511c333..f889fde 100644
--- a/Boids/ProjectSettings/ProjectSettings.asset
+++ b/Boids/ProjectSettings/ProjectSettings.asset
@@ -17,7 +17,7 @@ PlayerSettings:
defaultCursor: {fileID: 0}
cursorHotspot: {x: 0, y: 0}
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
- m_ShowUnitySplashScreen: 1
+ m_ShowUnitySplashScreen: 0
m_ShowUnitySplashLogo: 1
m_SplashScreenOverlayOpacity: 1
m_SplashScreenAnimation: 1
@@ -53,7 +53,7 @@ PlayerSettings:
iosShowActivityIndicatorOnLoading: -1
androidShowActivityIndicatorOnLoading: -1
iosAppInBackgroundBehavior: 0
- displayResolutionDialog: 0
+ displayResolutionDialog: 1
iosAllowHTTPDownload: 1
allowedAutorotateToPortrait: 1
allowedAutorotateToPortraitUpsideDown: 1