-
Notifications
You must be signed in to change notification settings - Fork 0
KlepGoal
The KLEPGoal is a specialized executable within the KLEP system designed to manage sequences of other executables. It organizes actions, sensors, and routers into structured layers, allowing for complex, multi-step behaviors. This hierarchical approach enables fine-grained control over AI behavior, supporting sequential logic, parallel execution, and conditional progression.
-
Layered Execution Management:
-
Organizes executables into layers (
KlepExecutableLayer
). - Allows multiple executables to fire within a layer based on validation and execution checks.
-
Organizes executables into layers (
-
Dynamic Progression Control:
- Advances through layers automatically if execution conditions are met.
- Supports resetting, pausing, or tracking progress through specific flags.
-
Activation Key Handling:
- Optionally releases an activation key, signaling other behaviors when the goal is active.
-
Event-Driven Design:
- Subscribes to events through the SLASHBridge, allowing reactive behaviors.
private void Awake()
{
int count = 0;
foreach (var layer in executableLayers) // Initialize all layers
{
layer.init(count);
count++;
}
}
- Initializes each executable layer, assigning layer indices.
- Prepares the goal for execution by setting up internal states.
public override void Execute()
{
if (!isInitialized)
{
SubscribeToExecutableEvents();
isInitialized = true;
}
IssueActivationKey(); // Optionally push an activation key
if (!trackProgress)
currentLayerIndex = 0;
while (currentLayerIndex < executableLayers.Count)
{
var currentLayer = executableLayers[currentLayerIndex];
ExecuteLayerExecutables(currentLayer);
bool canAdvance = EvaluateLayerCompletion(currentLayer, false);
if (canAdvance)
currentLayerIndex++;
else
break;
}
if (!IsComplete())
OnFailedToFireAllExecutables();
if (currentLayerIndex >= executableLayers.Count)
currentLayerIndex = 0;
}
-
Execution Order:
- Initialize and subscribe to events if not already done.
- Issue an activation key, if configured.
- Loop through layers, executing executables in the current layer.
- Evaluate if progression is allowed to the next layer.
- If the goal completes, reset the index to avoid overflows.
-
FixedExecute works similarly, but is tied to the physics update cycle.
private void ExecuteLayerExecutables(KlepExecutableLayer layer)
{
failedToFire = false;
oneFired = false;
foreach (var executable in layer.ExecutablesInLayer)
{
if (executable.CanValidate(parentNeuron.heldKeys) && executable.CanExecute(parentNeuron.heldKeys))
{
if (executable.isActiveAndEnabled)
{
executable.ExecutableUpdates();
executable.Execute();
}
oneFired = true;
}
else
{
failedToFire = true;
if (parentNeuron.activateDebugLog && activateDebugOnThisGoal)
Debug.Log("Failed to fire " + executable.executableName);
}
}
}
- Attempts to execute all executables within the current layer.
-
Tracks success and failure through
failedToFire
andoneFired
flags. - Only advances if layer completion conditions are met.
private bool EvaluateLayerCompletion(KlepExecutableLayer layer, bool isFixedUpdate)
{
switch (layer.ExecutionRequirement)
{
case KlepExecutableLayer.LayerExecutionRequirement.AllMustFire:
return !failedToFire && layer.ExecutablesInLayer.All(exe => exe.IsComplete());
case KlepExecutableLayer.LayerExecutionRequirement.AnyCanFire:
return oneFired;
case KlepExecutableLayer.LayerExecutionRequirement.NoneNeedToFire:
return true;
default:
return false;
}
}
-
Layer Execution Requirements:
-
AllMustFire:
All executables in the layer must fire and complete. -
AnyCanFire:
The layer is considered complete if any executable fires. -
NoneNeedToFire:
The layer is always complete, useful for skipping steps.
-
private void IssueActivationKey()
{
string keyName = activationKeyName.NullIfEmpty();
if (keyName == null) return;
var bestMatchingLoader = parentNeuron.keyManager.FindBestMatchingKeyLoader(keyName);
if (bestMatchingLoader == null)
{
Debug.LogWarning($"No suitable key loader found for {keyName}.");
return;
}
PushKeyToNeuron(KeyCreationService.CreateKeyData(activationKeyName, 0f, bestMatchingLoader), executableName);
}
- Pushes an activation key to the neuron or buffer, allowing other executables to react.
- Enables signaling behavior, such as "GoalStarted" or "EnemySpotted".
-
Goal: "Attack Player"
-
Layer 1: Navigate to Player:
- Contains move actions and pathfinding routers.
-
All actions must fire to proceed (
AllMustFire
).
-
Layer 2: Attack Player:
-
Attack action fires if within range (
AnyCanFire
).
-
Attack action fires if within range (
-
Layer 3: Evaluate State:
- Check if the player is dead.
- If player is dead, reset to patrol mode (
NoneNeedToFire
).
-
- KLEPGoal acts as a mini-execution engine, managing sequential and conditional behaviors.
- Organizes actions into layers, allowing for complex multi-step processes.
- Supports dynamic progression, automatic resets, and event-driven behavior.
- Provides fine-grained control over AI behavior, enabling adaptive responses in real-time environments.
- Goals are part of the executable hierarchy, sitting above sensors, routers, and actions.
- Can manage sub-goals, enabling nested decision-making structures.
- Supports both solo and in-tandem executables, offering flexibility in execution strategies.
Would you like further examples, such as combining goals with Q-learning or using activation keys for complex signaling in KLEP? 😊