Advertisement
Guest User

PlayerMovement

a guest
Jan 25th, 2022
41
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System.Collections;
  2. using UnityEngine;
  3.  
  4. public class PlayerMovement : MonoBehaviour
  5. {
  6.     #region keymaps and assigns
  7.  
  8.     // Private assigns (initialized in Start())
  9.     private CharacterController controller;
  10.  
  11.     // Public assigns (need to be assigned in inspector)
  12.     [Header("Assignables")]
  13.     public Camera cam;
  14.     public LayerMask groundLayer;
  15.     public Transform playerTop;
  16.     public Transform playerBottom;
  17.  
  18.     // Keymaps (offers the ability to change controls)
  19.     [Header("Input")]
  20.     public KeyCode forward = KeyCode.W;
  21.     public KeyCode left = KeyCode.A;
  22.     public KeyCode backward = KeyCode.S;
  23.     public KeyCode right = KeyCode.D;
  24.     public KeyCode walkOrRunModifier = KeyCode.LeftShift;
  25.     public KeyCode jump = KeyCode.Space;
  26.     public KeyCode crouch = KeyCode.LeftControl;
  27.  
  28.     // Particle Systems (optional perticle systems for certain things)
  29.     public ParticleSystemInitializer landing;
  30.     [Range(1f, 20f)] public float landingSpeedRequirement = 11f;
  31.  
  32.     #endregion
  33.  
  34.     // Initialization methods and assigns
  35.     private void Start()
  36.     {
  37.         controller = gameObject.GetComponent<CharacterController>();
  38.  
  39.         CrouchInit();
  40.     }
  41.  
  42.     // Updating
  43.     void Update()
  44.     {
  45.         UpdateMovementAxes();
  46.         Move();
  47.         Crouch();
  48.         Interpolate();
  49.         Slide();
  50.     }
  51.  
  52.     #region camera movement interpolation
  53.  
  54.     [Header("Camera Interpolation")]
  55.     public Transform newCameraPos;
  56.     [Range(5, 65)] public int cameraMoveTime = 20;
  57.  
  58.     private void Interpolate()
  59.     {
  60.         cam.transform.position = Vector3.Lerp(cam.transform.position, newCameraPos.position, cameraMoveTime * Time.deltaTime);
  61.     }
  62.  
  63.     #endregion
  64.  
  65.     #region core
  66.  
  67.     // Public vars
  68.     [Header("Movement")]
  69.     [Range(1f, 50f)] public float runSpeed = 12f;
  70.     [Range(1f, 50f)] public float walkSpeed = 9f;
  71.     public bool runOrWalkDefault = true;
  72.     [Range(1, 100)] public int crouchSpeedPercentage = 55;
  73.     [Range(0.1f, 15f)] public float jumpHeight = 3f;
  74.     [Range(0.01f, 1f)] public float minCamToCeilingDistance = 0.3f;
  75.     [Range(0f, -50f)] public float gravity = -19.62f;
  76.     public Transform groundCheck;
  77.     [Range(0.1f, 1f)] public float groundDistance = 0.4f;
  78.     public bool canHoldJump = true;
  79.     public bool canDoubleJump = true;
  80.  
  81.     // Private vars that update each frame
  82.     private float x, z;
  83.     private Vector3 move;
  84.     private Vector3 velocity;
  85.     private bool isGrounded;
  86.     private bool doubleJumpIsReady;
  87.     private bool wasGrounded = true;
  88.  
  89.     // Moving the player in 3D space
  90.     private void Move()
  91.     {
  92.         // Moving on X and Z
  93.         move = transform.right * x + transform.forward * z;
  94.  
  95.         MovePlayer();
  96.  
  97.         // Ground check
  98.         isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundLayer);
  99.  
  100.         // Detect if we landed and if we did start the landing particle system
  101.         if ((!wasGrounded && isGrounded) && landing.system != null && Mathf.Abs(velocity.y) > landingSpeedRequirement)
  102.         {
  103.             StartParticleSystem(landing, playerBottom.position);
  104.         }
  105.  
  106.         // Reset Y velocity
  107.         if (isGrounded && velocity.y < 0f)
  108.         {
  109.             velocity.y = -2;
  110.         }
  111.  
  112.         // Jumping
  113.         Jump();
  114.  
  115.         // Moving on Y (gravity)
  116.         velocity.y += gravity * Time.deltaTime;
  117.  
  118.         // If we hit the ceiling, flip the y velocity
  119.         if (IsTouchingCeiling())
  120.         {
  121.             velocity = new Vector3(0f, -Mathf.Abs(velocity.y), 0f);
  122.         }
  123.  
  124.         controller.Move(velocity * Time.deltaTime);
  125.  
  126.         wasGrounded = isGrounded;
  127.     }
  128.  
  129.     // For moving the player around on the x and z axes, weather it be running or walking
  130.     private void MovePlayer()
  131.     {
  132.         float crouchSpeed = runSpeed * (crouchSpeedPercentage * 0.01f);
  133.  
  134.         // We are crouching, apply the crouch speed
  135.         if (isCrouching) { controller.Move(move * crouchSpeed * Time.deltaTime); }
  136.  
  137.         // Running is our default
  138.         else if (runOrWalkDefault)
  139.         {
  140.             // We are holding down the modifier key, so we apply the walking speed
  141.             if (Input.GetKey(walkOrRunModifier)) { controller.Move(move * walkSpeed * Time.deltaTime); }
  142.  
  143.             // We aren't holding down the modifier key, so apply the running speed
  144.             else { controller.Move(move * runSpeed * Time.deltaTime); }
  145.         }
  146.  
  147.         // Walking is our default
  148.         else
  149.         {
  150.             // We are holding down the modifier key, so we apply the running speed
  151.             if (Input.GetKey(walkOrRunModifier)) { controller.Move(move * runSpeed * Time.deltaTime); }
  152.  
  153.             // We aren't holding down the modifier key, so apply the walking speed
  154.             else { controller.Move(move * walkSpeed * Time.deltaTime); }
  155.         }
  156.     }
  157.  
  158.     // Making the player jump
  159.     private void Jump()
  160.     {
  161.         // Double jumping
  162.         if (canDoubleJump)
  163.         {
  164.             // Resetting the double jump
  165.             if (isGrounded)
  166.             {
  167.                 doubleJumpIsReady = true;
  168.             }
  169.  
  170.             // Normal jumping
  171.             if (isGrounded && !isCrouching /* We don't want to jump while crouching */)
  172.             {
  173.                 // We can hold down the jump button
  174.                 if (canHoldJump && Input.GetKey(jump))
  175.                 {
  176.                     velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
  177.                 }
  178.  
  179.                 // We can't hold down the jump button
  180.                 else if (!canHoldJump && Input.GetKeyDown(jump))
  181.                 {
  182.                     velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
  183.                 }
  184.             }
  185.  
  186.             // Double jumping
  187.             else if (!isGrounded && doubleJumpIsReady)
  188.             {
  189.                 if (Input.GetKeyDown(jump))
  190.                 {
  191.                     velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
  192.                     doubleJumpIsReady = false;
  193.                 }
  194.             }
  195.         }
  196.  
  197.         // Normal jumping
  198.         else
  199.         {
  200.             if (isGrounded && !isCrouching /* We don't want to jump while crouching */)
  201.             {
  202.                 // We can hold down the jump button
  203.                 if (canHoldJump && Input.GetKey(jump))
  204.                 {
  205.                     velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
  206.                 }
  207.  
  208.                 // We can't hold down the jump button
  209.                 else if (!canHoldJump && Input.GetKeyDown(jump))
  210.                 {
  211.                     velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
  212.                 }
  213.             }
  214.         }
  215.     }
  216.  
  217.     // Check if the player's head hits the ceiling
  218.     private bool IsTouchingCeiling()
  219.     {
  220.         if (Physics.Raycast(cam.transform.position, Vector3.up, minCamToCeilingDistance, groundLayer)) { return true; }
  221.         else { return false; }
  222.     }
  223.  
  224.     // Updating axes (used as an alternative to Input.GetAxis("Horizontal") and Input.GetAxis("Vertical"))
  225.     private void UpdateMovementAxes()
  226.     {
  227.         x = 0f; z = 0f;
  228.  
  229.         if (Input.GetKey(forward)) { z++; }
  230.         if (Input.GetKey(backward)) { z--; }
  231.         if (Input.GetKey(right)) { x++; }
  232.         if (Input.GetKey(left)) { x--; }
  233.     }
  234.  
  235.     #endregion
  236.  
  237.     #region crouching
  238.  
  239.     // Public vars
  240.     [Range(0.1f, 10f)] public float cameraMoveDistance = 1.05f;
  241.     public Transform normalCamPos;
  242.     public Vector3 crouchedControllerCenter = new Vector3(0f, -0.62f, 0f);
  243.     [Range(1f, 15f)] public float crouchedControllerHeight = 2.5f;
  244.  
  245.     // Private initialization variables
  246.     private Vector3 unCrouchedControllerCenter;
  247.     private float unCrouchedControllerHeight;
  248.     private bool isCrouching;
  249.  
  250.     // Initialization
  251.     private void CrouchInit()
  252.     {
  253.         unCrouchedControllerCenter = controller.center;
  254.         unCrouchedControllerHeight = controller.height;
  255.     }
  256.  
  257.     // Check if we are crouching or uncrouching
  258.     private void Crouch()
  259.     {
  260.         // We are starting a crouch
  261.         if (Input.GetKeyDown(crouch))
  262.         {
  263.             isCrouching = true;
  264.  
  265.             // Move camera down
  266.             Vector3 newCameraPosition = new Vector3(
  267.                 cam.transform.position.x,
  268.                 normalCamPos.position.y - cameraMoveDistance,
  269.                 cam.transform.position.z);
  270.  
  271.             newCameraPos.position = newCameraPosition;
  272.  
  273.             // Update CharacterController
  274.             UpdateController(crouchedControllerCenter, crouchedControllerHeight);
  275.         }
  276.  
  277.         // We are currently crouching
  278.         else if (Input.GetKey(crouch))
  279.         {
  280.             isCrouching = true;
  281.  
  282.             // Keep camera down
  283.             Vector3 newCameraPosition = new Vector3(
  284.                 cam.transform.position.x,
  285.                 normalCamPos.position.y - cameraMoveDistance,
  286.                 cam.transform.position.z);
  287.  
  288.             newCameraPos.position = newCameraPosition;
  289.         }
  290.  
  291.         // We are uncroucing
  292.         else if (Input.GetKeyUp(crouch))
  293.         {
  294.             StartCoroutine(TryUncrouch());
  295.         }
  296.     }
  297.  
  298.     // Coroutine we call to try to uncrouch the player
  299.     private IEnumerator TryUncrouch()
  300.     {
  301.         // If there is something between the top of the camera and the top of what would be the uncrouched player,
  302.         // We disable crouching again, and check if there is nothing there next frame
  303.         if (Physics.Linecast(cam.transform.position, playerTop.position, groundLayer))
  304.         {
  305.             // Waits one frame and runs this coroutine again
  306.             if (!Physics.Raycast(cam.transform.position, Vector3.up, minCamToCeilingDistance, groundLayer))
  307.             {
  308.                 newCameraPos.position = new Vector3(cam.transform.position.x, cam.transform.position.y + minCamToCeilingDistance, cam.transform.position.z);
  309.             }
  310.  
  311.             yield return new WaitForSeconds(0f);
  312.             StartCoroutine(TryUncrouch());
  313.         }
  314.         // We are free to uncrouch, nothing in the way
  315.         else
  316.         {
  317.             isCrouching = false;
  318.  
  319.             // Reset camera position
  320.             Vector3 newCameraPosition = new Vector3(
  321.                 cam.transform.position.x,
  322.                 normalCamPos.position.y,
  323.                 cam.transform.position.z);
  324.  
  325.             newCameraPos.position = newCameraPosition;
  326.  
  327.             // Update CharacterController
  328.             UpdateController(unCrouchedControllerCenter, unCrouchedControllerHeight);
  329.         }
  330.     }
  331.  
  332.     // Called to update the height and center of the character controller
  333.     private void UpdateController(Vector3 newCenter, float newHeight)
  334.     {
  335.         controller.center = newCenter;
  336.         controller.height = newHeight;
  337.     }
  338.  
  339.     #endregion
  340.  
  341.     #region sliding
  342.  
  343.     [Range(1f, 20f)] public float slideSpeed = 8f;
  344.     private Vector3 hitPointNormal;
  345.     private float slideVelocity = 1f;
  346.  
  347.     // Used to tell if we can / are forced to slide
  348.     private bool isSliding
  349.     {
  350.         get
  351.         {
  352.             // If we are crouching and touching the ground
  353.             if (isCrouching)
  354.             {
  355.                 if (isGrounded)
  356.                 {
  357.                     // Then we check if the ground is not flat, but angled
  358.                     RaycastHit hit;
  359.                     if (Physics.Raycast(groundCheck.position, Vector3.down, out hit, groundDistance, groundLayer) || slideVelocity > 1)
  360.                     {
  361.                         hitPointNormal = hit.normal;
  362.                         return Vector3.Angle(hitPointNormal, Vector3.up) != 0;
  363.                     }
  364.                 }
  365.             }
  366.  
  367.             return false;
  368.         }
  369.     }
  370.     private bool wasSliding;
  371.  
  372.     // Method used for sliding
  373.     private void Slide()
  374.     {
  375.         // If we are allowed and/or forced to slide
  376.         if (isSliding)
  377.         {
  378.             // Increase our slide velocity over time
  379.             if (wasSliding)
  380.             {
  381.                 slideVelocity += 0.1f;
  382.             }
  383.  
  384.             // Move the player accordingly
  385.             Vector3 move = new Vector3(hitPointNormal.x, -hitPointNormal.y, hitPointNormal.z) * slideSpeed * slideVelocity;
  386.             controller.Move(move * Time.deltaTime);
  387.  
  388.             // Confirm we were sliding this frame
  389.             wasSliding = true;
  390.         }
  391.         // If we are not supposed to slide, reset everything
  392.         else
  393.         {
  394.             slideVelocity = 0f;
  395.             wasSliding = false;
  396.         }
  397.     }
  398.  
  399.     #endregion
  400.  
  401.     #region particle systems
  402.  
  403.     [System.Serializable]
  404.     public class ParticleSystemInitializer
  405.     {
  406.         // Vars
  407.         [SerializeField] public GameObject system;
  408.         [SerializeField] public float duration;
  409.  
  410.         // Constructor
  411.         public ParticleSystemInitializer(GameObject _system, float _duration)
  412.         {
  413.             system = _system;
  414.             duration = _duration;
  415.         }
  416.     }
  417.  
  418.     // Generating the particle system
  419.     private void StartParticleSystem(ParticleSystemInitializer manager, Vector3 loc)
  420.     {
  421.         // Init
  422.         GameObject system = manager.system;
  423.         float duration = manager.duration;
  424.  
  425.         // Instantiating the particle system
  426.         GameObject sys = Instantiate(system, loc, Quaternion.identity);
  427.  
  428.         // Destroying it afterwards
  429.         Destroy(sys, duration);
  430.     }
  431.  
  432.     #endregion
  433. }
Advertisement
RAW Paste Data Copied
Advertisement