More nucleus like neurons
This commit is contained in:
parent
88bf20b9c2
commit
9a6ae0e071
@ -5,13 +5,13 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
public class NeuroidLayer {
|
public class NeuroidLayer {
|
||||||
public int ix = 0;
|
public int ix = 0;
|
||||||
public List<Neuroid> neuroids = new();
|
public List<Nucleus> neuroids = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GraphEditorWindow : EditorWindow {
|
public class GraphEditorWindow : EditorWindow {
|
||||||
private Neuroid currentNeuroid;
|
private Nucleus currentNucleus;
|
||||||
private List<Neuroid> allNeuroids;
|
private List<Neuroid> allNeuroids;
|
||||||
private Dictionary<Neuroid, Vector2Int> neuroidPositions = new();
|
private Dictionary<Nucleus, Vector2Int> neuroidPositions = new();
|
||||||
|
|
||||||
private List<NeuroidLayer> layers = new();
|
private List<NeuroidLayer> layers = new();
|
||||||
|
|
||||||
@ -21,7 +21,58 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
SelectNeuron();
|
SelectNeuron();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildLayers(List<Neuroid> neuroids) {
|
private void AddToLayer(NeuroidLayer layer, Nucleus nucleus) {
|
||||||
|
layer.neuroids.Add(nucleus);
|
||||||
|
nucleus.layerIx = layer.ix;
|
||||||
|
// Store its position
|
||||||
|
Vector2Int neuroidPosition = new(layer.ix, layer.neuroids.Count - 1);
|
||||||
|
neuroidPositions[nucleus] = neuroidPosition;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildLayers() {
|
||||||
|
// A temporary list to track what's been added to layers
|
||||||
|
this.layers = new();
|
||||||
|
int layerIx = 0;
|
||||||
|
|
||||||
|
Nucleus selectedNucleus = this.currentNucleus;
|
||||||
|
NeuroidLayer currentLayer = new() { ix = layerIx };
|
||||||
|
|
||||||
|
foreach (Neuroid outputNeuroid in selectedNucleus.outputNeuroids) {
|
||||||
|
if (outputNeuroid != null) {
|
||||||
|
AddToLayer(currentLayer, outputNeuroid);
|
||||||
|
Debug.Log($"layer {layerIx} nucleus {outputNeuroid.name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentLayer.neuroids.Count > 0) {
|
||||||
|
this.layers.Add(currentLayer);
|
||||||
|
layerIx++;
|
||||||
|
currentLayer = new() { ix = layerIx };
|
||||||
|
}
|
||||||
|
|
||||||
|
AddToLayer(currentLayer, selectedNucleus);
|
||||||
|
this.layers.Add(currentLayer);
|
||||||
|
Debug.Log($"layer {layerIx} nucleus {selectedNucleus.name}");
|
||||||
|
|
||||||
|
layerIx++;
|
||||||
|
currentLayer = new() { ix = layerIx };
|
||||||
|
|
||||||
|
int six = 0;
|
||||||
|
foreach (Synapse synapse in selectedNucleus.synapses.Values) {
|
||||||
|
Debug.Log($"Synapse {six}");
|
||||||
|
Nucleus input = synapse.neuroid;
|
||||||
|
if (input != null) {
|
||||||
|
AddToLayer(currentLayer, input);
|
||||||
|
Debug.Log($"layer {layerIx} nucleus {input.name}");
|
||||||
|
}
|
||||||
|
six++;
|
||||||
|
}
|
||||||
|
if (currentLayer.neuroids.Count > 0) {
|
||||||
|
this.layers.Add(currentLayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildLayers_old(List<Neuroid> neuroids) {
|
||||||
if (neuroids == null)
|
if (neuroids == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -41,10 +92,11 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
if (neuronVisited.Contains(neuroid))
|
if (neuronVisited.Contains(neuroid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (neuroid.IsStale()) {
|
// if (neuroid.IsStale()) {
|
||||||
neuronVisited.Add(neuroid);
|
// Debug.Log($"neuron {neuroid.name} is stale {neuroid.stale}");
|
||||||
continue;
|
// neuronVisited.Add(neuroid);
|
||||||
}
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
// If the output neuroid is visited
|
// If the output neuroid is visited
|
||||||
// Note: this does not yet work for multiple outputs yet (see the use of First())
|
// Note: this does not yet work for multiple outputs yet (see the use of First())
|
||||||
@ -92,7 +144,7 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void DrawGraph() {
|
private void DrawGraph() {
|
||||||
if (currentNeuroid == null)
|
if (currentNucleus == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (NeuroidLayer layer in layers)
|
foreach (NeuroidLayer layer in layers)
|
||||||
@ -103,25 +155,29 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
int column = layer.ix * 100;
|
int column = layer.ix * 100;
|
||||||
int nodeCount = layer.neuroids.Count;
|
int nodeCount = layer.neuroids.Count;
|
||||||
float maxValue = 0;
|
float maxValue = 0;
|
||||||
foreach (Neuroid neuroid in layer.neuroids) {
|
foreach (Nucleus nucleus in layer.neuroids) {
|
||||||
|
if (nucleus is Neuroid neuroid) {
|
||||||
float value = neuroid.outputValue.magnitude;
|
float value = neuroid.outputValue.magnitude;
|
||||||
if (value > maxValue)
|
if (value > maxValue)
|
||||||
maxValue = value;
|
maxValue = value;
|
||||||
}
|
}
|
||||||
float spacing = 200f / nodeCount;
|
}
|
||||||
|
float spacing = 400f / nodeCount;
|
||||||
float margin = 100 + spacing / 2;
|
float margin = 100 + spacing / 2;
|
||||||
foreach (Neuroid layerNeuroid in layer.neuroids) {
|
foreach (Nucleus layerNucleus in layer.neuroids) {
|
||||||
|
if (layerNucleus is Neuroid layerNeuroid) {
|
||||||
Vector2Int layerNeuroidPos = this.neuroidPositions[layerNeuroid];
|
Vector2Int layerNeuroidPos = this.neuroidPositions[layerNeuroid];
|
||||||
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);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
float inputSpacing = 200f / layerNeuroid.synapses.Count;
|
float inputSpacing = 400f / layerNeuroid.synapses.Count;
|
||||||
float inputMargin = 100 + inputSpacing / 2;
|
float inputMargin = 100 + inputSpacing / 2;
|
||||||
foreach (Synapse synapse in layerNeuroid.synapses.Values) {
|
foreach (Synapse synapse in layerNeuroid.synapses.Values) {
|
||||||
if (synapse.neuroid != null) {
|
if (synapse.neuroid != null) {
|
||||||
if (this.neuroidPositions.ContainsKey(synapse.neuroid)) {
|
if (this.neuroidPositions.ContainsKey(synapse.neuroid)) {
|
||||||
|
|
||||||
Vector2Int inputNeuroidPos = this.neuroidPositions[synapse.neuroid];
|
Vector2Int inputNeuroidPos = this.neuroidPositions[synapse.neuroid];
|
||||||
|
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
||||||
Vector3 pos = new(100 + inputNeuroidPos.x * 100, inputMargin + inputNeuroidPos.y * inputSpacing, 0.0f);
|
Vector3 pos = new(100 + inputNeuroidPos.x * 100, inputMargin + inputNeuroidPos.y * inputSpacing, 0.0f);
|
||||||
|
|
||||||
float brightness = synapse.weight / 10.0f;
|
float brightness = synapse.weight / 10.0f;
|
||||||
@ -130,28 +186,56 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float size = layerNeuroid.outputValue.magnitude / maxValue * 20;
|
float size = 20;
|
||||||
if (layerNeuroid.IsStale())
|
if (layerNeuroid.IsStale())
|
||||||
Handles.color = Color.yellow;
|
Handles.color = Color.black;
|
||||||
else
|
else {
|
||||||
Handles.color = Color.white;
|
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
||||||
|
Handles.color = new Color(brightness, brightness, brightness);
|
||||||
|
}
|
||||||
Handles.DrawSolidDisc(parentPos, Vector3.forward, size);
|
Handles.DrawSolidDisc(parentPos, Vector3.forward, size);
|
||||||
Rect neuronRect = new(parentPos.x - size, parentPos.y - size, size * 2, size * 2);
|
Vector3 labelPos = parentPos - Vector3.down * (size + 0.2f); // below disc along up axis
|
||||||
if (neuronRect.Contains(Event.current.mousePosition))
|
GUIStyle style = new GUIStyle(EditorStyles.label) {
|
||||||
HandleMouseHover(layerNeuroid, neuronRect);
|
alignment = TextAnchor.UpperCenter,
|
||||||
i++;
|
normal = { textColor = Color.white },
|
||||||
|
fontStyle = FontStyle.Bold
|
||||||
|
};
|
||||||
|
Handles.Label(labelPos, layerNeuroid.name, style);
|
||||||
|
|
||||||
|
Rect neuronRect = new(parentPos.x - size, parentPos.y - size, size * 2, size * 2);
|
||||||
|
Event e = Event.current;
|
||||||
|
if (e != null && neuronRect.Contains(e.mousePosition)) {
|
||||||
|
HandleMouseHover(layerNeuroid, neuronRect);
|
||||||
|
// Process click
|
||||||
|
if (e.type == EventType.MouseDown && e.button == 0) {
|
||||||
|
// Consume the event so the scene doesn't also handle it
|
||||||
|
e.Use();
|
||||||
|
HandleDiscClicked(layerNeuroid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleMouseHover(Neuroid neuroid, Rect rect) {
|
private void HandleMouseHover(Neuroid neuroid, Rect rect) {
|
||||||
// Draw the tooltip
|
GUIContent tooltip;
|
||||||
GUIContent tooltip = new(
|
if (neuroid is SensoryNeuroid sensoryNeuroid) {
|
||||||
|
tooltip = new(
|
||||||
|
$"{sensoryNeuroid.name}" +
|
||||||
|
$"\nThing {sensoryNeuroid.receptor.thingId}" +
|
||||||
|
$"\nValue: {neuroid.outputValue}" +
|
||||||
|
$"\nStale: {neuroid.stale}");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tooltip = new(
|
||||||
$"{neuroid.name}" +
|
$"{neuroid.name}" +
|
||||||
$"\nsynapse count {neuroid.synapses.Count}" +
|
$"\nsynapse count {neuroid.synapses.Count}" +
|
||||||
$"\nValue: {neuroid.outputValue}" +
|
$"\nValue: {neuroid.outputValue}" +
|
||||||
$"\nStale: {neuroid.stale}");
|
$"\nStale: {neuroid.stale}");
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 mousePosition = Event.current.mousePosition;
|
Vector2 mousePosition = Event.current.mousePosition;
|
||||||
|
|
||||||
@ -162,6 +246,10 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
GUI.Box(tooltipRect, tooltip);
|
GUI.Box(tooltipRect, tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleDiscClicked(Nucleus nucleus) {
|
||||||
|
this.currentNucleus = nucleus;
|
||||||
|
BuildLayers();
|
||||||
|
}
|
||||||
|
|
||||||
// Update node colors based on selected GameObjects
|
// Update node colors based on selected GameObjects
|
||||||
private void SelectNeuron() {
|
private void SelectNeuron() {
|
||||||
@ -175,15 +263,15 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Neuroid neuroid = boid.totalForce;
|
Neuroid neuroid = boid.totalForce;
|
||||||
this.currentNeuroid = neuroid;
|
this.currentNucleus = neuroid;
|
||||||
if (neuroid == null)
|
if (neuroid == null)
|
||||||
this.allNeuroids = new();
|
this.allNeuroids = new();
|
||||||
else
|
else
|
||||||
this.allNeuroids = neuroid.net.neuroids;
|
this.allNeuroids = neuroid.net.neuroids;
|
||||||
|
|
||||||
|
|
||||||
//Debug.Log($"Neuroncount = {this.allNeuroids.Count}");
|
Debug.Log($"Neuroncount = {this.allNeuroids.Count}");
|
||||||
BuildLayers(this.allNeuroids);
|
BuildLayers();
|
||||||
Debug.Log($"Layercount = {this.layers.Count}");
|
Debug.Log($"Layercount = {this.layers.Count}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,12 +3,12 @@ using UnityEngine;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
public class Synapse {
|
public class Synapse {
|
||||||
public Synapse(Neuroid neuroid, Vector3 value, float weight) {
|
public Synapse(Nucleus neuroid, Vector3 value, float weight) {
|
||||||
this.neuroid = neuroid;
|
this.neuroid = neuroid;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
}
|
}
|
||||||
public Neuroid neuroid;
|
public Nucleus neuroid;
|
||||||
public Vector3 value;
|
public Vector3 value;
|
||||||
public float weight;
|
public float weight;
|
||||||
}
|
}
|
||||||
@ -24,19 +24,16 @@ public class NeuroidNetwork {
|
|||||||
public void Update() {
|
public void Update() {
|
||||||
foreach (Neuroid neuroid in neuroids) {
|
foreach (Neuroid neuroid in neuroids) {
|
||||||
neuroid.stale++;
|
neuroid.stale++;
|
||||||
|
if (neuroid.IsStale())
|
||||||
|
neuroid.outputValue = Vector3.zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Neuroid : Nucleus {
|
public class Neuroid : Nucleus {
|
||||||
public string name;
|
|
||||||
|
|
||||||
public int stale = 0;
|
public int stale = 0;
|
||||||
|
|
||||||
// public readonly Dictionary<Neuroid, Synapse> synapses = new();
|
//public Vector3 outputValue;
|
||||||
|
|
||||||
public Vector3 outputValue;
|
|
||||||
// public HashSet<Neuroid> outputNeuroids = new();
|
|
||||||
|
|
||||||
public bool average = false;
|
public bool average = false;
|
||||||
//public bool quadratic = false;
|
//public bool quadratic = false;
|
||||||
@ -45,11 +42,12 @@ public class Neuroid : Nucleus {
|
|||||||
|
|
||||||
public NeuroidNetwork net;
|
public NeuroidNetwork net;
|
||||||
|
|
||||||
public Neuroid(NeuroidNetwork net, string name) : base(net) {
|
public Neuroid(NeuroidNetwork net, string name) : base(name) {
|
||||||
this.net = net;
|
this.net = net;
|
||||||
this.name = name;
|
|
||||||
if (this.net != null)
|
if (this.net != null)
|
||||||
this.net.neuroids.Add(this);
|
this.net.neuroids.Add(this);
|
||||||
|
else
|
||||||
|
Debug.LogError("No neuroid network");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSynapse(Neuroid input) {
|
public void AddSynapse(Neuroid input) {
|
||||||
@ -129,8 +127,14 @@ public class Neuroid : Nucleus {
|
|||||||
protected virtual void UpdateState() {
|
protected virtual void UpdateState() {
|
||||||
Vector3 result = Vector3.zero;
|
Vector3 result = Vector3.zero;
|
||||||
foreach (Synapse synapse in this.synapses.Values) {
|
foreach (Synapse synapse in this.synapses.Values) {
|
||||||
|
// if (synapse.neuroid == null)
|
||||||
|
// continue;
|
||||||
Vector3 direction = synapse.value.normalized;
|
Vector3 direction = synapse.value.normalized;
|
||||||
float magnitude = synapse.value.magnitude;
|
float magnitude = synapse.value.magnitude;
|
||||||
|
|
||||||
|
// Vector3 direction = synapse.neuroid.outputValue.normalized;
|
||||||
|
// float magnitude = synapse.neuroid.outputValue.magnitude;
|
||||||
|
|
||||||
magnitude = synapse.weight * Mathf.Pow(magnitude, exponent);
|
magnitude = synapse.weight * Mathf.Pow(magnitude, exponent);
|
||||||
if (inverse)
|
if (inverse)
|
||||||
magnitude = 1 / magnitude;
|
magnitude = 1 / magnitude;
|
||||||
|
|||||||
@ -1,26 +1,21 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
public class Nucleus {
|
public class Nucleus {
|
||||||
//public Neuroid output;
|
public string name;
|
||||||
public readonly Dictionary<Neuroid, Synapse> synapses = new();
|
|
||||||
|
|
||||||
|
public readonly Dictionary<Nucleus, Synapse> synapses = new();
|
||||||
public HashSet<Neuroid> outputNeuroids = new();
|
public HashSet<Neuroid> outputNeuroids = new();
|
||||||
|
public virtual Vector3 outputValue {get; set; }
|
||||||
|
|
||||||
public int layerIx;
|
public int layerIx;
|
||||||
|
|
||||||
|
public Nucleus(string name) {
|
||||||
public Nucleus(NeuroidNetwork neuroidNet) {
|
this.name = name;
|
||||||
//this.output = new(neuroidNet, "Nucleus output");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddReceiver(Neuroid receiver) {
|
public virtual void AddReceiver(Neuroid receiver) {
|
||||||
//this.output.AddReceiver(receiver);
|
|
||||||
this.outputNeuroids.Add(receiver);
|
this.outputNeuroids.Add(receiver);
|
||||||
|
receiver.synapses[this] = new(this, Vector3.zero, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void GetInputFrom(Neuroid input, float weight = 1.0f) {
|
|
||||||
// input.AddReceiver(this);
|
|
||||||
// this.synapses[input] = new(input, Vector3.zero, weight);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -15,7 +15,7 @@ public class Perception : Nucleus {
|
|||||||
public HashSet<Receiver> positionReceivers { get; protected set; }
|
public HashSet<Receiver> positionReceivers { get; protected set; }
|
||||||
public HashSet<Receiver> velocityReceivers { get; protected set; }
|
public HashSet<Receiver> velocityReceivers { get; protected set; }
|
||||||
|
|
||||||
public Perception(NeuroidNetwork neuroidNet) : base(neuroidNet) {
|
public Perception(NeuroidNetwork neuroidNet) : base("Perception") {
|
||||||
this.neuroidNet = neuroidNet;
|
this.neuroidNet = neuroidNet;
|
||||||
this.positionReceivers = new();
|
this.positionReceivers = new();
|
||||||
this.velocityReceivers = new();
|
this.velocityReceivers = new();
|
||||||
@ -48,9 +48,9 @@ public class Perception : Nucleus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessStimulus(int thingId, int thingType, Vector3 localPosition) {
|
public void ProcessStimulus(int thingId, int thingType, Vector3 localPosition, string name = "Sensing") {
|
||||||
int availableIx = -1;
|
int availableIx = -1;
|
||||||
SensoryNeuroid leastInterestingNeuroid = null;
|
int leastInterestingIx = -1;
|
||||||
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
||||||
if (sensoryNeuroids[i] == null || sensoryNeuroids[i].IsStale())
|
if (sensoryNeuroids[i] == null || sensoryNeuroids[i].IsStale())
|
||||||
availableIx = i;
|
availableIx = i;
|
||||||
@ -59,19 +59,16 @@ public class Perception : Nucleus {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sensoryNeuroids[i] != null) {
|
if (sensoryNeuroids[i] != null) {
|
||||||
if (leastInterestingNeuroid == null || leastInterestingNeuroid.receptor.position.magnitude > sensoryNeuroids[i].receptor.position.magnitude)
|
if (leastInterestingIx == -1 || sensoryNeuroids[leastInterestingIx].receptor.position.magnitude > sensoryNeuroids[i].receptor.position.magnitude)
|
||||||
leastInterestingNeuroid = sensoryNeuroids[i];
|
leastInterestingIx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (availableIx == -1)
|
||||||
|
availableIx = leastInterestingIx;
|
||||||
|
|
||||||
if (availableIx != -1) {
|
if (availableIx != -1) {
|
||||||
if (sensoryNeuroids[availableIx] != null) {
|
|
||||||
// Debug.Log($"revived receptor {availableIx} for {thingId}");
|
|
||||||
sensoryNeuroids[availableIx].receptor.thingId = thingId;
|
|
||||||
sensoryNeuroids[availableIx].receptor.position = localPosition;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Debug.Log($"new receptor for {thingId}");
|
// Debug.Log($"new receptor for {thingId}");
|
||||||
SensoryNeuroid neuroid = new(neuroidNet, thingId);
|
SensoryNeuroid neuroid = new(neuroidNet, thingId) { name = name };
|
||||||
foreach (Receiver receiver in positionReceivers) {
|
foreach (Receiver receiver in positionReceivers) {
|
||||||
if (receiver.thingType == 0 || receiver.thingType == thingType)
|
if (receiver.thingType == 0 || receiver.thingType == thingType)
|
||||||
receiver.neuroid.GetInputFrom(neuroid);
|
receiver.neuroid.GetInputFrom(neuroid);
|
||||||
@ -85,14 +82,6 @@ public class Perception : Nucleus {
|
|||||||
neuroid.receptor.position = localPosition;
|
neuroid.receptor.position = localPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (leastInterestingNeuroid != null) {
|
|
||||||
//Debug.Log($"replaced receptor {leastInterestingNeuroid.thingId} for {thingId}");
|
|
||||||
leastInterestingNeuroid.receptor.thingId = thingId;
|
|
||||||
leastInterestingNeuroid.receptor.position = localPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug.LogWarning($"No available receptor for {id}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveStimulus(int thingId) {
|
public void RemoveStimulus(int thingId) {
|
||||||
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
||||||
|
|||||||
@ -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: 2
|
||||||
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
|
||||||
|
|||||||
@ -21,15 +21,10 @@ public class Boid : MonoBehaviour {
|
|||||||
private Bounds innerBounds;
|
private Bounds innerBounds;
|
||||||
private Bounds outerBounds;
|
private Bounds outerBounds;
|
||||||
|
|
||||||
readonly Collider[] results = new Collider[10];
|
|
||||||
|
|
||||||
public NeuroidNetwork neuroidNet = new();
|
public NeuroidNetwork neuroidNet = new();
|
||||||
public Perception perception;
|
public Perception perception;
|
||||||
public Neuroid cohesion;
|
|
||||||
public Neuroid alignment;
|
public Nucleus behaviour;
|
||||||
public Neuroid avoidance;
|
|
||||||
// public Neuroid boundary;
|
|
||||||
public Roaming roaming;
|
|
||||||
|
|
||||||
public Neuroid totalForce;
|
public Neuroid totalForce;
|
||||||
|
|
||||||
@ -45,53 +40,34 @@ public class Boid : MonoBehaviour {
|
|||||||
|
|
||||||
perception = new Perception(neuroidNet);
|
perception = new Perception(neuroidNet);
|
||||||
|
|
||||||
// cohesion = new(neuroidNet, "Cohesion");
|
//behaviour = new Roaming(neuroidNet, perception, sc);
|
||||||
// perception.SendPositions(cohesion, 1.0f, BoidType);
|
behaviour = new Swarming(neuroidNet, perception, sc);
|
||||||
|
|
||||||
// alignment = new(neuroidNet, "Alignment") { average = true };
|
|
||||||
// perception.SendVelocities(alignment);
|
|
||||||
|
|
||||||
// avoidance = new(neuroidNet, "Separation") { inverse = true };
|
|
||||||
// perception.SendPositions(avoidance, sc.avoidanceForce);
|
|
||||||
|
|
||||||
//boundary = new(neuroidNet, "Boundary");
|
|
||||||
|
|
||||||
roaming = new(neuroidNet, perception, sc);
|
|
||||||
|
|
||||||
totalForce = new(neuroidNet, "Total");
|
totalForce = new(neuroidNet, "Total");
|
||||||
//totalForce.GetInputFrom(alignment, sc.alignmentForce);
|
behaviour.AddReceiver(totalForce);
|
||||||
//totalForce.GetInputFrom(cohesion, sc.cohesionForce);
|
|
||||||
// totalForce.GetInputFrom(avoidance, -sc.avoidanceForce);
|
|
||||||
//totalForce.GetInputFrom(boundary, sc.boundaryForce);
|
|
||||||
roaming.AddReceiver(totalForce);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
// Physics.OverlapSphereNonAlloc(this.transform.position, sc.perceptionDistance, results);
|
Collider[] results = Physics.OverlapSphere(this.transform.position, sc.perceptionDistance);
|
||||||
// foreach (Collider c in results) {
|
foreach (Collider c in results) {
|
||||||
// if (c == null)
|
if (c as CapsuleCollider != null) {
|
||||||
// continue;
|
Boid neighbour = c.GetComponentInParent<Boid>();
|
||||||
|
if (neighbour == null || neighbour == this)
|
||||||
|
continue;
|
||||||
|
|
||||||
// if (c as CapsuleCollider != null) {
|
Vector3 localPosition = neighbour.transform.position - this.transform.position;
|
||||||
// Boid neighbour = c.GetComponentInParent<Boid>();
|
|
||||||
// if (neighbour == null || neighbour == this)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
// Vector3 localPosition = neighbour.transform.position - this.transform.position;
|
int thingId = neighbour.GetInstanceID();
|
||||||
// if (debug)
|
perception.ProcessStimulus(thingId, BoidType, localPosition); //, neighbour.gameObject.name);
|
||||||
// Debug.Log($" distance {localPosition.magnitude}");
|
}
|
||||||
|
}
|
||||||
// int thingId = neighbour.GetInstanceID();
|
|
||||||
// perception.ProcessStimulus(thingId, localPosition);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!innerBounds.Contains(this.transform.position)) {
|
if (!innerBounds.Contains(this.transform.position)) {
|
||||||
Vector3 point = this.transform.position;
|
Vector3 point = this.transform.position;
|
||||||
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);
|
||||||
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace);
|
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
perception.RemoveStimulus(777);
|
perception.RemoveStimulus(777);
|
||||||
|
|||||||
@ -1,18 +1,11 @@
|
|||||||
public class Roaming : Nucleus {
|
public class Roaming : Nucleus {
|
||||||
public float avoidanceForce;
|
|
||||||
public Neuroid avoidance;
|
public Neuroid avoidance;
|
||||||
|
|
||||||
public Neuroid output;
|
public Neuroid output;
|
||||||
|
|
||||||
|
public Roaming(NeuroidNetwork neuroidNet, Perception perception, SwarmControl sc) : base("Roaming nucleus") {
|
||||||
public const int BoundaryType = 1;
|
|
||||||
public const int BoidType = 2;
|
|
||||||
|
|
||||||
public Roaming(NeuroidNetwork neuroidNet, Perception perception, SwarmControl sc) : base(neuroidNet) {
|
|
||||||
this.avoidanceForce = sc.avoidanceForce;
|
|
||||||
|
|
||||||
avoidance = new(neuroidNet, "Avoidance") { inverse = true };
|
avoidance = new(neuroidNet, "Avoidance") { inverse = true };
|
||||||
perception.SendPositions(avoidance);
|
perception.SendPositions(avoidance, 1.0f, 1);
|
||||||
|
|
||||||
this.output = new(neuroidNet, "Roaming");
|
this.output = new(neuroidNet, "Roaming");
|
||||||
output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
||||||
|
|||||||
@ -1,31 +1,34 @@
|
|||||||
public class Swarming : Nucleus {
|
using UnityEngine;
|
||||||
//public Perception perception;
|
|
||||||
|
|
||||||
|
public class Swarming : Nucleus {
|
||||||
public Neuroid cohesion;
|
public Neuroid cohesion;
|
||||||
public Neuroid alignment;
|
public Neuroid alignment;
|
||||||
public Neuroid avoidance;
|
public Neuroid avoidance;
|
||||||
public Neuroid boundary;
|
|
||||||
|
|
||||||
public Neuroid output;
|
public Neuroid output;
|
||||||
|
|
||||||
|
public override Vector3 outputValue { get => output.outputValue; set => output.outputValue = value; }
|
||||||
|
|
||||||
public const int BoundaryType = 1;
|
public const int BoundaryType = 1;
|
||||||
public const int BoidType = 2;
|
public const int BoidType = 2;
|
||||||
|
|
||||||
public Swarming(NeuroidNetwork neuroidNet, Perception perception, SwarmControl sc) : base(neuroidNet) {
|
public Swarming(NeuroidNetwork neuroidNet, Perception perception, SwarmControl sc) : base("Swarming Nucleus") {
|
||||||
cohesion = new(neuroidNet, "Cohesion");
|
this.cohesion = new(neuroidNet, "Cohesion");
|
||||||
perception.SendPositions(cohesion, 1.0f, BoidType);
|
perception.SendPositions(this.cohesion, 1.0f, BoidType);
|
||||||
|
|
||||||
alignment = new(neuroidNet, "Alignment") { average = true };
|
this.alignment = new(neuroidNet, "Alignment") { average = true };
|
||||||
perception.SendVelocities(alignment);
|
perception.SendVelocities(this.alignment, 1.0f, BoidType);
|
||||||
|
|
||||||
avoidance = new(neuroidNet, "Separation") { inverse = true };
|
this.avoidance = new(neuroidNet, "Avoidance") { inverse = true };
|
||||||
perception.SendPositions(avoidance, sc.avoidanceForce);
|
perception.SendPositions(this.avoidance);
|
||||||
|
|
||||||
boundary = new(neuroidNet, "Boundary");
|
|
||||||
|
|
||||||
this.output = new(neuroidNet, "Swarming");
|
this.output = new(neuroidNet, "Swarming");
|
||||||
output.GetInputFrom(alignment, sc.alignmentForce);
|
//this.output.GetInputFrom(alignment, sc.alignmentForce);
|
||||||
output.GetInputFrom(cohesion, sc.cohesionForce);
|
this.output.GetInputFrom(cohesion, sc.cohesionForce);
|
||||||
output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
this.output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
||||||
output.GetInputFrom(boundary, sc.boundaryForce);
|
}
|
||||||
}}
|
|
||||||
|
public override void AddReceiver(Neuroid receiver) {
|
||||||
|
this.output.AddReceiver(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user