Guest User

CharacterMovement.cs

a guest
Sep 22nd, 2020
1,218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.35 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class CharacterMovement : MonoBehaviour
  6. {
  7.  
  8.     public float floorOffsetY;
  9.     public float moveSpeed = 6f;
  10.     public float rotateSpeed = 10f;
  11.     public float slopeLimit = 45f;
  12.     public float slopeInfluence = 5f;
  13.     public float jumpPower = 10f;
  14.     public float characterHangOffset = 1.4f;
  15.  
  16.     Rigidbody rb;
  17.     Animator anim;
  18.     float vertical;
  19.     float horizontal;
  20.  
  21.     [SerializeField]
  22.     Vector3 moveDirection;
  23.     float inputAmount;
  24.     Vector3 raycastFloorPos;
  25.     Vector3 floorMovement;
  26.  
  27.     [SerializeField]
  28.     Vector3 gravity;
  29.     Vector3 CombinedRaycast;
  30.    
  31.     float jumpFalloff = 2f;
  32.     bool jump_input_down;
  33.     bool drop_input_down;
  34.     float slopeAmount;
  35.     Vector3 floorNormal;
  36.  
  37.     [SerializeField]
  38.     Vector3 velocity;
  39.  
  40.    
  41.     public bool safeForClimbUp;
  42.  
  43.  
  44.     // ledge climbing
  45.     bool GrabLedge;
  46.  
  47.    public Vector3 LedgePos;
  48.    public Vector3 WallNormal;
  49.  
  50.     public enum MovementControlType { Normal, Climbing };
  51.     [SerializeField]
  52.      MovementControlType movementControlType;
  53.  
  54.     // Use this for initialization
  55.     void Start()
  56.     {
  57.         rb = GetComponent<Rigidbody>();
  58.         anim = GetComponent<Animator>();
  59.     }
  60.  
  61.     private void Update()
  62.     {
  63.         // reset movement
  64.         moveDirection = Vector3.zero;
  65.         // get vertical and horizontal movement input (controller and WASD/ Arrow Keys)
  66.         vertical = Input.GetAxis("Vertical");
  67.         horizontal = Input.GetAxis("Horizontal");
  68.  
  69.         jump_input_down = Input.GetKeyDown(KeyCode.Space);
  70.         drop_input_down = Input.GetKeyDown(KeyCode.S);
  71.  
  72.      
  73.        
  74.         // base movement on camera
  75.         Vector3 correctedVertical = vertical * Camera.main.transform.forward;
  76.         Vector3 correctedHorizontal = horizontal * Camera.main.transform.right;
  77.  
  78.         Vector3 combinedInput = correctedHorizontal + correctedVertical;
  79.  
  80.         // make sure the input doesnt go negative or above 1;
  81.         float inputMagnitude = Mathf.Abs(horizontal) + Mathf.Abs(vertical);
  82.         inputAmount = Mathf.Clamp01(inputMagnitude);
  83.  
  84.         moveDirection = new Vector3((combinedInput).normalized.x, 0, (combinedInput).normalized.z);
  85.  
  86.  
  87.         if (jump_input_down)
  88.         {
  89.             Jump();
  90.         }
  91.  
  92.         // if hanging and cancel input is pressed, back to normal movement, and stop hanging
  93.         if(drop_input_down && GrabLedge)
  94.         {
  95.             CancelHanging();
  96.         }
  97.         // handle animation blendtree for walking
  98.         anim.SetFloat("Velocity", inputAmount, 0.2f, Time.deltaTime);
  99.         anim.SetFloat("SlopeNormal", slopeAmount, 0.2f, Time.deltaTime);    
  100.     }
  101.  
  102.  
  103.     private void FixedUpdate()
  104.     {
  105.         // if not grounded , increase down force
  106.         if (!IsGrounded() || slopeAmount >= 0.1f && !GrabLedge)// if going down, also apply, to stop bouncing, dont move down when grabbing onto ledge
  107.         {
  108.              gravity += Vector3.up * Physics.gravity.y * jumpFalloff * Time.fixedDeltaTime;
  109.         }
  110.  
  111.         switch (movementControlType)
  112.         {
  113.             case MovementControlType.Normal:
  114.              
  115.                 // normal movement
  116.                
  117.  
  118.                 // rotate player to movement direction
  119.                 Quaternion rot = Quaternion.LookRotation(moveDirection);
  120.                 Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rot, Time.fixedDeltaTime * inputAmount * rotateSpeed);
  121.                 transform.rotation = targetRotation;
  122.                 break;
  123.  
  124.             case MovementControlType.Climbing:
  125.                 // movement for climbing, going up and down/ left and right instead of forwards and sideways like the normal movement
  126.                 moveDirection = new Vector3(horizontal * 0.2f * inputAmount * transform.forward.z, vertical * 0.3f * inputAmount, -horizontal * 0.2f * inputAmount * transform.forward.x) + (transform.forward * 0.2f);
  127.  
  128.                 // if we are hanging on a ledge, dont move up or down
  129.                 if (GrabLedge)
  130.                 {
  131.                     moveDirection.y = 0f;
  132.                 }
  133.                // no gravity when climbing
  134.                 gravity = Vector3.zero;
  135.              
  136.                  // rotate towards the wall while moving, so you always face the wall even when its curved
  137.                 Vector3 targetDir = -WallNormal;
  138.                 targetDir.y = 0;
  139.                 if (targetDir == Vector3.zero)
  140.                 {
  141.                     targetDir = transform.forward;
  142.                 }
  143.                 Quaternion tr = Quaternion.LookRotation(targetDir);
  144.                 transform.rotation = Quaternion.Slerp(transform.rotation, tr, Time.fixedDeltaTime * inputAmount * rotateSpeed);
  145.                 break;
  146.         }
  147.  
  148.         rb.velocity = (moveDirection * GetMoveSpeed() * inputAmount) + gravity;
  149.  
  150.         // find the Y position via raycasts
  151.         floorMovement = new Vector3(rb.position.x, FindFloor().y + floorOffsetY, rb.position.z);
  152.  
  153.         // only stick to floor when grounded
  154.         if (floorMovement != rb.position && IsGrounded() && rb.velocity.y <= 0)
  155.         {
  156.             // move the rigidbody to the floor
  157.             rb.MovePosition(floorMovement);
  158.             gravity = Vector3.zero;
  159.             movementControlType = MovementControlType.Normal;
  160.             GrabLedge = false;
  161.         }
  162.  
  163.         // ledge grab only when not on ground
  164.         if (!IsGrounded())
  165.         {
  166.             LedgeGrab();
  167.            
  168.         }
  169.  
  170.         velocity = rb.velocity;
  171.     }
  172.  
  173.     Vector3 FindFloor()
  174.     {
  175.         // width of raycasts around the centre of your character
  176.         float raycastWidth = 0.25f;
  177.         // check floor on 5 raycasts   , get the average when not Vector3.zero  
  178.         int floorAverage = 1;
  179.  
  180.         CombinedRaycast = FloorRaycasts(0, 0, 1.6f);
  181.         floorAverage += (getFloorAverage(raycastWidth, 0) + getFloorAverage(-raycastWidth, 0) + getFloorAverage(0, raycastWidth) + getFloorAverage(0, -raycastWidth));
  182.  
  183.         return CombinedRaycast / floorAverage;
  184.     }
  185.  
  186.     // only add to average floor position if its not Vector3.zero
  187.     int getFloorAverage(float offsetx, float offsetz)
  188.     {
  189.  
  190.         if (FloorRaycasts(offsetx, offsetz, 1.6f) != Vector3.zero)
  191.         {
  192.             CombinedRaycast += FloorRaycasts(offsetx, offsetz, 1.6f);
  193.             return 1;
  194.         }
  195.         else { return 0; }
  196.     }
  197.  
  198.     public bool IsGrounded()
  199.     {
  200.         if (FloorRaycasts(0, 0, 0.6f) != Vector3.zero)
  201.         {
  202.             slopeAmount = Vector3.Dot(transform.forward, floorNormal);
  203.             return true;
  204.         }
  205.         else
  206.         {
  207.             return false;
  208.         }
  209.     }
  210.  
  211.  
  212.     Vector3 FloorRaycasts(float offsetx, float offsetz, float raycastLength)
  213.     {
  214.         RaycastHit hit;
  215.         // move raycast
  216.         raycastFloorPos = transform.TransformPoint(0 + offsetx, 0 + 0.5f, 0 + offsetz);
  217.  
  218.         Debug.DrawRay(raycastFloorPos, Vector3.down, Color.magenta);
  219.         if (Physics.Raycast(raycastFloorPos, -Vector3.up, out hit, raycastLength))
  220.         {
  221.             floorNormal = hit.normal;
  222.  
  223.             if (Vector3.Angle(floorNormal, Vector3.up) < slopeLimit)
  224.             {
  225.                 return hit.point;
  226.             }
  227.             else return Vector3.zero;
  228.         }
  229.         else return Vector3.zero;
  230.     }
  231.  
  232.     float GetMoveSpeed()
  233.     {
  234.         // you can add a run here, if run button : currentMovespeed = runSpeed;
  235.         float currentMovespeed = Mathf.Clamp(moveSpeed + (slopeAmount * slopeInfluence), 0, moveSpeed + 1);
  236.         return currentMovespeed;
  237.     }
  238.  
  239.     void Jump()
  240.     {
  241.         if (IsGrounded())
  242.         {
  243.             gravity.y = jumpPower;
  244.             anim.SetTrigger("Jumping");
  245.         }
  246.  
  247.         if (safeForClimbUp && anim.GetCurrentAnimatorStateInfo(0).IsName("Hanging"))
  248.         {
  249.             anim.SetTrigger("ClimbUp");
  250.         }
  251.     }
  252.  
  253.     public void CancelHanging()
  254.     {
  255.         movementControlType = MovementControlType.Normal;
  256.         GrabLedge = false;
  257.         anim.SetTrigger("StopHanging");
  258.     }
  259.  
  260.     public void GrabLedgePos(Vector3 ledgePos)
  261.     {
  262.         // set hanging animation trigger
  263.        anim.SetTrigger("Hanging");
  264.        anim.ResetTrigger("StopHanging");
  265.        LedgePos = ledgePos;
  266.        GrabLedge = true;
  267.        // set movement type for climbing
  268.        movementControlType = MovementControlType.Climbing;
  269.  
  270.     }
  271.  
  272.     void LedgeGrab()
  273.     {
  274.         if (anim.GetCurrentAnimatorStateInfo(0).IsName("Climbup"))
  275.         {
  276.             transform.position = Vector3.Lerp(transform.position, LedgePos + (transform.forward * 0.4f), Time.deltaTime * 5f);        
  277.         }
  278.  
  279.         if (anim.GetCurrentAnimatorStateInfo(0).IsName("To Hang"))
  280.         {
  281.             // lower position for hanging
  282.             Vector3 LedgeTopPosition = new Vector3(LedgePos.x, LedgePos.y - characterHangOffset, LedgePos.z);
  283.          
  284.             // lerp the position
  285.             transform.position = Vector3.Lerp(transform.position, LedgeTopPosition, Time.deltaTime * 5f);
  286.             // rotate to the wall
  287.             Quaternion rotateToWall = Quaternion.LookRotation(-WallNormal);
  288.             Quaternion targetRotation = Quaternion.Slerp(transform.rotation, rotateToWall, Time.deltaTime * rotateSpeed);
  289.             transform.rotation = targetRotation;          
  290.         }
  291.     }
  292. }
Add Comment
Please, Sign In to add comment