So I’m working on a state machine with a BUNCH of states and I’m trying to determine when the player enters the falling state. I see a bunch of examples that follow something like this:
yVel = rigidbody.velocity.y; //y velocity of rigidbody
if (yVel < 0) //if it's negative, that means it's falling down so set to true
isFalling = true;
That would likely work just fine IF i wasn’t using a custom gravity script. The script applies a gravitational force to the rigidbody in the direction of gravity.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class GravityBody : MonoBehaviour
{
//override the monobehavior's rigidbody getter
private new Rigidbody rigidbody;
[SerializeField]
private float m_Acceleration;
[SerializeField]
private Vector3 m_GravityDirection = new Vector3(0,1,0);
public bool useGravity = true;
public bool useFixedUpdate = true; //basically allows us to apply gravity in this script (true) or apply it in a class that uses it
public float jumpForce = 10;
/// <summary>The acceleration rate of gravity.</summary>
public float Acceleration
{
get
{
return m_Acceleration;
}
set
{
m_Acceleration = Mathf.Min(value, 0);
}
}
/// <summary>The direction of gravity.</summary>
public Vector3 GravityDirection
{
get
{
return m_GravityDirection;
}
set
{
m_GravityDirection = value.normalized;
}
}
///<summary>Force applied to body</summary>
public Vector3 Gravity
{
get
{
return -Acceleration * GravityDirection.normalized * rigidbody.mass;
}
}
public RigidbodyConstraints Constraints
{
get
{
return rigidbody != null ? rigidbody.constraints : RigidbodyConstraints.None;
}
set
{
rigidbody.constraints = value;
}
}
private void Start()
{
rigidbody = GetComponent<Rigidbody>();
rigidbody.useGravity = false;
}
private void FixedUpdate()
{
if (useFixedUpdate)
ApplyGravity();
//For testing purposes only
if (Input.GetButtonDown("Jump"))
rigidbody.AddForce(GravityDirection * jumpForce, ForceMode.Impulse);
}
public void InitGravityBody(Rigidbody rb)
{
rigidbody = rb;
useFixedUpdate = false;
}
public void ApplyGravity()
{
if (useGravity)
{
rigidbody.AddForce(Gravity);
}
}
//Editor
private void OnValidate()
{
m_Acceleration = Mathf.Max(m_Acceleration, 0f);
m_GravityDirection = m_GravityDirection.normalized;
}
}
This means that won’t work in this regards. How do I check if my player is falling in this regards? Is there a cheat I can do to do what I described earlier?
So I figured it out with some help from the Infallible Code Discord (thanks apieceoffruit!)
He told be about Vector3.dots and this is what we came up with
public bool CheckFalling(bool grounded = false)
{
var gravDir = useGravity ? GravityDirection : Vector3.zero;
FallingVelocity = Vector3.Dot(rigidbody.velocity, gravDir);
if (Mathf.Approximately(FallingVelocity, 0))
FallingVelocity = 0f;
if ( FallingVelocity < 0 && grounded == false)
{
return true;
}
return false;
}
So if the character is falling, the dot’s value return negative and if the character is ascending it returns positive, all relative to the gravity’s direction and velocity of the rigidbody