Hi everyone,
I need a little guidance… I can’t seem to figure out the proper way to detect negative y movement (downward movement).
In my current script, I am constantly setting my player into a “falling” state.
This section of the code is the culprit. I know it’s wrong, clearly, because player starts out doing the falling animation. (and I will note, this is despite the fact that the “onLand” bool is true, which should disable that animator bool)
// stuff below for determining if player is not "on land" and/or is falling
verticalVel = rb.velocity.y;
if (onLand == true)
{
animator.SetBool("IsFalling", false);
}
if (verticalVel >= 1f)
{
onLand = false;
Debug.Log("Is jumping");
}
if (verticalVel <= -1f)
{
onLand = false;
animator.SetBool("IsFalling", true);
Debug.Log("Is Falling");
}
else animator.SetBool("IsFalling", false);
And here’s the full code of my charactercontroller (which this appears)
using System.Collections; // call these systems to be used by this script
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour // public name of this script. Public means the name that other scripts can see it/reference it
{
// all of our initial declarations need to go directly below, BEFORE any function like start, update...
CharacterController2D controller; // cache charactercontroller script, must be defined below in awake or start
Animator animator; // cache the animator, must be defined in awake or start
PlayerHealth playerHealth; // cache playerhealth script, must be defined below in awake or start
Rigidbody2D rb; // cache the rigidbody2d name
public float runSpeed = 30f; // make a public float number called runSpeed. Maths and calculations are below in void start()
public float verticalVel; // declare a float called verticalVel
float horizontalMove = 0f; // make a float number called horizontalMove and set it to 0 by default
bool jump = false; // create a "bool" called "jump". A bool is a parameter, flag, or state, that can either be true or false
bool crouch = false; // create a "bool" called crouch, false by default
public bool attack = true; // create a "bool" called "attack", false by default. This bool is "public", meaning it can be seen/controlled by outside scripts
public bool onLand = true; // I want to be able to see in the inspector when the player is considered "on land". "landed" state is set by functions below
public bool canAttack; // create a "bool" called "canAttack". Oh, and in c#, the first letter of any bool or float name is automatically capitalized. Any following capitalized letter is automatically spaced. So, canAttack will actually be "Can Attack".
void Awake()
{
controller = GetComponent<CharacterController2D>(); // now we define what the controller points too
rb = GetComponent<Rigidbody2D>(); // along with the rest....
animator = GetComponent<Animator>(); // same
playerHealth = GetComponent<PlayerHealth>(); // same
}
void Update() // these functions happen once every frame
{
// stuff below for determining if player is not "on land" and/or is falling
verticalVel = rb.velocity.y;
if (onLand == true)
{
animator.SetBool("IsFalling", false);
}
if (verticalVel >= 1f)
{
onLand = false;
Debug.Log("Is jumping");
}
if (verticalVel <= -1f)
{
onLand = false;
animator.SetBool("IsFalling", true);
Debug.Log("Is Falling");
}
else animator.SetBool("IsFalling", false);
//moving left/right below
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed; // Horizontal move will equal the movement of "Horizonal" axis multiplied by our defined run speed float. Also sets controls that allow player to move left and right
animator.SetFloat("Speed", Mathf.Abs(horizontalMove)); // Trigger the "Speed" float variable in the animator and inserts the value of whatever Horizontal move above ends up being, but before that, use "Mathf.Abs" function to only allow positive values of this number (and never allow a negative value)
//Jump Setup Below
if (Input.GetButtonDown("Jump")) // If player presses the "jump" button...
{
jump = true; // change the "jump" bool to true
animator.SetBool("IsJumping", true); // change animator bool of "IsJumping" to true. Since inside the animator we have made transitions from idle to jumping, which requires "IsJumping" to be true to happen
onLand = false; // onLand boolean is set to false as soon as the jump button is pressed. onLand will return to true as soon as ground is touched.
}
//Attack Setup Below
if (canAttack == true) // if the bool "canAttack" is currently set to true...
{
if (Input.GetButtonDown("Attack1")) // ...and if "attack" button is pressed....
{
StartCoroutine(PlayerIsInvulnerable());
StartCoroutine(PlayerIsAttacking()); // we want the "PlayerIsAttacking" function from above to run
animator.SetBool("IsAttacking", true); // and change animator bool of "IsAttacking" to true. Attack Animator requires "IsAttacking" to be true for it to fire/play
}
else if (Input.GetButtonUp("Attack1")) // otherwise, once the button is released....
{
animator.SetBool("IsAttacking", false); // set the IsAttacking bool back to false
}
}
else animator.SetBool("IsAttacking", false); // an else statement directly following an "If" statement means "otherwise, do this". We want to make sure the "IsAttacking" state is always set to false, unless the player presses the attack button
if (attack == true)
{
rb.constraints = RigidbodyConstraints2D.FreezePositionY | RigidbodyConstraints2D.FreezeRotation; // if player is attacking, make sure that they are frozen on the y access and rotation, so they don't bounce around
}
else rb.constraints = RigidbodyConstraints2D.FreezeRotation; // otherwise, the rotation only is frozen
//Crouch Setup Below
if (Input.GetButtonDown("Crouch")) // If the player presses the crouch button....
{
crouch = true; // set crouching state to true
animator.SetBool("IsCrouching", true); // tell the animator that condition "IsCrouching" is now true. In the animator transitions, the crouch animation will only fire when the animator condition "IsCrouching" is true
}
else if (Input.GetButtonUp("Crouch")) // "else if" statements can contain bracketed functions, unlike "else" statements. if the crouch button is no longer being pressed....
{
crouch = false; // set crouching state to false
animator.SetBool("IsCrouching", false); // tell the animator that the character "IsCrouching" no more,
}
}
public IEnumerator PlayerIsInvulnerable() // this is a special function called PlayerIsInvulerable. Some below function in void update will have to trigger this to run
{
//the below instructions happen in order
playerHealth.noDamage = true; // "No Damage" is a public bool inside of the Player Health script. To Access it, we do this - scriptname.function, but only if we have declared it above in class.
yield return new WaitForSeconds(.80f); // we are going to wait 80/100 of a second
playerHealth.noDamage = false; // as well as our "no damage" bool inside player health
}
public IEnumerator PlayerIsAttacking() // this is a special function called PlayerIsAttacking. Some below function in void update will have to trigger this to run
{
//the below instructions happen in order
attack = true; // "No Damage" is a public bool inside of the Player Health script. To Access it, we do this - scriptname.function, but only if we have declared it above in class.
yield return new WaitForSeconds(.30f); // we are going to wait 80/100 of a second
attack = false; // as well as our "no damage" bool inside player health
}
public void OnLanding () // This is a trigger called "OnLanding", and in our case, will be used to tell the game what to do when the player stops (lands) on a collider
{
if (verticalVel <= 0) // If vertical velocity is less than 0, declared above as the y velocity of rigidbody2d.
{
animator.SetBool("IsJumping", false); // automatically disable the jumping state when player "lands"
animator.SetBool("IsFalling", false);
onLand = true; // set the onland bool to true
}
}
void FixedUpdate () // a non public void function called FixedUpdate
{
controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump); // Since we defined the Character Controller script at the top as public, we can call the functions within it. "controller.Move(stuffhere)" actually is read as "Use CharacterController Move Function (and insert function here)". If you look in Character Controller script, you can find the "Move" function. Anyway, that function defines 3 "bools" in order of Move, Crouch, and Jump. We are setting those bools with the actions we have defined here in this script --- and they need to be in the same order of the Move Function for them to work how we want
crouch = false; // set the default state of crouching within character controller to false
jump = false; // set the default state of Jumping within character controller to false
}
}