Almost flocking
This commit is contained in:
parent
ca48381dc2
commit
69c6b1e2b7
@ -8,6 +8,8 @@ public class NanoBrain_Editor : Editor {
|
|||||||
private List<NeuroidLayer> layers = new();
|
private List<NeuroidLayer> layers = new();
|
||||||
private Dictionary<Nucleus, Vector2Int> neuroidPositions = new();
|
private Dictionary<Nucleus, Vector2Int> neuroidPositions = new();
|
||||||
|
|
||||||
|
protected bool breakOnWake = false;
|
||||||
|
|
||||||
#region Start
|
#region Start
|
||||||
|
|
||||||
private void OnEnable() {
|
private void OnEnable() {
|
||||||
@ -19,7 +21,7 @@ public class NanoBrain_Editor : Editor {
|
|||||||
if (!selectedObject.TryGetComponent(out Boid boid))
|
if (!selectedObject.TryGetComponent(out Boid boid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Neuroid neuroid = boid.totalForce;
|
Nucleus neuroid = boid.totalForce;
|
||||||
this.currentNucleus = neuroid;
|
this.currentNucleus = neuroid;
|
||||||
|
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
@ -34,12 +36,32 @@ public class NanoBrain_Editor : Editor {
|
|||||||
if (this.currentNucleus == null)
|
if (this.currentNucleus == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake);
|
||||||
|
if (breakOnWake && currentNucleus is Neuroid currentNeuroid) {
|
||||||
|
if (!currentNeuroid.isSleeping)
|
||||||
|
Debug.Break();
|
||||||
|
}
|
||||||
|
|
||||||
DrawGraph();
|
DrawGraph();
|
||||||
|
|
||||||
//DrawDefaultInspector();
|
//DrawDefaultInspector();
|
||||||
EditorGUILayout.TextField("Name", currentNucleus.name);
|
EditorGUILayout.TextField("Name", currentNucleus.name);
|
||||||
EditorGUILayout.FloatField("Output Value", currentNucleus.outputValue.magnitude);
|
EditorGUILayout.Vector3Field("Output Value", currentNucleus.outputValue);
|
||||||
EditorGUILayout.IntField("# synapses", currentNucleus.synapses.Count);
|
if (currentNucleus.synapses.Count > 0) {
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
foreach ((Nucleus nucleus, float weight) in currentNucleus.synapses) {
|
||||||
|
EditorGUI.BeginDisabledGroup(nucleus.isSleeping);
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.Vector3Field(nucleus.name, nucleus.outputValue);
|
||||||
|
EditorGUILayout.FloatField(weight, GUILayout.Width(50));
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildLayers() {
|
private void BuildLayers() {
|
||||||
@ -140,8 +162,8 @@ public class NanoBrain_Editor : Editor {
|
|||||||
|
|
||||||
|
|
||||||
float size = 20;
|
float size = 20;
|
||||||
if (layerNeuroid.IsStale())
|
if (layerNeuroid.isSleeping)
|
||||||
Handles.color = Color.darkCyan;
|
Handles.color = Color.darkRed;
|
||||||
else {
|
else {
|
||||||
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
||||||
Handles.color = new Color(brightness, brightness, brightness);
|
Handles.color = new Color(brightness, brightness, brightness);
|
||||||
@ -224,7 +246,8 @@ public class NanoBrain_Editor : Editor {
|
|||||||
// Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up);
|
// Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up);
|
||||||
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);
|
||||||
|
Handles.DrawLine(position, position + worldForce * 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Update
|
#endregion Update
|
||||||
|
|||||||
@ -199,7 +199,7 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float size = 20;
|
float size = 20;
|
||||||
if (layerNeuroid.IsStale())
|
if (layerNeuroid.isSleeping)
|
||||||
Handles.color = Color.black;
|
Handles.color = Color.black;
|
||||||
else {
|
else {
|
||||||
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
||||||
@ -272,7 +272,7 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
if (boid == null)
|
if (boid == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Neuroid neuroid = boid.totalForce;
|
Nucleus neuroid = boid.behaviour;
|
||||||
this.currentNucleus = neuroid;
|
this.currentNucleus = neuroid;
|
||||||
if (neuroid == null)
|
if (neuroid == null)
|
||||||
this.allNeuroids = new();
|
this.allNeuroids = new();
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public class NanoBrain : MonoBehaviour {
|
|||||||
public void UpdateNeurons() {
|
public void UpdateNeurons() {
|
||||||
foreach (Neuroid neuroid in neuroids) {
|
foreach (Neuroid neuroid in neuroids) {
|
||||||
neuroid.stale++;
|
neuroid.stale++;
|
||||||
if (neuroid.IsStale())
|
if (neuroid.isSleeping)
|
||||||
neuroid.outputValue = Vector3.zero;
|
neuroid.outputValue = Vector3.zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class Neuroid : Nucleus {
|
public class Neuroid : Nucleus {
|
||||||
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;
|
||||||
@ -15,11 +13,6 @@ public class Neuroid : Nucleus {
|
|||||||
Debug.LogError("No neuroid network");
|
Debug.LogError("No neuroid network");
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void AddSynapse(Neuroid input) {
|
|
||||||
// input.AddReceiver(this);
|
|
||||||
// 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,7 +36,7 @@ public class Neuroid : Nucleus {
|
|||||||
public virtual void UpdateState() {
|
public virtual void UpdateState() {
|
||||||
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.isSleeping)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Vector3 direction = nucleus.outputValue.normalized;
|
Vector3 direction = nucleus.outputValue.normalized;
|
||||||
@ -65,8 +58,8 @@ public class Neuroid : Nucleus {
|
|||||||
receiver.SetInput(this);
|
receiver.SetInput(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsStale() {
|
// public bool IsStale() {
|
||||||
return this.stale > 2;
|
// return this.stale > 2;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,9 +2,11 @@ using System.Collections.Generic;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class Nucleus {
|
public class Nucleus {
|
||||||
|
public int stale = 0;
|
||||||
|
|
||||||
public NanoBrain brain { get; protected set; }
|
public NanoBrain brain { get; protected set; }
|
||||||
|
|
||||||
public string name;
|
public virtual string name { get; set; }
|
||||||
|
|
||||||
public readonly Dictionary<Nucleus, float> synapses = new();
|
public readonly Dictionary<Nucleus, float> synapses = new();
|
||||||
public HashSet<Neuroid> receivers = new();
|
public HashSet<Neuroid> receivers = new();
|
||||||
@ -22,4 +24,11 @@ public class Nucleus {
|
|||||||
receiver.synapses[this] = 1.0f; // new(this);
|
receiver.synapses[this] = 1.0f; // new(this);
|
||||||
//Debug.Log($"receiver # {this.receivers.Count} synapse count {receiver.synapses.Count}");
|
//Debug.Log($"receiver # {this.receivers.Count} synapse count {receiver.synapses.Count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool isSleeping {
|
||||||
|
get {
|
||||||
|
return this.stale > 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ public class Perception : Nucleus {
|
|||||||
this.velocityReceivers = new();
|
this.velocityReceivers = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendPositions(Neuroid receivingNeuroid, float weight = 1.0f, int thingType = 0) {
|
public void SendPositions(Neuroid receivingNeuroid, int thingType = 0, float weight = 1.0f) {
|
||||||
Receiver receiver = new() {
|
Receiver receiver = new() {
|
||||||
thingType = thingType,
|
thingType = thingType,
|
||||||
neuroid = receivingNeuroid
|
neuroid = receivingNeuroid
|
||||||
@ -32,7 +32,7 @@ public class Perception : Nucleus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void SendVelocities(Neuroid receivingNeuroid, float weight = 1.0f, int thingType = 0) {
|
public void SendVelocities(Neuroid receivingNeuroid, int thingType = 0, float weight = 1.0f) {
|
||||||
Receiver receiver = new() {
|
Receiver receiver = new() {
|
||||||
thingType = thingType,
|
thingType = thingType,
|
||||||
neuroid = receivingNeuroid
|
neuroid = receivingNeuroid
|
||||||
@ -57,7 +57,7 @@ public class Perception : Nucleus {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (availableIx == -1) {
|
if (availableIx == -1) {
|
||||||
if (sensoryNeuroids[i].IsStale())
|
if (sensoryNeuroids[i].isSleeping)
|
||||||
leastInterestingIx = i;
|
leastInterestingIx = i;
|
||||||
else if (sensoryNeuroids[i] != null) {
|
else if (sensoryNeuroids[i] != null) {
|
||||||
if (leastInterestingIx == -1 || sensoryNeuroids[leastInterestingIx].receptor.position.magnitude > sensoryNeuroids[i].receptor.position.magnitude)
|
if (leastInterestingIx == -1 || sensoryNeuroids[leastInterestingIx].receptor.position.magnitude > sensoryNeuroids[i].receptor.position.magnitude)
|
||||||
@ -77,7 +77,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(brain, thingId) { name = name };
|
neuroid = new(brain, thingId, name);
|
||||||
sensoryNeuroids[availableIx] = neuroid;
|
sensoryNeuroids[availableIx] = neuroid;
|
||||||
}
|
}
|
||||||
foreach (Receiver receiver in positionReceivers) {
|
foreach (Receiver receiver in positionReceivers) {
|
||||||
|
|||||||
@ -30,33 +30,38 @@ public class SensoryNeuroid : Neuroid {
|
|||||||
public VelocityNeuroid velocityNeuroid;
|
public VelocityNeuroid velocityNeuroid;
|
||||||
|
|
||||||
// public SensoryNeuroid(NeuroidNetwork net, int thingId) : base(net, "sensory neuroid") {
|
// public SensoryNeuroid(NeuroidNetwork net, int thingId) : base(net, "sensory neuroid") {
|
||||||
public SensoryNeuroid(NanoBrain net, int thingId) : base(net, "sensory neuroid") {
|
public SensoryNeuroid(NanoBrain net, int thingId, string name = "sensor") : base(net, name) {
|
||||||
|
this.name = name + ": position";
|
||||||
this.receptor = new Receptor {
|
this.receptor = new Receptor {
|
||||||
neuroid = this,
|
neuroid = this,
|
||||||
thingId = thingId
|
thingId = thingId
|
||||||
};
|
};
|
||||||
this.velocityNeuroid = new(net);
|
this.velocityNeuroid = new(net, name + ": velocity");
|
||||||
// The velocity neuroid received position data from this
|
// The velocity neuroid received position data from this
|
||||||
this.AddReceiver(velocityNeuroid);
|
this.AddReceiver(velocityNeuroid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Replace(int thingId, string name = "sensory neuroid") {
|
public void Replace(int thingId, string name = "sensor") {
|
||||||
this.name = name;
|
this.name = name + ": position";
|
||||||
|
|
||||||
this.receptor.thingId = thingId;
|
this.receptor.thingId = thingId;
|
||||||
this.receptor.localPosition = 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();
|
|
||||||
|
// this.velocityNeuroid.name = name + ": velocity";
|
||||||
|
// this.velocityNeuroid.receivers = new();
|
||||||
|
this.velocityNeuroid.Replace(name + ": velocity");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateState() {
|
public override void UpdateState() {
|
||||||
Vector3 result = receptor.localPosition;
|
Vector3 result = receptor.localPosition;
|
||||||
//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;
|
||||||
float magnitude = nucleus.outputValue.magnitude;
|
float magnitude = nucleus.outputValue.magnitude;
|
||||||
//magnitude = synapse.weight * Mathf.Pow(magnitude, exponent);
|
|
||||||
magnitude = weight * Mathf.Pow(magnitude, exponent);
|
magnitude = weight * Mathf.Pow(magnitude, exponent);
|
||||||
if (inverse)
|
if (inverse)
|
||||||
magnitude = 1 / magnitude;
|
magnitude = 1 / magnitude;
|
||||||
@ -77,8 +82,14 @@ public class VelocityNeuroid : Neuroid {
|
|||||||
private Vector3 lastPosition = Vector3.zero;
|
private Vector3 lastPosition = Vector3.zero;
|
||||||
private float lastValueTime = 0;
|
private float lastValueTime = 0;
|
||||||
|
|
||||||
// public VelocityNeuroid(NeuroidNetwork net) : base(net, "Velocity") {
|
public VelocityNeuroid(NanoBrain net, string name = "velocity") : base(net, name) {
|
||||||
public VelocityNeuroid(NanoBrain net) : base(net, "Velocity") {
|
}
|
||||||
|
|
||||||
|
public void Replace(string name = "velocity") {
|
||||||
|
this.name = name;
|
||||||
|
this.receivers = new();
|
||||||
|
this.lastPosition = Vector3.zero;
|
||||||
|
this.lastValueTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateState() {
|
public override void UpdateState() {
|
||||||
@ -86,17 +97,20 @@ public class VelocityNeuroid : Neuroid {
|
|||||||
Vector3 currentPosition = this.synapses.First().Key.outputValue;
|
Vector3 currentPosition = this.synapses.First().Key.outputValue;
|
||||||
float currentValueTime = Time.time;
|
float currentValueTime = Time.time;
|
||||||
|
|
||||||
float deltaTime = currentValueTime - lastValueTime;
|
if (lastValueTime != 0) {
|
||||||
Vector3 translation = currentPosition - lastPosition;
|
float deltaTime = currentValueTime - lastValueTime;
|
||||||
Vector3 velocity = translation / deltaTime;
|
Vector3 translation = currentPosition - lastPosition;
|
||||||
|
Vector3 velocity = translation / deltaTime;
|
||||||
|
|
||||||
// No activation function...
|
// No activation function...
|
||||||
this.outputValue = velocity;
|
this.outputValue = velocity;
|
||||||
foreach (Neuroid receiver in receivers)
|
this.stale = 0;
|
||||||
receiver?.SetInput(this);
|
|
||||||
this.stale = 0;
|
|
||||||
|
|
||||||
this.lastValueTime = Time.time;
|
foreach (Neuroid receiver in receivers)
|
||||||
|
receiver?.SetInput(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastValueTime = currentValueTime;
|
||||||
this.lastPosition = currentPosition;
|
this.lastPosition = currentPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,10 +372,10 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::SwarmControl
|
m_EditorClassIdentifier: Assembly-CSharp::SwarmControl
|
||||||
speed: 2
|
speed: 2
|
||||||
inertia: 0.1
|
inertia: 0.5
|
||||||
alignmentForce: 3
|
alignmentForce: 2
|
||||||
cohesionForce: 3
|
cohesionForce: 2
|
||||||
avoidanceForce: 5
|
avoidanceForce: 1
|
||||||
separationDistance: 0.3
|
separationDistance: 0.3
|
||||||
perceptionDistance: 1
|
perceptionDistance: 1
|
||||||
boundaryForce: 5
|
boundaryForce: 5
|
||||||
@ -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: 5
|
count: 20
|
||||||
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
|
||||||
|
|||||||
@ -2,17 +2,15 @@ using UnityEngine;
|
|||||||
|
|
||||||
[RequireComponent(typeof(NanoBrain))]
|
[RequireComponent(typeof(NanoBrain))]
|
||||||
public class Boid : MonoBehaviour {
|
public class Boid : MonoBehaviour {
|
||||||
public const int BoundaryType = 1;
|
public static int BoundaryType = 1;
|
||||||
public const int BoidType = 2;
|
public static int BoidType = 2;
|
||||||
|
|
||||||
public SwarmControl sc;
|
public SwarmControl sc;
|
||||||
public Vector3 velocity = Vector3.zero;
|
public Vector3 velocity = Vector3.zero;
|
||||||
public Vector3 acceleration = Vector3.zero;
|
public Vector3 acceleration = Vector3.zero;
|
||||||
|
|
||||||
private Bounds innerBounds;
|
private Bounds innerBounds;
|
||||||
private Bounds outerBounds;
|
|
||||||
|
|
||||||
//public NeuroidNetwork neuroidNet = new();
|
|
||||||
public NanoBrain neuroidNet;
|
public NanoBrain neuroidNet;
|
||||||
public Perception perception;
|
public Perception perception;
|
||||||
|
|
||||||
@ -30,7 +28,6 @@ public class Boid : MonoBehaviour {
|
|||||||
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);
|
||||||
outerBounds = new(sc.transform.position, sc.spaceSize);
|
|
||||||
|
|
||||||
perception = new Perception(neuroidNet);
|
perception = new Perception(neuroidNet);
|
||||||
|
|
||||||
@ -49,7 +46,8 @@ public class Boid : MonoBehaviour {
|
|||||||
if (neighbour == null || neighbour == this)
|
if (neighbour == null || neighbour == this)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Vector3 localPosition = neighbour.transform.position - this.transform.position;
|
Vector3 localPosition = this.transform.InverseTransformPoint(neighbour.transform.position);
|
||||||
|
//Debug.DrawRay(this.transform.position, this.transform.TransformDirection(localPosition), Color.magenta);
|
||||||
|
|
||||||
int thingId = neighbour.GetInstanceID();
|
int thingId = neighbour.GetInstanceID();
|
||||||
perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name);
|
perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name);
|
||||||
@ -64,13 +62,14 @@ public class Boid : MonoBehaviour {
|
|||||||
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
|
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
|
Vector3 worldForce = this.transform.TransformDirection(behaviour.outputValue);
|
||||||
|
|
||||||
this.velocity = (1 - sc.inertia) * (worldForce * Time.deltaTime) + sc.inertia * velocity;
|
this.velocity = (1 - sc.inertia) * (worldForce * Time.deltaTime) + sc.inertia * velocity;
|
||||||
if (this.velocity.magnitude > 0)
|
if (this.velocity.magnitude > 0)
|
||||||
this.velocity = this.velocity.normalized * sc.speed;
|
this.velocity = this.velocity.normalized * sc.speed;
|
||||||
else
|
else
|
||||||
this.velocity = this.transform.forward * sc.speed;
|
this.velocity = this.transform.forward * sc.speed;
|
||||||
|
Debug.DrawRay(this.transform.position, this.velocity, Color.blue);
|
||||||
|
|
||||||
this.transform.position += this.velocity * Time.deltaTime;
|
this.transform.position += this.velocity * Time.deltaTime;
|
||||||
|
|
||||||
@ -82,14 +81,4 @@ public class Boid : MonoBehaviour {
|
|||||||
neuroidNet.UpdateNeurons();
|
neuroidNet.UpdateNeurons();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 ClosestPointOnBoundsSurface(Bounds b, Vector3 p) {
|
|
||||||
if (!b.Contains(p)) return b.ClosestPoint(p);
|
|
||||||
Vector3 d = p - b.center;
|
|
||||||
Vector3 ext = b.extents;
|
|
||||||
float sx = ext.x / Mathf.Abs(d.x);
|
|
||||||
float sy = ext.y / Mathf.Abs(d.y);
|
|
||||||
float sz = ext.z / Mathf.Abs(d.z);
|
|
||||||
float m = Mathf.Min(sx, Mathf.Min(sy, sz));
|
|
||||||
return b.center + d * m;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ public class 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, Boid.BoundaryType);
|
||||||
|
|
||||||
this.output = new(neuroidNet, "Roaming");
|
this.output = new(neuroidNet, "Roaming");
|
||||||
output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
||||||
|
|||||||
@ -4,28 +4,30 @@ 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 override Vector3 outputValue { get => output.outputValue; set => output.outputValue = value; }
|
||||||
|
|
||||||
public const int BoundaryType = 1;
|
|
||||||
public const int BoidType = 2;
|
|
||||||
|
|
||||||
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") { inverse = false };
|
||||||
perception.SendPositions(this.cohesion, 1.0f, BoidType);
|
perception.SendPositions(this.cohesion, Boid.BoidType);
|
||||||
|
|
||||||
this.alignment = new(neuroidNet, "Alignment") { average = true };
|
this.alignment = new(neuroidNet, "Alignment") { average = true };
|
||||||
perception.SendVelocities(this.alignment, 1.0f, BoidType);
|
perception.SendVelocities(this.alignment, Boid.BoidType);
|
||||||
|
|
||||||
this.avoidance = new(neuroidNet, "Avoidance") { inverse = true };
|
this.avoidance = new(neuroidNet, "Avoidance") { inverse = true };
|
||||||
perception.SendPositions(this.avoidance);
|
perception.SendPositions(this.avoidance);
|
||||||
|
|
||||||
|
this.boundary = new(neuroidNet, "Boundary");
|
||||||
|
perception.SendPositions(this.boundary, Boid.BoundaryType);
|
||||||
|
|
||||||
this.output = new(neuroidNet, "Swarming");
|
this.output = new(neuroidNet, "Swarming");
|
||||||
this.output.GetInputFrom(alignment, sc.alignmentForce);
|
this.output.GetInputFrom(alignment, sc.alignmentForce);
|
||||||
this.output.GetInputFrom(cohesion, sc.cohesionForce);
|
this.output.GetInputFrom(cohesion, sc.cohesionForce);
|
||||||
this.output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
this.output.GetInputFrom(avoidance, -sc.avoidanceForce);
|
||||||
|
this.output.GetInputFrom(boundary, -sc.avoidanceForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddReceiver(Neuroid receiver) {
|
public override void AddReceiver(Neuroid receiver) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user