Help with player grounding issue??

Fairly new to Unity and C# scripting, but I understand the majority of the logic. Trying to build a 2D platformer while I learn, but I can’t for the life of me figure out why my bool “grounded” is so unpredictable… In general, if my character is facing right (default), grounded = true as it should. Though when I move left and Flip() executes, grounded = false. Also at certain spot on my terrain, the opposite happens. Any insight?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharController2d : MonoBehaviour {
    [HideInInspector] public bool facingRight = true;
    [HideInInspector] public bool jump = false;
    [HideInInspector] public bool grounded;
    private Vector3 m_Velocity = Vector3.zero;

    // public float moveForce = 365f;
    // public float maxSpeed = 5f;
    public float runSpeed = 40f;
    public float jumpForce = 1000f;
    [Range(0, .1f)] public float movementSmoothing = .05f;
    public Transform groundCheck;

   
    private Animator anim;
    private Rigidbody2D rb2d;

    // Use this for initialization
    void Start () {
        anim = GetComponent<Animator>();
        rb2d = GetComponent<Rigidbody2D>();

    }
   
    // Update is called once per frame
    void Update () {
        grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
        Debug.Log(grounded);

        if (!grounded)
            anim.SetBool("grounded", false);
        else if (grounded)
            anim.SetBool("grounded", true);
       

        if (Input.GetButtonDown("Jump") && grounded)
        {
            jump = true;
        }

    }

    void FixedUpdate()
    {   
        float h = Input.GetAxisRaw("Horizontal") * runSpeed;
        anim.SetFloat("speed", Mathf.Abs(h));
        // Move the character by finding the target velocity
        Vector3 targetVelocity = new Vector2(h * Time.fixedDeltaTime * 10f, rb2d.velocity.y);
        // And then smoothing it out and applying it to the character
        rb2d.velocity = Vector3.SmoothDamp(rb2d.velocity, targetVelocity, ref m_Velocity, movementSmoothing);
       
        if (h > 0 && !facingRight)
            Flip();
        else if (h < 0 && facingRight)
            Flip();

        if (jump)
        {
            rb2d.AddForce(new Vector2(0f, jumpForce));
            jump = false;
        }
    }

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

One way to get a better handle on this is to temporarily disable your game’s physics and controls and replace them with direct mouse control.

In this example above, just set the Rigidbody2D to ignore gravity:

rb2d.gravityScale = 0.0f;

Now each frame take your Input.mousePosition and raycast into the scene (use the camera to get a ray) to find out world coordinates for that mouse position.

At line 32 take that world coordinate and assign it to your player.

This way you can drag your player around pixel by pixel and try to figure out what is going on, complete with watching the “isGrounded” spewing out of your Debug.Log().

Two more observations: I assume groundCheck is a child object and is always offset downwards? Is it far enough into the ground to detect the player? Is the player’s position up enough that you’re sure it’s not partially in the ground?

It was indeed the position of groundCheck, it was .005 too high; the player’s collider was interfering when !facingRight

1 Like