How to allow to jump only once in Unity2D - c#

Hey Guys im Currently working on an 2D Endlessrunner and i need help, i want to only jump once until the character touches the ground again could anyone help me please i would be very thankfull
heres the code for the character :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Dino : MonoBehaviour
{
bool isJumping;
Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
isJumping = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetKey("space"))
{
rb.velocity = new Vector3(0, 20, 0);
isJumping = true;
}
}
}

Add the is jumping condition to your jump code like this:
// Update is called once per frame
void Update()
{
if (Input.GetKey("space") && !isJumping)
{
rb.velocity = new Vector3(0, 20, 0);
isJumping = true;
}
}
And handle the isJumping boolean in the collision logic of your character with the ground. You can keep a reference to the floor collider to check if whats dino is colliding with is the floor:
public collider2D floorCol; //attach in unity editor
OnCollisionEnter2D(Collision2D collision) {
//check you are colliding with the floor
if (collision.collider == floorCol)
isJumping = false;
}
assuming 2d for simplicity's sake.

Related

Character Stopped Moving and I Don't Know Why

I had my code working perfectly the character was moving side to side and jumping but I tried to get him to stop jumping twice and he just stopped moving entirely. Can you help me figure out what I did wrong? I have looked this question up but yet to find an answer that makes sense to me (I'm relatively new) so if some can work through this with me I would appreciate it greatly so I can get back to work learning.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
bool jumpKeyWasPressed;
float horizontalInput;
Rigidbody rigidBodyComponent;
bool isGrounded;
// Start is called before the first frame update
void Start()
{
rigidBodyComponent = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
//Space key input
if (Input.GetKeyDown(KeyCode.Space))
{
jumpKeyWasPressed = true;
}
horizontalInput = Input.GetAxis("Horizontal");
}
//main problem I think
void FixedUpdate ()
{
if (!isGrounded)
{
return;
}
if (jumpKeyWasPressed)
{
rigidBodyComponent.AddForce(Vector3.up * 5, ForceMode.VelocityChange);
jumpKeyWasPressed = false;
}
rigidBodyComponent.velocity = new Vector3(horizontalInput,rigidBodyComponent.velocity.y, 0);
}
void OnCollisionEnter(Collision collision)
{
isGrounded = true;
}
void OnCollisionExit(Collision collision)
{
isGrounded = false;
}
}
If isGrounded is false, you return right out of the function. The last line is also skipped this way. To fix this, you could simply check if isGrounded is true, and only execute the jumping code then (forget return).
if (isGrounded) {
if (jumpKeyWasPressed) {
// ...
}
}

Why is my collision not detecting (unity)

So right now I am stuck. I want to make a conveyor belt with my code but I ran inot this problem. I found this piece of code,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ConveyorPush : MonoBehaviour {
public float speed = 3.0f;
void OnTriggerStay(Collider other) {
// Assign velocity based upon direction of conveyor belt
// Ensure that conveyor mesh is facing towards its local Z-axis
float conveyorVelocity = speed * Time.deltaTime;
Rigidbody rigidbody = other.gameObject.GetComponent<Rigidbody>();
rigidbody.velocity = conveyorVelocity * transform.forward;
}
}
I understand it but for some reason my trigger collider on the conveyor belt is not detecting a collision to a sprite with a non-trigger collider that has a rigid body.
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false;
FindObjectOfType<GameManager>().GameOver();
rb.useGravity = false;
rb.AddExplosionForce(1000,transform.position, 200);
}
}
When you defined collider in the function u didn't use it anywhere
If your using 2d then u should use the 2d collider
void OnCollisionEnter(Collision2D collisionInfo)
{
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false;
FindObjectOfType<GameManager>().GameOver();
rb.useGravity = false;
rb.AddExplosionForce(1000,transform.position, 200);
}
}
Collision and Collision2D are types u have to define

OnTriggerEnter2D() seems to not work unity

I am developing a platform game, where a ball should be able to move left and right and to jump. I could make the character jump or move successfully, but when i tried to check if it was on the ground, by creating an element as child of the character, with a trigger collider 2D, and wrote the code using a variable that was supposed to be true when the player was touching the ground, and false when it wasn't, it just did not activate.
Here is the code for the main movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Grounded : MonoBehaviour
{
GameObject Player;
// Start is called before the first frame update
void Start()
{
Player = gameObject.transform.parent.gameObject;
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (GetComponent<Collider2D>().tag == "Ground")
{
Player.GetComponent<Move2D>().isGrounded = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (GetComponent<Collider2D>().tag == "Ground")
{
Player.GetComponent<Move2D>().isGrounded = true;
}
}
}
And this is the Grounded script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move2D : MonoBehaviour
{
public float moveSpeed = 5f;
public bool isGrounded = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Jump();
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
transform.position += movement * Time.deltaTime * moveSpeed;
}
void Jump()
{
if (Input.GetButtonDown("Jump") && isGrounded)
{
gameObject.GetComponent<Rigidbody2D>().AddForce(new Vector3(0f, 5f), ForceMode2D.Impulse);
}
}
}
Any help or information is really appreciated.
In
GetComponent<Collider2D>().tag == "Ground"
you are checking the tag of this GameObject's (child of Player) collider itself!
You probably rather wanted to check the tag of the thing you collided with.
Also avoid repeated GetComponent calls .. rather do it only once.
(Thanks #Jichael) You should also rather use CompareTag instead of using tag == "XY". It is more efficient and also actually checks if the given compare string exists as tag. If not an error is thrown while using == simply returns false which makes it hard to find evtl. typos.
// Would be better even to already reference this via Inspector
[SerializeField] private Move2D Player;
private void Awake()
{
if(!Player) Player = GetComponentInParent<Move2D>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Ground"))
{
Player.isGrounded = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Ground"))
{
Player.isGrounded = true;
}
}
The same also in Move2D
[SerializeField] private Rigidbody2D rigidbody;
private void Awake()
{
if(!rigidbody) rigidbody = GetComppnent<Rigidbody2D>();
}
void Jump()
{
// This is very small but it is slightly cheaper to check the
// isGrounded value so this order is minimal faster if isGrounded is false
if (isGrounded && Input.GetButtonDown("Jump"))
{
rigidbody.AddForce(new Vector3(0f, 5f), ForceMode2D.Impulse);
}
}
Also note: Whenever a Rigidbody is involved you should not control the position via the Transform component but rather use Rigidbody2D.MovePosition to keep the Physics intact!
This has to be done however in FixedUpdate so your code would become something like
private Vector3 movement;
void Update()
{
Jump();
movement = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
}
private void FixedUpdate ()
{
rigidbody.MovePosition(rigidbody.position += movement * Time.deltaTime * moveSpeed);
}
void Jump()
{
if (Input.GetButtonDown("Jump") && isGrounded)
{
rigidbody.AddForce(new Vector3(0f, 5f), ForceMode2D.Impulse);
}
}
Whether both objects require a Rigidbody or only the player depends on the ground objects (afaik):
ground objects are static &rightarrow; one (player) Rigidbody is enough
ground objects move &rightarrow; both need a rigidBody (the ground e.g. a kinematic)
Could you check both ball and ground has a rigidbody? which is required to trigger a trigger.
*Note: Trigger events are only sent if one of the Colliders also has a Rigidbody attached. *
Also could you change your code
private void OnTriggerEnter2D(Collider2D collision)
{
if (GetComponent<Collider2D>().tag == "Ground")
{
Player.GetComponent<Move2D>().isGrounded = true;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Ground")
{
Player.GetComponent<Move2D>().isGrounded = true;
}
}
Also I also recommend to use "layer" instead of using tag

My player dies touching any object with box collider

I want to do a game and I want my player to jump from an object to another and when it touches the ground to die. My player dies when he touch anything , how can I make him die just when it touches the ground? This is my code bellow
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move2d : MonoBehaviour
{
public float playerSpeed; //allows us to be able to change speed in Unity
public Vector2 jumpHeight;
public bool isDead = false;
private Rigidbody2D rb2d;
// Use this for initialization
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (isDead) { return; }
transform.Translate(playerSpeed * Time.deltaTime, 0f, 0f); //makes player run
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpHeight, ForceMode2D.Impulse);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
isDead = true;
rb2d.velocity = Vector2.zero;
GameController.Instance.Die();
}
}
You can set a tag to your ground gameobject.
Your new OnCollisionEnter2D would look like this.
private void OnCollisionEnter2D(Collision2D collision){
if (collision.gameObject.CompareTag("ground")) // this will return true if the collision gameobject has ground tag on it.
{
isDead = true;
rb2d.velocity = Vector2.zero;
GameController.Instance.Die();
}}
So in the method OnCollisionEnter2D(), whatever code is inside there will be triggered every time, regardless of what hit it. However, you can retrieve data about the collision to determine if it hit your ground. The best way to do this is using Unity's layer system.
First, you will want to create a layer (going to Project Settings > Tags and Layers. Be sure to remember which number was to the left of your layer's name) for all of your ground pieces and then should assign them to that layer. The when you collide with something, you can check if it is on that layer by using an if statement, like this.
private void OnCollisionEnter2D(Collision2D collision)
{
// Foo represents the number of the layer that the ground is assigned to.
if (collision.collider.gameObject.layer == foo)
{
isDead = true;
rb2d.velocity = Vector2.zero;
GameController.Instance.Die();
}
}

Detect collision between player and ground Unity3D

I'm still learning Unity and right now I'm trying to make my player able to jump. Of course I don't want my player to be able to jump on forever, so my idea was to only enable jumping when the player is in contact with a floor object. This is the code I have so far:
public class PlayerController : NetworkBehaviour
{
public float speed; // Player movement speed
private bool grounded = true; // Contact with floor
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Show a different color for local player to recognise its character
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.red;
}
// Detect collision with floor
void OnCollisionEnter(Collision hit)
{
if (hit.gameObject.tag == "Ground")
{
grounded = true;
}
}
// Detect collision exit with floor
void OnCollisionExit(Collision hit)
{
if (hit.gameObject.tag == "Ground")
{
grounded = false;
}
}
void FixedUpdate()
{
// Make sure only local player can control the character
if (!isLocalPlayer)
return;
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
// Detect space key press and allow jump if collision with ground is true
if (Input.GetKey("space") && grounded == true)
{
rb.AddForce(new Vector3(0, 1.0f, 0), ForceMode.Impulse);
}
}
}
But it seems OnCollisionEnter and OnCollisionExit never trigger. So the player is still able to jump whenever he wants. Am I doing something wrong?
Edit: It seems OnCollisionEnter and OnCollisionExit are triggered perfectly fine. It's just the if statements returning false. I have no idea why though.
if (GameObject.Find("Ground") != null) returned true.
Edit 2: Strangely enough both of these return Untagged:
Debug.Log(hit.gameObject.tag);
Debug.Log(hit.collider.tag);
Please give us more information
Please tell me which version of unity you are using?
Have you updated the project to some other latest version of unity?
Also give a screen shot of your 'tag' array.

Categories

Resources