using System.Collections.Generic; using UnityEngine; namespace Invector.vCharacterController.AI.FSMBehaviour { [vClassHeader(" FSM BEHAVIOUR CONTROLLER", helpBoxText = "Required a AI Controller Component", useHelpBox = true, iconName = "Textures/Editor/FSMIcon2")] public partial class vFSMBehaviourController : vMonoBehaviour, vIFSMBehaviourController { [vEditorToolbar("FSM")] [SerializeField] protected vFSMBehaviour _fsmBehaviour; [SerializeField] protected bool _stop; [SerializeField] protected bool _debugMode; public UnityEngine.Events.UnityEvent onStartFSM; public UnityEngine.Events.UnityEvent onPauseFSM; public UnityEngine.Events.UnityEvent onResetFSM; public FSMStateEvent onStateEnter; public FSMStateEvent onStateExit; public FSMBehaviourEvent onChangeBehaviour; Dictionary _timers = new Dictionary(); vFSMState _currentState; vFSMState _lastState; bool inChangeState; protected virtual void Start() { aiController = GetComponent(); } protected virtual void Update() { if (aiController != null && !aiController.isDead && !isStopped) UpdateStates(); } protected virtual void UpdateStates() { if (currentState) { if(!inChangeState) { currentState.UpdateState(this); UpdateAnyState(); } } else { Entry(); } } public virtual void ResetFSM() { if (currentState) currentState.OnStateExit(this); onResetFSM.Invoke(); currentState = null; } protected virtual void Entry() { if (!_fsmBehaviour) return; if (_fsmBehaviour.states.Count > 1) { currentState = _fsmBehaviour.states[0]; currentState.OnStateEnter(this); } else if (currentState != null) currentState = null; } protected virtual void UpdateAnyState() { // AnyState if (currentState && _fsmBehaviour && _fsmBehaviour.states.Count > 1) { _fsmBehaviour.states[1].UpdateState(this); } } #region FSM Interface public virtual vFSMBehaviour fsmBehaviour { get { return _fsmBehaviour; } set { _fsmBehaviour = value; } } public virtual bool debugMode { get { return _debugMode; } set { _debugMode = value; } } public virtual bool isStopped { get { return _stop; } set { _stop = value; } } public virtual vIControlAI aiController { get; set; } public virtual int indexOffCurrentState { get { return currentState && _fsmBehaviour ? _fsmBehaviour.states.IndexOf(currentState) : -1; } } public virtual string nameOffCurrentState { get { return currentState ? currentState.Name : string.Empty; } } public virtual void SendDebug(string message, UnityEngine.Object sender = null) { if (debugList == null) debugList = new List(); if (debugList.Exists(d => d.sender == sender)) { var debug = debugList.Find(d => d.sender == sender); debug.message = message; } else { debugList.Add(new vFSMDebugObject(message, sender)); } } public virtual List debugList { get;protected set; } public virtual vFSMState anyState { get { return _fsmBehaviour.states.Count > 1? _fsmBehaviour.states[1]:null; } } public virtual vFSMState currentState { get { return _currentState; } protected set { _currentState = value; } } public virtual vFSMState lastState { get { return _lastState; } protected set { _lastState = value; } } public virtual bool HasTimer(string key) { return _timers.ContainsKey(key); } public virtual void RemoveTimer(string key) { if (_timers.ContainsKey(key)) _timers.Remove(key); } public virtual float GetTimer(string key) { if (!_timers.ContainsKey(key)) { _timers.Add(key, 0f); } if (_timers.ContainsKey(key)) { if (debugMode) SendDebug("Get Timer " + key + " = " + _timers[key].ToString("0.0") + " ", gameObject); return _timers[key]; } return 0; } public virtual void SetTimer(string key,float value) { if (!_timers.ContainsKey(key)) { _timers.Add(key, value); } else if (_timers.ContainsKey(key)) { _timers[key] = value; } if (debugMode) SendDebug("Set " + key+ " Timer to " +value.ToString("0.0") +" ", gameObject); } public virtual void ChangeState(vFSMState state) { if (state && state != currentState && !inChangeState) { inChangeState = true; _lastState = currentState; currentState = null; if (_lastState) { if (debugMode) SendDebug("EXIT:" + _lastState.name + "" + " "+" ENTER :" + state.Name + " ", gameObject); _lastState.OnStateExit(this); onStateExit.Invoke(_lastState); } currentState = state; state.OnStateEnter(this); inChangeState = false; onStateEnter.Invoke(state); } } public virtual void ChangeBehaviour(vFSMBehaviour behaviour) { if(_fsmBehaviour !=behaviour) { inChangeState = true; _fsmBehaviour = behaviour; currentState = null; ResetFSM(); if (debugMode) SendDebug("CHANGE BEHAVIOUR TO " + behaviour.name); inChangeState = false; onChangeBehaviour.Invoke(_fsmBehaviour); } } public virtual void StartFSM() { isStopped = false; onStartFSM.Invoke(); } public virtual void StopFSM() { isStopped = true; onPauseFSM.Invoke(); } [System.Serializable] public class FSMStateEvent : UnityEngine.Events.UnityEvent { } [System.Serializable] public class FSMBehaviourEvent : UnityEngine.Events.UnityEvent { } #endregion } }