From 21751f8ceaf93f7d441965320075c6f505b7a02b Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 11 Dec 2025 12:27:55 +0100 Subject: [PATCH] Brain object --- Assembly-CSharp.csproj | 1 + Assets/NanoBrain/Editor/NanoBrain_Editor.cs | 2 +- Assets/NanoBrain/Editor/NeuroidWindow.cs | 2 +- Assets/NanoBrain/Neuroid.cs | 13 +- Assets/NanoBrain/Nucleus.cs | 87 +++++--- Assets/NanoBrain/Perception.cs | 13 +- Assets/NanoBrain/Perceptoid.cs | 156 ++++++++++++++ Assets/NanoBrain/Perceptoid.cs.meta | 2 + Assets/NanoBrain/SensoryNeuroid.cs | 9 +- .../Editor/NanoBrainComponent_Editor.cs | 25 ++- .../VisualEditor/Editor/NanoBrainEditor.cs | 2 +- .../VisualEditor/Editor/NanoBrainInspector.cs | 196 +++++++++++++++--- .../VisualEditor/NanoBrainComponent.cs | 14 +- Assets/NanoBrain/VisualEditor/NanoBrainObj.cs | 55 ++++- Assets/Scenes/Boids/Boids.unity | 2 +- Assets/Scenes/Boids/New Nano Brain Obj.asset | 60 ------ Assets/Scenes/Boids/Prefabs/Boid.prefab | 2 +- Assets/Scenes/Boids/RoamingBrain.asset | 100 +++------ Assets/Scenes/Boids/Scripts/Boid.cs | 32 +-- Assets/Scenes/Boids/Scripts/RoamingNucleus.cs | 2 +- .../Scenes/Boids/Scripts/SwarmingNucleus.cs | 2 +- Assets/Scenes/Boids/SwarmingBrain.asset | 88 ++++++++ ...bj.asset.meta => SwarmingBrain.asset.meta} | 2 +- 23 files changed, 611 insertions(+), 256 deletions(-) create mode 100644 Assets/NanoBrain/Perceptoid.cs create mode 100644 Assets/NanoBrain/Perceptoid.cs.meta delete mode 100644 Assets/Scenes/Boids/New Nano Brain Obj.asset create mode 100644 Assets/Scenes/Boids/SwarmingBrain.asset rename Assets/Scenes/Boids/{New Nano Brain Obj.asset.meta => SwarmingBrain.asset.meta} (79%) diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 4067143..6b711a6 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -50,6 +50,7 @@ + diff --git a/Assets/NanoBrain/Editor/NanoBrain_Editor.cs b/Assets/NanoBrain/Editor/NanoBrain_Editor.cs index b877b32..51e6694 100644 --- a/Assets/NanoBrain/Editor/NanoBrain_Editor.cs +++ b/Assets/NanoBrain/Editor/NanoBrain_Editor.cs @@ -221,7 +221,7 @@ public class NanoBrain_Editor : Editor { if (neuroid is SensoryNeuroid sensoryNeuroid) { tooltip = new( $"{sensoryNeuroid.name}" + - $"\nThing {sensoryNeuroid.receptor.thingId}" + + $"\nThing {sensoryNeuroid.receptor.thingType}" + $"\nValue: {neuroid.outputValue}" + $"\nStale: {neuroid.stale}"); } diff --git a/Assets/NanoBrain/Editor/NeuroidWindow.cs b/Assets/NanoBrain/Editor/NeuroidWindow.cs index b3e17a2..133d99c 100644 --- a/Assets/NanoBrain/Editor/NeuroidWindow.cs +++ b/Assets/NanoBrain/Editor/NeuroidWindow.cs @@ -244,7 +244,7 @@ public class GraphEditorWindow : EditorWindow { if (neuroid is SensoryNeuroid sensoryNeuroid) { tooltip = new( $"{sensoryNeuroid.name}" + - $"\nThing {sensoryNeuroid.receptor.thingId}" + + $"\nThing {sensoryNeuroid.receptor.thingType}" + $"\nValue: {neuroid.outputValue}" + $"\nStale: {neuroid.stale}"); } diff --git a/Assets/NanoBrain/Neuroid.cs b/Assets/NanoBrain/Neuroid.cs index c2a2a30..92cf2f2 100644 --- a/Assets/NanoBrain/Neuroid.cs +++ b/Assets/NanoBrain/Neuroid.cs @@ -1,5 +1,6 @@ using UnityEngine; +[System.Serializable] public class Neuroid : Nucleus { public bool average = false; public bool inverse = false; @@ -13,9 +14,17 @@ public class Neuroid : Nucleus { // Debug.LogError("No neuroid network"); // } - public Neuroid(NanoBrainObj brain, string name) : base(brain, name) { + public Neuroid(NanoBrainObj brain, string name) : base(name) { + this.brain = brain; + if (this.brain != null) { + this.brain.nuclei.Add(this); + } + else + Debug.LogError("No neuroid network"); } + public Neuroid(string name): base(name) {} + public void SetWeight(Neuroid input, float weight) { //this.synapses[input] = weight; this.SetWeight((Nucleus)input, weight); @@ -30,7 +39,7 @@ public class Neuroid : Nucleus { public void SetInput(Neuroid input) { // if (this.synapses.ContainsKey(input) == false) // this.synapses[input] = 1.0f; - if (this.SynapseExists(input)) + if (this.SynapseExists(input) == false) this.SetWeight(input, 1.0f); UpdateState(); } diff --git a/Assets/NanoBrain/Nucleus.cs b/Assets/NanoBrain/Nucleus.cs index d78418e..4593628 100644 --- a/Assets/NanoBrain/Nucleus.cs +++ b/Assets/NanoBrain/Nucleus.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using UnityEngine; @@ -13,33 +14,53 @@ public class Nucleus { set => _name = value; } - //public readonly Dictionary synapses = new(); [SerializeField] - public List synapses = new(); - //public HashSet receivers = new(); + public List synapses = new(); [SerializeField] public List receivers = new(); #region Serialization - public void Rebuild(NanoBrainObj brain) { + [SerializeField] + protected string nucleusType; + + public virtual void Rebuild(NanoBrainObj brain) { if (this.synapses != null) { foreach (Synapse synapse in synapses) synapse.Rebuild(brain); } if (this.receivers == null) this.receivers = new(); - else - foreach (Receiver receiver in receivers) - receiver.Rebuild(brain); + else { + foreach (Receiver receiver in receivers.ToArray()) { + if (receiver.Rebuild(brain) == false) { + Debug.Log("Rebuilding failed, removing receiver."); + receivers.Remove(receiver); + } + } + } } - #endregion + public static Nucleus RebuildType(NanoBrainObj brain, Nucleus nucleus) { + if (string.IsNullOrEmpty(nucleus.nucleusType) == false) { + Type nucleusType = Type.GetType(nucleus.nucleusType); + if (nucleusType != null) { + object[] args = new object[] { brain, nucleus.name }; + Nucleus rebuiltNucleus = (Nucleus)Activator.CreateInstance(nucleusType, args); + rebuiltNucleus.Deserialize(nucleus); + return rebuiltNucleus; + } + } + return nucleus; + } + + public virtual void Deserialize(Nucleus nucleus) { } + + #endregion Serialization #region Runtime state (not serialized) - // public NanoBrain brain { get; protected set; } - public NanoBrainObj newBrain { get; protected set; } + public NanoBrainObj brain { get; protected set; } public virtual Vector3 outputValue { get; set; } @@ -50,12 +71,13 @@ public class Nucleus { #endregion Runtime state - public Nucleus(NanoBrainObj brain, string name) { - this.newBrain = brain; - if (this.newBrain != null) - this.newBrain.nuclei.Add(this); - else - Debug.LogError("No neuroid network"); + public Nucleus(string name) { + // this.brain = brain; + // if (this.brain != null) { + // this.brain.nuclei.Add(this); + // } + // else + // Debug.LogError("No neuroid network"); this._name = name; this.id = this.GetHashCode(); @@ -63,9 +85,7 @@ public class Nucleus { public virtual void AddReceiver(Nucleus receiver) { this.receivers.Add(new Receiver(receiver)); - //receiver.synapses[this] = 1.0f; // new(this); receiver.SetWeight(this, 1.0f); - //Debug.Log($"receiver # {this.receivers.Count} synapse count {receiver.synapses.Count}"); } public static void Delete(Nucleus nucleus) { @@ -73,15 +93,19 @@ public class Nucleus { if (synapse.nucleus.receivers.Count > 1) { // there is another nucleus feeding into this input nucleus synapse.nucleus.receivers.RemoveAll(r => r.nucleus == nucleus); - } else { + } + else { // No other links, delete it. Nucleus.Delete(synapse.nucleus); } } - foreach (Receiver receiver in nucleus.receivers) - receiver.nucleus.synapses.RemoveAll(s => s.nucleus == nucleus); + foreach (Receiver receiver in nucleus.receivers) { + if (receiver.nucleus != null && receiver.nucleus.synapses != null) + receiver.nucleus.synapses.RemoveAll(s => s.nucleus == nucleus); + } - nucleus.newBrain.nuclei.RemoveAll(n => n == nucleus); + nucleus.brain.nuclei.RemoveAll(n => n == nucleus); + nucleus.brain.GarbageCollection(); } public void GetInputFrom(Nucleus input, float weight = 1.0f) { @@ -113,6 +137,7 @@ public class Nucleus { Synapse newSynapse = new(nucleus, weight); synapses.Add(newSynapse); } + } [System.Serializable] @@ -139,6 +164,12 @@ public class Synapse { return; } } + foreach (Perceptoid perceptoid in brain.perceptei) { + if (perceptoid.id == this.nucleusId) { + this.nucleus = perceptoid; + return; + } + } Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}"); } } @@ -154,16 +185,18 @@ public class Receiver { this.nucleusId = nucleus.id; } - public void Rebuild(NanoBrainObj brain) { - if (brain == null) - return; + public bool Rebuild(NanoBrainObj brain) { + if (brain == null) { + return false; + } foreach (Nucleus nucleus in brain.nuclei) { if (nucleus.id == this.nucleusId) { this.nucleus = nucleus; - return; + return true; } } - Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}"); + Debug.LogWarning($"Receiver deserialization error: could not find nucleus with id {this.nucleusId}"); + return false; } } \ No newline at end of file diff --git a/Assets/NanoBrain/Perception.cs b/Assets/NanoBrain/Perception.cs index ccc254e..d6ee5a7 100644 --- a/Assets/NanoBrain/Perception.cs +++ b/Assets/NanoBrain/Perception.cs @@ -16,11 +16,18 @@ public class Perception : Nucleus { //public HashSet velocityReceivers { get; protected set; } public List velocityReceivers; - public Perception(NanoBrainObj brain) : base(brain, "Perception") { + public Perception(NanoBrainObj brain) : base("Perception") { this.positionReceivers = new(); this.velocityReceivers = new(); } + public Perceptoid GetPerception(int thingType = 0) { + foreach (Nucleus nucleus in this.brain.nuclei) { + if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.receptor.thingType == thingType)) + return perceptoid; + } + return null; + } public void SendPositions(Nucleus receivingNeuroid, int thingType = 0, float weight = 1.0f) { Receiver receiver = new() { @@ -55,7 +62,7 @@ public class Perception : Nucleus { for (int i = 0; i < sensoryNeuroids.Length; i++) { if (sensoryNeuroids[i] == null) availableIx = i; - else if (sensoryNeuroids[i].receptor.thingId == thingId) { + else if (sensoryNeuroids[i].receptor.thingType == thingId) { sensoryNeuroids[i].receptor.position = localPosition; return; } @@ -80,7 +87,7 @@ public class Perception : Nucleus { } else { Debug.Log($"new receptor for {thingId} at {availableIx}"); - neuroid = new(newBrain, thingId, name); + neuroid = new(brain, thingId, name); sensoryNeuroids[availableIx] = neuroid; } foreach (Receiver receiver in positionReceivers) { diff --git a/Assets/NanoBrain/Perceptoid.cs b/Assets/NanoBrain/Perceptoid.cs new file mode 100644 index 0000000..bea7cce --- /dev/null +++ b/Assets/NanoBrain/Perceptoid.cs @@ -0,0 +1,156 @@ +using UnityEngine; + +[System.Serializable] +public class Perceptoid : Neuroid { + // A neuroid which has no neurons as input + // But receives value from a receptor + public Receptor receptor; + public VelocityNeuroid velocityNeuroid; + + #region Serialization + + [SerializeField] + public int thingType; + + public override void Rebuild(NanoBrainObj brain) { + base.Rebuild(brain); + this.receptor = new Receptor() { + neuroid = this + }; + } + + public override void Deserialize(Nucleus nucleus) { + base.Deserialize(nucleus); + + if (nucleus is Perceptoid perceptoid) + this.receptor.thingType = perceptoid.thingType; + + // Point all receivers to this perceptoid instead of the default nucleus + foreach (Receiver receiver in nucleus.receivers) { + foreach (Synapse synapse in receiver.nucleus.synapses) { + if (synapse.nucleus == nucleus) + synapse.nucleus = this; + } + } + // Point all synapses to this perceptoid instead of the default nucleus + foreach (Synapse synapse in nucleus.synapses) { + foreach (Receiver receiver in synapse.nucleus.receivers) { + if (receiver.nucleus == nucleus) + receiver.nucleus = this; + } + } + // Copy all the synapses + this.synapses = nucleus.synapses; + // Copy all receivers + this.receivers = nucleus.receivers; + } + + #endregion Serialization + + public Perceptoid(NanoBrainObj brain, string name) : base(name) { + this.brain = brain; + if (this.brain != null) { + this.brain.perceptei.Add(this); + } + else + Debug.LogError("No neuroid network"); + + this.nucleusType = nameof(Perceptoid); + this.name = name; + this.receptor = new Receptor { + neuroid = this + }; + } + + public Perceptoid(NanoBrainObj brain, int thingType, string name = "sensor") : base(name) { + this.brain = brain; + if (this.brain != null) { + this.brain.perceptei.Add(this); + } + else + Debug.LogError("No neuroid network"); + + this.nucleusType = nameof(Perceptoid); + this.name = name; + this.thingType = thingType; + this.receptor = new Receptor { + neuroid = this, + thingType = thingType + }; + this.velocityNeuroid = new(brain, name + ": velocity"); + // The velocity neuroid received position data from this + this.AddReceiver(velocityNeuroid); + } + + public void Replace(int thingType, string name = "sensor") { + this.name = name; + + this.thingType = thingType; + this.receptor.thingType = thingType; + this.receptor.localPosition = Vector3.zero; + + this.outputValue = Vector3.zero; + this.receivers = new(); + this.AddReceiver(velocityNeuroid); + + this.velocityNeuroid.Replace(name + ": velocity"); + } + + public override void UpdateState() { + Vector3 result = receptor.localPosition; + foreach (Synapse synapse in this.synapses) { + Nucleus nucleus = synapse.nucleus; + float weight = synapse.weight; + Vector3 direction = nucleus.outputValue.normalized; + float magnitude = nucleus.outputValue.magnitude; + + magnitude = weight * Mathf.Pow(magnitude, exponent); + if (inverse) + magnitude = 1 / magnitude; + result += direction * magnitude; + } + if (average && this.synapses.Count > 0) + result /= this.synapses.Count + 1; + + this.outputValue = result; + foreach (Receiver receiver in this.receivers) + if (receiver.nucleus is Neuroid neuroid) + neuroid.SetInput(this); + this.stale = 0; + } + + public static Perceptoid GetPerception(NanoBrainObj brain, int thingType = 0) { + foreach (Nucleus nucleus in brain.nuclei) { + if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.thingType == thingType)) + return perceptoid; + } + return null; + } + + public static void ProcessStimulus(NanoBrainObj brain, int thingType, Vector3 lcoalPosition) { + Perceptoid selectedPerceptoid = null; + foreach (Perceptoid nucleus in brain.perceptei) { + if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.thingType == thingType)) + if (selectedPerceptoid == null) { + selectedPerceptoid = perceptoid; + if (perceptoid.isSleeping) { + break; + } + } + else if (perceptoid.receptor.position.magnitude < selectedPerceptoid.receptor.position.magnitude) + selectedPerceptoid = perceptoid; + } + if (selectedPerceptoid == null) { + Debug.Log("No perceptoid selected, stimulus is ignored"); + return; + } + selectedPerceptoid.receptor.position = lcoalPosition; + } + public static Receptor GetReceptor(NanoBrainObj brain, int thingType) { + foreach (Perceptoid perceptoid in brain.perceptei) { + if (thingType == 0 || perceptoid.thingType == thingType) + return perceptoid.receptor; + } + return null; + } +} diff --git a/Assets/NanoBrain/Perceptoid.cs.meta b/Assets/NanoBrain/Perceptoid.cs.meta new file mode 100644 index 0000000..ebac122 --- /dev/null +++ b/Assets/NanoBrain/Perceptoid.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 702f634001a21a9d7ae1057c8ce356e9 \ No newline at end of file diff --git a/Assets/NanoBrain/SensoryNeuroid.cs b/Assets/NanoBrain/SensoryNeuroid.cs index 78440de..1cdeabb 100644 --- a/Assets/NanoBrain/SensoryNeuroid.cs +++ b/Assets/NanoBrain/SensoryNeuroid.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; using System.Linq; using UnityEngine; public class Receptor { - public SensoryNeuroid neuroid; + public Neuroid neuroid; - public int thingId; + public int thingType; public Vector3 localPosition; /// @@ -33,7 +32,7 @@ public class SensoryNeuroid : Neuroid { this.name = name + ": position"; this.receptor = new Receptor { neuroid = this, - thingId = thingId + thingType = thingId }; this.velocityNeuroid = new(brain, name + ": velocity"); // The velocity neuroid received position data from this @@ -43,7 +42,7 @@ public class SensoryNeuroid : Neuroid { public void Replace(int thingId, string name = "sensor") { this.name = name + ": position"; - this.receptor.thingId = thingId; + this.receptor.thingType = thingId; this.receptor.localPosition = Vector3.zero; this.outputValue = Vector3.zero; diff --git a/Assets/NanoBrain/VisualEditor/Editor/NanoBrainComponent_Editor.cs b/Assets/NanoBrain/VisualEditor/Editor/NanoBrainComponent_Editor.cs index e762a1e..2229cdb 100644 --- a/Assets/NanoBrain/VisualEditor/Editor/NanoBrainComponent_Editor.cs +++ b/Assets/NanoBrain/VisualEditor/Editor/NanoBrainComponent_Editor.cs @@ -11,14 +11,16 @@ public class NanoBrainComponent_Editor : Editor { private SerializedProperty brainProp; public void OnEnable() { - brainProp = serializedObject.FindProperty(nameof(NanoBrainComponent.brain)); + if (Application.isPlaying == false) + brainProp = serializedObject.FindProperty(nameof(NanoBrainComponent.defaultBrain)); } public override VisualElement CreateInspectorGUI() { NanoBrainComponent component = target as NanoBrainComponent; - NanoBrainObj brain = component.brain; + NanoBrainObj brain = Application.isPlaying ? component.brain : component.defaultBrain; - serializedObject.Update(); + if (Application.isPlaying == false) + serializedObject.Update(); VisualElement root = new(); @@ -32,9 +34,11 @@ public class NanoBrainComponent_Editor : Editor { root.styleSheets.Add(Resources.Load("GraphStyles")); - PropertyField brainField = new(brainProp); - brainField.label = "Nano Brain"; - root.Add(brainField); + if (Application.isPlaying == false) { + PropertyField brainField = new(brainProp); + brainField.label = "Nano Brain"; + root.Add(brainField); + } mainContainer = new() { name = "main", @@ -70,14 +74,15 @@ public class NanoBrainComponent_Editor : Editor { if (brain != null) board.SetGraph(brain, brain.root, inspectorContainer); - else - Debug.LogWarning(" No brain!"); + // else + // Debug.LogWarning(" No brain!"); - serializedObject.ApplyModifiedProperties(); + if (Application.isPlaying == false) + serializedObject.ApplyModifiedProperties(); return root; } - private void UpdateLayout(float containerWidth) { + private void UpdateLayout(float containerWidth) { if (containerWidth > 800f) { mainContainer.style.flexDirection = FlexDirection.Row; inspectorContainer.style.width = 400; // fixed sidebar width diff --git a/Assets/NanoBrain/VisualEditor/Editor/NanoBrainEditor.cs b/Assets/NanoBrain/VisualEditor/Editor/NanoBrainEditor.cs index 2e38c69..7c86c74 100644 --- a/Assets/NanoBrain/VisualEditor/Editor/NanoBrainEditor.cs +++ b/Assets/NanoBrain/VisualEditor/Editor/NanoBrainEditor.cs @@ -299,7 +299,7 @@ public class GraphBoardView : VisualElement { if (neuroid is SensoryNeuroid sensoryNeuroid) { tooltip = new( $"{sensoryNeuroid.name}" + - $"\nThing {sensoryNeuroid.receptor.thingId}" + + $"\nThing {sensoryNeuroid.receptor.thingType}" + $"\nValue: {neuroid.outputValue}" + $"\nStale: {neuroid.stale}"); } diff --git a/Assets/NanoBrain/VisualEditor/Editor/NanoBrainInspector.cs b/Assets/NanoBrain/VisualEditor/Editor/NanoBrainInspector.cs index 21b5c83..e944386 100644 --- a/Assets/NanoBrain/VisualEditor/Editor/NanoBrainInspector.cs +++ b/Assets/NanoBrain/VisualEditor/Editor/NanoBrainInspector.cs @@ -104,7 +104,8 @@ public class NanoBrainInspector : Editor { public void SetGraph(NanoBrainObj brain, Nucleus nucleus, VisualElement inspectorContainer) { this.brain = brain; - this.serializedBrain = new SerializedObject(brain); + if (Application.isPlaying == false) + this.serializedBrain = new SerializedObject(brain); this.currentNucleus = nucleus; Rebuild(inspectorContainer); } @@ -212,17 +213,130 @@ public class NanoBrainInspector : Editor { if (currentNucleus == null) return; - serializedBrain.Update(); + if (Application.isPlaying == false) + serializedBrain.Update(); Handles.BeginGUI(); - foreach (NeuroidLayer layer in layers) - DrawLayer(layer); + DrawGraph(); + // foreach (NeuroidLayer layer in layers) + // DrawLayer(layer); Handles.EndGUI(); } + private void DrawGraph() { + float size = 20; + Vector3 position = new(200, 210, 0); + + DrawReceivers(this.currentNucleus, position, size); + DrawSynapses(this.currentNucleus, position, size); + + // Draw selected Nucleus + Handles.color = Color.white; + Handles.DrawSolidDisc(position, Vector3.forward, size + 2); + DrawNucleus(this.currentNucleus, position, this.currentNucleus.outputValue.magnitude, 20); + } + + private void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue, float size) { + if (nucleus.isSleeping) + Handles.color = Color.darkRed; + else { + float brightness = nucleus.outputValue.magnitude / maxValue; + Handles.color = new Color(brightness, brightness, brightness); + } + Handles.DrawSolidDisc(position, Vector3.forward, size); + Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis + GUIStyle style = new GUIStyle(EditorStyles.label) { + alignment = TextAnchor.UpperCenter, + normal = { textColor = Color.white }, + fontStyle = FontStyle.Bold + }; + Handles.Label(labelPos, nucleus.name, style); + + Rect neuronRect = new(position.x - size, position.y - size, size * 2, size * 2); + int id = GUIUtility.GetControlID(FocusType.Passive); + Event e = Event.current; + EventType et = e.GetTypeForControl(id); + if (e != null && neuronRect.Contains(e.mousePosition)) { + // Process Hover + HandleMouseHover(nucleus, neuronRect); + // Process click + if (e.type == EventType.MouseDown && e.button == 0) { + // Consume the event so the scene doesn't also handle it + e.Use(); + HandleClicked(nucleus); + } + } + } + + private void DrawReceivers(Nucleus nucleus, Vector3 parentPos, float size) { + int nodeCount = nucleus.receivers.Count; + + // Determine the maximum value in this layer + // This is used to 'scale' the output value colors of the nuclei + float maxValue = 0; + foreach (Receiver receiver in nucleus.receivers) { + if (receiver.nucleus is Neuroid neuroid) { + float value = neuroid.outputValue.magnitude; + if (value > maxValue) + maxValue = value; + } + } + + // Determine the spacing of the nuclei in the layer + float spacing = 400f / nodeCount; + float margin = 10 + spacing / 2; + + int row = 0; + foreach (Receiver receiver in nucleus.receivers) { + Nucleus receiverNucleus = receiver.nucleus; + + Vector3 pos = new(100, margin + row * spacing, 0.0f); + Handles.color = Color.white; + Handles.DrawLine(parentPos, pos); + + DrawNucleus(receiverNucleus, pos, maxValue, size); + row++; + } + } + + private void DrawSynapses(Nucleus nucleus, Vector3 parentPos, float size) { + int nodeCount = nucleus.synapses.Count; + + // Determine the maximum value in this layer + // This is used to 'scale' the output value colors of the nuclei + float maxValue = 0; + foreach (Synapse receiver in nucleus.synapses) { + if (receiver.nucleus is Neuroid neuroid) { + float value = neuroid.outputValue.magnitude; + if (value > maxValue) + maxValue = value; + } + } + + // Determine the spacing of the nuclei in the layer + float spacing = 400f / nodeCount; + float margin = 10 + spacing / 2; + + int row = 0; + foreach (Synapse receiver in nucleus.synapses) { + Nucleus receiverNucleus = receiver.nucleus; + + Vector3 pos = new(300, margin + row * spacing, 0.0f); + Handles.color = Color.white; + Handles.DrawLine(parentPos, pos); + + DrawNucleus(receiverNucleus, pos, maxValue, size); + row++; + } + } + + /* private void DrawLayer(NeuroidLayer layer) { int nodeCount = layer.neuroids.Count; + + // Determine the maximum value in this layer + // This is used to 'scale' the output value colors of the nuclei float maxValue = 0; foreach (Nucleus nucleus in layer.neuroids) { if (nucleus is Neuroid neuroid) { @@ -231,8 +345,11 @@ public class NanoBrainInspector : Editor { maxValue = value; } } + + // Determine the spacing of the nuclei in the layer float spacing = 400f / nodeCount; float margin = 10 + spacing / 2; + foreach (Nucleus layerNucleus in layer.neuroids) { Vector2Int layerNeuroidPos = this.neuroidPositions[layerNucleus]; Vector3 parentPos = new(100 + layerNeuroidPos.x * 100, margin + layerNeuroidPos.y * spacing, 0.1f); @@ -240,11 +357,9 @@ public class NanoBrainInspector : Editor { float inputSpacing = 400f / layerNucleus.synapses.Count; float inputMargin = 10 + inputSpacing / 2; int minStale = 10000; - Debug.Log($"layer neuron {layerNucleus.name} has {layerNucleus.synapses.Count} synapses"); foreach (Synapse synapse in layerNucleus.synapses) { Nucleus nucleus = synapse.nucleus; if (nucleus != null) { - Debug.Log($"Synapse to {nucleus.name} is valid"); float weight = synapse.weight; if (this.neuroidPositions.ContainsKey(nucleus)) { Vector2Int inputNeuroidPos = this.neuroidPositions[nucleus]; if (inputNeuroidPos.x == layerNeuroidPos.x + 1) { @@ -265,20 +380,21 @@ public class NanoBrainInspector : Editor { Handles.color = Color.white; Handles.DrawSolidDisc(parentPos, Vector3.forward, size + 2); } - if (layerNucleus.isSleeping) - Handles.color = Color.darkRed; - else { - float brightness = layerNucleus.outputValue.magnitude / maxValue; - Handles.color = new Color(brightness, brightness, brightness); - } - Handles.DrawSolidDisc(parentPos, Vector3.forward, size); - Vector3 labelPos = parentPos - Vector3.down * (size + 0.2f); // below disc along up axis - GUIStyle style = new GUIStyle(EditorStyles.label) { - alignment = TextAnchor.UpperCenter, - normal = { textColor = Color.white }, - fontStyle = FontStyle.Bold - }; - Handles.Label(labelPos, layerNucleus.name, style); + DrawNucleus(layerNucleus, parentPos, maxValue, size); + // if (layerNucleus.isSleeping) + // Handles.color = Color.darkRed; + // else { + // float brightness = layerNucleus.outputValue.magnitude / maxValue; + // Handles.color = new Color(brightness, brightness, brightness); + // } + // Handles.DrawSolidDisc(parentPos, Vector3.forward, size); + // Vector3 labelPos = parentPos - Vector3.down * (size + 0.2f); // below disc along up axis + // GUIStyle style = new GUIStyle(EditorStyles.label) { + // alignment = TextAnchor.UpperCenter, + // normal = { textColor = Color.white }, + // fontStyle = FontStyle.Bold + // }; + // Handles.Label(labelPos, layerNucleus.name, style); Rect neuronRect = new(parentPos.x - size, parentPos.y - size, size * 2, size * 2); int id = GUIUtility.GetControlID(FocusType.Passive); @@ -296,13 +412,14 @@ public class NanoBrainInspector : Editor { } } } + */ private void HandleMouseHover(Nucleus neuroid, Rect rect) { GUIContent tooltip; if (neuroid is SensoryNeuroid sensoryNeuroid) { tooltip = new( $"{sensoryNeuroid.name}" + - $"\nThing {sensoryNeuroid.receptor.thingId}" + + $"\nThing {sensoryNeuroid.receptor.thingType}" + $"\nValue: {neuroid.outputValue}" + $"\nStale: {neuroid.stale}"); } @@ -343,7 +460,11 @@ public class NanoBrainInspector : Editor { if (so.targetObject == null) return; so.Update(); + if (this.currentNucleus == null) + return; this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name); + if (this.currentNucleus is Perceptoid currentPerceptoid) + currentPerceptoid.thingType = EditorGUILayout.IntField("Thing Type", currentPerceptoid.thingType); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Output Value", GUILayout.Width(100)); EditorGUILayout.Vector3Field(GUIContent.none, this.currentNucleus.outputValue); @@ -359,8 +480,15 @@ public class NanoBrainInspector : Editor { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(synapse.nucleus.name, GUILayout.Width(120)); EditorGUI.indentLevel--; + // if (synapse.nucleus is Perceptoid perceptoid) { + // EditorGUILayout.LabelField("Thing", GUILayout.Width(45)); + // perceptoid.thingType = EditorGUILayout.IntField(perceptoid.thingType, GUILayout.Width(40)); + + // } + // else { EditorGUILayout.LabelField("Weight", GUILayout.Width(45)); synapse.weight = EditorGUILayout.FloatField(synapse.weight, GUILayout.Width(40)); + // } EditorGUI.indentLevel++; EditorGUILayout.Vector3Field(GUIContent.none, synapse.nucleus.outputValue, GUILayout.Width(180)); EditorGUILayout.EndHorizontal(); @@ -372,10 +500,8 @@ public class NanoBrainInspector : Editor { } if (GUILayout.Button("Add Neuron")) AddInputNeuron(this.currentNucleus); - if (GUILayout.Button("Add Position Perception")) - AddPositionPerception(this.currentNucleus); - if (GUILayout.Button("Add Velocity Perception")) - AddVelocityPerception(this.currentNucleus); + if (GUILayout.Button("Add Perceptoid")) + AddPerceptoid(this.currentNucleus); if (GUILayout.Button("Delete this neuron")) DeleteNeuron(this.currentNucleus); @@ -384,9 +510,9 @@ public class NanoBrainInspector : Editor { inspectorContainer.Add(container); } - protected virtual void AddInputNeuron(Nucleus receiver) { + protected virtual void AddInputNeuron(Nucleus nucleus) { Neuroid newNeuroid = new(this.brain, "New neuron"); - newNeuroid.AddReceiver(receiver); + newNeuroid.AddReceiver(nucleus); //Rebuild(inspectorContainer); BuildLayers(); } @@ -398,13 +524,19 @@ public class NanoBrainInspector : Editor { BuildLayers(); } - protected virtual void AddPositionPerception(Nucleus receiver) { - this.brain.perception.SendPositions(receiver); - } - protected virtual void AddVelocityPerception(Nucleus receiver) { - this.brain.perception.SendVelocities(receiver); + protected virtual void AddPerceptoid(Nucleus nucleus) { + Perceptoid newPerceptoid = new(this.brain, 0, "New Perceptoid"); + newPerceptoid.AddReceiver(nucleus); + BuildLayers(); } + // protected virtual void AddPositionPerception(Nucleus receiver) { + // this.brain.perception.SendPositions(receiver); + // } + // protected virtual void AddVelocityPerception(Nucleus receiver) { + // this.brain.perception.SendVelocities(receiver); + // } + private Vector3 NodePosition(Nucleus nucleus, int layerNodeCount = 1) { if (this.neuroidPositions.ContainsKey(nucleus)) { Vector2Int nucleusPos = this.neuroidPositions[nucleus]; diff --git a/Assets/NanoBrain/VisualEditor/NanoBrainComponent.cs b/Assets/NanoBrain/VisualEditor/NanoBrainComponent.cs index f4e7090..79a25d2 100644 --- a/Assets/NanoBrain/VisualEditor/NanoBrainComponent.cs +++ b/Assets/NanoBrain/VisualEditor/NanoBrainComponent.cs @@ -1,15 +1,21 @@ using UnityEngine; public class NanoBrainComponent : MonoBehaviour { - public NanoBrainObj brain; + public NanoBrainObj defaultBrain; + private NanoBrainObj brainInstance; + public Nucleus root { get { - return brain.root; + return brainInstance.root; } } - public Perception perception { + public NanoBrainObj brain { get { - return brain.perception; + if (brainInstance == null && defaultBrain != null) { + brainInstance = Instantiate(defaultBrain); + brainInstance.name = defaultBrain.name + " (Instance)"; + } + return brainInstance; } } } \ No newline at end of file diff --git a/Assets/NanoBrain/VisualEditor/NanoBrainObj.cs b/Assets/NanoBrain/VisualEditor/NanoBrainObj.cs index 16f386f..3d913bb 100644 --- a/Assets/NanoBrain/VisualEditor/NanoBrainObj.cs +++ b/Assets/NanoBrain/VisualEditor/NanoBrainObj.cs @@ -9,18 +9,19 @@ public class NanoBrainObj : ScriptableObject, ISerializationCallbackReceiver { public Color color = Color.white; public Texture2D texture; - public List nuclei = new(); + public List nuclei = new(); + public List perceptei = new(); // This is probably always the first element in the nuclei list... [System.NonSerialized] public Nucleus root; public int rootId; - public Perception perception; + // public Perception perception; public NanoBrainObj() { - this.root = new(this, "Root"); - this.perception = new Perception(this); + this.root = new Neuroid(this, "Root"); + // this.perception = new Perception(this); } public Neuroid AddNeuron(string name) { @@ -40,10 +41,48 @@ public class NanoBrainObj : ScriptableObject, ISerializationCallbackReceiver { this.rootId = root.id; } public void OnAfterDeserialize() { - foreach (Nucleus nucleus in nuclei) { - if (this.rootId == nucleus.id) - this.root = nucleus; - nucleus.Rebuild(this); + try { + foreach (Nucleus nucleus in this.nuclei.ToArray()) { + if (this.rootId == nucleus.id) + this.root = nucleus; + nucleus.Rebuild(this); + } + + // List rebuildNuclei = new(); + // foreach (Nucleus nucleus in this.nuclei.ToArray()) { + // rebuildNuclei.Add(Nucleus.RebuildType(this, nucleus)); + // } + // this.nuclei = rebuildNuclei; + foreach (Perceptoid perceptoid in this.perceptei.ToArray()) { + perceptoid.Rebuild(this); + } + } + catch (System.Exception) { } + this.GarbageCollection(); + } + + public void GarbageCollection() { + HashSet visitedNuclei = new(); + MarkNuclei(visitedNuclei, this.root); + Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei"); + this.nuclei.RemoveAll(nucleus => visitedNuclei.Contains(nucleus) == false); + this.perceptei.RemoveAll(perceptoid => visitedNuclei.Contains(perceptoid) == false); + } + + public void MarkNuclei(HashSet visitedNuclei, Nucleus nucleus) { + if (nucleus is null) + return; + + visitedNuclei.Add(nucleus); + if (nucleus.synapses != null) { + HashSet visitedSynapses = new(); + foreach (Synapse synapse in nucleus.synapses) { + if (synapse != null && synapse.nucleus != null) { + visitedSynapses.Add(synapse); + MarkNuclei(visitedNuclei, synapse.nucleus); + } + } + nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false); } } } \ No newline at end of file diff --git a/Assets/Scenes/Boids/Boids.unity b/Assets/Scenes/Boids/Boids.unity index 5b10cbd..5515d90 100644 --- a/Assets/Scenes/Boids/Boids.unity +++ b/Assets/Scenes/Boids/Boids.unity @@ -393,7 +393,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: ec888ca5333d45a438f9f417fa5ce135, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::SwarmSpawn - count: 1 + count: 3 boidPrefab: {fileID: 8702527964058765413, guid: f9c706268554ce449a8773675b2864b8, type: 3} spawnAreaSize: {x: 0.5, y: 0.5, z: 0.5} minDelay: 0.05 diff --git a/Assets/Scenes/Boids/New Nano Brain Obj.asset b/Assets/Scenes/Boids/New Nano Brain Obj.asset deleted file mode 100644 index df2a58c..0000000 --- a/Assets/Scenes/Boids/New Nano Brain Obj.asset +++ /dev/null @@ -1,60 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 36081359186edfec998d891a1feeb17b, type: 3} - m_Name: New Nano Brain Obj - m_EditorClassIdentifier: Assembly-CSharp::NanoBrainObj - title: - count: -26 - color: {r: 1, g: 1, b: 1, a: 1} - texture: {fileID: 0} - nuclei: - - id: 257807948 - _name: Root - synapses: - - nucleusId: -651011940 - weight: 1 - - nucleusId: -1689048724 - weight: 1 - receivers: [] - - id: -1868865374 - _name: Perception - synapses: [] - receivers: [] - - id: -651011940 - _name: Neuron 1 - synapses: [] - receivers: - - nucleusId: 257807948 - - id: -1689048724 - _name: New neuron - synapses: [] - receivers: - - nucleusId: 257807948 - - id: -152927560 - _name: 'Boundary: position' - synapses: [] - receivers: - - nucleusId: -1462684836 - - id: -1462684836 - _name: 'Boundary: velocity' - synapses: - - nucleusId: -152927560 - weight: 1 - receivers: [] - rootId: 257807948 - perception: - id: 1565766940 - _name: Perception - synapses: [] - receivers: [] - positionReceivers: [] - velocityReceivers: [] diff --git a/Assets/Scenes/Boids/Prefabs/Boid.prefab b/Assets/Scenes/Boids/Prefabs/Boid.prefab index 1a756c3..31be0f5 100644 --- a/Assets/Scenes/Boids/Prefabs/Boid.prefab +++ b/Assets/Scenes/Boids/Prefabs/Boid.prefab @@ -176,4 +176,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 92f34a5e4027a1dc39efd8ce63cf6aba, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::NanoBrainComponent - brain: {fileID: 11400000, guid: af8d90b8b4b9dcad7837130c4143d91c, type: 2} + defaultBrain: {fileID: 11400000, guid: fc1a4800a8c531eb4855b436bc9084ae, type: 2} diff --git a/Assets/Scenes/Boids/RoamingBrain.asset b/Assets/Scenes/Boids/RoamingBrain.asset index e603273..0d13ed5 100644 --- a/Assets/Scenes/Boids/RoamingBrain.asset +++ b/Assets/Scenes/Boids/RoamingBrain.asset @@ -17,86 +17,36 @@ MonoBehaviour: color: {r: 1, g: 1, b: 1, a: 1} texture: {fileID: 0} nuclei: - - id: -1753291412 + - id: -1707533328 _name: Root synapses: - - nucleusId: 237822944 + - nucleusId: -112538112 weight: 1 receivers: [] - - id: 472852910 - _name: Perception - synapses: [] - receivers: [] - - id: 237822944 + nucleusType: + average: 0 + inverse: 0 + exponent: 1 + - id: -112538112 _name: Avoidance - synapses: [] - receivers: - - nucleusId: -1753291412 - - id: 983561152 - _name: 'Boundary: position' - synapses: [] - receivers: - - nucleusId: -1818801134 - - id: -1818801134 - _name: 'Boundary: velocity' synapses: - - nucleusId: 983561152 - weight: 1 - receivers: [] - - id: 1386590800 - _name: 'Boundary: position' + - nucleusId: 407735232 + weight: -1 + receivers: + - nucleusId: -1707533328 + nucleusType: + average: 0 + inverse: 0 + exponent: 1 + perceptei: + - id: 407735232 + _name: Boundary synapses: [] receivers: - - nucleusId: -1415771486 - - nucleusId: 237822944 - - id: -1415771486 - _name: 'Boundary: velocity' - synapses: - - nucleusId: 1386590800 - weight: 1 - receivers: [] - - id: -213085248 - _name: 'Boundary: position' - synapses: [] - receivers: - - nucleusId: 1279519762 - - nucleusId: 237822944 - - id: 1279519762 - _name: 'Boundary: velocity' - synapses: - - nucleusId: -213085248 - weight: 1 - receivers: [] - - id: 1783940116 - _name: 'Boundary: position' - synapses: [] - receivers: - - nucleusId: -1018422170 - - nucleusId: 237822944 - - id: -1018422170 - _name: 'Boundary: velocity' - synapses: - - nucleusId: 1783940116 - weight: 1 - receivers: [] - rootId: -1753291412 - perception: - id: 2139386530 - _name: Perception - synapses: [] - receivers: [] - positionReceivers: - - thingType: 0 - neuroid: - id: 237822944 - _name: Avoidance - synapses: - - nucleusId: 1386590800 - weight: 1 - - nucleusId: -213085248 - weight: 1 - - nucleusId: 1783940116 - weight: 1 - receivers: - - nucleusId: -1753291412 - velocityReceivers: [] + - nucleusId: -112538112 + nucleusType: Perceptoid + average: 0 + inverse: 0 + exponent: 1 + thingType: 1 + rootId: -1707533328 diff --git a/Assets/Scenes/Boids/Scripts/Boid.cs b/Assets/Scenes/Boids/Scripts/Boid.cs index f5a83cf..2f557be 100644 --- a/Assets/Scenes/Boids/Scripts/Boid.cs +++ b/Assets/Scenes/Boids/Scripts/Boid.cs @@ -13,32 +13,21 @@ public class Boid : MonoBehaviour { private Bounds innerBounds; public NanoBrainComponent nanoBrain; - - // public NanoBrain neuroidNet; - // public Perception perception; - - // public Nucleus behaviour; - - // public Neuroid totalForce; + public Receptor boundaryReceptor; + public Receptor boidReceptor; public int id; void Awake() { - nanoBrain = GetComponent(); this.id = this.GetInstanceID(); + nanoBrain = GetComponent(); + boundaryReceptor = Perceptoid.GetReceptor(nanoBrain.brain, BoundaryType); + boidReceptor = Perceptoid.GetReceptor(nanoBrain.brain, BoidType); + sc = FindFirstObjectByType(); innerBounds = new(sc.transform.position, sc.spaceSize - 2 * sc.boundaryWidth); - - // neuroidNet = GetComponent(); - // perception = new Perception(neuroidNet); - - // //behaviour = new Roaming(neuroidNet, perception, sc); - // behaviour = new Swarming(neuroidNet, perception, sc); - - // totalForce = new(neuroidNet, "Total"); - // behaviour.AddReceiver(totalForce); } void Update() { @@ -52,8 +41,9 @@ public class Boid : MonoBehaviour { Vector3 localPosition = this.transform.InverseTransformPoint(neighbour.transform.position); //Debug.DrawRay(this.transform.position, this.transform.TransformDirection(localPosition), Color.magenta); - int thingId = neighbour.GetInstanceID(); - nanoBrain.perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name); + //int thingId = neighbour.GetInstanceID(); + // nanoBrain.perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name); + boidReceptor.position = localPosition; } } @@ -62,10 +52,9 @@ public class Boid : MonoBehaviour { Vector3 pointOnBounds = innerBounds.ClosestPoint(point); Vector3 desiredWorldSpace = (pointOnBounds - point).normalized * sc.speed; Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace); - nanoBrain.perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary"); + boundaryReceptor.position = desiredLocalSpace; } - //Vector3 worldForce = this.transform.TransformDirection(behaviour.outputValue); Vector3 worldForce = this.transform.TransformDirection(nanoBrain.root.outputValue); this.velocity = (1 - sc.inertia) * (worldForce * Time.deltaTime) + sc.inertia * velocity; @@ -82,7 +71,6 @@ public class Boid : MonoBehaviour { transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f); // Adjust the speed of rotation } - //neuroidNet.UpdateNeurons(); nanoBrain.brain.UpdateNuclei(); } diff --git a/Assets/Scenes/Boids/Scripts/RoamingNucleus.cs b/Assets/Scenes/Boids/Scripts/RoamingNucleus.cs index be2fe61..513f05e 100644 --- a/Assets/Scenes/Boids/Scripts/RoamingNucleus.cs +++ b/Assets/Scenes/Boids/Scripts/RoamingNucleus.cs @@ -3,7 +3,7 @@ public class Roaming : Nucleus { public Neuroid output; - public Roaming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base(null, "Roaming nucleus") { + public Roaming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base("Roaming nucleus") { avoidance = new(brain, "Avoidance") { inverse = true }; perception.SendPositions(avoidance, Boid.BoundaryType); diff --git a/Assets/Scenes/Boids/Scripts/SwarmingNucleus.cs b/Assets/Scenes/Boids/Scripts/SwarmingNucleus.cs index de25135..92f9950 100644 --- a/Assets/Scenes/Boids/Scripts/SwarmingNucleus.cs +++ b/Assets/Scenes/Boids/Scripts/SwarmingNucleus.cs @@ -10,7 +10,7 @@ public class Swarming : Nucleus { public override Vector3 outputValue { get => output.outputValue; set => output.outputValue = value; } - public Swarming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base(null, "Swarming Nucleus") { + public Swarming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base("Swarming Nucleus") { this.cohesion = new(brain, "Cohesion") { inverse = false }; perception.SendPositions(this.cohesion, Boid.BoidType); diff --git a/Assets/Scenes/Boids/SwarmingBrain.asset b/Assets/Scenes/Boids/SwarmingBrain.asset new file mode 100644 index 0000000..4228d29 --- /dev/null +++ b/Assets/Scenes/Boids/SwarmingBrain.asset @@ -0,0 +1,88 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 36081359186edfec998d891a1feeb17b, type: 3} + m_Name: SwarmingBrain + m_EditorClassIdentifier: Assembly-CSharp::NanoBrainObj + title: + count: 0 + color: {r: 1, g: 1, b: 1, a: 1} + texture: {fileID: 0} + nuclei: + - id: -1707533328 + _name: Root + synapses: + - nucleusId: -112538112 + weight: 1 + - nucleusId: 1938577052 + weight: 1 + receivers: [] + nucleusType: + average: 0 + inverse: 0 + exponent: 1 + - id: -112538112 + _name: Avoidance + synapses: + - nucleusId: 407735232 + weight: -1 + receivers: + - nucleusId: -1707533328 + nucleusType: + average: 0 + inverse: 0 + exponent: 1 + - id: 1938577052 + _name: Cohesion + synapses: + - nucleusId: -1408496896 + weight: 1 + - nucleusId: -133566816 + weight: 1 + receivers: + - nucleusId: -1707533328 + nucleusType: + average: 0 + inverse: 0 + exponent: 1 + perceptei: + - id: 407735232 + _name: Boundary + synapses: [] + receivers: + - nucleusId: -112538112 + nucleusType: Perceptoid + average: 0 + inverse: 0 + exponent: 1 + thingType: 1 + - id: -1408496896 + _name: Boid1 + synapses: [] + receivers: + - nucleusId: 1938577052 + nucleusType: Perceptoid + average: 0 + inverse: 0 + exponent: 1 + thingType: 2 + - id: -133566816 + _name: Boid2 + synapses: [] + receivers: + - nucleusId: 27651644 + - nucleusId: 1938577052 + nucleusType: Perceptoid + average: 0 + inverse: 0 + exponent: 1 + thingType: 2 + rootId: -1707533328 diff --git a/Assets/Scenes/Boids/New Nano Brain Obj.asset.meta b/Assets/Scenes/Boids/SwarmingBrain.asset.meta similarity index 79% rename from Assets/Scenes/Boids/New Nano Brain Obj.asset.meta rename to Assets/Scenes/Boids/SwarmingBrain.asset.meta index 01cdcae..a12ec48 100644 --- a/Assets/Scenes/Boids/New Nano Brain Obj.asset.meta +++ b/Assets/Scenes/Boids/SwarmingBrain.asset.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 55099766f6f09071ab4e8c89b02fa302 +guid: fc1a4800a8c531eb4855b436bc9084ae NativeFormatImporter: externalObjects: {} mainObjectFileID: 11400000