Compare commits
No commits in common. "91c4500b0a1288dc674dc4a89b675b344aa861e6" and "a64ff841ac0dde229f22b4228f8cf479fea3ebff" have entirely different histories.
91c4500b0a
...
a64ff841ac
344
Cluster.cs
344
Cluster.cs
@ -4,9 +4,12 @@ using UnityEngine;
|
|||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using static Unity.Mathematics.math;
|
using static Unity.Mathematics.math;
|
||||||
|
|
||||||
[Serializable]
|
[System.Serializable]
|
||||||
public class Cluster : INucleus {
|
public class Cluster : INucleus {
|
||||||
// The ScriptableObject asset from which the runtime object has been created
|
// The ScriptableObject asset from which the runtime object has been created
|
||||||
|
public readonly ClusterPrefab prefab;
|
||||||
|
|
||||||
|
public ClusterPrefab cluster { get; set; }
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
protected string _name;
|
protected string _name;
|
||||||
@ -15,113 +18,17 @@ public class Cluster : INucleus {
|
|||||||
set => _name = value;
|
set => _name = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Init
|
// Hmm, a cluster instance can never be part of a scriptable object...(Cluster)
|
||||||
|
public Cluster(ClusterPrefab parent, ClusterPrefab prefab) {
|
||||||
public Cluster(ClusterPrefab prefab, Cluster parent) {
|
|
||||||
this.prefab = prefab;
|
this.prefab = prefab;
|
||||||
this.name = prefab.name;
|
|
||||||
|
|
||||||
this.parent = parent;
|
|
||||||
this.parent?.nuclei.Add(this);
|
|
||||||
|
|
||||||
ClonePrefab();
|
|
||||||
this.sortedNuclei = TopologicalSort(this.nuclei);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cluster(ClusterPrefab prefab, ClusterPrefab parent = null) {
|
|
||||||
this.prefab = prefab;
|
|
||||||
this.name = prefab.name;
|
|
||||||
this.cluster = parent;
|
this.cluster = parent;
|
||||||
|
|
||||||
if (this.cluster != null)
|
if (this.cluster != null)
|
||||||
this.cluster.nuclei.Add(this);
|
this.cluster.nuclei.Add(this);
|
||||||
|
|
||||||
ClonePrefab();
|
// foreach (IReceptor nucleus in this.prefab.nuclei) {
|
||||||
this.sortedNuclei = TopologicalSort(this.nuclei);
|
// IReceptor clone = nucleus.CloneTo(null);
|
||||||
}
|
// this.dynamicNuclei.Add(clone);
|
||||||
|
// }
|
||||||
// public Cluster(ClusterPrefab parent, ClusterPrefab realPrefab) {
|
|
||||||
// this.prefab = realPrefab;
|
|
||||||
// this.name = realPrefab.name;
|
|
||||||
// this.cluster = parent;
|
|
||||||
// if (this.cluster != null)
|
|
||||||
// this.cluster.nuclei.Add(this);
|
|
||||||
|
|
||||||
// ClonePrefab();
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void ClonePrefab() {
|
|
||||||
IReceptor[] nucleiArray = this.prefab.nuclei.ToArray();
|
|
||||||
// first clone the nuclei without their connections
|
|
||||||
foreach (IReceptor nucleus in this.prefab.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 clonedSender = clonedNuclei[nucleusIx];
|
|
||||||
if (clonedSender == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Copy the receivers, which will also create the synapses
|
|
||||||
foreach (INucleus receiver in receptor.receivers) {
|
|
||||||
int ix = GetNucleusIndex(nucleiArray, receiver);
|
|
||||||
if (ix < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (clonedNuclei[ix] is not INucleus clonedReceiver)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Find the synapse for the weight
|
|
||||||
float weight = 1;
|
|
||||||
foreach (Synapse synapse in receiver.synapses) {
|
|
||||||
if (synapse.nucleus == receptor) {
|
|
||||||
weight = synapse.weight;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clonedSender.AddReceiver(clonedReceiver, weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the nuclei in a correct evaluation order
|
|
||||||
private List<IReceptor> TopologicalSort(List<IReceptor> nodes) {
|
|
||||||
Dictionary<IReceptor, int> inDegree = new();
|
|
||||||
foreach (IReceptor node in nodes)
|
|
||||||
inDegree[node] = 0; // Initialize in-degree to zero
|
|
||||||
|
|
||||||
// Calculate in-degrees
|
|
||||||
foreach (IReceptor node in nodes) {
|
|
||||||
foreach (INucleus receiver in node.receivers)
|
|
||||||
inDegree[receiver]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Queue<IReceptor> queue = new();
|
|
||||||
foreach (IReceptor node in nodes) {
|
|
||||||
if (inDegree[node] == 0) // Nodes with no dependencies
|
|
||||||
queue.Enqueue(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IReceptor> sortedOrder = new();
|
|
||||||
while (queue.Count > 0) {
|
|
||||||
IReceptor current = queue.Dequeue();
|
|
||||||
sortedOrder.Add(current); // Process the node
|
|
||||||
|
|
||||||
foreach (INucleus receiver in current.receivers) {
|
|
||||||
inDegree[receiver]--;
|
|
||||||
if (inDegree[receiver] == 0) // If all dependencies resolved
|
|
||||||
queue.Enqueue(receiver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for cycles in the graph
|
|
||||||
if (sortedOrder.Count != nodes.Count)
|
|
||||||
throw new InvalidOperationException("Graph is not a DAG; a cycle exists.");
|
|
||||||
|
|
||||||
return sortedOrder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IReceptor Clone() {
|
public virtual IReceptor Clone() {
|
||||||
@ -139,59 +46,6 @@ public class Cluster : INucleus {
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReceptor ShallowCloneTo(Cluster parent) {
|
|
||||||
Cluster clone = new(this.prefab, parent) {
|
|
||||||
name = this.name,
|
|
||||||
};
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetNucleusIndex(IReceptor[] nucleiArray, IReceptor nucleus) {
|
|
||||||
for (int i = 0; i < nucleiArray.Length; i++) {
|
|
||||||
if (nucleus == nucleiArray[i])
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Init
|
|
||||||
|
|
||||||
public ClusterPrefab prefab;
|
|
||||||
|
|
||||||
public ClusterPrefab cluster { get; set; }
|
|
||||||
public Cluster parent { get; set; }
|
|
||||||
|
|
||||||
[SerializeReference]
|
|
||||||
public List<IReceptor> nuclei = new();
|
|
||||||
// the nuclei sorted using topological sorting
|
|
||||||
// to ensure that the cluster is computer in the right order
|
|
||||||
public List<IReceptor> sortedNuclei;
|
|
||||||
|
|
||||||
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) {
|
|
||||||
// inputs have no incoming synapses yet.
|
|
||||||
if (nucleus.synapses.Count == 0)
|
|
||||||
this._inputs.Add(nucleus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._inputs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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...
|
// Not sure if this belongs here...
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
private NucleusArray _array;
|
private NucleusArray _array;
|
||||||
@ -202,14 +56,27 @@ public class Cluster : INucleus {
|
|||||||
|
|
||||||
#region Synapses
|
#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]
|
[SerializeField]
|
||||||
private List<Synapse> _synapses = new();
|
private List<Synapse> _synapses = new();
|
||||||
public List<Synapse> synapses => _synapses;
|
public List<Synapse> synapses => _synapses;
|
||||||
|
|
||||||
public Synapse AddSynapse(IReceptor sendingNucleus, float weight = 1.0f) {
|
public Synapse AddSynapse(IReceptor sendingNucleus) {
|
||||||
Synapse synapse = new(sendingNucleus, weight);
|
Synapse synapse = new(sendingNucleus); //, this.prefab.inputs[0]);
|
||||||
this._synapses.Add(synapse);
|
this._synapses.Add(synapse);
|
||||||
return 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?
|
// Does this even exist already?
|
||||||
@ -228,9 +95,9 @@ public class Cluster : INucleus {
|
|||||||
set { _receivers = value; }
|
set { _receivers = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddReceiver(INucleus receivingNucleus, float weight = 1) {
|
public virtual void AddReceiver(INucleus receivingNucleus) {
|
||||||
this._receivers.Add(receivingNucleus);
|
this._receivers.Add(receivingNucleus);
|
||||||
receivingNucleus.AddSynapse(this, weight);
|
receivingNucleus.AddSynapse(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveReceiver(INucleus receiverNucleus) {
|
public void RemoveReceiver(INucleus receiverNucleus) {
|
||||||
@ -238,6 +105,48 @@ public class Cluster : INucleus {
|
|||||||
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
|
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
|
#endregion Receivers
|
||||||
|
|
||||||
#region Runtime
|
#region Runtime
|
||||||
@ -262,68 +171,89 @@ public class Cluster : INucleus {
|
|||||||
UpdateState(new float3(0, 0, 0));
|
UpdateState(new float3(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateState(float3 bias) {
|
public void UpdateState(float3 inputValue) {
|
||||||
float3 sum = bias; // new(0, 0, 0);
|
float3 sum = inputValue; // new(0, 0, 0);
|
||||||
|
|
||||||
//Applying the weight factors
|
//Applying the weight factgors
|
||||||
foreach (Synapse synapse in this.synapses) {
|
foreach (Synapse synapse in this.synapses) {
|
||||||
sum += synapse.weight * synapse.nucleus.outputValue;
|
sum += synapse.weight * synapse.nucleus.outputValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.inputs[0].UpdateState(sum);
|
// This does not work because the prefab nucleus does not have a state
|
||||||
this.inputs[0].UpdateStateIsolated(sum);
|
this.prefab.inputs[0].UpdateState(sum);
|
||||||
foreach (IReceptor receptor in this.sortedNuclei) {
|
|
||||||
if (receptor is INucleus nucleus && nucleus != this.inputs[0])
|
|
||||||
nucleus.UpdateStateIsolated();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateResult(this.output.outputValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateStateIsolated() {
|
|
||||||
float3 bias = new(0,0,0);
|
|
||||||
UpdateStateIsolated(bias);
|
|
||||||
}
|
|
||||||
public void UpdateStateIsolated(float3 bias) {
|
|
||||||
float3 sum = bias; // new(0, 0, 0);
|
|
||||||
|
|
||||||
//Applying the weight factors
|
|
||||||
foreach (Synapse synapse in this.synapses) {
|
|
||||||
sum += synapse.weight * synapse.nucleus.outputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//this.inputs[0].UpdateState(sum);
|
|
||||||
this.inputs[0].UpdateStateIsolated(sum);
|
|
||||||
foreach (IReceptor receptor in this.sortedNuclei) {
|
|
||||||
if (receptor is INucleus nucleus && nucleus != this.inputs[0])
|
|
||||||
nucleus.UpdateStateIsolated();
|
|
||||||
}
|
|
||||||
this.outputValue = this.output.outputValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void UpdateResult(Vector3 result) {
|
|
||||||
// float d = Vector3.Distance(result, this.outputValue);
|
|
||||||
// if (d < 0.5f) {
|
|
||||||
// //Debug.Log($"insignificant update: {d}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.outputValue = result;
|
|
||||||
foreach (INucleus receiver in this.receivers)
|
|
||||||
receiver.UpdateState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateNuclei() {
|
public void UpdateNuclei() {
|
||||||
this.stale++;
|
this.stale++;
|
||||||
if (this.stale > 2)
|
if (this.stale > 2)
|
||||||
_outputValue = Vector3.zero;
|
_outputValue = Vector3.zero;
|
||||||
|
|
||||||
//foreach (IReceptor nucleus in this.prefab.nuclei)
|
foreach (IReceptor nucleus in this.prefab.nuclei)
|
||||||
foreach (IReceptor nucleus in this.nuclei)
|
|
||||||
nucleus.UpdateNuclei();
|
nucleus.UpdateNuclei();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Update
|
#endregion Update
|
||||||
|
|
||||||
#endregion Runtime
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,11 +4,18 @@ using UnityEngine;
|
|||||||
[CreateAssetMenu(menuName = "Passer/Cluster")]
|
[CreateAssetMenu(menuName = "Passer/Cluster")]
|
||||||
public class ClusterPrefab : ScriptableObject {
|
public class ClusterPrefab : ScriptableObject {
|
||||||
|
|
||||||
|
//public virtual Cluster cluster {get;set;}
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
public List<IReceptor> nuclei = new();
|
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 virtual INucleus output => this.nuclei[0] as INucleus;
|
||||||
|
|
||||||
@ -18,11 +25,8 @@ public class ClusterPrefab : ScriptableObject {
|
|||||||
if (this._inputs == null) {
|
if (this._inputs == null) {
|
||||||
this._inputs = new();
|
this._inputs = new();
|
||||||
foreach (IReceptor receptor in this.nuclei) {
|
foreach (IReceptor receptor in this.nuclei) {
|
||||||
if (receptor is INucleus nucleus) {
|
if (receptor is INucleus nucleus)
|
||||||
// inputs have no incoming synapses yet.
|
this._inputs.Add(nucleus);
|
||||||
if (nucleus.synapses.Count == 0)
|
|
||||||
this._inputs.Add(nucleus);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this._inputs;
|
return this._inputs;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ public interface INucleus : IReceptor {
|
|||||||
|
|
||||||
// Senders
|
// Senders
|
||||||
public List<Synapse> synapses { get; }
|
public List<Synapse> synapses { get; }
|
||||||
public Synapse AddSynapse(IReceptor sender, float weight = 1.0f);
|
public Synapse AddSynapse(IReceptor sender);
|
||||||
|
|
||||||
public NucleusArray array { get; set; }
|
public NucleusArray array { get; set; }
|
||||||
|
|
||||||
@ -20,8 +20,7 @@ public interface INucleus : IReceptor {
|
|||||||
|
|
||||||
public void UpdateState();
|
public void UpdateState();
|
||||||
public void UpdateState(float3 inputValue);
|
public void UpdateState(float3 inputValue);
|
||||||
public void UpdateStateIsolated();
|
|
||||||
public void UpdateStateIsolated(float3 inputValue);
|
|
||||||
|
|
||||||
#endregion dynamic state
|
#endregion dynamic state
|
||||||
}
|
}
|
||||||
@ -34,7 +33,7 @@ public interface IReceptor {
|
|||||||
// Receivers
|
// Receivers
|
||||||
public List<INucleus> receivers { get; set; }
|
public List<INucleus> receivers { get; set; }
|
||||||
|
|
||||||
public void AddReceiver(INucleus receiver, float weight = 1);
|
public void AddReceiver(INucleus receiver);
|
||||||
public void RemoveReceiver(INucleus receiverNucleus);
|
public void RemoveReceiver(INucleus receiverNucleus);
|
||||||
|
|
||||||
#endregion static
|
#endregion static
|
||||||
@ -49,7 +48,7 @@ public interface IReceptor {
|
|||||||
|
|
||||||
#endregion dynamic
|
#endregion dynamic
|
||||||
|
|
||||||
public IReceptor ShallowCloneTo(Cluster parent);
|
//public IReceptor CloneTo(ClusterPrefab parent);
|
||||||
public IReceptor Clone();
|
public IReceptor Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,38 +4,35 @@ using Unity.Mathematics;
|
|||||||
using static Unity.Mathematics.math;
|
using static Unity.Mathematics.math;
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class MemoryCell : Neuron, INucleus {
|
public class MemoryCell : Neuron {
|
||||||
|
|
||||||
public MemoryCell(ClusterPrefab cluster, string name) : base(cluster, name) { }
|
public MemoryCell(ClusterPrefab cluster, string name) : base(cluster, name) {}
|
||||||
public MemoryCell(Cluster parent, string name) : base(parent, name) { }
|
|
||||||
// this.parent = parent;
|
|
||||||
// this.name = name;
|
|
||||||
// this.parent?.nuclei.Add(this);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public override IReceptor ShallowCloneTo(Cluster newParent) {
|
#region Parameters
|
||||||
MemoryCell clone = new(newParent, this.name) {
|
|
||||||
array = this.array,
|
// Returns the memorized value weighted by time
|
||||||
curve = this.curve,
|
// return lastValue * (current time - last time)
|
||||||
curvePreset = this.curvePreset,
|
[SerializeField]
|
||||||
curveMax = this.curveMax,
|
public bool deltaValue = false;
|
||||||
average = this.average
|
|
||||||
};
|
#endregion Parameters
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region State
|
#region State
|
||||||
|
|
||||||
private float3 _memorizedValue;
|
private float3 _memorizedValue;
|
||||||
private float _memorizedTime;
|
private float _memorizedTime;
|
||||||
|
|
||||||
public override void UpdateState(float3 bias) {
|
public override void UpdateState() {
|
||||||
// A memorycell does not have an activation function
|
// A memorycell does not have an activation function
|
||||||
float3 result = bias;
|
float3 result = new(0, 0, 0);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
//Applying the weight factgors
|
//Applying the weight factgors
|
||||||
foreach (Synapse synapse in this.synapses) {
|
foreach (Synapse synapse in this.synapses) {
|
||||||
|
if (synapse.nucleus == this) {
|
||||||
|
float deltaTime = Time.time - this.lastTime;
|
||||||
|
synapse.weight = deltaTime;
|
||||||
|
}
|
||||||
result += synapse.weight * synapse.nucleus.outputValue;
|
result += synapse.weight * synapse.nucleus.outputValue;
|
||||||
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
||||||
n++;
|
n++;
|
||||||
@ -47,40 +44,14 @@ public class MemoryCell : Neuron, INucleus {
|
|||||||
UpdateResult(result);
|
UpdateResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateStateIsolated() {
|
|
||||||
float3 bias = new(0, 0, 0);
|
|
||||||
UpdateStateIsolated(bias);
|
|
||||||
}
|
|
||||||
public override void UpdateStateIsolated(float3 bias) {
|
|
||||||
// A memorycell does not have an activation function
|
|
||||||
float3 result = bias;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
//Applying the weight factgors
|
|
||||||
foreach (Synapse synapse in this.synapses) {
|
|
||||||
result += synapse.weight * synapse.nucleus.outputValue;
|
|
||||||
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.average)
|
|
||||||
result /= n;
|
|
||||||
|
|
||||||
this.outputValue = this._memorizedValue;
|
|
||||||
|
|
||||||
// Store the result for the next time
|
|
||||||
this._memorizedValue = result;
|
|
||||||
this._memorizedTime = Time.time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void UpdateResult(Vector3 result) {
|
public override void UpdateResult(Vector3 result) {
|
||||||
// output value is the previous value
|
// output value is the previous value
|
||||||
// if (this.deltaValue) {
|
if (this.deltaValue) {
|
||||||
// float deltaTime = Time.time - this._memorizedTime;
|
float deltaTime = Time.time - this._memorizedTime;
|
||||||
// this._outputValue = this._memorizedValue * deltaTime;
|
this._outputValue = this._memorizedValue * deltaTime;
|
||||||
// }
|
}
|
||||||
//else
|
else
|
||||||
this.outputValue = this._memorizedValue;
|
this._outputValue = this._memorizedValue;
|
||||||
|
|
||||||
// Store the result for the next time
|
// Store the result for the next time
|
||||||
this._memorizedValue = result;
|
this._memorizedValue = result;
|
||||||
|
|||||||
99
Neuron.cs
99
Neuron.cs
@ -88,7 +88,6 @@ public class Neuron : INucleus {
|
|||||||
#region Runtime state (not serialized)
|
#region Runtime state (not serialized)
|
||||||
|
|
||||||
public ClusterPrefab cluster { get; set; }
|
public ClusterPrefab cluster { get; set; }
|
||||||
public Cluster parent { get; set; }
|
|
||||||
|
|
||||||
#region Activation
|
#region Activation
|
||||||
|
|
||||||
@ -154,22 +153,18 @@ public class Neuron : INucleus {
|
|||||||
// private bool _isSleeping = false;
|
// private bool _isSleeping = false;
|
||||||
// public bool isSleeping => _isSleeping;
|
// public bool isSleeping => _isSleeping;
|
||||||
public bool isSleeping => lengthsq(this.outputValue) == 0;
|
public bool isSleeping => lengthsq(this.outputValue) == 0;
|
||||||
|
public float lastTime { get; private set; }
|
||||||
|
|
||||||
public void UpdateNuclei() {
|
public void UpdateNuclei() {
|
||||||
this.stale++;
|
this.stale++;
|
||||||
// this._isSleeping = this.stale > 2;
|
// this._isSleeping = this.stale > 2;
|
||||||
// if (isSleeping)
|
// if (isSleeping)
|
||||||
if (this.stale > 2)
|
if (this.stale > 2)
|
||||||
_outputValue = Vector3.zero;
|
_outputValue = Vector3.zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Runtime state
|
#endregion Runtime state
|
||||||
|
|
||||||
public Neuron(Cluster parent, string name) {
|
|
||||||
this.parent = parent;
|
|
||||||
this.name = name;
|
|
||||||
this.parent?.nuclei.Add(this);
|
|
||||||
}
|
|
||||||
public Neuron(ClusterPrefab parent, string name) {
|
public Neuron(ClusterPrefab parent, string name) {
|
||||||
this.cluster = parent;
|
this.cluster = parent;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -180,27 +175,9 @@ public class Neuron : INucleus {
|
|||||||
// Debug.LogError("No neuroid network");
|
// Debug.LogError("No neuroid network");
|
||||||
}
|
}
|
||||||
|
|
||||||
// this clone the nucleus without the synapses and receivers
|
// public Neuron(string name) {
|
||||||
public virtual IReceptor ShallowCloneTo(Cluster newParent) {
|
// this._name = name;
|
||||||
Neuron clone = new(newParent, this.name) {
|
// }
|
||||||
array = this.array,
|
|
||||||
curve = this.curve,
|
|
||||||
curvePreset = this.curvePreset,
|
|
||||||
curveMax = this.curveMax,
|
|
||||||
average = this.average
|
|
||||||
};
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
public virtual IReceptor ShallowCloneTo(ClusterPrefab newParent) {
|
|
||||||
Neuron clone = new(newParent, this.name) {
|
|
||||||
array = this.array,
|
|
||||||
curve = this.curve,
|
|
||||||
curvePreset = this.curvePreset,
|
|
||||||
curveMax = this.curveMax,
|
|
||||||
average = this.average
|
|
||||||
};
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IReceptor CloneTo(ClusterPrefab parent) {
|
public virtual IReceptor CloneTo(ClusterPrefab parent) {
|
||||||
Neuron clone = new(parent, this.name) {
|
Neuron clone = new(parent, this.name) {
|
||||||
@ -210,6 +187,8 @@ public class Neuron : INucleus {
|
|||||||
curveMax = this.curveMax,
|
curveMax = this.curveMax,
|
||||||
average = this.average
|
average = this.average
|
||||||
};
|
};
|
||||||
|
// if (clone.cluster != null)
|
||||||
|
// 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);
|
||||||
@ -241,9 +220,9 @@ public class Neuron : INucleus {
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddReceiver(INucleus receivingNucleus, float weight = 1) {
|
public virtual void AddReceiver(INucleus receivingNucleus) {
|
||||||
this._receivers.Add(receivingNucleus);
|
this._receivers.Add(receivingNucleus);
|
||||||
receivingNucleus.AddSynapse(this, weight);
|
receivingNucleus.AddSynapse(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveReceiver(INucleus receiverNucleus) {
|
public void RemoveReceiver(INucleus receiverNucleus) {
|
||||||
@ -275,25 +254,27 @@ public class Neuron : INucleus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Synapse AddSynapse(IReceptor sendingNucleus, float weight = 1.0f) {
|
public Synapse AddSynapse(IReceptor sendingNucleus) {
|
||||||
Synapse synapse = new(sendingNucleus, weight);
|
Synapse synapse = new(sendingNucleus);
|
||||||
this.synapses.Add(synapse);
|
this.synapses.Add(synapse);
|
||||||
return synapse;
|
return synapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateState() {
|
public virtual void UpdateState() {
|
||||||
//UpdateState(new float3(0, 0, 0));
|
UpdateState(new float3(0, 0, 0));
|
||||||
this.parent?.UpdateState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateState(float3 inputValue) {
|
public virtual void UpdateState(float3 inputValue) {
|
||||||
float3 sum = inputValue;
|
float3 sum = inputValue;//new(0, 0, 0);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
//Applying the weight factgors
|
//Applying the weight factgors
|
||||||
foreach (Synapse synapse in this.synapses) {
|
foreach (Synapse synapse in this.synapses) {
|
||||||
|
if (synapse.nucleus == this) {
|
||||||
|
float deltaTime = Time.time - this.lastTime;
|
||||||
|
synapse.weight = deltaTime;
|
||||||
|
}
|
||||||
sum += synapse.weight * synapse.nucleus.outputValue;
|
sum += synapse.weight * synapse.nucleus.outputValue;
|
||||||
|
|
||||||
// Perhaps synapses should be removed when the output value goes to 0....
|
// Perhaps synapses should be removed when the output value goes to 0....
|
||||||
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
||||||
n++;
|
n++;
|
||||||
@ -324,47 +305,6 @@ public class Neuron : INucleus {
|
|||||||
UpdateResult(result);
|
UpdateResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateStateIsolated() {
|
|
||||||
UpdateStateIsolated(new float3(0, 0, 0));
|
|
||||||
}
|
|
||||||
public virtual void UpdateStateIsolated(float3 bias) {
|
|
||||||
float3 sum = bias;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
//Applying the weight factgors
|
|
||||||
foreach (Synapse synapse in this.synapses) {
|
|
||||||
sum += synapse.weight * synapse.nucleus.outputValue;
|
|
||||||
|
|
||||||
// Perhaps synapses should be removed when the output value goes to 0....
|
|
||||||
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
if (this.average && n > 0)
|
|
||||||
sum /= n;
|
|
||||||
|
|
||||||
// Activation function
|
|
||||||
Vector3 result;
|
|
||||||
switch (this.curvePreset) {
|
|
||||||
case CurvePresets.Linear:
|
|
||||||
result = sum;
|
|
||||||
break;
|
|
||||||
case CurvePresets.Sqrt:
|
|
||||||
result = normalize(sum) * System.MathF.Sqrt(length(sum));
|
|
||||||
break;
|
|
||||||
case CurvePresets.Power:
|
|
||||||
result = normalize(sum) * System.MathF.Pow(length(sum), 2);
|
|
||||||
break;
|
|
||||||
case CurvePresets.Reciprocal:
|
|
||||||
result = normalize(sum) * (1 / length(sum));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
float activatedValue = this.curve.Evaluate(length(sum));
|
|
||||||
result = normalize(sum) * activatedValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.outputValue = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void UpdateResult(Vector3 result) {
|
public virtual void UpdateResult(Vector3 result) {
|
||||||
// float d = Vector3.Distance(result, this.outputValue);
|
// float d = Vector3.Distance(result, this.outputValue);
|
||||||
// if (d < 0.5f) {
|
// if (d < 0.5f) {
|
||||||
@ -373,10 +313,7 @@ public class Neuron : INucleus {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
this.outputValue = result;
|
this.outputValue = result;
|
||||||
if (lengthsq(outputValue) != 0) {
|
this.lastTime = Time.time;
|
||||||
Debug.Log($"{this.parent.name}.{this.name}: {this.outputValue}");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (INucleus receiver in this.receivers)
|
foreach (INucleus receiver in this.receivers)
|
||||||
receiver.UpdateState();
|
receiver.UpdateState();
|
||||||
|
|
||||||
|
|||||||
26
Receptor.cs
26
Receptor.cs
@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
@ -7,7 +6,6 @@ using static Unity.Mathematics.math;
|
|||||||
public class Receptor : IReceptor {
|
public class Receptor : IReceptor {
|
||||||
|
|
||||||
private ClusterPrefab cluster;
|
private ClusterPrefab cluster;
|
||||||
private Cluster parent;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
protected string _name;
|
protected string _name;
|
||||||
@ -16,11 +14,6 @@ public class Receptor : IReceptor {
|
|||||||
set => _name = value;
|
set => _name = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Receptor(Cluster parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
if (parent != null)
|
|
||||||
parent.nuclei.Add(this);
|
|
||||||
}
|
|
||||||
public Receptor(ClusterPrefab cluster) {
|
public Receptor(ClusterPrefab cluster) {
|
||||||
this.cluster = cluster;
|
this.cluster = cluster;
|
||||||
if (cluster != null)
|
if (cluster != null)
|
||||||
@ -34,13 +27,15 @@ public class Receptor : IReceptor {
|
|||||||
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;
|
||||||
|
|
||||||
Receptor receptor = new(cluster);
|
Receptor receptor = new(cluster);
|
||||||
foreach (INucleus nucleus in cluster.inputs) {
|
foreach (INucleus nucleus in cluster.inputs) {
|
||||||
if (nucleus != null && nucleus.name == nucleusName) {
|
if (nucleus != null && nucleus.name == nucleusName) {
|
||||||
|
// Receptor receptor = new(cluster, nucleus);
|
||||||
|
// return receptor;
|
||||||
receptor.AddReceiver(nucleus);
|
receptor.AddReceiver(nucleus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,15 +45,6 @@ public class Receptor : IReceptor {
|
|||||||
return receptor;
|
return receptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IReceptor ShallowCloneTo(Cluster parent) {
|
|
||||||
Receptor clone = new(parent);
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
public virtual IReceptor ShallowCloneTo(ClusterPrefab parent) {
|
|
||||||
Receptor clone = new(parent);
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IReceptor CloneTo(ClusterPrefab parent) {
|
public virtual IReceptor CloneTo(ClusterPrefab parent) {
|
||||||
Receptor clone = new(parent);
|
Receptor clone = new(parent);
|
||||||
|
|
||||||
@ -98,9 +84,9 @@ public class Receptor : IReceptor {
|
|||||||
|
|
||||||
protected int[] thingIds; // every receiver can handle a thing with this id
|
protected int[] thingIds; // every receiver can handle a thing with this id
|
||||||
|
|
||||||
public virtual void AddReceiver(INucleus receivingNucleus, float weight = 1) {
|
public virtual void AddReceiver(INucleus receivingNucleus) {
|
||||||
this._receivers.Add(receivingNucleus);
|
this._receivers.Add(receivingNucleus);
|
||||||
receivingNucleus.AddSynapse(this, weight);
|
receivingNucleus.AddSynapse(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveReceiver(INucleus receiverNucleus) {
|
public void RemoveReceiver(INucleus receiverNucleus) {
|
||||||
@ -136,8 +122,6 @@ public class Receptor : IReceptor {
|
|||||||
|
|
||||||
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) {
|
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector, string thingName = null) {
|
||||||
this.localPosition = newLocalPositionVector;
|
this.localPosition = newLocalPositionVector;
|
||||||
if (this._receivers == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
thingIds ??= new int[this._receivers.Count];
|
thingIds ??= new int[this._receivers.Count];
|
||||||
|
|
||||||
|
|||||||
@ -11,20 +11,26 @@ MonoBehaviour:
|
|||||||
m_EditorHideFlags: 0
|
m_EditorHideFlags: 0
|
||||||
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::ClusterPrefab
|
m_EditorClassIdentifier: Assembly-CSharp::Cluster
|
||||||
nuclei:
|
nuclei:
|
||||||
- rid: 2243601425629446539
|
- rid: 2243601403683012671
|
||||||
|
- rid: 2243601403683012676
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
- rid: 2243601425629446539
|
- rid: -2
|
||||||
|
type: {class: , ns: , asm: }
|
||||||
|
- rid: 2243601403683012671
|
||||||
type: {class: Neuron, ns: , asm: Assembly-CSharp}
|
type: {class: Neuron, ns: , asm: Assembly-CSharp}
|
||||||
data:
|
data:
|
||||||
_name: Output
|
_name: Output
|
||||||
_synapses: []
|
_synapses:
|
||||||
|
- nucleus:
|
||||||
|
rid: -2
|
||||||
|
weight: 1
|
||||||
_receivers: []
|
_receivers: []
|
||||||
_array:
|
_array:
|
||||||
rid: 2243601425629446540
|
rid: 2243601403683012672
|
||||||
_curvePreset: 0
|
_curvePreset: 0
|
||||||
curve:
|
curve:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@ -52,9 +58,51 @@ MonoBehaviour:
|
|||||||
m_RotationOrder: 4
|
m_RotationOrder: 4
|
||||||
curveMax: 1
|
curveMax: 1
|
||||||
average: 0
|
average: 0
|
||||||
- rid: 2243601425629446540
|
- rid: 2243601403683012672
|
||||||
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
|
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
|
||||||
data:
|
data:
|
||||||
_nuclei:
|
_nuclei:
|
||||||
- rid: 2243601425629446539
|
- rid: 2243601403683012671
|
||||||
name: Output
|
name: Output
|
||||||
|
- rid: 2243601403683012676
|
||||||
|
type: {class: Neuron, ns: , asm: Assembly-CSharp}
|
||||||
|
data:
|
||||||
|
_name: Position
|
||||||
|
_synapses: []
|
||||||
|
_receivers:
|
||||||
|
- rid: 2243601403683012671
|
||||||
|
_array:
|
||||||
|
rid: 2243601403683012677
|
||||||
|
_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: 2243601403683012677
|
||||||
|
type: {class: NucleusArray, ns: , asm: Assembly-CSharp}
|
||||||
|
data:
|
||||||
|
_nuclei:
|
||||||
|
- rid: 2243601403683012676
|
||||||
|
name: New neuron
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: c61aecac62c26de4aaefb2612bcc9a5d
|
guid: dd622ac7ed09e70ea8edac595047ac82
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
mainObjectFileID: 11400000
|
||||||
|
|||||||
@ -3,14 +3,14 @@ using UnityEngine;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
public class ClusterPickerWindow : EditorWindow {
|
public class BrainPickerWindow : EditorWindow {
|
||||||
private Vector2 scroll;
|
private Vector2 scroll;
|
||||||
private ClusterPrefab[] items = new ClusterPrefab[0];
|
private ClusterPrefab[] items = new ClusterPrefab[0];
|
||||||
private Action<ClusterPrefab> onPicked;
|
private Action<ClusterPrefab> onPicked;
|
||||||
private string search = "";
|
private string search = "";
|
||||||
|
|
||||||
public static void ShowPicker(Action<ClusterPrefab> onPicked, string title = "Select Cluster") {
|
public static void ShowPicker(Action<ClusterPrefab> onPicked, string title = "Select Cluster") {
|
||||||
var w = CreateInstance<ClusterPickerWindow>();
|
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);
|
||||||
w.onPicked = onPicked;
|
w.onPicked = onPicked;
|
||||||
@ -21,7 +21,7 @@ public class ClusterPickerWindow : EditorWindow {
|
|||||||
private void OnEnable() => RefreshList();
|
private void OnEnable() => RefreshList();
|
||||||
|
|
||||||
private void RefreshList() {
|
private void RefreshList() {
|
||||||
var guids = AssetDatabase.FindAssets("t:ClusterPrefab");
|
var guids = AssetDatabase.FindAssets("t:Cluster");
|
||||||
items = guids
|
items = guids
|
||||||
.Select(g => AssetDatabase.LoadAssetAtPath<ClusterPrefab>(AssetDatabase.GUIDToAssetPath(g)))
|
.Select(g => AssetDatabase.LoadAssetAtPath<ClusterPrefab>(AssetDatabase.GUIDToAssetPath(g)))
|
||||||
.Where(b => b != null)
|
.Where(b => b != null)
|
||||||
|
|||||||
@ -617,22 +617,22 @@ public class ClusterInspector : Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddCluster(INucleus nucleus) {
|
protected virtual void AddCluster(INucleus nucleus) {
|
||||||
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
BrainPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClusterPicked(INucleus nucleus, ClusterPrefab prefab) {
|
private void OnClusterPicked(INucleus nucleus, ClusterPrefab subCluster) {
|
||||||
Cluster subclusterInstance = new(prefab, this.cluster);
|
Cluster subclusterInstance = new(this.cluster, subCluster);
|
||||||
|
//this.cluster.AddSubCluster(subclusterInstance);
|
||||||
|
//this.cluster.nuclei.Add(subclusterInstance);
|
||||||
subclusterInstance.AddReceiver(nucleus);
|
subclusterInstance.AddReceiver(nucleus);
|
||||||
// This does not work somehow
|
|
||||||
// this.currentNucleus = subclusterInstance;
|
|
||||||
// BuildLayers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EditCluster(Cluster subCluster) {
|
private void EditCluster(Cluster subCluster) {
|
||||||
// May be used with storedPrefab...
|
//var currentActiveObject = Selection.activeObject;
|
||||||
Selection.activeObject = subCluster.prefab;
|
Selection.activeObject = subCluster.prefab;
|
||||||
EditorGUIUtility.PingObject(subCluster.prefab);
|
EditorGUIUtility.PingObject(subCluster.prefab);
|
||||||
var editor = Editor.CreateEditor(subCluster.prefab);
|
var editor = Editor.CreateEditor(subCluster.prefab);
|
||||||
|
//Selection.activeObject = currentActiveObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to another nucleus in the same cluster
|
// Connect to another nucleus in the same cluster
|
||||||
|
|||||||
@ -22,8 +22,8 @@ public class NanoBrainComponent_Editor : Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override VisualElement CreateInspectorGUI() {
|
public override VisualElement CreateInspectorGUI() {
|
||||||
//ClusterPrefab brain = Application.isPlaying ? component.brain.prefab : component.defaultBrain;
|
//NanoBrainComponent component = target as NanoBrainComponent;
|
||||||
Cluster brain = component.brain;
|
ClusterPrefab brain = Application.isPlaying ? component.brain : component.defaultBrain;
|
||||||
|
|
||||||
if (Application.isPlaying == false)
|
if (Application.isPlaying == false)
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
@ -79,7 +79,7 @@ public class NanoBrainComponent_Editor : Editor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (brain != null && board != null)
|
if (brain != null && board != null)
|
||||||
board.SetGraph(component.gameObject, brain.prefab, brain.output, inspectorContainer);
|
board.SetGraph(component.gameObject, brain, brain.output, inspectorContainer);
|
||||||
// else
|
// else
|
||||||
// Debug.LogWarning(" No brain!");
|
// Debug.LogWarning(" No brain!");
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class NanoBrainComponent : MonoBehaviour {
|
public class NanoBrainComponent : MonoBehaviour {
|
||||||
public ClusterPrefab defaultBrain;
|
public ClusterPrefab defaultBrain;
|
||||||
|
private ClusterPrefab brainInstance;
|
||||||
|
|
||||||
[NonSerialized]
|
public INucleus root => brainInstance.output;
|
||||||
private Cluster brainInstance;
|
public ClusterPrefab brain {
|
||||||
public Cluster brain {
|
|
||||||
get {
|
get {
|
||||||
if (brainInstance == null && defaultBrain != null) {
|
if (brainInstance == null && defaultBrain != null) {
|
||||||
brainInstance = new Cluster(defaultBrain); //Instantiate(defaultBrain);
|
brainInstance = Instantiate(defaultBrain);
|
||||||
brainInstance.name = defaultBrain.name + " (Instance)";
|
brainInstance.name = defaultBrain.name + " (Instance)";
|
||||||
|
|
||||||
SwarmControl sc = FindFirstObjectByType<SwarmControl>();
|
SwarmControl sc = FindFirstObjectByType<SwarmControl>();
|
||||||
@ -24,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) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user