Created
December 11, 2024 02:26
-
-
Save millerbyte/8bfedc0fb7d42d6eeb96433072613be9 to your computer and use it in GitHub Desktop.
Objectless State Machine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Godot; | |
| using System; | |
| public class AIStateMachine : Node | |
| { | |
| // Enum to represent states | |
| private enum StateEnum | |
| { | |
| Idle, | |
| Follow, | |
| Attack, | |
| Recover | |
| } | |
| // Struct to represent a state | |
| private struct State | |
| { | |
| public StateEnum StateType; | |
| public int NextStateIndex; // Index of the next state in the array | |
| public Action<StateMachinePayload> UpdateAction; | |
| public State(StateEnum stateType, int nextStateIndex, Action<StateMachinePayload> updateAction) | |
| { | |
| StateType = stateType; | |
| NextStateIndex = nextStateIndex; | |
| UpdateAction = updateAction; | |
| } | |
| } | |
| // Payload shared across all states | |
| private struct StateMachinePayload | |
| { | |
| public Vector3 Position; | |
| public Vector3 TargetPosition; | |
| public bool IsEnemyVisible; | |
| public float AttackCooldown; | |
| // Add other shared data here | |
| } | |
| private State[] states; // Array to hold all states | |
| private StateMachinePayload payload; // Shared payload | |
| private int currentStateIndex; // Current state index | |
| public override void _Ready() | |
| { | |
| // Initialize states | |
| states = new State[] | |
| { | |
| new State(StateEnum.Idle, 1, UpdateIdle), | |
| new State(StateEnum.Follow, 2, UpdateFollow), | |
| new State(StateEnum.Attack, 3, UpdateAttack), | |
| new State(StateEnum.Recover, 0, UpdateRecover) | |
| }; | |
| payload = new StateMachinePayload | |
| { | |
| Position = Vector3.Zero, | |
| TargetPosition = new Vector3(10, 0, 10), | |
| IsEnemyVisible = false, | |
| AttackCooldown = 0 | |
| }; | |
| currentStateIndex = 0; // Start with Idle | |
| } | |
| public override void _Process(float delta) | |
| { | |
| // Call the update function of the current state | |
| states[currentStateIndex].UpdateAction(payload); | |
| } | |
| private void UpdateIdle(StateMachinePayload payload) | |
| { | |
| GD.Print("Idle state: Looking for an enemy..."); | |
| if (payload.IsEnemyVisible) | |
| { | |
| TransitionToState(states[currentStateIndex].NextStateIndex); | |
| } | |
| } | |
| private void UpdateFollow(StateMachinePayload payload) | |
| { | |
| GD.Print("Follow state: Moving towards the target..."); | |
| if ((payload.Position - payload.TargetPosition).Length() < 1f) | |
| { | |
| TransitionToState(states[currentStateIndex].NextStateIndex); | |
| } | |
| } | |
| private void UpdateAttack(StateMachinePayload payload) | |
| { | |
| GD.Print("Attack state: Attacking the enemy..."); | |
| if (payload.AttackCooldown <= 0) | |
| { | |
| TransitionToState(states[currentStateIndex].NextStateIndex); | |
| } | |
| } | |
| private void UpdateRecover(StateMachinePayload payload) | |
| { | |
| GD.Print("Recover state: Cooling down..."); | |
| payload.AttackCooldown -= GetProcessDeltaTime(); | |
| if (payload.AttackCooldown <= 0) | |
| { | |
| TransitionToState(states[currentStateIndex].NextStateIndex); | |
| } | |
| } | |
| private void TransitionToState(int nextStateIndex) | |
| { | |
| GD.Print($"Transitioning from {states[currentStateIndex].StateType} to {states[nextStateIndex].StateType}"); | |
| currentStateIndex = nextStateIndex; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment