Cannot make double jump - c#

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

Related

Unity2D Problem: Enemy does not shoot but it moves

I have a problem with an enemy on Unity2D.
The enemy should run to the player and if it's in the attackRange then it has to attack the enemy with a bullet, but the enemy follows my Player.
But there is a problem:
The enemy doesn't shoot with the bullet.
I changed the code, so when I press a button the enemy attacks too.
It worked only with the button.
Here's my code for the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class Enemy2 : MonoBehaviour
{
public Transform target;
public Transform firePoint;
public float speed = 200f;
public float nextWaypointDistance = 3f;
public float range = 10f; // the range at which the enemy will start moving towards the player
public float attackRange = 8f; // the range at which the enemy will attack the player
float distance;
public Transform enemyGFX;
private Transform player; // reference to the player's transform
public GameObject EnemyWeapon;
Path path;
int currentWaypoint = 0;
bool reachedEndOfPath = false;
Seeker seeker;
Rigidbody2D rb;
public Animator animator;
bool Stop = false;
public static float Enemy2Direction;
// Start is called before the first frame update
void Start()
{
seeker = GetComponent<Seeker>();
rb = GetComponent<Rigidbody2D>();
animator = GetComponentInChildren<Animator>();
player = GameObject.FindGameObjectWithTag("Player").transform;
InvokeRepeating("UpdatePath", 0f, .5f);
}
void UpdatePath()
{
if (seeker.IsDone())
{
seeker.StartPath(rb.position, target.position, OnPathComplete);
}
}
void OnPathComplete (Path p)
{
if (!p.error)
{
path = p;
currentWaypoint = 0;
}
}
// Update is called once per frame
void FixedUpdate()
{
if (Pause.IsPause == false)
{
if (path == null)
{
return;
}
if (currentWaypoint >= path.vectorPath.Count)
{
reachedEndOfPath = true;
return;
}
else
{
reachedEndOfPath = false;
}
Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] -rb.position).normalized;
Vector2 force = direction * speed * Time.deltaTime;
rb.AddForce(force);
float distance = Vector2.Distance(rb.position, path.vectorPath[currentWaypoint]);
if (distance < nextWaypointDistance)
{
currentWaypoint++;
}
//You can make look it differently, if you delete 'rb.velocity' and add 'force' instead.
if (rb.velocity.x >= 0.01f)
{
enemyGFX.transform.localScale = new Vector3(-1f, 1f, 1f);
Enemy2Direction = 1f;
}
else if (rb.velocity.x <= -0.01f)
{
enemyGFX.transform.localScale = new Vector3(1f, 1f, 1f);
Enemy2Direction = 0f;
}
if (distance < attackRange)
{
if (Stop = false)
{
StartCoroutine(Attack());
}
}
}
distance = Vector2.Distance(transform.position, player.position);
if (distance > range)
{
Destroy(gameObject);
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
animator.SetBool("Damage", true);
}
if (collision.gameObject.tag == "Bullet")
{
animator.SetBool("Damage", true);
}
}
void Update()
{
if (animator.GetBool("Damage"))
{
StartCoroutine(DamageAnimation());
}
if (Input.GetKeyDown(KeyCode.L))
{
StartCoroutine(Attack());
}
}
IEnumerator Attack()
{
Debug.Log("Attacked");
Stop = true;
yield return new WaitForSeconds(2.0f);
animator.SetBool("Attack", true);
Instantiate(EnemyWeapon, firePoint.position, firePoint.rotation);
yield return new WaitForSeconds(2.0f);
animator.SetBool("Attack", false);
StartCoroutine(Wait());
}
IEnumerator DamageAnimation()
{
yield return new WaitForSeconds(2.0f);
animator.SetBool("Damage", false);
}
IEnumerator Wait()
{
yield return new WaitForSeconds(2.0f);
Stop = false;
}
}
I don't know what's wrong with my code.
Can somebody please help me?
if(Stop == false)
Replace the = in when you check the Stop bool with ==, in C# you use == in order to check for equality
See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators for more detail.

Unity Tag and Collider problem while player is jumping

This is my player's jump code:
void Update()
{
float oldmoveHorizontal = moveHorizontal;
moveHorizontal = Joystick.Horizontal;
moveVertical = Joystick.Vertical;
if (isJumping == false && moveVertical >= .7f)
{
moveVertical = Speed * 70;
isJumping = true;
}
ball_move = new Vector2(moveHorizontal, moveVertical);
ball_rigid.AddForce(ball_move);
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "Ground")
{
isJumping = false;
}
}
}
When ball touches under of the collider it can jump again. How can i block this situation ?
if you cant download: https://ibb.co/yVgXmrM
One solution is to check the position of the collision points of the collision and see any of them is "low enough" from the center of your player to be a jumpable collision:
private Collider2D playerCollider;
private float playerJumpableOffset = 0.001;
void Start() { playerCollider = GetComponent<Collider2D>(); }
void OnCollisionEnter2D(Collision2D col)
{
float jumpableWorldHeight = transform.position.y - playerJumpableOffset;
for (int i = 0 ; i < col.contactCount && isJumping; i++)
{
Vector2 contactPoint = col.GetContact(i).point;
if (contactPoint.y <= jumpableWorldHeight)
{
isJumping = false;
}
}
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "Ground")
{
foreach (ContactPoint2D item in col.contacts)
{
Debug.Log("Normal:" + item.normal);
if (item.normal.y > 0 && col.gameObject.tag == "Ground")
{
isJumping = false;
Debug.Log("Top of Collider");
}
}
}}
I found my solution with checking top side of collider.
With this code way, if player touchs top side of collider, it's going to activate jump again.

Crouching issues in Unity

So I've created crouching in Unity 2D game, everything goes well except when there is something above the character after exiting crouching, what it does is that it returns to idle animation and decreases Y-axis position, I know that is normal but how can I keep the character crouched when there is something above him or when I hold the ctrl button? Check the script down below if necessary. Thanks!
private Rigidbody2D rb2d;
private float h = 0.0f;
public float Speed, Jump;
private bool canJump;
private Animator anim;
private BoxCollider2D bc2d;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
bc2d = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
transform.Translate(Vector3.right * h * Speed * Time.deltaTime);
if (h != 0.0f)
{
transform.localScale = new Vector2(h, transform.localScale.y);
}
if (Input.GetKeyDown(KeyCode.Space) && canJump == true)
{
rb2d.AddForce(new Vector2(rb2d.velocity.x, Jump));
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
bc2d.enabled = false;
Speed = Speed / 2;
anim.SetBool("Crouch", true);
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
bc2d.enabled = true;
Speed = Speed * 2;
anim.SetBool("Crouch", false);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = true;
anim.SetBool("Jump", false);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = false;
anim.SetBool("Jump", true);
}
}
Use RaycastHit2D. Basically before "standing" cast a ray Vector2.up from the character and if it hits, check to make sure there's enough room to stand. Something like:
private Rigidbody2D rb2d;
private Transform t;
private float h = 0.0f;
public float Speed, Jump;
private bool canJump;
private Animator anim;
private BoxCollider2D bc2d;
// Variable to check if character is attempting to stand
private bool tryingToStand = false;
// Keep crouching state
private bool isCrouching = false;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
bc2d = GetComponent<BoxCollider2D>();
t = GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
transform.Translate(Vector3.right * h * Speed * Time.deltaTime);
if (h != 0.0f)
{
transform.localScale = new Vector2(h, transform.localScale.y);
}
// Make sure we can jump and we're not crouching before jumping
if (Input.GetKeyDown(KeyCode.Space) && canJump == true && !isCrouching)
{
rb2d.AddForce(new Vector2(rb2d.velocity.x, Jump));
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
bc2d.enabled = false;
anim.SetBool("Crouch", true);
// Make sure we haven't already halved the speed
if (!tryingToStand)
{
Speed = Speed / 2;
}
// Set tryingToStand to false in case player holds ctrl before character has stood up
tryingToStand = false;
// Set crouching state to true
isCrouching = true;
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
tryingToStand = true;
}
if (tryingToStand && CanStand())
{
tryingToStand = false;
// Set crouching state to false;
isCrouching = false;
bc2d.enabled = true;
Speed = Speed * 2;
anim.SetBool("Crouch", false);
}
}
bool CanStand()
{
RaycastHit2D hit = Physics2D.Raycast(t.position, Vector2.up);
if (hit.collider != null)
{
// Check the distance to make sure the character has clearance, you'll have to change the 1.0f to what makes sense in your situation.
if (hit.distance <= 1.0f)
{
return false;
}
}
return true;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = true;
anim.SetBool("Jump", false);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = false;
anim.SetBool("Jump", true);
}
}

Making the player to double-jump

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.

C# 2D platformer movement code

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;
}
}

Categories

Resources