Created
August 13, 2014 16:29
-
-
Save devindazzle/f3b55028fc49f434365d to your computer and use it in GitHub Desktop.
CharacterController2D
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; | |
using System.Linq; | |
using UnityEngine; | |
[RequireComponent(typeof(BoxCollider2D))] | |
public class CharacterController2D : MonoBehaviour | |
{ | |
#region Fields and Properties | |
[Range(.001f, 0.3f)] | |
public float SkinWidth = .02f; | |
public LayerMask PlatformMask = 0; | |
[SerializeField] | |
private LayerMask OneWayPlatformMask = 0; | |
public ControllerParameters2D Parameters { get { return _overrideParameters ?? DefaultParameters; } } | |
public ControllerParameters2D DefaultParameters; | |
private ControllerParameters2D _overrideParameters; | |
public bool HandleCollisions { get; set; } | |
public ControllerState2D State { get; private set; } | |
[SerializeField] | |
[Range(2, 20)] | |
private int TotalHorizontalRays = 4; | |
[SerializeField] | |
[Range(2, 20)] | |
private int TotalVerticalRays = 3; | |
private Transform _transform; | |
private BoxCollider2D _boxCollider; | |
private float | |
_verticalDistanceBetweenRays, | |
_horizontalDistanceBetweenRays; | |
private Vector3 | |
_rayCastTopLeft, | |
_rayCastBottomRight, | |
_rayCastBottomLeft; | |
public bool CanJump | |
{ | |
get | |
{ | |
if (Parameters.JumpRestrictions == ControllerParameters2D.JumpBehavior.CanJumpAnywhere) | |
return _jumpIn <= 0; | |
if (Parameters.JumpRestrictions == ControllerParameters2D.JumpBehavior.CanJumpOnGround) | |
return State.IsGrounded; | |
return false; | |
} | |
} | |
private float _jumpIn; | |
public Vector2 Velocity { get { return _velocity; } } | |
private Vector2 _velocity; | |
#endregion | |
public void Awake() | |
{ | |
HandleCollisions = true; | |
State = new ControllerState2D(); | |
// Add one-way platforms to our normal platform mask so that we can land on them from above | |
PlatformMask |= OneWayPlatformMask; | |
// Cache some of the components | |
_transform = transform; | |
_boxCollider = GetComponent<BoxCollider2D>(); | |
// Calculate the distance between rays | |
RecalculateDistanceBetweenRays(); | |
} | |
public void AddForce(Vector2 force) | |
{ | |
_velocity += force; | |
} | |
public void SetForce(Vector2 force) | |
{ | |
_velocity = force; | |
} | |
public void SetHorizontalForce(float x) | |
{ | |
_velocity.x = x; | |
} | |
public void SetVerticalForce(float y) | |
{ | |
_velocity.y = y; | |
} | |
public void Jump() | |
{ | |
} | |
public void LateUpdate() | |
{ | |
// Jump restrictions | |
_jumpIn -= Time.deltaTime; | |
// Move the character | |
Move(Velocity * Time.deltaTime); | |
} | |
private void Move(Vector2 deltaMovement) | |
{ | |
// Determine if the character was grounded last frame | |
var wasGrounded = State.IsCollidingBelow; | |
State.Reset(); | |
if (HandleCollisions) | |
{ | |
HandlePlatforms(); | |
CalculateRayOrigins(); | |
// Move horizontally | |
if (Mathf.Abs(deltaMovement.x) > .001f) | |
MoveHorizontally(ref deltaMovement); | |
} | |
// Move the character | |
_transform.Translate(deltaMovement, Space.World); | |
if (Time.deltaTime > 0f) | |
_velocity = deltaMovement/Time.deltaTime; | |
// Ensure the character is never moving faster the the maximum allowed speed | |
_velocity.x = Mathf.Min(_velocity.x, Parameters.MaxVelocity.x); | |
_velocity.y = Mathf.Min(_velocity.y, Parameters.MaxVelocity.y); | |
// Determine if character became grounded (landed) on this frame | |
State.BecameGroundedThisFrame = (!wasGrounded && State.IsCollidingBelow); | |
} | |
private void HandlePlatforms() | |
{ | |
} | |
private void RecalculateDistanceBetweenRays() | |
{ | |
var colliderWidth = _boxCollider.size.x * Mathf.Abs(_transform.localScale.x) - (2 * SkinWidth); | |
_horizontalDistanceBetweenRays = colliderWidth / (TotalVerticalRays - 1); | |
var colliderHeight = _boxCollider.size.y * Mathf.Abs(_transform.localScale.y) - (2 * SkinWidth); | |
_verticalDistanceBetweenRays = colliderHeight / (TotalHorizontalRays - 1); | |
} | |
private void CalculateRayOrigins() | |
{ | |
var size = new Vector2(_boxCollider.size.x * Mathf.Abs(_transform.localScale.x), _boxCollider.size.y * Mathf.Abs(_transform.localScale.y)) / 2; | |
var center = new Vector2(_boxCollider.center.x * _transform.localScale.x, _boxCollider.center.y * _transform.localScale.y); | |
_rayCastTopLeft = _transform.position + new Vector3(center.x - size.x + SkinWidth, center.y + size.y - SkinWidth); | |
_rayCastBottomRight = _transform.position + new Vector3(center.x + size.x - SkinWidth, center.y - size.y + SkinWidth); | |
_rayCastBottomLeft = _transform.position + new Vector3(center.x - size.x + SkinWidth, center.y - size.y + SkinWidth); | |
} | |
private void MoveHorizontally(ref Vector2 deltaMovement) | |
{ | |
var isGoingRight = deltaMovement.x > 0; | |
var rayDistance = Mathf.Abs(deltaMovement.x) + SkinWidth; | |
var rayDirection = isGoingRight ? Vector2.right : -Vector2.right; | |
var rayOrigin = isGoingRight ? _rayCastBottomRight : _rayCastBottomLeft; | |
// Debug.Log("isGoingRight: " + isGoingRight + " Distance: " + rayDistance + " Dírection: " + rayDirection + " Origin: " + rayOrigin); | |
for (var i = 0; i < TotalHorizontalRays; i++) | |
{ | |
var rayVector = new Vector2(rayOrigin.x, rayOrigin.y + (i * _verticalDistanceBetweenRays)); | |
Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red); | |
var rayCastHit = Physics2D.Raycast(rayVector, rayDirection, rayDistance, PlatformMask); | |
if (!rayCastHit) | |
continue; | |
// if (i == 0 && HandleHorizontalSlope(ref deltaMovement, Vector2.Angle(rayCastHit.normal, Vector2.up), isGoingRight)) | |
// break; | |
deltaMovement.x = rayCastHit.point.x - rayVector.x; | |
rayDistance = Mathf.Abs(deltaMovement.x); | |
if (isGoingRight) | |
{ | |
deltaMovement.x -= SkinWidth; | |
State.IsCollidingRight = true; | |
} | |
else | |
{ | |
deltaMovement.x += SkinWidth; | |
State.IsCollidingLeft = true; | |
} | |
if (rayDistance < SkinWidth + .0001f) | |
break; | |
} | |
} | |
private void MoveVertically(ref Vector2 deltaMovement) | |
{ | |
} | |
public void OnTriggerEnter2D(Collider2D other) | |
{ | |
var parameters = other.gameObject.GetComponent<ControllerPhysicsVolume2D>(); | |
if (parameters == null) | |
return; | |
_overrideParameters = parameters.Parameters; | |
} | |
public void OnTriggerExit2D(Collider2D other) | |
{ | |
var parameters = other.gameObject.GetComponent<ControllerPhysicsVolume2D>(); | |
if (parameters == null) | |
return; | |
_overrideParameters = null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment