Fix boundary velocityneuroid to alignment

This commit is contained in:
Pascal Serrarens 2025-12-03 15:54:16 +01:00
parent a3d49e330f
commit fc4e1ea889
10 changed files with 47 additions and 103 deletions

View File

@ -26,7 +26,6 @@ public class NanoBrain_Editor : Editor {
Debug.Log($"Layercount = {this.layers.Count}"); Debug.Log($"Layercount = {this.layers.Count}");
} }
#endregion Start #endregion Start
#region Update #region Update
@ -205,10 +204,18 @@ public class NanoBrain_Editor : Editor {
if (brain == null) if (brain == null)
return; return;
Vector3 position = brain.transform.position;
float radius = 1;
Handles.DrawWireDisc(position, Vector3.up, radius); // horizontal circle
Handles.DrawWireDisc(position, Vector3.right, radius); // X-plane
Handles.DrawWireDisc(position, Vector3.forward, radius); // Z-plane
// Debug.DrawRay(brain.transform.position, Vector3.forward, Color.magenta); // Debug.DrawRay(brain.transform.position, Vector3.forward, Color.magenta);
// Handles.color = Color.green; // Handles.color = Color.green;
// Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up); // Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up);
Vector3 position = brain.transform.position;
Handles.color = Color.yellow; Handles.color = Color.yellow;
Vector3 worldForce = brain.transform.TransformDirection(this.currentNucleus.outputValue); Vector3 worldForce = brain.transform.TransformDirection(this.currentNucleus.outputValue);
Debug.DrawRay(position, worldForce * 10, Color.yellow); Debug.DrawRay(position, worldForce * 10, Color.yellow);

View File

@ -3,13 +3,10 @@ using UnityEngine;
public class Neuroid : Nucleus { public class Neuroid : Nucleus {
public int stale = 0; public int stale = 0;
public bool average = false; public bool average = false;
public bool inverse = false; public bool inverse = false;
public float exponent = 1.0f; public float exponent = 1.0f;
public NanoBrain brain;
public Neuroid(NanoBrain brain, string name) : base(name) { public Neuroid(NanoBrain brain, string name) : base(name) {
this.brain = brain; this.brain = brain;
if (this.brain != null) if (this.brain != null)
@ -18,10 +15,10 @@ public class Neuroid : Nucleus {
Debug.LogError("No neuroid network"); Debug.LogError("No neuroid network");
} }
public void AddSynapse(Neuroid input) { // public void AddSynapse(Neuroid input) {
input.AddReceiver(this); // input.AddReceiver(this);
this.synapses[input] = 1.0f; // this.synapses[input] = 1.0f;
} // }
public void SetWeight(Neuroid input, float weight) { public void SetWeight(Neuroid input, float weight) {
this.synapses[input] = weight; this.synapses[input] = weight;
@ -43,21 +40,7 @@ public class Neuroid : Nucleus {
UpdateState(); UpdateState();
} }
public void RemoveInputFrom(Neuroid input) {
if (this.synapses.Count == 0)
return;
this.synapses.Remove(input);
if (this.synapses.Count == 0) {
// In case this was the last synapse, we reset the output because in this case no updates from synapses will follow.
this.outputValue = Vector3.zero;
foreach (Neuroid neuroid in this.receivers)
neuroid.SetInput(this);
}
}
public virtual void UpdateState() { public virtual void UpdateState() {
// int minStale = 10000;
Vector3 result = Vector3.zero; Vector3 result = Vector3.zero;
foreach ((Nucleus nucleus, float weight) in this.synapses) { foreach ((Nucleus nucleus, float weight) in this.synapses) {
if (nucleus is Neuroid neuroid && neuroid.IsStale()) if (nucleus is Neuroid neuroid && neuroid.IsStale())
@ -71,16 +54,11 @@ public class Neuroid : Nucleus {
magnitude = 1 / magnitude; magnitude = 1 / magnitude;
result += direction * magnitude; result += direction * magnitude;
// if (nucleus is Neuroid neuroid && neuroid.stale < minStale)
// minStale = neuroid.stale;
} }
if (average && this.synapses.Count > 0) if (average && this.synapses.Count > 0)
result /= this.synapses.Count; result /= this.synapses.Count;
this.outputValue = result; this.outputValue = result;
// if (minStale > 2)
// Debug.LogWarning($"Strange {minStale} is big duing update");
this.stale = 0; this.stale = 0;
foreach (Neuroid receiver in this.receivers) foreach (Neuroid receiver in this.receivers)

View File

@ -2,6 +2,8 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class Nucleus { public class Nucleus {
public NanoBrain brain { get; protected set; }
public string name; public string name;
public readonly Dictionary<Nucleus, float> synapses = new(); public readonly Dictionary<Nucleus, float> synapses = new();

View File

@ -5,9 +5,6 @@ using UnityEngine;
public class Perception : Nucleus { public class Perception : Nucleus {
public SensoryNeuroid[] sensoryNeuroids = new SensoryNeuroid[7]; public SensoryNeuroid[] sensoryNeuroids = new SensoryNeuroid[7];
// public NeuroidNetwork neuroidNet { get; protected set; }
public NanoBrain neuroidNet { get; protected set; }
public class Receiver { public class Receiver {
public int thingType = 0; public int thingType = 0;
public Neuroid neuroid; public Neuroid neuroid;
@ -16,9 +13,8 @@ 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("Perception") {
public Perception(NanoBrain neuroidNet) : base("Perception") { public Perception(NanoBrain neuroidNet) : base("Perception") {
this.neuroidNet = neuroidNet; this.brain = neuroidNet;
this.positionReceivers = new(); this.positionReceivers = new();
this.velocityReceivers = new(); this.velocityReceivers = new();
} }
@ -32,7 +28,7 @@ public class Perception : Nucleus {
foreach (SensoryNeuroid neuroid in sensoryNeuroids) { foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
if (neuroid != null) { if (neuroid != null) {
neuroid.AddReceiver(receivingNeuroid); neuroid.AddReceiver(receivingNeuroid);
receivingNeuroid.synapses[neuroid] = weight; // new(neuroid, weight); receivingNeuroid.synapses[neuroid] = weight;
} }
} }
} }
@ -45,7 +41,7 @@ public class Perception : Nucleus {
foreach (SensoryNeuroid neuroid in sensoryNeuroids) { foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
if (neuroid != null && neuroid.velocityNeuroid != null) { if (neuroid != null && neuroid.velocityNeuroid != null) {
neuroid.velocityNeuroid.AddReceiver(receivingNeuroid); neuroid.velocityNeuroid.AddReceiver(receivingNeuroid);
receivingNeuroid.synapses[neuroid] = 1.0f; //new(neuroid); receivingNeuroid.synapses[neuroid] = weight;
} }
} }
} }
@ -73,49 +69,28 @@ public class Perception : Nucleus {
availableIx = leastInterestingIx; availableIx = leastInterestingIx;
if (availableIx != -1) { if (availableIx != -1) {
SensoryNeuroid neuroid;
if (sensoryNeuroids[availableIx] != null) { if (sensoryNeuroids[availableIx] != null) {
Debug.Log($"replace receptor for {thingId} at {availableIx}"); // Debug.Log($"replace receptor for {thingId} at {availableIx}");
SensoryNeuroid neuroid = sensoryNeuroids[availableIx]; neuroid = sensoryNeuroids[availableIx];
neuroid.Replace(thingId); neuroid.Replace(thingId, name);
neuroid.name = name;
foreach (Receiver receiver in positionReceivers) {
if (receiver.thingType == 0 || receiver.thingType == thingType)
receiver.neuroid.GetInputFrom(neuroid);
}
foreach (Receiver receiver in velocityReceivers) {
if (receiver.thingType == 0 || receiver.thingType == thingType)
receiver.neuroid.GetInputFrom(neuroid.velocityNeuroid);
}
neuroid.receptor.position = localPosition;
} }
else { else {
Debug.Log($"new receptor for {thingId} at {availableIx}"); // Debug.Log($"new receptor for {thingId} at {availableIx}");
SensoryNeuroid neuroid = new(neuroidNet, thingId) { name = name }; neuroid = new(brain, thingId) { name = name };
foreach (Receiver receiver in positionReceivers) {
if (receiver.thingType == 0 || receiver.thingType == thingType)
receiver.neuroid.GetInputFrom(neuroid);
}
foreach (Receiver receiver in velocityReceivers) {
if (receiver.thingType == 0 || receiver.thingType == thingType)
receiver.neuroid.GetInputFrom(neuroid.velocityNeuroid);
}
sensoryNeuroids[availableIx] = neuroid; sensoryNeuroids[availableIx] = neuroid;
neuroid.receptor.position = localPosition;
} }
foreach (Receiver receiver in positionReceivers) {
if (receiver.thingType == 0 || receiver.thingType == thingType)
receiver.neuroid.GetInputFrom(neuroid);
}
foreach (Receiver receiver in velocityReceivers) {
if (receiver.thingType == 0 || receiver.thingType == thingType)
receiver.neuroid.GetInputFrom(neuroid.velocityNeuroid);
}
neuroid.receptor.position = localPosition;
} }
} }
public void RemoveStimulus(int thingId) {
for (int i = 0; i < sensoryNeuroids.Length; i++) {
if (sensoryNeuroids[i] != null && sensoryNeuroids[i].receptor.thingId == thingId) {
foreach (Neuroid receiver in sensoryNeuroids[i].receivers)
receiver.RemoveInputFrom(sensoryNeuroids[i]);
sensoryNeuroids[i] = null;
return;
}
}
}
} }

View File

@ -7,17 +7,17 @@ public class Receptor {
public SensoryNeuroid neuroid; public SensoryNeuroid neuroid;
public int thingId; public int thingId;
public Vector3 value; public Vector3 localPosition;
/// <summary> /// <summary>
/// Local position of the thing /// Local position of the thing
/// </summary> /// </summary>
public virtual Vector3 position { public virtual Vector3 position {
get { get {
return this.value; return this.localPosition;
} }
set { set {
this.value = value; this.localPosition = value;
neuroid.UpdateState(); neuroid.UpdateState();
} }
} }
@ -40,17 +40,18 @@ public class SensoryNeuroid : Neuroid {
this.AddReceiver(velocityNeuroid); this.AddReceiver(velocityNeuroid);
} }
public void Replace(int thingId) { public void Replace(int thingId, string name = "sensory neuroid") {
this.name = "sensory neuroid"; this.name = name;
this.receptor.thingId = thingId; this.receptor.thingId = thingId;
this.receptor.value = Vector3.zero; this.receptor.localPosition = Vector3.zero;
this.outputValue = Vector3.zero; this.outputValue = Vector3.zero;
this.receivers = new(); this.receivers = new();
this.AddReceiver(velocityNeuroid); this.AddReceiver(velocityNeuroid);
this.velocityNeuroid.receivers = new();
} }
public override void UpdateState() { public override void UpdateState() {
Vector3 result = receptor.value; Vector3 result = receptor.localPosition;
//foreach ((Nucleus nucleus, Synapse synapse) in this.synapses) { //foreach ((Nucleus nucleus, Synapse synapse) in this.synapses) {
foreach ((Nucleus nucleus, float weight) in this.synapses) { foreach ((Nucleus nucleus, float weight) in this.synapses) {
Vector3 direction = nucleus.outputValue.normalized; Vector3 direction = nucleus.outputValue.normalized;

View File

@ -373,8 +373,8 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::SwarmControl m_EditorClassIdentifier: Assembly-CSharp::SwarmControl
speed: 2 speed: 2
inertia: 0.1 inertia: 0.1
alignmentForce: 5 alignmentForce: 3
cohesionForce: 5 cohesionForce: 3
avoidanceForce: 5 avoidanceForce: 5
separationDistance: 0.3 separationDistance: 0.3
perceptionDistance: 1 perceptionDistance: 1
@ -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: 2 count: 5
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

View File

@ -63,9 +63,6 @@ public class Boid : MonoBehaviour {
Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace); Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace);
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary"); perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
} }
// else {
// perception.RemoveStimulus(777);
// }
Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue); Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
@ -95,19 +92,4 @@ public class Boid : MonoBehaviour {
float m = Mathf.Min(sx, Mathf.Min(sy, sz)); float m = Mathf.Min(sx, Mathf.Min(sy, sz));
return b.center + d * m; return b.center + d * m;
} }
// void OnDrawGizmosSelected() {
// if (sc == null)
// return;
// Gizmos.DrawWireSphere(this.transform.position, sc.perceptionDistance);
// Gizmos.color = Color.yellow;
// Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
// Gizmos.DrawRay(transform.position, worldForce * 10);
// // Gizmos.color = Color.magenta;
// // Gizmos.DrawRay(transform.position, this.transform.TransformDirection(avoidance.outputValue) * 10);
// // Debug.Log($"Avoidance {roaming.avoidance.outputValue} Roaming {roaming.output.outputValue} Total {totalForce.outputValue}");
// // Debug.Log($"WorldForce {worldForce} velocity {velocity} inertia {sc.inertia}");
// Gizmos.color = Color.blue;
// Gizmos.DrawRay(transform.position, this.velocity * 10);
// }
} }

View File

@ -3,7 +3,6 @@ public class Roaming : Nucleus {
public Neuroid output; public Neuroid output;
// public Roaming(NeuroidNetwork neuroidNet, Perception perception, SwarmControl sc) : base("Roaming nucleus") {
public Roaming(NanoBrain neuroidNet, Perception perception, SwarmControl sc) : base("Roaming nucleus") { public Roaming(NanoBrain neuroidNet, Perception perception, SwarmControl sc) : base("Roaming nucleus") {
avoidance = new(neuroidNet, "Avoidance") { inverse = true }; avoidance = new(neuroidNet, "Avoidance") { inverse = true };
perception.SendPositions(avoidance, 1.0f, 1); perception.SendPositions(avoidance, 1.0f, 1);

View File

@ -26,7 +26,8 @@ public class SwarmSpawn : MonoBehaviour {
); );
// Instantiate the prefab at the random position relative to the spawner // Instantiate the prefab at the random position relative to the spawner
Instantiate(boidPrefab, transform.position + randomPosition, Random.rotation); GameObject boid = Instantiate(boidPrefab, transform.position + randomPosition, Random.rotation);
boid.name = "Boid " + i;
} }
} }
} }

View File

@ -12,7 +12,6 @@ public class Swarming : Nucleus {
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("Swarming Nucleus") {
public Swarming(NanoBrain neuroidNet, Perception perception, SwarmControl sc) : base("Swarming Nucleus") { public Swarming(NanoBrain neuroidNet, Perception perception, SwarmControl sc) : base("Swarming Nucleus") {
this.cohesion = new(neuroidNet, "Cohesion"); this.cohesion = new(neuroidNet, "Cohesion");
perception.SendPositions(this.cohesion, 1.0f, BoidType); perception.SendPositions(this.cohesion, 1.0f, BoidType);