First steps to using instanceCount for clusters
This commit is contained in:
parent
8801fa2ff2
commit
b6630ad84e
@ -196,13 +196,16 @@ namespace NanoBrain {
|
|||||||
|
|
||||||
if (this.currentNucleus is Cluster cluster) {
|
if (this.currentNucleus is Cluster cluster) {
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1)
|
if (cluster.instanceCount > 1)
|
||||||
|
EditorGUILayout.IntField("Array size", cluster.instanceCount, GUILayout.MinWidth(150));
|
||||||
|
else if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1)
|
||||||
EditorGUILayout.IntField("Array size", cluster.siblingClusters.Count(), GUILayout.MinWidth(150));
|
EditorGUILayout.IntField("Array size", cluster.siblingClusters.Count(), GUILayout.MinWidth(150));
|
||||||
else
|
else
|
||||||
EditorGUILayout.IntField("Array size", 1, GUILayout.MinWidth(150));
|
EditorGUILayout.IntField("Array size", 1, GUILayout.MinWidth(150));
|
||||||
if (GUILayout.Button("Add")) {
|
if (GUILayout.Button("Add")) {
|
||||||
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
|
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
|
||||||
cluster.AddInstance(this.prefab);
|
//cluster.AddInstance(this.prefab);
|
||||||
|
cluster.AddInstance();
|
||||||
anythingChanged = true;
|
anythingChanged = true;
|
||||||
}
|
}
|
||||||
if (GUILayout.Button("Del")) {
|
if (GUILayout.Button("Del")) {
|
||||||
@ -213,8 +216,36 @@ namespace NanoBrain {
|
|||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synapses
|
SynapsesInspector(ref anythingChanged);
|
||||||
|
ActivationInspector(ref anythingChanged);
|
||||||
|
|
||||||
|
if (GUILayout.Button("Delete this neuron"))
|
||||||
|
DeleteNucleus(this.currentNucleus);
|
||||||
|
|
||||||
|
if (this.currentNucleus is Cluster subCluster) {
|
||||||
|
if (GUILayout.Button("Reimport Cluster"))
|
||||||
|
ReimportCluster(subCluster);
|
||||||
|
if (GUILayout.Button("Edit Cluster"))
|
||||||
|
EditCluster(subCluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake);
|
||||||
|
if (breakOnWake && this.currentNucleus is Neuron currentNeuron) {
|
||||||
|
if (currentNeuron.isSleeping == false)
|
||||||
|
Debug.Break();
|
||||||
|
}
|
||||||
|
trace = EditorGUILayout.Toggle("Trace", trace);
|
||||||
|
this.currentNucleus.trace = trace;
|
||||||
|
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
if (anythingChanged) {
|
||||||
|
EditorUtility.SetDirty(prefabAsset);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SynapsesInspector(ref bool anythingChanged) {
|
||||||
showSynapses = EditorGUILayout.BeginFoldoutHeaderGroup(showSynapses, "Synapses");
|
showSynapses = EditorGUILayout.BeginFoldoutHeaderGroup(showSynapses, "Synapses");
|
||||||
if (showSynapses) {
|
if (showSynapses) {
|
||||||
if (this.currentNucleus is Neuron neuron2) {
|
if (this.currentNucleus is Neuron neuron2) {
|
||||||
@ -248,19 +279,17 @@ namespace NanoBrain {
|
|||||||
else
|
else
|
||||||
elementIx = thisElementIx;
|
elementIx = thisElementIx;
|
||||||
}
|
}
|
||||||
// if (array.Contains(synapse.nucleus))
|
if (array.Contains(synapse.neuron))
|
||||||
// continue;
|
continue;
|
||||||
else if (array.Contains(synapse.neuron.parent))
|
else if (array.Contains(synapse.neuron.parent))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if (synapse.neuron.parent is IReceptor iReceptor) {
|
if (synapse.neuron.parent is Cluster iReceptor) {
|
||||||
// array = iReceptor.nucleiArray;
|
array = iReceptor.siblingClusters;
|
||||||
// if (iReceptor is Cluster iCluster)
|
if (iReceptor is Cluster iCluster)
|
||||||
// elementIx = Cluster.GetNucleusIndex(iCluster.clusterNuclei, synapse.neuron);
|
elementIx = Cluster.GetNucleusIndex(iCluster.clusterNuclei, synapse.neuron);
|
||||||
// }
|
}
|
||||||
// else if (synapse.nucleus is Receptor receptor2) // && receptor2.array != null && receptor2.array.nuclei.Length > 1)
|
|
||||||
// array = receptor2.nucleiArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
@ -325,8 +354,9 @@ namespace NanoBrain {
|
|||||||
anythingChanged |= AddSynapse(this.prefab, this.currentNucleus);
|
anythingChanged |= AddSynapse(this.prefab, this.currentNucleus);
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||||
|
}
|
||||||
|
|
||||||
// Activation
|
protected void ActivationInspector(ref bool anythingChanged) {
|
||||||
|
|
||||||
if (this.currentNucleus is not Cluster) {
|
if (this.currentNucleus is not Cluster) {
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
@ -356,30 +386,6 @@ namespace NanoBrain {
|
|||||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GUILayout.Button("Delete this neuron"))
|
|
||||||
DeleteNucleus(this.currentNucleus);
|
|
||||||
|
|
||||||
if (this.currentNucleus is Cluster subCluster) {
|
|
||||||
if (GUILayout.Button("Reimport Cluster"))
|
|
||||||
ReimportCluster(subCluster);
|
|
||||||
if (GUILayout.Button("Edit Cluster"))
|
|
||||||
EditCluster(subCluster);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake);
|
|
||||||
if (breakOnWake && this.currentNucleus is Neuron currentNeuron) {
|
|
||||||
if (currentNeuron.isSleeping == false)
|
|
||||||
Debug.Break();
|
|
||||||
}
|
|
||||||
trace = EditorGUILayout.Toggle("Trace", trace);
|
|
||||||
this.currentNucleus.trace = trace;
|
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
if (anythingChanged) {
|
|
||||||
EditorUtility.SetDirty(prefabAsset);
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Synapses
|
#region Synapses
|
||||||
@ -426,8 +432,8 @@ namespace NanoBrain {
|
|||||||
protected virtual void AddClusterInput(Nucleus nucleus) {
|
protected virtual void AddClusterInput(Nucleus nucleus) {
|
||||||
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
||||||
}
|
}
|
||||||
private void OnClusterPicked(Nucleus nucleus, ClusterPrefab prefab) {
|
private void OnClusterPicked(Nucleus nucleus, ClusterPrefab selectedPrefab) {
|
||||||
Cluster subclusterInstance = new(prefab, this.prefab);
|
Cluster subclusterInstance = new(selectedPrefab, this.prefab);
|
||||||
subclusterInstance.defaultOutput.AddReceiver(nucleus);
|
subclusterInstance.defaultOutput.AddReceiver(nucleus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,8 +449,10 @@ namespace NanoBrain {
|
|||||||
Cluster reimportedCluster = new(subCluster.prefab, this.prefab);
|
Cluster reimportedCluster = new(subCluster.prefab, this.prefab);
|
||||||
subCluster.MoveReceivers(reimportedCluster);
|
subCluster.MoveReceivers(reimportedCluster);
|
||||||
// subcluster should be garbage now...
|
// subcluster should be garbage now...
|
||||||
|
this.currentNucleus = reimportedCluster;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
this.currentNucleus = null;
|
||||||
List<Cluster> newSiblingsList = new();
|
List<Cluster> newSiblingsList = new();
|
||||||
foreach (Cluster sibling in subCluster.siblingClusters) {
|
foreach (Cluster sibling in subCluster.siblingClusters) {
|
||||||
Cluster reimportedCluster = new(sibling.prefab, this.prefab) {
|
Cluster reimportedCluster = new(sibling.prefab, this.prefab) {
|
||||||
@ -452,6 +460,8 @@ namespace NanoBrain {
|
|||||||
};
|
};
|
||||||
sibling.MoveReceivers(reimportedCluster);
|
sibling.MoveReceivers(reimportedCluster);
|
||||||
newSiblingsList.Add(reimportedCluster);
|
newSiblingsList.Add(reimportedCluster);
|
||||||
|
// make the first reimportedCluster the new current nucleus
|
||||||
|
this.currentNucleus ??= reimportedCluster;
|
||||||
}
|
}
|
||||||
Cluster[] newSiblings = newSiblingsList.ToArray();
|
Cluster[] newSiblings = newSiblingsList.ToArray();
|
||||||
foreach (Cluster sibling in newSiblings)
|
foreach (Cluster sibling in newSiblings)
|
||||||
@ -460,7 +470,7 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int selectedConnectNucleus = -1;
|
int selectedConnectNucleus = -1;
|
||||||
// Connect to another nucleus in the same cluster
|
// Connect to another nucleus
|
||||||
protected virtual bool ConnectNucleus(ClusterPrefab cluster, Nucleus nucleusToConnect) {
|
protected virtual bool ConnectNucleus(ClusterPrefab cluster, Nucleus nucleusToConnect) {
|
||||||
if (cluster == null)
|
if (cluster == null)
|
||||||
return false;
|
return false;
|
||||||
@ -485,14 +495,10 @@ namespace NanoBrain {
|
|||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
if (connecting) {
|
if (connecting) {
|
||||||
Nucleus nucleus = nuclei.ElementAt(selectedConnectNucleus);
|
Nucleus nucleus = nuclei.ElementAt(selectedConnectNucleus);
|
||||||
// if (nucleus is IReceptor receptor)
|
if (nucleus is Cluster subCluster)
|
||||||
// receptor.AddArrayReceiver(this.currentNucleus);
|
subCluster.AddArrayReceiver(this.currentNucleus);
|
||||||
// else
|
else if (nucleus is Neuron neuron)
|
||||||
if (nucleus is Neuron neuron)
|
|
||||||
neuron.AddReceiver(this.currentNucleus);
|
neuron.AddReceiver(this.currentNucleus);
|
||||||
else if (nucleus is Cluster subCluster)
|
|
||||||
subCluster.defaultOutput.AddReceiver(this.currentNucleus);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return connecting;
|
return connecting;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -557,8 +557,16 @@ namespace NanoBrain {
|
|||||||
Handles.Label(labelPos1, "0", style);
|
Handles.Label(labelPos1, "0", style);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (parentCluster.siblingClusters != null && parentCluster.siblingClusters.Length > 1) {
|
|
||||||
// draw the array size label
|
// draw the array size label
|
||||||
|
if (parentCluster.instanceCount > 1) {
|
||||||
|
if (color.grayscale > 0.5f)
|
||||||
|
style.normal.textColor = Color.black;
|
||||||
|
else
|
||||||
|
style.normal.textColor = Color.white;
|
||||||
|
Handles.Label(labelPosition, parentCluster.instanceCount.ToString(), style);
|
||||||
|
style.normal.textColor = Color.white;
|
||||||
|
}
|
||||||
|
else if (parentCluster.siblingClusters != null && parentCluster.siblingClusters.Length > 1) {
|
||||||
if (color.grayscale > 0.5f)
|
if (color.grayscale > 0.5f)
|
||||||
style.normal.textColor = Color.black;
|
style.normal.textColor = Color.black;
|
||||||
else
|
else
|
||||||
@ -582,8 +590,16 @@ namespace NanoBrain {
|
|||||||
Handles.Label(labelPos1, "0", style);
|
Handles.Label(labelPos1, "0", style);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1) {
|
|
||||||
// draw the array size label
|
// draw the array size label
|
||||||
|
if (cluster.instanceCount > 1) {
|
||||||
|
if (color.grayscale > 0.5f)
|
||||||
|
style.normal.textColor = Color.black;
|
||||||
|
else
|
||||||
|
style.normal.textColor = Color.white;
|
||||||
|
Handles.Label(labelPosition, cluster.instanceCount.ToString(), style);
|
||||||
|
style.normal.textColor = Color.white;
|
||||||
|
}
|
||||||
|
else if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1) {
|
||||||
if (color.grayscale > 0.5f)
|
if (color.grayscale > 0.5f)
|
||||||
style.normal.textColor = Color.black;
|
style.normal.textColor = Color.black;
|
||||||
else
|
else
|
||||||
|
|||||||
@ -15,6 +15,7 @@ namespace NanoBrain {
|
|||||||
/// Clusters can be nested inside other clusters.
|
/// Clusters can be nested inside other clusters.
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Cluster : Nucleus {
|
public class Cluster : Nucleus {
|
||||||
|
// It may be that clusters will not be nuclei anymore in the future....
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base name of the cluster. I don't think this is actively used at this moment
|
/// The base name of the cluster. I don't think this is actively used at this moment
|
||||||
@ -28,8 +29,11 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This should not be serialized
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
public Cluster[] siblingClusters;
|
public Cluster[] siblingClusters;
|
||||||
|
// This serialization should be enough
|
||||||
|
public int instanceCount = 1;
|
||||||
public Dictionary<int, Cluster> thingClusters = new();
|
public Dictionary<int, Cluster> thingClusters = new();
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
@ -141,7 +145,6 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
arrayIx++;
|
arrayIx++;
|
||||||
}
|
}
|
||||||
//clonedNucleus.array = clonedArray;
|
|
||||||
clonedNucleus.siblingClusters = clonedArray;
|
clonedNucleus.siblingClusters = clonedArray;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -152,6 +155,50 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect the subclusters
|
||||||
|
List<Cluster> subClusters = new();
|
||||||
|
foreach (Nucleus nucleus in prefabNuclei) {
|
||||||
|
foreach (Synapse synapse in nucleus.synapses) {
|
||||||
|
Nucleus synapseNucleus = synapse.neuron;
|
||||||
|
if (synapseNucleus is not Cluster subCluster)
|
||||||
|
continue;
|
||||||
|
if (subClusters.Contains(subCluster))
|
||||||
|
continue;
|
||||||
|
subClusters.Add(subCluster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create the subcluster instances
|
||||||
|
foreach (Cluster subCluster in subClusters) {
|
||||||
|
for (int ix = 0; ix < subCluster.instanceCount; ix++) {
|
||||||
|
// create the new instance
|
||||||
|
Cluster clusterInstance = new(subCluster.prefab);
|
||||||
|
// connect it
|
||||||
|
foreach ((Neuron sender, Nucleus receiver) in subCluster.CollectConnections()) {
|
||||||
|
int receiverIx = GetNucleusIndex(prefabNuclei, receiver);
|
||||||
|
if (receiverIx < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (clonedNuclei[receiverIx] is not Nucleus clonedReceiver)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Find the synapse for the weight
|
||||||
|
float weight = 1;
|
||||||
|
foreach (Synapse synapse in receiver.synapses) {
|
||||||
|
// Find the weight for this synapse
|
||||||
|
if (synapse.neuron == sender) {
|
||||||
|
weight = synapse.weight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clusterInstance.GetNucleus(sender.name) is not Neuron clonedSender)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clonedSender.AddReceiver(clonedReceiver, weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach (Nucleus nucleus in this.clusterNuclei) {
|
foreach (Nucleus nucleus in this.clusterNuclei) {
|
||||||
if (nucleus is Cluster clonedSubCluster)
|
if (nucleus is Cluster clonedSubCluster)
|
||||||
@ -245,6 +292,7 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override Nucleus ShallowCloneTo(Cluster parent) {
|
public override Nucleus ShallowCloneTo(Cluster parent) {
|
||||||
|
// Clusters should not be cloned, but instantiated from the prefab....
|
||||||
Cluster clone = new(this.prefab, parent) {
|
Cluster clone = new(this.prefab, parent) {
|
||||||
name = this.name,
|
name = this.name,
|
||||||
clusterPrefab = this.clusterPrefab,
|
clusterPrefab = this.clusterPrefab,
|
||||||
@ -314,6 +362,10 @@ namespace NanoBrain {
|
|||||||
|
|
||||||
#region Cluster Array
|
#region Cluster Array
|
||||||
|
|
||||||
|
public void AddInstance() {
|
||||||
|
this.instanceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddInstance(ClusterPrefab prefab) {
|
public void AddInstance(ClusterPrefab prefab) {
|
||||||
// Ensure siblingClusters exists
|
// Ensure siblingClusters exists
|
||||||
if (this.siblingClusters == null || this.siblingClusters.Length == 0)
|
if (this.siblingClusters == null || this.siblingClusters.Length == 0)
|
||||||
@ -340,6 +392,9 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveInstance() {
|
public void RemoveInstance() {
|
||||||
|
if (instanceCount > 1)
|
||||||
|
instanceCount--;
|
||||||
|
else {
|
||||||
if (this.siblingClusters == null || this.siblingClusters.Length <= 1)
|
if (this.siblingClusters == null || this.siblingClusters.Length <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -353,6 +408,7 @@ namespace NanoBrain {
|
|||||||
Neuron.Delete(this.siblingClusters[^1]);
|
Neuron.Delete(this.siblingClusters[^1]);
|
||||||
this.siblingClusters = newClusters;
|
this.siblingClusters = newClusters;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public virtual Cluster GetThingCluster() {
|
public virtual Cluster GetThingCluster() {
|
||||||
Cluster selectedCluster = SelectCluster();
|
Cluster selectedCluster = SelectCluster();
|
||||||
@ -411,6 +467,13 @@ namespace NanoBrain {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1) {
|
||||||
|
foreach (Cluster cluster in this.siblingClusters) {
|
||||||
|
cluster.defaultOutput.AddReceiver(receiverToAdd, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endregion ClusterArray
|
#endregion ClusterArray
|
||||||
|
|
||||||
public ClusterPrefab prefab;
|
public ClusterPrefab prefab;
|
||||||
@ -593,6 +656,22 @@ namespace NanoBrain {
|
|||||||
return receivers;
|
return receivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<(Neuron, Nucleus)> CollectConnections() {
|
||||||
|
List<(Neuron, Nucleus)> connections = new();
|
||||||
|
|
||||||
|
foreach (Nucleus outputNucleus in this.clusterNuclei) {
|
||||||
|
if (outputNucleus is not Neuron output)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (Nucleus receiver in output.receivers) {
|
||||||
|
// Only add receivers outside this cluster
|
||||||
|
if (receiver.clusterPrefab != this.prefab)
|
||||||
|
connections.Add((output, receiver));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
public void MoveReceivers(Cluster newCluster) {
|
public void MoveReceivers(Cluster newCluster) {
|
||||||
Debug.Log($"Move receivers for {this.name} to {newCluster.name}");
|
Debug.Log($"Move receivers for {this.name} to {newCluster.name}");
|
||||||
foreach (Nucleus outputNucleus in this.clusterNuclei) {
|
foreach (Nucleus outputNucleus in this.clusterNuclei) {
|
||||||
|
|||||||
@ -88,6 +88,10 @@ public abstract class Nucleus {
|
|||||||
return synapse;
|
return synapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public Synapse AddSynapse(ClusterPrefab clusterPrefab, string neuronName, float weight = 1) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find a synapse
|
/// Find a synapse
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -10,6 +10,7 @@ namespace NanoBrain {
|
|||||||
public class ClusterPrefab : ScriptableObject {
|
public class ClusterPrefab : ScriptableObject {
|
||||||
/// The nuclei in this cluster
|
/// The nuclei in this cluster
|
||||||
[SerializeReference]
|
[SerializeReference]
|
||||||
|
// This list should not include any clusters...
|
||||||
public List<Nucleus> nuclei = new();
|
public List<Nucleus> nuclei = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user