File size: 4,056 Bytes
c80142e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(CharacterController))]
public class FirstPersonController : MonoBehaviour
{
    [Header("Player")]
    public float moveSpeed = 4.0f;
    public float sprintSpeed = 6.0f;
    public float crouchSpeed = 2.0f;
    public float jumpHeight = 1.2f;
    public float gravity = -15.0f;

    [Header("Camera")]
    public Transform cameraTransform;
    public float cameraSensitivity = 1.0f;
    public float maxCameraAngle = 85f;

    [Header("Ground Check")]
    public float groundCheckDistance = 0.4f;
    public float groundCheckRadius = 0.3f;
    public LayerMask groundLayer;
    public bool isGrounded;

    private float _fallTimeoutDelta;
    private float _jumpTimeoutDelta;
    private const float _terminalVelocity = 53.0f;

    [Space(10)]
    public float JumpTimeout = 0.1f;
    public float FallTimeout = 0.15f;

    private CharacterController controller;
    private StarterAssetsInputs input;

    private Vector3 velocity;
    private float cameraPitch = 0f;
    bool canMove = true;

    private void Awake()
    {
        controller = GetComponent<CharacterController>();
        input = GetComponent<StarterAssetsInputs>();
    }

    void Start()
    {
        _jumpTimeoutDelta = JumpTimeout;
        _fallTimeoutDelta = FallTimeout;
    }

    private void OnDrawGizmos()
    {
        if (!Application.isPlaying) return;

        Gizmos.color = isGrounded ? Color.green : Color.red;

        Vector3 checkPosition = transform.position + Vector3.down * (controller.height / 2f) + controller.center;
        Gizmos.DrawWireSphere(checkPosition, groundCheckRadius);
    }

    private void Update()
    {
        GroundedCheck();
        JumpAndGravity();
        if (!canMove)
            return;
        Move();
    }

    private void LateUpdate()
    {
        CameraRotation();
    }

    private void GroundedCheck()
    {
        Vector3 spherePosition = transform.position + Vector3.down * (controller.height / 2f) + controller.center;
        isGrounded = Physics.CheckSphere(spherePosition, groundCheckRadius, groundLayer, QueryTriggerInteraction.Ignore);
    }

    private void JumpAndGravity()
    {
        if (isGrounded)
        {
            _fallTimeoutDelta = FallTimeout;

            if (velocity.y < 0.0f)
            {
                velocity.y = -2f;
            }

            if (input.jump && _jumpTimeoutDelta <= 0.0f)
            {
                velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
                _jumpTimeoutDelta = JumpTimeout;
                input.jump = false; 
            }
        }
        else
        {
            _fallTimeoutDelta -= Time.deltaTime;
        }

        if (_jumpTimeoutDelta >= 0.0f)
        {
            _jumpTimeoutDelta -= Time.deltaTime;
        }

        velocity.y = Mathf.Max(velocity.y + gravity * Time.deltaTime, -_terminalVelocity);

        controller.Move(velocity * Time.deltaTime);
    }


    private void Move()
    {
        float speed = input.sprint ? sprintSpeed : (input.crouch ? crouchSpeed : moveSpeed);

        Vector3 move = (transform.right * input.move.x + transform.forward * input.move.y).normalized;
        controller.Move(move * speed * Time.deltaTime);
    }

    private void CameraRotation()
    {
        if (input.look.sqrMagnitude >= 0.01f)
        {
            float mouseX = input.look.x * cameraSensitivity * Time.deltaTime;
            float mouseY = input.look.y * cameraSensitivity * Time.deltaTime;

            cameraPitch -= mouseY;
            cameraPitch = Mathf.Clamp(cameraPitch, -maxCameraAngle, maxCameraAngle);
            cameraTransform.localRotation = Quaternion.Euler(cameraPitch, 0f, 0f);

            transform.Rotate(Vector3.up * mouseX);
        }
    }

    public void UnlockMove(bool value) => canMove = value;
}