How to make 2D sprite character stop jittering when running into walls?

Hi, I am just getting started with unity and game development. I decided to start working with platformer game first as those seem simple enough. However, I have run into a very simple problem I cannot figure out how to fix.

When my character (who is a sprite with a rigidbody2D and a box collider) runs into any other object with a box collider (walls, boxes, etc.) it will basically jitter. It is the sprite continually trying to force its way into the collider and sometimes it will actually get stuck within the wall’s collider. It isn’t the camera because when the camera is still the sprite will still jitter, but it is amplified when my camera follow script is on (because it shakes with the sprite). Any ideas on a quick simple fix?

I’ll post my player controller script down below (warning: it isn’t optimized and I had to do a crude fix to work with the flipping of my sprite sheets cause they weren’t the right directions before you critique that).

using UnityEngine;
using System.Collections;

public class PlayerCharacter : MonoBehaviour {

	//[HideInInspector]
	public bool facingRight = true;
	//[HideInInspector]
	public bool jump = false;
	//[HideInInspector]
	public bool grounded = false;

	public float jumpForce = 10.0f;
	public float moveSpeed = 20.0f;			// Movement speed of the player
	
	private Transform groundCheck;			// A position marking where to check if the player is grounded.
	private Animator anim;					// Reference to the player's animator component.
	private SpriteRenderer srend;
	private bool jumped = false;
	private bool air = false;
	
	void Awake()
	{
		// Setting up references.

		groundCheck = transform.Find("groundCheck");
		anim = GetComponent<Animator>();
		srend = GetComponent<SpriteRenderer> ();
	}

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update()
	{

		float h = Input.GetAxis ("Horizontal");

		transform.Translate (h * moveSpeed * Time.deltaTime,0,0);

		// The player is grounded if a linecast to the groundcheck position hits anything on the ground layer.
		grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));  
		
		// If the jump button is pressed and the player is grounded then the player should jump.
		if(Input.GetButtonDown("Jump") && grounded)
			jump = true;
	
		// If the player should jump...
		if(jump)
		{

			Vector3 Rotation = srend.transform.localScale;
			Rotation.x *= -1;
			transform.localScale = Rotation;
			srend.transform.localScale = Rotation;
			Debug.Log("I Rotated you sky");

			// Add a vertical force to the player.
			rigidbody2D.AddForce(new Vector2(0f, jumpForce));
			
			// Make sure the player can't jump again until the jump conditions from Update are satisfied.
			jump = false;
			jumped = true;
		}
		// If the input is moving the player right and the player is facing left...
		if(h < 0 && !facingRight)
			// ... flip the player.
			Flip();
		// Otherwise if the input is moving the player left and the player is facing right...
		else if(h > 0 && facingRight)
			// ... flip the player.
			Flip();

		if (h != 0 && !jump)
			anim.SetBool ("Move", true);
		else
			anim.SetBool ("Move", false);


		if (!grounded)
		{
			anim.SetBool("InAir", true);
			if(jumped)
				air = true;
		}
		else
		{
			anim.SetBool("InAir",false);

			if (air)
			{
				Vector3 Rotation = srend.transform.localScale;
				Rotation.x *= -1;
				transform.localScale = Rotation;
				srend.transform.localScale = Rotation;
				Debug.Log("I Rotated you land");
				jumped = false;
				air = false;
			}

		}
	}


	void Flip ()
	{
		// Switch the way the player is labelled as facing.
		facingRight = !facingRight;
		
		// Multiply the player's x local scale by -1.
		Vector3 theScale = transform.localScale;
		theScale.x *= -1;
		transform.localScale = theScale;
	}

}

Also as a side note, I wasn’t sure how to post line numbers with my code, so sorry about that. Thanks in advance!

Problem is using transform.translate with a rigidbody attached.

Essentially transform.translate ignores physics and moves your object directly. When you get to a collider your object gets moved one step further during update so it overlaps the obstacle. Then physics has its turn and moves your object back slightly so the colliders don’t overlap. Update runs again and moves it forward. Hence the jittering.

To fix you can

  • Use RigidBody.AddForce to move the object. This give the most accurate simulation. However the inherent lag in acceleration and deceleration makes it a poor choice for player control (unless you are driving a space ship)
  • Use RigidBody.Velocity This gives less accurate physics simulation but more accurate player control.

In both cases you should get your inputs in Update but apply the changes in FixedUpdate.

If someone see this today the most likely problem is the camera (not the script).
Just add an Cinemachine (there are 100+ tutorials out there how to) and set Main Camera → Cinemachine Brain → Update Method to “Smart Update”.