Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class PlayerController : MonoBehaviour
- {
- //Inputs
- public Controls controls;
- Vector2 inputNormalized;
- [SerializeField] Vector2 inputs;
- [SerializeField] float rotation;
- [SerializeField] bool run = true;
- bool jump;
- //Velocity
- Vector3 velocity;
- float gravity = -18f;
- float velocityY;
- float terminalVelocity = -25f;
- [SerializeField] float fallMult;
- //Running
- public float currentSpeed;
- public float baseSpeed = 1f;
- public float runSpeed = 4;
- public float rotateSpeed = 2f;
- //ground
- Vector3 forwardDirection;
- Vector3 collisionPoint;
- [SerializeField] float slopeAngle;
- [SerializeField] float forwardAngle;
- [SerializeField] float forwardMult;
- Ray groundRay;
- RaycastHit groundHit;
- //Jumping
- bool jumping;
- float jumpSpeed;
- float jumpHeight = 3f;
- Vector3 jumpDirection;
- //DebugGroundNormals
- public bool showGroundNormal;
- public bool showFallNormal;
- public bool showGroundRay;
- //Component References
- CharacterController controller;
- public Transform groundDirection;
- public Transform fallDirection;
- // Start is called before the first frame update
- void Start()
- {
- controller = GetComponent<CharacterController>();
- }
- // Update is called once per frame
- void Update()
- {
- GetInputs();
- Locomotion();
- }
- void Locomotion()
- {
- GroundDirection();
- //Rotating object because cannot rotate controller
- Vector3 characterRotation = transform.eulerAngles + new Vector3(0, rotation * rotateSpeed, 0);
- transform.eulerAngles = characterRotation;
- //Running and walking (remove if statement if you want to be able to control direction while falling)
- //Slope angle condition to allow for sliding
- if(controller.isGrounded && slopeAngle <= controller.slopeLimit)
- {
- inputNormalized = inputs;
- currentSpeed = baseSpeed;
- if (run)
- {
- currentSpeed *= runSpeed;
- if (inputNormalized.y < 0)
- {
- currentSpeed = currentSpeed / 2;
- }
- }
- }
- else if (!controller.isGrounded || slopeAngle > controller.slopeLimit)
- {
- inputNormalized = Vector2.Lerp(inputNormalized, Vector2.zero, 0.025f);
- currentSpeed = Mathf.Lerp(currentSpeed, 0, 0.025f);
- }
- //Press Space to Jump
- if(jump && controller.isGrounded && slopeAngle <= controller.slopeLimit)
- {
- Jump();
- }
- //Falling, apply gravity if not grounded
- if(!controller.isGrounded && velocityY > terminalVelocity)
- {
- velocityY += gravity * Time.deltaTime;
- }
- //Lerp speed below is a possible lever for adjusting fall speed on slopes
- else if(controller.isGrounded && slopeAngle > controller.slopeLimit)
- {
- velocityY = Mathf.Lerp(velocityY, terminalVelocity, 0.25f);
- }
- //Applying Inputs (only use top line if you want to control direction during jumps)
- if(!jumping)
- {
- velocity = (groundDirection.forward * inputNormalized.magnitude) * (currentSpeed * forwardMult) + fallDirection.up * (velocityY * fallMult);
- }
- else
- {
- velocity = jumpDirection * jumpSpeed + Vector3.up * velocityY;
- }
- //Moving controller
- controller.Move(velocity * Time.deltaTime);
- //Reset Velocity if grounded
- if(controller.isGrounded)
- {
- //Stop Jumping if grounded
- if(jumping == true)
- {
- jumping = false;
- }
- //Stop Gravity if grounded
- velocityY = 0;
- }
- }
- void GroundDirection()
- {
- //Creating normal from player controller position
- //Setting forward direction to controller position
- forwardDirection = transform.position;
- //Creating normal pointing in forward direction
- //Setting foward direction based on controller input
- if(inputNormalized.magnitude > 0)
- {
- forwardDirection += transform.forward * inputNormalized.y + transform.right * inputNormalized.x;
- }
- else
- {
- forwardDirection += transform.forward;
- }
- //Setting ground direction to look at the forward direction normal
- groundDirection.LookAt(forwardDirection);
- fallDirection.rotation = transform.rotation;
- //Setting Ground Ray
- groundRay.origin = transform.position + collisionPoint + Vector3.up * 0.05f;
- groundRay.direction = Vector3.down;
- if(showGroundRay)
- {
- Debug.DrawLine(groundRay.origin, groundRay.origin + Vector3.down * 0.3f, Color.red);
- }
- forwardMult = 1;
- fallMult = 1;
- if(Physics.Raycast(groundRay, out groundHit, 0.3f))
- {
- //Getting angles
- slopeAngle = Vector3.Angle(transform.up, groundHit.normal);
- forwardAngle = Vector3.Angle(groundDirection.forward, groundHit.normal) -90;
- //Slopelimit conditional to allow character to slide downhill
- if(forwardAngle < 0 && slopeAngle <= controller.slopeLimit)
- {
- //Downward slope multiplier to correct for downward speed vector shorting horizontal movement
- forwardMult = 1 / Mathf.Cos(forwardAngle * Mathf.Deg2Rad);
- //Pointing widget down if downhill, ground direction based on forward angle
- groundDirection.eulerAngles += new Vector3(-forwardAngle, 0, 0);
- }
- else if (slopeAngle > controller.slopeLimit) //fixing slope slide
- {
- float groundDistance = Vector3.Distance(groundRay.origin, groundHit.point);
- if(groundDistance <= 0.1f)
- {
- fallMult = 1 / Mathf.Cos((90 - slopeAngle) * Mathf.Deg2Rad);
- Vector3 groundCross = Vector3.Cross(groundHit.normal, Vector3.up);
- fallDirection.rotation = Quaternion.FromToRotation(transform.up, Vector3.Cross(groundCross, groundHit.normal));
- }
- }
- }
- DebugGroundNormals();
- }
- void Jump()
- {
- //Set jumping to true
- if(!jumping)
- {
- jumping = true;
- }
- //Set jumping direction and speed
- jumpDirection = (transform.forward * inputs.y + transform.right * inputs.x).normalized;
- jumpSpeed = currentSpeed;
- velocityY = Mathf.Sqrt(-gravity * jumpHeight);
- }
- void GetInputs()
- {
- //Y axis controls - Forward/Backwards
- //Forwards
- if(controls.forwards.GetControlBinding())
- {
- inputs.y = 1;
- }
- //Backwards
- if (controls.backwards.GetControlBinding())
- {
- if (controls.forwards.GetControlBinding())
- {
- inputs.y = 0;
- }
- else
- {
- inputs.y = -1;
- }
- }
- //Forward backward nothing
- if (!controls.forwards.GetControlBinding() && !controls.backwards.GetControlBinding())
- {
- inputs.y = 0;
- }
- //X axis controls - Strafe Left/Right
- //Strafe Left
- if (controls.strafeRight.GetControlBinding())
- {
- inputs.x = 1;
- }
- //Strafe Right
- if (controls.strafeLeft.GetControlBinding())
- {
- if (controls.strafeRight.GetControlBinding())
- {
- inputs.x = 0;
- }
- else
- {
- inputs.x = -1;
- }
- }
- //Strafe Left/Right Nothing
- if (!controls.strafeLeft.GetControlBinding() && !controls.strafeRight.GetControlBinding())
- {
- inputs.x = 0;
- }
- //Rotation Controls Left/Right
- if (controls.rotateRight.GetControlBinding())
- {
- rotation = 1;
- }
- if (controls.rotateLeft.GetControlBinding())
- {
- if (controls.rotateRight.GetControlBinding())
- {
- rotation = 0;
- }
- else
- {
- rotation = -1;
- }
- }
- //Rotation Nothing
- if (!controls.rotateLeft.GetControlBinding() && !controls.rotateRight.GetControlBinding())
- {
- rotation = 0;
- }
- //Toggle Run
- if(controls.walkRun.GetControlBindingDown())
- {
- run = !run;
- }
- //Jumping
- jump = controls.jump.GetControlBinding();
- }
- void DebugGroundNormals()
- {
- Vector3 lineStart = transform.position + Vector3.up * 0.05f;
- // if(showGroundNormal)
- // {
- // Debug.DrawLine(lineStart, lineStart + groundDirection.forward * 0.5f, Color.blue);
- // }
- if (showFallNormal)
- {
- Debug.DrawLine(lineStart, lineStart + fallDirection.up * 0.5f, Color.green);
- }
- }
- private void OnControllerColliderHit(ControllerColliderHit hit)
- {
- collisionPoint = hit.point;
- collisionPoint = collisionPoint - transform.position;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement