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
10 KiB
C#
276 lines
10 KiB
C#
using MalbersAnimations.Utilities;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace MalbersAnimations.Controller
|
|
{
|
|
/// <summary>Swim Logic</summary>
|
|
public class Swim : State
|
|
{
|
|
public override string StateName => "Swim";
|
|
|
|
[Header("Swim Paramenters")]
|
|
public LayerMask WaterLayer = 16;
|
|
|
|
[Tooltip("Lerp value for the animal to stay align to the water level ")]
|
|
public float AlignSmooth = 10;
|
|
[Tooltip("When entering the water the Animal will sink for a while... Higher values, will return to the surface faster")]
|
|
public float Bounce = 5;
|
|
[Tooltip("If the Animal Enters it will wait this time to try exiting the water")]
|
|
public float TryExitTime = 0.5f;
|
|
protected float EnterWaterTime;
|
|
[Tooltip("Means the Water does not change the shape. Less RayCasting")]
|
|
public bool WaterIsStatic = true;
|
|
[Tooltip("Gives an extra impulse when entering the state using the accumulated inertia")]
|
|
public bool KeepInertia = true;
|
|
[Tooltip("Spherecast radius to find water using the Water Pivot")]
|
|
public float m_Radius = 0.1f;
|
|
|
|
[Tooltip("Ray to the Front to check if the Animal has touched a Front Ground")]
|
|
public float FrontRayLength = 1;
|
|
|
|
|
|
|
|
public bool PivotAboveWater { get; private set; }
|
|
|
|
/// <summary>Has the animal found Water</summary>
|
|
public bool IsInWater { get; private set; }
|
|
|
|
protected MPivots WaterPivot;
|
|
protected Vector3 WaterNormal = Vector3.up;
|
|
protected Vector3 HorizontalInertia;
|
|
|
|
/// <summary>Water Collider used on the Sphere Cast</summary>
|
|
protected Collider[] WaterCollider;
|
|
/// <summary>Point Above the Animal to Look Down and Find the Water level and Water Normal</summary>
|
|
|
|
private Vector3 WaterPivot_Dist_from_Water;
|
|
private Vector3 WaterUPPivot => WaterPivotPoint + animal.DeltaVelocity + (animal.UpVector * UpMult);
|
|
|
|
private Vector3 UpImpulse;
|
|
const float UpMult = 30;
|
|
|
|
public Vector3 WaterPivotPoint => WaterPivot.World(animal.transform)+animal.DeltaVelocity;
|
|
|
|
|
|
public override void InitializeState()
|
|
{
|
|
WaterPivot = animal.pivots.Find(p => p.name.ToLower().Contains("water")); //Find the Water Pivot
|
|
if (WaterPivot == null) Debug.LogError("No Water Pivot Found.. please create a Water Pivot");
|
|
|
|
WaterCollider = new Collider[1];
|
|
IsInWater = false;
|
|
}
|
|
|
|
public override bool TryActivate()
|
|
{
|
|
//if (HasFallState && animal.ActiveStateID == StateEnum.UnderWater && animal.Sprint && animal.UpDownSmooth > 0)
|
|
// return false; //If we are underwater and we are sprinting Upwards ... dont enter this state.. go to fall directly
|
|
|
|
CheckWater();
|
|
|
|
if (IsInWater)
|
|
{
|
|
var waterCol = WaterCollider[0];
|
|
|
|
Ray WaterRay = new Ray(WaterUPPivot, Gravity);
|
|
|
|
if (waterCol.Raycast(WaterRay, out RaycastHit WaterHit, 100f))
|
|
{
|
|
WaterNormal = WaterHit.normal;
|
|
}
|
|
|
|
EnterWaterTime = Time.time;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
public override void Activate()
|
|
{
|
|
base.Activate();
|
|
|
|
HorizontalInertia = Vector3.ProjectOnPlane(animal.DeltaPos, animal.UpVector);
|
|
UpImpulse = Vector3.Project(animal.DeltaPos, animal.UpVector); //Clean the Vector from Forward and Horizontal Influence
|
|
IgnoreLowerStates = true; //Ignore Falling, Idle and Locomotion while swimming
|
|
animal.UseGravity = false; //IMPORTANT
|
|
animal.InertiaPositionSpeed = Vector3.zero; //THIS MOTHER F!#$ER was messing with the water entering
|
|
animal.Force_Reset();
|
|
}
|
|
|
|
|
|
public void CheckWater()
|
|
{
|
|
int WaterFound = Physics.OverlapSphereNonAlloc(WaterPivotPoint, m_Radius * animal.ScaleFactor, WaterCollider, WaterLayer);
|
|
IsInWater = WaterFound > 0; //Means the Water SphereOverlap found Water
|
|
}
|
|
|
|
public override void TryExitState(float DeltaTime)
|
|
{
|
|
if (!InExitAnimation && MTools.ElapsedTime(EnterWaterTime, TryExitTime)) //do not try to exit if the animal just enter the water
|
|
{
|
|
CheckWater();
|
|
if (!IsInWater)
|
|
{
|
|
Debugging("[Allow Exit] No Longer in water");
|
|
animal.CheckIfGrounded();
|
|
AllowExit();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public override void AllowStateExit()
|
|
{
|
|
IsInWater = false;
|
|
}
|
|
|
|
|
|
//public override void OnStatePreMove(float deltatime)
|
|
//{
|
|
// if (animal.MovementAxis.y > 0)
|
|
// {
|
|
// animal.MovementAxis.y = 0;
|
|
// animal.Move_Direction.y = 0;
|
|
// }
|
|
//}
|
|
|
|
public override void OnStateMove(float deltatime)
|
|
{
|
|
if (IsInWater && !InExitAnimation)
|
|
{
|
|
if (KeepInertia) animal.AddInertia(ref HorizontalInertia, 3);
|
|
if (Bounce > 0) animal.AddInertia(ref UpImpulse, Bounce);
|
|
|
|
var waterCol = WaterCollider[0]; //Get the Water Collider
|
|
// var WaterUPSurface = waterCol.ClosestPoint(WaterUPAnimalPos);
|
|
|
|
if (!WaterIsStatic) //Means that the Water Changes shape
|
|
{
|
|
Ray WaterRay = new Ray(WaterUPPivot, Gravity * UpMult);
|
|
|
|
if (waterCol.Raycast(WaterRay, out RaycastHit WaterHit, 100f)) WaterNormal = WaterHit.normal; //RayCast to find the Water Normal
|
|
}
|
|
|
|
animal.AlignRotation(WaterNormal, deltatime, AlignSmooth > 0 ? AlignSmooth : 5); //Aling the Animal to the Water
|
|
|
|
//Find the Water Level
|
|
FindWaterLevel();
|
|
|
|
//var Smoothness = 1f; //SNAP there's no Main Pivos Touching the a ground mean is on the water
|
|
var rayColor = (Color.blue + Color.cyan) /2;
|
|
|
|
//HACK so it does not come out of the water
|
|
if (FrontRayLength > 0 &&
|
|
Physics.Raycast(WaterPivotPoint, Forward, out RaycastHit FrontRayWater, FrontRayLength, GroundLayer, QueryTriggerInteraction.Ignore))
|
|
{
|
|
var FrontPivot = Vector3.Angle(FrontRayWater.normal, animal.UpVector);
|
|
|
|
rayColor = Color.cyan;
|
|
|
|
if (FrontPivot > animal.maxAngleSlope) //BAD Angle Slope
|
|
{
|
|
rayColor = Color.black;
|
|
animal.transform.position += WaterPivot_Dist_from_Water;
|
|
animal.ResetUPVector();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (AlignSmooth > 0)
|
|
animal.AdditivePosition += WaterPivot_Dist_from_Water * (deltatime * AlignSmooth);
|
|
else
|
|
{
|
|
animal.transform.position += WaterPivot_Dist_from_Water;
|
|
animal.ResetUPVector();
|
|
}
|
|
}
|
|
if (debug) Debug.DrawRay(WaterPivotPoint, animal.Forward * FrontRayLength, rayColor);
|
|
}
|
|
}
|
|
|
|
public void FindWaterLevel()
|
|
{
|
|
if (IsInWater)
|
|
{
|
|
var waterCol = WaterCollider[0];
|
|
var PivotPointDistance = waterCol.ClosestPoint(WaterUPPivot); //IMPORTANT IS NOT CLOSEST POINT ON BOUNDS THAT CAUSES ERRORS
|
|
|
|
// Debug.Log("FindWaterLevel");
|
|
|
|
WaterPivot_Dist_from_Water = Vector3.Project((PivotPointDistance - WaterPivotPoint), animal.UpVector);
|
|
|
|
//Debug.Break();
|
|
|
|
PivotAboveWater = Vector3.Dot(WaterPivot_Dist_from_Water, animal.UpVector) < 0;
|
|
}
|
|
else
|
|
{
|
|
PivotAboveWater = true;
|
|
}
|
|
}
|
|
|
|
public override void ResetStateValues()
|
|
{
|
|
WaterCollider = new Collider[1];
|
|
IsInWater = false;
|
|
EnterWaterTime = 0;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
void Reset()
|
|
{
|
|
ID = MTools.GetInstance<StateID>("Swim");
|
|
|
|
WaterCollider = new Collider[1]; //Set the Array to 1
|
|
|
|
ExitCooldown = 1f;
|
|
EnterCooldown = 1f;
|
|
|
|
General = new AnimalModifier()
|
|
{
|
|
RootMotion = true,
|
|
Grounded = false,
|
|
Sprint = true,
|
|
OrientToGround = false,
|
|
CustomRotation = true,
|
|
IgnoreLowerStates = true, //IMPORTANT
|
|
AdditivePosition = true,
|
|
AdditiveRotation = true,
|
|
Gravity = false,
|
|
modify = (modifier)(-1),
|
|
|
|
};
|
|
// SpeedIndex = 0;
|
|
}
|
|
|
|
|
|
public override void StateGizmos(MAnimal animal)
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
if (IsInWater)
|
|
{
|
|
var scale = animal.ScaleFactor;
|
|
Collider WaterCol = WaterCollider[0];
|
|
|
|
Gizmos.color = Color.blue;
|
|
Gizmos.DrawSphere(WaterPivotPoint, m_Radius * scale);
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawSphere(animal.transform.position, m_Radius * scale);
|
|
|
|
if (WaterCol)
|
|
{
|
|
Gizmos.color = Color.cyan;
|
|
Gizmos.DrawSphere(WaterCol.ClosestPoint(WaterUPPivot), m_Radius * scale);
|
|
Gizmos.DrawSphere(WaterUPPivot, m_Radius * scale);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|