Improved network

This commit is contained in:
Pascal Serrarens 2026-01-08 17:41:43 +01:00
parent 600ecd5406
commit 5206469764
17 changed files with 7248 additions and 478 deletions

View File

@ -53,8 +53,8 @@
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector2IntTest.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector2IntTest.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Quaternion.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/src/Quaternion.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/float16.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/src/float16.cs" />
<Compile Include="Assets/NanoBrain/VisualEditor/NanoBrainObj.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/DirectionTest.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/test/DirectionTest.cs" />
<Compile Include="Assets/NanoBrain/VisualEditor/NanoBrain.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector2FloatTest.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector2FloatTest.cs" />
<Compile Include="Assets/Scenes/Boids/Scripts/SwarmSpawner.cs" /> <Compile Include="Assets/Scenes/Boids/Scripts/SwarmSpawner.cs" />
<Compile Include="Assets/NanoBrain/Perceptoid.cs" /> <Compile Include="Assets/NanoBrain/Perceptoid.cs" />
@ -62,6 +62,7 @@
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector2Float.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector2Float.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/SwingTwistTest.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/test/SwingTwistTest.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector3Int.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector3Int.cs" />
<Compile Include="Assets/NanoBrain/PercepteiArray.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector3Float.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector3Float.cs" />
<Compile Include="Assets/NanoBrain/Receptor.cs" /> <Compile Include="Assets/NanoBrain/Receptor.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Matrix.cs" /> <Compile Include="Assets/NanoBrain/LinearAlgebra/src/Matrix.cs" />

View File

@ -1,6 +1,4 @@
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using LinearAlgebra;
[System.Serializable] [System.Serializable]
public class Neuroid : Nucleus { public class Neuroid : Nucleus {
@ -80,10 +78,8 @@ public class Neuroid : Nucleus {
//Applying the weight factgors //Applying the weight factgors
foreach (Synapse synapse in this.synapses) { foreach (Synapse synapse in this.synapses) {
Vector3 outputValue = synapse.nucleus.outputValue; sum += synapse.weight * synapse.nucleus.outputValue;
float magnitude = synapse.weight * outputValue.magnitude; if (synapse.nucleus.outputValue.sqrMagnitude != 0)
sum += magnitude * outputValue.normalized;
n++; n++;
} }
if (average) if (average)

View File

@ -154,11 +154,11 @@ public class Nucleus {
public virtual void UpdateState() { } public virtual void UpdateState() { }
public void UpdateResult(Vector3 result) { public void UpdateResult(Vector3 result) {
float d = Vector3.Distance(result, this.outputValue); // float d = Vector3.Distance(result, this.outputValue);
if (d < 0.5f) { // if (d < 0.5f) {
//Debug.Log($"insignificant update: {d}"); // //Debug.Log($"insignificant update: {d}");
return; // return;
} // }
this.outputValue = result; this.outputValue = result;
foreach (Receiver receiver in this.receivers) foreach (Receiver receiver in this.receivers)

View File

@ -0,0 +1,22 @@
public class PercepteiArray {
public ArrayPerceptoid[] perceptei;
public string name;
public PercepteiArray(NanoBrain brain, int thingType, string baseName, uint count) {
this.name = baseName;
this.perceptei = new ArrayPerceptoid[count];
for (uint i = 0; i < count; i++) {
this.perceptei[i] = new ArrayPerceptoid(brain, thingType, $"{baseName}[{i}]") {
array = this
};
}
}
}
public class ArrayPerceptoid : Perceptoid {
public PercepteiArray array;
public ArrayPerceptoid(NanoBrain brain, int thingType, string name = "sensor") : base(brain, thingType, name) {
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f8cac60bd79854595a8571c042f77998

View File

@ -6,7 +6,7 @@ public class Perceptoid : Neuroid {
// A neuroid which has no neurons as input // A neuroid which has no neurons as input
// But receives value from a receptor // But receives value from a receptor
public Receptor receptor; public Receptor receptor;
//public VelocityNeuroid velocityNeuroid; public string baseName;
#region Serialization #region Serialization
@ -58,21 +58,22 @@ public class Perceptoid : Neuroid {
this.nucleusType = nameof(Perceptoid); this.nucleusType = nameof(Perceptoid);
this.name = name; this.name = name;
this.baseName = name;
this.thingType = thingType; this.thingType = thingType;
this.receptor = Receptor.GetReceptor(brain, thingType); this.receptor = Receptor.GetReceptor(brain, thingType);
this.receptor.perceptei.Add(this); this.receptor.perceptei.Add(this);
} }
public void Replace(int thingType, string name = "sensor") { // public void Replace(int thingType, string name = "sensor") {
this.name = name; // this.name = name;
this.thingType = thingType; // this.thingType = thingType;
this.receptor.thingType = thingType; // this.receptor.thingType = thingType;
this.receptor.localPosition = Vector3.zero; // this.receptor.localPosition = Vector3.zero;
this.outputValue = Vector3.zero; // this.outputValue = Vector3.zero;
this.receivers = new(); // this.receivers = new();
} // }
public override void UpdateState() { public override void UpdateState() {
Vector3 result = this.receptor.localPosition; Vector3 result = this.receptor.localPosition;
@ -80,11 +81,11 @@ public class Perceptoid : Neuroid {
} }
public static Perceptoid GetPerception(NanoBrain brain, int thingType = 0) { // public static Perceptoid GetPerception(NanoBrain brain, int thingType = 0) {
foreach (Nucleus nucleus in brain.nuclei) { // foreach (Nucleus nucleus in brain.nuclei) {
if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.receptor.thingType == thingType)) // if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.receptor.thingType == thingType))
return perceptoid; // return perceptoid;
} // }
return null; // return null;
} // }
} }

View File

@ -37,7 +37,7 @@ public class Receptor {
return newReceptor; return newReceptor;
} }
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector) { public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) {
this.localPosition = newLocalPositionVector; this.localPosition = newLocalPositionVector;
Perceptoid selectedPerceptoid = null; Perceptoid selectedPerceptoid = null;
@ -75,6 +75,8 @@ public class Receptor {
} }
// Debug.Log($"Stimulus {thingType} {thingId} {selectedPerceptoid.name}"); // Debug.Log($"Stimulus {thingType} {thingId} {selectedPerceptoid.name}");
selectedPerceptoid.thingId = thingId; selectedPerceptoid.thingId = thingId;
if (thingName != null)
selectedPerceptoid.name = selectedPerceptoid.baseName + " " + thingName;
selectedPerceptoid.UpdateState(); selectedPerceptoid.UpdateState();
} }
} }

View File

@ -1,3 +1,4 @@
/*
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
@ -406,7 +407,7 @@ public class GraphBoardView : VisualElement {
// } // }
} }
/*
public class NodeView : VisualElement { public class NodeView : VisualElement {
Nucleus data; Nucleus data;
GraphBoardView board; GraphBoardView board;
@ -466,7 +467,7 @@ public class NodeView : VisualElement {
//dragging = false; //dragging = false;
} }
} }
*/
public class GraphNodeWrapper : ScriptableObject { public class GraphNodeWrapper : ScriptableObject {
// expose fields that map to GraphNode // expose fields that map to GraphNode
@ -507,3 +508,4 @@ public static class OpenAssetHandler {
return false; // let Unity open normally return false; // let Unity open normally
} }
} }
*/

View File

@ -181,22 +181,6 @@ public class NanoBrainInspector : Editor {
} }
// basic pan/zoom handling
// void OnWheel(WheelEvent e) {
// if (e.ctrlKey) {
// float delta = -e.delta.y * 0.001f;
// zoom = Mathf.Clamp(zoom + delta, 0.25f, 2f);
// content.transform.rotation = Quaternion.identity; // keep transform accessible
// content.transform.scale = new Vector3(zoom, zoom, 1);
// e.StopPropagation();
// }
// else {
// pan += e.delta;
// content.style.left = pan.x;
// content.style.top = pan.y;
// }
// }
void OnMouseDown(MouseDownEvent e) { void OnMouseDown(MouseDownEvent e) {
if (e.button == 2) { draggingCanvas = true; lastMouse = e.mousePosition; e.StopPropagation(); } if (e.button == 2) { draggingCanvas = true; lastMouse = e.mousePosition; e.StopPropagation(); }
} }
@ -220,8 +204,6 @@ public class NanoBrainInspector : Editor {
Handles.BeginGUI(); Handles.BeginGUI();
DrawGraph(); DrawGraph();
// foreach (NeuroidLayer layer in layers)
// DrawLayer(layer);
Handles.EndGUI(); Handles.EndGUI();
} }
@ -291,17 +273,26 @@ public class NanoBrainInspector : Editor {
float margin = 10 + spacing / 2; float margin = 10 + spacing / 2;
int row = 0; int row = 0;
foreach (Synapse receiver in nucleus.synapses) { List<PercepteiArray> drawnArrays = new();
Nucleus receiverNucleus = receiver.nucleus; foreach (Synapse synapse in nucleus.synapses) {
Vector3 pos = new(250, margin + row * spacing, 0.0f); Vector3 pos = new(250, margin + row * spacing, 0.0f);
Handles.color = Color.white; Handles.color = Color.white;
Handles.DrawLine(parentPos, pos); Handles.DrawLine(parentPos, pos);
if (synapse.nucleus is ArrayPerceptoid perceptoid) {
if (drawnArrays.Contains(perceptoid.array))
// We already drawn this array
continue;
DrawNucleus(receiverNucleus, pos, maxValue, size); drawnArrays.Add(perceptoid.array);
DrawArray(perceptoid.array, pos, size);
}
else {
DrawNucleus(synapse.nucleus, pos, maxValue, size);
row++; row++;
} }
} }
}
private void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue, float size) { private void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue, float size) {
if (nucleus.isSleeping) if (nucleus.isSleeping)
@ -312,7 +303,7 @@ public class NanoBrainInspector : Editor {
} }
Handles.DrawSolidDisc(position, Vector3.forward, size); Handles.DrawSolidDisc(position, Vector3.forward, size);
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
GUIStyle style = new GUIStyle(EditorStyles.label) { GUIStyle style = new(EditorStyles.label) {
alignment = TextAnchor.UpperCenter, alignment = TextAnchor.UpperCenter,
normal = { textColor = Color.white }, normal = { textColor = Color.white },
fontStyle = FontStyle.Bold fontStyle = FontStyle.Bold
@ -335,15 +326,28 @@ public class NanoBrainInspector : Editor {
} }
} }
private void DrawArray(PercepteiArray array, Vector3 position, float size) {
Vector3 offset = new(size/4, size/4, 0);
Handles.color = Color.darkGray;
Handles.DrawSolidDisc(position + offset * 2, Vector3.forward, size);
Handles.color = Color.lightGray;
Handles.DrawSolidDisc(position + offset, Vector3.forward, size);
Handles.color = Color.white;
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, array.name, style);
// To do: add HandleClick (see above) to expand the array
}
private void HandleMouseHover(Nucleus nucleus, Rect rect) { private void HandleMouseHover(Nucleus nucleus, Rect rect) {
GUIContent tooltip; GUIContent tooltip;
// if (nucleus is SensoryNeuroid sensoryNeuroid) {
// tooltip = new(
// $"{sensoryNeuroid.name}" +
// $"\nThing {sensoryNeuroid.receptor.thingType}" +
// $"\nValue: {nucleus.outputValue}");
// }
//else
if (nucleus is Perceptoid perceptoid) { if (nucleus is Perceptoid perceptoid) {
if (perceptoid.receptor != null) { if (perceptoid.receptor != null) {
tooltip = new( tooltip = new(
@ -419,42 +423,43 @@ public class NanoBrainInspector : Editor {
EditorGUILayout.LabelField(" "); EditorGUILayout.LabelField(" ");
if (this.currentNucleus.synapses.Count > 0) { if (this.currentNucleus.synapses.Count > 0) {
foreach (Synapse synapse in this.currentNucleus.synapses) { Synapse[] synapses = this.currentNucleus.synapses.ToArray();
foreach (Synapse synapse in synapses) {
if (synapse.nucleus != null) { if (synapse.nucleus != null) {
EditorGUILayout.Space(); EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping); EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping);
if (Application.isPlaying) if (Application.isPlaying)
EditorGUILayout.FloatField(synapse.nucleus.name, synapse.nucleus.outputValue.magnitude * synapse.weight); EditorGUILayout.FloatField(synapse.nucleus.name, synapse.nucleus.outputValue.magnitude * synapse.weight);
else else {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(synapse.nucleus.name); EditorGUILayout.LabelField(synapse.nucleus.name);
if (GUILayout.Button("Disconnect"))
synapse.nucleus.RemoveReceiver(this.currentNucleus);
EditorGUILayout.EndHorizontal();
}
EditorGUI.indentLevel++; EditorGUI.indentLevel++;
// EditorGUI.BeginChangeCheck();
synapse.weight = EditorGUILayout.FloatField("Weight", synapse.weight); synapse.weight = EditorGUILayout.FloatField("Weight", synapse.weight);
// synapse.curvePreset = (Synapse.CurvePresets)EditorGUILayout.EnumPopup("Preset", synapse.curvePreset);
// if (EditorGUI.EndChangeCheck()) {
// synapse.curve = synapse.GenerateCurve();
// }
// if (synapse.curveMax > 0)
// EditorGUILayout.CurveField("Curve", synapse.curve, Color.cyan, new Rect(0, 0, 1, synapse.curveMax));
// else
// EditorGUILayout.CurveField("Curve", synapse.curve, Color.cyan, new Rect(0, synapse.curveMax, 1, -synapse.curveMax));
EditorGUI.indentLevel--; EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup(); EditorGUI.EndDisabledGroup();
} }
} }
//EditorGUI.indentLevel--;
} }
if (GUILayout.Button("Add Neuron"))
EditorGUILayout.Space();
ConnectNucleus(this.currentNucleus);
if (GUILayout.Button("Add Input Neuron"))
AddInputNeuron(this.currentNucleus); AddInputNeuron(this.currentNucleus);
if (GUILayout.Button("Add Perceptoid")) if (GUILayout.Button("Add Input Perceptoid"))
AddPerceptoid(this.currentNucleus); AddPerceptoid(this.currentNucleus);
EditorGUILayout.Space();
if (GUILayout.Button("Delete this neuron")) if (GUILayout.Button("Delete this neuron"))
DeleteNeuron(this.currentNucleus); DeleteNeuron(this.currentNucleus);
ConnectNucleus(this.currentNucleus); //DisconnectNucleus(this.currentNucleus);
DisconnectNucleus(this.currentNucleus);
if (this.gameObject != null) { if (this.gameObject != null) {
Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue); Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue);
@ -498,9 +503,9 @@ public class NanoBrainInspector : Editor {
if (this.currentNucleus.brain == null) if (this.currentNucleus.brain == null)
return; return;
//string[] names = this.currentNucleus.brain.perceptei.Select(i => i.name).ToArray(); IEnumerable<string> synapseNuclei = this.currentNucleus.synapses.Select(synapse => synapse.nucleus.name);
IEnumerable<string> perceptei = this.currentNucleus.brain.perceptei.Select(i => i.name); IEnumerable<string> perceptei = this.currentNucleus.brain.perceptei.Select(i => i.name).Except(synapseNuclei);
IEnumerable<string> nuclei = this.currentNucleus.brain.nuclei.Select(i => i.name); IEnumerable<string> nuclei = this.currentNucleus.brain.nuclei.Select(i => i.name).Except(synapseNuclei);
string[] names = perceptei.Concat(nuclei).ToArray(); string[] names = perceptei.Concat(nuclei).ToArray();
int selectedIndex = -1; int selectedIndex = -1;
selectedIndex = EditorGUILayout.Popup("Connect to", selectedIndex, names); selectedIndex = EditorGUILayout.Popup("Connect to", selectedIndex, names);
@ -527,32 +532,6 @@ public class NanoBrainInspector : Editor {
synapse.nucleus.RemoveReceiver(this.currentNucleus); synapse.nucleus.RemoveReceiver(this.currentNucleus);
} }
} }
// private Vector3 NodePosition(Nucleus nucleus, int layerNodeCount = 1) {
// if (this.neuroidPositions.ContainsKey(nucleus)) {
// Vector2Int nucleusPos = this.neuroidPositions[nucleus];
// return NodePosition(nucleusPos, layerNodeCount);
// }
// else {
// return Vector3.zero;
// }
// }
// private Vector3 NodePosition(Vector2Int location, int layerNodeCount = 1) {
// float spacing = 400f / layerNodeCount;
// float margin = 10 + spacing / 2;
// float size = 20;
// Vector3 parentPos = new(100 + location.x * 100 - size, margin + location.y * spacing - size, 0.1f);
// return parentPos;
// }
// public void CreateEdge(string fromId, string toId) {
// if (fromId == toId) return;
// Undo.RecordObject(graph, "Create Edge");
// graph.edges.Add(new GraphEdge { fromNodeId = fromId, toNodeId = toId });
// EditorUtility.SetDirty(graph);
// Rebuild();
// }
} }
#endregion Start #endregion Start
@ -573,29 +552,31 @@ public class NanoBrainInspector : Editor {
} }
} }
// protected virtual void OnSceneGUI() {
// NanoBrain brain = target as NanoBrain;
// if (brain == null)
// return;
// Vector3 position = brain.transform.position;
// float radius = 1;
// Handles.DrawWireDisc(position, Vector3.up, radius); // horizontal circle
// Handles.DrawWireDisc(position, Vector3.right, radius); // X-plane
// Handles.DrawWireDisc(position, Vector3.forward, radius); // Z-plane
// // Debug.DrawRay(brain.transform.position, Vector3.forward, Color.magenta);
// // Handles.color = Color.green;
// // Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up);
// // Handles.color = Color.yellow;
// // Vector3 worldForce = brain.transform.TransformDirection(this.currentNucleus.outputValue);
// // //Debug.DrawRay(position, worldForce * 10, Color.yellow);
// // Handles.DrawLine(position, position + worldForce * 10);
// }
#endregion Update #endregion Update
} }
public class GraphNodeWrapper : ScriptableObject {
// expose fields that map to GraphNode
public string title;
public Vector2 position;
Nucleus node;
NanoBrain graph; // needed to write back and mark dirty
public GraphNodeWrapper Init(Nucleus node, NanoBrain graphAsset) {
this.node = node;
this.graph = graphAsset;
this.title = " A " + node.name;
//position = node.position;
return this;
}
void OnValidate() {
if (node != null) {
node.name = title;
//node.position = position;
#if UNITY_EDITOR
if (graph != null)
UnityEditor.EditorUtility.SetDirty(graph);
#endif
}
}
}

View File

@ -1,6 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using LinearAlgebra;
[CreateAssetMenu(menuName = "Passer/NanoBrain")] [CreateAssetMenu(menuName = "Passer/NanoBrain")]
public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver { public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
@ -19,11 +18,8 @@ public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
public Nucleus root; public Nucleus root;
public int rootId; public int rootId;
// public Perception perception;
public NanoBrain() { public NanoBrain() {
this.root = new Neuroid(this, "Root"); this.root = new Neuroid(this, "Root");
// this.perception = new Perception(this);
} }
public Neuroid AddNeuron(string name) { public Neuroid AddNeuron(string name) {
@ -32,18 +28,10 @@ public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
} }
public void UpdateNuclei() { public void UpdateNuclei() {
foreach (Nucleus nucleus in nuclei) { foreach (Nucleus nucleus in nuclei)
//nucleus.stale++;
nucleus.IncreaseAge(); nucleus.IncreaseAge();
// if (nucleus.isSleeping) foreach (Perceptoid perception in perceptei)
// nucleus.outputValue = Spherical.zero;
}
foreach (Perceptoid perception in perceptei) {
//perception.stale++;
perception.IncreaseAge(); perception.IncreaseAge();
// if (perception.isSleeping)
// perception.outputValue = Spherical.zero;
}
} }
public void OnBeforeSerialize() { public void OnBeforeSerialize() {
@ -57,15 +45,9 @@ public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
nucleus.Rebuild(this); nucleus.Rebuild(this);
} }
// List<Nucleus> rebuildNuclei = new(); foreach (Perceptoid perceptoid in this.perceptei.ToArray())
// 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); perceptoid.Rebuild(this);
} }
}
catch (System.Exception) { } catch (System.Exception) { }
this.GarbageCollection(); this.GarbageCollection();
} }
@ -85,9 +67,6 @@ public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
if (nucleus.brain == null) if (nucleus.brain == null)
nucleus.brain = this; nucleus.brain = this;
if (nucleus.name == "Boid1")
Debug.Log(" Found boiid1");
visitedNuclei.Add(nucleus); visitedNuclei.Add(nucleus);
if (nucleus.synapses != null) { if (nucleus.synapses != null) {
HashSet<Synapse> visitedSynapses = new(); HashSet<Synapse> visitedSynapses = new();
@ -105,7 +84,6 @@ public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
if (receiver != null && receiver.nucleus != null) { if (receiver != null && receiver.nucleus != null) {
visitedReceivers.Add(receiver); visitedReceivers.Add(receiver);
visitedNuclei.Add(receiver.nucleus); visitedNuclei.Add(receiver.nucleus);
//MarkNuclei(visitedNuclei, receiver.nucleus);
} }
} }
nucleus.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false); nucleus.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false);

View File

@ -4,18 +4,30 @@ public class NanoBrainComponent : MonoBehaviour {
public NanoBrain defaultBrain; public NanoBrain defaultBrain;
private NanoBrain brainInstance; private NanoBrain brainInstance;
public Nucleus root { public Nucleus root => brainInstance.root;
get {
return brainInstance.root;
}
}
public NanoBrain brain { public NanoBrain brain {
get { get {
if (brainInstance == null && defaultBrain != null) { if (brainInstance == null && defaultBrain != null) {
brainInstance = Instantiate(defaultBrain); brainInstance = Instantiate(defaultBrain);
brainInstance.name = defaultBrain.name + " (Instance)"; brainInstance.name = defaultBrain.name + " (Instance)";
SwarmControl sc = FindFirstObjectByType<SwarmControl>();
UpdateWeight(brainInstance, "Avoidance", sc.avoidanceForce);
UpdateWeight(brainInstance, "Cohesion", sc.cohesionForce);
UpdateWeight(brainInstance, "Separation", sc.separationForce);
UpdateWeight(brainInstance, "Alignment", sc.alignmentForce);
} }
return brainInstance; return brainInstance;
} }
} }
public static void UpdateWeight(NanoBrain brain, string name, float weight) {
Nucleus root = brain.root;
foreach (Synapse synapse in root.synapses) {
if (synapse.nucleus.name == name) {
synapse.weight = weight;
}
}
}
} }

View File

@ -376,12 +376,11 @@ MonoBehaviour:
speed: 1 speed: 1
inertia: 0.7 inertia: 0.7
alignmentForce: 0.5 alignmentForce: 0.5
cohesionForce: 2.2 cohesionForce: 0.1
separationForce: -5 separationForce: -0.1
avoidanceForce: 1 avoidanceForce: 1
separationDistance: 0.3 separationDistance: 0.3
perceptionDistance: 2 perceptionDistance: 2
boundaryForce: 5
spaceSize: {x: 10, y: 10, z: 10} spaceSize: {x: 10, y: 10, z: 10}
boundaryWidth: {x: 1, y: 1, z: 1} boundaryWidth: {x: 1, y: 1, z: 1}
--- !u!114 &301943979 --- !u!114 &301943979

View File

@ -47,8 +47,13 @@ public class Boid : MonoBehaviour {
int thingId = neighbour.GetInstanceID(); int thingId = neighbour.GetInstanceID();
Vector3 localPosition = this.transform.InverseTransformPoint(neighbour.transform.position); Vector3 localPosition = this.transform.InverseTransformPoint(neighbour.transform.position);
float d = localPosition.magnitude;
if (d <= sc.separationDistance)
localPosition = localPosition.normalized * 0.01f;
else
localPosition = localPosition.normalized * (localPosition.magnitude - sc.separationDistance);
if (localPosition.sqrMagnitude > 0) if (localPosition.sqrMagnitude > 0)
boidReceptor?.ProcessStimulus(thingId, localPosition); boidReceptor?.ProcessStimulus(thingId, localPosition, neighbour.name);
Vector3 localVelocity = this.transform.InverseTransformVector(neighbour.velocity); Vector3 localVelocity = this.transform.InverseTransformVector(neighbour.velocity);
if (localVelocity.sqrMagnitude > 0) if (localVelocity.sqrMagnitude > 0)

View File

@ -13,21 +13,21 @@ public class SwarmControl_Editor : Editor {
NanoBrain[] nanoBrains = FindObjectsByType<NanoBrain>(FindObjectsSortMode.None); NanoBrain[] nanoBrains = FindObjectsByType<NanoBrain>(FindObjectsSortMode.None);
foreach (NanoBrain brain in nanoBrains) { foreach (NanoBrain brain in nanoBrains) {
UpdateWeight(brain, "Avoidance", swarmControl.avoidanceForce); NanoBrainComponent.UpdateWeight(brain, "Avoidance", swarmControl.avoidanceForce);
UpdateWeight(brain, "Cohesion", swarmControl.cohesionForce); NanoBrainComponent.UpdateWeight(brain, "Cohesion", swarmControl.cohesionForce);
UpdateWeight(brain, "Separation", swarmControl.separationForce); NanoBrainComponent.UpdateWeight(brain, "Separation", swarmControl.separationForce);
UpdateWeight(brain, "Alignment", swarmControl.alignmentForce); NanoBrainComponent.UpdateWeight(brain, "Alignment", swarmControl.alignmentForce);
} }
Debug.Log("Updated weights"); Debug.Log("Updated weights");
} }
} }
protected void UpdateWeight(NanoBrain brain, string name, float weight) { // protected void UpdateWeight(NanoBrain brain, string name, float weight) {
Nucleus root = brain.root; // Nucleus root = brain.root;
foreach (Synapse synapse in root.synapses) { // foreach (Synapse synapse in root.synapses) {
if (synapse.nucleus.name == name) { // if (synapse.nucleus.name == name) {
synapse.weight = weight; // synapse.weight = weight;
} // }
} // }
} // }
} }

View File

@ -14,7 +14,7 @@ public class SwarmControl : MonoBehaviour
// public float bodyForce = 20; // public float bodyForce = 20;
public float perceptionDistance = 1.0f; public float perceptionDistance = 1.0f;
public float boundaryForce = 2.0f; //public float boundaryForce = 2.0f;
public Vector3 spaceSize = new (10, 10, 10); public Vector3 spaceSize = new (10, 10, 10);
public Vector3 boundaryWidth = Vector3.one * 1.0f; public Vector3 boundaryWidth = Vector3.one * 1.0f;
} }

File diff suppressed because it is too large Load Diff