How to jumping only on the ground

Hello! I have a problem with my script : I want my player to jump only when he is on the ground. But my script doesn’t work, can you please tell me what’s is wrong with him?

I’m new with scripting, i’m really a beginner. The original code is from the unity tutorial “roll-a-ball”.

My technique is to declare a boolean called “canjump” who become true only when he is on a game object with the tag “ground”. When the boolean is true and the player press the jump button, the avatar jump.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class PlayerController : MonoBehaviour {

private Rigidbody rb;
public Text countText;
public Text WinText;
public float speed;
private int count;
public float upper = 9.0F;
public bool canjump = false; // boolean for jump

void Start ()
{
rb = GetComponent ();
count = 0;
SetCountText ();
WinText.text = “”;
canjump = false; // the boolean is false by default
}

void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis (“Horizontal”);
float movevertical = Input.GetAxis (“Vertical”);

Vector3 movement = new Vector3 (moveHorizontal, 0.0f, movevertical);

rb.AddForce (movement * speed);

if ((canjump == true) && (Input.GetButton (“Jump”))) //if canjump boolean is true and if the player press the button jump , the player can jump.
{
Vector3 up = new Vector3 (0.0f, upper, 0.0f); // script for jumping
rb.AddForce (up * upper);
}
}

void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag (“Pick Up”))
{
other.gameObject.SetActive(false);
count++;
SetCountText ();
}

if (other.gameObject.CompareTag (“ground”))// if the player is touching the gameobject with the Tag ground, the boolean become true
{
canjump = true;
}
else //if the player is not anymore on the ground, the boolean become false
{
canjump = false;
}

}

void SetCountText ()
{
countText.text = "Count: " + count.ToString ();
if (count >= 8)
{
WinText.text = “You Win!”;
}
}

}

[ code] [ /code] tags when you paste in code to the forums please, really helps with the readability, sticking on them at the top of the scripting forum.

does the ground have a collider set to trigger on it?

The way I normally set this up is like this:

if (Input.GetKey("space") && playerController.isGrounded) {
            playerController.Move(Vector3.up);
        }

That’s a little snippet from the code I use basically the isGrounded will check if you are grounded or not if im not mistaken.

If you are using a RegidBody I would probably go about using a short raycast downward to check if im grounded or not.

thanks for the advice LeftRighty i’ll think about it next time! Yeah i’ve tried with a collider and with a trigger but nothing to do, it’s not working!! :frowning:

DarkBladeNemo i’ll try the raycast tonight, i’ve never do raycast before, i’ll use the unity documentation, thanks!

(and sorry if i have a bad english, i’m french and i’m trying to learn since not long :wink: )

Hey guys! I’ve manage for the bool to become “true” if the player touch the ground, but he doesn’t become “false” when the player quit the ground. Any advice? I’ll put my new script below. to see the script that blew the player, look at the lines with the comments.

public class PlayerController : MonoBehaviour {

    private Rigidbody rb;
    public Text countText;
    public Text WinText;
    public float speed;
    private int count;
    public float upper = 9.0F;
    public bool canjump = false; // boolean for jump

    void Start ()
    {
        rb = GetComponent<Rigidbody> ();
        count = 0;
        SetCountText ();
        WinText.text = "";
        canjump = false; // the boolean is false by default
    }
   


    void FixedUpdate ()
    {
        float moveHorizontal = Input.GetAxis ("Horizontal");
        float movevertical = Input.GetAxis ("Vertical");

        Vector3 movement = new Vector3 (moveHorizontal, 0.0f, movevertical);

        rb.AddForce (movement * speed);


            if ((canjump == true) && (Input.GetButton ("Jump"))) //if canjump boolean is true and if the player press the button jump , the player can jump.
            {
                Vector3 up = new Vector3 (0.0f, upper, 0.0f); // script for jumping
                rb.AddForce (up * upper);
            }
    }
   

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag ("Pick Up"))
        {
            other.gameObject.SetActive(false);
            count++;
            SetCountText ();
        }

        if (other.gameObject.CompareTag ("ground"))
        {
            canjump = true; // if the player is in the ground, the bool "canjump" become true
        }
        else
        {
            canjump = false; //if the player quit the ground, the bool become false
        }

    }
   
    void SetCountText ()
    {
        countText.text = "Count: " + count.ToString ();
        if (count >= 8)
        {
            WinText.text = "You Win!";
        }
    }
}
1 Like
if (other.gameObject.CompareTag ("ground"))
{
    canjump = true; // if the player is in the ground, the bool "canjump" become true
}
else
{
    canjump = false; //if the player quit the ground, the bool become false
}

Put this in the FixedUpdate, as the way you have set it up, the else condition never gets triggered unless you trigger another gameObject altogether.

Okay thanks! But it’s working the same way! ^^

How can i trigger the else condition just in leaving the ground?

up

Here is a script from the Unity 5 Standard Assets pack that shows an implementation of the jump mechanic:

using System;
using UnityEngine;

namespace UnityStandardAssets._2D
{
    public class PlatformerCharacter2D : MonoBehaviour
    {
        [SerializeField] private float m_MaxSpeed = 10f;                    // The fastest the player can travel in the x axis.
        [SerializeField] private float m_JumpForce = 400f;                  // Amount of force added when the player jumps.
        [Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f;  // Amount of maxSpeed applied to crouching movement. 1 = 100%
        [SerializeField] private bool m_AirControl = false;                 // Whether or not a player can steer while jumping;
        [SerializeField] private LayerMask m_WhatIsGround;                  // A mask determining what is ground to the character

        private Transform m_GroundCheck;    // A position marking where to check if the player is grounded.
        const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
        private bool m_Grounded;            // Whether or not the player is grounded.
        private Transform m_CeilingCheck;   // A position marking where to check for ceilings
        const float k_CeilingRadius = .01f; // Radius of the overlap circle to determine if the player can stand up
        private Animator m_Anim;            // Reference to the player's animator component.
        private Rigidbody2D m_Rigidbody2D;
        private bool m_FacingRight = true;  // For determining which way the player is currently facing.

        private void Awake()
        {
            // Setting up references.
            m_GroundCheck = transform.Find("GroundCheck");
            m_CeilingCheck = transform.Find("CeilingCheck");
            m_Anim = GetComponent<Animator>();
            m_Rigidbody2D = GetComponent<Rigidbody2D>();
        }


        private void FixedUpdate()
        {
            m_Grounded = false;

            // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
            // This can be done using layers instead but Sample Assets will not overwrite your project settings.
            Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
            for (int i = 0; i < colliders.Length; i++)
            {
                if (colliders[i].gameObject != gameObject)
                    m_Grounded = true;
            }
            m_Anim.SetBool("Ground", m_Grounded);

            // Set the vertical animation
            m_Anim.SetFloat("vSpeed", m_Rigidbody2D.velocity.y);
        }


        public void Move(float move, bool crouch, bool jump)
        {
            // If crouching, check to see if the character can stand up
            if (!crouch && m_Anim.GetBool("Crouch"))
            {
                // If the character has a ceiling preventing them from standing up, keep them crouching
                if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
                {
                    crouch = true;
                }
            }

            // Set whether or not the character is crouching in the animator
            m_Anim.SetBool("Crouch", crouch);

            //only control the player if grounded or airControl is turned on
            if (m_Grounded || m_AirControl)
            {
                // Reduce the speed if crouching by the crouchSpeed multiplier
                move = (crouch ? move*m_CrouchSpeed : move);

                // The Speed animator parameter is set to the absolute value of the horizontal input.
                m_Anim.SetFloat("Speed", Mathf.Abs(move));

                // Move the character
                m_Rigidbody2D.velocity = new Vector2(move*m_MaxSpeed, m_Rigidbody2D.velocity.y);

                // If the input is moving the player right and the player is facing left...
                if (move > 0 && !m_FacingRight)
                {
                    // ... flip the player.
                    Flip();
                }
                    // Otherwise if the input is moving the player left and the player is facing right...
                else if (move < 0 && m_FacingRight)
                {
                    // ... flip the player.
                    Flip();
                }
            }
            // If the player should jump...
            if (m_Grounded && jump && m_Anim.GetBool("Ground"))
            {
                // Add a vertical force to the player.
                m_Grounded = false;
                m_Anim.SetBool("Ground", false);
                m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
            }
        }


        private void Flip()
        {
            // Switch the way the player is labelled as facing.
            m_FacingRight = !m_FacingRight;

            // Multiply the player's x local scale by -1.
            Vector3 theScale = transform.localScale;
            theScale.x *= -1;
            transform.localScale = theScale;
        }
    }
}

You can download the package in Unity by going from the menu to Assets > Import Package > 2D