Guest User

CharacterMovement.cs

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