Example #1
0
    private void Update()
    {
        Cursor.lockState = CursorLockMode.Locked; // Keep doing this. We don't want cursor anywhere just yet

        var dt = Time.deltaTime;

        // We use GetAxisRaw, since we need it to feel as responsive as possible
        _moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;

        if (Input.GetKeyDown(KeyCode.Space) && !_isGonnaJump)
        {
            _isGonnaJump = true;
        }
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            _isGonnaJump = false;
        }

        MouseLook(ref _pitch, dt, _isInverted);
        _transform.rotation *= Quaternion.Euler(Input.GetAxis("Mouse X") * Sensitivity * dt * Vector3.up);
        if (Input.GetKeyDown(KeyCode.I))
        {
            _isInverted = !_isInverted;
        }

        _fov.ExternalUpdate(_velocity);
        _hook.ExternalUpdate(dt, _transform.position);

        // Reset player -- makes testing much easier
        if (Input.GetKeyDown(KeyCode.R))
        {
            _transform.position = new Vector3(0, 5, 0);
            _velocity           = Vector3.forward;
            _hook.ResetHook();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////// MOVEMENT ///////////////////////////////////////////////
        var wishDir = _camFollow.TransformDirectionHorizontal(_moveInput); // We want to go in this direction

        _wishDirDebug = wishDir.ToHorizontal();

        Vector3 groundNormal;
        var     isGrounded = IsGrounded(out groundNormal);

        _footsteps.ExternalUpdate(_isGonnaJump, isGrounded, isGrounded && !_isGroundedInPrevFrame);

        if (isGrounded) // Ground move
        {
            // Don't apply friction if just landed or about to jump
            if (_isGroundedInPrevFrame && !_isGonnaJump)
            {
                ApplyFriction(ref _velocity, dt);
            }

            Accelerate(ref _velocity, wishDir, GroundAccelerationCoeff, dt);

            // Crop up horizontal velocity component
            _velocity = Vector3.ProjectOnPlane(_velocity, groundNormal);
            if (_isGonnaJump)
            {
                // Jump away
                _velocity += Vector3.up * JumpStrength;
            }
        }
        else // Air move
        {
            // If the input doesn't have the same facing with the current velocity
            // then slow down instead of speeding up
            var coeff = Vector3.Dot(_velocity, wishDir) > 0 ? AirAccelCoeff : AirDecelCoeff;

            Accelerate(ref _velocity, wishDir, coeff, dt);

            if (Mathf.Abs(_moveInput.z) > 0.0001) // Pure side velocity doesn't allow air control
            {
                ApplyAirControl(ref _velocity, wishDir, dt);
            }

            _velocity += Vector3.down * (GravityAmount * dt);
        }
        _hook.ApplyHookAcceleration(ref _velocity, _transform, _moveInput);

        var displacement = _velocity * dt;

        // If we're moving too fast, make sure we don't hollow through any collider
        if (displacement.magnitude > _collisionVolume.radius)
        {
            ClampDisplacement(ref _velocity, ref displacement, _transform.position);
        }
        _transform.position += displacement;

        var collisionDisplacement = ResolveCollisions(ref _velocity);

        _hook.ApplyHookDisplacement(ref _velocity, ref collisionDisplacement, _transform.position - Vector3.up * 0.4f);
        _transform.position   += collisionDisplacement;
        _isGroundedInPrevFrame = isGrounded;

        _hook.Draw();

        _animator.SetBool("OnGround", isGrounded);
        _animator.SetFloat("Forward", Mathf.Lerp(0, 1, _velocity.WithY(0).magnitude / MaxSpeedAlongOneDimension));
        _animator.SetFloat("Turn", Mathf.Clamp(_moveInput.x, -0.4f, 0.4f));
        _animator.SetFloat("JumpLeg", _moveInput.x);

        _animator.SetFloat("Jump", Mathf.Lerp(-5, 5, Lerp(_velocity.y, -8f, 8f)));
    }