using MalbersAnimations.Controller; using MalbersAnimations.Scriptables; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace MalbersAnimations { [AddComponentMenu("Malbers/Animal Controller/Mode Align")] public class MModeAlign : MonoBehaviour { [RequiredField] public MAnimal animal; [ContextMenuItem("Attack Mode","AddAttackMode")] public List modes = new List(); [Tooltip("It will search only for Animals on the Radius. If is set to false then it will search for all colliders using the LayerMask")] public bool AnimalsOnly = true; public LayerReference Layer = new LayerReference(-1); [Tooltip("Radius used for the Search") ,UnityEngine.Serialization.FormerlySerializedAs("LookRadius")] [Min(0)] public float SearchRadius = 2f; [Tooltip("Radius used push closer/farther the Target when playing the Mode"), UnityEngine.Serialization.FormerlySerializedAs("DistanceRadius")] [Min(0)] public float Distance = 0; [Tooltip("Time needed to complete the Position aligment")] [Min(0)] public float AlignTime = 0.3f; [Tooltip("Time needed to complete the Rotation aligment")] [Min(0)] public float LookAtTime = 0.15f; public Color debugColor = new Color(1, 0.5f, 0, 0.2f); void Awake() { if (animal == null) animal = this.FindComponent(); if (modes == null || modes.Count == 0) { Debug.LogWarning("Please Add Modes to the Mode Align. ", this); enabled = false; } } void OnEnable() { animal.OnModeStart.AddListener(StartingMode); } void OnDisable() { animal.OnModeStart.RemoveListener(StartingMode); } void StartingMode(int ModeID, int ability) { if (!isActiveAndEnabled) return; if (modes == null || modes.Count == 0 || modes.Exists(x => x.ID == ModeID)) { if (AnimalsOnly) AlignAnimalsOnly(); else Align(); } } private void AlignAnimalsOnly() { MAnimal ClosestAnimal = null; float ClosestDistance = float.MaxValue; foreach (var a in MAnimal.Animals) { if (a == animal || //We are the same animal a.ActiveStateID.ID == StateEnum.Death //The Animal is death || a.Sleep //The Animal is sleep (Not working) || !MTools.Layer_in_LayerMask(a.gameObject.layer, Layer) //Is not using the correct layer ) continue; //Don't Find yourself or don't find death animals var animalsDistance = Vector3.Distance(transform.position, a.Center); if (SearchRadius >= animalsDistance && ClosestDistance >= animalsDistance) { ClosestDistance = animalsDistance; ClosestAnimal = a; } } if (ClosestAnimal) StartAligning(ClosestAnimal.Center); } private void Align() { var pos = animal.Center; var AllColliders = Physics.OverlapSphere(pos, SearchRadius, Layer.Value); Collider ClosestCollider = null; float ClosestDistance = float.MaxValue; foreach (var col in AllColliders) { if (col.transform.root == animal.transform.root) continue; //Don't Find yourself var DistCol = Vector3.Distance(transform.position, col.bounds.center); if (ClosestDistance > DistCol) { ClosestDistance = DistCol; ClosestCollider = col; } } if (ClosestCollider) StartAligning(ClosestCollider.bounds.center); } private void StartAligning(Vector3 TargetCenter) { TargetCenter.y = animal.transform.position.y; Debug.DrawLine(transform.position, TargetCenter, Color.red, 3f); StartCoroutine(MTools.AlignLookAtTransform(animal.transform, TargetCenter, LookAtTime)); if (Distance > 0) StartCoroutine(MTools.AlignTransformRadius(animal.transform, TargetCenter, AlignTime, Distance * animal.ScaleFactor)); //Align Look At the Zone } #if UNITY_EDITOR [ContextMenu("Add Attack Mode")] private void AddAttackMode() { Reset(); } void Reset() { ModeID modeID = MTools.GetResource("Attack1"); animal = gameObject.FindComponent(); modes = new List(); modes.Add(modeID); MTools.SetDirty(this); } void OnDrawGizmosSelected() { if (animal) { UnityEditor.Handles.color = debugColor; UnityEditor.Handles.DrawSolidDisc(transform.position, Vector3.up, SearchRadius); var c = debugColor; c.a = 1; UnityEditor.Handles.color = c; UnityEditor.Handles.DrawWireDisc(transform.position, Vector3.up, SearchRadius); UnityEditor.Handles.color = (c + Color.white) / 2; UnityEditor.Handles.DrawWireDisc(transform.position, Vector3.up, Distance); } } #endif } #if UNITY_EDITOR [CustomEditor(typeof(MModeAlign)),CanEditMultipleObjects] public class MModeAlignEditor : Editor { SerializedProperty animal, modes, AnimalsOnly, Layer, LookRadius, DistanceRadius, AlignTime, LookAtTime, debugColor; private void OnEnable() { animal = serializedObject.FindProperty("animal"); modes = serializedObject.FindProperty("modes"); AnimalsOnly = serializedObject.FindProperty("AnimalsOnly"); Layer = serializedObject.FindProperty("Layer"); LookRadius = serializedObject.FindProperty("SearchRadius"); DistanceRadius = serializedObject.FindProperty("Distance"); AlignTime = serializedObject.FindProperty("AlignTime"); LookAtTime = serializedObject.FindProperty("LookAtTime"); debugColor = serializedObject.FindProperty("debugColor"); } public override void OnInspectorGUI() { serializedObject.Update(); MalbersEditor.DrawDescription($"Execute a LookAt towards the closest Animal or GameObject when is playing a Mode on the list"); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginHorizontal(); { EditorGUILayout.PropertyField(animal); EditorGUILayout.PropertyField(debugColor, GUIContent.none, GUILayout.Width(36)); } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(modes,true); EditorGUI.indentLevel--; EditorGUILayout.PropertyField(AnimalsOnly); EditorGUILayout.PropertyField(Layer); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.PropertyField(LookRadius); if (LookRadius.floatValue > 0) EditorGUILayout.PropertyField(LookAtTime); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.PropertyField(DistanceRadius); if (DistanceRadius.floatValue>0) EditorGUILayout.PropertyField(AlignTime); EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); } } #endif }