Action, Magic - March 08, 2020

2D Character Controller for Unity

2D Character Controller for Unity

2D Platformer is a type of game where the player jumps between platforms, avoids obstacles, and fights enemies, all of which is observed from a 2D side-view perspective.

Sharp Coder Video Player

To make a 2D Platformer Character Controller in Unity, follow the steps below.

The controller will be physics-based and will use a Rigidbody2D component.

Steps

  • Open Scene with your 2D level (make sure the level sprites have 2D colliders attached, so the player won't fall through)
  • Create a new GameObject and call it "Player"
  • Create another GameObject, call it "player_sprite" and add the Sprite Renderer component to it
  • Assign your sprite to "player_sprite" and move it inside the "Player" Object

Create a new script, name it "CharacterController2D" and paste the code below inside it:

using System.Collections; using System.Collections.Generic; using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] [RequireComponent(typeof(CapsuleCollider2D))] public class CharacterController2D : MonoBehaviour { public float maxSpeed = 3.4f; public float jumpHeight = 6.5f; public float gravityScale = 1.5f; public Camera mainCamera; bool facingRight = true; float moveDirection = 0; bool isGrounded = false; Vector3 cameraPos; Rigidbody2D r2d; CapsuleCollider2D mainCollider; Transform t; void Start() { t = transform; r2d = GetComponent(); mainCollider = GetComponent(); r2d.freezeRotation = true; r2d.collisionDetectionMode = CollisionDetectionMode2D.Continuous; r2d.gravityScale = gravityScale; facingRight = t.localScale.x > 0; if (mainCamera) { cameraPos = mainCamera.transform.position; } } void Update() { if ((Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) && (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f)) { moveDirection = Input.GetKey(KeyCode.A) ? -1 : 1; } else { if (isGrounded || r2d.velocity.magnitude < 0.01f) { moveDirection = 0; } } if (moveDirection != 0) { if (moveDirection > 0 && !facingRight) { facingRight = true; t.localScale = new Vector3(Mathf.Abs(t.localScale.x), t.localScale.y, transform.localScale.z); } if (moveDirection < 0 && facingRight) { facingRight = false; t.localScale = new Vector3(-Mathf.Abs(t.localScale.x), t.localScale.y, t.localScale.z); } } if (Input.GetKeyDown(KeyCode.W) && isGrounded) { r2d.velocity = new Vector2(r2d.velocity.x, jumpHeight); } if (mainCamera) { mainCamera.transform.position = new Vector3(t.position.x, cameraPos.y, cameraPos.z); } } void FixedUpdate() { Bounds colliderBounds = mainCollider.bounds; float colliderRadius = mainCollider.size.x * 0.4f * Mathf.Abs(transform.localScale.x); Vector3 groundCheckPos = colliderBounds.min + new Vector3(colliderBounds.size.x * 0.5f, colliderRadius * 0.9f, 0); Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckPos, colliderRadius); isGrounded = false; if (colliders.Length > 0) { for (int i = 0; i < colliders.Length; i++) { if (colliders[i] != mainCollider) { isGrounded = true; break; } } } r2d.velocity = new Vector2((moveDirection) * maxSpeed, r2d.velocity.y); Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(0, colliderRadius, 0), isGrounded ? Color.green : Color.red); Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(colliderRadius, 0, 0), isGrounded ? Color.green : Color.red); } }

Attach the CharacterController2D script to the "Player" Object (You'll notice it also added other components called Rigidbody2D and CapsuleCollider2D)

Tweak CapsuleCollider2D dimensions until they match the player Sprite

Make sure there are no child colliders and the CapsuleCollider2D is the only collider attached to this player

In the CharacterController2D script there's an option to assign the Main Camera variable which can be any Camera that'll follow the player:

The 2D Character Controller is now ready!