This code will keep on jumping even though it is not on the ground how do you stop this (using Unity).
The Code:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
//Movement
public float speed;
public float jump;
float moveVelocity;
//Grounded Vars
bool grounded = true;
void Update ()
{
//Jumping
if (Input.GetKeyDown (KeyCode.Space) || Input.GetKeyDown (KeyCode.UpArrow) || Input.GetKeyDown (KeyCode.Z) || Input.GetKeyDown (KeyCode.W))
{
if(grounded)
{
GetComponent<Rigidbody2D> ().velocity = new Vector2 (GetComponent<Rigidbody2D> ().velocity.x, jump);
}
}
moveVelocity = 0;
//Left Right Movement
if (Input.GetKey (KeyCode.LeftArrow) || Input.GetKey (KeyCode.A))
{
moveVelocity = -speed;
}
if (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.D))
{
moveVelocity = speed;
}
GetComponent<Rigidbody2D> ().velocity = new Vector2 (moveVelocity, GetComponent<Rigidbody2D> ().velocity.y);
}
//Check if Grounded
void OnTriggerEnter2D()
{
grounded = true;
}
void OnTriggerExit2D()
{
grounded = false;
}
}
There are a couple of ways to achieve this but following your current implementation: why not set the isGrounded flag to false when you jump and just let the trigger handle resetting the flag when you land?
Some things you could check:
Are all your colliders 2D and set to be triggers?
Have you checked your layer collisions are actually happening?
public class PlayerController : MonoBehaviour
{
//Movement
public float speed;
public float jump;
float moveVelocity;
//Grounded Vars
bool isGrounded = true;
void Update ()
{
//Jumping
if (Input.GetKeyDown (KeyCode.Space) || Input.GetKeyDown (KeyCode.UpArrow) || Input.GetKeyDown (KeyCode.Z) || Input.GetKeyDown (KeyCode.W))
{
if(isGrounded)
{
GetComponent<Rigidbody2D> ().velocity = new Vector2 (GetComponent<Rigidbody2D> ().velocity.x, jump);
isGrounded = false;
}
}
moveVelocity = 0;
//Left Right Movement
if (Input.GetKey (KeyCode.LeftArrow) || Input.GetKey (KeyCode.A))
{
moveVelocity = -speed;
}
if (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.D))
{
moveVelocity = speed;
}
GetComponent<Rigidbody2D> ().velocity = new Vector2 (moveVelocity, GetComponent<Rigidbody2D> ().velocity.y);
}
//Check if Grounded
void OnTriggerEnter2D()
{
isGrounded = true;
}
}
Im pretty sure you need to have "" for the GetKeyDown in () but im not sure im pretty new at this, my username says it.
I know it's been 6 years, but I found a solution that worked for me.
//Movement
public float speed;
public float jump;
float moveVelocity;
public Rigidbody2D rb;
bool isGrounded;
void Update()
{
//Grounded?
if(isGrounded == true){
//jumping
if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Z) || Input.GetKeyDown(KeyCode.W))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, jump);
}
}
moveVelocity = 0;
//Left Right Movement
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
moveVelocity = -speed;
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
moveVelocity = speed;
}
GetComponent<Rigidbody2D>().velocity = new Vector2(moveVelocity, GetComponent<Rigidbody2D>().velocity.y);
}
void OnCollisionEnter2D(Collision2D col)
{
Debug.Log("OnCollisionEnter2D");
isGrounded = true;
}
void OnCollisionExit2D(Collision2D col)
{
Debug.Log("OnCollisionExit2D");
isGrounded = false;
}
}
Related
I can't jump when I press the up arrow key. When I remove the condition of isGrounded to be able to jump, then my character can jump while in the air.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float speed;
private Rigidbody2D body;
bool isGrounded;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
float HorizontalInput = Input.GetAxis("Horizontal");
body.velocity = new Vector3(Input.GetAxis("Horizontal") * speed, body.velocity.y);
if (HorizontalInput < -0.01f)
transform.localScale = Vector3.one;
else if (HorizontalInput > 0.01f)
transform.localScale = new Vector3(-1, 1, 1);
if (Input.GetKey(KeyCode.UpArrow))
isGrounded = false;
if (Input.GetKey(KeyCode.UpArrow) && isGrounded)
body.velocity = new Vector2(body.velocity.x, speed);
}
private void OnCollisionEnter2D()
{
isGrounded = true;
}
}
I tried to use OnCollisionEnter2D to set isGrounded to true, but I don't think it is working.
The problem is with this logic:
if (Input.GetKey(KeyCode.UpArrow))
isGrounded = false;
// isGrounded will always be false here if up-arrow key is pressed.
if (Input.GetKey(KeyCode.UpArrow) && isGrounded)
body.velocity = new Vector2(body.velocity.x, speed);
What you are looking for:
if (Input.GetKey(KeyCode.UpArrow) && isGrounded) {
body.velocity = new Vector2(body.velocity.x, speed);
isGrounded = false;
}
Use curly braces to denote multiple lines of code under a statement.
Also, use FixedUpdate for physics related manipulation like Rigidbodies.
I am new to programming and was wondering how I could make my "dash" make me move forward. I watched an online tutorial on how to make a dash work but after trying, the dash would only push me at all if I had written rb.velocity = Vector2.up * dashSpeed;. Currently, when I press the dash key, my character's gravity slows down for a second but no movement is made. Can I please get some help in making it push my character?
If you need clarification, please ask!
PS: Sorry for the long script, all my player control is in here.
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
//Player Movement
public float speed;
public float jumpForce;
public Transform feetPos;
public float checkRadius;
public LayerMask whatIsGround;
public float dashSpeed;
public float startDashTime;
public Animator animator;
private Rigidbody2D rb;
private float moveInput;
private bool isGrounded;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private float dashTime;
private int direction;
void Start()
{
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
}
void FixedUpdate()
{
moveInput = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
}
void Update()
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
// Dashing
if(direction == 0)
{
if(Input.GetKeyDown(KeyCode.LeftShift))
{
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
else
{
if(dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
}
else
{
dashTime -= Time.deltaTime;
}
}
}
void Dashleft()
{
rb.velocity = Vector2.left * dashSpeed;
}
void DashRight()
{
rb.velocity = Vector2.right * dashSpeed;
}
}
The problem is that your horizontal velocity is being controlled in FixedUpdate()
It is being overriden in every physics frame, so when you change velocity in DashLeft() or DashRight() methods, velocity is being reset in this line rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
You can do something like this:
if (dashTime <= 0)
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
So you control your velocity by Input only if player is not dashing
In my script, I have a patrol method and a chase method. My chase code using ray cast is not working properly. The only thing that works is my AI patrol code. When I hit a ray cast that I assign, it doesn't chase me. However, when I remove the patrol code in my script, my chase code works fine. What would be the problem? I want my AI to Patrol and Chase. If there is any collision and if the player is outside of the collision, the AI will start to patrol again
public class LineTrigger : MonoBehaviour {
private Transform targett;
public Transform sightStart, sightEnd;
public bool spotted = false;
public GameObject arrow;
public GameObject target;
public bool facingRight = false;
public float speed = 8;
[SerializeField]
float moveSpeed = 3f;
Rigidbody2D rb;
Vector3 localScale;
float dirX;
Vector3 directionToTarget;
void Start()
{
localScale = transform.localScale;
rb = GetComponent<Rigidbody2D> ();
dirX = -1f;
target = GameObject.Find ("Girl");
}
void Update()
{
if (transform.position.x < 1f)
dirX = 1f;
else if (transform.position.x > 20f)
dirX = -1f;
Raycasting ();
Behaviours ();
}
void Raycasting ()
{
Debug.DrawLine (sightStart.position, sightEnd.position);
spotted = Physics2D.Linecast (sightStart.position, sightEnd.position, 1 << LayerMask.NameToLayer ("Girl"));
}
void Behaviours()
{
if (spotted == true) {
arrow.SetActive (true);
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2 (directionToTarget.x * moveSpeed, directionToTarget.y * moveSpeed);
}
else
{
arrow.SetActive (false);
}
}
void FixedUpdate()
{
rb.velocity = new Vector2 (dirX * moveSpeed, rb.velocity.y);
}
void LateUpdate()
{
CheckWhereToFace ();
}
void CheckWhereToFace()
{
if (dirX > 0)
facingRight = false;
else if (dirX < 0)
facingRight = true;
if (((facingRight) && (localScale.x < 0)) || ((!facingRight) && (localScale.x > 0)))
localScale.x *= -1;
transform.localScale = localScale;
}
}
I think you are missing a if(!spotted) in your FixedUpdate
I want to allow the player to double-jump,but the player can keep jumping infinitely,can anyone help me? I use Unity 5
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour {
public float moveSpeed;
public float jumpHeight;
private bool grounded;
private Rigidbody2D rb;
private int jumpCount = 0;
private int maxJumps = 2;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.Space) && jumpCount < maxJumps) {
rb = GetComponent<Rigidbody2D> ();
rb.velocity = new Vector2 (rb.velocity.x, jumpHeight);
jumpCount = jumpCount + 1;
}
if (grounded == true) {
jumpCount = 0;
}
if (Input.GetKey (KeyCode.D)) {
rb.velocity = new Vector2 (moveSpeed,rb.velocity.y);
}
if (Input.GetKey (KeyCode.A)) {
rb.velocity = new Vector2 (-moveSpeed,rb.velocity.y);
}
}
void OnCollisionEnter2D (Collision2D collider){
if (collider.gameObject.tag == "Ground") {
grounded = true;
}
}
}
The reason you can keep jumping infinitely is because you never set grounded to false so it will always reset the value of your jumpCount back to 0 here
if (grounded == true) {
jumpCount = 0;
}
So when you jump set grounded = false because you're no longer on the ground.
if (Input.GetKeyDown (KeyCode.Space) && jumpCount < maxJumps) {
rb = GetComponent<Rigidbody2D> ();
rb.velocity = new Vector2 (rb.velocity.x, jumpHeight);
jumpCount = jumpCount + 1;
grounded = false;
}
And when working with RigidBody and physics it's better to use FixedUpdate
FixedUpdate should be used instead of Update when dealing with Rigidbody.
I have problem when making a 2d platformer game with Unity 5 about cannot perform double jump and just perform one jump for my playable character. Please check out what's wrong from my script below:
Player Movement.cs
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
public float forwardSpeed = 1f;
public float jumpHeight;
bool doJump = false;
bool canJumpAgain;
bool isGrounded;
float deathCooldown;
Animator animator;
Rigidbody2D myRigidbody;
void Awake () {
myRigidbody = GetComponent<Rigidbody2D> ();
}
// Use this for initialization
void Start () {
animator = transform.GetComponentInChildren<Animator>();
if(animator == null) {
Debug.LogError("Didn't find animator!");
}
}
// Update is called once per frame
void Update () {
isGrounded = true;
//for movement with infinite run to right
myRigidbody.AddForce( Vector2.right * forwardSpeed );
transform.rotation = Quaternion.Euler(0, 0, 0);
}
void OnCollisionStay2D (Collision2D col) {
if (col.gameObject.tag == "Ground") {
if (Input.GetKeyDown (KeyCode.Space) || Input.GetMouseButtonDown (0) && isGrounded && !doJump) {
myRigidbody.velocity = new Vector2 (GetComponent<Rigidbody2D>().velocity.x, jumpHeight);
animator.SetTrigger("DoJump");
isGrounded = false;
canJumpAgain = true;
doJump = true;
}
//perform double jump but failed
if (Input.GetKeyDown (KeyCode.Space) || Input.GetMouseButtonDown (0) && doJump && !isGrounded) {
myRigidbody.velocity = Vector2.zero;
myRigidbody.velocity = new Vector2 (GetComponent<Rigidbody2D>().velocity.x, jumpHeight);
animator.SetTrigger("DoJump");
Debug.Log ("yes");
canJumpAgain = true;
doJump = false;
}
if (canJumpAgain) {
//myRigidbody.velocity = Vector2.zero;
myRigidbody.AddForce(Vector2.up * jumpHeight);
animator.SetTrigger("DoJump");
Debug.Log ("yes1");
}
}
}
void OnCollisionExit2D (Collision2D col) {
if (col.gameObject.tag == "Ground") {
isGrounded = false;
GetComponent<CircleCollider2D>().isTrigger = false;
}
transform.parent = null;
}
void OnTriggerEnter2D(Collider2D Other)
{
}
}
I'm pretty sure this will fix the problem you're facing. Do not set isGrounded to true every Update() call. On the OnTriggerEnter2D() you wan't to have something like this: if (other.gameObject.tag == "ground") isGrounded = true; On the OnTriggerExit2D() you need to have this: if (other.gameObject.tag == "ground") isGrounded = false; Set the floor tag in the Unity inspector to ground. Explained: Before each double jump you're checking if isGrounded is false, however this will be always true since you're making it true every frame.
Finally I can resolved with my way please check out my script below:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
public float forwardSpeed = 1f;
public float jumpHeight;
bool doJump;
bool canJumpAgain;
bool isGrounded;
float deathCooldown;
Animator animator;
Rigidbody2D myRigidbody;
private bool canJump = false;
private int availableJumps = 1;
float jumpForce = 0f; // Force added when the player jumps.
public float firstJumpForce = 0f;
public float secondJumpForce = 0f;
void Awake () {
myRigidbody = GetComponent<Rigidbody2D> ();
}
// Use this for initialization
void Start () {
animator = transform.GetComponentInChildren<Animator>();
if(animator == null) {
Debug.LogError("Didn't find animator!");
}
}
// Update is called once per frame
void Update () {
isGrounded = true;
//for movement with infinite run to right
myRigidbody.AddForce( Vector2.right * forwardSpeed );
transform.rotation = Quaternion.Euler(0, 0, 0);
if (Input.GetKeyDown (KeyCode.Space) || Input.GetMouseButtonDown (0) && isGrounded) {
doJump = true;
}
}
void FixedUpdate () {
if(doJump && canJump)
{
// Add a vertical force to the player.
myRigidbody.velocity = new Vector2 (GetComponent<Rigidbody2D>().velocity.x, jumpHeight);
animator.SetTrigger("DoJump");
// Can the player jump again??
availableJumps--;
if (availableJumps <= 0){
canJump = false;
} else {
//I modify the second jump force
jumpForce = secondJumpForce;
}
doJump = false;
}
}
void OnCollisionStay2D (Collision2D col) {
if (col.gameObject.tag == "Ground") {
canJump = true;
availableJumps = 1;
jumpForce = firstJumpForce;
}
}
void OnCollisionExit2D (Collision2D col) {
if (col.gameObject.tag == "Ground") {
isGrounded = false;
GetComponent<CircleCollider2D>().isTrigger = false;
}
transform.parent = null;
}
void OnTriggerEnter2D(Collider2D Other)
{
}
}
I cannot remove "isGrounded = true;" on void update section because cannot perform first jump although already tried from TuukkaX's solution