You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
7.9 KiB
C#

3 years ago
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<ModeID> modes = new List<ModeID>();
[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<MAnimal>();
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<ModeID>("Attack1");
animal = gameObject.FindComponent<MAnimal>();
modes = new List<ModeID>();
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
}