Move to ClusterPfab

This commit is contained in:
Pascal Serrarens 2026-01-28 17:44:18 +01:00
parent 96ed53312d
commit 33f5af32d1
21 changed files with 432 additions and 464 deletions

View File

@ -73,7 +73,6 @@
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector2Int.cs" />
<Compile Include="Assets/Scenes/Boids/Scripts/SwarmControl.cs" />
<Compile Include="Assets/NanoBrain/INucleus.cs" />
<Compile Include="Assets/NanoBrain/ClusterInstance.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Spherical.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector3FloatTest.cs" />
<Compile Include="Assets/NanoBrain/MemoryCell.cs" />
@ -81,6 +80,7 @@
<Compile Include="Assets/Scenes/Boids/Scripts/Boid.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/SwingTwist.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/SphericalTest.cs" />
<Compile Include="Assets/NanoBrain/ClusterPrefab.cs" />
<Compile Include="Assets/NanoBrain/Cluster.cs" />
<Compile Include="Assets/NanoBrain/Synapse.cs" />
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector3IntTest.cs" />

View File

@ -1,84 +1,259 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[CreateAssetMenu(menuName = "Passer/Cluster")]
public class Cluster : ScriptableObject {
public Cluster cluster => this;
[System.Serializable]
public class Cluster : INucleus {
// The ScriptableObject asset from which the runtime object has been created
public Cluster asset;
public readonly ClusterPrefab prefab;
public ClusterPrefab cluster { get; set; }
[SerializeField]
protected string _name;
public virtual string name {
get => _name;
set => _name = value;
}
// Hmm, a cluster instance can never be part of a scriptable object...(Cluster)
public Cluster(ClusterPrefab parent, ClusterPrefab prefab) {
this.prefab = prefab;
this.cluster = parent;
if (this.cluster != null)
this.cluster.nuclei.Add(this);
// foreach (IReceptor nucleus in this.prefab.nuclei) {
// IReceptor clone = nucleus.CloneTo(null);
// this.dynamicNuclei.Add(clone);
// }
}
public virtual IReceptor Clone() {
Neuron clone = new(this.cluster, this.name) {
array = this.array,
};
foreach (Synapse synapse in this.synapses) {
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
clonedSynapse.weight = synapse.weight;
}
foreach (INucleus receiver in this.receivers) {
clone.AddReceiver(receiver);
}
return clone;
}
// Not sure if this belongs here...
[SerializeReference]
private NucleusArray _array;
public NucleusArray array {
get { return _array; }
set { _array = value; }
}
#region Synapses
// class ClusterSynapse : Synapse {
// public IReceptor receptor;
// public ClusterSynapse(IReceptor nucleus, INucleus receptor, float weight = 1.0f) : base(nucleus, weight) {
// this.receptor = receptor;
// }
// }
[SerializeField]
private List<Synapse> _synapses = new();
public List<Synapse> synapses => _synapses;
public Synapse AddSynapse(IReceptor sendingNucleus) {
Synapse synapse = new(sendingNucleus); //, this.prefab.inputs[0]);
this._synapses.Add(synapse);
return synapse;
// else {
// INucleus receptor = (INucleus)this.prefab.nuclei.Find(nucleus => nucleus is INucleus n && nucleus.name == nucleusName);
// ClusterSynapse synapse = new(sendingNucleus, receptor);
// receptor.AddSynapse(sendingNucleus);
// }
// // Add synapse to which neuron?
// return null;
}
// Does this even exist already?
public void RemoveSynapse() {
}
#endregion Synapses
#region Receivers
[SerializeReference]
public List<IReceptor> nuclei = new();
// public List<Cluster> subClusters = new();
public void AddSubCluster(ClusterInstance subCluster) {
this.nuclei.Add(subCluster);
private List<INucleus> _receivers = new();
public List<INucleus> receivers {
get { return _receivers; }
set { _receivers = value; }
}
public INucleus output => this.nuclei[0] as INucleus;
public virtual void AddReceiver(INucleus receivingNucleus) {
this._receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this);
}
public List<INucleus> _inputs = null;
public List<INucleus> inputs {
get {
if (this._inputs == null) {
this._inputs = new();
foreach (IReceptor receptor in this.nuclei) {
if (receptor is INucleus nucleus)
this._inputs.Add(nucleus);
}
}
return this._inputs;
public void RemoveReceiver(INucleus receiverNucleus) {
this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
}
// public void AddReceiver(INucleus receivingNucleus) {
// int newLength = this._receivers.Count + 1;
// INucleus[] newReceivers = new INucleus[newLength];
// // Copy the existing receivers
// for (int ix = 0; ix < this._receivers.Count; ix++)
// newReceivers[ix] = this._receivers[ix];
// // Add the new receivers
// newReceivers[this._receivers.Count] = receivingNucleus;
// // Replace the receivers with the new receivers
// this._receivers = new(newReceivers);
// receivingNucleus.AddSynapse(this);
// }
// public void RemoveReceiver(INucleus receivingNucleus) {
// Debug.Log("Clusterinstance. remote receiver");
// int newLength = this._receivers.Count - 1;
// if (newLength < 0)
// // Array was empty, so we cannot remove anything
// return;
// INucleus[] newReceivers = new INucleus[newLength];
// int newIx = 0;
// // Copy all receivers except receivingNucleus
// for (int ix = 0; ix < this._receivers.Count; ix++) {
// if (this._receivers[ix] == receivingNucleus)
// // skip the receiver we want to remote
// continue;
// if (newIx >= newLength)
// // We want to copy more elements than expected
// // the receivingNucleus is not found
// // and the original array is returned
// return;
// newReceivers[newIx] = this._receivers[ix];
// newIx++;
// }
// this._receivers = new(newReceivers);
// }
#endregion Receivers
#region Runtime
[NonSerialized]
private int stale = 1000;
public bool isSleeping => lengthsq(this.outputValue) == 0;
[NonSerialized]
protected float3 _outputValue;
public virtual float3 outputValue {
get { return _outputValue; }
set {
this.stale = 0;
_outputValue = value;
}
}
// Call this function to ensure that there is at least one nucleus
// This is an invariant and should be ensured before the nucleus is used
// because output requires it.
public void EnsureInitialization() {
nuclei ??= new List<IReceptor>();
if (nuclei.Count == 0)
new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
#region Update
public virtual void UpdateState() {
UpdateState(new float3(0, 0, 0));
}
public void GarbageCollection() {
HashSet<INucleus> visitedNuclei = new();
MarkNuclei(visitedNuclei, this.output);
//Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei");
this.nuclei.RemoveAll(nucleus => nucleus is INucleus n && visitedNuclei.Contains(n) == false);
}
public void UpdateState(float3 inputValue) {
float3 sum = inputValue; // new(0, 0, 0);
public void MarkNuclei(HashSet<INucleus> visitedNuclei, INucleus nucleus) {
if (nucleus is null)
return;
visitedNuclei.Add(nucleus);
if (nucleus.synapses != null) {
HashSet<Synapse> visitedSynapses = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse != null && synapse.nucleus != null) {
visitedSynapses.Add(synapse);
if (synapse.nucleus is INucleus synapse_nucleus)
MarkNuclei(visitedNuclei, synapse_nucleus);
}
}
nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
}
if (nucleus.receivers != null) {
HashSet<INucleus> visitedReceivers = new();
foreach (INucleus receiver in nucleus.receivers) {
if (receiver != null && receiver != null) {
visitedReceivers.Add(receiver);
visitedNuclei.Add(receiver);
}
}
nucleus.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false);
//Applying the weight factgors
foreach (Synapse synapse in this.synapses) {
sum += synapse.weight * synapse.nucleus.outputValue;
}
// This does not work because the prefab nucleus does not have a state
this.prefab.inputs[0].UpdateState(sum);
}
public void UpdateNuclei() {
foreach (IReceptor nucleus in this.nuclei)
this.stale++;
if (this.stale > 2)
_outputValue = Vector3.zero;
foreach (IReceptor nucleus in this.prefab.nuclei)
nucleus.UpdateNuclei();
}
}
#endregion Update
#endregion Runtime
/*
[SerializeField]
private List<IReceptor> _dynamicNuclei;
public List<IReceptor> dynamicNuclei {// = new();
get {
if (_dynamicNuclei == null) {
this._dynamicNuclei = new();
foreach (IReceptor nucleus in this.prefab.nuclei) {
IReceptor clone = nucleus.CloneTo(null);
this._dynamicNuclei.Add(clone);
}
}
return this._dynamicNuclei;
}
}
public List<INucleus> _inputs = null;
public List<INucleus> inputs {
get {
this._inputs = new();
if (this.dynamicNuclei != null) {
foreach (IReceptor receptor in this.dynamicNuclei) {
if (receptor is INucleus nucleus)
this._inputs.Add(nucleus);
}
}
return this._inputs;
}
}
public INucleus output => this.dynamicNuclei[0] as INucleus;
public float3 outputValue => this.output.outputValue;
public IReceptor CloneTo(ClusterPrefab parent) {
Cluster clone = new(parent, this.prefab);
return clone;
}
public IReceptor Clone() {
Cluster clone = new(this.cluster, this.prefab);
return clone;
}
#region Properties
public string name {
get { return prefab.name; }
set { prefab.name = value; }
}
public bool isSleeping => lengthsq(this.outputValue) == 0;
public NucleusArray array { get; set; }
#endregion Properties
*/
}

View File

@ -1,2 +1,2 @@
fileFormatVersion: 2
guid: 60a957541c24c57e78018c202ebb1d9b
guid: f13cdc4a175a9f379a00317ae68d8bea

View File

@ -1,138 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[System.Serializable]
public class ClusterInstance : INucleus {
// The ScriptableObject asset from which the runtime object has been created
public Cluster asset;
public Cluster cluster => this.asset;
public List<IReceptor> dynamicNuclei = new();
public INucleus output => this.asset.nuclei[0] as INucleus;
public float3 outputValue => this.output.outputValue;
public ClusterInstance(Cluster asset) {
this.asset = asset;
foreach (IReceptor nucleus in this.asset.nuclei)
dynamicNuclei.Add(nucleus.Clone());
}
public IReceptor Clone() {
ClusterInstance clone = new(this.asset);
return clone;
}
#region Properties
public string name {
get { return asset.name; }
set { asset.name = value; }
}
public bool isSleeping => lengthsq(this.outputValue) == 0;
public NucleusArray array { get; set; }
#endregion Properties
#region Synapses
[SerializeReference]
private List<Synapse> _synapses = new();
public List<Synapse> synapses => new(_synapses);
public Synapse AddSynapse(IReceptor sendingNucleus, string nucleusName = null) {
if (nucleusName == null) {
Synapse synapse = new(sendingNucleus);
this._synapses.Add(synapse);
// Nice, but this is not yet connected to the nucleusName
} else {
INucleus receptor = (INucleus)this.asset.nuclei.Find(nucleus => nucleus is INucleus n && nucleus.name == nucleusName);
receptor.AddSynapse(sendingNucleus);
}
// Add synapse to which neuron?
return null;
}
// Does this even exist already?
public void RemoveSynapse() {
}
#endregion Synapses
#region Receivers
[SerializeReference]
private List<INucleus> _receivers = new();
public List<INucleus> receivers {
get { return _receivers; }
set { _receivers = value; }
}
public void AddReceiver(INucleus receivingNucleus) {
int newLength = this._receivers.Count + 1;
INucleus[] newReceivers = new INucleus[newLength];
// Copy the existing receivers
for (int ix = 0; ix < this._receivers.Count; ix++)
newReceivers[ix] = this._receivers[ix];
// Add the new receivers
newReceivers[this._receivers.Count] = receivingNucleus;
// Replace the receivers with the new receivers
this._receivers = new(newReceivers);
receivingNucleus.AddSynapse(this);
}
public void RemoveReceiver(INucleus receivingNucleus) {
int newLength = this._receivers.Count - 1;
if (newLength < 0)
// Array was empty, so we cannot remove anything
return;
INucleus[] newReceivers = new INucleus[newLength];
int newIx = 0;
// Copy all receivers except receivingNucleus
for (int ix = 0; ix < this._receivers.Count; ix++) {
if (this._receivers[ix] == receivingNucleus)
// skip the receiver we want to remote
continue;
if (newIx >= newLength)
// We want to copy more elements than expected
// the receivingNucleus is not found
// and the original array is returned
return;
newReceivers[newIx] = this._receivers[ix];
newIx++;
}
this._receivers = new(newReceivers);
}
#endregion Receivers
#region Update
public void UpdateState() {
float3 sum = new(0, 0, 0);
//Applying the weight factgors
foreach (Synapse synapse in this.synapses) {
sum += synapse.weight * synapse.nucleus.outputValue;
}
this.asset.inputs[0].UpdateState();
}
public void UpdateNuclei() {
foreach (IReceptor nucleus in this.asset.nuclei)
nucleus.UpdateNuclei();
}
#endregion Update
}

View File

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

View File

@ -0,0 +1,84 @@
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Passer/Cluster")]
public class ClusterPrefab : ScriptableObject {
//public virtual Cluster cluster {get;set;}
// The ScriptableObject asset from which the runtime object has been created
//public Cluster asset;
[SerializeReference]
public List<IReceptor> nuclei = new();
// public List<Cluster> subClusters = new();
// public void AddSubCluster(ClusterInstance subCluster) {
// this.nuclei.Add(subCluster);
// }
public virtual INucleus output => this.nuclei[0] as INucleus;
public List<INucleus> _inputs = null;
public virtual List<INucleus> inputs {
get {
if (this._inputs == null) {
this._inputs = new();
foreach (IReceptor receptor in this.nuclei) {
if (receptor is INucleus nucleus)
this._inputs.Add(nucleus);
}
}
return this._inputs;
}
}
// Call this function to ensure that there is at least one nucleus
// This is an invariant and should be ensured before the nucleus is used
// because output requires it.
public void EnsureInitialization() {
nuclei ??= new List<IReceptor>();
if (nuclei.Count == 0)
new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
}
public void GarbageCollection() {
HashSet<INucleus> visitedNuclei = new();
MarkNuclei(visitedNuclei, this.output);
//Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei");
this.nuclei.RemoveAll(nucleus => nucleus is INucleus n && visitedNuclei.Contains(n) == false);
}
public void MarkNuclei(HashSet<INucleus> visitedNuclei, INucleus nucleus) {
if (nucleus is null)
return;
visitedNuclei.Add(nucleus);
if (nucleus.synapses != null) {
HashSet<Synapse> visitedSynapses = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse != null && synapse.nucleus != null) {
visitedSynapses.Add(synapse);
if (synapse.nucleus is INucleus synapse_nucleus)
MarkNuclei(visitedNuclei, synapse_nucleus);
}
}
nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
}
if (nucleus.receivers != null) {
HashSet<INucleus> visitedReceivers = new();
foreach (INucleus receiver in nucleus.receivers) {
if (receiver != null && receiver != null) {
visitedReceivers.Add(receiver);
visitedNuclei.Add(receiver);
}
}
nucleus.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false);
}
}
public virtual void UpdateNuclei() {
foreach (IReceptor nucleus in this.nuclei)
nucleus.UpdateNuclei();
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 60a957541c24c57e78018c202ebb1d9b

View File

@ -6,11 +6,11 @@ public interface INucleus : IReceptor {
#region static struct
// Cluster
public Cluster cluster { get; }
public ClusterPrefab cluster { get; }
// Senders
public List<Synapse> synapses { get; }
public Synapse AddSynapse(IReceptor sender, string nucleusName = null);
public Synapse AddSynapse(IReceptor sender);
public NucleusArray array { get; set; }
@ -19,6 +19,7 @@ public interface INucleus : IReceptor {
#region dynamic state
public void UpdateState();
public void UpdateState(float3 inputValue);
#endregion dynamic state
@ -47,6 +48,7 @@ public interface IReceptor {
#endregion dynamic
//public IReceptor CloneTo(ClusterPrefab parent);
public IReceptor Clone();
}

View File

@ -12,123 +12,19 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
m_Name: Identity
m_EditorClassIdentifier: Assembly-CSharp::Cluster
asset: {fileID: 0}
nuclei:
- rid: 2243601242842202241
- rid: 2243601383627161705
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
- rid: 2243601242842202241
- rid: 2243601383627161705
type: {class: Neuron, ns: , asm: Assembly-CSharp}
data:
_name: Output
_synapses:
- basicNucleus:
rid: 2243601249170358348
cluster:
rid: -2
weight: 1
curveMax: 1
_receivers: []
_array:
rid: 2243601242842202242
_curvePreset: 0
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 1
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1000
value: 1000
inSlope: 1
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
curveMax: 1
average: 0
- rid: 2243601242842202242
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
data:
_nuclei:
- rid: 2243601242842202241
name: Output
- rid: 2243601249170358348
type: {class: Neuron, ns: , asm: Assembly-CSharp}
data:
_name: New neuron
_synapses: []
_receivers:
- rid: 2243601249170358349
_array:
rid: 2243601249170358350
_curvePreset: 0
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 1
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1000
value: 1000
inSlope: 1
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
curveMax: 1
average: 0
- rid: 2243601249170358349
type: {class: ClusterInstance, ns: , asm: Assembly-CSharp}
data:
asset: {fileID: 11400000}
_receivers:
- rid: 2243601249170358351
- rid: 2243601249170358350
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
data:
_nuclei:
- rid: 2243601249170358348
name: New neuron
- rid: 2243601249170358351
type: {class: Neuron, ns: , asm: Assembly-CSharp}
data:
_name: Output
_synapses:
- basicNucleus:
rid: 2243601249170358349
cluster:
rid: -2
weight: 1
curveMax: 1
_receivers: []
_array:
rid: 2243601249170358352
rid: 2243601383627161706
_curvePreset: 0
curve:
serializedVersion: 2
@ -156,9 +52,9 @@ MonoBehaviour:
m_RotationOrder: 4
curveMax: 1
average: 0
- rid: 2243601249170358352
- rid: 2243601383627161706
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
data:
_nuclei:
- rid: 2243601249170358351
- rid: 2243601383627161705
name: Output

View File

@ -6,7 +6,7 @@ using static Unity.Mathematics.math;
[Serializable]
public class MemoryCell : Neuron {
public MemoryCell(Cluster cluster, string name) : base(cluster, name) {}
public MemoryCell(ClusterPrefab cluster, string name) : base(cluster, name) {}
#region Parameters

View File

@ -87,7 +87,7 @@ public class Neuron : INucleus {
#region Runtime state (not serialized)
public Cluster cluster { get; set; }
public ClusterPrefab cluster { get; set; }
#region Activation
@ -165,20 +165,40 @@ public class Neuron : INucleus {
#endregion Runtime state
public Neuron(Cluster brain, string name) {
this.cluster = brain;
public Neuron(ClusterPrefab parent, string name) {
this.cluster = parent;
this.name = name;
if (this.cluster != null) {
this.cluster.nuclei.Add(this);
}
else
Debug.LogError("No neuroid network");
// else
// Debug.LogError("No neuroid network");
}
// public Neuron(string name) {
// this._name = name;
// }
public virtual IReceptor CloneTo(ClusterPrefab parent) {
Neuron clone = new(parent, this.name) {
array = this.array,
curve = this.curve,
curvePreset = this.curvePreset,
curveMax = this.curveMax,
average = this.average
};
// if (clone.cluster != null)
// clone.cluster.nuclei.Add(clone);
foreach (Synapse synapse in this.synapses) {
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
clonedSynapse.weight = synapse.weight;
}
foreach (INucleus receiver in this.receivers) {
clone.AddReceiver(receiver);
}
return clone;
}
public virtual IReceptor Clone() {
Neuron clone = new(this.cluster, this.name) {
array = this.array,
@ -187,8 +207,8 @@ public class Neuron : INucleus {
curveMax = this.curveMax,
average = this.average
};
if (clone.cluster != null)
clone.cluster.nuclei.Add(clone);
// if (clone.cluster != null)
// clone.cluster.nuclei.Add(clone);
foreach (Synapse synapse in this.synapses) {
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
@ -234,14 +254,18 @@ public class Neuron : INucleus {
}
}
public Synapse AddSynapse(IReceptor sendingNucleus, string nucleusName = null) {
public Synapse AddSynapse(IReceptor sendingNucleus) {
Synapse synapse = new(sendingNucleus);
this.synapses.Add(synapse);
return synapse;
}
public virtual void UpdateState() {
float3 sum = new(0, 0, 0);
UpdateState(new float3(0, 0, 0));
}
public virtual void UpdateState(float3 inputValue) {
float3 sum = inputValue;//new(0, 0, 0);
int n = 0;
//Applying the weight factgors
@ -255,7 +279,7 @@ public class Neuron : INucleus {
if (lengthsq(synapse.nucleus.outputValue) != 0)
n++;
}
if (this.average)
if (this.average && n > 0)
sum /= n;
// Activation function

View File

@ -6,7 +6,7 @@ using UnityEngine;
public class NucleusArray {
[SerializeReference]
private INucleus[] _nuclei;
private Cluster[] _clusters;
private ClusterPrefab[] _clusters;
public IEnumerable<INucleus> nuclei {
get {
// if (_nuclei == null)
@ -23,12 +23,12 @@ public class NucleusArray {
this.name = nucleus.name;
this._nuclei = new INucleus[1];
this._nuclei[0] = nucleus;
this._clusters = new Cluster[0];
this._clusters = new ClusterPrefab[0];
}
public NucleusArray(Cluster cluster) {
public NucleusArray(ClusterPrefab cluster) {
this.name = cluster.name;
this._nuclei = new INucleus[0];
this._clusters = new Cluster[1];
this._clusters = new ClusterPrefab[1];
this._clusters[0] = cluster;
}

View File

@ -5,7 +5,7 @@ using static Unity.Mathematics.math;
public class Receptor : IReceptor {
private Cluster cluster;
private ClusterPrefab cluster;
[SerializeField]
protected string _name;
@ -14,20 +14,20 @@ public class Receptor : IReceptor {
set => _name = value;
}
public Receptor(Cluster cluster) {
public Receptor(ClusterPrefab cluster) {
this.cluster = cluster;
if (cluster != null)
cluster.nuclei.Add(this);
}
public Receptor(Cluster cluster, INucleus nucleus) {
public Receptor(ClusterPrefab cluster, INucleus nucleus) {
this.cluster = cluster;
if (cluster != null)
cluster.nuclei.Add(this);
this.AddReceiver(nucleus);
}
public static Receptor CreateReceptor(Cluster cluster, string nucleusName) {
public static Receptor CreateReceptor(ClusterPrefab cluster, string nucleusName) {
if (cluster == null)
return null;
@ -45,6 +45,15 @@ public class Receptor : IReceptor {
return receptor;
}
public virtual IReceptor CloneTo(ClusterPrefab parent) {
Receptor clone = new(parent);
foreach (INucleus receiver in this.receivers) {
clone.AddReceiver(receiver);
}
return clone;
}
public virtual IReceptor Clone() {
Receptor clone = new(this.cluster);

View File

@ -4,18 +4,19 @@ using UnityEngine;
[Serializable]
public class Synapse {
// Support access to cluster of basic nucleus
public IReceptor nucleus => basicNucleus;
//public IReceptor nucleus => basicNucleus;
//[SerializeReference]
//public Cluster cluster;
[SerializeReference]
private IReceptor basicNucleus;
[SerializeReference]
public ClusterInstance cluster;
public IReceptor nucleus;
public float weight;
public Synapse(IReceptor nucleus, float weight = 1.0f) {
this.basicNucleus = nucleus;
this.nucleus = nucleus;
this.weight = weight;
}
}

View File

@ -12,50 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
m_Name: Velocity
m_EditorClassIdentifier: Assembly-CSharp::Cluster
asset: {fileID: 0}
nuclei:
- rid: 2243601362379866169
nuclei: []
references:
version: 2
RefIds:
- rid: 2243601362379866169
type: {class: Neuron, ns: , asm: Assembly-CSharp}
data:
_name: Output
_synapses: []
_receivers: []
_array:
rid: 2243601362379866170
_curvePreset: 0
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 1
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1000
value: 1000
inSlope: 1
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
curveMax: 1
average: 0
- rid: 2243601362379866170
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
data:
_nuclei:
- rid: 2243601362379866169
name: Output
RefIds: []

View File

@ -5,11 +5,11 @@ using System.Linq;
public class BrainPickerWindow : EditorWindow {
private Vector2 scroll;
private Cluster[] items = new Cluster[0];
private Action<Cluster> onPicked;
private ClusterPrefab[] items = new ClusterPrefab[0];
private Action<ClusterPrefab> onPicked;
private string search = "";
public static void ShowPicker(Action<Cluster> onPicked, string title = "Select Cluster") {
public static void ShowPicker(Action<ClusterPrefab> onPicked, string title = "Select Cluster") {
var w = CreateInstance<BrainPickerWindow>();
w.titleContent = new GUIContent(title);
w.minSize = new Vector2(360, 320);
@ -23,7 +23,7 @@ public class BrainPickerWindow : EditorWindow {
private void RefreshList() {
var guids = AssetDatabase.FindAssets("t:Cluster");
items = guids
.Select(g => AssetDatabase.LoadAssetAtPath<Cluster>(AssetDatabase.GUIDToAssetPath(g)))
.Select(g => AssetDatabase.LoadAssetAtPath<ClusterPrefab>(AssetDatabase.GUIDToAssetPath(g)))
.Where(b => b != null)
.OrderBy(b => b.name)
.ToArray();
@ -47,7 +47,7 @@ public class BrainPickerWindow : EditorWindow {
continue;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(EditorGUIUtility.ObjectContent(it, typeof(Cluster)), GUILayout.Height(20));
EditorGUILayout.LabelField(EditorGUIUtility.ObjectContent(it, typeof(ClusterPrefab)), GUILayout.Height(20));
if (GUILayout.Button("Select", GUILayout.Width(70))) {
onPicked?.Invoke(it);
Close();

View File

@ -7,7 +7,7 @@ using UnityEngine.UIElements;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[CustomEditor(typeof(Cluster))]
[CustomEditor(typeof(ClusterPrefab))]
public class ClusterInspector : Editor {
protected static VisualElement mainContainer;
protected static VisualElement inspectorContainer;
@ -17,7 +17,7 @@ public class ClusterInspector : Editor {
#region Start
public override VisualElement CreateInspectorGUI() {
Cluster cluster = target as Cluster;
ClusterPrefab cluster = target as ClusterPrefab;
serializedObject.Update();
@ -72,7 +72,7 @@ public class ClusterInspector : Editor {
}
public class GraphView : VisualElement {
Cluster cluster;
ClusterPrefab cluster;
SerializedObject serializedBrain;
INucleus currentNucleus;
GameObject gameObject;
@ -123,7 +123,7 @@ public class ClusterInspector : Editor {
subscribed = false;
}
public void SetGraph(GameObject gameObject, Cluster brain, INucleus nucleus, VisualElement inspectorContainer) {
public void SetGraph(GameObject gameObject, ClusterPrefab brain, INucleus nucleus, VisualElement inspectorContainer) {
this.gameObject = gameObject;
this.cluster = brain;
if (Application.isPlaying == false)
@ -410,7 +410,7 @@ public class ClusterInspector : Editor {
Handles.Label(labelPos, nucleus.name, style);
}
if (nucleus is ClusterInstance cluster) {
if (nucleus is Cluster cluster) {
Handles.color = Color.white;
Handles.DrawWireDisc(position, Vector3.forward, size + 10);
}
@ -529,7 +529,7 @@ public class ClusterInspector : Editor {
if (synapse.nucleus != null) {
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping);
//EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping);
if (Application.isPlaying)
EditorGUILayout.FloatField(synapse.nucleus.name, length(synapse.nucleus.outputValue) * synapse.weight);
else {
@ -543,7 +543,7 @@ public class ClusterInspector : Editor {
EditorGUI.indentLevel++;
synapse.weight = EditorGUILayout.FloatField("Weight", synapse.weight);
EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup();
//EditorGUI.EndDisabledGroup();
}
}
}
@ -563,7 +563,7 @@ public class ClusterInspector : Editor {
if (GUILayout.Button("Delete this neuron"))
DeleteNeuron(this.currentNucleus);
if (this.currentNucleus is ClusterInstance subCluster) {
if (this.currentNucleus is Cluster subCluster) {
if (GUILayout.Button("Edit Cluster"))
EditCluster(subCluster);
}
@ -588,7 +588,7 @@ public class ClusterInspector : Editor {
}
protected virtual void AddInputNeuron(INucleus nucleus) {
Neuron newNeuroid = new(this.cluster.cluster, "New neuron");
Neuron newNeuroid = new(this.cluster, "New neuron");
newNeuroid.AddReceiver(nucleus);
this.currentNucleus = newNeuroid;
BuildLayers();
@ -610,7 +610,7 @@ public class ClusterInspector : Editor {
}
protected virtual void AddInputMemoryCell(INucleus nucleus) {
MemoryCell newMemory = new(this.cluster.cluster, "New memory cell");
MemoryCell newMemory = new(this.cluster, "New memory cell");
newMemory.AddReceiver(nucleus);
this.currentNucleus = newMemory;
BuildLayers();
@ -620,22 +620,23 @@ public class ClusterInspector : Editor {
BrainPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
}
private void OnClusterPicked(INucleus nucleus, Cluster subCluster) {
ClusterInstance clusterInstance = new(subCluster);
this.cluster.AddSubCluster(clusterInstance);
clusterInstance.AddReceiver(nucleus);
private void OnClusterPicked(INucleus nucleus, ClusterPrefab subCluster) {
Cluster subclusterInstance = new(this.cluster, subCluster);
//this.cluster.AddSubCluster(subclusterInstance);
//this.cluster.nuclei.Add(subclusterInstance);
subclusterInstance.AddReceiver(nucleus);
}
private void EditCluster(ClusterInstance subCluster) {
private void EditCluster(Cluster subCluster) {
//var currentActiveObject = Selection.activeObject;
Selection.activeObject = subCluster.asset;
EditorGUIUtility.PingObject(subCluster.asset);
var editor = Editor.CreateEditor(subCluster.asset);
Selection.activeObject = subCluster.prefab;
EditorGUIUtility.PingObject(subCluster.prefab);
var editor = Editor.CreateEditor(subCluster.prefab);
//Selection.activeObject = currentActiveObject;
}
// Connect to another nucleus in the same cluster
protected virtual void ConnectNucleus(Cluster cluster, INucleus nucleus) {
protected virtual void ConnectNucleus(ClusterPrefab cluster, INucleus nucleus) {
if (cluster == null)
return;
@ -705,9 +706,9 @@ public class ClusterWrapper : ScriptableObject {
//public string title;
public Vector2 position;
INucleus node;
Cluster graph; // needed to write back and mark dirty
ClusterPrefab graph; // needed to write back and mark dirty
public ClusterWrapper Init(INucleus node, Cluster graphAsset) {
public ClusterWrapper Init(INucleus node, ClusterPrefab graphAsset) {
this.node = node;
this.graph = graphAsset;
//this.title = " A " + node.name;

View File

@ -23,7 +23,7 @@ public class NanoBrainComponent_Editor : Editor {
public override VisualElement CreateInspectorGUI() {
//NanoBrainComponent component = target as NanoBrainComponent;
Cluster brain = Application.isPlaying ? component.brain : component.defaultBrain;
ClusterPrefab brain = Application.isPlaying ? component.brain : component.defaultBrain;
if (Application.isPlaying == false)
serializedObject.Update();

View File

@ -1,11 +1,11 @@
using UnityEngine;
public class NanoBrainComponent : MonoBehaviour {
public Cluster defaultBrain;
private Cluster brainInstance;
public ClusterPrefab defaultBrain;
private ClusterPrefab brainInstance;
public INucleus root => brainInstance.output;
public Cluster brain {
public ClusterPrefab brain {
get {
if (brainInstance == null && defaultBrain != null) {
brainInstance = Instantiate(defaultBrain);
@ -23,7 +23,7 @@ public class NanoBrainComponent : MonoBehaviour {
}
}
public static void UpdateWeight(Cluster brain, string name, float weight) {
public static void UpdateWeight(ClusterPrefab brain, string name, float weight) {
INucleus root = brain.output;
foreach (Synapse synapse in root.synapses) {
if (synapse.nucleus.name == name) {

View File

@ -12,50 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
m_Name: New Cluster
m_EditorClassIdentifier: Assembly-CSharp::Cluster
asset: {fileID: 0}
nuclei:
- rid: 2243601249170358341
nuclei: []
references:
version: 2
RefIds:
- rid: 2243601249170358341
type: {class: Neuron, ns: , asm: Assembly-CSharp}
data:
_name: Output
_synapses: []
_receivers: []
_array:
rid: 2243601249170358342
_curvePreset: 0
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 1
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1000
value: 1000
inSlope: 1
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
curveMax: 1
average: 0
- rid: 2243601249170358342
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
data:
_nuclei:
- rid: 2243601249170358341
name: Output
RefIds: []

View File

@ -10,9 +10,9 @@ public class SwarmControl_Editor : Editor {
if (EditorGUI.EndChangeCheck()) {
SwarmControl swarmControl = (SwarmControl)target;
Cluster[] nanoBrains = FindObjectsByType<Cluster>(FindObjectsSortMode.None);
ClusterPrefab[] nanoBrains = FindObjectsByType<ClusterPrefab>(FindObjectsSortMode.None);
foreach (Cluster brain in nanoBrains) {
foreach (ClusterPrefab brain in nanoBrains) {
NanoBrainComponent.UpdateWeight(brain, "Avoidance", swarmControl.avoidanceForce);
NanoBrainComponent.UpdateWeight(brain, "Cohesion", swarmControl.cohesionForce);
NanoBrainComponent.UpdateWeight(brain, "Separation", swarmControl.separationForce);