Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- public class Controller2D : RaycastController {
- /* changes for slope sliding:
- * faceDir calculated after DescendSlope method call
- * Descend slope method has new code to handle slopes > maxangle
- * Vertical collision does not set collision below flag if sliding down slope
- */
- float maxSlopeAngle = 60;
- public CollisionInfo collisions;
- [HideInInspector]
- public Vector2 playerInput;
- public override void Start() {
- base.Start ();
- collisions.faceDir = 1;
- }
- public void Move(Vector2 moveAmount, bool standingOnPlatform) {
- Move (moveAmount, Vector2.zero, standingOnPlatform);
- }
- bool started;
- public void Move(Vector2 moveAmount, Vector2 input, bool standingOnPlatform = false) {
- UpdateRaycastOrigins ();
- collisions.Reset ();
- collisions.moveAmountOld = moveAmount;
- playerInput = input;
- if (moveAmount.y < 0) {
- DescendSlope(ref moveAmount);
- }
- // set faceDir after descend slope method as sliding down slope may chance movedir
- if (moveAmount.x != 0) {
- collisions.faceDir = (int)Mathf.Sign(moveAmount.x);
- }
- HorizontalCollisions (ref moveAmount);
- if (moveAmount.y != 0) {
- VerticalCollisions (ref moveAmount);
- }
- transform.Translate (moveAmount);
- if (standingOnPlatform) {
- collisions.below = true;
- }
- }
- void HorizontalCollisions(ref Vector2 moveAmount) {
- float directionX = collisions.faceDir;
- float rayLength = Mathf.Abs (moveAmount.x) + skinWidth;
- if (Mathf.Abs(moveAmount.x) < skinWidth) {
- rayLength = 2*skinWidth;
- }
- for (int i = 0; i < horizontalRayCount; i ++) {
- Vector2 rayOrigin = (directionX == -1)?raycastOrigins.bottomLeft:raycastOrigins.bottomRight;
- rayOrigin += Vector2.up * (horizontalRaySpacing * i);
- RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * directionX, rayLength, collisionMask);
- Debug.DrawRay(rayOrigin, Vector2.right * directionX,Color.red);
- if (hit) {
- if (hit.distance == 0) {
- continue;
- }
- float slopeAngle = Vector2.Angle(hit.normal, Vector2.up);
- if (i == 0 && slopeAngle <= maxSlopeAngle) {
- if (collisions.descendingSlope) {
- collisions.descendingSlope = false;
- moveAmount = collisions.moveAmountOld;
- }
- float distanceToSlopeStart = 0;
- if (slopeAngle != collisions.slopeAngleOld) {
- distanceToSlopeStart = hit.distance-skinWidth;
- moveAmount.x -= distanceToSlopeStart * directionX;
- }
- ClimbSlope(ref moveAmount, slopeAngle);
- moveAmount.x += distanceToSlopeStart * directionX;
- }
- if (!collisions.climbingSlope || slopeAngle > maxSlopeAngle) {
- moveAmount.x = (hit.distance - skinWidth) * directionX;
- rayLength = hit.distance;
- if (collisions.climbingSlope) {
- moveAmount.y = Mathf.Tan(collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Abs(moveAmount.x);
- }
- collisions.left = directionX == -1;
- collisions.right = directionX == 1;
- }
- }
- }
- }
- void VerticalCollisions(ref Vector2 moveAmount) {
- float directionY = Mathf.Sign (moveAmount.y);
- float rayLength = Mathf.Abs (moveAmount.y) + skinWidth;
- float yB = moveAmount.y;
- for (int i = 0; i < verticalRayCount; i ++) {
- Vector2 rayOrigin = (directionY == -1)?raycastOrigins.bottomLeft:raycastOrigins.topLeft;
- rayOrigin += Vector2.right * (verticalRaySpacing * i + moveAmount.x);
- RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
- Debug.DrawRay(rayOrigin, Vector2.up * directionY,Color.red);
- if (hit) {
- if (hit.collider.tag == "Through") {
- if (directionY == 1 || hit.distance == 0) {
- continue;
- }
- if (collisions.fallingThroughPlatform) {
- continue;
- }
- if (playerInput.y == -1) {
- collisions.fallingThroughPlatform = true;
- Invoke("ResetFallingThroughPlatform",.5f);
- continue;
- }
- }
- moveAmount.y = (hit.distance - skinWidth) * directionY;
- rayLength = hit.distance;
- if (collisions.climbingSlope) {
- moveAmount.x = moveAmount.y / Mathf.Tan(collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Sign(moveAmount.x);
- }
- if (!collisions.descendingSlope) {
- collisions.below = directionY == -1;
- collisions.above = directionY == 1;
- }
- }
- }
- if (collisions.climbingSlope) {
- float directionX = Mathf.Sign(moveAmount.x);
- rayLength = Mathf.Abs(moveAmount.x) + skinWidth;
- Vector2 rayOrigin = ((directionX == -1)?raycastOrigins.bottomLeft:raycastOrigins.bottomRight) + Vector2.up * moveAmount.y;
- RaycastHit2D hit = Physics2D.Raycast(rayOrigin,Vector2.right * directionX,rayLength,collisionMask);
- if (hit) {
- float slopeAngle = Vector2.Angle(hit.normal,Vector2.up);
- if (slopeAngle != collisions.slopeAngle) {
- moveAmount.x = (hit.distance - skinWidth) * directionX;
- collisions.slopeAngle = slopeAngle;
- }
- }
- }
- }
- void ClimbSlope(ref Vector2 moveAmount, float slopeAngle) {
- float moveDistance = Mathf.Abs (moveAmount.x);
- float climbmoveAmountY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;
- if (moveAmount.y <= climbmoveAmountY) {
- moveAmount.y = climbmoveAmountY;
- moveAmount.x = Mathf.Cos (slopeAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign (moveAmount.x);
- collisions.below = true;
- collisions.climbingSlope = true;
- collisions.slopeAngle = slopeAngle;
- }
- }
- void DescendSlope(ref Vector2 moveAmount) {
- // Detect slope > max angle
- RaycastHit2D hitDLeft = Physics2D.Raycast (raycastOrigins.bottomLeft, -Vector2.up, (Mathf.Abs(moveAmount.y)+skinWidth), collisionMask);
- if (hitDLeft) {
- float slopeAngle = Vector2.Angle(hitDLeft.normal, Vector2.up);
- slopeAngle = Mathf.Min (slopeAngle, 180 - slopeAngle);
- if (slopeAngle > maxSlopeAngle) {
- moveAmount.x = (Mathf.Abs(moveAmount.y) - hitDLeft.distance)/ Mathf.Tan (slopeAngle * Mathf.Deg2Rad);
- collisions.descendingSlope = true;
- return;
- }
- }
- RaycastHit2D hitDRight = Physics2D.Raycast (raycastOrigins.bottomRight, -Vector2.up, (Mathf.Abs(moveAmount.y)+skinWidth), collisionMask);
- if (hitDRight) {
- float slopeAngle = Vector2.Angle(hitDRight.normal, Vector2.up);
- slopeAngle = Mathf.Min (slopeAngle, 180 - slopeAngle);
- if (slopeAngle > maxSlopeAngle) {
- moveAmount.x = -(Mathf.Abs(moveAmount.y) - hitDRight.distance)/ Mathf.Tan (slopeAngle * Mathf.Deg2Rad);
- collisions.descendingSlope = true;
- return;
- }
- }
- // detect slope < max angle
- float directionX = Mathf.Sign (moveAmount.x);
- Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomRight : raycastOrigins.bottomLeft;
- RaycastHit2D hit = Physics2D.Raycast (rayOrigin, -Vector2.up, Mathf.Infinity, collisionMask);
- if (hit) {
- float slopeAngle = Vector2.Angle(hit.normal, Vector2.up);
- if (slopeAngle != 0 && slopeAngle <= maxSlopeAngle) {
- if (Mathf.Sign(hit.normal.x) == directionX) {
- if (hit.distance - skinWidth <= Mathf.Tan(slopeAngle * Mathf.Deg2Rad) * Mathf.Abs(moveAmount.x)) {
- float moveDistance = Mathf.Abs(moveAmount.x);
- float descendmoveAmountY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;
- moveAmount.x = Mathf.Cos (slopeAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign (moveAmount.x);
- moveAmount.y -= descendmoveAmountY;
- collisions.slopeAngle = slopeAngle;
- collisions.descendingSlope = true;
- collisions.below = true;
- }
- }
- }
- }
- }
- void ResetFallingThroughPlatform() {
- collisions.fallingThroughPlatform = false;
- }
- public struct CollisionInfo {
- public bool above, below;
- public bool left, right;
- public bool climbingSlope;
- public bool descendingSlope;
- public float slopeAngle, slopeAngleOld;
- public Vector2 moveAmountOld;
- public int faceDir;
- public bool fallingThroughPlatform;
- public void Reset() {
- above = below = false;
- left = right = false;
- climbingSlope = false;
- descendingSlope = false;
- slopeAngleOld = slopeAngle;
- slopeAngle = 0;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement