I am making my first Game and now I have a problem: I have a jump button when i press it I am jumping but when I am in the air I can press it again and jump in the air again. How can fix that, so I can jump only on the ground. Here is my Code:
using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class Move2D : MonoBehaviour
{
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
public void Jump()
{
rigidBody.AddForce(transform.up * jumpSpeed, ForceMode2D.Impulse);
}
// Update is called once per frame
}
Here is the Code
public class Move2D : MonoBehaviour
{
public bool isGrounded = false;
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "Ground") //you need to add a tag to your Ground, like "Ground"
{
isGrounded = true;
}
}
public void Jump()
{
rigidBody.AddForce(transform.up * jumpSpeed, ForceMode2D.Impulse);
isGrounded = false;
}
void Update()
{
if (Input.GetButtonDown("Jump") && isGrounded == true)
{
isGrounded = false;
Jump();
}
}
}
first of all you need a boolean (isGrounded). Then you have to check the collision between the player and the ground with
private void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "Ground") //you need to add a tag to your Ground, like "Ground"
{
isGrounded = true;
}
}
And then in the Update method add this code:
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
isGrounded = false;
Jump();
}
Related
so I started unity literally yesterday meaning this is my second day. I followed a tutorial to make a movement script, but when I continuously press space, I can jump like infinitely. This is my code below, is there any way to fix the infinite jump to just two jumps and then it resets when it hits the ground?
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float speed;
private Rigidbody2D body;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
body.velocity = new Vector2(Input.GetAxis("Horizontal") * speed, body.velocity.y);
if (Input.GetKey(KeyCode.Space))
body.velocity = new Vector2(body.velocity.x, speed);
}
}
You can prevent this by adding time delay
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
[SerializeField] private float speed;
[SerializeField] private float jumpTimeDelay = 0.5f; // feel free to increase or decrease
private const float timeDelayConst = jumpTimeDelay;
private bool isGrounded = false;
private Rigidbody2D body;
private void Awake() {
body = GetComponent<Rigidbody2D>();
}
private void Update(){
body.velocity = new Vector2(Input.GetAxis("Horizontal") * speed,
body.velocity.y);
isGrounded = jumpTimeDelay <= 0;
jumpTimeDelay -= Time.time;
if (Input.GetKey(KeyCode.Space) && isGrounded){
body.velocity = new Vector2(body.velocity.x, speed);
jumpTimeDelay = timeDelayConst;
}
}
}
This is easily done by adding a boolean value to check if the player is grounded or not and change the value when player jumps. You also need to add a tag to your ground object so we can check if the player is touching the ground. To add tags to objects please refer to Unity - Manual: https://docs.unity3d.com/530/Documentation/Manual/Tags.html
Just for future these kind of questions are asked a lot so you can pretty much google your question and find similar answers.
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float speed;
private Rigidbody2D body;
private bool isGrounded = true;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
body.velocity = new Vector2(Input.GetAxis("Horizontal") * speed, body.velocity.y);
if(Input.GetKey(KeyCode.Space))
{
if (isGrounded)
{
isGrounded = false;
body.velocity = new Vector2(body.velocity.x, speed);
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground") {
isGrounded = true;
}
}
}
I have both player and ground with colliders 2D and player is supposed to stop on top of ground but instead it stops at the bottom of the ground.
Code
PlayerController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
private float moveSpeedStore;
public float speedMultiplier;
public float speedIncreateMilestone;
private float speedIncreateMilestoneStore;
private float speedMilestoneCount;
private float speedMilestoneCountStore;
public float jumpForce;
public float jumpTime;
private float jumpTimeCounter;
private bool stoppedJumping;
private bool canDoubleJump;
private Rigidbody2D myRigidbody;
public bool grounded;
public LayerMask whatIsGround;
public Transform groundCheck;
public float groundCheckRadius;
// private Collider2D myCollider;
private Animator myAnimator;
public GameManager theGameManager;
public AudioSource jumpSound;
public AudioSource deathSound;
// Start is called before the first frame update
void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
myAnimator = GetComponent<Animator>();
jumpTimeCounter = jumpTime;
speedMilestoneCount = speedIncreateMilestone;
moveSpeedStore = moveSpeed;
speedMilestoneCountStore = speedMilestoneCount;
speedIncreateMilestoneStore = speedIncreateMilestone;
stoppedJumping = true;
}
// Update is called once per frame
void Update()
{
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
if(transform.position.x > speedMilestoneCount)
{
speedMilestoneCount += speedIncreateMilestone;
speedIncreateMilestone = speedIncreateMilestone * speedMultiplier;
moveSpeed = moveSpeed * speedMultiplier;
}
myRigidbody.velocity = new Vector2(moveSpeed, myRigidbody.velocity.y);
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0) )
{
if(grounded)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
stoppedJumping = false;
jumpSound.Play();
}
if(!grounded && canDoubleJump)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
jumpTimeCounter = jumpTime;
stoppedJumping = false;
canDoubleJump = false;
jumpSound.Play();
}
}
if((Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0)) && !stoppedJumping)
{
if(jumpTimeCounter > 0)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
jumpTimeCounter -= Time.deltaTime;
}
}
if(Input.GetKeyUp(KeyCode.Space) || Input.GetMouseButtonUp(0))
{
jumpTimeCounter = 0;
stoppedJumping = true;
}
if(grounded)
{
jumpTimeCounter = jumpTime;
canDoubleJump = true;
}
myAnimator.SetFloat("Speed", myRigidbody.velocity.x);
myAnimator.SetBool("Grounded", grounded);
}
void OnCollisionEnter2D(Collision2D other) {
if(other.gameObject.tag == "killbox")
{
theGameManager.RestartGame();
moveSpeed = moveSpeedStore;
speedMilestoneCount = speedMilestoneCountStore;
speedIncreateMilestone = speedIncreateMilestoneStore;
deathSound.Play();
}
}
}
Player settings
Question
What should I do to hold my player on top of ground?
NOTE: it's my first question on unity ever so if you need any sort of code or data please just ask, I try my best to provide you what you need.
Thanks.
It looks like your collider is simply too high. You'll notice that the green box indicating your collider size and position is colliding with the correct spot on the ground. The bottom of it is just touching the top of the ground. You simply need to move the collider down on the player so that the bottom of the green box is at the bottom of the player's sprite.
I am making a simple 2D game in Unity, and I'm trying to make it so my character can only jump if it's touching the ground. Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float movementSpeed = 5.0f;
[SerializeField] private bool isGrounded = false;
private Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
move();
jump();
}
private void move()
{
float move = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(movementSpeed * move * Time.deltaTime, rb.velocity.y);
}
private void jump()
{
if(Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
Debug.Log("jump");
}
}
void OnCollisionStay2D(Collision2D, col)
{
if(col.gameObject.tag == "Ground")
{
isGrounded = true;
}
}
void OnCollisionExit2D(Collision2D, col)
{
if(col.gameObject.tag == "Ground")
{
isGrounded = false;
}
}
}
When I run this, it gives me this error: "PlayerMovement.cs(45,44): error CS1001: Identifier expected"
I have tried using Collider2D instead of Collision2D in the OnCollisionStay, but that won't work either. Thanks in advance for the help!
(Collision2D, col) change to (Collision2D col)
void OnCollisionStay2D(Collision2D col)
{
if(col.gameObject.tag == "Ground")
{
isGrounded = true;
}
}
void OnCollisionExit2D(Collision2D col)
{
if(col.gameObject.tag == "Ground")
{
isGrounded = false;
}
}
I just started using Unity am trying to make a simple 3D platformer, before I can get to that, I need to get movement down. My problem comes in when the player jumps. When they jump, they can jump in the air as much as they want. I want it to only jump once. Can anybody help?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Playermovement : MonoBehaviour
{
public Rigidbody rb;
void Start ()
}
void Update()
{
bool player_jump = Input.GetButtonDown("DefaultJump");
if (player_jump)
{
rb.AddForce(Vector3.up * 365f);
}
}
}
}
You can use a flag to detect when the player is touching the ground then only jump the player is touching the floor. This can be set to true and false in the OnCollisionEnter and OnCollisionExit functions.
Create a tag named "Ground" and make the GameObjects use this tag then attach the modified code below to the player that is doing the jumping.
private Rigidbody rb;
bool isGrounded = true;
public float jumpForce = 20f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
bool player_jump = Input.GetButtonDown("DefaultJump");
if (player_jump && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce);
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
}
}
Sometimes, using OnCollisionEnter and OnCollisionExit may not be fast enough. This is rare but possible. If you run into this then use Raycast with Physics.Raycast to detect the floor. Make sure to throw the ray to the "Ground" layer only.
private Rigidbody rb;
public float jumpForce = 20f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
bool player_jump = Input.GetButtonDown("DefaultJump");
if (player_jump && IsGrounded())
{
rb.AddForce(Vector3.up * jumpForce);
}
}
bool IsGrounded()
{
RaycastHit hit;
float raycastDistance = 10;
//Raycast to to the floor objects only
int mask = 1 << LayerMask.NameToLayer("Ground");
//Raycast downwards
if (Physics.Raycast(transform.position, Vector3.down, out hit,
raycastDistance, mask))
{
return true;
}
return false;
}
We are at very beginning of studying Unity, so we decided to create a mini-platformer. We've already made coins, platforms and character animation, but when we tried to animate a platform, a huge catastrophe appeared. The problem is that character can't stand on the platform. When the platform moves, he falls (it looks like there's no friction, but we tried to set one - it was helpless).
Maybe, we repeat the question, that have been asked before, but hope you'll help us to solve this paradox. Have a nice day ;)
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class CharControl : MonoBehaviour
{
public float maxSpeed = 10f;
private bool isFacingRight = true;
private Animator anim;
private bool isGrounded = false;
public Transform groundCheck;
private float groundRadius = 0.2f;
public LayerMask whatIsGround;
public Text scoreText;
public float score = 0;
private void Start()
{
anim = GetComponent<Animator>();
}
private void FixedUpdate()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
anim.SetBool ("Ground", isGrounded);
anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
if (isGrounded && rigidbody2D.velocity.y != 0)
return;
float move = Input.GetAxis("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(move));
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
if(move > 0 && !isFacingRight)
Flip();
else if (move < 0 && isFacingRight)
Flip();
}
private void Update()
{
if (isGrounded && (Input.GetKeyDown (KeyCode.Space) || Input.GetKeyDown(KeyCode.Joystick1Button0)))
{
anim.SetBool("Ground", false);
rigidbody2D.AddForce(new Vector2(0, 600));
}
}
private void Flip()
{
isFacingRight = !isFacingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void OnTriggerEnter2D(Collider2D col){
if(col.gameObject.name == "Skull"){
score++;
Destroy (col.gameObject);
scoreText.text = "" + score;
}
if ((col.gameObject.name == "dead"))
Application.LoadLevel (Application.loadedLevel);
}}
you need to set MovingPlatform is ParentObject of HoldPlayerPlatform.
check below images for that also
Here is Holding Player Script on Moving Platform.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HoldPlayer : MonoBehaviour
{
private GameObject target = null;
private Vector3 offset;
void Start()
{
target = null;
}
void OnTriggerStay(Collider col)
{
target = col.gameObject;
offset = target.transform.position - transform.position;
}
void OnTriggerExit(Collider col)
{
target = null;
}
void LateUpdate()
{
if (target != null)
{
target.transform.position = transform.position + offset;
}
}
}
Here is image for setup HoldPlayerPlatform
Here is Setup for MovingPlatform