Advertisement
SebastianLague

platformer slide test

Sep 27th, 2016
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.02 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class Controller2D : RaycastController {
  5.  
  6.     /* changes for slope sliding:
  7.      * faceDir calculated after DescendSlope method call
  8.      * Descend slope method has new code to handle slopes > maxangle
  9.      * Vertical collision does not set collision below flag if sliding down slope
  10.      */
  11.  
  12.     float maxSlopeAngle = 60;
  13.    
  14.     public CollisionInfo collisions;
  15.     [HideInInspector]
  16.     public Vector2 playerInput;
  17.    
  18.     public override void Start() {
  19.         base.Start ();
  20.         collisions.faceDir = 1;
  21.  
  22.     }
  23.    
  24.     public void Move(Vector2 moveAmount, bool standingOnPlatform) {
  25.         Move (moveAmount, Vector2.zero, standingOnPlatform);
  26.     }
  27.  
  28.     bool started;
  29.  
  30.     public void Move(Vector2 moveAmount, Vector2 input, bool standingOnPlatform = false) {
  31.         UpdateRaycastOrigins ();
  32.  
  33.         collisions.Reset ();
  34.         collisions.moveAmountOld = moveAmount;
  35.         playerInput = input;
  36.  
  37.         if (moveAmount.y < 0) {
  38.             DescendSlope(ref moveAmount);
  39.         }
  40.  
  41.         // set faceDir after descend slope method as sliding down slope may chance movedir
  42.         if (moveAmount.x != 0) {
  43.             collisions.faceDir = (int)Mathf.Sign(moveAmount.x);
  44.         }
  45.         HorizontalCollisions (ref moveAmount);
  46.         if (moveAmount.y != 0) {
  47.             VerticalCollisions (ref moveAmount);
  48.         }
  49.  
  50.         transform.Translate (moveAmount);
  51.  
  52.         if (standingOnPlatform) {
  53.             collisions.below = true;
  54.         }
  55.     }
  56.  
  57.     void HorizontalCollisions(ref Vector2 moveAmount) {
  58.         float directionX = collisions.faceDir;
  59.         float rayLength = Mathf.Abs (moveAmount.x) + skinWidth;
  60.  
  61.         if (Mathf.Abs(moveAmount.x) < skinWidth) {
  62.             rayLength = 2*skinWidth;
  63.         }
  64.        
  65.         for (int i = 0; i < horizontalRayCount; i ++) {
  66.             Vector2 rayOrigin = (directionX == -1)?raycastOrigins.bottomLeft:raycastOrigins.bottomRight;
  67.             rayOrigin += Vector2.up * (horizontalRaySpacing * i);
  68.             RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * directionX, rayLength, collisionMask);
  69.  
  70.             Debug.DrawRay(rayOrigin, Vector2.right * directionX,Color.red);
  71.  
  72.             if (hit) {
  73.  
  74.                 if (hit.distance == 0) {
  75.                     continue;
  76.                 }
  77.            
  78.                 float slopeAngle = Vector2.Angle(hit.normal, Vector2.up);
  79.  
  80.                 if (i == 0 && slopeAngle <= maxSlopeAngle) {
  81.                     if (collisions.descendingSlope) {
  82.                         collisions.descendingSlope = false;
  83.                         moveAmount = collisions.moveAmountOld;
  84.                     }
  85.                     float distanceToSlopeStart = 0;
  86.                     if (slopeAngle != collisions.slopeAngleOld) {
  87.                         distanceToSlopeStart = hit.distance-skinWidth;
  88.                         moveAmount.x -= distanceToSlopeStart * directionX;
  89.                     }
  90.                     ClimbSlope(ref moveAmount, slopeAngle);
  91.                     moveAmount.x += distanceToSlopeStart * directionX;
  92.                 }
  93.  
  94.                 if (!collisions.climbingSlope || slopeAngle > maxSlopeAngle) {
  95.                     moveAmount.x = (hit.distance - skinWidth) * directionX;
  96.                     rayLength = hit.distance;
  97.  
  98.                     if (collisions.climbingSlope) {
  99.                         moveAmount.y = Mathf.Tan(collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Abs(moveAmount.x);
  100.                     }
  101.  
  102.                     collisions.left = directionX == -1;
  103.                     collisions.right = directionX == 1;
  104.                 }
  105.             }
  106.         }
  107.     }
  108.    
  109.     void VerticalCollisions(ref Vector2 moveAmount) {
  110.         float directionY = Mathf.Sign (moveAmount.y);
  111.         float rayLength = Mathf.Abs (moveAmount.y) + skinWidth;
  112.         float yB = moveAmount.y;
  113.         for (int i = 0; i < verticalRayCount; i ++) {
  114.  
  115.             Vector2 rayOrigin = (directionY == -1)?raycastOrigins.bottomLeft:raycastOrigins.topLeft;
  116.             rayOrigin += Vector2.right * (verticalRaySpacing * i + moveAmount.x);
  117.             RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
  118.  
  119.             Debug.DrawRay(rayOrigin, Vector2.up * directionY,Color.red);
  120.  
  121.  
  122.  
  123.             if (hit) {
  124.                 if (hit.collider.tag == "Through") {
  125.                     if (directionY == 1 || hit.distance == 0) {
  126.                         continue;
  127.                     }
  128.                     if (collisions.fallingThroughPlatform) {
  129.                         continue;
  130.                     }
  131.                     if (playerInput.y == -1) {
  132.                         collisions.fallingThroughPlatform = true;
  133.                         Invoke("ResetFallingThroughPlatform",.5f);
  134.                         continue;
  135.                     }
  136.                 }
  137.  
  138.                 moveAmount.y = (hit.distance - skinWidth) * directionY;
  139.                 rayLength = hit.distance;
  140.  
  141.                 if (collisions.climbingSlope) {
  142.                     moveAmount.x = moveAmount.y / Mathf.Tan(collisions.slopeAngle * Mathf.Deg2Rad) * Mathf.Sign(moveAmount.x);
  143.                 }
  144.  
  145.                 if (!collisions.descendingSlope) {
  146.                     collisions.below = directionY == -1;
  147.                     collisions.above = directionY == 1;
  148.                 }
  149.             }
  150.         }
  151.  
  152.         if (collisions.climbingSlope) {
  153.             float directionX = Mathf.Sign(moveAmount.x);
  154.             rayLength = Mathf.Abs(moveAmount.x) + skinWidth;
  155.             Vector2 rayOrigin = ((directionX == -1)?raycastOrigins.bottomLeft:raycastOrigins.bottomRight) + Vector2.up * moveAmount.y;
  156.             RaycastHit2D hit = Physics2D.Raycast(rayOrigin,Vector2.right * directionX,rayLength,collisionMask);
  157.  
  158.             if (hit) {
  159.                 float slopeAngle = Vector2.Angle(hit.normal,Vector2.up);
  160.                 if (slopeAngle != collisions.slopeAngle) {
  161.                     moveAmount.x = (hit.distance - skinWidth) * directionX;
  162.                     collisions.slopeAngle = slopeAngle;
  163.                 }
  164.             }
  165.         }
  166.     }
  167.  
  168.     void ClimbSlope(ref Vector2 moveAmount, float slopeAngle) {
  169.         float moveDistance = Mathf.Abs (moveAmount.x);
  170.         float climbmoveAmountY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;
  171.  
  172.         if (moveAmount.y <= climbmoveAmountY) {
  173.             moveAmount.y = climbmoveAmountY;
  174.             moveAmount.x = Mathf.Cos (slopeAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign (moveAmount.x);
  175.             collisions.below = true;
  176.             collisions.climbingSlope = true;
  177.             collisions.slopeAngle = slopeAngle;
  178.         }
  179.     }
  180.  
  181.     void DescendSlope(ref Vector2 moveAmount) {
  182.  
  183.         // Detect slope > max angle
  184.         RaycastHit2D hitDLeft = Physics2D.Raycast (raycastOrigins.bottomLeft, -Vector2.up, (Mathf.Abs(moveAmount.y)+skinWidth), collisionMask);
  185.         if (hitDLeft) {
  186.             float slopeAngle = Vector2.Angle(hitDLeft.normal, Vector2.up);
  187.             slopeAngle = Mathf.Min (slopeAngle, 180 - slopeAngle);
  188.             if (slopeAngle > maxSlopeAngle) {
  189.                 moveAmount.x = (Mathf.Abs(moveAmount.y) - hitDLeft.distance)/ Mathf.Tan (slopeAngle * Mathf.Deg2Rad);
  190.  
  191.                 collisions.descendingSlope = true;
  192.                 return;
  193.             }
  194.         }
  195.  
  196.         RaycastHit2D hitDRight = Physics2D.Raycast (raycastOrigins.bottomRight, -Vector2.up, (Mathf.Abs(moveAmount.y)+skinWidth), collisionMask);
  197.         if (hitDRight) {
  198.             float slopeAngle = Vector2.Angle(hitDRight.normal, Vector2.up);
  199.             slopeAngle = Mathf.Min (slopeAngle, 180 - slopeAngle);
  200.             if (slopeAngle > maxSlopeAngle) {
  201.                 moveAmount.x = -(Mathf.Abs(moveAmount.y) - hitDRight.distance)/ Mathf.Tan (slopeAngle * Mathf.Deg2Rad);
  202.  
  203.                 collisions.descendingSlope = true;
  204.                 return;
  205.             }
  206.         }
  207.  
  208.         // detect slope < max angle
  209.  
  210.         float directionX = Mathf.Sign (moveAmount.x);
  211.         Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomRight : raycastOrigins.bottomLeft;
  212.         RaycastHit2D hit = Physics2D.Raycast (rayOrigin, -Vector2.up, Mathf.Infinity, collisionMask);
  213.  
  214.         if (hit) {
  215.             float slopeAngle = Vector2.Angle(hit.normal, Vector2.up);
  216.             if (slopeAngle != 0 && slopeAngle <= maxSlopeAngle) {
  217.                 if (Mathf.Sign(hit.normal.x) == directionX) {
  218.                     if (hit.distance - skinWidth <= Mathf.Tan(slopeAngle * Mathf.Deg2Rad) * Mathf.Abs(moveAmount.x)) {
  219.                         float moveDistance = Mathf.Abs(moveAmount.x);
  220.                         float descendmoveAmountY = Mathf.Sin (slopeAngle * Mathf.Deg2Rad) * moveDistance;
  221.                         moveAmount.x = Mathf.Cos (slopeAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign (moveAmount.x);
  222.                         moveAmount.y -= descendmoveAmountY;
  223.  
  224.                         collisions.slopeAngle = slopeAngle;
  225.                         collisions.descendingSlope = true;
  226.                         collisions.below = true;
  227.                     }
  228.                 }
  229.             }
  230.         }
  231.     }
  232.  
  233.     void ResetFallingThroughPlatform() {
  234.         collisions.fallingThroughPlatform = false;
  235.     }
  236.  
  237.     public struct CollisionInfo {
  238.         public bool above, below;
  239.         public bool left, right;
  240.  
  241.         public bool climbingSlope;
  242.         public bool descendingSlope;
  243.         public float slopeAngle, slopeAngleOld;
  244.         public Vector2 moveAmountOld;
  245.         public int faceDir;
  246.         public bool fallingThroughPlatform;
  247.  
  248.         public void Reset() {
  249.             above = below = false;
  250.             left = right = false;
  251.             climbingSlope = false;
  252.             descendingSlope = false;
  253.  
  254.             slopeAngleOld = slopeAngle;
  255.             slopeAngle = 0;
  256.         }
  257.     }
  258.  
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement