Separation/Cohesion curve

This commit is contained in:
Pascal Serrarens 2025-12-17 09:28:34 +01:00
parent 76af037a01
commit 0cee652110
4 changed files with 2611 additions and 35 deletions

View File

@ -2,6 +2,46 @@ using UnityEngine;
[System.Serializable]
public class Neuroid : Nucleus {
public enum CurvePresets {
Linear,
Power,
Sqrt,
Reciprocal,
Custom
}
[SerializeField]
private CurvePresets _curvePreset;
public CurvePresets curvePreset {
get { return _curvePreset; }
set {
_curvePreset = value;
this.curve = GenerateCurve();
}
}
public AnimationCurve curve;
public float curveMax = 1.0f;
public AnimationCurve GenerateCurve() {
switch (this.curvePreset) {
case CurvePresets.Linear:
this.curveMax = 1;
return Synapse.Presets.Linear(1);
case CurvePresets.Power:
this.curveMax = 1;
return Synapse.Presets.Power(2.0f, 1);
case CurvePresets.Sqrt:
this.curveMax = 1;
return Synapse.Presets.Power(0.5f, 1);
case CurvePresets.Reciprocal:
this.curveMax = 1 / 0.01f * 1;
return Synapse.Presets.Reciprocal(1);
default:
this.curveMax = 1;
//return AnimationCurve.Constant(0, 1, 1);
return this.curve;
}
}
public bool average = false;
public bool inverse = false;
public float exponent = 1.0f;
@ -16,7 +56,7 @@ public class Neuroid : Nucleus {
Debug.LogError("No neuroid network");
}
public Neuroid(string name): base(name) {}
public Neuroid(string name) : base(name) { }
public void SetWeight(Neuroid input, float weight) {
this.SetWeight((Nucleus)input, weight);
@ -40,17 +80,18 @@ public class Neuroid : Nucleus {
Vector3 result = Vector3.zero;
//foreach ((Nucleus nucleus, float weight) in this.synapses) {
foreach (Synapse synapse in this.synapses) {
Nucleus nucleus = synapse.nucleus;
if (nucleus is Neuroid neuroid && neuroid.isSleeping)
Nucleus synapseNucleus = synapse.nucleus;
if (synapseNucleus is Neuroid neuroid && neuroid.isSleeping)
continue;
Vector3 direction = nucleus.outputValue.normalized;
float magnitude = nucleus.outputValue.magnitude;
Vector3 direction = synapseNucleus.outputValue.normalized;
float magnitude = synapseNucleus.outputValue.magnitude;
float weight = synapse.weight;
magnitude = weight * Mathf.Pow(magnitude, exponent);
if (inverse && magnitude > 0)
magnitude = 1 / magnitude;
magnitude = weight * curve.Evaluate(synapseNucleus.outputValue.magnitude);
// magnitude = weight * Mathf.Pow(magnitude, exponent);
// if (inverse && magnitude > 0)
// magnitude = 1 / magnitude;
result += direction * magnitude;
}

View File

@ -73,7 +73,7 @@ public class NanoBrainComponent_Editor : Editor {
});
if (brain != null)
board.SetGraph(brain, brain.root, inspectorContainer);
board.SetGraph(component.gameObject, brain, brain.root, inspectorContainer);
// else
// Debug.LogWarning(" No brain!");

View File

@ -63,7 +63,7 @@ public class NanoBrainInspector : Editor {
});
if (brain != null)
board.SetGraph(brain, brain.root, inspectorContainer);
board.SetGraph(null, brain, brain.root, inspectorContainer);
else
Debug.LogWarning(" No brain!");
@ -75,6 +75,7 @@ public class NanoBrainInspector : Editor {
NanoBrainObj brain;
SerializedObject serializedBrain;
Nucleus currentNucleus;
GameObject gameObject;
private List<NeuroidLayer> layers = new();
private readonly Dictionary<Nucleus, Vector2Int> neuroidPositions = new();
@ -102,7 +103,8 @@ public class NanoBrainInspector : Editor {
RegisterCallback<MouseUpEvent>(OnMouseUp);
}
public void SetGraph(NanoBrainObj brain, Nucleus nucleus, VisualElement inspectorContainer) {
public void SetGraph(GameObject gameObject, NanoBrainObj brain, Nucleus nucleus, VisualElement inspectorContainer) {
this.gameObject = gameObject;
this.brain = brain;
if (Application.isPlaying == false)
this.serializedBrain = new SerializedObject(brain);
@ -398,31 +400,45 @@ public class NanoBrainInspector : Editor {
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.LabelField("Output Value", GUILayout.Width(100));
EditorGUILayout.Vector3Field(GUIContent.none, this.currentNucleus.outputValue);
EditorGUILayout.EndHorizontal();
if (this.currentNucleus.synapses.Count > 0) {
if (this.currentNucleus is Neuroid neuroid) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Activation Curve", GUILayout.Width(150));
if (neuroid.curveMax > 0)
EditorGUILayout.CurveField(neuroid.curve, Color.cyan, new Rect(0, 0, 1, neuroid.curveMax));
else
EditorGUILayout.CurveField(neuroid.curve, Color.cyan, new Rect(0, neuroid.curveMax, 1, -neuroid.curveMax));
neuroid.curvePreset = (Neuroid.CurvePresets)EditorGUILayout.EnumPopup(neuroid.curvePreset, GUILayout.Width(100));
EditorGUILayout.EndHorizontal();
}
if (Application.isPlaying)
EditorGUILayout.FloatField("Output", this.currentNucleus.outputValue.magnitude);
else
EditorGUILayout.LabelField(" ");
if (this.currentNucleus.synapses.Count > 0) {
foreach (Synapse synapse in this.currentNucleus.synapses) {
if (synapse.nucleus != null) {
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(synapse.nucleus.isSleeping);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(synapse.nucleus.name, GUILayout.Width(150));
EditorGUILayout.Vector3Field(GUIContent.none, synapse.nucleus.outputValue); //, GUILayout.Width(180));
EditorGUILayout.EndHorizontal();
if (Application.isPlaying)
EditorGUILayout.FloatField(synapse.nucleus.name, synapse.nucleus.outputValue.magnitude * synapse.weight);
else
EditorGUILayout.LabelField(synapse.nucleus.name);
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
// EditorGUI.BeginChangeCheck();
synapse.weight = EditorGUILayout.FloatField("Weight", synapse.weight);
synapse.curvePreset = (Synapse.CurvePresets)EditorGUILayout.EnumPopup("Preset", synapse.curvePreset);
if (EditorGUI.EndChangeCheck()) {
synapse.curve = synapse.GenerateCurve();
}
if (synapse.curveMax > 0)
EditorGUILayout.CurveField("Curve", synapse.curve, Color.cyan, new Rect(0, 0, 1, synapse.curveMax));
else
EditorGUILayout.CurveField("Curve", synapse.curve, Color.cyan, new Rect(0, synapse.curveMax, 1, -synapse.curveMax));
// synapse.curvePreset = (Synapse.CurvePresets)EditorGUILayout.EnumPopup("Preset", synapse.curvePreset);
// if (EditorGUI.EndChangeCheck()) {
// synapse.curve = synapse.GenerateCurve();
// }
// if (synapse.curveMax > 0)
// EditorGUILayout.CurveField("Curve", synapse.curve, Color.cyan, new Rect(0, 0, 1, synapse.curveMax));
// else
// EditorGUILayout.CurveField("Curve", synapse.curve, Color.cyan, new Rect(0, synapse.curveMax, 1, -synapse.curveMax));
EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup();
}
@ -438,6 +454,11 @@ public class NanoBrainInspector : Editor {
ConnectNucleus(this.currentNucleus);
DisconnectNucleus(this.currentNucleus);
if (this.gameObject != null) {
Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue);
Debug.DrawRay(this.gameObject.transform.position, worldVector, Color.yellow );
}
});
inspectorContainer.Add(container);

File diff suppressed because it is too large Load Diff