using UnityEngine;
namespace EmeraldAI
{
[HelpURL("https://black-horizon-studios.gitbook.io/emerald-ai-wiki/emerald-components-optional/debugger-component")]
public class EmeraldDebugger : MonoBehaviour
{
#region Debugger Variables
public YesOrNo EnableDebuggingTools = YesOrNo.Yes;
public YesOrNo DrawLineOfSightLines = YesOrNo.Yes;
public YesOrNo DrawNavMeshPath = YesOrNo.Yes;
public Color NavMeshPathColor = Color.blue;
public YesOrNo DrawNavMeshDestination = YesOrNo.Yes;
public Color NavMeshDestinationColor = Color.red;
public YesOrNo DrawLookAtPoints = YesOrNo.Yes;
public YesOrNo DrawUndetectedTargetsLine = YesOrNo.Yes;
public YesOrNo DebugLogTargets = YesOrNo.Yes;
public YesOrNo DebugLogObstructions = YesOrNo.Yes;
public YesOrNo DrawFootstepPositions = YesOrNo.Yes;
public YesOrNo DebugLogFootsteps = YesOrNo.Yes;
#endregion
#region Private Variables
EmeraldSystem EmeraldComponent;
EmeraldInverseKinematics IKComponent;
Color DebugLineColor = Color.green;
Vector3 TargetDirection;
Transform DestinationObject;
#endregion
#region Editor Variables
public bool HideSettingsFoldout;
public bool SettingsFoldout;
#endregion
void Start()
{
InitializeDebugger();
}
///
/// Initialize the Debugger Component.
///
void InitializeDebugger ()
{
EmeraldComponent = GetComponent();
IKComponent = GetComponent();
EmeraldComponent.DetectionComponent.OnEnemyTargetDetected += DebugDetectedEnemyTarget; //Subscribe to the OnEnemyTargetDetected delegate for DebugDetectedEnemyTarget
EmeraldComponent.DetectionComponent.OnPlayerDetected += DebugDetectedPlayerTarget; //Subscribe to the OnEnemyTargetDetected delegate for DebugDetectedPlayerTarget
}
public void DebuggerUpdate()
{
if (!enabled) return;
DebugObstructions();
DrawTargetRaycastLines();
DrawUndetectedTargetsLineInternal();
DrawNavMeshPathInternal();
DrawNavMeshDestinationInternal();
}
///
/// Debug logs a message to the Unity Console for testing purposes.
///
public void DebugLogMessage(string Message)
{
Debug.Log(Message);
}
///
/// Debug logs an AI's current obstruction to the Untiy Console.
///
void DebugObstructions()
{
if (EnableDebuggingTools == YesOrNo.No || DebugLogObstructions == YesOrNo.No || !EmeraldComponent.CombatTarget && !EmeraldComponent.LookAtTarget) return;
Transform CurrentObstruction = EmeraldComponent.DetectionComponent.CurrentObstruction;
if (!EmeraldComponent.CombatComponent.DeathDelayActive && EmeraldComponent.CombatTarget && EmeraldComponent.CombatTarget.localScale != Vector3.one * 0.003f && CurrentObstruction)
{
Debug.Log("" + "" + gameObject.name + " - Current Obstruction: " + "" + "" + CurrentObstruction.name + "" + "");
}
}
///
/// Debug logs detected enemy target's information to the Untiy Console.
///
void DebugDetectedEnemyTarget()
{
if (EnableDebuggingTools == YesOrNo.No || DebugLogTargets == YesOrNo.No) return;
if (!EmeraldComponent.CombatComponent.DeathDelayActive)
{
if (EmeraldComponent.CombatTarget != null)
{
Debug.Log("" + "" + gameObject.name + " - Current Combat Target: " + "" + "" + EmeraldComponent.CombatTarget.gameObject.name + "" + "" + " |" +
"" + "" + " Relation Type: " + "" + "" + EmeraldComponent.DetectionComponent.GetTargetFactionRelation(EmeraldComponent.CombatTarget) + "" + "");
}
}
}
///
/// Debug logs detected player target's information to the Untiy Console.
///
void DebugDetectedPlayerTarget()
{
if (EnableDebuggingTools == YesOrNo.No || DebugLogTargets == YesOrNo.No) return;
if (!EmeraldComponent.CombatComponent.DeathDelayActive)
{
if (EmeraldComponent.LookAtTarget != null)
{
Debug.Log("" + "" + gameObject.name + " - Current Look At Target: " + "" + "" + EmeraldComponent.LookAtTarget.gameObject.name + "" + "" + " |" +
"" + "" + " Relation Type: " + "" + "" + EmeraldComponent.DetectionComponent.GetTargetFactionRelation(EmeraldComponent.LookAtTarget) + "" + "");
}
}
}
///
/// Draws the raycast lines between targets and look at targets.
///
void DrawTargetRaycastLines()
{
if (EnableDebuggingTools == YesOrNo.No || DrawLineOfSightLines == YesOrNo.No || EmeraldComponent.CurrentTargetInfo.TargetSource == null) return;
Transform HeadTransform = EmeraldComponent.DetectionComponent.HeadTransform;
if (EmeraldComponent.CombatTarget != null)
{
TargetDirection = EmeraldComponent.CurrentTargetInfo.CurrentICombat.DamagePosition() - HeadTransform.position;
Debug.DrawRay(new Vector3(HeadTransform.position.x, HeadTransform.position.y, HeadTransform.position.z), TargetDirection, DebugLineColor);
}
else if (EmeraldComponent.LookAtTarget != null)
{
Vector3 LookAtTargetDir = EmeraldComponent.CurrentTargetInfo.CurrentICombat.DamagePosition() - HeadTransform.position;
Debug.DrawRay(new Vector3(EmeraldComponent.DetectionComponent.HeadTransform.position.x, HeadTransform.position.y, HeadTransform.position.z), LookAtTargetDir, DebugLineColor);
}
if (EmeraldComponent.DetectionComponent.TargetObstructed || EmeraldComponent.AnimationComponent.IsTurning)
{
DebugLineColor = Color.red;
}
else
{
DebugLineColor = Color.green;
}
}
///
/// Draws lines towards each undetected targets while the AI is still in its Alert state.
///
void DrawUndetectedTargetsLineInternal()
{
if (EnableDebuggingTools == YesOrNo.No || DrawUndetectedTargetsLine == YesOrNo.No) return;
if (EmeraldComponent.DetectionComponent.CurrentDetectionState == EmeraldDetection.DetectionStates.Alert && EmeraldComponent.CombatTarget == null && !EmeraldComponent.AnimationComponent.IsDead)
{
foreach (Collider C in EmeraldComponent.DetectionComponent.LineOfSightTargets.ToArray())
{
Vector3 direction = C.bounds.center - EmeraldComponent.DetectionComponent.HeadTransform.position;
Debug.DrawRay(EmeraldComponent.DetectionComponent.HeadTransform.position, direction, new Color(1, 0.549f, 0));
}
}
}
///
/// Draws the AI's current path with a line.
///
void DrawNavMeshPathInternal ()
{
if (EnableDebuggingTools == YesOrNo.No || DrawNavMeshPath == YesOrNo.No) return;
for (int i = 0; i < EmeraldComponent.m_NavMeshAgent.path.corners.Length; i++)
{
if (i > 0) Debug.DrawLine(EmeraldComponent.m_NavMeshAgent.path.corners[i - 1] + Vector3.up * 0.5f, EmeraldComponent.m_NavMeshAgent.path.corners[i] + Vector3.up * 0.5f, NavMeshPathColor);
else Debug.DrawLine(EmeraldComponent.m_NavMeshAgent.path.corners[0] + Vector3.up * 0.5f, EmeraldComponent.m_NavMeshAgent.path.corners[i] + Vector3.up * 0.5f, NavMeshPathColor);
}
}
///
/// Draws the AI's current destination.
///
void DrawNavMeshDestinationInternal ()
{
if (EnableDebuggingTools == YesOrNo.No || DrawNavMeshDestination == YesOrNo.No) return;
DrawCircle(EmeraldComponent.m_NavMeshAgent.destination, 0.25f, NavMeshDestinationColor);
Debug.DrawLine(EmeraldComponent.m_NavMeshAgent.destination + Vector3.up * 0.5f, EmeraldComponent.m_NavMeshAgent.destination, NavMeshDestinationColor);
}
///
/// Draws the AI's current look at point when using the IK Component.
///
void DrawLookAtPointsInternal()
{
if (DrawLookAtPoints == YesOrNo.No || !IKComponent || !IKComponent.m_AimSource || EmeraldComponent.AnimationComponent.IsDead) return;
Gizmos.color = new Color(1, 0, 0, 0.35f);
Gizmos.DrawSphere(IKComponent.m_AimSource.position, 0.12f);
Gizmos.color = Color.white;
}
void DrawCircle(Vector3 center, float radius, Color color)
{
Vector3 prevPos = center + new Vector3(radius, 0, 0);
for (int i = 0; i < 30; i++)
{
float angle = (float)(i + 1) / 30.0f * Mathf.PI * 2.0f;
Vector3 newPos = center + new Vector3(Mathf.Cos(angle) * radius, 0, Mathf.Sin(angle) * radius);
Debug.DrawLine(prevPos, newPos, color);
prevPos = newPos;
}
}
private void OnDrawGizmos()
{
DrawLookAtPointsInternal();
}
}
}