NucleusArray to Receptor

This commit is contained in:
Pascal Serrarens 2026-02-13 15:12:45 +01:00
parent f295da9c55
commit f8aaa4ca80
8 changed files with 99 additions and 72 deletions

View File

@ -79,13 +79,13 @@ public class Cluster : Nucleus {
// Copy nucleus arrays
for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) {
Nucleus prefabReceptor = prefabNuclei[nucleusIx];
if (prefabReceptor is not Nucleus prefabNucleus)
if (prefabReceptor is not Receptor prefabNucleus)
continue;
if (prefabNucleus.array == null || prefabNucleus.array.nuclei == null || prefabNucleus.array.nuclei.Length == 0)
continue;
Nucleus clonedNucleus = clonedNuclei[nucleusIx] as Nucleus;
Receptor clonedNucleus = clonedNuclei[nucleusIx] as Receptor;
if (prefabNucleus == prefabNucleus.array.nuclei[0]) {
// We clone the array only for the first entry
NucleusArray clonedArray = new(prefabNucleus.array.nuclei.Length, "array");
@ -106,7 +106,7 @@ public class Cluster : Nucleus {
else {
// The others will refer to the array created for the first nucleus in the array
int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabNucleus.array.nuclei[0]);
Nucleus clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Nucleus;
Receptor clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Receptor;
clonedNucleus.array = clonedFirstNucleus.array;
}
}
@ -153,7 +153,7 @@ public class Cluster : Nucleus {
public override Nucleus Clone(ClusterPrefab prefab) {
//Neuron clone = new(this.cluster, this.name) {
Neuron clone = new(prefab, this.name) {
array = this.array,
// array = this.array,
};
foreach (Synapse synapse in this.synapses) {

View File

@ -295,30 +295,30 @@ public class ClusterInspector : Editor {
row++;
}
}
else {
else if (this.currentNucleus is Receptor receptor1) {
float maxValue = 0;
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
foreach (Nucleus nucleus in receptor1.array.nuclei) {
float value = length(nucleus.outputValue);
if (value > maxValue)
maxValue = value;
}
float spacing = 400f / this.currentNucleus.array.nuclei.Count();
float spacing = 400f / receptor1.array.nuclei.Count();
float margin = 10 + spacing / 2;
float xMin = 150 - size;
float xMax = 150 + size;
float yMin = 10 + margin - size / 2;
float yMax = 400 - margin + size;
Vector3[] verts = new Vector3[4] {
new(xMin, yMin, 0),
new(xMax, yMin, 0),
new(xMax, yMax, 0),
new(xMin, yMax, 0)
};
new(xMin, yMin, 0),
new(xMax, yMin, 0),
new(xMax, yMax, 0),
new(xMin, yMax, 0)
};
Handles.color = Color.black;
Handles.DrawAAConvexPolygon(verts);
int row = 0;
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
foreach (Nucleus nucleus in receptor1.array.nuclei) {
Vector3 pos = new(150, margin + row * spacing, 0.0f);
Handles.color = Color.white;
// The selected nucleus highlight ring
@ -357,9 +357,11 @@ public class ClusterInspector : Editor {
int row = 0;
List<NucleusArray> drawnArrays = new();
foreach (Nucleus receiver in nucleus.receivers) {
if (drawnArrays.Contains(receiver.array))
continue;
drawnArrays.Add(receiver.array);
if (receiver is Receptor receptor) {
if (drawnArrays.Contains(receptor.array))
continue;
drawnArrays.Add(receptor.array);
}
Nucleus receiverNucleus = receiver;
if (receiverNucleus == null)
@ -383,10 +385,10 @@ public class ClusterInspector : Editor {
int neuronCount = 0;
List<NucleusArray> drawnArrays = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Neuron neuroid) {
if (drawnArrays.Contains(neuroid.array))
if (synapse.nucleus is Receptor receptor) {
if (drawnArrays.Contains(receptor.array))
continue;
drawnArrays.Add(neuroid.array);
drawnArrays.Add(receptor.array);
}
float value = length(synapse.nucleus.outputValue) * synapse.weight;
@ -403,7 +405,7 @@ public class ClusterInspector : Editor {
int row = 0;
drawnArrays = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Neuron neuron) {
if (synapse.nucleus is Receptor neuron) {
if (drawnArrays.Contains(neuron.array))
continue;
drawnArrays.Add(neuron.array);
@ -461,11 +463,13 @@ public class ClusterInspector : Editor {
fontStyle = FontStyle.Bold,
};
if (nucleus.array == null || nucleus.array.nuclei == null || nucleus.array.nuclei.Count() == 0)
nucleus.array = new NucleusArray(nucleus);
if (nucleus is Receptor receptor1) {
if (receptor1.array == null || receptor1.array.nuclei == null || receptor1.array.nuclei.Count() == 0)
receptor1.array = new NucleusArray(nucleus);
if ((!expandArray || nucleus.array.nuclei.First() != this.currentNucleus) && nucleus.array.nuclei.Count() > 1) {
Handles.Label(labelPosition, nucleus.array.nuclei.Count().ToString(), style);
if ((!expandArray || receptor1.array.nuclei.First() != this.currentNucleus) && receptor1.array.nuclei.Count() > 1) {
Handles.Label(labelPosition, receptor1.array.nuclei.Count().ToString(), style);
}
}
if (nucleus is ReceptorArray receptor) {
Handles.Label(labelPosition, receptor.instances.Count().ToString(), style);
@ -481,9 +485,9 @@ public class ClusterInspector : Editor {
// Handles.Label(labelPosition, $"[{arrayIx}]", style);
// }
// }
if (expandArray && nucleus.array.nuclei.First() == this.currentNucleus) {
if (expandArray && nucleus is Receptor receptor2 && receptor2.array.nuclei.First() == this.currentNucleus) {
int arrayIx = 0;
foreach (Nucleus n in nucleus.array.nuclei) {
foreach (Nucleus n in receptor2.array.nuclei) {
if (n == nucleus)
break;
arrayIx++;
@ -672,8 +676,8 @@ public class ClusterInspector : Editor {
continue;
}
else {
if (synapse.nucleus.array != null && synapse.nucleus.array.nuclei.Length > 1)
array = synapse.nucleus.array;
if (synapse.nucleus is Receptor receptor2 && receptor2.array != null && receptor2.array.nuclei.Length > 1)
array = receptor2.array;
}
EditorGUILayout.Space();
@ -721,8 +725,10 @@ public class ClusterInspector : Editor {
neuron.curvePreset = newPreset;
EditorGUILayout.EndHorizontal();
}
if (neuron.array == null || neuron.array.nuclei == null || neuron.array.nuclei.Count() == 0)
neuron.array = new NucleusArray(neuron);
if (neuron is Receptor receptor2) {
if (receptor2.array == null || receptor2.array.nuclei == null || receptor2.array.nuclei.Count() == 0)
receptor2.array = new NucleusArray(neuron);
}
// if (this.currentNucleus is Receptor receptor1) {
// EditorGUILayout.BeginHorizontal();
@ -778,13 +784,20 @@ public class ClusterInspector : Editor {
Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
}
}
else {
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) {
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
if (this.currentNucleus is Receptor receptor1) {
foreach (Nucleus nucleus in receptor1.array.nuclei) {
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
}
}
else {
Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue);
Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
}
}
}

View File

@ -45,12 +45,12 @@ public class Neuron : Nucleus {
public CurvePresets curvePreset {
get { return _curvePreset; }
set {
if (this.array != null && this.array.nuclei != null) {
foreach (Neuron nucleus in this.array.nuclei.Cast<Neuron>()) {
nucleus._curvePreset = value;
nucleus.curve = GenerateCurve();
}
}
// if (this.array != null && this.array.nuclei != null) {
// foreach (Neuron nucleus in this.array.nuclei.Cast<Neuron>()) {
// nucleus._curvePreset = value;
// nucleus.curve = GenerateCurve();
// }
// }
_curvePreset = value;
this.curve = GenerateCurve();
}
@ -145,7 +145,7 @@ public class Neuron : Nucleus {
}
protected virtual void CloneFields(Neuron clone) {
clone.array = this.array;
// clone.array = this.array;
clone.bias = this.bias;
clone.combinator = this.combinator;
clone.curve = this.curve;

View File

@ -6,8 +6,8 @@ using static Unity.Mathematics.math;
[Serializable]
public abstract class Nucleus {
public string name;
public string name;
//[Obsolete]
public ClusterPrefab cluster { get; set; }
public Cluster parent { get; set; }
@ -48,7 +48,7 @@ public abstract class Nucleus {
#region Synapses
public Vector3 bias = Vector3.zero;
[SerializeField]
private List<Synapse> _synapses = new();
public List<Synapse> synapses => _synapses;
@ -90,35 +90,43 @@ public abstract class Nucleus {
#endregion Receivers
[SerializeReference]
private NucleusArray _array;
public NucleusArray array {
get { return _array; }
set { _array = value; }
}
// [SerializeReference]
// private NucleusArray _array;
// public NucleusArray array {
// get { return _array; }
// set { _array = value; }
// }
#region Update
public abstract void UpdateStateIsolated();
public virtual void UpdateNuclei() {
if (this.array == null || this.array.nuclei == null || this.array.nuclei.Length <= 1)
return;
// if (this.array == null || this.array.nuclei == null || this.array.nuclei.Length <= 1)
return;
this.stale++;
if (this.stale > staleValueForSleep) {
//Debug.Log($"{this.name} goes to sleep, stale = {this.stale}");
_outputValue = Vector3.zero;
}
// this.stale++;
// if (this.stale > staleValueForSleep) {
// //Debug.Log($"{this.name} goes to sleep, stale = {this.stale}");
// _outputValue = Vector3.zero;
// }
}
public virtual void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
this.array.ProcessStimulus(thingId, inputValue, thingName);
//this.array.ProcessStimulus(thingId, inputValue, thingName);
// this.ProcessStimulus(inputValue);
this.stale = 0;
this.bias = inputValue;
this.parent.UpdateFromNucleus(this);
}
public virtual void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) {
this.array.ProcessStimulus(thingId, inputValue, thingName);
}
// public virtual void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) {
// // this.array.ProcessStimulus(thingId, inputValue, thingName);
// // this.ProcessStimulus(inputValue);
// this.stale = 0;
// this.bias = inputValue;
// this.parent.UpdateFromNucleus(this);
// }
#endregion Update

View File

@ -9,23 +9,26 @@ public class Receptor : Neuron {
public override Nucleus ShallowCloneTo(Cluster parent) {
Receptor clone = new(parent, name);
CloneFields(clone);
clone.array = this.array;
return clone;
}
public override Nucleus Clone(ClusterPrefab prefab) {
Receptor clone = new(prefab, name);
CloneFields(clone);
clone.array = this.array;
// Adding receivers will also add synapses to the receivers
foreach (Nucleus receiver in this.receivers)
clone.AddReceiver(receiver);
return clone;
}
// [SerializeReference]
// private NucleusArray _array;
// public NucleusArray array {
// get { return _array; }
// set { _array = value; }
// }
[SerializeReference]
private NucleusArray _array;
public NucleusArray array {
get { return _array; }
set { _array = value; }
}
public override void UpdateStateIsolated() {
@ -40,4 +43,7 @@ public class Receptor : Neuron {
}
}
public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
this.array.ProcessStimulus(thingId, inputValue, thingName);
}
}

View File

@ -138,9 +138,9 @@ public class ReceptorArray : Nucleus {
private Dictionary<int, Nucleus> thingReceivers = new();
public override void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) {
ProcessStimulus(inputValue, thingId, thingName);
}
// public override void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) {
// ProcessStimulus(inputValue, thingId, thingName);
// }
public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
CleanupReceivers();
if (!thingReceivers.TryGetValue(thingId, out Nucleus selectedReceiver)) {

View File

@ -14,8 +14,8 @@ public class SelectorBrain : NanoBrain {
}
protected void Update() {
receptor.ProcessStimulus(0, input1);
receptor.ProcessStimulus(1, input2);
receptor.ProcessStimulus(input1, 0);
receptor.ProcessStimulus(input2, 1);
output = this.brain.outputValue;
this.brain.UpdateNuclei();

View File

@ -9,7 +9,7 @@ public class Selector : Neuron {
public override Nucleus ShallowCloneTo(Cluster newParent) {
Selector clone = new(newParent, this.name) {
array = this.array,
// array = this.array,
curve = this.curve,
curvePreset = this.curvePreset,
curveMax = this.curveMax,