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.
1606 lines
63 KiB
C#
1606 lines
63 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Events;
|
|
using MalbersAnimations.Events;
|
|
using MalbersAnimations.Scriptables;
|
|
using System;
|
|
using System.Collections;
|
|
using MalbersAnimations.Utilities;
|
|
|
|
namespace MalbersAnimations.Controller
|
|
{
|
|
/// Variables
|
|
public partial class MAnimal
|
|
{
|
|
// public List<bool> StateLocalActive;
|
|
|
|
/// <summary>Sets a Bool Parameter on the Animator using the parameter Hash</summary>
|
|
public System.Action<int, bool> SetBoolParameter { get; set; } = delegate { };
|
|
/// <summary>Sets a float Parameter on the Animator using the parameter Hash</summary>
|
|
public System.Action<int, float> SetFloatParameter { get; set; } = delegate { };
|
|
|
|
/// <summary>Sets a Integer Parameter on the Animator using the parameter Hash</summary>
|
|
public System.Action<int, int> SetIntParameter { get; set; } = delegate { };
|
|
|
|
/// <summary>Sets a Trigger Parameter on the Animator using the parameter Hash</summary>
|
|
public System.Action<int> SetTriggerParameter { get; set; } = delegate { };
|
|
|
|
/// <summary>Check when a Animation State is Starting</summary>
|
|
public System.Action<int> StateCycle { get; set; }
|
|
|
|
/// <summary>Invoked after the ActiveState execute its code</summary>
|
|
public System.Action<MAnimal> PreStateMovement = delegate { };
|
|
|
|
/// <summary>Invoked after the ActiveState execute its code</summary>
|
|
public System.Action<MAnimal> PostStateMovement = delegate { };
|
|
|
|
/// <summary>Get all the Animator Parameters the Animal Controller has</summary>
|
|
private List<int> animatorHashParams;
|
|
//private Hashtable animatorParams;
|
|
|
|
#region Static Properties
|
|
/// <summary>List of all the animals on the scene</summary>
|
|
public static List<MAnimal> Animals;
|
|
/// <summary>Main Animal used as the player controlled by Input</summary>
|
|
public static MAnimal MainAnimal;
|
|
#endregion
|
|
|
|
#region States
|
|
|
|
|
|
/// <summary>NECESARY WHEN YOU ARE USING MULTIPLE ANIMALS</summary>
|
|
public bool CloneStates = true;
|
|
|
|
[Tooltip("The Animal gameObject will have no Parent on the Hierarchy. (Recommended)")]
|
|
public bool NoParent = true;
|
|
|
|
///<summary> List of States for this animal </summary>
|
|
public List<State> states = new List<State>();
|
|
|
|
///<summary>On Which State the animal should Start on Enable</summary>
|
|
public StateID OverrideStartState;
|
|
|
|
/// <summary> Current State. Changing this variable wil not exectute the Active State logic</summary>
|
|
internal State activeState;
|
|
/// <summary> Store the Last State, This will not change the Last State parameter on the animator</summary>
|
|
internal State lastState;
|
|
|
|
internal State queueState;
|
|
|
|
/// <summary> Check if a State wsa queued and if it can be released because it was activated </summary>
|
|
public bool QueueReleased => QueueState != null && QueueState.OnActiveQueue && !QueueState.OnQueue;
|
|
|
|
/// <summary> Store the current queue State </summary>
|
|
public State QueueState { get => queueState; internal set => queueState = value;}
|
|
|
|
|
|
/// <summary> Store the Last State </summary>
|
|
public State LastState
|
|
{
|
|
get => lastState;
|
|
internal set
|
|
{
|
|
//Debug.Log("value = " + value);
|
|
|
|
// if (value != lastState) //Change when its different (Stack overflow BUG)
|
|
{
|
|
lastState = value;
|
|
LastState.EnterExitEvent?.OnExit.Invoke();
|
|
|
|
LastState.ExitState();
|
|
|
|
var LastStateID = (QueueState == null) ? lastState.ID.ID : QueueState.ID.ID;
|
|
|
|
// Debug.Log("LastStateID = " + LastStateID);
|
|
SetIntParameter(hash_LastState, LastStateID); //Sent to the Animator the previews Active State
|
|
}
|
|
}
|
|
}
|
|
|
|
///<summary> Store a State (PreState) that can be used later</summary>
|
|
protected State Pin_State;
|
|
|
|
/// <summary>Used to call the Last State one more time before it changes to the new state </summary>
|
|
public bool JustActivateState { get; internal set; }
|
|
|
|
/// <summary> ID of the Current Active State</summary>
|
|
public StateID ActiveStateID { get; private set; }
|
|
|
|
|
|
/// <summary>State Float Value</summary>
|
|
public float State_Float { get; private set; }
|
|
|
|
/// <summary>Set/Get the Active State</summary>
|
|
public State ActiveState
|
|
{
|
|
get => activeState;
|
|
internal set
|
|
{
|
|
activeState = value;
|
|
|
|
if (value == null) return;
|
|
|
|
JustActivateState = true;
|
|
|
|
if (LastState != null && LastState.ExitFrame) LastState.OnStateMove(DeltaTime); //Play One Last Time the Last State
|
|
|
|
this.Delay_Action(() => { JustActivateState = false; }); //Reset Just Activate State The next Frame
|
|
ActiveStateID = activeState.ID;
|
|
|
|
OnStateActivate.Invoke(activeState.ID);
|
|
|
|
SetIntParameter(hash_State, activeState.ID.ID); //Sent to the Animator the value to Apply
|
|
// Debug.Log("hash_State = " + activeState.ID.ID);
|
|
|
|
SetOptionalAnimParameter(hash_StateOn); //Use trigger in case the Animal is using Triggers
|
|
Strafe = Strafe; // Execute the code inside in case has changed
|
|
|
|
if (!activeState.ValidStance(currentStance)) Stance_Reset();
|
|
|
|
foreach (var st in states) st.NewActiveState(activeState.ID); //Notify all states that a new state has been activated
|
|
|
|
Set_Sleep_FromStates(activeState);
|
|
Check_Queue_States(activeState.ID); //Check if a queue State was released
|
|
|
|
|
|
if (IsPlayingMode && ActiveMode.StateCanInterrupt(ActiveStateID))//If a mode is playing check a State Change
|
|
{
|
|
Mode_Interrupt();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>When a new State is Activated, Make sure the other States are sent to sleep</summary>
|
|
internal void Set_Sleep_FromStates(State state)
|
|
{
|
|
foreach (var st in states)
|
|
{
|
|
st.IsSleepFromState = st.SleepFromState.Contains(state.ID); //Sent to sleep states that has some Avoid State
|
|
st.IsSleepFromState ^= !st.IncludeSleepState;
|
|
}
|
|
}
|
|
|
|
/// <summary>Check if there's a State that cannot be enabled when playing a mode </summary>
|
|
internal virtual void Set_State_Sleep_FromMode(bool playingMode)
|
|
{
|
|
foreach (var state in states)
|
|
state.IsSleepFromMode = playingMode && state.SleepFromMode.Contains(ActiveMode.ID);
|
|
}
|
|
|
|
|
|
/// <summary>Check if there's a State that cannot be enabled when playing a mode </summary>
|
|
internal virtual void Set_State_Sleep_FromStance()
|
|
{
|
|
foreach (var state in states)
|
|
state.IsSleepFromStance = state.SleepFromStance.Contains(Stance);
|
|
}
|
|
|
|
/// <summary>When a new State is Activated, Make sure the other States are sent to sleep</summary>
|
|
internal virtual void Check_Queue_States(StateID ID)
|
|
{
|
|
foreach (var st in states)
|
|
{
|
|
st.OnQueue = st.QueueFrom.Contains(ID); //Sent to sleep states that has some Avoid State
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region General
|
|
/// <summary> Layers the Animal considers ground</summary>
|
|
[SerializeField] private LayerReference groundLayer = new LayerReference(1);
|
|
|
|
/// <summary> Layers the Animal considers ground</summary>
|
|
public LayerMask GroundLayer => groundLayer.Value;
|
|
|
|
/// <summary>Distance from the Pivots to the ground </summary>
|
|
public float height = 1f;
|
|
/// <summary>Height from the ground to the hip multiplied for the Scale Factor</summary>
|
|
public float Height => (height) * ScaleFactor;
|
|
|
|
/// <summary>The Scale Factor of the Animal.. if the animal has being scaled this is the multiplier for the raycasting things </summary>
|
|
public float ScaleFactor => transform.localScale.y;
|
|
|
|
/// <summary>Does this Animal have an InputSource </summary>
|
|
public IInputSource InputSource;
|
|
|
|
[SerializeField] private Vector3 center;
|
|
/// <summary>Center of the Animal to be used for AI and Targeting based on World Position</summary>
|
|
public Vector3 Center
|
|
{
|
|
private set => center = value;
|
|
get => transform.TransformPoint(center);
|
|
}
|
|
#endregion
|
|
|
|
#region Stance
|
|
|
|
[SerializeField] private StanceID currentStance;
|
|
[SerializeField] private StanceID defaultStance;
|
|
|
|
|
|
/// <summary>Last Stance the Animal was</summary>
|
|
public int LastStance { get; private set; }
|
|
|
|
public StanceID DefaultStance { get => defaultStance; set => defaultStance = value; }
|
|
|
|
|
|
|
|
/// <summary>Current Active Stance</summary>
|
|
public StanceID Stance
|
|
{
|
|
get => currentStance;
|
|
set
|
|
{
|
|
if (Sleep || !enabled) return; //Do nothing if is not active
|
|
if (!ActiveState.ValidStance(value)) return; //Do not Activate any new stance if the STATE does not allow it
|
|
|
|
LastStance = currentStance;
|
|
currentStance = value;
|
|
|
|
var exit = OnEnterExitStances.Find(st => st.ID.ID == LastStance);
|
|
exit?.OnExit.Invoke();
|
|
OnStanceChange.Invoke(value);
|
|
var enter = OnEnterExitStances.Find(st => st.ID.ID == value);
|
|
enter?.OnEnter.Invoke();
|
|
|
|
Set_State_Sleep_FromStance();
|
|
|
|
if (debugStances)
|
|
{
|
|
Debug.Log($"<B>[{name}]</B> → <B>[Set Stance] → <color=yellow>{value.name} [{value.ID}]</color></B>");
|
|
}
|
|
|
|
SetOptionalAnimParameter(hash_Stance, currentStance.ID); //Set on the Animator the Current Stance
|
|
SetOptionalAnimParameter(hash_LastStance, LastStance); //Set on the Animator the Last Stance
|
|
SetOptionalAnimParameter(hash_StateOn); //Set on the Animator the Trigger Stance
|
|
|
|
if (!JustActivateState) SetIntParameter(hash_LastState, ActiveStateID); //Sent to the Animator the previews Active State (BUG)
|
|
|
|
ActiveState.SetSpeed(); //Check if the speed modifier has changed when you have a new Stance
|
|
|
|
if (IsPlayingMode && ActiveMode.StanceCanInterrupt(currentStance))//If a mode is playing check a State Change
|
|
{
|
|
Mode_Interrupt();
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Movement
|
|
|
|
/// <summary> Global Animator Speed for the Animal </summary>
|
|
public FloatReference AnimatorSpeed = new FloatReference(1);
|
|
|
|
//public FloatReference MovementDeathValue = new FloatReference(0.05f);
|
|
[SerializeField] private BoolReference alwaysForward = new BoolReference(false);
|
|
|
|
/// <summary>Sets to Zero the Z on the Movement Axis when this is set to true</summary>
|
|
[Tooltip("Sets to Zero the Z on the Movement Axis when this is set to true")]
|
|
[SerializeField] private BoolReference lockForwardMovement = new BoolReference(false);
|
|
/// <summary>Sets to Zero the X on the Movement Axis when this is set to true</summary>
|
|
[Tooltip("Sets to Zero the X on the Movement Axis when this is set to true")]
|
|
[SerializeField] private BoolReference lockHorizontalMovement = new BoolReference(false);
|
|
/// <summary>Sets to Zero the Y on the Movement Axis when this is set to true</summary>
|
|
[Tooltip("Sets to Zero the Y on the Movement Axis when this is set to true")]
|
|
[SerializeField] private BoolReference lockUpDownMovement = new BoolReference(false);
|
|
|
|
////public bool AdditiveX;
|
|
////public bool AdditiveY;
|
|
//[Tooltip("The Up Down Input is interpreted as Additive (Spyro Underwater Movement Style)")]
|
|
//public bool AdditiveUp;
|
|
|
|
/// <summary>Multiplier to Add or Remove Forward Movement to the Animal, Used when the Animal Rotates in Place</summary>
|
|
public float ForwardMultiplier { get; set; }
|
|
|
|
/// <summary>(Z), horizontal (X) and Vertical (Y) Movement Input</summary>
|
|
public Vector3 MovementAxis;
|
|
|
|
/// <summary>(Z), horizontal (X) and Vertical (Y) Raw Movement Input</summary>
|
|
public Vector3 MovementAxisRaw;// { get; set; }
|
|
//{
|
|
// get => movementAxisRaw;
|
|
// set
|
|
// {
|
|
// movementAxisRaw = value;
|
|
// Debug.Log($"movementAxisRaw: {movementAxisRaw} ");
|
|
// }
|
|
//}
|
|
//Vector3 movementAxisRaw;
|
|
|
|
/// <summary>Current Raw Input Axis gotted from an Input Entry </summary>
|
|
public Vector3 RawInputAxis;// { get; set; }
|
|
//{
|
|
// get => rawInputAxis;
|
|
// set
|
|
// {
|
|
// rawInputAxis = value;
|
|
// Debug.Log($"RawInputAxis: {rawInputAxis} ");
|
|
// }
|
|
//}
|
|
//Vector3 rawInputAxis;
|
|
|
|
|
|
/// <summary>The Animal is using Input instead of a Direction to move</summary>
|
|
public bool UseRawInput { get; internal set; }
|
|
//{
|
|
// get => useRawInput;
|
|
// set
|
|
// {
|
|
// useRawInput = value;
|
|
// Debug.Log($"useRawInput: {useRawInput} ");
|
|
// }
|
|
//}
|
|
//bool useRawInput;
|
|
|
|
/// <summary>Forward (Z), horizontal (X) and Vertical (Y) Smoothed Movement Input AFTER aplied Speeds Multipliers (THIS GOES TO THE ANIMATOR)</summary>
|
|
public Vector3 MovementAxisSmoothed;
|
|
|
|
|
|
/// <summary>The animal will always move forward</summary>
|
|
public bool AlwaysForward
|
|
{
|
|
get => alwaysForward.Value;
|
|
set
|
|
{
|
|
alwaysForward.Value = value;
|
|
MovementAxis.z = alwaysForward.Value ? 1 : 0;
|
|
MovementDetected = AlwaysForward;
|
|
}
|
|
}
|
|
|
|
/// <summary>[Raw Direction the Character will go Using Inputs or a Move Direction</summary>
|
|
public Vector3 Move_Direction;
|
|
// public Vector3 MoveDirection => Move_Direction;
|
|
|
|
|
|
private bool movementDetected;
|
|
|
|
/// <summary>Checking if the movement input was activated</summary>
|
|
public bool MovementDetected
|
|
{
|
|
get => movementDetected;
|
|
internal set
|
|
{
|
|
if (movementDetected != value)
|
|
{
|
|
movementDetected = value;
|
|
OnMovementDetected.Invoke(value);
|
|
SetBoolParameter(hash_Movement, MovementDetected);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>The Animal uses the Camera Forward Diretion to Move</summary>
|
|
public BoolReference useCameraInput = new BoolReference(true);
|
|
|
|
/// <summary>Use the Camera Up Vector to Move while flying or Swiming UnderWater</summary>
|
|
public BoolReference useCameraUp = new BoolReference();
|
|
|
|
/// <summary>Store the Starting Use camera Input Value</summary>
|
|
public bool DefaultCameraInput { get; set; }
|
|
|
|
public void ResetCameraInput() => UseCameraInput = DefaultCameraInput; //Restore to the default camera input on the Animal
|
|
|
|
/// <summary>Use the Camera Up Vector to Move while flying or Swiming UnderWater</summary>
|
|
public bool UseCameraUp { get => useCameraUp.Value; set => useCameraUp.Value = value; }
|
|
|
|
/// <summary>The Animal uses the Camera Forward Direction to Move</summary>
|
|
public bool UseCameraInput
|
|
{
|
|
get => useCameraInput.Value;
|
|
set { useCameraInput.Value = UsingMoveWithDirection = value; }
|
|
}
|
|
|
|
/// <summary> Is the animal using a Direction Vector for moving(True) or a World Axis Input (False)</summary>
|
|
public bool UsingMoveWithDirection { set; get; }
|
|
//{
|
|
// get => usingMoveWithDirection;
|
|
// set
|
|
// {
|
|
// usingMoveWithDirection = value;
|
|
// Debug.Log("UsingMoveWithDirection = " + value);
|
|
// }
|
|
//}
|
|
|
|
//private bool usingMoveWithDirection;
|
|
|
|
/// <summary> Is the animal using a Direction Vector for rotate in place(true?)</summary>
|
|
public bool Rotate_at_Direction { set; get; }
|
|
|
|
/// <summary>Main Camera on the Game</summary>
|
|
public TransformReference m_MainCamera = new TransformReference();
|
|
|
|
public Transform MainCamera => m_MainCamera.Value;
|
|
|
|
|
|
[SerializeField] private bool additivePosLog;
|
|
[SerializeField] private bool additiveRotLog;
|
|
|
|
|
|
private void DebLogAdditivePos()
|
|
{
|
|
additivePosLog ^= true;
|
|
MTools.SetDirty(this);
|
|
}
|
|
|
|
private void DebLogAdditiveRot()
|
|
{
|
|
additiveRotLog ^= true;
|
|
MTools.SetDirty(this);
|
|
}
|
|
[ContextMenuItem("Debug AdditivePos", nameof(DebLogAdditivePos))]
|
|
[ContextMenuItem("Debug AdditiveRot", nameof(DebLogAdditiveRot))]
|
|
|
|
/// <summary>Is this animal is the main Player?</summary>
|
|
public BoolReference isPlayer = new BoolReference(true);
|
|
|
|
|
|
/// <summary> Additive Position Modifications for the animal (Terrian Snapping, Speed Modifiers Positions, etc)</summary>
|
|
public Vector3 AdditivePosition//;
|
|
{
|
|
get => additivePosition;
|
|
set
|
|
{
|
|
additivePosition = value;
|
|
if (additivePosLog)
|
|
Debug.Log($"Additive Pos: {(additivePosition / DeltaTime)} ");
|
|
}
|
|
}
|
|
internal Vector3 additivePosition;
|
|
|
|
/// <summary> Additive Rotation Modifications for the animal (Terrian Aligment, Speed Modifiers Rotations, etc)</summary>
|
|
public Quaternion AdditiveRotation
|
|
{
|
|
get => additiveRotation;
|
|
set
|
|
{
|
|
additiveRotation = value;
|
|
if (additiveRotLog) Debug.Log($"Additive ROT: {(additiveRotation):F3} ");
|
|
}
|
|
}
|
|
Quaternion additiveRotation;
|
|
|
|
|
|
|
|
|
|
/// <summary>Inertia Speed to smoothly change the Speed Modifiers </summary>
|
|
public Vector3 InertiaPositionSpeed { get; internal set; }
|
|
//{
|
|
// get => InertiaPPS;
|
|
// set
|
|
// {
|
|
// InertiaPPS = value;
|
|
// Debug.Log($"InertiaPositionSpeed: {(InertiaPPS):F3} ");
|
|
// }
|
|
//}
|
|
//Vector3 InertiaPPS;
|
|
|
|
|
|
[SerializeField] private BoolReference SmoothVertical = new BoolReference(true);
|
|
|
|
[Tooltip("Global turn multiplier to increase rotation on the animal")]
|
|
public FloatReference TurnMultiplier = new FloatReference(0f);
|
|
|
|
[Tooltip("Smooth Damp Value to Turn in place, when using LookAt Direction Instead of Move()")]
|
|
public FloatReference inPlaceDamp = new FloatReference(2f);
|
|
|
|
/// <summary>Difference from the Last Frame and the Current Frame</summary>
|
|
public Vector3 DeltaPos { get; internal set; }
|
|
//{
|
|
// set
|
|
// {
|
|
// m_DeltaPos = value;
|
|
// Debug.Log($"DeltaPos POS: {(m_DeltaPos / DeltaTime):F3} ");
|
|
// }
|
|
// get => m_DeltaPos;
|
|
//}
|
|
//Vector3 m_DeltaPos;
|
|
|
|
|
|
/// <summary>World Position on the last Frame</summary>
|
|
public Vector3 LastPos { get; internal set; }
|
|
|
|
/// <summary>Velocity acumulated from the last Frame</summary>
|
|
public Vector3 Inertia => DeltaPos / DeltaTime;
|
|
|
|
/// <summary>Difference between the Current Rotation and the desire Input Rotation </summary>
|
|
public float DeltaAngle { get; internal set; }
|
|
|
|
/// <summary>Pitch direction used when Free Movement is Enable (Direction of the Move Input) </summary>
|
|
public Vector3 PitchDirection { get; internal set; }
|
|
/// <summary>Pitch Angle </summary>
|
|
public float PitchAngle { get; internal set; }
|
|
/// <summary>Bank</summary>
|
|
public float Bank { get; internal set; }
|
|
|
|
/// <summary>Speed from the Vertical input multiplied by the speeds inputs(Walk Trot Run) this is the value thats goes to the Animator, is not the actual Speed of the animals</summary>
|
|
public float VerticalSmooth { get => MovementAxisSmoothed.z; internal set => MovementAxisSmoothed.z = value; }
|
|
|
|
/// <summary>Direction from the Horizontal input multiplied by the speeds inputs this is the value thats goes to the Animator, is not the actual Speed of the animals</summary>
|
|
public float HorizontalSmooth { get => MovementAxisSmoothed.x; internal set => MovementAxisSmoothed.x = value; }
|
|
|
|
/// <summary>Direction from the Up Down input multiplied by the speeds inputs this is the value thats goes to the Animator, is not the actual Speed of the animals</summary>
|
|
public float UpDownSmooth
|
|
{
|
|
get => MovementAxisSmoothed.y;
|
|
internal set
|
|
{
|
|
MovementAxisSmoothed.y = value;
|
|
// Debug.Log("UD" + value);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary> Vertical (Y) Difference between Target and Current UpDown</summary>
|
|
public float DeltaUpDown { get; internal set; }
|
|
|
|
|
|
/// <summary> If true it will keep the Controller smooth push of the movement stick</summary>
|
|
public bool UseSmoothVertical { get => SmoothVertical.Value; set => SmoothVertical.Value = value; }
|
|
|
|
|
|
/// <summary> The current value of the Delta time the animal is using (Fixed or not)</summary>
|
|
public float DeltaTime { get; private set; }
|
|
|
|
#endregion
|
|
|
|
#region Alignment Ground
|
|
/// <summary>Smoothness value to Snap to ground </summary>
|
|
public FloatReference AlignPosLerp = new FloatReference(15f);
|
|
/// <summary>Smoothness Position value when Entering from Non Grounded States</summary>
|
|
public FloatReference AlignPosDelta = new FloatReference(2.5f);
|
|
/// <summary>Smoothness Rotation value when Entering from Non Grounded States</summary>
|
|
public FloatReference AlignRotDelta = new FloatReference(2.5f);
|
|
|
|
/// <summary>Smoothness Position value when Entering from Non Grounded States </summary>
|
|
public float AlignPosLerpDelta { get; private set; }
|
|
|
|
/// <summary>Smoothness Rotation value when Entering from non Grounded States </summary>
|
|
public float AlignRotLerpDelta { get; private set; }
|
|
|
|
|
|
/// <summary>Smoothness value to Snap to ground </summary>
|
|
public FloatReference AlignRotLerp = new FloatReference(15f);
|
|
|
|
|
|
public IntReference AlignLoop = new IntReference(1);
|
|
|
|
[Tooltip("Tag your small rocks, debris,steps and stair objects with this Tag. It will help the animal to recognize better the Terrain")]
|
|
public StringReference DebrisTag = new StringReference("Stair");
|
|
|
|
/// <summary>Maximun angle on the terrain the animal can walk </summary>
|
|
[Range(1f, 90f), Tooltip("Maximun angle on the terrain the animal can walk")]
|
|
public float maxAngleSlope = 45f;
|
|
|
|
/// <summary>Main Pivot Slope Angle</summary>
|
|
public float MainPivotSlope { get; private set; }
|
|
|
|
/// <summary>Used to add extra Rotations to the Animal</summary>
|
|
public Transform Rotator;
|
|
public Transform RootBone;
|
|
|
|
/// <summary>Check if can Fall on slope while on the ground "Decline Slope"</summary>
|
|
public bool DeepSlope => TerrainSlope < -maxAngleSlope;
|
|
|
|
/// <summary>Check if the Animal is on any Slope</summary>
|
|
public bool isinSlope => Mathf.Abs(TerrainSlope) > maxAngleSlope;
|
|
|
|
/// <summary>Speed of the Animal used on the Rigid Body (Used on Custom Speed Modifiers)</summary>
|
|
public float HorizontalSpeed { get; private set; }
|
|
|
|
/// <summary>Velocity of the Animal used on the RIgid Body (Useful for Speed Modifiers)</summary>
|
|
public Vector3 HorizontalVelocity { get; private set; }
|
|
|
|
|
|
/// <summary>Calculation of the Average Surface Normal</summary>
|
|
public Vector3 SurfaceNormal { get; internal set; }
|
|
|
|
/// <summary>Calculate slope Angle and normalize it with the Max Angle Slope</summary>
|
|
public float SlopeNormalized => TerrainSlope / maxAngleSlope; //Normalize the AngleSlop by the MAX Angle Slope and make it positive(HighHill) or negative(DownHill)
|
|
|
|
/// <summary>Slope Calculate from the Surface Normal. Positive = Higher Slope, Negative = Lower Slope </summary>
|
|
public float TerrainSlope { get; private set; }
|
|
|
|
|
|
[SerializeField] private BoolReference grounded = new BoolReference(false);
|
|
/// <summary> Is the Animal on a surface, when True the Raycasting for the Ground is Applied</summary>
|
|
public bool Grounded
|
|
{
|
|
get => grounded.Value;
|
|
set
|
|
{
|
|
if (grounded.Value != value)
|
|
{
|
|
grounded.Value = value;
|
|
|
|
if (!value)
|
|
{
|
|
platform = null; //If groundes is false remove the stored Platform
|
|
}
|
|
else
|
|
{
|
|
ResetGravityValues();
|
|
Force_Reset();
|
|
|
|
UpDownAdditive = 0; //Reset UpDown Additive
|
|
UsingUpDownExternal = false; //Reset UpDown Additive
|
|
GravityMultiplier = 1;
|
|
ExternalForceAirControl = true; //Reset the External Force Air Control
|
|
}
|
|
|
|
SetBoolParameter(hash_Grounded, grounded.Value);
|
|
}
|
|
OnGrounded.Invoke(value);
|
|
// Debug.Log("Grounded: " + value);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region External Force
|
|
|
|
/// <summary>Add an External Force to the Animal</summary>
|
|
public Vector3 ExternalForce { get; set; }
|
|
|
|
/// <summary>Current External Force the animal current has</summary>
|
|
public Vector3 CurrentExternalForce { get; set; }
|
|
public bool LocalForce { get; set; }
|
|
//{
|
|
// set
|
|
// {
|
|
// m_CurrentExternalForce = value;
|
|
// Debug.Log($"CurrentExternalForce: {m_CurrentExternalForce} ");
|
|
// }
|
|
// get => m_CurrentExternalForce;
|
|
//}
|
|
//Vector3 m_CurrentExternalForce;
|
|
|
|
/// <summary>External Force Aceleration /summary>
|
|
public float ExternalForceAcel { get; set; }
|
|
|
|
/// <summary>External Force Air Control, Can it be controlled while on the air?? </summary>
|
|
public bool ExternalForceAirControl { get; set; }
|
|
|
|
public bool HasExternalForce => ExternalForce != Vector3.zero;
|
|
#endregion
|
|
|
|
#region References
|
|
/// <summary>Returns the Animator Component of the Animal </summary>
|
|
|
|
[RequiredField] public Animator Anim;
|
|
[RequiredField] public Rigidbody RB; //Reference for the RigidBody
|
|
|
|
/// <summary>Transform.UP (Stored)</summary>
|
|
public Vector3 Up => transform.up;
|
|
/// <summary>Transform.Right (Stored)</summary>
|
|
public Vector3 Right => transform.right;
|
|
/// <summary>Transform.Forward (Stored) </summary>
|
|
public Vector3 Forward => transform.forward;
|
|
|
|
|
|
#endregion
|
|
|
|
#region Modes
|
|
/// <summary>Allows the Animal Start Playing a Mode</summary>
|
|
public IntReference StartWithMode = new IntReference(0);
|
|
|
|
/// <summary>Status value for the Mode (-1: Loop, -2: Interrupted, 0: Available</summary>
|
|
public int ModeStatus { get; private set; }
|
|
|
|
/// <summary>Float value for the Mode</summary>
|
|
public float ModePower { get; set; }
|
|
|
|
// private int modeStatus;
|
|
private Mode activeMode;
|
|
|
|
///<summary> List of States for this animal </summary>
|
|
public List<Mode> modes = new List<Mode>();
|
|
|
|
/// <summary>Is Playing a mode on the Animator</summary>
|
|
public bool IsPlayingMode => activeMode != null;
|
|
|
|
/// <summary>A mode is Set, but the Animation has not started yet</summary>
|
|
public bool IsPreparingMode { get; set; }
|
|
//{
|
|
// get => m_IsPreparingMode;
|
|
// internal set
|
|
// {
|
|
// m_IsPreparingMode = value;
|
|
// Debug.Log("m_IsPreparingMode: " + m_IsPreparingMode);
|
|
// }
|
|
//}
|
|
//bool m_IsPreparingMode;
|
|
|
|
public Zone Zone { get; internal set; }
|
|
|
|
/// <summary>ID Value for the Last Mode Played </summary>
|
|
public int LastModeID { get; internal set; }
|
|
|
|
/// <summary>ID Value for the Last Ablity Played </summary>
|
|
public int LastAbilityIndex { get; internal set; }
|
|
|
|
|
|
/// <summary>Set/Get the Active Mode, Prepare the values for the Animator... Does not mean the Mode is Playing</summary>
|
|
public Mode ActiveMode
|
|
{
|
|
get => activeMode;
|
|
internal set
|
|
{
|
|
var lastMode = activeMode;
|
|
activeMode = value;
|
|
ModeTime = 0;
|
|
|
|
if (value != null)
|
|
{
|
|
OnModeStart.Invoke(ActiveModeID = value.ID, value.AbilityIndex);
|
|
ActiveState.OnModeStart(activeMode);
|
|
}
|
|
else
|
|
{
|
|
ActiveModeID = 0;
|
|
}
|
|
|
|
if (lastMode != null)
|
|
{
|
|
LastModeID = lastMode.ID;
|
|
LastAbilityIndex = lastMode.AbilityIndex;
|
|
OnModeEnd.Invoke(lastMode.ID, LastAbilityIndex);
|
|
ActiveState.OnModeEnd(lastMode);
|
|
// Stance = Stance; //Updates the Stance Code ??
|
|
}
|
|
// Debug.Log("IsPlayingMode = " + IsPlayingMode);
|
|
}
|
|
}
|
|
|
|
/// <summary>Set the Values to the Animator to Enable a mode... Does not mean that the mode is enabled</summary>
|
|
internal virtual void SetModeParameters(Mode value, int status)
|
|
{
|
|
if (value != null)
|
|
{
|
|
var ability = (value.ActiveAbility != null ? (int)value.ActiveAbility.Index : 0);
|
|
|
|
int mode = Mathf.Abs(value.ID * 1000) + Mathf.Abs(ability); //Convert it into a 4 int value Ex: Attack 1001
|
|
|
|
//If the Mode is negative or the Ability is negative then Set the Animator Parameter negative too. (Right Left Abilities)
|
|
ModeAbility = (value.ID < 0 || ability < 0) ? -mode : mode;
|
|
|
|
SetOptionalAnimParameter(hash_ModeOn); //Activate the Optional Trigger
|
|
|
|
//IMPORTANT WHEN IS MAKING SOME RANDOM STUFF
|
|
|
|
if (hash_ModeOn != 0 && status != 0) //Only send the mode status when we are using Mode ON
|
|
SetModeStatus(status);
|
|
else
|
|
SetModeStatus(status); //Normal way
|
|
|
|
IsPreparingMode = true;
|
|
ModeTime = 0;
|
|
}
|
|
else
|
|
{
|
|
SetModeStatus(Int_ID.Available);
|
|
ModeAbility = 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>Current Mode ID and Ability Append Together (ModeID*100+AbilityIndex)</summary>
|
|
public int ModeAbility
|
|
{
|
|
get => m_ModeIDAbility;
|
|
internal set
|
|
{
|
|
m_ModeIDAbility = value;
|
|
SetIntParameter?.Invoke(hash_Mode, m_ModeIDAbility);
|
|
}
|
|
}
|
|
private int m_ModeIDAbility;
|
|
|
|
/// <summary>Current Animation Time of the Mode,used in combos</summary>
|
|
public float ModeTime { get; internal set; }
|
|
|
|
/// <summary>Active Mode ID</summary>
|
|
public int ActiveModeID { get; private set; }
|
|
|
|
public Mode Pin_Mode { get; private set; }
|
|
|
|
#endregion
|
|
|
|
#region Sleep
|
|
[SerializeField] private BoolReference sleep = new BoolReference(false);
|
|
|
|
/// <summary>Put the Controller to sleep, is like disalbling the script but internally</summary>
|
|
public bool Sleep
|
|
{
|
|
get => sleep.Value;
|
|
set
|
|
{
|
|
if (!value && Sleep) //Means is out of sleep
|
|
{
|
|
MTools.ResetFloatParameters(Anim); //Set All Float values to their defaut (For all the Float Values on the Controller while is not riding)
|
|
ResetController();
|
|
}
|
|
sleep.Value = value;
|
|
|
|
//Debug.Log("Sleep" + Sleep);
|
|
|
|
LockInput = LockMovement = value; //Also Set to sleep the Movement and Input
|
|
|
|
if (Sleep)
|
|
{
|
|
SetOptionalAnimParameter(hash_Random, 0); //Set Random to 0
|
|
//Reset FreeMovement.
|
|
if (Rotator) Rotator.localRotation = Quaternion.identity;
|
|
Bank = 0;
|
|
PitchAngle = 0;
|
|
PitchDirection = Vector3.forward;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Strafe
|
|
public BoolEvent OnStrafe = new BoolEvent();
|
|
|
|
[SerializeField] private BoolReference m_strafe = new BoolReference(false);
|
|
[SerializeField] private BoolReference m_CanStrafe = new BoolReference(false);
|
|
[SerializeField] private BoolReference m_StrafeNormalize = new BoolReference(false);
|
|
[SerializeField] private FloatReference m_StrafeLerp = new FloatReference(5f);
|
|
|
|
|
|
public bool StrafeNormalize => m_StrafeNormalize.Value;
|
|
|
|
|
|
/// <summary> Is the Animal on the Strafe Mode</summary>
|
|
public bool Strafe
|
|
{
|
|
get => m_CanStrafe.Value && m_strafe.Value && ActiveState.CanStrafe;
|
|
set
|
|
{
|
|
if (sleep) return;
|
|
|
|
var newStrafe = value && m_CanStrafe.Value && ActiveState.CanStrafe;
|
|
|
|
if (newStrafe != m_strafe.Value)
|
|
{
|
|
m_strafe.Value = newStrafe;
|
|
OnStrafe.Invoke(m_strafe.Value);
|
|
SetOptionalAnimParameter(hash_Strafe, m_strafe.Value);
|
|
SetOptionalAnimParameter(hash_StateOn); // Check again that the Strafe is On!
|
|
|
|
if (!JustActivateState) SetIntParameter(hash_LastState, ActiveStateID); //Sent to the Animator the previews Active State (BUG)
|
|
|
|
if (!m_strafe.Value) //false
|
|
{
|
|
ResetCameraInput();
|
|
}
|
|
else
|
|
{
|
|
Aimer?.SetEnable(true); //Enable the Aimer just in case
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool CanStrafe { get => m_CanStrafe.Value; set => m_CanStrafe.Value = value; }
|
|
|
|
private float StrafeDeltaValue;
|
|
private float HorizontalAimAngle_Raw;
|
|
|
|
public Aim Aimer;
|
|
|
|
|
|
#endregion
|
|
|
|
#region Pivots
|
|
|
|
internal RaycastHit hit_Hip; //Hip and Chest Ray Cast Information
|
|
internal RaycastHit hit_Chest; //Hip and Chest Ray Cast Information
|
|
|
|
public List<MPivots> pivots = new List<MPivots>
|
|
{ new MPivots("Hip", new Vector3(0,0.7f,-0.7f), 1), new MPivots("Chest", new Vector3(0,0.7f,0.7f), 1), new MPivots("Water", new Vector3(0,1,0), 0.05f) };
|
|
|
|
public MPivots Pivot_Hip;
|
|
public MPivots Pivot_Chest;
|
|
|
|
public int AlignUniqueID { get; private set; }
|
|
|
|
/// <summary>Does it have a Hip Pivot?</summary>
|
|
public bool Has_Pivot_Hip;
|
|
|
|
/// <summary>Does it have a Hip Pivot?</summary>
|
|
public bool Has_Pivot_Chest;
|
|
|
|
/// <summary> Do the Main (Hip Ray) found ground </summary>
|
|
public bool MainRay { get; private set; }
|
|
/// <summary> Do the Fron (Chest Ray) found ground </summary>
|
|
public bool FrontRay { get; private set; }
|
|
|
|
/// <summary>Main pivot Point is the Pivot Chest Position, if not the Pivot Hip Position one</summary>
|
|
public Vector3 Main_Pivot_Point
|
|
{
|
|
get
|
|
{
|
|
Vector3 pivotPoint;
|
|
if (Has_Pivot_Chest)
|
|
{
|
|
pivotPoint = Pivot_Chest.World(transform);
|
|
}
|
|
else if (Has_Pivot_Hip)
|
|
{
|
|
pivotPoint = Pivot_Hip.World(transform);
|
|
}
|
|
else
|
|
{
|
|
pivotPoint = transform.TransformPoint(new Vector3(0, Height, 0));
|
|
}
|
|
|
|
return pivotPoint + DeltaVelocity;
|
|
}
|
|
}
|
|
|
|
public Vector3 DeltaVelocity { get; private set; }
|
|
|
|
/// <summary> Does the Animal Had a Pivot Chest at the beggining?</summary>
|
|
private bool Starting_PivotChest;
|
|
|
|
/// <summary> Disable Temporally the Pivot Chest in case the animal is on 2 legs </summary>
|
|
public void DisablePivotChest() => Has_Pivot_Chest = false;
|
|
|
|
/// <summary> Used for when the Animal is on 2 feet instead of 4</summary>
|
|
public void ResetPivotChest() => Has_Pivot_Chest = Starting_PivotChest;
|
|
public void UsePivotChest(bool value) => Has_Pivot_Chest = value;
|
|
|
|
|
|
/// <summary>Check if there's no Pivot Active </summary>
|
|
public bool NoPivot => !Has_Pivot_Chest && !Has_Pivot_Hip;
|
|
|
|
/// <summary> Gets the the Main Pivot Multiplier * Scale factor (Main Pivot is the Chest, if not then theHip Pivot) </summary>
|
|
public float Pivot_Multiplier
|
|
{
|
|
get
|
|
{
|
|
float multiplier = Has_Pivot_Chest ? Pivot_Chest.multiplier : (Has_Pivot_Hip ? Pivot_Hip.multiplier : 1f);
|
|
return multiplier * ScaleFactor * (NoPivot ? 1.5f : 1f);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Speed Modifiers
|
|
|
|
/// <summary>The full Velocity we want to without lerping, for the Additional Position NOT INLCUDING ROOTMOTION</summary>
|
|
public Vector3 TargetSpeed { get; internal set; }
|
|
public Vector3 DesiredRBVelocity { get; internal set; }
|
|
|
|
/// <summary>True if the Current Speed is Locked</summary>
|
|
public bool CurrentSpeedSetIsLocked => CurrentSpeedSet.LockSpeed;
|
|
|
|
/// <summary>Speed Set for Stances</summary>
|
|
public List<MSpeedSet> speedSets;
|
|
/// <summary>Active Speed Set</summary>
|
|
private MSpeedSet currentSpeedSet = new MSpeedSet();
|
|
internal MSpeedSet defaultSpeedSet = new MSpeedSet()
|
|
{ name = "Default Set", Speeds = new List<MSpeed>(1) { new MSpeed("Default", 1, 4, 4) } }; //Create a Default Speed at Awake
|
|
|
|
/// <summary>True if the State is modifing the current Speed Modifier</summary>
|
|
public bool CustomSpeed;
|
|
|
|
public MSpeed currentSpeedModifier = MSpeed.Default;
|
|
internal MSpeed SprintSpeed = MSpeed.Default;
|
|
//public List<MSpeed> speedModifiers = new List<MSpeed>();
|
|
|
|
protected int speedIndex;
|
|
|
|
/// <summary>What is the Speed modifier the Animal is current using (Walk? trot? Run?)</summary>
|
|
public MSpeed CurrentSpeedModifier
|
|
{
|
|
get
|
|
{
|
|
if (CurrentSpeedSetIsLocked) return CurrentSpeedSet.LockedSpeedModifier; //Return the Locked
|
|
if (Sprint && !CustomSpeed) return SprintSpeed;
|
|
return currentSpeedModifier;
|
|
}
|
|
internal set
|
|
{
|
|
//Debug.Log("******value = " + value.name);
|
|
|
|
if (currentSpeedModifier.name != value.name)
|
|
{
|
|
currentSpeedModifier = value;
|
|
OnSpeedChange.Invoke(CurrentSpeedModifier);
|
|
EnterSpeedEvent(CurrentSpeedIndex);
|
|
ActiveState?.SpeedModifierChanged(CurrentSpeedModifier, CurrentSpeedIndex);
|
|
// Debug.Log("******CurrentSpeedModifier = " + currentSpeedModifier.name);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>Current Speed Index used of the Current Speed Set E.G. (1 for Walk, 2 for trot)</summary>
|
|
public int CurrentSpeedIndex
|
|
{
|
|
get => CurrentSpeedSet.LockSpeed ? CurrentSpeedSet.LockIndex : speedIndex; //Return the LockSpeed Index in case the speed is locked
|
|
internal set
|
|
{
|
|
if (CustomSpeed || CurrentSpeedSet == null) return;
|
|
|
|
var speedModifiers = CurrentSpeedSet.Speeds;
|
|
|
|
var newValue = Mathf.Clamp(value, 1, speedModifiers.Count); //Clamp the Speed Index
|
|
if (newValue > CurrentSpeedSet.TopIndex) newValue = CurrentSpeedSet.TopIndex;
|
|
|
|
newValue = Mathf.Clamp(value, 1, newValue); // TOP INDEX CANNOT BE SET OT ZERO
|
|
|
|
|
|
if (speedIndex != newValue)
|
|
{
|
|
speedIndex = newValue;
|
|
|
|
var sprintSpeed = Mathf.Clamp(speedIndex + 1, 1, speedModifiers.Count);
|
|
|
|
CurrentSpeedModifier = speedModifiers[speedIndex - 1];
|
|
|
|
//Debug.Log("CurrentSpeedIndex: " + speedIndex);
|
|
SprintSpeed = speedModifiers[sprintSpeed - 1];
|
|
|
|
if (CurrentSpeedSet != null)
|
|
CurrentSpeedSet.CurrentIndex = speedIndex; //Keep the Speed saved on the state too in case the active speed was changed
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Current Speed Set used on the Animal</summary>
|
|
public MSpeedSet CurrentSpeedSet
|
|
{
|
|
get => currentSpeedSet;
|
|
internal set
|
|
{
|
|
if (value.name != currentSpeedSet.name) //Calculate this only when the Set changes
|
|
{
|
|
//Debug.Log("SpeedSet = " + currentSpeedSet.name);
|
|
//Debug.Log("currentSpeedSet = " + currentSpeedSet.CurrentIndex);
|
|
currentSpeedSet = value;
|
|
speedIndex = -1; //Reset the speed Index
|
|
JustChangedSpeedSet = true;
|
|
CurrentSpeedIndex = currentSpeedSet.CurrentIndex;
|
|
JustChangedSpeedSet = false;
|
|
|
|
EnterSpeedEvent(CurrentSpeedIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool JustChangedSpeedSet;
|
|
|
|
private void EnterSpeedEvent(int index)
|
|
{
|
|
if (JustChangedSpeedSet) return;
|
|
|
|
if (OnEnterExitSpeeds != null)
|
|
{
|
|
var SpeedEnterEvent = OnEnterExitSpeeds.Find(s => s.SpeedIndex == index && s.SpeedSet == CurrentSpeedSet.name);
|
|
|
|
if (OldEnterExitSpeed != null && SpeedEnterEvent != OldEnterExitSpeed)
|
|
{
|
|
OldEnterExitSpeed.OnExit.Invoke();
|
|
OldEnterExitSpeed = null;
|
|
}
|
|
|
|
|
|
if (SpeedEnterEvent != null)
|
|
{
|
|
SpeedEnterEvent.OnEnter.Invoke();
|
|
OldEnterExitSpeed = SpeedEnterEvent;
|
|
}
|
|
}
|
|
}
|
|
|
|
private OnEnterExitSpeed OldEnterExitSpeed;
|
|
|
|
/// <summary> Use Default SpeedSet 0 everything </summary>
|
|
public void ResetSpeedSet() => CurrentSpeedSet = defaultSpeedSet;
|
|
|
|
|
|
/// <summary> Value for the Speed Global Multiplier Parameter on the Animator</summary>
|
|
internal float SpeedMultiplier { get; set; }
|
|
|
|
internal bool sprint;
|
|
internal bool realSprint;
|
|
|
|
/// <summary>Sprint Input</summary>
|
|
public bool Sprint
|
|
{
|
|
get => UseSprintState && sprint && UseSprint && MovementDetected && !CurrentSpeedSetIsLocked;
|
|
set
|
|
{
|
|
var newRealSprint = UseSprintState && value && UseSprint && MovementDetected && !CurrentSpeedSetIsLocked; //Check if the animal has movement
|
|
|
|
//Debug.Log($"UseSprintState {UseSprintState} && value{value} && " +
|
|
// $"UseSprint{UseSprint} && MovementDetected{MovementDetected} && !SpeedChangeLocked {SpeedChangeLocked}");
|
|
|
|
sprint = value; //Store only the Input value for the sprint I think it works
|
|
|
|
if (realSprint != newRealSprint)
|
|
{
|
|
realSprint = newRealSprint;
|
|
|
|
OnSprintEnabled.Invoke(realSprint);
|
|
SetOptionalAnimParameter(hash_Sprint, realSprint); //Set on the Animator Sprint Value
|
|
|
|
int currentPI = CurrentSpeedIndex;
|
|
var speed = CurrentSpeedModifier;
|
|
|
|
if (realSprint)
|
|
{
|
|
speed = SprintSpeed;
|
|
currentPI++;
|
|
}
|
|
|
|
OnSpeedChange.Invoke(speed); //Invoke the Speed again
|
|
EnterSpeedEvent(currentPI);
|
|
|
|
ActiveState?.SpeedModifierChanged(speed, currentPI);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetSprint(bool value) => Sprint = value;
|
|
|
|
/// <summary> Try State current Cycle </summary>
|
|
internal int CurrentCycle { get; private set; }
|
|
|
|
#endregion
|
|
|
|
#region Gravity
|
|
[SerializeField] private Vector3Reference m_gravityDir = new Vector3Reference(Vector3.down);
|
|
|
|
[SerializeField] private FloatReference m_gravityPower = new FloatReference(9.8f);
|
|
|
|
[SerializeField] private IntReference m_gravityTime = new IntReference(10);
|
|
[SerializeField] private IntReference m_gravityTimeLimit = new IntReference(0);
|
|
|
|
|
|
public int StartGravityTime { get => m_gravityTime.Value ; internal set => m_gravityTime.Value = value; }
|
|
public int LimitGravityTime { get => m_gravityTimeLimit.Value ; internal set => m_gravityTimeLimit.Value = value; }
|
|
|
|
/// <summary>Multiplier Added to the Gravity Direction</summary>
|
|
public float GravityMultiplier { get; internal set; }
|
|
|
|
|
|
public int GravityTime { get; internal set; }
|
|
//{
|
|
// get => m_GravityTime;
|
|
// set
|
|
// {
|
|
// m_GravityTime = value;
|
|
// Debug.Log("m_GravityTime " + m_GravityTime);
|
|
// }
|
|
//}
|
|
//int m_GravityTime;
|
|
|
|
|
|
public float GravityPower { get => m_gravityPower.Value * GravityMultiplier; set => m_gravityPower.Value = value; }
|
|
|
|
|
|
/// <summary>Stored Gravity Velocity when the animal is using Gravity</summary>
|
|
public Vector3 GravityStoredVelocity { get; internal set; }
|
|
|
|
/// <summary> Direction of the Gravity </summary>
|
|
public Vector3 Gravity { get => m_gravityDir.Value; set => m_gravityDir.Value = value; }
|
|
|
|
/// <summary> Up Vector is the Opposite direction of the Gravity dir</summary>
|
|
public Vector3 UpVector => -m_gravityDir.Value;
|
|
|
|
/// <summary>if True the gravity will be the Negative Ground Normal Value</summary>
|
|
public BoolReference ground_Changes_Gravity = new BoolReference(false);
|
|
|
|
#endregion
|
|
|
|
#region Advanced Parameters
|
|
|
|
[Range(0,180),Tooltip("Slow the Animal when the Turn Angle is ouside this limit")]
|
|
public float TurnLimit = 120;
|
|
|
|
public BoolReference rootMotion = new BoolReference(true);
|
|
|
|
/// <summary> Raudius for the Sphere Cast</summary>
|
|
public FloatReference rayCastRadius = new FloatReference(0.05f);
|
|
|
|
/// <summary>RayCast Radius for the Alignment Raycasting</summary>
|
|
public float RayCastRadius => rayCastRadius.Value + 0.001f;
|
|
/// <summary>This parameter exist to Add Additive pose to correct the animal</summary>
|
|
public IntReference animalType = new IntReference(0);
|
|
#endregion
|
|
|
|
#region Use Stuff Properties
|
|
/// <summary>Does the Active State uses Additive Position Speed?</summary>
|
|
public bool UseAdditivePos// { get; internal set; }
|
|
{
|
|
get => useAdditivePos;
|
|
set
|
|
{
|
|
useAdditivePos = value;
|
|
if (!useAdditivePos) ResetInertiaSpeed();
|
|
}
|
|
}
|
|
private bool useAdditivePos;
|
|
|
|
/// <summary>Does the Active State uses Additive Position Speed?</summary>
|
|
public bool UseAdditiveRot { get; internal set; }
|
|
|
|
/// <summary>Does the Active State uses Sprint?</summary>
|
|
public bool UseSprintState { get; internal set; }
|
|
|
|
/// <summary>Custom Alignment done by some States.. (E.g. Swim) </summary>
|
|
public bool UseCustomAlign { get; set; }
|
|
/// <summary>The Animal is on Free Movement... which means is flying or swiming underwater</summary>
|
|
public bool FreeMovement { get; set; }
|
|
/// <summary>Enable Disable the Global Sprint</summary>
|
|
public bool UseSprint
|
|
{
|
|
get => useSprintGlobal;
|
|
set
|
|
{
|
|
useSprintGlobal.Value = value;
|
|
Sprint = sprint; //Update the Sprint value IMPORTANT
|
|
}
|
|
}
|
|
/// <summary>Enable Disable the Global Sprint (SAME AS USE SPRINT)</summary>
|
|
public bool CanSprint { get => UseSprint; set => UseSprint = value; }
|
|
|
|
/// <summary>Locks Input on the Animal, Ingore inputs like Jumps, Attacks , Actions etc</summary>
|
|
public bool LockInput
|
|
{
|
|
get => lockInput.Value;
|
|
set
|
|
{
|
|
lockInput.Value = value;
|
|
OnInputLocked.Invoke(lockInput);
|
|
}
|
|
}
|
|
|
|
/// <summary>Enable/Disable RootMotion on the Animator</summary>
|
|
public bool RootMotion
|
|
{
|
|
get => rootMotion;
|
|
set => Anim.applyRootMotion = rootMotion.Value = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This store the DeltaRootMotion everytime its Deactivated/Activated
|
|
/// </summary>
|
|
private Vector3 DeltaRootMotion;
|
|
|
|
private bool useGravity;
|
|
/// <summary>Does it use Gravity or not? </summary>
|
|
public bool UseGravity
|
|
{
|
|
get => useGravity;
|
|
set
|
|
{
|
|
useGravity = value;
|
|
|
|
if (!useGravity) ResetGravityValues();//Reset Gravity Logic when Use gravity is false
|
|
// Debug.Log("useGravity = " + useGravity);
|
|
}
|
|
}
|
|
|
|
/// <summary>Locks the Movement on the Animal</summary>
|
|
public bool LockMovement
|
|
{
|
|
get => lockMovement;
|
|
set
|
|
{
|
|
lockMovement.Value = value;
|
|
OnMovementLocked.Invoke(lockMovement);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>Sets to Zero the Z on the Movement Axis when this is set to true</summary>
|
|
public bool LockForwardMovement
|
|
{
|
|
get => lockForwardMovement;
|
|
set
|
|
{
|
|
lockForwardMovement.Value = value;
|
|
LockMovementAxis.z = value ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
/// <summary>Sets to Zero the X on the Movement Axis when this is set to true</summary>
|
|
public bool LockHorizontalMovement
|
|
{
|
|
get => lockHorizontalMovement;
|
|
set
|
|
{
|
|
lockHorizontalMovement.Value = value;
|
|
LockMovementAxis.x = value ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
/// <summary>Sets to Zero the Y on the Movement Axis when this is set to true</summary>
|
|
public bool LockUpDownMovement
|
|
{
|
|
get => lockUpDownMovement;
|
|
set
|
|
{
|
|
lockUpDownMovement.Value = value;
|
|
LockMovementAxis.y = value ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
private Vector3 LockMovementAxis;
|
|
private bool useOrientToGround;
|
|
|
|
/// <summary>if True It will Aling it to the ground rotation depending the Front and Back Pivots</summary>
|
|
public bool UseOrientToGround
|
|
{
|
|
get => useOrientToGround && m_OrientToGround.Value;
|
|
set => useOrientToGround = value;
|
|
}
|
|
|
|
|
|
public bool GlobalOrientToGround
|
|
{
|
|
get => m_OrientToGround.Value;
|
|
set
|
|
{
|
|
m_OrientToGround.Value = value;
|
|
Has_Pivot_Chest = value ? Pivot_Chest != null : false; //Hide the Pivor Chest
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[SerializeField, Tooltip("Global Orient to ground. Disable This for Humanoids")]
|
|
private BoolReference m_OrientToGround = new BoolReference(true);
|
|
|
|
|
|
[SerializeField,Tooltip("Locks Input on the Animal, Ignore inputs like Jumps, Attacks, Actions etc")]
|
|
private BoolReference lockInput = new BoolReference(false);
|
|
|
|
[SerializeField,Tooltip("Locks the Movement entries on the animal. (Horizontal, Vertical,Up Down)")]
|
|
private BoolReference lockMovement = new BoolReference(false);
|
|
|
|
[SerializeField]
|
|
private BoolReference useSprintGlobal = new BoolReference(true);
|
|
#endregion
|
|
|
|
#region Animator States Info
|
|
internal AnimatorStateInfo m_CurrentState; // Information about the base layer of the animator cached.
|
|
internal AnimatorStateInfo m_NextState;
|
|
internal AnimatorStateInfo m_PreviousCurrentState; // Information about the base layer of the animator from last frame.
|
|
internal AnimatorStateInfo m_PreviousNextState;
|
|
|
|
/// <summary> If we are in any animator transition </summary>
|
|
internal bool m_IsAnimatorTransitioning;
|
|
internal bool FirstAnimatorTransition;
|
|
protected bool m_PreviousIsAnimatorTransitioning;
|
|
|
|
|
|
/// <summary>Returns the Current Animation State Tag of animal, if is in transition it will return the NextState Tag</summary>
|
|
public AnimatorStateInfo AnimState { get; set; }
|
|
|
|
public int currentAnimTag;
|
|
/// <summary>Current Active Animation Hash Tag </summary>
|
|
public int AnimStateTag
|
|
{
|
|
get => currentAnimTag;
|
|
private set
|
|
{
|
|
if (value != currentAnimTag)
|
|
{
|
|
currentAnimTag = value;
|
|
activeState.AnimationTagEnter(value);
|
|
|
|
if (ActiveState.IsPending) //If the new Animation Tag is not on the New Active State try to activate it on the last State
|
|
LastState.AnimationTagEnter(value);
|
|
//Debug.Log("value = " + value);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Platform
|
|
public Transform platform;
|
|
protected Vector3 platform_LastPos;
|
|
protected Quaternion platform_Rot;
|
|
#endregion
|
|
|
|
#region Extras
|
|
/// <summary>Used for Disabling Additive Position and Additive Rotation on the ANimal (The Pulling Wagons on the Horse Car take care of it)</summary>?????
|
|
internal bool DisablePositionRotation = false;
|
|
///// <summary>Used for Disabling Additive Position and Additive Rotation on the ANimal (The Pulling Wagons on the Horse Car take care of it)</summary>?????
|
|
//internal bool DisableRotation = false;
|
|
|
|
//[Tooltip("When Falling and the animal get stuck falling, the animal will be force to move forward.")]
|
|
//public FloatReference FallForward = new FloatReference(2);
|
|
|
|
protected List<IMDamager> Attack_Triggers; //List of all the Damage Triggers on this Animal.
|
|
|
|
|
|
/// <summary>All Colliders Inside the Animals> summary>
|
|
public List<Collider> colliders = new List<Collider>();
|
|
|
|
/// <summary>Animator Normalized State Time for the Base Layer </summary>
|
|
public float StateTime { get; private set; }
|
|
|
|
///// <summary>Store from where the damage came from</summary>
|
|
//public Vector3 HitDirection { set; get; }
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
public IntEvent OnAnimationChange;
|
|
public UnityEvent OnMaxSlopeReached = new UnityEvent();
|
|
private bool HasReachedMaxSlope;
|
|
public BoolEvent OnInputLocked = new BoolEvent(); //Used for Sync Animators
|
|
public BoolEvent OnMovementLocked = new BoolEvent(); //Used for Sync Animators
|
|
public BoolEvent OnSprintEnabled = new BoolEvent(); //Used for Sync Animators
|
|
public BoolEvent OnGrounded = new BoolEvent(); //Used for Sync Animators
|
|
public BoolEvent OnMovementDetected = new BoolEvent(); //Used for Sync Animators
|
|
|
|
/// <summary> Invoked when a new State is Activated</summary>
|
|
public IntEvent OnStateActivate = new IntEvent();
|
|
/// <summary> Invoked when a new State has entered any of its Animations</summary>
|
|
public IntEvent OnStateChange = new IntEvent();
|
|
/// <summary> Invoked when a new Mode start</summary>
|
|
public Int2Event OnModeStart = new Int2Event();
|
|
/// <summary> Invoked when a new Mode ends</summary>
|
|
public Int2Event OnModeEnd = new Int2Event();
|
|
/// <summary> Invoked when a new Stance is Activated</summary>
|
|
public IntEvent OnStanceChange = new IntEvent(); //Invoked when is Changed to a new Stance
|
|
public SpeedModifierEvent OnSpeedChange = new SpeedModifierEvent(); //Invoked when a new Speed is changed
|
|
public Vector3Event OnTeleport = new Vector3Event(); //Invoked when a new Speed is changed
|
|
|
|
|
|
///<summary>List of Events to Use on the States</summary>
|
|
public List<OnEnterExitState> OnEnterExitStates;
|
|
///<summary>List of Events to Use on the Stances</summary>
|
|
public List<OnEnterExitStance> OnEnterExitStances;
|
|
///<summary>List of Events to Use on the Speeds</summary>
|
|
public List<OnEnterExitSpeed> OnEnterExitSpeeds;
|
|
|
|
|
|
#endregion
|
|
|
|
#region Random
|
|
public int RandomID { get; private set; }
|
|
public int RandomPriority { get; private set; }
|
|
|
|
/// <summary>Let States have Random Animations</summary>
|
|
public bool Randomizer { get; set; }
|
|
#endregion
|
|
|
|
#region Animator Parameters
|
|
|
|
[SerializeField, Tooltip("Forward (Z) Movement for the Animator")] private string m_Vertical = "Vertical";
|
|
[SerializeField, Tooltip("Horizontal (X) Movement for the Animator")] private string m_Horizontal = "Horizontal";
|
|
[SerializeField, Tooltip("Vertical (Y) Movement for the Animator")] private string m_UpDown = "UpDown";
|
|
[SerializeField, Tooltip("Vertical (Y) Difference between Target and Current UpDown")] private string m_DeltaUpDown = "DeltaUpDown";
|
|
|
|
[SerializeField, Tooltip("Is the animal on the Ground? ")] private string m_Grounded = "Grounded";
|
|
[SerializeField, Tooltip("Is the animal moving?")] private string m_Movement = "Movement";
|
|
|
|
[SerializeField, Tooltip("Active/Current State the animal is")]
|
|
private string m_State = "State";
|
|
|
|
[SerializeField, Tooltip("Trigger to Notify the Activation of a State")]
|
|
private string m_StateOn = "StateOn";
|
|
|
|
//[SerializeField, Tooltip("Trigger to Notify the Activation of a State")]
|
|
//private string m_StanceOn = "StanceOn";
|
|
|
|
[SerializeField, Tooltip("Trigger to Notify the Activation of a Mode")]
|
|
private string m_ModeOn = "ModeOn";
|
|
|
|
|
|
[SerializeField, Tooltip("The Active State can have multiple status to change inside the State itself")]
|
|
private string m_StateStatus = "StateEnterStatus";
|
|
[SerializeField, Tooltip("The Active State can use this parameter to activate exiting animations")]
|
|
private string m_StateExitStatus = "StateExitStatus";
|
|
[SerializeField, Tooltip("Float value for the States to be used when needed")]
|
|
private string m_StateFloat = "StateFloat";
|
|
[SerializeField, Tooltip("Last State the animal was")]
|
|
private string m_LastState = "LastState";
|
|
|
|
[SerializeField, Tooltip("Active State Time for the States Animations")]
|
|
private string m_StateTime = "StateTime";
|
|
|
|
[SerializeField, Tooltip("Speed Multiplier for the Animations")]
|
|
private string m_SpeedMultiplier = "SpeedMultiplier";
|
|
|
|
|
|
[SerializeField, Tooltip("Active Mode the animal is... The Value is the Mode ID plus the Ability Index. Example Action Eat = 4002")]
|
|
private string m_Mode = "Mode";
|
|
|
|
|
|
|
|
[SerializeField, Tooltip("Store the Modes Status (Available=0 Started=1 Looping=-1 Interrupted=-2)")]
|
|
private string m_ModeStatus = "ModeStatus";
|
|
[SerializeField, Tooltip("Mode Float Value, Used to have a float Value for the modes to be used when needed")]
|
|
private string m_ModePower = "ModePower";
|
|
|
|
[SerializeField, Tooltip("Sprint Value")]
|
|
private string m_Sprint = "Sprint";
|
|
|
|
[SerializeField, Tooltip("Active/Current stance of the animal")] private string m_Stance = "Stance";
|
|
[SerializeField, Tooltip("Previus/Last stance of the animal")] private string m_LastStance = "LastStance";
|
|
[SerializeField, Tooltip("Normalized value of the Slope of the Terrain")] private string m_Slope = "Slope";
|
|
[SerializeField, Tooltip("Type of animal for the Additive corrective pose")] private string m_Type = "Type";
|
|
|
|
[SerializeField, Tooltip("Random Value for Animations States with multiple animations")] private string m_Random = "Random";
|
|
[SerializeField, Tooltip("Target Angle calculated from the current forward direction to the desired direction")] private string m_DeltaAngle = "DeltaAngle";
|
|
[SerializeField, Tooltip("Does the Animal Uses Strafe")] private string m_Strafe = "Strafe";
|
|
[SerializeField, Tooltip("Horizontal Angle for Strafing.")] private string m_strafeAngle = "StrafeAngle";
|
|
|
|
internal int hash_Vertical;
|
|
internal int hash_Horizontal;
|
|
internal int hash_UpDown;
|
|
|
|
internal int hash_DeltaUpDown;
|
|
|
|
internal int hash_Movement;
|
|
internal int hash_Grounded;
|
|
internal int hash_SpeedMultiplier;
|
|
|
|
internal int hash_DeltaAngle;
|
|
|
|
internal int hash_State;
|
|
internal int hash_StateOn;
|
|
internal int hash_StateEnterStatus;
|
|
internal int hash_StateExitStatus;
|
|
internal int hash_StateFloat;
|
|
internal int hash_StateTime;
|
|
internal int hash_LastState;
|
|
|
|
internal int hash_Mode;
|
|
internal int hash_ModeOn;
|
|
internal int hash_ModeStatus;
|
|
internal int hash_ModePower;
|
|
|
|
internal int hash_Stance;
|
|
//internal int hash_StanceOn;
|
|
internal int hash_LastStance;
|
|
|
|
internal int hash_Slope;
|
|
internal int hash_Sprint;
|
|
internal int hash_Random;
|
|
internal int hash_Strafe;
|
|
internal int hash_StrafeAngle;
|
|
#endregion
|
|
}
|
|
|
|
|
|
[System.Serializable]
|
|
public class OnEnterExitSpeed
|
|
{
|
|
[Tooltip("Which is the Speed Set (By its Name) changed. Case Sensitive")]
|
|
public string SpeedSet;
|
|
[Tooltip("Which is the Speed Modifier (By its Name) changed. This is Ignored if is set to 1. Case Sensitive")]
|
|
public int SpeedIndex;
|
|
public UnityEvent OnEnter;
|
|
public UnityEvent OnExit;
|
|
}
|
|
|
|
|
|
[System.Serializable]
|
|
public class OnEnterExitState
|
|
{
|
|
public StateID ID;
|
|
public UnityEvent OnEnter;
|
|
public UnityEvent OnExit;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class OnEnterExitStance
|
|
{
|
|
public StanceID ID;
|
|
public UnityEvent OnEnter;
|
|
public UnityEvent OnExit;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class SpeedModifierEvent : UnityEvent<MSpeed> { }
|
|
}
|