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}");
}
#endregion Start
#region Update
@ -205,10 +204,18 @@ public class NanoBrain_Editor : Editor {
if (brain == null)
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);
// Handles.color = Color.green;
// Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up);
Vector3 position = brain.transform.position;
Handles.color = Color.yellow;
Vector3 worldForce = brain.transform.TransformDirection(this.currentNucleus.outputValue);
Debug.DrawRay(position, worldForce * 10, Color.yellow);

View File

@ -3,13 +3,10 @@ using UnityEngine;
public class Neuroid : Nucleus {
public int stale = 0;
public bool average = false;
public bool inverse = false;
public float exponent = 1.0f;
public NanoBrain brain;
public Neuroid(NanoBrain brain, string name) : base(name) {
this.brain = brain;
if (this.brain != null)
@ -18,10 +15,10 @@ public class Neuroid : Nucleus {
Debug.LogError("No neuroid network");
}
public void AddSynapse(Neuroid input) {
input.AddReceiver(this);
this.synapses[input] = 1.0f;
}
// public void AddSynapse(Neuroid input) {
// input.AddReceiver(this);
// this.synapses[input] = 1.0f;
// }
public void SetWeight(Neuroid input, float weight) {
this.synapses[input] = weight;
@ -43,21 +40,7 @@ public class Neuroid : Nucleus {
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() {
// int minStale = 10000;
Vector3 result = Vector3.zero;
foreach ((Nucleus nucleus, float weight) in this.synapses) {
if (nucleus is Neuroid neuroid && neuroid.IsStale())
@ -71,16 +54,11 @@ public class Neuroid : Nucleus {
magnitude = 1 / magnitude;
result += direction * magnitude;
// if (nucleus is Neuroid neuroid && neuroid.stale < minStale)
// minStale = neuroid.stale;
}
if (average && this.synapses.Count > 0)
result /= this.synapses.Count;
this.outputValue = result;
// if (minStale > 2)
// Debug.LogWarning($"Strange {minStale} is big duing update");
this.stale = 0;
foreach (Neuroid receiver in this.receivers)

View File

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

View File

@ -5,9 +5,6 @@ using UnityEngine;
public class Perception : Nucleus {
public SensoryNeuroid[] sensoryNeuroids = new SensoryNeuroid[7];
// public NeuroidNetwork neuroidNet { get; protected set; }
public NanoBrain neuroidNet { get; protected set; }
public class Receiver {
public int thingType = 0;
public Neuroid neuroid;
@ -16,9 +13,8 @@ public class Perception : Nucleus {
public HashSet<Receiver> positionReceivers { get; protected set; }
public HashSet<Receiver> velocityReceivers { get; protected set; }
// public Perception(NeuroidNetwork neuroidNet) : base("Perception") {
public Perception(NanoBrain neuroidNet) : base("Perception") {
this.neuroidNet = neuroidNet;
this.brain = neuroidNet;
this.positionReceivers = new();
this.velocityReceivers = new();
}
@ -32,7 +28,7 @@ public class Perception : Nucleus {
foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
if (neuroid != null) {
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) {
if (neuroid != null && neuroid.velocityNeuroid != null) {
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;
if (availableIx != -1) {
SensoryNeuroid neuroid;
if (sensoryNeuroids[availableIx] != null) {
Debug.Log($"replace receptor for {thingId} at {availableIx}");
SensoryNeuroid neuroid = sensoryNeuroids[availableIx];
neuroid.Replace(thingId);
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;
// Debug.Log($"replace receptor for {thingId} at {availableIx}");
neuroid = sensoryNeuroids[availableIx];
neuroid.Replace(thingId, name);
}
else {
Debug.Log($"new receptor for {thingId} at {availableIx}");
SensoryNeuroid neuroid = new(neuroidNet, 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);
}
// Debug.Log($"new receptor for {thingId} at {availableIx}");
neuroid = new(brain, thingId) { name = name };
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 int thingId;
public Vector3 value;
public Vector3 localPosition;
/// <summary>
/// Local position of the thing
/// </summary>
public virtual Vector3 position {
get {
return this.value;
return this.localPosition;
}
set {
this.value = value;
this.localPosition = value;
neuroid.UpdateState();
}
}
@ -40,17 +40,18 @@ public class SensoryNeuroid : Neuroid {
this.AddReceiver(velocityNeuroid);
}
public void Replace(int thingId) {
this.name = "sensory neuroid";
public void Replace(int thingId, string name = "sensory neuroid") {
this.name = name;
this.receptor.thingId = thingId;
this.receptor.value = Vector3.zero;
this.receptor.localPosition = Vector3.zero;
this.outputValue = Vector3.zero;
this.receivers = new();
this.AddReceiver(velocityNeuroid);
this.velocityNeuroid.receivers = new();
}
public override void UpdateState() {
Vector3 result = receptor.value;
Vector3 result = receptor.localPosition;
//foreach ((Nucleus nucleus, Synapse synapse) in this.synapses) {
foreach ((Nucleus nucleus, float weight) in this.synapses) {
Vector3 direction = nucleus.outputValue.normalized;

View File

@ -373,8 +373,8 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::SwarmControl
speed: 2
inertia: 0.1
alignmentForce: 5
cohesionForce: 5
alignmentForce: 3
cohesionForce: 3
avoidanceForce: 5
separationDistance: 0.3
perceptionDistance: 1
@ -393,7 +393,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: ec888ca5333d45a438f9f417fa5ce135, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::SwarmSpawn
count: 2
count: 5
boidPrefab: {fileID: 8702527964058765413, guid: f9c706268554ce449a8773675b2864b8, type: 3}
spawnAreaSize: {x: 0.5, y: 0.5, z: 0.5}
minDelay: 0.05

View File

@ -63,9 +63,6 @@ public class Boid : MonoBehaviour {
Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace);
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
}
// else {
// perception.RemoveStimulus(777);
// }
Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
@ -95,19 +92,4 @@ public class Boid : MonoBehaviour {
float m = Mathf.Min(sx, Mathf.Min(sy, sz));
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 Roaming(NeuroidNetwork 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 };
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(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 BoidType = 2;
// public Swarming(NeuroidNetwork neuroidNet, Perception perception, SwarmControl sc) : base("Swarming Nucleus") {
public Swarming(NanoBrain neuroidNet, Perception perception, SwarmControl sc) : base("Swarming Nucleus") {
this.cohesion = new(neuroidNet, "Cohesion");
perception.SendPositions(this.cohesion, 1.0f, BoidType);