Having Errors w/ 2D Movement Script (C#)

Hey, everyone. It’s my first time posting to the Unity forums, so I’ll make this short and sweet: I would really like some help. I was working along on my script and encountered three issues. The first was that if I hit the “Jump” key quickly enough in succession I can infinitely jump. The second was to do with my Animator not telling me what variables were changing and when, and the final was that when I crouch my animation continues on a loop even if I let go of the crouch button (but this only occurs if I hold it down for more than a second). I have to tap the crouch key again to make the animation switch back to idle.

Script: (I apologize for it not being in proper forum format but I’m pressed for time)

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour
{
public float maxSpeed = 10f;
bool facingRight = true;

Animator anim;

public float jumpForce = 50f;
public float normalfall = 2f;
public float fastfall = 9f;
bool grounded;

void Start ()
{
anim = GetComponent();

this.rigidbody2D.gravityScale = normalfall;
}

void Update ()
{

}

void FixedUpdate ()
{
anim.SetFloat (“vSpeed”, rigidbody2D.velocity.y);

if (grounded = true)
{
if (Input.GetButton (“Vertical”))
anim.SetBool (“Crouch”, true);

if (Input.GetButtonUp (“Vertical”))
anim.SetBool (“Crouch”, false);
}
else
{
if (Input.GetButton (“Vertical”))
this.rigidbody2D.gravityScale = fastfall;

if (Input.GetButtonUp (“Vertical”))
this.rigidbody2D.gravityScale = normalfall;
}

float move = Input.GetAxis (“Horizontal”);

anim.SetFloat (“Speed”, Mathf.Abs (move));

rigidbody2D.velocity = new Vector2 (move * maxSpeed, rigidbody2D.velocity.y);

if (move > 0 && !facingRight)
Flip ();
else if (move < 0 && facingRight)
Flip ();

if (grounded && Input.GetButtonDown (“Jump”))
{
anim.SetBool (“grounded”, false);
rigidbody2D.AddForce(new Vector2(0, jumpForce));
}
grounded = false;

}

void OnCollisionStay ()
{
grounded = true;
}

void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}

If you have enough time to post on forums, you have enough time to take the literally two seconds it takes to format it. Using code tags properly - Unity Engine - Unity Discussions

–Eric

1 Like

Oh, I’m sorry-- I didn’t see that before. I was a bit busy preparing for the new year.

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour
{
    public float maxSpeed = 10f;
    bool facingRight = true;
   
    Animator anim;

    public float jumpForce = 50f;
    public float normalfall = 2f;
    public float fastfall = 9f;
    bool grounded;
   
    void Start ()
    {
        anim = GetComponent<Animator>();
       
        this.rigidbody2D.gravityScale = normalfall;
    }
   
    void  Update ()
    {   

    }
   
    void FixedUpdate ()
    {
        anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
       
        if (grounded = true)
        {
            if (Input.GetButton ("Vertical"))
            anim.SetBool ("Crouch", true);

            if (Input.GetButtonUp ("Vertical"))
                anim.SetBool ("Crouch", false);
        }
        else
        {
            if (Input.GetButton ("Vertical"))
            this.rigidbody2D.gravityScale = fastfall;

            if (Input.GetButtonUp ("Vertical"))
                this.rigidbody2D.gravityScale = normalfall;
        }
       
        float move = Input.GetAxis ("Horizontal");
       
        anim.SetFloat ("Speed", Mathf.Abs (move));
       
        rigidbody2D.velocity = new Vector2 (move * maxSpeed, rigidbody2D.velocity.y);
       
        if (move > 0 && !facingRight)
            Flip ();
        else if (move < 0 && facingRight)
            Flip ();

            if (grounded && Input.GetButtonDown ("Jump"))
        {
            anim.SetBool ("grounded", false);
            rigidbody2D.AddForce(new Vector2(0, jumpForce));
        }
        grounded = false;
       
    }
   
    void OnCollisionStay ()
    {
        grounded = true;
    }
   
    void Flip()
    {
        facingRight = !facingRight;
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
}

Can someone respond to this, please? All I got in over a week was a passive-aggressive moderator telling me to fix my post, which I was totally fine with… I can’t figure this out…

Also, the crouch thing was just a sticky keyboard.

if (grounded = true) will always return true, and will always make grounded = true. So you can keep jumping cause grounded always is true. Make it if (grounded) no need to do an == true.

In the jump conditional set grounded to false not needed to do every time you update.

Change

if (grounded && Input.GetButtonDown ("Jump"))
{
     anim.SetBool ("grounded", false);
     rigidbody2D.AddForce(new Vector2(0, jumpForce));
}
grounded = false;

to

if (grounded && Input.GetButtonDown ("Jump"))
{
     anim.SetBool ("grounded", false);
     rigidbody2D.AddForce(new Vector2(0, jumpForce));
     grounded = false;
}

Then you need to tell the animator that grounded is true in the OnCollisionStay().
Which needs to be a OnCollisionStay2D() to work with 2D colliders.

void OnCollisionStay2D ()
{
      grounded = true;
     anim.SetBool("grounded", true);
}

Hope that helps a bit.

Thanks for the help… even if it didn’t work! Maybe I’m just being stupid and missed something. I fixed the problem, actually. I did go back and try that but strangely it didn’t work at all. I do need help with one thing, though. My public bool grounded is always true unless I am on the ground and holding the jump button down. I’m trying to implement a fast-fall system for when airborne, but I can only crouch while in the air, rendering the whole line of code useless. Here’s my new script:

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour
{
    public float maxSpeed = 10f;
    bool facingRight = true;
   
    Animator anim;

    public float jumpForce = 50f;
    public float normalfall = 2f;
    public float fastfall = 9f;
    public bool grounded;
    public bool dead;

    void Start ()
    {
        anim = GetComponent<Animator>();
       
        this.rigidbody2D.gravityScale = normalfall;
    }
   
    void  Update ()
    {   

    }
   
    void FixedUpdate ()
    {
        anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);

        if (Input.GetButton ("Jump"))
        {
            grounded = false;
            anim.SetBool ("grounded", false);
        }
       
        if (grounded = true)
        {
            if (Input.GetButton ("Down"))
            anim.SetBool ("Crouch", true);

            if (Input.GetButtonUp ("Down"))
            anim.SetBool ("Crouch", false);
        }

        else if (grounded = false) //This does not work
        {
            if (Input.GetButton ("Down"))
            this.rigidbody2D.gravityScale = fastfall;

            if (Input.GetButtonUp ("Down"))
                this.rigidbody2D.gravityScale = normalfall;
        }
       
        float move = Input.GetAxis ("Horizontal");
       
        anim.SetFloat ("Speed", Mathf.Abs (move));
       
        if (move > 0 && !facingRight)
            Flip ();
        else if (move < 0 && facingRight)
            Flip ();

        rigidbody2D.velocity = new Vector2 (move * maxSpeed, rigidbody2D.velocity.y);
    }
   
    void OnCollisionStay2D ()
    {
        grounded = true;
        anim.SetBool ("grounded", true);

        if (grounded && Input.GetButtonDown ("Jump"))
        {
            rigidbody2D.AddForce(new Vector2(0, jumpForce));
        }
    }

    void OnTriggerEnter2D ()
    {
        dead = true;
        StartCoroutine(DieandRespawn());
    }

    IEnumerator DieandRespawn ()
    {
        yield return new WaitForSeconds(2);
        dead = false;
    }
   
    void Flip()
    {
        facingRight = !facingRight;
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
}

You didn’t change your if statements.

Your conditional will make grounded = true ALL the time.
You need to use == or nothing at all.

if (grounded)
{
     //This will trigger only if grounded is true.
}
else
{
     //This will trigger only if grounded is false.
}


if (grounded = true)
{
     //This will trigger every time and make grounded = true.
}
else if (grounded = false)
{
     //This will never trigger, as the first part of the conditional always is true.
}

Change it to this:

if (grounded)//same as if (grounded == true)
{
     if (Input.GetButton ("Down"))
          anim.SetBool ("Crouch", true);
    if (Input.GetButtonUp ("Down"))
         anim.SetBool ("Crouch", false);
}
else
{
     if (Input.GetButton ("Down"))
            this.rigidbody2D.gravityScale = fastfall;
     if (Input.GetButtonUp ("Down"))
            this.rigidbody2D.gravityScale = normalfall;
}

Jeez… I really have no idea how I missed that! Thanks!