using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using AlicizaX; using AlicizaX.Fsm; using UnityEngine; public enum PlayerState { Idle, Move, Jump, Dead } public sealed class PlayerBlackBoard : IMemory { public float Hp; public bool Grounded; public Vector3 Pos; public Vector3 Vel; public void Clear() { Hp = 100f; Grounded = true; Pos = Vector3.zero; Vel = Vector3.zero; } } public static class PlayerFSM { public static readonly StateFunc[] Funcs; public static readonly Transition[] Trans; static PlayerFSM() { Funcs = new StateFunc[3]; Funcs[(int)PlayerState.Idle] = StateFunc.Make( (PlayerBlackBoard b) => { }, (PlayerBlackBoard b) => { var h = Input.GetAxisRaw("Horizontal"); var v = Input.GetAxisRaw("Vertical"); if (h != 0 || v != 0) return (int)PlayerState.Move; if (Input.GetKeyDown(KeyCode.Space) && b.Grounded) return (int)PlayerState.Jump; return -1; }, (PlayerBlackBoard b) => { } ); Funcs[(int)PlayerState.Move] = StateFunc.Make( (PlayerBlackBoard b) => { }, (PlayerBlackBoard b) => { var move = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")); if (move.sqrMagnitude < 0.001f) return (int)PlayerState.Idle; b.Pos += move.normalized * 5f * Time.deltaTime; if (Input.GetKeyDown(KeyCode.Space) && b.Grounded) return (int)PlayerState.Jump; return -1; }, (PlayerBlackBoard b) => { } ); Funcs[(int)PlayerState.Jump] = StateFunc.Make( (PlayerBlackBoard b) => { b.Grounded = false; b.Vel = Vector3.up * 5f; }, (PlayerBlackBoard b) => { b.Vel += Physics.gravity * Time.deltaTime; b.Pos += b.Vel * Time.deltaTime; if (b.Pos.y <= 0f) { b.Pos = new Vector3(b.Pos.x, 0f, b.Pos.z); b.Grounded = true; return (int)PlayerState.Idle; } return -1; }, (PlayerBlackBoard b) => { } ); Trans = new Transition[] { new Transition((int)PlayerState.Idle, (int)PlayerState.Dead, (PlayerBlackBoard b) => b.Hp <= 0f, priority: -10), new Transition((int)PlayerState.Move, (int)PlayerState.Dead, (PlayerBlackBoard b) => b.Hp <= 0f, priority: -10), new Transition((int)PlayerState.Jump, (int)PlayerState.Dead, (PlayerBlackBoard b) => b.Hp <= 0f, priority: -10), }; } public static FsmConfig CreateConfig(PlayerState defaultState = PlayerState.Idle) { return new FsmConfig(Funcs, Trans, (int)defaultState); } } public class PlayerController : MonoBehaviour { private Fsm _fsm; void Awake() { // Use pooled blackboard and manager-created FSM (auto debug bind in Editor) var cfg = PlayerFSM.CreateConfig(); _fsm = GameApp.Fsm.Create(cfg, owner: this, stateNameGetter: i => ((PlayerState)i).ToString()); _fsm.Blackboard.Clear(); // ensure default values on start } void Update() { if (Input.GetKeyDown(KeyCode.H)) { _fsm.Blackboard.Hp -= 50f; Debug.Log("HP: " + _fsm.Blackboard.Hp); } if (Input.GetKeyDown(KeyCode.P)) { _fsm.Blackboard.Hp = 100f; _fsm.Reset((int)PlayerState.Idle); Debug.Log("Revived"); } transform.position = _fsm.Blackboard.Pos; } void OnDestroy() { // Return both FSM and BB to their pools via manager helper GameApp.Fsm.DestroyFsm(_fsm); _fsm = null; } }