using System;
using System.Text;
using UnityEngine;
namespace UOP1.StateMachine
{
///
/// Class specialized in debugging the state transitions, should only be used while in editor mode.
///
[Serializable]
internal class StateMachineDebugger
{
[SerializeField]
[Tooltip("Issues a debug log when a state transition is triggered")]
internal bool debugTransitions = false;
[SerializeField]
[Tooltip("List all conditions evaluated, the result is read: ConditionName == BooleanResult [PassedTest]")]
internal bool appendConditionsInfo = true;
[SerializeField]
[Tooltip("List all actions activated by the new State")]
internal bool appendActionsInfo = true;
[SerializeField]
[Tooltip("The current State name [Readonly]")]
internal string currentState;
private StateMachine _stateMachine;
private StringBuilder _logBuilder;
private string _targetState = string.Empty;
private const string CHECK_MARK = "\u2714";
private const string UNCHECK_MARK = "\u2718";
private const string THICK_ARROW = "\u279C";
private const string SHARP_ARROW = "\u27A4";
///
/// Must be called together with StateMachine.Awake()
///
internal void Awake(StateMachine stateMachine, string initialState)
{
_stateMachine = stateMachine;
_logBuilder = new StringBuilder();
currentState = initialState;
}
internal void TransitionEvaluationBegin(string targetState)
{
_targetState = targetState;
if (!debugTransitions)
return;
_logBuilder.Clear();
_logBuilder.AppendLine($"{_stateMachine.gameObject.name} state changed");
_logBuilder.AppendLine($"{currentState} {SHARP_ARROW} {_targetState}");
if (appendConditionsInfo)
{
_logBuilder.AppendLine();
_logBuilder.AppendLine($"Transition Conditions:");
}
}
internal void TransitionConditionResult(string conditionName, bool result, bool isMet)
{
if (!debugTransitions || _logBuilder.Length == 0 || !appendConditionsInfo)
return;
_logBuilder.Append($" {THICK_ARROW} {conditionName} == {result}");
if (isMet)
_logBuilder.AppendLine($" [{CHECK_MARK}]");
else
_logBuilder.AppendLine($" [{UNCHECK_MARK}]");
}
internal void TransitionEvaluationEnd(bool passed, StateAction[] actions)
{
if (passed)
currentState = _targetState;
if (!debugTransitions || _logBuilder.Length == 0)
return;
if (passed)
{
LogActions(actions);
PrintDebugLog();
}
_logBuilder.Clear();
}
private void LogActions(StateAction[] actions)
{
if (!appendActionsInfo)
return;
_logBuilder.AppendLine();
_logBuilder.AppendLine("State Actions:");
foreach (StateAction action in actions)
{
_logBuilder.AppendLine($" {THICK_ARROW} {action._originSO.name}");
}
}
private void PrintDebugLog()
{
_logBuilder.AppendLine();
_logBuilder.Append("--------------------------------");
Debug.Log(_logBuilder.ToString());
}
}
}