0
votes

I recently started using Unity2D and put together a simple character controller with a rigidbody and colliders. The way it is set up now is a circle collider for the feet and a box collider for the rest of the body. The reason I did this is a box collider on the feet causes the character to sometimes get stuck moving across tiles. The problem I am trying to fix happens when the character is pressed against a wall. While moving horizontally into a wall gravity and jumping seem to have no affect. He gets stuck in the wall. I believe it has something to do with friction because when I set the block material to 0 friction he no longer has this problem. However, when I do this he becomes slippery enough to slide off the edge of blocks because of the circle collider on his feet. Any suggestions/fixes would be much appreciated.

public class SpriteController : MonoBehaviour {

    public float maxSpeed = 2f;
    bool facingRight = true;

    Animator anim;

    bool grounded = false;
    bool swimming = false;
    public Transform groundCheck;
    float groundRadius = 0.05f;
    public LayerMask whatIsGround;
    public float jumpForce = 700f;
    public float swimForce = 10f;
    public PhysicsMaterial2D myMaterial;

    void Start () 
    {
        anim = GetComponent<Animator> ();
    }

    void FixedUpdate () 
    {
        grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround);
        anim.SetBool ("Ground", grounded);

        anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);


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

    void Update()
    {
        Spin();
        if (grounded && Input.GetKeyDown (KeyCode.Space)) 
        {
            anim.SetBool ("Ground", false);
            rigidbody2D.AddForce(new Vector2(0, jumpForce));
        }
        else if(swimming && Input.GetKey (KeyCode.Space)) rigidbody2D.AddForce(new Vector2(0, swimForce));
    }
    void Spin()
    {
        if(Input.GetKeyDown ("f")) anim.SetBool("Spin", true);
        if(Input.GetKeyUp ("f")) anim.SetBool("Spin", false);
    }
    void Flip()
    {
        facingRight = !facingRight;
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
    void OnTriggerEnter2D(Collider2D collider)
    {
        if (collider.gameObject.tag == "Water") {
            rigidbody2D.drag = 15;
            swimming = true;
            grounded = false;
        }
    }
    void OnTriggerExit2D(Collider2D collider)
    {
        if (collider.gameObject.tag == "Water"){
            rigidbody2D.drag = 0;
            swimming = false;
        }
    }
}
2
From the character controller unity doc. I remember it note that the character skin depth also plays in getting stuck. Check the doc.VicM
The sprite uses a 2d sprite sheet so I don't see how skin depth would be a problem. However I may be misinterpreting your comment.user1569940

2 Answers

0
votes

Friction being set to 0 should be fine. How far away from the edge of the block does the character start to slip? You could try shrinking the size of the circle collider relative to the character (particularly width). If all your other physics work OK it might be something to do with the positioning or size of the circle collider.

0
votes

Here, my fix which works quite well for me. I've just checked whether the player is colliding with something which is not the ground. In this particular case, I disable the Player (user input) movement :

void FixedUpdate () 
{
    grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround);
    anim.SetBool ("Ground", grounded);

    anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);

    // -- JUST ADD THIS --
    if (!grounded && rigidbody2D.IsTouchingLayers ()) {
        return;
    }
    // -- END --

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