Brain object
This commit is contained in:
parent
86b5053383
commit
21751f8cea
@ -50,6 +50,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Assets/NanoBrain/VisualEditor/NanoBrainObj.cs" />
|
<Compile Include="Assets/NanoBrain/VisualEditor/NanoBrainObj.cs" />
|
||||||
<Compile Include="Assets/Scenes/Boids/Scripts/SwarmSpawner.cs" />
|
<Compile Include="Assets/Scenes/Boids/Scripts/SwarmSpawner.cs" />
|
||||||
|
<Compile Include="Assets/NanoBrain/Perceptoid.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/NeuroidBehaviour.cs" />
|
<Compile Include="Assets/NanoBrain/NeuroidBehaviour.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/NanoBrain.cs" />
|
<Compile Include="Assets/NanoBrain/NanoBrain.cs" />
|
||||||
<Compile Include="Assets/NanoBrain/SensoryNeuroid.cs" />
|
<Compile Include="Assets/NanoBrain/SensoryNeuroid.cs" />
|
||||||
|
|||||||
@ -221,7 +221,7 @@ public class NanoBrain_Editor : Editor {
|
|||||||
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
||||||
tooltip = new(
|
tooltip = new(
|
||||||
$"{sensoryNeuroid.name}" +
|
$"{sensoryNeuroid.name}" +
|
||||||
$"\nThing {sensoryNeuroid.receptor.thingId}" +
|
$"\nThing {sensoryNeuroid.receptor.thingType}" +
|
||||||
$"\nValue: {neuroid.outputValue}" +
|
$"\nValue: {neuroid.outputValue}" +
|
||||||
$"\nStale: {neuroid.stale}");
|
$"\nStale: {neuroid.stale}");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -244,7 +244,7 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
||||||
tooltip = new(
|
tooltip = new(
|
||||||
$"{sensoryNeuroid.name}" +
|
$"{sensoryNeuroid.name}" +
|
||||||
$"\nThing {sensoryNeuroid.receptor.thingId}" +
|
$"\nThing {sensoryNeuroid.receptor.thingType}" +
|
||||||
$"\nValue: {neuroid.outputValue}" +
|
$"\nValue: {neuroid.outputValue}" +
|
||||||
$"\nStale: {neuroid.stale}");
|
$"\nStale: {neuroid.stale}");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
public class Neuroid : Nucleus {
|
public class Neuroid : Nucleus {
|
||||||
public bool average = false;
|
public bool average = false;
|
||||||
public bool inverse = false;
|
public bool inverse = false;
|
||||||
@ -13,9 +14,17 @@ public class Neuroid : Nucleus {
|
|||||||
// Debug.LogError("No neuroid network");
|
// Debug.LogError("No neuroid network");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public Neuroid(NanoBrainObj brain, string name) : base(brain, name) {
|
public Neuroid(NanoBrainObj brain, string name) : base(name) {
|
||||||
|
this.brain = brain;
|
||||||
|
if (this.brain != null) {
|
||||||
|
this.brain.nuclei.Add(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.LogError("No neuroid network");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Neuroid(string name): base(name) {}
|
||||||
|
|
||||||
public void SetWeight(Neuroid input, float weight) {
|
public void SetWeight(Neuroid input, float weight) {
|
||||||
//this.synapses[input] = weight;
|
//this.synapses[input] = weight;
|
||||||
this.SetWeight((Nucleus)input, weight);
|
this.SetWeight((Nucleus)input, weight);
|
||||||
@ -30,7 +39,7 @@ public class Neuroid : Nucleus {
|
|||||||
public void SetInput(Neuroid input) {
|
public void SetInput(Neuroid input) {
|
||||||
// if (this.synapses.ContainsKey(input) == false)
|
// if (this.synapses.ContainsKey(input) == false)
|
||||||
// this.synapses[input] = 1.0f;
|
// this.synapses[input] = 1.0f;
|
||||||
if (this.SynapseExists(input))
|
if (this.SynapseExists(input) == false)
|
||||||
this.SetWeight(input, 1.0f);
|
this.SetWeight(input, 1.0f);
|
||||||
UpdateState();
|
UpdateState();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -13,33 +14,53 @@ public class Nucleus {
|
|||||||
set => _name = value;
|
set => _name = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//public readonly Dictionary<Nucleus, float> synapses = new();
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
public List<Synapse> synapses = new();
|
public List<Synapse> synapses = new();
|
||||||
//public HashSet<Nucleus> receivers = new();
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
public List<Receiver> receivers = new();
|
public List<Receiver> receivers = new();
|
||||||
|
|
||||||
#region Serialization
|
#region Serialization
|
||||||
|
|
||||||
public void Rebuild(NanoBrainObj brain) {
|
[SerializeField]
|
||||||
|
protected string nucleusType;
|
||||||
|
|
||||||
|
public virtual void Rebuild(NanoBrainObj brain) {
|
||||||
if (this.synapses != null) {
|
if (this.synapses != null) {
|
||||||
foreach (Synapse synapse in synapses)
|
foreach (Synapse synapse in synapses)
|
||||||
synapse.Rebuild(brain);
|
synapse.Rebuild(brain);
|
||||||
}
|
}
|
||||||
if (this.receivers == null)
|
if (this.receivers == null)
|
||||||
this.receivers = new();
|
this.receivers = new();
|
||||||
else
|
else {
|
||||||
foreach (Receiver receiver in receivers)
|
foreach (Receiver receiver in receivers.ToArray()) {
|
||||||
receiver.Rebuild(brain);
|
if (receiver.Rebuild(brain) == false) {
|
||||||
|
Debug.Log("Rebuilding failed, removing receiver.");
|
||||||
|
receivers.Remove(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
public static Nucleus RebuildType(NanoBrainObj brain, Nucleus nucleus) {
|
||||||
|
if (string.IsNullOrEmpty(nucleus.nucleusType) == false) {
|
||||||
|
Type nucleusType = Type.GetType(nucleus.nucleusType);
|
||||||
|
if (nucleusType != null) {
|
||||||
|
object[] args = new object[] { brain, nucleus.name };
|
||||||
|
Nucleus rebuiltNucleus = (Nucleus)Activator.CreateInstance(nucleusType, args);
|
||||||
|
rebuiltNucleus.Deserialize(nucleus);
|
||||||
|
return rebuiltNucleus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nucleus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Deserialize(Nucleus nucleus) { }
|
||||||
|
|
||||||
|
#endregion Serialization
|
||||||
|
|
||||||
#region Runtime state (not serialized)
|
#region Runtime state (not serialized)
|
||||||
|
|
||||||
// public NanoBrain brain { get; protected set; }
|
public NanoBrainObj brain { get; protected set; }
|
||||||
public NanoBrainObj newBrain { get; protected set; }
|
|
||||||
|
|
||||||
public virtual Vector3 outputValue { get; set; }
|
public virtual Vector3 outputValue { get; set; }
|
||||||
|
|
||||||
@ -50,12 +71,13 @@ public class Nucleus {
|
|||||||
|
|
||||||
#endregion Runtime state
|
#endregion Runtime state
|
||||||
|
|
||||||
public Nucleus(NanoBrainObj brain, string name) {
|
public Nucleus(string name) {
|
||||||
this.newBrain = brain;
|
// this.brain = brain;
|
||||||
if (this.newBrain != null)
|
// if (this.brain != null) {
|
||||||
this.newBrain.nuclei.Add(this);
|
// this.brain.nuclei.Add(this);
|
||||||
else
|
// }
|
||||||
Debug.LogError("No neuroid network");
|
// else
|
||||||
|
// Debug.LogError("No neuroid network");
|
||||||
|
|
||||||
this._name = name;
|
this._name = name;
|
||||||
this.id = this.GetHashCode();
|
this.id = this.GetHashCode();
|
||||||
@ -63,9 +85,7 @@ public class Nucleus {
|
|||||||
|
|
||||||
public virtual void AddReceiver(Nucleus receiver) {
|
public virtual void AddReceiver(Nucleus receiver) {
|
||||||
this.receivers.Add(new Receiver(receiver));
|
this.receivers.Add(new Receiver(receiver));
|
||||||
//receiver.synapses[this] = 1.0f; // new(this);
|
|
||||||
receiver.SetWeight(this, 1.0f);
|
receiver.SetWeight(this, 1.0f);
|
||||||
//Debug.Log($"receiver # {this.receivers.Count} synapse count {receiver.synapses.Count}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Delete(Nucleus nucleus) {
|
public static void Delete(Nucleus nucleus) {
|
||||||
@ -73,15 +93,19 @@ public class Nucleus {
|
|||||||
if (synapse.nucleus.receivers.Count > 1) {
|
if (synapse.nucleus.receivers.Count > 1) {
|
||||||
// there is another nucleus feeding into this input nucleus
|
// there is another nucleus feeding into this input nucleus
|
||||||
synapse.nucleus.receivers.RemoveAll(r => r.nucleus == nucleus);
|
synapse.nucleus.receivers.RemoveAll(r => r.nucleus == nucleus);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// No other links, delete it.
|
// No other links, delete it.
|
||||||
Nucleus.Delete(synapse.nucleus);
|
Nucleus.Delete(synapse.nucleus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (Receiver receiver in nucleus.receivers)
|
foreach (Receiver receiver in nucleus.receivers) {
|
||||||
receiver.nucleus.synapses.RemoveAll(s => s.nucleus == nucleus);
|
if (receiver.nucleus != null && receiver.nucleus.synapses != null)
|
||||||
|
receiver.nucleus.synapses.RemoveAll(s => s.nucleus == nucleus);
|
||||||
|
}
|
||||||
|
|
||||||
nucleus.newBrain.nuclei.RemoveAll(n => n == nucleus);
|
nucleus.brain.nuclei.RemoveAll(n => n == nucleus);
|
||||||
|
nucleus.brain.GarbageCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetInputFrom(Nucleus input, float weight = 1.0f) {
|
public void GetInputFrom(Nucleus input, float weight = 1.0f) {
|
||||||
@ -113,6 +137,7 @@ public class Nucleus {
|
|||||||
Synapse newSynapse = new(nucleus, weight);
|
Synapse newSynapse = new(nucleus, weight);
|
||||||
synapses.Add(newSynapse);
|
synapses.Add(newSynapse);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
@ -139,6 +164,12 @@ public class Synapse {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
foreach (Perceptoid perceptoid in brain.perceptei) {
|
||||||
|
if (perceptoid.id == this.nucleusId) {
|
||||||
|
this.nucleus = perceptoid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}");
|
Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,16 +185,18 @@ public class Receiver {
|
|||||||
this.nucleusId = nucleus.id;
|
this.nucleusId = nucleus.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rebuild(NanoBrainObj brain) {
|
public bool Rebuild(NanoBrainObj brain) {
|
||||||
if (brain == null)
|
if (brain == null) {
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Nucleus nucleus in brain.nuclei) {
|
foreach (Nucleus nucleus in brain.nuclei) {
|
||||||
if (nucleus.id == this.nucleusId) {
|
if (nucleus.id == this.nucleusId) {
|
||||||
this.nucleus = nucleus;
|
this.nucleus = nucleus;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}");
|
Debug.LogWarning($"Receiver deserialization error: could not find nucleus with id {this.nucleusId}");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -16,11 +16,18 @@ public class Perception : Nucleus {
|
|||||||
//public HashSet<Receiver> velocityReceivers { get; protected set; }
|
//public HashSet<Receiver> velocityReceivers { get; protected set; }
|
||||||
public List<Receiver> velocityReceivers;
|
public List<Receiver> velocityReceivers;
|
||||||
|
|
||||||
public Perception(NanoBrainObj brain) : base(brain, "Perception") {
|
public Perception(NanoBrainObj brain) : base("Perception") {
|
||||||
this.positionReceivers = new();
|
this.positionReceivers = new();
|
||||||
this.velocityReceivers = new();
|
this.velocityReceivers = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Perceptoid GetPerception(int thingType = 0) {
|
||||||
|
foreach (Nucleus nucleus in this.brain.nuclei) {
|
||||||
|
if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.receptor.thingType == thingType))
|
||||||
|
return perceptoid;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void SendPositions(Nucleus receivingNeuroid, int thingType = 0, float weight = 1.0f) {
|
public void SendPositions(Nucleus receivingNeuroid, int thingType = 0, float weight = 1.0f) {
|
||||||
Receiver receiver = new() {
|
Receiver receiver = new() {
|
||||||
@ -55,7 +62,7 @@ public class Perception : Nucleus {
|
|||||||
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
||||||
if (sensoryNeuroids[i] == null)
|
if (sensoryNeuroids[i] == null)
|
||||||
availableIx = i;
|
availableIx = i;
|
||||||
else if (sensoryNeuroids[i].receptor.thingId == thingId) {
|
else if (sensoryNeuroids[i].receptor.thingType == thingId) {
|
||||||
sensoryNeuroids[i].receptor.position = localPosition;
|
sensoryNeuroids[i].receptor.position = localPosition;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -80,7 +87,7 @@ public class Perception : Nucleus {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Debug.Log($"new receptor for {thingId} at {availableIx}");
|
Debug.Log($"new receptor for {thingId} at {availableIx}");
|
||||||
neuroid = new(newBrain, thingId, name);
|
neuroid = new(brain, thingId, name);
|
||||||
sensoryNeuroids[availableIx] = neuroid;
|
sensoryNeuroids[availableIx] = neuroid;
|
||||||
}
|
}
|
||||||
foreach (Receiver receiver in positionReceivers) {
|
foreach (Receiver receiver in positionReceivers) {
|
||||||
|
|||||||
156
Assets/NanoBrain/Perceptoid.cs
Normal file
156
Assets/NanoBrain/Perceptoid.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class Perceptoid : Neuroid {
|
||||||
|
// A neuroid which has no neurons as input
|
||||||
|
// But receives value from a receptor
|
||||||
|
public Receptor receptor;
|
||||||
|
public VelocityNeuroid velocityNeuroid;
|
||||||
|
|
||||||
|
#region Serialization
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
public int thingType;
|
||||||
|
|
||||||
|
public override void Rebuild(NanoBrainObj brain) {
|
||||||
|
base.Rebuild(brain);
|
||||||
|
this.receptor = new Receptor() {
|
||||||
|
neuroid = this
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(Nucleus nucleus) {
|
||||||
|
base.Deserialize(nucleus);
|
||||||
|
|
||||||
|
if (nucleus is Perceptoid perceptoid)
|
||||||
|
this.receptor.thingType = perceptoid.thingType;
|
||||||
|
|
||||||
|
// Point all receivers to this perceptoid instead of the default nucleus
|
||||||
|
foreach (Receiver receiver in nucleus.receivers) {
|
||||||
|
foreach (Synapse synapse in receiver.nucleus.synapses) {
|
||||||
|
if (synapse.nucleus == nucleus)
|
||||||
|
synapse.nucleus = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Point all synapses to this perceptoid instead of the default nucleus
|
||||||
|
foreach (Synapse synapse in nucleus.synapses) {
|
||||||
|
foreach (Receiver receiver in synapse.nucleus.receivers) {
|
||||||
|
if (receiver.nucleus == nucleus)
|
||||||
|
receiver.nucleus = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy all the synapses
|
||||||
|
this.synapses = nucleus.synapses;
|
||||||
|
// Copy all receivers
|
||||||
|
this.receivers = nucleus.receivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Serialization
|
||||||
|
|
||||||
|
public Perceptoid(NanoBrainObj brain, string name) : base(name) {
|
||||||
|
this.brain = brain;
|
||||||
|
if (this.brain != null) {
|
||||||
|
this.brain.perceptei.Add(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.LogError("No neuroid network");
|
||||||
|
|
||||||
|
this.nucleusType = nameof(Perceptoid);
|
||||||
|
this.name = name;
|
||||||
|
this.receptor = new Receptor {
|
||||||
|
neuroid = this
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Perceptoid(NanoBrainObj brain, int thingType, string name = "sensor") : base(name) {
|
||||||
|
this.brain = brain;
|
||||||
|
if (this.brain != null) {
|
||||||
|
this.brain.perceptei.Add(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.LogError("No neuroid network");
|
||||||
|
|
||||||
|
this.nucleusType = nameof(Perceptoid);
|
||||||
|
this.name = name;
|
||||||
|
this.thingType = thingType;
|
||||||
|
this.receptor = new Receptor {
|
||||||
|
neuroid = this,
|
||||||
|
thingType = thingType
|
||||||
|
};
|
||||||
|
this.velocityNeuroid = new(brain, name + ": velocity");
|
||||||
|
// The velocity neuroid received position data from this
|
||||||
|
this.AddReceiver(velocityNeuroid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Replace(int thingType, string name = "sensor") {
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
this.thingType = thingType;
|
||||||
|
this.receptor.thingType = thingType;
|
||||||
|
this.receptor.localPosition = Vector3.zero;
|
||||||
|
|
||||||
|
this.outputValue = Vector3.zero;
|
||||||
|
this.receivers = new();
|
||||||
|
this.AddReceiver(velocityNeuroid);
|
||||||
|
|
||||||
|
this.velocityNeuroid.Replace(name + ": velocity");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateState() {
|
||||||
|
Vector3 result = receptor.localPosition;
|
||||||
|
foreach (Synapse synapse in this.synapses) {
|
||||||
|
Nucleus nucleus = synapse.nucleus;
|
||||||
|
float weight = synapse.weight;
|
||||||
|
Vector3 direction = nucleus.outputValue.normalized;
|
||||||
|
float magnitude = nucleus.outputValue.magnitude;
|
||||||
|
|
||||||
|
magnitude = weight * Mathf.Pow(magnitude, exponent);
|
||||||
|
if (inverse)
|
||||||
|
magnitude = 1 / magnitude;
|
||||||
|
result += direction * magnitude;
|
||||||
|
}
|
||||||
|
if (average && this.synapses.Count > 0)
|
||||||
|
result /= this.synapses.Count + 1;
|
||||||
|
|
||||||
|
this.outputValue = result;
|
||||||
|
foreach (Receiver receiver in this.receivers)
|
||||||
|
if (receiver.nucleus is Neuroid neuroid)
|
||||||
|
neuroid.SetInput(this);
|
||||||
|
this.stale = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Perceptoid GetPerception(NanoBrainObj brain, int thingType = 0) {
|
||||||
|
foreach (Nucleus nucleus in brain.nuclei) {
|
||||||
|
if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.thingType == thingType))
|
||||||
|
return perceptoid;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ProcessStimulus(NanoBrainObj brain, int thingType, Vector3 lcoalPosition) {
|
||||||
|
Perceptoid selectedPerceptoid = null;
|
||||||
|
foreach (Perceptoid nucleus in brain.perceptei) {
|
||||||
|
if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.thingType == thingType))
|
||||||
|
if (selectedPerceptoid == null) {
|
||||||
|
selectedPerceptoid = perceptoid;
|
||||||
|
if (perceptoid.isSleeping) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (perceptoid.receptor.position.magnitude < selectedPerceptoid.receptor.position.magnitude)
|
||||||
|
selectedPerceptoid = perceptoid;
|
||||||
|
}
|
||||||
|
if (selectedPerceptoid == null) {
|
||||||
|
Debug.Log("No perceptoid selected, stimulus is ignored");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedPerceptoid.receptor.position = lcoalPosition;
|
||||||
|
}
|
||||||
|
public static Receptor GetReceptor(NanoBrainObj brain, int thingType) {
|
||||||
|
foreach (Perceptoid perceptoid in brain.perceptei) {
|
||||||
|
if (thingType == 0 || perceptoid.thingType == thingType)
|
||||||
|
return perceptoid.receptor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/NanoBrain/Perceptoid.cs.meta
Normal file
2
Assets/NanoBrain/Perceptoid.cs.meta
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 702f634001a21a9d7ae1057c8ce356e9
|
||||||
@ -1,12 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class Receptor {
|
public class Receptor {
|
||||||
|
|
||||||
public SensoryNeuroid neuroid;
|
public Neuroid neuroid;
|
||||||
|
|
||||||
public int thingId;
|
public int thingType;
|
||||||
public Vector3 localPosition;
|
public Vector3 localPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -33,7 +32,7 @@ public class SensoryNeuroid : Neuroid {
|
|||||||
this.name = name + ": position";
|
this.name = name + ": position";
|
||||||
this.receptor = new Receptor {
|
this.receptor = new Receptor {
|
||||||
neuroid = this,
|
neuroid = this,
|
||||||
thingId = thingId
|
thingType = thingId
|
||||||
};
|
};
|
||||||
this.velocityNeuroid = new(brain, name + ": velocity");
|
this.velocityNeuroid = new(brain, name + ": velocity");
|
||||||
// The velocity neuroid received position data from this
|
// The velocity neuroid received position data from this
|
||||||
@ -43,7 +42,7 @@ public class SensoryNeuroid : Neuroid {
|
|||||||
public void Replace(int thingId, string name = "sensor") {
|
public void Replace(int thingId, string name = "sensor") {
|
||||||
this.name = name + ": position";
|
this.name = name + ": position";
|
||||||
|
|
||||||
this.receptor.thingId = thingId;
|
this.receptor.thingType = thingId;
|
||||||
this.receptor.localPosition = Vector3.zero;
|
this.receptor.localPosition = Vector3.zero;
|
||||||
|
|
||||||
this.outputValue = Vector3.zero;
|
this.outputValue = Vector3.zero;
|
||||||
|
|||||||
@ -11,14 +11,16 @@ public class NanoBrainComponent_Editor : Editor {
|
|||||||
private SerializedProperty brainProp;
|
private SerializedProperty brainProp;
|
||||||
|
|
||||||
public void OnEnable() {
|
public void OnEnable() {
|
||||||
brainProp = serializedObject.FindProperty(nameof(NanoBrainComponent.brain));
|
if (Application.isPlaying == false)
|
||||||
|
brainProp = serializedObject.FindProperty(nameof(NanoBrainComponent.defaultBrain));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override VisualElement CreateInspectorGUI() {
|
public override VisualElement CreateInspectorGUI() {
|
||||||
NanoBrainComponent component = target as NanoBrainComponent;
|
NanoBrainComponent component = target as NanoBrainComponent;
|
||||||
NanoBrainObj brain = component.brain;
|
NanoBrainObj brain = Application.isPlaying ? component.brain : component.defaultBrain;
|
||||||
|
|
||||||
serializedObject.Update();
|
if (Application.isPlaying == false)
|
||||||
|
serializedObject.Update();
|
||||||
|
|
||||||
|
|
||||||
VisualElement root = new();
|
VisualElement root = new();
|
||||||
@ -32,9 +34,11 @@ public class NanoBrainComponent_Editor : Editor {
|
|||||||
|
|
||||||
root.styleSheets.Add(Resources.Load<StyleSheet>("GraphStyles"));
|
root.styleSheets.Add(Resources.Load<StyleSheet>("GraphStyles"));
|
||||||
|
|
||||||
PropertyField brainField = new(brainProp);
|
if (Application.isPlaying == false) {
|
||||||
brainField.label = "Nano Brain";
|
PropertyField brainField = new(brainProp);
|
||||||
root.Add(brainField);
|
brainField.label = "Nano Brain";
|
||||||
|
root.Add(brainField);
|
||||||
|
}
|
||||||
|
|
||||||
mainContainer = new() {
|
mainContainer = new() {
|
||||||
name = "main",
|
name = "main",
|
||||||
@ -70,14 +74,15 @@ public class NanoBrainComponent_Editor : Editor {
|
|||||||
|
|
||||||
if (brain != null)
|
if (brain != null)
|
||||||
board.SetGraph(brain, brain.root, inspectorContainer);
|
board.SetGraph(brain, brain.root, inspectorContainer);
|
||||||
else
|
// else
|
||||||
Debug.LogWarning(" No brain!");
|
// Debug.LogWarning(" No brain!");
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
if (Application.isPlaying == false)
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLayout(float containerWidth) {
|
private void UpdateLayout(float containerWidth) {
|
||||||
if (containerWidth > 800f) {
|
if (containerWidth > 800f) {
|
||||||
mainContainer.style.flexDirection = FlexDirection.Row;
|
mainContainer.style.flexDirection = FlexDirection.Row;
|
||||||
inspectorContainer.style.width = 400; // fixed sidebar width
|
inspectorContainer.style.width = 400; // fixed sidebar width
|
||||||
|
|||||||
@ -299,7 +299,7 @@ public class GraphBoardView : VisualElement {
|
|||||||
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
||||||
tooltip = new(
|
tooltip = new(
|
||||||
$"{sensoryNeuroid.name}" +
|
$"{sensoryNeuroid.name}" +
|
||||||
$"\nThing {sensoryNeuroid.receptor.thingId}" +
|
$"\nThing {sensoryNeuroid.receptor.thingType}" +
|
||||||
$"\nValue: {neuroid.outputValue}" +
|
$"\nValue: {neuroid.outputValue}" +
|
||||||
$"\nStale: {neuroid.stale}");
|
$"\nStale: {neuroid.stale}");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,8 @@ public class NanoBrainInspector : Editor {
|
|||||||
|
|
||||||
public void SetGraph(NanoBrainObj brain, Nucleus nucleus, VisualElement inspectorContainer) {
|
public void SetGraph(NanoBrainObj brain, Nucleus nucleus, VisualElement inspectorContainer) {
|
||||||
this.brain = brain;
|
this.brain = brain;
|
||||||
this.serializedBrain = new SerializedObject(brain);
|
if (Application.isPlaying == false)
|
||||||
|
this.serializedBrain = new SerializedObject(brain);
|
||||||
this.currentNucleus = nucleus;
|
this.currentNucleus = nucleus;
|
||||||
Rebuild(inspectorContainer);
|
Rebuild(inspectorContainer);
|
||||||
}
|
}
|
||||||
@ -212,17 +213,130 @@ public class NanoBrainInspector : Editor {
|
|||||||
if (currentNucleus == null)
|
if (currentNucleus == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
serializedBrain.Update();
|
if (Application.isPlaying == false)
|
||||||
|
serializedBrain.Update();
|
||||||
|
|
||||||
Handles.BeginGUI();
|
Handles.BeginGUI();
|
||||||
foreach (NeuroidLayer layer in layers)
|
DrawGraph();
|
||||||
DrawLayer(layer);
|
// foreach (NeuroidLayer layer in layers)
|
||||||
|
// DrawLayer(layer);
|
||||||
Handles.EndGUI();
|
Handles.EndGUI();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawGraph() {
|
||||||
|
float size = 20;
|
||||||
|
Vector3 position = new(200, 210, 0);
|
||||||
|
|
||||||
|
DrawReceivers(this.currentNucleus, position, size);
|
||||||
|
DrawSynapses(this.currentNucleus, position, size);
|
||||||
|
|
||||||
|
// Draw selected Nucleus
|
||||||
|
Handles.color = Color.white;
|
||||||
|
Handles.DrawSolidDisc(position, Vector3.forward, size + 2);
|
||||||
|
DrawNucleus(this.currentNucleus, position, this.currentNucleus.outputValue.magnitude, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue, float size) {
|
||||||
|
if (nucleus.isSleeping)
|
||||||
|
Handles.color = Color.darkRed;
|
||||||
|
else {
|
||||||
|
float brightness = nucleus.outputValue.magnitude / maxValue;
|
||||||
|
Handles.color = new Color(brightness, brightness, brightness);
|
||||||
|
}
|
||||||
|
Handles.DrawSolidDisc(position, Vector3.forward, size);
|
||||||
|
Vector3 labelPos = position - Vector3.down * (size + 0.2f); // below disc along up axis
|
||||||
|
GUIStyle style = new GUIStyle(EditorStyles.label) {
|
||||||
|
alignment = TextAnchor.UpperCenter,
|
||||||
|
normal = { textColor = Color.white },
|
||||||
|
fontStyle = FontStyle.Bold
|
||||||
|
};
|
||||||
|
Handles.Label(labelPos, nucleus.name, style);
|
||||||
|
|
||||||
|
Rect neuronRect = new(position.x - size, position.y - size, size * 2, size * 2);
|
||||||
|
int id = GUIUtility.GetControlID(FocusType.Passive);
|
||||||
|
Event e = Event.current;
|
||||||
|
EventType et = e.GetTypeForControl(id);
|
||||||
|
if (e != null && neuronRect.Contains(e.mousePosition)) {
|
||||||
|
// Process Hover
|
||||||
|
HandleMouseHover(nucleus, neuronRect);
|
||||||
|
// Process click
|
||||||
|
if (e.type == EventType.MouseDown && e.button == 0) {
|
||||||
|
// Consume the event so the scene doesn't also handle it
|
||||||
|
e.Use();
|
||||||
|
HandleClicked(nucleus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawReceivers(Nucleus nucleus, Vector3 parentPos, float size) {
|
||||||
|
int nodeCount = nucleus.receivers.Count;
|
||||||
|
|
||||||
|
// Determine the maximum value in this layer
|
||||||
|
// This is used to 'scale' the output value colors of the nuclei
|
||||||
|
float maxValue = 0;
|
||||||
|
foreach (Receiver receiver in nucleus.receivers) {
|
||||||
|
if (receiver.nucleus is Neuroid neuroid) {
|
||||||
|
float value = neuroid.outputValue.magnitude;
|
||||||
|
if (value > maxValue)
|
||||||
|
maxValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the spacing of the nuclei in the layer
|
||||||
|
float spacing = 400f / nodeCount;
|
||||||
|
float margin = 10 + spacing / 2;
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
foreach (Receiver receiver in nucleus.receivers) {
|
||||||
|
Nucleus receiverNucleus = receiver.nucleus;
|
||||||
|
|
||||||
|
Vector3 pos = new(100, margin + row * spacing, 0.0f);
|
||||||
|
Handles.color = Color.white;
|
||||||
|
Handles.DrawLine(parentPos, pos);
|
||||||
|
|
||||||
|
DrawNucleus(receiverNucleus, pos, maxValue, size);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSynapses(Nucleus nucleus, Vector3 parentPos, float size) {
|
||||||
|
int nodeCount = nucleus.synapses.Count;
|
||||||
|
|
||||||
|
// Determine the maximum value in this layer
|
||||||
|
// This is used to 'scale' the output value colors of the nuclei
|
||||||
|
float maxValue = 0;
|
||||||
|
foreach (Synapse receiver in nucleus.synapses) {
|
||||||
|
if (receiver.nucleus is Neuroid neuroid) {
|
||||||
|
float value = neuroid.outputValue.magnitude;
|
||||||
|
if (value > maxValue)
|
||||||
|
maxValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the spacing of the nuclei in the layer
|
||||||
|
float spacing = 400f / nodeCount;
|
||||||
|
float margin = 10 + spacing / 2;
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
foreach (Synapse receiver in nucleus.synapses) {
|
||||||
|
Nucleus receiverNucleus = receiver.nucleus;
|
||||||
|
|
||||||
|
Vector3 pos = new(300, margin + row * spacing, 0.0f);
|
||||||
|
Handles.color = Color.white;
|
||||||
|
Handles.DrawLine(parentPos, pos);
|
||||||
|
|
||||||
|
DrawNucleus(receiverNucleus, pos, maxValue, size);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private void DrawLayer(NeuroidLayer layer) {
|
private void DrawLayer(NeuroidLayer layer) {
|
||||||
int nodeCount = layer.neuroids.Count;
|
int nodeCount = layer.neuroids.Count;
|
||||||
|
|
||||||
|
// Determine the maximum value in this layer
|
||||||
|
// This is used to 'scale' the output value colors of the nuclei
|
||||||
float maxValue = 0;
|
float maxValue = 0;
|
||||||
foreach (Nucleus nucleus in layer.neuroids) {
|
foreach (Nucleus nucleus in layer.neuroids) {
|
||||||
if (nucleus is Neuroid neuroid) {
|
if (nucleus is Neuroid neuroid) {
|
||||||
@ -231,8 +345,11 @@ public class NanoBrainInspector : Editor {
|
|||||||
maxValue = value;
|
maxValue = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine the spacing of the nuclei in the layer
|
||||||
float spacing = 400f / nodeCount;
|
float spacing = 400f / nodeCount;
|
||||||
float margin = 10 + spacing / 2;
|
float margin = 10 + spacing / 2;
|
||||||
|
|
||||||
foreach (Nucleus layerNucleus in layer.neuroids) {
|
foreach (Nucleus layerNucleus in layer.neuroids) {
|
||||||
Vector2Int layerNeuroidPos = this.neuroidPositions[layerNucleus];
|
Vector2Int layerNeuroidPos = this.neuroidPositions[layerNucleus];
|
||||||
Vector3 parentPos = new(100 + layerNeuroidPos.x * 100, margin + layerNeuroidPos.y * spacing, 0.1f);
|
Vector3 parentPos = new(100 + layerNeuroidPos.x * 100, margin + layerNeuroidPos.y * spacing, 0.1f);
|
||||||
@ -240,11 +357,9 @@ public class NanoBrainInspector : Editor {
|
|||||||
float inputSpacing = 400f / layerNucleus.synapses.Count;
|
float inputSpacing = 400f / layerNucleus.synapses.Count;
|
||||||
float inputMargin = 10 + inputSpacing / 2;
|
float inputMargin = 10 + inputSpacing / 2;
|
||||||
int minStale = 10000;
|
int minStale = 10000;
|
||||||
Debug.Log($"layer neuron {layerNucleus.name} has {layerNucleus.synapses.Count} synapses");
|
|
||||||
foreach (Synapse synapse in layerNucleus.synapses) {
|
foreach (Synapse synapse in layerNucleus.synapses) {
|
||||||
Nucleus nucleus = synapse.nucleus;
|
Nucleus nucleus = synapse.nucleus;
|
||||||
if (nucleus != null) {
|
if (nucleus != null) {
|
||||||
Debug.Log($"Synapse to {nucleus.name} is valid"); float weight = synapse.weight;
|
|
||||||
if (this.neuroidPositions.ContainsKey(nucleus)) {
|
if (this.neuroidPositions.ContainsKey(nucleus)) {
|
||||||
Vector2Int inputNeuroidPos = this.neuroidPositions[nucleus];
|
Vector2Int inputNeuroidPos = this.neuroidPositions[nucleus];
|
||||||
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
||||||
@ -265,20 +380,21 @@ public class NanoBrainInspector : Editor {
|
|||||||
Handles.color = Color.white;
|
Handles.color = Color.white;
|
||||||
Handles.DrawSolidDisc(parentPos, Vector3.forward, size + 2);
|
Handles.DrawSolidDisc(parentPos, Vector3.forward, size + 2);
|
||||||
}
|
}
|
||||||
if (layerNucleus.isSleeping)
|
DrawNucleus(layerNucleus, parentPos, maxValue, size);
|
||||||
Handles.color = Color.darkRed;
|
// if (layerNucleus.isSleeping)
|
||||||
else {
|
// Handles.color = Color.darkRed;
|
||||||
float brightness = layerNucleus.outputValue.magnitude / maxValue;
|
// else {
|
||||||
Handles.color = new Color(brightness, brightness, brightness);
|
// float brightness = layerNucleus.outputValue.magnitude / maxValue;
|
||||||
}
|
// Handles.color = new Color(brightness, brightness, brightness);
|
||||||
Handles.DrawSolidDisc(parentPos, Vector3.forward, size);
|
// }
|
||||||
Vector3 labelPos = parentPos - Vector3.down * (size + 0.2f); // below disc along up axis
|
// Handles.DrawSolidDisc(parentPos, Vector3.forward, size);
|
||||||
GUIStyle style = new GUIStyle(EditorStyles.label) {
|
// Vector3 labelPos = parentPos - Vector3.down * (size + 0.2f); // below disc along up axis
|
||||||
alignment = TextAnchor.UpperCenter,
|
// GUIStyle style = new GUIStyle(EditorStyles.label) {
|
||||||
normal = { textColor = Color.white },
|
// alignment = TextAnchor.UpperCenter,
|
||||||
fontStyle = FontStyle.Bold
|
// normal = { textColor = Color.white },
|
||||||
};
|
// fontStyle = FontStyle.Bold
|
||||||
Handles.Label(labelPos, layerNucleus.name, style);
|
// };
|
||||||
|
// Handles.Label(labelPos, layerNucleus.name, style);
|
||||||
|
|
||||||
Rect neuronRect = new(parentPos.x - size, parentPos.y - size, size * 2, size * 2);
|
Rect neuronRect = new(parentPos.x - size, parentPos.y - size, size * 2, size * 2);
|
||||||
int id = GUIUtility.GetControlID(FocusType.Passive);
|
int id = GUIUtility.GetControlID(FocusType.Passive);
|
||||||
@ -296,13 +412,14 @@ public class NanoBrainInspector : Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
private void HandleMouseHover(Nucleus neuroid, Rect rect) {
|
private void HandleMouseHover(Nucleus neuroid, Rect rect) {
|
||||||
GUIContent tooltip;
|
GUIContent tooltip;
|
||||||
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
||||||
tooltip = new(
|
tooltip = new(
|
||||||
$"{sensoryNeuroid.name}" +
|
$"{sensoryNeuroid.name}" +
|
||||||
$"\nThing {sensoryNeuroid.receptor.thingId}" +
|
$"\nThing {sensoryNeuroid.receptor.thingType}" +
|
||||||
$"\nValue: {neuroid.outputValue}" +
|
$"\nValue: {neuroid.outputValue}" +
|
||||||
$"\nStale: {neuroid.stale}");
|
$"\nStale: {neuroid.stale}");
|
||||||
}
|
}
|
||||||
@ -343,7 +460,11 @@ public class NanoBrainInspector : Editor {
|
|||||||
if (so.targetObject == null)
|
if (so.targetObject == null)
|
||||||
return;
|
return;
|
||||||
so.Update();
|
so.Update();
|
||||||
|
if (this.currentNucleus == null)
|
||||||
|
return;
|
||||||
this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name);
|
this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name);
|
||||||
|
if (this.currentNucleus is Perceptoid currentPerceptoid)
|
||||||
|
currentPerceptoid.thingType = EditorGUILayout.IntField("Thing Type", currentPerceptoid.thingType);
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
EditorGUILayout.LabelField("Output Value", GUILayout.Width(100));
|
EditorGUILayout.LabelField("Output Value", GUILayout.Width(100));
|
||||||
EditorGUILayout.Vector3Field(GUIContent.none, this.currentNucleus.outputValue);
|
EditorGUILayout.Vector3Field(GUIContent.none, this.currentNucleus.outputValue);
|
||||||
@ -359,8 +480,15 @@ public class NanoBrainInspector : Editor {
|
|||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
EditorGUILayout.LabelField(synapse.nucleus.name, GUILayout.Width(120));
|
EditorGUILayout.LabelField(synapse.nucleus.name, GUILayout.Width(120));
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
// if (synapse.nucleus is Perceptoid perceptoid) {
|
||||||
|
// EditorGUILayout.LabelField("Thing", GUILayout.Width(45));
|
||||||
|
// perceptoid.thingType = EditorGUILayout.IntField(perceptoid.thingType, GUILayout.Width(40));
|
||||||
|
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
EditorGUILayout.LabelField("Weight", GUILayout.Width(45));
|
EditorGUILayout.LabelField("Weight", GUILayout.Width(45));
|
||||||
synapse.weight = EditorGUILayout.FloatField(synapse.weight, GUILayout.Width(40));
|
synapse.weight = EditorGUILayout.FloatField(synapse.weight, GUILayout.Width(40));
|
||||||
|
// }
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.Vector3Field(GUIContent.none, synapse.nucleus.outputValue, GUILayout.Width(180));
|
EditorGUILayout.Vector3Field(GUIContent.none, synapse.nucleus.outputValue, GUILayout.Width(180));
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
@ -372,10 +500,8 @@ public class NanoBrainInspector : Editor {
|
|||||||
}
|
}
|
||||||
if (GUILayout.Button("Add Neuron"))
|
if (GUILayout.Button("Add Neuron"))
|
||||||
AddInputNeuron(this.currentNucleus);
|
AddInputNeuron(this.currentNucleus);
|
||||||
if (GUILayout.Button("Add Position Perception"))
|
if (GUILayout.Button("Add Perceptoid"))
|
||||||
AddPositionPerception(this.currentNucleus);
|
AddPerceptoid(this.currentNucleus);
|
||||||
if (GUILayout.Button("Add Velocity Perception"))
|
|
||||||
AddVelocityPerception(this.currentNucleus);
|
|
||||||
if (GUILayout.Button("Delete this neuron"))
|
if (GUILayout.Button("Delete this neuron"))
|
||||||
DeleteNeuron(this.currentNucleus);
|
DeleteNeuron(this.currentNucleus);
|
||||||
|
|
||||||
@ -384,9 +510,9 @@ public class NanoBrainInspector : Editor {
|
|||||||
inspectorContainer.Add(container);
|
inspectorContainer.Add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddInputNeuron(Nucleus receiver) {
|
protected virtual void AddInputNeuron(Nucleus nucleus) {
|
||||||
Neuroid newNeuroid = new(this.brain, "New neuron");
|
Neuroid newNeuroid = new(this.brain, "New neuron");
|
||||||
newNeuroid.AddReceiver(receiver);
|
newNeuroid.AddReceiver(nucleus);
|
||||||
//Rebuild(inspectorContainer);
|
//Rebuild(inspectorContainer);
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
}
|
}
|
||||||
@ -398,13 +524,19 @@ public class NanoBrainInspector : Editor {
|
|||||||
BuildLayers();
|
BuildLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddPositionPerception(Nucleus receiver) {
|
protected virtual void AddPerceptoid(Nucleus nucleus) {
|
||||||
this.brain.perception.SendPositions(receiver);
|
Perceptoid newPerceptoid = new(this.brain, 0, "New Perceptoid");
|
||||||
}
|
newPerceptoid.AddReceiver(nucleus);
|
||||||
protected virtual void AddVelocityPerception(Nucleus receiver) {
|
BuildLayers();
|
||||||
this.brain.perception.SendVelocities(receiver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// protected virtual void AddPositionPerception(Nucleus receiver) {
|
||||||
|
// this.brain.perception.SendPositions(receiver);
|
||||||
|
// }
|
||||||
|
// protected virtual void AddVelocityPerception(Nucleus receiver) {
|
||||||
|
// this.brain.perception.SendVelocities(receiver);
|
||||||
|
// }
|
||||||
|
|
||||||
private Vector3 NodePosition(Nucleus nucleus, int layerNodeCount = 1) {
|
private Vector3 NodePosition(Nucleus nucleus, int layerNodeCount = 1) {
|
||||||
if (this.neuroidPositions.ContainsKey(nucleus)) {
|
if (this.neuroidPositions.ContainsKey(nucleus)) {
|
||||||
Vector2Int nucleusPos = this.neuroidPositions[nucleus];
|
Vector2Int nucleusPos = this.neuroidPositions[nucleus];
|
||||||
|
|||||||
@ -1,15 +1,21 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class NanoBrainComponent : MonoBehaviour {
|
public class NanoBrainComponent : MonoBehaviour {
|
||||||
public NanoBrainObj brain;
|
public NanoBrainObj defaultBrain;
|
||||||
|
private NanoBrainObj brainInstance;
|
||||||
|
|
||||||
public Nucleus root {
|
public Nucleus root {
|
||||||
get {
|
get {
|
||||||
return brain.root;
|
return brainInstance.root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Perception perception {
|
public NanoBrainObj brain {
|
||||||
get {
|
get {
|
||||||
return brain.perception;
|
if (brainInstance == null && defaultBrain != null) {
|
||||||
|
brainInstance = Instantiate(defaultBrain);
|
||||||
|
brainInstance.name = defaultBrain.name + " (Instance)";
|
||||||
|
}
|
||||||
|
return brainInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,18 +9,19 @@ public class NanoBrainObj : ScriptableObject, ISerializationCallbackReceiver {
|
|||||||
public Color color = Color.white;
|
public Color color = Color.white;
|
||||||
public Texture2D texture;
|
public Texture2D texture;
|
||||||
|
|
||||||
public List<Nucleus> nuclei = new();
|
public List<Neuroid> nuclei = new();
|
||||||
|
public List<Perceptoid> perceptei = new();
|
||||||
|
|
||||||
// This is probably always the first element in the nuclei list...
|
// This is probably always the first element in the nuclei list...
|
||||||
[System.NonSerialized]
|
[System.NonSerialized]
|
||||||
public Nucleus root;
|
public Nucleus root;
|
||||||
public int rootId;
|
public int rootId;
|
||||||
|
|
||||||
public Perception perception;
|
// public Perception perception;
|
||||||
|
|
||||||
public NanoBrainObj() {
|
public NanoBrainObj() {
|
||||||
this.root = new(this, "Root");
|
this.root = new Neuroid(this, "Root");
|
||||||
this.perception = new Perception(this);
|
// this.perception = new Perception(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Neuroid AddNeuron(string name) {
|
public Neuroid AddNeuron(string name) {
|
||||||
@ -40,10 +41,48 @@ public class NanoBrainObj : ScriptableObject, ISerializationCallbackReceiver {
|
|||||||
this.rootId = root.id;
|
this.rootId = root.id;
|
||||||
}
|
}
|
||||||
public void OnAfterDeserialize() {
|
public void OnAfterDeserialize() {
|
||||||
foreach (Nucleus nucleus in nuclei) {
|
try {
|
||||||
if (this.rootId == nucleus.id)
|
foreach (Nucleus nucleus in this.nuclei.ToArray()) {
|
||||||
this.root = nucleus;
|
if (this.rootId == nucleus.id)
|
||||||
nucleus.Rebuild(this);
|
this.root = nucleus;
|
||||||
|
nucleus.Rebuild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// List<Nucleus> rebuildNuclei = new();
|
||||||
|
// foreach (Nucleus nucleus in this.nuclei.ToArray()) {
|
||||||
|
// rebuildNuclei.Add(Nucleus.RebuildType(this, nucleus));
|
||||||
|
// }
|
||||||
|
// this.nuclei = rebuildNuclei;
|
||||||
|
foreach (Perceptoid perceptoid in this.perceptei.ToArray()) {
|
||||||
|
perceptoid.Rebuild(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception) { }
|
||||||
|
this.GarbageCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GarbageCollection() {
|
||||||
|
HashSet<Nucleus> visitedNuclei = new();
|
||||||
|
MarkNuclei(visitedNuclei, this.root);
|
||||||
|
Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei");
|
||||||
|
this.nuclei.RemoveAll(nucleus => visitedNuclei.Contains(nucleus) == false);
|
||||||
|
this.perceptei.RemoveAll(perceptoid => visitedNuclei.Contains(perceptoid) == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkNuclei(HashSet<Nucleus> visitedNuclei, Nucleus 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);
|
||||||
|
MarkNuclei(visitedNuclei, synapse.nucleus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,7 +393,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: ec888ca5333d45a438f9f417fa5ce135, type: 3}
|
m_Script: {fileID: 11500000, guid: ec888ca5333d45a438f9f417fa5ce135, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::SwarmSpawn
|
m_EditorClassIdentifier: Assembly-CSharp::SwarmSpawn
|
||||||
count: 1
|
count: 3
|
||||||
boidPrefab: {fileID: 8702527964058765413, guid: f9c706268554ce449a8773675b2864b8, type: 3}
|
boidPrefab: {fileID: 8702527964058765413, guid: f9c706268554ce449a8773675b2864b8, type: 3}
|
||||||
spawnAreaSize: {x: 0.5, y: 0.5, z: 0.5}
|
spawnAreaSize: {x: 0.5, y: 0.5, z: 0.5}
|
||||||
minDelay: 0.05
|
minDelay: 0.05
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 36081359186edfec998d891a1feeb17b, type: 3}
|
|
||||||
m_Name: New Nano Brain Obj
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::NanoBrainObj
|
|
||||||
title:
|
|
||||||
count: -26
|
|
||||||
color: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
texture: {fileID: 0}
|
|
||||||
nuclei:
|
|
||||||
- id: 257807948
|
|
||||||
_name: Root
|
|
||||||
synapses:
|
|
||||||
- nucleusId: -651011940
|
|
||||||
weight: 1
|
|
||||||
- nucleusId: -1689048724
|
|
||||||
weight: 1
|
|
||||||
receivers: []
|
|
||||||
- id: -1868865374
|
|
||||||
_name: Perception
|
|
||||||
synapses: []
|
|
||||||
receivers: []
|
|
||||||
- id: -651011940
|
|
||||||
_name: Neuron 1
|
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: 257807948
|
|
||||||
- id: -1689048724
|
|
||||||
_name: New neuron
|
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: 257807948
|
|
||||||
- id: -152927560
|
|
||||||
_name: 'Boundary: position'
|
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: -1462684836
|
|
||||||
- id: -1462684836
|
|
||||||
_name: 'Boundary: velocity'
|
|
||||||
synapses:
|
|
||||||
- nucleusId: -152927560
|
|
||||||
weight: 1
|
|
||||||
receivers: []
|
|
||||||
rootId: 257807948
|
|
||||||
perception:
|
|
||||||
id: 1565766940
|
|
||||||
_name: Perception
|
|
||||||
synapses: []
|
|
||||||
receivers: []
|
|
||||||
positionReceivers: []
|
|
||||||
velocityReceivers: []
|
|
||||||
@ -176,4 +176,4 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 92f34a5e4027a1dc39efd8ce63cf6aba, type: 3}
|
m_Script: {fileID: 11500000, guid: 92f34a5e4027a1dc39efd8ce63cf6aba, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::NanoBrainComponent
|
m_EditorClassIdentifier: Assembly-CSharp::NanoBrainComponent
|
||||||
brain: {fileID: 11400000, guid: af8d90b8b4b9dcad7837130c4143d91c, type: 2}
|
defaultBrain: {fileID: 11400000, guid: fc1a4800a8c531eb4855b436bc9084ae, type: 2}
|
||||||
|
|||||||
@ -17,86 +17,36 @@ MonoBehaviour:
|
|||||||
color: {r: 1, g: 1, b: 1, a: 1}
|
color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
texture: {fileID: 0}
|
texture: {fileID: 0}
|
||||||
nuclei:
|
nuclei:
|
||||||
- id: -1753291412
|
- id: -1707533328
|
||||||
_name: Root
|
_name: Root
|
||||||
synapses:
|
synapses:
|
||||||
- nucleusId: 237822944
|
- nucleusId: -112538112
|
||||||
weight: 1
|
weight: 1
|
||||||
receivers: []
|
receivers: []
|
||||||
- id: 472852910
|
nucleusType:
|
||||||
_name: Perception
|
average: 0
|
||||||
synapses: []
|
inverse: 0
|
||||||
receivers: []
|
exponent: 1
|
||||||
- id: 237822944
|
- id: -112538112
|
||||||
_name: Avoidance
|
_name: Avoidance
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: -1753291412
|
|
||||||
- id: 983561152
|
|
||||||
_name: 'Boundary: position'
|
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: -1818801134
|
|
||||||
- id: -1818801134
|
|
||||||
_name: 'Boundary: velocity'
|
|
||||||
synapses:
|
synapses:
|
||||||
- nucleusId: 983561152
|
- nucleusId: 407735232
|
||||||
weight: 1
|
weight: -1
|
||||||
receivers: []
|
receivers:
|
||||||
- id: 1386590800
|
- nucleusId: -1707533328
|
||||||
_name: 'Boundary: position'
|
nucleusType:
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
perceptei:
|
||||||
|
- id: 407735232
|
||||||
|
_name: Boundary
|
||||||
synapses: []
|
synapses: []
|
||||||
receivers:
|
receivers:
|
||||||
- nucleusId: -1415771486
|
- nucleusId: -112538112
|
||||||
- nucleusId: 237822944
|
nucleusType: Perceptoid
|
||||||
- id: -1415771486
|
average: 0
|
||||||
_name: 'Boundary: velocity'
|
inverse: 0
|
||||||
synapses:
|
exponent: 1
|
||||||
- nucleusId: 1386590800
|
thingType: 1
|
||||||
weight: 1
|
rootId: -1707533328
|
||||||
receivers: []
|
|
||||||
- id: -213085248
|
|
||||||
_name: 'Boundary: position'
|
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: 1279519762
|
|
||||||
- nucleusId: 237822944
|
|
||||||
- id: 1279519762
|
|
||||||
_name: 'Boundary: velocity'
|
|
||||||
synapses:
|
|
||||||
- nucleusId: -213085248
|
|
||||||
weight: 1
|
|
||||||
receivers: []
|
|
||||||
- id: 1783940116
|
|
||||||
_name: 'Boundary: position'
|
|
||||||
synapses: []
|
|
||||||
receivers:
|
|
||||||
- nucleusId: -1018422170
|
|
||||||
- nucleusId: 237822944
|
|
||||||
- id: -1018422170
|
|
||||||
_name: 'Boundary: velocity'
|
|
||||||
synapses:
|
|
||||||
- nucleusId: 1783940116
|
|
||||||
weight: 1
|
|
||||||
receivers: []
|
|
||||||
rootId: -1753291412
|
|
||||||
perception:
|
|
||||||
id: 2139386530
|
|
||||||
_name: Perception
|
|
||||||
synapses: []
|
|
||||||
receivers: []
|
|
||||||
positionReceivers:
|
|
||||||
- thingType: 0
|
|
||||||
neuroid:
|
|
||||||
id: 237822944
|
|
||||||
_name: Avoidance
|
|
||||||
synapses:
|
|
||||||
- nucleusId: 1386590800
|
|
||||||
weight: 1
|
|
||||||
- nucleusId: -213085248
|
|
||||||
weight: 1
|
|
||||||
- nucleusId: 1783940116
|
|
||||||
weight: 1
|
|
||||||
receivers:
|
|
||||||
- nucleusId: -1753291412
|
|
||||||
velocityReceivers: []
|
|
||||||
|
|||||||
@ -13,32 +13,21 @@ public class Boid : MonoBehaviour {
|
|||||||
private Bounds innerBounds;
|
private Bounds innerBounds;
|
||||||
|
|
||||||
public NanoBrainComponent nanoBrain;
|
public NanoBrainComponent nanoBrain;
|
||||||
|
public Receptor boundaryReceptor;
|
||||||
// public NanoBrain neuroidNet;
|
public Receptor boidReceptor;
|
||||||
// public Perception perception;
|
|
||||||
|
|
||||||
// public Nucleus behaviour;
|
|
||||||
|
|
||||||
// public Neuroid totalForce;
|
|
||||||
|
|
||||||
public int id;
|
public int id;
|
||||||
|
|
||||||
void Awake() {
|
void Awake() {
|
||||||
nanoBrain = GetComponent<NanoBrainComponent>();
|
|
||||||
this.id = this.GetInstanceID();
|
this.id = this.GetInstanceID();
|
||||||
|
|
||||||
|
nanoBrain = GetComponent<NanoBrainComponent>();
|
||||||
|
boundaryReceptor = Perceptoid.GetReceptor(nanoBrain.brain, BoundaryType);
|
||||||
|
boidReceptor = Perceptoid.GetReceptor(nanoBrain.brain, BoidType);
|
||||||
|
|
||||||
sc = FindFirstObjectByType<SwarmControl>();
|
sc = FindFirstObjectByType<SwarmControl>();
|
||||||
|
|
||||||
innerBounds = new(sc.transform.position, sc.spaceSize - 2 * sc.boundaryWidth);
|
innerBounds = new(sc.transform.position, sc.spaceSize - 2 * sc.boundaryWidth);
|
||||||
|
|
||||||
// neuroidNet = GetComponent<NanoBrain>();
|
|
||||||
// perception = new Perception(neuroidNet);
|
|
||||||
|
|
||||||
// //behaviour = new Roaming(neuroidNet, perception, sc);
|
|
||||||
// behaviour = new Swarming(neuroidNet, perception, sc);
|
|
||||||
|
|
||||||
// totalForce = new(neuroidNet, "Total");
|
|
||||||
// behaviour.AddReceiver(totalForce);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
@ -52,8 +41,9 @@ public class Boid : MonoBehaviour {
|
|||||||
Vector3 localPosition = this.transform.InverseTransformPoint(neighbour.transform.position);
|
Vector3 localPosition = this.transform.InverseTransformPoint(neighbour.transform.position);
|
||||||
//Debug.DrawRay(this.transform.position, this.transform.TransformDirection(localPosition), Color.magenta);
|
//Debug.DrawRay(this.transform.position, this.transform.TransformDirection(localPosition), Color.magenta);
|
||||||
|
|
||||||
int thingId = neighbour.GetInstanceID();
|
//int thingId = neighbour.GetInstanceID();
|
||||||
nanoBrain.perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name);
|
// nanoBrain.perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name);
|
||||||
|
boidReceptor.position = localPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +52,9 @@ public class Boid : MonoBehaviour {
|
|||||||
Vector3 pointOnBounds = innerBounds.ClosestPoint(point);
|
Vector3 pointOnBounds = innerBounds.ClosestPoint(point);
|
||||||
Vector3 desiredWorldSpace = (pointOnBounds - point).normalized * sc.speed;
|
Vector3 desiredWorldSpace = (pointOnBounds - point).normalized * sc.speed;
|
||||||
Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace);
|
Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace);
|
||||||
nanoBrain.perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
|
boundaryReceptor.position = desiredLocalSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Vector3 worldForce = this.transform.TransformDirection(behaviour.outputValue);
|
|
||||||
Vector3 worldForce = this.transform.TransformDirection(nanoBrain.root.outputValue);
|
Vector3 worldForce = this.transform.TransformDirection(nanoBrain.root.outputValue);
|
||||||
|
|
||||||
this.velocity = (1 - sc.inertia) * (worldForce * Time.deltaTime) + sc.inertia * velocity;
|
this.velocity = (1 - sc.inertia) * (worldForce * Time.deltaTime) + sc.inertia * velocity;
|
||||||
@ -82,7 +71,6 @@ public class Boid : MonoBehaviour {
|
|||||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f); // Adjust the speed of rotation
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f); // Adjust the speed of rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
//neuroidNet.UpdateNeurons();
|
|
||||||
nanoBrain.brain.UpdateNuclei();
|
nanoBrain.brain.UpdateNuclei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ public class Roaming : Nucleus {
|
|||||||
|
|
||||||
public Neuroid output;
|
public Neuroid output;
|
||||||
|
|
||||||
public Roaming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base(null, "Roaming nucleus") {
|
public Roaming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base("Roaming nucleus") {
|
||||||
avoidance = new(brain, "Avoidance") { inverse = true };
|
avoidance = new(brain, "Avoidance") { inverse = true };
|
||||||
perception.SendPositions(avoidance, Boid.BoundaryType);
|
perception.SendPositions(avoidance, Boid.BoundaryType);
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ public class Swarming : Nucleus {
|
|||||||
|
|
||||||
public override Vector3 outputValue { get => output.outputValue; set => output.outputValue = value; }
|
public override Vector3 outputValue { get => output.outputValue; set => output.outputValue = value; }
|
||||||
|
|
||||||
public Swarming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base(null, "Swarming Nucleus") {
|
public Swarming(NanoBrainObj brain, Perception perception, SwarmControl sc) : base("Swarming Nucleus") {
|
||||||
this.cohesion = new(brain, "Cohesion") { inverse = false };
|
this.cohesion = new(brain, "Cohesion") { inverse = false };
|
||||||
perception.SendPositions(this.cohesion, Boid.BoidType);
|
perception.SendPositions(this.cohesion, Boid.BoidType);
|
||||||
|
|
||||||
|
|||||||
88
Assets/Scenes/Boids/SwarmingBrain.asset
Normal file
88
Assets/Scenes/Boids/SwarmingBrain.asset
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 36081359186edfec998d891a1feeb17b, type: 3}
|
||||||
|
m_Name: SwarmingBrain
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::NanoBrainObj
|
||||||
|
title:
|
||||||
|
count: 0
|
||||||
|
color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
texture: {fileID: 0}
|
||||||
|
nuclei:
|
||||||
|
- id: -1707533328
|
||||||
|
_name: Root
|
||||||
|
synapses:
|
||||||
|
- nucleusId: -112538112
|
||||||
|
weight: 1
|
||||||
|
- nucleusId: 1938577052
|
||||||
|
weight: 1
|
||||||
|
receivers: []
|
||||||
|
nucleusType:
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
- id: -112538112
|
||||||
|
_name: Avoidance
|
||||||
|
synapses:
|
||||||
|
- nucleusId: 407735232
|
||||||
|
weight: -1
|
||||||
|
receivers:
|
||||||
|
- nucleusId: -1707533328
|
||||||
|
nucleusType:
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
- id: 1938577052
|
||||||
|
_name: Cohesion
|
||||||
|
synapses:
|
||||||
|
- nucleusId: -1408496896
|
||||||
|
weight: 1
|
||||||
|
- nucleusId: -133566816
|
||||||
|
weight: 1
|
||||||
|
receivers:
|
||||||
|
- nucleusId: -1707533328
|
||||||
|
nucleusType:
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
perceptei:
|
||||||
|
- id: 407735232
|
||||||
|
_name: Boundary
|
||||||
|
synapses: []
|
||||||
|
receivers:
|
||||||
|
- nucleusId: -112538112
|
||||||
|
nucleusType: Perceptoid
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
thingType: 1
|
||||||
|
- id: -1408496896
|
||||||
|
_name: Boid1
|
||||||
|
synapses: []
|
||||||
|
receivers:
|
||||||
|
- nucleusId: 1938577052
|
||||||
|
nucleusType: Perceptoid
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
thingType: 2
|
||||||
|
- id: -133566816
|
||||||
|
_name: Boid2
|
||||||
|
synapses: []
|
||||||
|
receivers:
|
||||||
|
- nucleusId: 27651644
|
||||||
|
- nucleusId: 1938577052
|
||||||
|
nucleusType: Perceptoid
|
||||||
|
average: 0
|
||||||
|
inverse: 0
|
||||||
|
exponent: 1
|
||||||
|
thingType: 2
|
||||||
|
rootId: -1707533328
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 55099766f6f09071ab4e8c89b02fa302
|
guid: fc1a4800a8c531eb4855b436bc9084ae
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
mainObjectFileID: 11400000
|
||||||
Loading…
x
Reference in New Issue
Block a user