using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; public class FSM : MonoBehaviour { [SerializeField] private State initialState; [SerializeField] private State currentState; [SerializeField] private NPCController controller; public NPCController Controller => controller; void Awake() { controller = GetComponent<NPCController>(); } void Start() { initialState.InitializeSubStates(); currentState = initialState; //Sets a state } void Update() { if (currentState == null) return; ExecuteState(currentState); } private void ExecuteState(State state) { state.ExecuteActions(this); Transition triggeredTransition = state.GetTriggeredTransition(this); if (triggeredTransition != null) { ChangeState(triggeredTransition.TargetState()); } else if (state.SubStates() != null && state.SubStates().Count > 0) { foreach (State substate in state.SubStates()) { ExecuteState(substate); // Check for triggered transitions in the substate triggeredTransition = substate.GetTriggeredTransition(this); if (triggeredTransition != null) { // If a transition is triggered in the substate, change to the target state ChangeState(triggeredTransition.TargetState()); return; // Exit after transitioning to avoid running further substates } } } } //Changes the current state to a new state public void ChangeState(State newState) { currentState?.ExitAction()?.Execute(this); //Executes the exit action of the current state currentState = newState; //Changes the state currentState?.Enter(this); //Executes entry action } //Returns the current state public State CurrentState() => currentState; //DEBUGING void OnGUI() { float yPosition = 10; float elementHeight = 20; // Height for each line float padding = 5; List<string> actions = new List<string>(); List<string> conditions = new List<string>(); foreach (Action action in currentState.GetActions()) { actions.Add($"Action: {action.name}"); } foreach (Transition transition in currentState.GetTransitions().ToList()) { conditions.Add($"Transition: {transition}\nCondition: {transition.GetCondition().name}: {transition.GetCondition()}"); } // Create a list to hold all the UI elements List<string> uiElements = new List<string> { $"State: {currentState.name}" }; uiElements.AddRange(actions); uiElements.AddRange(conditions); // Define the GUIStyle GUIStyle style = new GUIStyle(); style.fontSize = 14; for (int i = 0; i < uiElements.Count; i++) { if (i == 0) { style.normal.textColor = Color.green; } else { style.normal.textColor = Color.yellow; } // Create the rectangle for each line of text Rect rect = new Rect(10, yPosition, 300, elementHeight); // Display the label with the appropriate style GUI.Label(rect, uiElements[i], style); // Move the yPosition down for the next line yPosition += elementHeight + padding; } } }