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.
471 lines
17 KiB
C#
471 lines
17 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using MalbersAnimations.Scriptables;
|
|
|
|
namespace MalbersAnimations.Controller
|
|
{
|
|
public class JumpBasic : State
|
|
{
|
|
public override string StateName => "Jump/Basic Jump";
|
|
|
|
private int JumpEndHash = Animator.StringToHash("JumpEnd");
|
|
private int JumpStartHash = Animator.StringToHash("JumpStart");
|
|
// private int DoubleJumpHash = Animator.StringToHash("DoubleJump");
|
|
|
|
|
|
[Header("Jump Parameters")]
|
|
|
|
|
|
|
|
[Tooltip("Can the Animal be Rotated while Jumping?")]
|
|
public BoolReference AirControl = new BoolReference(true);
|
|
[Tooltip("How much Rotation the Animal can do while Jumping")]
|
|
public FloatReference AirRotation = new FloatReference(10);
|
|
[Tooltip("States that will Reset the Jump Count. By Default Idle and Locomotion Reset the value")]
|
|
public FloatReference AirMovement = new FloatReference(5);
|
|
[Tooltip("Smooth Value for Changing Speed Movement on the Air")]
|
|
public FloatReference AirSmooth = new FloatReference(5);
|
|
|
|
[Space, Tooltip("Wait for the Animation to Activate the Jump Logic\n Use [void ActivateJump()] on the Animator with a Messsage Behavior")]
|
|
public bool WaitForAnimation;
|
|
|
|
[Tooltip("Amount of jumps the Animal can do (Double and Triple Jumps)\n**IMPORTANT**\nWhen using multiple Jumps,Fall cannot be on the Sleep From State List")]
|
|
public IntReference Jumps = new IntReference(1);
|
|
//[Tooltip("For Multiple Jumps, time needed to activate the next jump logic")]
|
|
//public FloatReference JumpTime = new FloatReference(0.3f);
|
|
|
|
/// <summary>If the Jump input is pressed, the Animal will keep going Up while the Jump Animation is Playing</summary>
|
|
[Space, Tooltip("If the Jump input is pressed, the Animal will keep going Up while the Jump Animation is Playing")]
|
|
public BoolReference JumpPressed = new BoolReference(false);
|
|
[Tooltip("Lerp Value for Pressing Jump")]
|
|
public FloatReference JumpPressedLerp = new FloatReference(5);
|
|
|
|
|
|
|
|
[Tooltip("The Jump can be interrupted if a ground is found in the middle of the jump. This is the multiplier to cast the Ray using the Animal Height.")]
|
|
// [Range(0,99)]
|
|
public FloatReference JumpInterruptRay = new FloatReference(0.9f);
|
|
|
|
[Space, Tooltip("How much Movement the Animal can do while Jumping")]
|
|
public List<StateID> ResetJump;
|
|
|
|
#if UNITY_2020_3_OR_NEWER
|
|
[NonReorderable]
|
|
#endif
|
|
public List<JumpBasicProfile> profiles = new List<JumpBasicProfile>();
|
|
#if UNITY_2020_3_OR_NEWER
|
|
[NonReorderable]
|
|
#endif
|
|
public List<JumpDoubleProfile> multipleJumps = new List<JumpDoubleProfile>();
|
|
|
|
|
|
private JumpBasicProfile activeJump;
|
|
protected MSpeed JumpSpeed;
|
|
|
|
/// <summary> This allows the Jump Logic to occur, its activated by the </summary>
|
|
private bool IsDoubleJump;
|
|
|
|
private bool ActivateJumpLogic;
|
|
//{
|
|
// get => activateJumpLogic;
|
|
// set
|
|
// {
|
|
// activateJumpLogic = value;
|
|
// //Debug.Log("activateJumpLogic = " + activateJumpLogic);
|
|
// }
|
|
//}
|
|
//private bool activateJumpLogic;
|
|
|
|
public int JumpsPerformanced //{ get; set; }
|
|
{
|
|
get => jumpsPerformanced;
|
|
set
|
|
{
|
|
jumpsPerformanced = value;
|
|
// Debug.Log("jumpsPerformanced = " + jumpsPerformanced);
|
|
}
|
|
}
|
|
private int jumpsPerformanced;
|
|
//private int GravityTime = 0;
|
|
/// <summary> Used on the Pressed feature so it cannot be pressed again on the middle </summary>
|
|
private bool justJumpPressed;
|
|
|
|
private float StartedJumpLogicTime;
|
|
private float JumpPressHeight_Value = 1;
|
|
|
|
|
|
public override void AwakeState()
|
|
{
|
|
base.AwakeState();
|
|
if (EnterTagHash != 0) JumpStartHash = EnterTagHash;
|
|
if (ExitTagHash != 0) JumpEndHash = ExitTagHash;
|
|
}
|
|
|
|
|
|
/// <summary> Restore Internal values on the State (DO NOT INLCUDE Animal Methods or Parameter calls here</summary>
|
|
public override void ResetStateValues()
|
|
{
|
|
JumpPressHeight_Value = 1;
|
|
ActivateJumpLogic = false;
|
|
justJumpPressed = false;
|
|
StartedJumpLogicTime = 0;
|
|
IsDoubleJump = false;
|
|
//Debugging("Reset Jump Values");
|
|
}
|
|
|
|
|
|
//Do not use the Try Activate
|
|
public override bool TryActivate() => false;
|
|
//public override bool TryActivate() => InputValue && (JumpsPerformanced < Jumps);
|
|
|
|
|
|
public override void StatebyInput()
|
|
{
|
|
if (InputValue && (JumpsPerformanced < Jumps)) Activate();
|
|
}
|
|
|
|
|
|
public void ActivateJump()
|
|
{
|
|
ActivateJumpLogic = true;
|
|
justJumpPressed = true;
|
|
animal.Grounded = false;
|
|
StartedJumpLogicTime = Time.time;
|
|
animal.GravityTime = activeJump.StartGravityTime;
|
|
StartingSpeedDirection = animal.Forward; //Store the Starting SpeedDirection
|
|
Debugging("[Basic Jump] Activate JumpLogic");
|
|
}
|
|
|
|
public override void Activate()
|
|
{
|
|
//SpeedSets = new List<MSpeedSet> { animal.CurrentSpeedSet }; //Store the Speed from the Last State Super Important
|
|
|
|
base.Activate();
|
|
animal.State_SetFloat(0);
|
|
|
|
JumpsPerformanced++;
|
|
// Debug.Log("JumpsPerformanced = " + JumpsPerformanced);
|
|
|
|
General.Gravity = false;
|
|
IsPersistent = true; //IMPORTANT!!!!! DO NOT ELIMINATE!!!!!
|
|
|
|
animal.currentSpeedModifier.animator = 1;
|
|
animal.ResetGravityValues(); //Reset the Gravity
|
|
StartingSpeedDirection = animal.Forward; //Store the Starting SpeedDirection
|
|
FindJumpProfile();
|
|
}
|
|
|
|
private void FindJumpProfile()
|
|
{
|
|
activeJump = (profiles != null && profiles.Count > 0) ? profiles[0] : new JumpBasicProfile() { };
|
|
|
|
foreach (var j in profiles) //Save/Search the Current Jump Profile by the Lowest Speed available
|
|
{
|
|
if (j.LastState == null)
|
|
{
|
|
if (j.VerticalSpeed <= animal.VerticalSmooth) activeJump = j; //Find the Closest
|
|
}
|
|
else
|
|
{
|
|
if (j.VerticalSpeed <= animal.VerticalSmooth &&
|
|
j.LastState == animal.LastState.ID)
|
|
{
|
|
activeJump = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var JumpNumber = 0;
|
|
|
|
//Search again if the Character can perform multiple jumps
|
|
if (Jumps > 1 && JumpsPerformanced > 1 && multipleJumps != null && multipleJumps.Count > 0)
|
|
{
|
|
var PosibleJump = new JumpDoubleProfile() { JumpNumber = -1 };
|
|
|
|
foreach (var j in multipleJumps) //Save/Search the Current Jump Profile by the Lowest Speed available
|
|
{
|
|
if (JumpsPerformanced == j.JumpNumber) PosibleJump = j;
|
|
}
|
|
|
|
if (PosibleJump.JumpNumber != -1) //Means that it found a Multiple Jump
|
|
{
|
|
activeJump.name = PosibleJump.name;
|
|
activeJump.GravityPower = PosibleJump.GravityPower;
|
|
activeJump.Height = PosibleJump.Height;
|
|
activeJump.JumpTime = PosibleJump.JumpTime;
|
|
activeJump.StartGravityTime = PosibleJump.StartGravityTime;
|
|
JumpNumber = PosibleJump.JumpNumber;
|
|
IsDoubleJump = true;
|
|
}
|
|
}
|
|
SetEnterStatus(JumpNumber);
|
|
}
|
|
|
|
public override void EnterCoreAnimation()
|
|
{
|
|
Debugging($"Jump Profile: [{activeJump.name}] Jump:[{JumpsPerformanced}]");
|
|
JumpPressHeight_Value = 1;
|
|
|
|
var Speed = animal.HorizontalSpeed;
|
|
|
|
// var passInertia = true;
|
|
|
|
if (animal.HasExternalForce)
|
|
{
|
|
var HorizontalForce = Vector3.ProjectOnPlane(animal.ExternalForce, animal.UpVector); //Remove Horizontal Force
|
|
var HorizontalInertia = Vector3.ProjectOnPlane(animal.Inertia, animal.UpVector); //Remove Horizontal Force
|
|
|
|
var HorizontalSpeed = HorizontalInertia - HorizontalForce;
|
|
Speed = HorizontalSpeed.magnitude;
|
|
// passInertia = false;
|
|
}
|
|
|
|
|
|
if (!animal.ExternalForceAirControl)
|
|
{
|
|
Speed = 0; //Remove all Speed if the External Force does not allows it
|
|
}
|
|
|
|
JumpSpeed = new MSpeed(animal.CurrentSpeedModifier) //Inherit the Vertical and the Lerps
|
|
{
|
|
name = "Jump Basic Speed",
|
|
position = General.RootMotion ? 0 : Speed, //Inherit the Horizontal Speed you have from the last state
|
|
strafeSpeed = General.RootMotion ? 0 : Speed,
|
|
lerpPosition = AirSmooth.Value,
|
|
lerpStrafe = AirSmooth.Value,
|
|
rotation = AirRotation.Value,
|
|
animator = 1,
|
|
};
|
|
|
|
animal.SetCustomSpeed(JumpSpeed, false); //Set the Current Speed to the Jump Speed Modifier
|
|
|
|
if (!WaitForAnimation) ActivateJump(); //if it does not require to Wait for the Animator to call
|
|
|
|
if (IsDoubleJump) ActivateJump(); //Mean is doing a double jump!
|
|
}
|
|
|
|
|
|
|
|
public override Vector3 Speed_Direction()
|
|
{
|
|
return AirControl.Value ? base.Speed_Direction() : StartingSpeedDirection;
|
|
}
|
|
|
|
private Vector3 StartingSpeedDirection;
|
|
|
|
|
|
public override void EnterTagAnimation()
|
|
{
|
|
if (CurrentAnimTag == JumpStartHash && !animal.RootMotion)
|
|
{
|
|
var speed = animal.HorizontalSpeed / ScaleFactor;
|
|
|
|
var JumpStartSpeed = new MSpeed(animal.CurrentSpeedModifier)
|
|
{
|
|
name = "JumpStartSpeed",
|
|
position = speed,
|
|
Vertical = animal.CurrentSpeedModifier.Vertical,
|
|
animator = 1,
|
|
rotation = AirControl.Value ? (!animal.UseCameraInput ? AirRotation.Value : AirRotation.Value / 10f) : 0f,
|
|
strafeSpeed = speed,
|
|
lerpStrafe = AirSmooth
|
|
};
|
|
|
|
Debugging("[EnterTag-JumpStart]");
|
|
animal.SetCustomSpeed(JumpStartSpeed, false); //Set the Current Speed to the Jump Speed Modifier
|
|
|
|
if (animal.TerrainSlope > 0) animal.UseCustomAlign = true; //Means we are jumping uphill
|
|
|
|
}
|
|
else if (CurrentAnimTag == JumpEndHash)
|
|
{
|
|
Debugging("[EnterTag-JumpEnd]");
|
|
AllowExit();
|
|
}
|
|
}
|
|
|
|
|
|
public override void OnStateMove(float deltaTime)
|
|
{
|
|
if (InCoreAnimation && ActivateJumpLogic)
|
|
{
|
|
if (JumpPressed.Value)
|
|
{
|
|
if (!InputValue) justJumpPressed = false;
|
|
|
|
JumpPressHeight_Value = Mathf.Lerp(JumpPressHeight_Value, (InputValue && justJumpPressed) ? 1 : 0, deltaTime * JumpPressedLerp);
|
|
}
|
|
|
|
Vector3 ExtraJumpHeight = (UpVector * activeJump.Height.Value);
|
|
animal.AdditivePosition += ExtraJumpHeight * deltaTime * JumpPressHeight_Value * ScaleFactor; //Up Movement
|
|
|
|
|
|
if (AirMovement > CurrentSpeedPos && AirControl)
|
|
{
|
|
if (!animal.ExternalForceAirControl) return;
|
|
CurrentSpeedPos = Mathf.Lerp(CurrentSpeedPos, AirMovement, (AirSmooth != 0 ? (deltaTime * AirSmooth) : 1));
|
|
}
|
|
|
|
//Apply Fake Gravity (HAD TO TO IT)
|
|
|
|
var GTime = deltaTime * animal.GravityTime;
|
|
var GravityStoredVelocity = Gravity * animal.GravityPower * (GTime * GTime / 2);
|
|
animal.AdditivePosition += GravityStoredVelocity * deltaTime * activeJump.GravityPower.Value * ScaleFactor; //Add Gravity if is in use
|
|
animal.GravityTime++;
|
|
}
|
|
}
|
|
|
|
public override void TryExitState(float deltaTime)
|
|
{
|
|
if (!ActivateJumpLogic) return; //The Jump logic has not being activated yet
|
|
|
|
Debug.DrawRay(animal.Main_Pivot_Point, Gravity * Height * JumpInterruptRay, Color.black);
|
|
|
|
if (Physics.Raycast(animal.Main_Pivot_Point, Gravity, out _, Height * JumpInterruptRay, GroundLayer, IgnoreTrigger))
|
|
{
|
|
Debugging("[Allow Exit] - Interrupt Ray Touched Ground");
|
|
AllowExit();
|
|
}
|
|
else if (MTools.ElapsedTime(StartedJumpLogicTime, activeJump.JumpTime))
|
|
{
|
|
AllowExit();
|
|
|
|
var lastGravityTime = animal.GravityTime;
|
|
animal.State_Activate(StateEnum.Fall); //Seems Important
|
|
animal.GravityTime = lastGravityTime;
|
|
|
|
Debugging("[Allow Exit]");
|
|
}
|
|
}
|
|
|
|
/// <summary>Is called when a new State enters</summary>
|
|
public override void NewActiveState(StateID newState)
|
|
{
|
|
if (newState.ID == ID) return; //Do nothing if this we are entering the same state
|
|
|
|
//Reset all the jumps (Idle and Locomotion) and all the extra States required
|
|
if (newState <= 1 || ResetJump.Contains(newState))
|
|
{
|
|
JumpsPerformanced = 0; //Reset the amount of jumps performanced
|
|
}
|
|
else if (newState == StateEnum.Fall && animal.LastState.ID <= 1) //If we were not jumping then increase the Double Jump factor when falling from locomotion
|
|
{
|
|
JumpsPerformanced++; //If we are in fall animation then increase a Jump perfomanced
|
|
}
|
|
}
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
internal void Reset()
|
|
{
|
|
ID = MTools.GetInstance<StateID>("Jump");
|
|
Input = "Jump";
|
|
|
|
SleepFromState = new List<StateID>() { /*MTools.GetInstance<StateID>("Fall"),*/ MTools.GetInstance<StateID>("Fly") };
|
|
SleepFromMode = new List<ModeID>() { MTools.GetInstance<ModeID>("Action"), MTools.GetInstance<ModeID>("Attack1") };
|
|
|
|
EnterTag.Value = "JumpStart";
|
|
ExitTag.Value = "JumpEnd";
|
|
|
|
General = new AnimalModifier()
|
|
{
|
|
RootMotion = false,
|
|
Grounded = false,
|
|
Sprint = false,
|
|
OrientToGround = false,
|
|
CustomRotation = false,
|
|
IgnoreLowerStates = true, //IMPORTANT!
|
|
Persistent = true,
|
|
AdditivePosition = true,
|
|
AdditiveRotation = true,
|
|
Gravity = false,
|
|
modify = (modifier)(-1),
|
|
};
|
|
|
|
ExitFrame = false;
|
|
|
|
profiles = new List<JumpBasicProfile>(1) { new JumpBasicProfile()
|
|
{
|
|
Height = new FloatReference(6),
|
|
GravityPower = new FloatReference(1),
|
|
JumpTime = 0.3f,
|
|
VerticalSpeed = 0,
|
|
name = "Default",
|
|
StartGravityTime = 15,
|
|
LastState = null,
|
|
}
|
|
};
|
|
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/// <summary>Different Jump parameters on different speeds</summary>
|
|
[System.Serializable]
|
|
public struct JumpBasicProfile
|
|
{
|
|
//[Tooltip("Name to identify the Jump Profile")]
|
|
public string name;
|
|
|
|
// [Header("Conditions")]
|
|
// [Tooltip("Last State the animal was before making the Jump")]
|
|
public StateID LastState;
|
|
|
|
// [Tooltip("Minimal Vertical Speed to Activate this Profile")]
|
|
public float VerticalSpeed;
|
|
|
|
// [Header("Values")]
|
|
// [Tooltip("Duration of the Jump logic")]
|
|
public float JumpTime;
|
|
|
|
// [Tooltip("How High the animal can Jump")]
|
|
public FloatReference Height;
|
|
|
|
// [Tooltip("Multiplier for the Gravity")]
|
|
public FloatReference GravityPower;
|
|
|
|
// [Tooltip("Higher value makes the Jump more Arcady")]
|
|
public int StartGravityTime;
|
|
|
|
//public JumpBasicProfile(int Vertical)
|
|
//{
|
|
// Height = new FloatReference(6);
|
|
// GravityPower = new FloatReference(1);
|
|
// JumpTime = 0.3f;
|
|
// VerticalSpeed = Vertical;
|
|
// name = "Default";
|
|
// StartGravityTime = 15;
|
|
// LastState = null;
|
|
//}
|
|
}
|
|
|
|
|
|
/// <summary>Different Jump parameters for Multiple Jumps</summary>
|
|
[System.Serializable]
|
|
public struct JumpDoubleProfile
|
|
{
|
|
[Tooltip("Name to identify the Jump Profile")]
|
|
public string name;
|
|
|
|
[Tooltip("Multiple Jump Number (Is it a Double or a Triple Jump. Default is 0. This is the Value for the [Enter State Status]")]
|
|
public int JumpNumber;
|
|
|
|
[Header("Values")]
|
|
[Tooltip("Duration of the Jump logic")]
|
|
public float JumpTime;
|
|
|
|
[Tooltip("How High the animal can Jump")]
|
|
public FloatReference Height;
|
|
|
|
[Tooltip("Multiplier for the Gravity")]
|
|
public FloatReference GravityPower;
|
|
|
|
[Tooltip("Higher value makes the Jump more Arcady")]
|
|
public int StartGravityTime;
|
|
}
|
|
}
|