Move to ClusterPfab
This commit is contained in:
parent
96ed53312d
commit
33f5af32d1
@ -73,7 +73,6 @@
|
|||||||
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector2Int.cs" />
|
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/Vector2Int.cs" />
|
||||||
<Compile Include="Assets/Scenes/Boids/Scripts/SwarmControl.cs" />
|
<Compile Include="Assets/Scenes/Boids/Scripts/SwarmControl.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/INucleus.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/src/Spherical.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector3FloatTest.cs" />
|
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector3FloatTest.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/MemoryCell.cs" />
|
<Compile Include="Assets/NanoBrain/MemoryCell.cs" />
|
||||||
@ -81,6 +80,7 @@
|
|||||||
<Compile Include="Assets/Scenes/Boids/Scripts/Boid.cs" />
|
<Compile Include="Assets/Scenes/Boids/Scripts/Boid.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/SwingTwist.cs" />
|
<Compile Include="Assets/NanoBrain/LinearAlgebra/src/SwingTwist.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/SphericalTest.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/Cluster.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/Synapse.cs" />
|
<Compile Include="Assets/NanoBrain/Synapse.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector3IntTest.cs" />
|
<Compile Include="Assets/NanoBrain/LinearAlgebra/test/Vector3IntTest.cs" />
|
||||||
|
|||||||
@ -1,84 +1,259 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
using static Unity.Mathematics.math;
|
||||||
|
|
||||||
[CreateAssetMenu(menuName = "Passer/Cluster")]
|
[System.Serializable]
|
||||||
public class Cluster : ScriptableObject {
|
public class Cluster : INucleus {
|
||||||
|
|
||||||
public Cluster cluster => this;
|
|
||||||
|
|
||||||
// The ScriptableObject asset from which the runtime object has been created
|
// 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]
|
[SerializeReference]
|
||||||
public List<IReceptor> nuclei = new();
|
private List<INucleus> _receivers = new();
|
||||||
|
public List<INucleus> receivers {
|
||||||
// public List<Cluster> subClusters = new();
|
get { return _receivers; }
|
||||||
public void AddSubCluster(ClusterInstance subCluster) {
|
set { _receivers = value; }
|
||||||
this.nuclei.Add(subCluster);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 void RemoveReceiver(INucleus receiverNucleus) {
|
||||||
public List<INucleus> inputs {
|
this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
|
||||||
get {
|
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
|
||||||
if (this._inputs == null) {
|
}
|
||||||
this._inputs = new();
|
|
||||||
foreach (IReceptor receptor in this.nuclei) {
|
// public void AddReceiver(INucleus receivingNucleus) {
|
||||||
if (receptor is INucleus nucleus)
|
// int newLength = this._receivers.Count + 1;
|
||||||
this._inputs.Add(nucleus);
|
// INucleus[] newReceivers = new INucleus[newLength];
|
||||||
}
|
|
||||||
}
|
// // Copy the existing receivers
|
||||||
return this._inputs;
|
// 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
|
#region Update
|
||||||
// This is an invariant and should be ensured before the nucleus is used
|
|
||||||
// because output requires it.
|
public virtual void UpdateState() {
|
||||||
public void EnsureInitialization() {
|
UpdateState(new float3(0, 0, 0));
|
||||||
nuclei ??= new List<IReceptor>();
|
|
||||||
if (nuclei.Count == 0)
|
|
||||||
new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GarbageCollection() {
|
public void UpdateState(float3 inputValue) {
|
||||||
HashSet<INucleus> visitedNuclei = new();
|
float3 sum = inputValue; // new(0, 0, 0);
|
||||||
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) {
|
//Applying the weight factgors
|
||||||
if (nucleus is null)
|
foreach (Synapse synapse in this.synapses) {
|
||||||
return;
|
sum += synapse.weight * synapse.nucleus.outputValue;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This does not work because the prefab nucleus does not have a state
|
||||||
|
this.prefab.inputs[0].UpdateState(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateNuclei() {
|
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();
|
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
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 60a957541c24c57e78018c202ebb1d9b
|
guid: f13cdc4a175a9f379a00317ae68d8bea
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f13cdc4a175a9f379a00317ae68d8bea
|
|
||||||
84
Assets/NanoBrain/ClusterPrefab.cs
Normal file
84
Assets/NanoBrain/ClusterPrefab.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/NanoBrain/ClusterPrefab.cs.meta
Normal file
2
Assets/NanoBrain/ClusterPrefab.cs.meta
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 60a957541c24c57e78018c202ebb1d9b
|
||||||
@ -6,11 +6,11 @@ public interface INucleus : IReceptor {
|
|||||||
#region static struct
|
#region static struct
|
||||||
|
|
||||||
// Cluster
|
// Cluster
|
||||||
public Cluster cluster { get; }
|
public ClusterPrefab cluster { get; }
|
||||||
|
|
||||||
// Senders
|
// Senders
|
||||||
public List<Synapse> synapses { get; }
|
public List<Synapse> synapses { get; }
|
||||||
public Synapse AddSynapse(IReceptor sender, string nucleusName = null);
|
public Synapse AddSynapse(IReceptor sender);
|
||||||
|
|
||||||
public NucleusArray array { get; set; }
|
public NucleusArray array { get; set; }
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ public interface INucleus : IReceptor {
|
|||||||
#region dynamic state
|
#region dynamic state
|
||||||
|
|
||||||
public void UpdateState();
|
public void UpdateState();
|
||||||
|
public void UpdateState(float3 inputValue);
|
||||||
|
|
||||||
|
|
||||||
#endregion dynamic state
|
#endregion dynamic state
|
||||||
@ -47,6 +48,7 @@ public interface IReceptor {
|
|||||||
|
|
||||||
#endregion dynamic
|
#endregion dynamic
|
||||||
|
|
||||||
|
//public IReceptor CloneTo(ClusterPrefab parent);
|
||||||
public IReceptor Clone();
|
public IReceptor Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,123 +12,19 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
|
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
|
||||||
m_Name: Identity
|
m_Name: Identity
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
||||||
asset: {fileID: 0}
|
|
||||||
nuclei:
|
nuclei:
|
||||||
- rid: 2243601242842202241
|
- rid: 2243601383627161705
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
- rid: -2
|
- rid: 2243601383627161705
|
||||||
type: {class: , ns: , asm: }
|
|
||||||
- rid: 2243601242842202241
|
|
||||||
type: {class: Neuron, ns: , asm: Assembly-CSharp}
|
type: {class: Neuron, ns: , asm: Assembly-CSharp}
|
||||||
data:
|
data:
|
||||||
_name: Output
|
_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: []
|
_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: []
|
_receivers: []
|
||||||
_array:
|
_array:
|
||||||
rid: 2243601249170358352
|
rid: 2243601383627161706
|
||||||
_curvePreset: 0
|
_curvePreset: 0
|
||||||
curve:
|
curve:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@ -156,9 +52,9 @@ MonoBehaviour:
|
|||||||
m_RotationOrder: 4
|
m_RotationOrder: 4
|
||||||
curveMax: 1
|
curveMax: 1
|
||||||
average: 0
|
average: 0
|
||||||
- rid: 2243601249170358352
|
- rid: 2243601383627161706
|
||||||
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
|
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
|
||||||
data:
|
data:
|
||||||
_nuclei:
|
_nuclei:
|
||||||
- rid: 2243601249170358351
|
- rid: 2243601383627161705
|
||||||
name: Output
|
name: Output
|
||||||
|
|||||||
@ -6,7 +6,7 @@ using static Unity.Mathematics.math;
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class MemoryCell : Neuron {
|
public class MemoryCell : Neuron {
|
||||||
|
|
||||||
public MemoryCell(Cluster cluster, string name) : base(cluster, name) {}
|
public MemoryCell(ClusterPrefab cluster, string name) : base(cluster, name) {}
|
||||||
|
|
||||||
#region Parameters
|
#region Parameters
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ public class Neuron : INucleus {
|
|||||||
|
|
||||||
#region Runtime state (not serialized)
|
#region Runtime state (not serialized)
|
||||||
|
|
||||||
public Cluster cluster { get; set; }
|
public ClusterPrefab cluster { get; set; }
|
||||||
|
|
||||||
#region Activation
|
#region Activation
|
||||||
|
|
||||||
@ -165,20 +165,40 @@ public class Neuron : INucleus {
|
|||||||
|
|
||||||
#endregion Runtime state
|
#endregion Runtime state
|
||||||
|
|
||||||
public Neuron(Cluster brain, string name) {
|
public Neuron(ClusterPrefab parent, string name) {
|
||||||
this.cluster = brain;
|
this.cluster = parent;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
if (this.cluster != null) {
|
if (this.cluster != null) {
|
||||||
this.cluster.nuclei.Add(this);
|
this.cluster.nuclei.Add(this);
|
||||||
}
|
}
|
||||||
else
|
// else
|
||||||
Debug.LogError("No neuroid network");
|
// Debug.LogError("No neuroid network");
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Neuron(string name) {
|
// public Neuron(string name) {
|
||||||
// this._name = 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() {
|
public virtual IReceptor Clone() {
|
||||||
Neuron clone = new(this.cluster, this.name) {
|
Neuron clone = new(this.cluster, this.name) {
|
||||||
array = this.array,
|
array = this.array,
|
||||||
@ -187,8 +207,8 @@ public class Neuron : INucleus {
|
|||||||
curveMax = this.curveMax,
|
curveMax = this.curveMax,
|
||||||
average = this.average
|
average = this.average
|
||||||
};
|
};
|
||||||
if (clone.cluster != null)
|
// if (clone.cluster != null)
|
||||||
clone.cluster.nuclei.Add(clone);
|
// clone.cluster.nuclei.Add(clone);
|
||||||
|
|
||||||
foreach (Synapse synapse in this.synapses) {
|
foreach (Synapse synapse in this.synapses) {
|
||||||
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
|
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);
|
Synapse synapse = new(sendingNucleus);
|
||||||
this.synapses.Add(synapse);
|
this.synapses.Add(synapse);
|
||||||
return synapse;
|
return synapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateState() {
|
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;
|
int n = 0;
|
||||||
|
|
||||||
//Applying the weight factgors
|
//Applying the weight factgors
|
||||||
@ -255,7 +279,7 @@ public class Neuron : INucleus {
|
|||||||
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
if (this.average)
|
if (this.average && n > 0)
|
||||||
sum /= n;
|
sum /= n;
|
||||||
|
|
||||||
// Activation function
|
// Activation function
|
||||||
|
|||||||
@ -6,7 +6,7 @@ using UnityEngine;
|
|||||||
public class NucleusArray {
|
public class NucleusArray {
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
private INucleus[] _nuclei;
|
private INucleus[] _nuclei;
|
||||||
private Cluster[] _clusters;
|
private ClusterPrefab[] _clusters;
|
||||||
public IEnumerable<INucleus> nuclei {
|
public IEnumerable<INucleus> nuclei {
|
||||||
get {
|
get {
|
||||||
// if (_nuclei == null)
|
// if (_nuclei == null)
|
||||||
@ -23,12 +23,12 @@ public class NucleusArray {
|
|||||||
this.name = nucleus.name;
|
this.name = nucleus.name;
|
||||||
this._nuclei = new INucleus[1];
|
this._nuclei = new INucleus[1];
|
||||||
this._nuclei[0] = nucleus;
|
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.name = cluster.name;
|
||||||
this._nuclei = new INucleus[0];
|
this._nuclei = new INucleus[0];
|
||||||
this._clusters = new Cluster[1];
|
this._clusters = new ClusterPrefab[1];
|
||||||
this._clusters[0] = cluster;
|
this._clusters[0] = cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using static Unity.Mathematics.math;
|
|||||||
|
|
||||||
public class Receptor : IReceptor {
|
public class Receptor : IReceptor {
|
||||||
|
|
||||||
private Cluster cluster;
|
private ClusterPrefab cluster;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
protected string _name;
|
protected string _name;
|
||||||
@ -14,20 +14,20 @@ public class Receptor : IReceptor {
|
|||||||
set => _name = value;
|
set => _name = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Receptor(Cluster cluster) {
|
public Receptor(ClusterPrefab cluster) {
|
||||||
this.cluster = cluster;
|
this.cluster = cluster;
|
||||||
if (cluster != null)
|
if (cluster != null)
|
||||||
cluster.nuclei.Add(this);
|
cluster.nuclei.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Receptor(Cluster cluster, INucleus nucleus) {
|
public Receptor(ClusterPrefab cluster, INucleus nucleus) {
|
||||||
this.cluster = cluster;
|
this.cluster = cluster;
|
||||||
if (cluster != null)
|
if (cluster != null)
|
||||||
cluster.nuclei.Add(this);
|
cluster.nuclei.Add(this);
|
||||||
this.AddReceiver(nucleus);
|
this.AddReceiver(nucleus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Receptor CreateReceptor(Cluster cluster, string nucleusName) {
|
public static Receptor CreateReceptor(ClusterPrefab cluster, string nucleusName) {
|
||||||
if (cluster == null)
|
if (cluster == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -45,6 +45,15 @@ public class Receptor : IReceptor {
|
|||||||
return receptor;
|
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() {
|
public virtual IReceptor Clone() {
|
||||||
Receptor clone = new(this.cluster);
|
Receptor clone = new(this.cluster);
|
||||||
|
|
||||||
|
|||||||
@ -4,18 +4,19 @@ using UnityEngine;
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class Synapse {
|
public class Synapse {
|
||||||
// Support access to cluster of basic nucleus
|
// Support access to cluster of basic nucleus
|
||||||
public IReceptor nucleus => basicNucleus;
|
//public IReceptor nucleus => basicNucleus;
|
||||||
|
|
||||||
|
|
||||||
|
//[SerializeReference]
|
||||||
|
//public Cluster cluster;
|
||||||
|
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
private IReceptor basicNucleus;
|
public IReceptor nucleus;
|
||||||
|
|
||||||
[SerializeReference]
|
|
||||||
public ClusterInstance cluster;
|
|
||||||
|
|
||||||
public float weight;
|
public float weight;
|
||||||
|
|
||||||
public Synapse(IReceptor nucleus, float weight = 1.0f) {
|
public Synapse(IReceptor nucleus, float weight = 1.0f) {
|
||||||
this.basicNucleus = nucleus;
|
this.nucleus = nucleus;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,50 +12,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
|
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
|
||||||
m_Name: Velocity
|
m_Name: Velocity
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
||||||
asset: {fileID: 0}
|
nuclei: []
|
||||||
nuclei:
|
|
||||||
- rid: 2243601362379866169
|
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
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
|
|
||||||
|
|||||||
@ -5,11 +5,11 @@ using System.Linq;
|
|||||||
|
|
||||||
public class BrainPickerWindow : EditorWindow {
|
public class BrainPickerWindow : EditorWindow {
|
||||||
private Vector2 scroll;
|
private Vector2 scroll;
|
||||||
private Cluster[] items = new Cluster[0];
|
private ClusterPrefab[] items = new ClusterPrefab[0];
|
||||||
private Action<Cluster> onPicked;
|
private Action<ClusterPrefab> onPicked;
|
||||||
private string search = "";
|
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>();
|
var w = CreateInstance<BrainPickerWindow>();
|
||||||
w.titleContent = new GUIContent(title);
|
w.titleContent = new GUIContent(title);
|
||||||
w.minSize = new Vector2(360, 320);
|
w.minSize = new Vector2(360, 320);
|
||||||
@ -23,7 +23,7 @@ public class BrainPickerWindow : EditorWindow {
|
|||||||
private void RefreshList() {
|
private void RefreshList() {
|
||||||
var guids = AssetDatabase.FindAssets("t:Cluster");
|
var guids = AssetDatabase.FindAssets("t:Cluster");
|
||||||
items = guids
|
items = guids
|
||||||
.Select(g => AssetDatabase.LoadAssetAtPath<Cluster>(AssetDatabase.GUIDToAssetPath(g)))
|
.Select(g => AssetDatabase.LoadAssetAtPath<ClusterPrefab>(AssetDatabase.GUIDToAssetPath(g)))
|
||||||
.Where(b => b != null)
|
.Where(b => b != null)
|
||||||
.OrderBy(b => b.name)
|
.OrderBy(b => b.name)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -47,7 +47,7 @@ public class BrainPickerWindow : EditorWindow {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
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))) {
|
if (GUILayout.Button("Select", GUILayout.Width(70))) {
|
||||||
onPicked?.Invoke(it);
|
onPicked?.Invoke(it);
|
||||||
Close();
|
Close();
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using UnityEngine.UIElements;
|
|||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using static Unity.Mathematics.math;
|
using static Unity.Mathematics.math;
|
||||||
|
|
||||||
[CustomEditor(typeof(Cluster))]
|
[CustomEditor(typeof(ClusterPrefab))]
|
||||||
public class ClusterInspector : Editor {
|
public class ClusterInspector : Editor {
|
||||||
protected static VisualElement mainContainer;
|
protected static VisualElement mainContainer;
|
||||||
protected static VisualElement inspectorContainer;
|
protected static VisualElement inspectorContainer;
|
||||||
@ -17,7 +17,7 @@ public class ClusterInspector : Editor {
|
|||||||
#region Start
|
#region Start
|
||||||
|
|
||||||
public override VisualElement CreateInspectorGUI() {
|
public override VisualElement CreateInspectorGUI() {
|
||||||
Cluster cluster = target as Cluster;
|
ClusterPrefab cluster = target as ClusterPrefab;
|
||||||
|
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ public class ClusterInspector : Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class GraphView : VisualElement {
|
public class GraphView : VisualElement {
|
||||||
Cluster cluster;
|
ClusterPrefab cluster;
|
||||||
SerializedObject serializedBrain;
|
SerializedObject serializedBrain;
|
||||||
INucleus currentNucleus;
|
INucleus currentNucleus;
|
||||||
GameObject gameObject;
|
GameObject gameObject;
|
||||||
@ -123,7 +123,7 @@ public class ClusterInspector : Editor {
|
|||||||
subscribed = false;
|
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.gameObject = gameObject;
|
||||||
this.cluster = brain;
|
this.cluster = brain;
|
||||||
if (Application.isPlaying == false)
|
if (Application.isPlaying == false)
|
||||||
@ -410,7 +410,7 @@ public class ClusterInspector : Editor {
|
|||||||
Handles.Label(labelPos, nucleus.name, style);
|
Handles.Label(labelPos, nucleus.name, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nucleus is ClusterInstance cluster) {
|
if (nucleus is Cluster cluster) {
|
||||||
Handles.color = Color.white;
|
Handles.color = Color.white;
|
||||||
Handles.DrawWireDisc(position, Vector3.forward, size + 10);
|
Handles.DrawWireDisc(position, Vector3.forward, size + 10);
|
||||||
}
|
}
|
||||||
@ -529,7 +529,7 @@ public class ClusterInspector : Editor {
|
|||||||
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, length(synapse.nucleus.outputValue) * synapse.weight);
|
EditorGUILayout.FloatField(synapse.nucleus.name, length(synapse.nucleus.outputValue) * synapse.weight);
|
||||||
else {
|
else {
|
||||||
@ -543,7 +543,7 @@ public class ClusterInspector : Editor {
|
|||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
synapse.weight = EditorGUILayout.FloatField("Weight", synapse.weight);
|
synapse.weight = EditorGUILayout.FloatField("Weight", synapse.weight);
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
EditorGUI.EndDisabledGroup();
|
//EditorGUI.EndDisabledGroup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -563,7 +563,7 @@ public class ClusterInspector : Editor {
|
|||||||
if (GUILayout.Button("Delete this neuron"))
|
if (GUILayout.Button("Delete this neuron"))
|
||||||
DeleteNeuron(this.currentNucleus);
|
DeleteNeuron(this.currentNucleus);
|
||||||
|
|
||||||
if (this.currentNucleus is ClusterInstance subCluster) {
|
if (this.currentNucleus is Cluster subCluster) {
|
||||||
if (GUILayout.Button("Edit Cluster"))
|
if (GUILayout.Button("Edit Cluster"))
|
||||||
EditCluster(subCluster);
|
EditCluster(subCluster);
|
||||||
}
|
}
|
||||||
@ -588,7 +588,7 @@ public class ClusterInspector : Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddInputNeuron(INucleus nucleus) {
|
protected virtual void AddInputNeuron(INucleus nucleus) {
|
||||||
Neuron newNeuroid = new(this.cluster.cluster, "New neuron");
|
Neuron newNeuroid = new(this.cluster, "New neuron");
|
||||||
newNeuroid.AddReceiver(nucleus);
|
newNeuroid.AddReceiver(nucleus);
|
||||||
this.currentNucleus = newNeuroid;
|
this.currentNucleus = newNeuroid;
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
@ -610,7 +610,7 @@ public class ClusterInspector : Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddInputMemoryCell(INucleus nucleus) {
|
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);
|
newMemory.AddReceiver(nucleus);
|
||||||
this.currentNucleus = newMemory;
|
this.currentNucleus = newMemory;
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
@ -620,22 +620,23 @@ public class ClusterInspector : Editor {
|
|||||||
BrainPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
BrainPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClusterPicked(INucleus nucleus, Cluster subCluster) {
|
private void OnClusterPicked(INucleus nucleus, ClusterPrefab subCluster) {
|
||||||
ClusterInstance clusterInstance = new(subCluster);
|
Cluster subclusterInstance = new(this.cluster, subCluster);
|
||||||
this.cluster.AddSubCluster(clusterInstance);
|
//this.cluster.AddSubCluster(subclusterInstance);
|
||||||
clusterInstance.AddReceiver(nucleus);
|
//this.cluster.nuclei.Add(subclusterInstance);
|
||||||
|
subclusterInstance.AddReceiver(nucleus);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EditCluster(ClusterInstance subCluster) {
|
private void EditCluster(Cluster subCluster) {
|
||||||
//var currentActiveObject = Selection.activeObject;
|
//var currentActiveObject = Selection.activeObject;
|
||||||
Selection.activeObject = subCluster.asset;
|
Selection.activeObject = subCluster.prefab;
|
||||||
EditorGUIUtility.PingObject(subCluster.asset);
|
EditorGUIUtility.PingObject(subCluster.prefab);
|
||||||
var editor = Editor.CreateEditor(subCluster.asset);
|
var editor = Editor.CreateEditor(subCluster.prefab);
|
||||||
//Selection.activeObject = currentActiveObject;
|
//Selection.activeObject = currentActiveObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to another nucleus in the same cluster
|
// 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)
|
if (cluster == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -705,9 +706,9 @@ public class ClusterWrapper : ScriptableObject {
|
|||||||
//public string title;
|
//public string title;
|
||||||
public Vector2 position;
|
public Vector2 position;
|
||||||
INucleus node;
|
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.node = node;
|
||||||
this.graph = graphAsset;
|
this.graph = graphAsset;
|
||||||
//this.title = " A " + node.name;
|
//this.title = " A " + node.name;
|
||||||
|
|||||||
@ -23,7 +23,7 @@ public class NanoBrainComponent_Editor : Editor {
|
|||||||
|
|
||||||
public override VisualElement CreateInspectorGUI() {
|
public override VisualElement CreateInspectorGUI() {
|
||||||
//NanoBrainComponent component = target as NanoBrainComponent;
|
//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)
|
if (Application.isPlaying == false)
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class NanoBrainComponent : MonoBehaviour {
|
public class NanoBrainComponent : MonoBehaviour {
|
||||||
public Cluster defaultBrain;
|
public ClusterPrefab defaultBrain;
|
||||||
private Cluster brainInstance;
|
private ClusterPrefab brainInstance;
|
||||||
|
|
||||||
public INucleus root => brainInstance.output;
|
public INucleus root => brainInstance.output;
|
||||||
public Cluster brain {
|
public ClusterPrefab brain {
|
||||||
get {
|
get {
|
||||||
if (brainInstance == null && defaultBrain != null) {
|
if (brainInstance == null && defaultBrain != null) {
|
||||||
brainInstance = Instantiate(defaultBrain);
|
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;
|
INucleus root = brain.output;
|
||||||
foreach (Synapse synapse in root.synapses) {
|
foreach (Synapse synapse in root.synapses) {
|
||||||
if (synapse.nucleus.name == name) {
|
if (synapse.nucleus.name == name) {
|
||||||
|
|||||||
@ -12,50 +12,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
|
m_Script: {fileID: 11500000, guid: 60a957541c24c57e78018c202ebb1d9b, type: 3}
|
||||||
m_Name: New Cluster
|
m_Name: New Cluster
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
||||||
asset: {fileID: 0}
|
nuclei: []
|
||||||
nuclei:
|
|
||||||
- rid: 2243601249170358341
|
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
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
|
|
||||||
|
|||||||
@ -10,9 +10,9 @@ public class SwarmControl_Editor : Editor {
|
|||||||
|
|
||||||
if (EditorGUI.EndChangeCheck()) {
|
if (EditorGUI.EndChangeCheck()) {
|
||||||
SwarmControl swarmControl = (SwarmControl)target;
|
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, "Avoidance", swarmControl.avoidanceForce);
|
||||||
NanoBrainComponent.UpdateWeight(brain, "Cohesion", swarmControl.cohesionForce);
|
NanoBrainComponent.UpdateWeight(brain, "Cohesion", swarmControl.cohesionForce);
|
||||||
NanoBrainComponent.UpdateWeight(brain, "Separation", swarmControl.separationForce);
|
NanoBrainComponent.UpdateWeight(brain, "Separation", swarmControl.separationForce);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user