Last active
April 29, 2021 08:26
-
-
Save LiamPerson/ed28083c7a649b302d30f5ff1520d49c to your computer and use it in GitHub Desktop.
Physics-compliant 2D Platformer Movement in Unity using Rigidbody2D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[RequireComponent(typeof(Rigidbody2D))] | |
public class Movement : MonoBehaviour | |
{ | |
// Rigidbody contained on the object this script is attached to. | |
private Rigidbody2D rb; | |
// Player size and ground detection for jumping. | |
public Vector2 PlayerSize = new Vector2(1f, 1f); | |
public float GroundDetectionLength = 0.1f; | |
// Movement settings. | |
public float Acceleration = 2; | |
public float MaxSpeed = 8; | |
public float GroundFriction = 1; | |
public float JumpHeight = 3f; | |
// Transfers jump button to fixedUpdate. | |
private bool JumpPressed = false; | |
void Start() | |
{ | |
// Get the rigidbody. | |
rb = GetComponent<Rigidbody2D>(); | |
} | |
void Update() | |
{ | |
// If jump button is pressed, set jump pressed to true. | |
if (Input.GetButtonDown("Jump")) | |
JumpPressed = true; | |
} | |
void FixedUpdate() | |
{ | |
// Scale acceleration by target velocity and clamp it between 0 and Accelleration. | |
float scaledAcceleration = Acceleration * (1 - Mathf.Abs(rb.velocity.x) / MaxSpeed); | |
// Simulate friction. | |
if (rb.velocity.x > 0) | |
rb.velocity = new Vector2(rb.velocity.x - Mathf.Min(GroundFriction, rb.velocity.x), rb.velocity.y); // Velocity is positive. | |
else if (rb.velocity.x < 0) | |
rb.velocity = new Vector2(rb.velocity.x - Mathf.Max(-GroundFriction, rb.velocity.x), rb.velocity.y); // Velocity is negative. | |
// Add scaled acceleration to velocity in the direction of the horizontal axis. | |
rb.velocity += new Vector2(scaledAcceleration * Input.GetAxis("Horizontal"), 0); | |
// Simulate jumping. | |
if(JumpPressed && CheckIsGrounded()) | |
{ | |
JumpPressed = false; | |
rb.AddForce(Vector2.up * JumpHeight); | |
} | |
} | |
/// <summary> | |
/// Checks if this object is grounded based on defined PlayerSize field. | |
/// </summary> | |
bool CheckIsGrounded() | |
{ | |
// Check what is below us. | |
RaycastHit2D[] collisions = Physics2D.BoxCastAll(rb.position, PlayerSize, rb.rotation, transform.TransformDirection(Vector2.down), GroundDetectionLength); | |
// Check if any of the collided objects are solid. | |
foreach(RaycastHit2D hit in collisions) | |
{ | |
// Get the collider and check if its solid and not the current game object. | |
if (!hit.collider.isTrigger && hit.collider.gameObject != gameObject) | |
return true; | |
} | |
// If nothing was a trigger, return false. | |
return false; | |
} | |
/// <summary> | |
/// Draws the character PlayerSize box and the ground detection box. | |
/// </summary> | |
private void OnDrawGizmosSelected() | |
{ | |
// Change drawing matrix to local space. | |
Gizmos.matrix = transform.localToWorldMatrix; | |
// Draw the character shape. | |
Gizmos.color = new Color(.68f, .04f, .37f); // Purple | |
Gizmos.DrawWireCube(Vector2.zero, PlayerSize); | |
// Draw the ground detection length. | |
Gizmos.color = new Color(1f, .74f, 0f); // Orange | |
Gizmos.DrawWireCube(Vector2.zero - new Vector2(0, PlayerSize.y / 2 + GroundDetectionLength / 2), new Vector2(PlayerSize.x, GroundDetectionLength)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment