- Home /
How to only Jump on Ground Items
So im making a 2D platformer and im having an issue with jumping. I just started the game so there isnt much code. I got all the code and animation for moving and jumping sorted out but my "groundCheck" isnt working properly. I made an empty game object and put it on the feet of my Player. The code i attached to it is called "GroundCheck" and it is supposed to restrict the Player from being able to jump unless they are on the "ground" and only jump one time (not infinitely).
I think this is a pretty normal issue but my Player can jump on anything that has a collider including coins and enemies. For my actual ground platforms, I put "Ground" as their layer at the top of the inspector. My question is, how do I decipher between what is the difference between the ground, a coin or an enemy in a way my code will understand? I think thats the problem. The groundCheck Is Trigger so I feel like every collider it is coming into contact with is somehow being considered ground? Ill Post my code for the groundCheck and the Player its attached to. Let me know if you guys need anymore info! Thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
public float maxSpeed = 3; //limits the speed
public float speed = 50f;
public float jumpPower = 150f;
public bool grounded;
private Rigidbody2D rb2d;
private Animator anim;
void Start ()
{
rb2d = gameObject.GetComponent<Rigidbody2D>();
anim = gameObject.GetComponent<Animator>();
}
void Update ()
{
anim.SetBool("Grounded",grounded);
anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis("Horizontal")));
if (Input.GetAxis("Horizontal") < -0.1f)
{
transform.localScale = new Vector3(-1,1,1); //These two bits of code make the player animations switch directions when walking back a forth
}
if (Input.GetAxis("Horizontal") > 0.1f)
{
transform.localScale = new Vector3(1, 1, 1);
}
if(Input.GetButtonDown("Jump") && grounded ==true)
{
rb2d.AddForce(Vector2.up * jumpPower);//Jumps with spacebar (spacebar is Jump by default)
}
}
void FixedUpdate()
{
Vector3 easeVelocity = rb2d.velocity;
easeVelocity.y = rb2d.velocity.y; //This is set up to not affect y axis
easeVelocity.z = 0.0f; //set for 0 cause you dont use z axis in 2D game
easeVelocity.x *= 0.75f;
//for left and right arrows
float h = Input.GetAxis("Horizontal");
//Fake friction / keeps player from sliding
if(grounded)
{
rb2d.velocity = easeVelocity;
}
//will physically move player when left / right pressed
rb2d.AddForce((Vector2.right * speed) * h);
//basically if this hits max speed, it will keep it there and not go faster
if (rb2d.velocity.x > maxSpeed)
{
rb2d.velocity = new Vector2(maxSpeed, rb2d.velocity.y);//this is max speed for moving right
}
if(rb2d.velocity.x <-maxSpeed)
{
rb2d.velocity = new Vector2(-maxSpeed, rb2d.velocity.y);//this is max speed for moving left
}
}
}
And for the groundCheck
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GroundCheck : MonoBehaviour {
private Player player; //refferences the Player script
void Start ()
{
player = gameObject.GetComponentInParent<Player>();//If this code messes up what is considered grounded, on ep 3 there is a comment with other code you can try
}
void OnTriggerEnter2D(Collider2D col)
{
player.grounded = true;//NOTE: This may be the bad code. this makes it look like if the grounded game object under the players feet collides collides with another Collider 2D, he is grounded. This wouldnt be true for landing on enemies.
}
void OnTriggerStay2D(Collider2D col)
{
player.grounded = true; //Fixes groundCheck bug?
}
void OnTriggerExit2D(Collider2D col)
{
player.grounded = false;//When player is not on a collider, he is not grounded (i dont think this should always be false)
}
}
Answer by IndievdB · Sep 20, 2017 at 01:58 AM
Normally you would check the Collider2D's layer with col.gameobject.layer == "Grounded", but I don't recommend this. You will have to keep track of everything you collide with and using a collider to check if you are grounded can be a little inconsistent. I suggest you ditch GroundCheck.cs and use raycasts instead. Something like this should work:
bool IsGrounded()
{
return Physics2D.Raycast (transform.position, new Vector2 (0, -1), groundCheckDistance, LayerMask.GetMask ("Ground"));
}
In your update, you can use Debug.DrawRay to visualize the raycast.