Created
February 12, 2018 00:24
-
-
Save walterpalladino/3bd8cdfc282c1236ac94cc032b413514 to your computer and use it in GitHub Desktop.
Unity Retro 2D Platform Platform Controller
This file contains 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; | |
public class RetroPhysicsObject : MonoBehaviour { | |
// Boundary control | |
[System.Serializable] | |
public class BoundaryControl | |
{ | |
public bool checkBoundaries = false; | |
public float boundaryLeft = 0; | |
public float boundaryRight = 1; | |
public float boundaryTop = 0; | |
public float boundaryBottom = 1; | |
} | |
public BoundaryControl boundaryControl; | |
private float movMinX; | |
private float movMaxX; | |
private float movMinY; | |
private float movMaxY; | |
[SerializeField] | |
private bool forceIntegerPositions = false; | |
public float customGravity = 9.8f; | |
protected Vector2 targetVelocity; | |
protected bool isGrounded; | |
protected Vector2 groundNormal; | |
protected Rigidbody2D rb2d; | |
protected Vector2 velocity; | |
protected int layerMask ; | |
protected const float minMoveDistance = 0.001f; | |
protected const float shellRadius = 0.01f; | |
protected BoxCollider2D bc2d; | |
void Awake () { | |
rb2d = GetComponent<Rigidbody2D> (); | |
bc2d = GetComponent<BoxCollider2D> (); | |
// Precaulculate the Maxs and Mins to check boundaries | |
Vector3 objectExtents ; | |
SpriteRenderer spriteRenderer; | |
spriteRenderer = GetComponent<SpriteRenderer> (); | |
objectExtents = spriteRenderer.bounds.extents; | |
// Works for Scale == 1 | |
movMinX = boundaryControl.boundaryLeft + objectExtents.x ; | |
movMaxX = boundaryControl.boundaryRight - objectExtents.x ; | |
movMinY = boundaryControl.boundaryBottom + objectExtents.y ; | |
movMaxY = boundaryControl.boundaryTop - objectExtents.y ; | |
layerMask = LayerMask.GetMask ("Platform") | LayerMask.GetMask ("Wall"); | |
} | |
void Update () | |
{ | |
targetVelocity = Vector2.zero; | |
ComputeVelocity (); | |
} | |
protected virtual void ComputeVelocity() {} | |
void FixedUpdate() | |
{ | |
UpdateMovement (); | |
} | |
protected virtual void UpdateMovement () { | |
velocity -= customGravity * Vector2.up * Time.deltaTime; | |
velocity.x = targetVelocity.x; | |
isGrounded = false; | |
Vector2 deltaPosition = velocity * Time.deltaTime; | |
// Check movement along X (Ground) | |
Vector2 move = Vector2.right * deltaPosition.x; | |
Movement (move, false); | |
// Check movement along Y (Vertically) | |
move = Vector2.up * deltaPosition.y; | |
Movement (move, true); | |
} | |
protected void Movement (Vector2 move, bool yMovement) | |
{ | |
float distance = move.magnitude; | |
RaycastHit2D hit ; | |
if (distance > minMoveDistance) { | |
// If the player is jumping will not test for collisions | |
if (!yMovement || (move.y < 0.01f)) { | |
Vector2 start = rb2d.position; | |
if (yMovement) { | |
start.y -= bc2d.bounds.extents.y; | |
} else { | |
start.x += bc2d.bounds.extents.x * Mathf.Sign (move.x); | |
} | |
Vector2 end = start + move; | |
hit = Physics2D.Linecast (start, end, layerMask, -Mathf.Infinity, distance + shellRadius); | |
if (hit.collider != null) { | |
if (yMovement) { | |
isGrounded = true; | |
velocity.y = 0.0f; | |
} | |
float modifiedDistance = hit.distance - shellRadius; | |
distance = modifiedDistance < distance ? modifiedDistance : distance; | |
} | |
} | |
UpdatePosition (rb2d.position + move.normalized * distance); | |
} | |
} | |
// This method controls the player movement inside boundaries | |
protected void UpdatePosition (Vector2 position) { | |
Vector2 newPosition = position; | |
if (boundaryControl.checkBoundaries) { | |
newPosition.x = Mathf.Clamp (newPosition.x, movMinX, movMaxX); | |
newPosition.y = Mathf.Clamp (newPosition.y, movMinY, movMaxY); | |
} | |
if (forceIntegerPositions) { | |
// Force the position x/y to integer values only | |
newPosition.x = Mathf.Floor (newPosition.x + 0.5f); | |
newPosition.y = Mathf.Floor (newPosition.y + 0.5f); | |
} | |
rb2d.position = newPosition ; | |
} | |
} |
This file contains 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; | |
public class RetroPlatformController : RetroPhysicsObject { | |
[SerializeField] | |
private float walkingSpeed = 7; | |
[SerializeField] | |
private float jumpTakeOffSpeed = 7; | |
[SerializeField] | |
private float climbingSpeed = 7; | |
private SpriteRenderer spriteRenderer; | |
private Animator animator; | |
private float prevMovX = 0.0f; | |
private bool canClimb = false; | |
private Ladder ladder = null; | |
private bool isClimbing = false; | |
private bool hasStoppedClimbing = false; | |
private float deltaLadderBoundaries = 0.3f; | |
// | |
private Vector2 initialPosition; | |
private bool isDead = false; | |
// Use this for initialization | |
void Start () | |
{ | |
spriteRenderer = GetComponent<SpriteRenderer> (); | |
animator = GetComponent<Animator> (); | |
Ladder.onCanClimbChanged += OnCanClimbChanged; | |
// Store the initial position to respawn at the same place | |
initialPosition = rb2d.transform.position; | |
} | |
protected override void ComputeVelocity() | |
{ | |
if (isDead) { | |
return; | |
} | |
Vector2 move = Vector2.zero; | |
if (isGrounded) { | |
if (Input.GetKey (KeyCode.A)) { | |
move.x = -1.0f; | |
} else if (Input.GetKey (KeyCode.D)) { | |
move.x = 1.0f; | |
} | |
prevMovX = move.x; | |
} else { | |
move.x = prevMovX; | |
} | |
bool flipSprite = (spriteRenderer.flipX ? (move.x < -0.01f) : (move.x > 0.01f)) ; | |
if (flipSprite) | |
{ | |
spriteRenderer.flipX = !spriteRenderer.flipX; | |
} | |
// Check Ladder | |
if ((canClimb) && (isGrounded)) { | |
if (Input.GetKey (KeyCode.W)) { | |
if (IsPlayerOnLadderBottom()) { | |
isClimbing = true; | |
// Force x player position to the ladder center | |
Vector2 tmp = rb2d.position; | |
tmp.x = ladder.gameObject.transform.position.x; | |
rb2d.position = tmp; | |
} | |
} else if (Input.GetKey (KeyCode.S)) { | |
if (IsPlayerOnLadderTop ()) { | |
isClimbing = true; | |
// Force x player position to the ladder center | |
Vector2 tmp = rb2d.position; | |
tmp.x = ladder.gameObject.transform.position.x; | |
rb2d.position = tmp; | |
} | |
} | |
} | |
if (isClimbing) { | |
if (Input.GetKey (KeyCode.W)) { | |
targetVelocity = Vector2.up * climbingSpeed; | |
} else if (Input.GetKey (KeyCode.S)) { | |
targetVelocity = Vector2.up * -climbingSpeed; | |
} | |
} else { | |
if (Input.GetKey (KeyCode.W) && isGrounded) { | |
velocity.y = jumpTakeOffSpeed; | |
} | |
targetVelocity = move * walkingSpeed; | |
} | |
// Update the animations | |
if (animator != null) { | |
if (isGrounded && !isClimbing) { | |
animator.enabled = true; | |
if (Mathf.Abs (move.x) > 0.01f) { | |
animator.Play ("Henry Walk"); | |
} else { | |
animator.Play ("Henry Idle"); | |
} | |
} else if (isClimbing) { | |
animator.Play ("Henry Climb"); | |
if (isGrounded) { | |
animator.enabled = true; | |
} else { | |
if (targetVelocity.y > 0.01f) { | |
animator.enabled = true; | |
} else if (targetVelocity.y < -0.01f) { | |
animator.enabled = true; | |
} else { | |
animator.enabled = false; | |
} | |
} | |
} else { | |
animator.enabled = true; | |
animator.Play ("Henry Jump"); | |
} | |
} | |
} | |
public void OnCanClimbChanged (bool canClimb, Ladder ladder) { | |
this.canClimb = canClimb; | |
this.ladder = ladder; | |
} | |
private bool IsPlayerOnLadderBottom () { | |
if (ladder == null) { | |
return false; | |
} | |
BoxCollider2D ladderBc2d; | |
ladderBc2d = ladder.GetComponent<BoxCollider2D> (); | |
float ladderBottom = ladderBc2d.bounds.center.y - ladderBc2d.bounds.extents.y; | |
float playerBottom = bc2d.bounds.center.y - bc2d.bounds.extents.y; | |
if ((playerBottom - ladderBottom) < deltaLadderBoundaries) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
private bool IsPlayerOnLadderTop () { | |
if (ladder == null) { | |
return false; | |
} | |
BoxCollider2D ladderBc2d; | |
ladderBc2d = ladder.GetComponent<BoxCollider2D> (); | |
float ladderTop = ladderBc2d.bounds.center.y + ladderBc2d.bounds.extents.y; | |
float playerBottom = bc2d.bounds.center.y - bc2d.bounds.extents.y; | |
if ((ladderTop - playerBottom) < deltaLadderBoundaries) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
protected override void UpdateMovement () { | |
if (isClimbing) { | |
// Logic for ladder climbing | |
isGrounded = false; | |
// Check movement along Y (Vertically) | |
Vector2 newPosition = rb2d.position + Vector2.up * targetVelocity.y * Time.deltaTime; | |
if (targetVelocity.y > 0.01f) { | |
// Up - Check Top | |
if (IsPlayerOnLadderTop ()) { | |
// Adjust position on ground | |
BoxCollider2D ladderBc2d; | |
ladderBc2d = ladder.GetComponent<BoxCollider2D> (); | |
float ladderTop = ladderBc2d.bounds.center.y + ladderBc2d.bounds.extents.y; | |
newPosition.y = ladderTop + bc2d.bounds.extents.y + 0.01f; | |
isClimbing = false; | |
isGrounded = true; | |
} | |
} else if (targetVelocity.y < -0.01f) { | |
// Down - Check Bottom | |
if (IsPlayerOnLadderBottom ()) { | |
// Adjust position on ground | |
BoxCollider2D ladderBc2d; | |
ladderBc2d = ladder.GetComponent<BoxCollider2D> (); | |
float ladderBottom = ladderBc2d.bounds.center.y - ladderBc2d.bounds.extents.y; | |
newPosition.y = ladderBottom + bc2d.bounds.extents.y + 0.01f; | |
isClimbing = false; | |
isGrounded = true; | |
} | |
} | |
rb2d.position = newPosition; | |
} else { | |
// Logic for walking and jumping | |
base.UpdateMovement(); | |
} | |
} | |
public void PlayerDied () { | |
isDead = true; | |
animator.enabled = true; | |
animator.Play ("Henry Died"); | |
} | |
public void PlayerRespawn () { | |
isDead = false; | |
rb2d.transform.position = initialPosition; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment