Each boid now has its own brain (but output is still not correct)

This commit is contained in:
Pascal Serrarens 2026-01-30 10:10:37 +01:00
parent 5cb9e788a4
commit 728ef1767c
5 changed files with 161 additions and 64 deletions

View File

@ -7,22 +7,61 @@ using static Unity.Mathematics.math;
[System.Serializable]
public class Cluster : INucleus {
// The ScriptableObject asset from which the runtime object has been created
[SerializeField]
protected string _name;
public virtual string name {
get => _name;
set => _name = value;
}
public ClusterPrefab storedPrefab;
//public ClusterPrefab prefab;
public Cluster() {
}
public Cluster(Cluster parent) {
// public Cluster() {
// }
public Cluster(Cluster parent, ClusterPrefab realPrefab) {
this.storedPrefab = realPrefab;
this.parent = parent;
this.parent?.nuclei.Add(this);
ClonePrefab();
}
public Cluster(ClusterPrefab prefab) {
this.storedPrefab = prefab;
public Cluster(ClusterPrefab realPrefab) {
this.storedPrefab = realPrefab;
//this.prefab = prefab.Clone();
this.name = prefab.name;
this.name = realPrefab.name;
this.cluster = null;
if (this.cluster != null)
this.cluster.nuclei.Add(this);
ClonePrefab();
// IReceptor[] nucleiArray = this.storedPrefab.nuclei.ToArray();
// // first clone the nuclei without their connections
// foreach (IReceptor nucleus in this.storedPrefab.nuclei)
// nucleus.ShallowCloneTo(this);
// IReceptor[] clonedNuclei = this.nuclei.ToArray();
// // Now clone the connections
// for (int nucleusIx = 0; nucleusIx < nucleiArray.Length; nucleusIx++) {
// //IReceptor receptor = nucleiArray[nucleusIx];
// IReceptor clonedReceptor = clonedNuclei[nucleusIx];
// if (clonedReceptor == null)
// continue;
// // Copy the receivers, which will also create the synapses
// foreach (INucleus receiver in nucleiArray[nucleusIx].receivers) {
// int ix = GetNucleusIndex(nucleiArray, receiver);
// if (ix < 0)
// continue;
// if (clonedNuclei[ix] is not INucleus clonedReceiver)
// continue;
// clonedReceptor.AddReceiver(clonedReceiver);
// }
// }
}
public Cluster(ClusterPrefab parent, ClusterPrefab realPrefab) {
@ -32,6 +71,61 @@ public class Cluster : INucleus {
this.cluster = parent;
if (this.cluster != null)
this.cluster.nuclei.Add(this);
ClonePrefab();
// IReceptor[] nucleiArray = this.storedPrefab.nuclei.ToArray();
// // first clone the nuclei without their connections
// foreach (IReceptor nucleus in this.storedPrefab.nuclei)
// nucleus.ShallowCloneTo(this);
// IReceptor[] clonedNuclei = this.nuclei.ToArray();
// // Now clone the connections
// for (int nucleusIx = 0; nucleusIx < nucleiArray.Length; nucleusIx++) {
// IReceptor receptor = nucleiArray[nucleusIx];
// IReceptor clonedReceptor = clonedNuclei[nucleusIx];
// if (clonedReceptor == null)
// continue;
// // Copy the receivers, which will also create the synapses
// foreach (INucleus receiver in nucleiArray[nucleusIx].receivers) {
// int ix = GetNucleusIndex(nucleiArray, receiver);
// if (ix < 0)
// continue;
// if (clonedNuclei[ix] is not INucleus clonedReceiver)
// continue;
// clonedReceptor.AddReceiver(clonedReceiver);
// }
// }
}
private void ClonePrefab() {
IReceptor[] nucleiArray = this.storedPrefab.nuclei.ToArray();
// first clone the nuclei without their connections
foreach (IReceptor nucleus in this.storedPrefab.nuclei)
nucleus.ShallowCloneTo(this);
IReceptor[] clonedNuclei = this.nuclei.ToArray();
// Now clone the connections
for (int nucleusIx = 0; nucleusIx < nucleiArray.Length; nucleusIx++) {
IReceptor receptor = nucleiArray[nucleusIx];
IReceptor clonedReceptor = clonedNuclei[nucleusIx];
if (clonedReceptor == null)
continue;
// Copy the receivers, which will also create the synapses
foreach (INucleus receiver in nucleiArray[nucleusIx].receivers) {
int ix = GetNucleusIndex(nucleiArray, receiver);
if (ix < 0)
continue;
if (clonedNuclei[ix] is not INucleus clonedReceiver)
continue;
clonedReceptor.AddReceiver(clonedReceiver);
}
}
}
public virtual IReceptor Clone() {
@ -55,7 +149,9 @@ public class Cluster : INucleus {
// }
public IReceptor ShallowCloneTo(Cluster parent) {
Cluster clone = new(parent);
Cluster clone = new(parent, this.storedPrefab) {
name = this.name,
};
return clone;
}
@ -65,55 +161,55 @@ public class Cluster : INucleus {
// }
// Deep clone a nucleus with its connections
public virtual Cluster InstantiatePrefab(ClusterPrefab prefab) {
Cluster clone = new Cluster {
nuclei = new()
};
// public virtual Cluster InstantiatePrefab(ClusterPrefab prefab) {
// Cluster clone = new Cluster {
// nuclei = new()
// };
IReceptor[] nucleiArray = this.nuclei.ToArray();
// first clone the nuclei without their connections
foreach (IReceptor nucleus in this.nuclei)
nucleus.ShallowCloneTo(clone);
IReceptor[] clonedNuclei = clone.nuclei.ToArray();
// IReceptor[] nucleiArray = this.nuclei.ToArray();
// // first clone the nuclei without their connections
// foreach (IReceptor nucleus in this.nuclei)
// nucleus.ShallowCloneTo(clone);
// IReceptor[] clonedNuclei = clone.nuclei.ToArray();
// Now clone the connections
for (int nucleusIx = 0; nucleusIx < nucleiArray.Length; nucleusIx++) {
IReceptor receptor = nucleiArray[nucleusIx];
IReceptor clonedReceptor = clonedNuclei[nucleusIx];
if (clonedReceptor == null)
continue;
// // Now clone the connections
// for (int nucleusIx = 0; nucleusIx < nucleiArray.Length; nucleusIx++) {
// IReceptor receptor = nucleiArray[nucleusIx];
// IReceptor clonedReceptor = clonedNuclei[nucleusIx];
// if (clonedReceptor == null)
// continue;
// Copy the synapses
if (receptor is INucleus nucleus) {
foreach (Synapse synapse in nucleus.synapses) {
if (clonedReceptor is not INucleus clonedNucleus)
continue;
// // Copy the synapses
// if (receptor is INucleus nucleus) {
// foreach (Synapse synapse in nucleus.synapses) {
// if (clonedReceptor is not INucleus clonedNucleus)
// continue;
int ix = GetNucleusIndex(nucleiArray, synapse.nucleus);
if (ix < 0)
continue;
IReceptor clonedSynapseNucleus = clonedNuclei[ix];
if (clonedSynapseNucleus == null)
continue;
// int ix = GetNucleusIndex(nucleiArray, synapse.nucleus);
// if (ix < 0)
// continue;
// IReceptor clonedSynapseNucleus = clonedNuclei[ix];
// if (clonedSynapseNucleus == null)
// continue;
clonedNucleus.AddSynapse(clonedSynapseNucleus, synapse.weight);
}
}
// Copy the receivers
foreach (INucleus receiver in nucleiArray[nucleusIx].receivers) {
int ix = GetNucleusIndex(nucleiArray, receiver);
if (ix < 0)
continue;
// clonedNucleus.AddSynapse(clonedSynapseNucleus, synapse.weight);
// }
// }
// // Copy the receivers
// foreach (INucleus receiver in nucleiArray[nucleusIx].receivers) {
// int ix = GetNucleusIndex(nucleiArray, receiver);
// if (ix < 0)
// continue;
if (clonedNuclei[ix] is not INucleus clonedReceiver)
continue;
// if (clonedNuclei[ix] is not INucleus clonedReceiver)
// continue;
clonedReceptor.AddReceiver(clonedReceiver);
}
}
// clonedReceptor.AddReceiver(clonedReceiver);
// }
// }
return clone;
}
// return clone;
// }
private int GetNucleusIndex(IReceptor[] nucleiArray, IReceptor nucleus) {
for (int i = 0; i < nucleiArray.Length; i++) {
@ -129,13 +225,6 @@ public class Cluster : INucleus {
[SerializeReference]
public List<IReceptor> nuclei = new();
[SerializeField]
protected string _name;
public virtual string name {
get => _name;
set => _name = value;
}
public List<INucleus> _inputs = null;
public virtual List<INucleus> inputs {
get {
@ -154,7 +243,13 @@ public class Cluster : INucleus {
}
//public INucleus output => prefab.output;
public virtual INucleus output => this.nuclei[0] as INucleus;
public virtual INucleus output {//=> this.nuclei[0] as INucleus;
get {
if (this.nuclei.Count > 0)
return this.nuclei[0] as INucleus;
return null;
}
}
// Not sure if this belongs here...
[SerializeReference]

View File

@ -169,9 +169,7 @@ public class Neuron : INucleus {
public Neuron(Cluster parent, string name) {
this.parent = parent;
this.name = name;
if (this.cluster != null) {
this.cluster.nuclei.Add(this);
}
this.parent?.nuclei.Add(this);
}
public Neuron(ClusterPrefab parent, string name) {
this.cluster = parent;

View File

@ -4,7 +4,6 @@ using UnityEngine;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[Serializable]
public class Receptor : IReceptor {
private ClusterPrefab cluster;
@ -141,7 +140,9 @@ public class Receptor : IReceptor {
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) {
this.localPosition = newLocalPositionVector;
if (this._receivers == null)
return;
thingIds ??= new int[this._receivers.Count];
int receiverIx = 0;

View File

@ -623,6 +623,9 @@ public class ClusterInspector : Editor {
private void OnClusterPicked(INucleus nucleus, ClusterPrefab prefab) {
Cluster subclusterInstance = new(this.cluster, prefab);
subclusterInstance.AddReceiver(nucleus);
// This does not work somehow
// this.currentNucleus = subclusterInstance;
// BuildLayers();
}
private void EditCluster(Cluster subCluster) {

View File

@ -1,11 +1,11 @@
using System;
using UnityEngine;
public class NanoBrainComponent : MonoBehaviour {
[SerializeField]
public ClusterPrefab defaultBrain;
[NonSerialized]
private Cluster brainInstance;
//public INucleus root => brainInstance.output;
public Cluster brain {
get {
if (brainInstance == null && defaultBrain != null) {