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.

276 lines
11 KiB
C#

using MalbersAnimations.Scriptables;
using MalbersAnimations.Utilities;
using UnityEngine;
namespace MalbersAnimations.Controller
{
/// <summary>This will be in charge of the Movement While is on the Ground </summary>
public class Locomotion : State
{
public override string StateName => "Locomotion";
[Header("Locomotion Parameters")]
[Tooltip("Backward Offset Position of the BackFall Ray")]
public FloatReference FallRayBackwards = new FloatReference(0.3f);
[Tooltip("Reset Inertia On Enter")]
public BoolReference ResetIntertia = new BoolReference(false);
[Space(10), Tooltip("Makes the Animal Stop Moving when is near a Wall")]
public bool WallStop = false;
[Hide("WallStop", true, false)] public float WallRayLength = 1f;
[Hide("WallStop", true, false)] public LayerMask StopLayer = 1;
[Hide("WallStop", true, false)] public QueryTriggerInteraction trigger = QueryTriggerInteraction.UseGlobal;
[Space(10), Tooltip("Makes the Animal avoid ledges, Useful when the Animal without a Fall State, like the Elephant")]
public bool AntiFall = false;
[Hide("AntiFall", true, false)] public float frontDistance = 0.5f;
[Hide("AntiFall", true, false)] public float frontSpace = 0.2f;
[Space]
[Hide("AntiFall", true, false)] public float BackDistance = 0.5f;
[Hide("AntiFall", true, false)] public float BackSpace = 0.2f;
[Space]
[Hide("AntiFall", true, false)] public float FallMultiplier = 1f;
[Hide("AntiFall", true, false)] public Color DebugColor = Color.yellow;
/// <summary> The Locomotion also works as the Idle Animation </summary>
public bool HasIdle { get; private set; }
public override void InitializeState()
{
HasIdle = animal.HasState(StateEnum.Idle); //Check if the animal has Idle State if it does not have then Locomotion is IDLE TOO
}
/// <summary>This try to enable the Locomotion Logic</summary>
public override bool TryActivate()
{
if (animal.Grounded)
{
if (!HasIdle) return true; //Return true if is grounded (Meaning Locomotion is also the IDLE STATE
if (animal.MovementAxisSmoothed != Vector3.zero || animal.MovementDetected) //If is moving?
{
return true;
}
}
return false;
}
public override void Activate()
{
base.Activate();
var speed = (int)animal.CurrentSpeedModifier.Vertical.Value;
// if (animal.Sprint) speed++;
SetEnterStatus(speed); //When entering Locomotion the State set the Status the current Speed Modifier.
}
public override void EnterCoreAnimation()
{
// SetEnterStatus(0);//Use the Status on the Animator to show the Vertical Speed used on start of the state
if (animal.LastState.ID == StateEnum.Climb) animal.ResetCameraInput(); //HACK
if (ResetIntertia.Value) animal.ResetInertiaSpeed(); //BUG THAT IT WAS MAKING GO FASTER WHEN ENTERING LOCOMOTION
}
public override void EnterTagAnimation()
{
if (CurrentAnimTag == EnterTagHash) //Using Enter Animation Tag
{
animal.VerticalSmooth = animal.CurrentSpeedModifier.Vertical;
}
}
public override void OnStatePreMove(float deltatime)
{
Wall_Stop();
Anti_Fall();
}
public override void OnStateMove(float deltatime)
{
SetFloatSmooth(0, deltatime * CurrentSpeed.lerpPosition);
}
private void Wall_Stop()
{
if (WallStop && MovementRaw.z > 0)
{
var MainPivotPoint = animal.Main_Pivot_Point;
if (Physics.Raycast(MainPivotPoint, animal.Forward, out _, WallRayLength, StopLayer, trigger))
{
Gizmos.color = Color.red;
Debug.DrawRay(MainPivotPoint, animal.Forward * WallRayLength,Color.red);
animal.MovementAxis.z = 0;
}
else
{
Debug.DrawRay(MainPivotPoint, animal.Forward * WallRayLength, DebugColor);
}
}
}
///// <summary> The Locomotion Uses the Status State Animator Parameter to know which speed Index is using </summary>
//public override void SpeedModifierChanged(MSpeed speed, int SpeedIndex)
//{
// if (InCoreAnimation) SetStatus(SpeedIndex); //This is I think for Changing Fly to Locomotion
//}
//───────────────────────────────────────── ANTI FALL CODE ──────────────────────────────────────────────────────────────────
private void Anti_Fall()
{
if (AntiFall)
{
bool BlockForward = false;
MovementAxisMult = Vector3.one;
var ForwardMov = MovementRaw.z; // Get the Raw movement that enters on the animal witouth any modifications
var Dir = animal.TerrainSlope > 0 ? Gravity : -animal.Up;
float SprintMultiplier = (animal.CurrentSpeedModifier.Vertical).Value;
SprintMultiplier += animal.Sprint ? 1f : 0f; //Check if the animal is sprinting
var RayMultiplier = animal.Pivot_Multiplier * FallMultiplier; //Get the Multiplier
var MainPivotPoint = animal.Pivot_Chest.World(animal.transform);
RaycastHit[] hits = new RaycastHit[1];
Vector3 Center;
Vector3 Left;
Vector3 Right;
if (ForwardMov > 0) //Means we are going forward
{
Center = MainPivotPoint + (animal.Forward * frontDistance * SprintMultiplier * ScaleFactor); //Calculate ahead the falling ray
Left = Center + (animal.Right * frontSpace * ScaleFactor);
Right = Center + (-animal.Right * frontSpace * ScaleFactor);
}
else if (ForwardMov < 0) //Means we are going backwards
{
Center = MainPivotPoint - (animal.Forward * BackDistance * SprintMultiplier * ScaleFactor); //Calculate ahead the falling ray
Left = Center + (animal.Right * BackSpace * ScaleFactor);
Right = Center + (-animal.Right * BackSpace * ScaleFactor);
}
else
{ return; }
Debug.DrawRay(Center, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(Left, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(Right, Dir * RayMultiplier, DebugColor);
var fallHits = Physics.RaycastNonAlloc(Center, Dir, hits, RayMultiplier, GroundLayer, QueryTriggerInteraction.Ignore);
if (fallHits == 0)
{
BlockForward = true; //Means there's 2 rays that are falling
}
else
fallHits = Physics.RaycastNonAlloc(Left, Dir, hits, RayMultiplier, GroundLayer, QueryTriggerInteraction.Ignore);
if (fallHits == 0)
{
BlockForward = true; //Means there's 2 rays that are falling
}
else
{
fallHits = Physics.RaycastNonAlloc(Right, Dir, hits, RayMultiplier, GroundLayer, QueryTriggerInteraction.Ignore);
if (fallHits == 0)
{
BlockForward = true; //Means there's 2 rays that are falling
}
}
if (BlockForward) MovementAxisMult.z = 0;
//animal.Remove_HMovement = BlockForward;
}
else if (!animal.UseCameraInput && MovementRaw.z < 0) //Meaning is going backwards so AntiFall B
{
var MainPivotPoint = animal.Has_Pivot_Hip ? animal.Pivot_Hip.World(transform) : animal.Pivot_Chest.World(transform);
MainPivotPoint += Forward * -(FallRayBackwards * ScaleFactor);
RaycastHit[] hits = new RaycastHit[1];
var RayMultiplier = animal.Pivot_Multiplier; //Get the Multiplier
Debug.DrawRay(MainPivotPoint, -Up * RayMultiplier, Color.white);
var fallHits = Physics.RaycastNonAlloc(MainPivotPoint, -Up, hits, RayMultiplier, GroundLayer, QueryTriggerInteraction.Ignore);
if (fallHits == 0)
{
MovementAxisMult.z = 0;
//animal.Remove_HMovement = true;
}
}
}
public override void StateGizmos(MAnimal animal)
{
if (AntiFall) PaintRays(animal);
if (WallStop)
{
var MainPivotPoint = animal.Main_Pivot_Point;
Debug.DrawRay(MainPivotPoint, animal.Forward * WallRayLength, DebugColor);
}
}
void PaintRays(MAnimal animal)
{
float scale = animal.ScaleFactor;
var Dir = animal.TerrainSlope > 0 ? animal.Gravity : -animal.Up;
var RayMultiplier = animal.Pivot_Multiplier * FallMultiplier; //Get the Multiplier
var MainPivotPoint = animal.Pivot_Chest.World(animal.transform);
var FrontCenter = MainPivotPoint + (animal.Forward * frontDistance * scale); //Calculate ahead the falling ray
var FrontLeft = FrontCenter + (animal.Right * frontSpace * scale);
var FrontRight = FrontCenter + (-animal.Right * frontSpace * scale);
var BackCenter = MainPivotPoint - (animal.Forward * BackDistance * scale); //Calculate ahead the falling ray
var BackLeft = BackCenter + (animal.Right * BackSpace * scale);
var BackRight = BackCenter + (-animal.Right * BackSpace * scale);
Debug.DrawRay(FrontCenter, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(FrontLeft, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(FrontRight, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(BackCenter, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(BackLeft, Dir * RayMultiplier, DebugColor);
Debug.DrawRay(BackRight, Dir * RayMultiplier, DebugColor);
}
#if UNITY_EDITOR
void Reset()
{
ID = MTools.GetInstance<StateID>("Locomotion");
General = new AnimalModifier()
{
RootMotion = true,
Grounded = true,
Sprint = true,
OrientToGround = true,
CustomRotation = false,
IgnoreLowerStates = false,
AdditivePosition = true,
AdditiveRotation = true,
Gravity = false,
modify = (modifier)(-1),
};
EnterTag.Value = "StartLocomotion";
}
#endif
}
}