예제 #1
0
    public void Tick(float dt)
    {
        Cursor.lockState = CursorLockMode.Locked; // Keep doing this. We don't want cursor anywhere just yet

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

        #region No clip
#if CHEATS_ENABLED
        if (Input.GetKeyDown(KeyCode.RightAlt))
        {
            _noClipMove = !_noClipMove;
        }

        if (Input.GetMouseButtonDown(2))
        {
            _velocity = _velocity.normalized * 20;
        }
#endif
        if (_noClipMove)
        {
            float y = 0;
            if (Input.GetKey(KeyCode.Space))
            {
                y = 1;
            }
            else if (Input.GetKey(KeyCode.LeftControl))
            {
                y = -1;
            }
            moveInput.y         = y;
            transform.position += _camTransform.TransformDirection(moveInput) * NoClipSpeed * Time.deltaTime;
            _velocity           = Vector3.zero;

            return;
        }
        #endregion

        IsWalking = Input.GetKey(KeyCode.LeftShift);

        // MOVEMENT
        var wishDir = _camTransform.TransformDirectionHorizontal(moveInput); // We want to go in this direction
        _wishDirDebug = wishDir.ToHorizontal();
        var isGrounded = IsGrounded(out Vector3 groundNormal);

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

            var speedLimit = IsWalking ? WalkSpeed : MaxSpeedAlongOneDimension;
            Accelerate(ref _velocity, wishDir, GroundAccelerationCoeff, speedLimit, dt);

            // Crop up horizontal velocity component
            _velocity = Vector3.ProjectOnPlane(_velocity, groundNormal);
            if (_isGonnaJump)
            {
                // Jump away
                _velocity += Gravity.Up * JumpStrength;
                _sfx.Jump();
            }
        }
        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, MaxSpeedAlongOneDimension, dt);

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

            _velocity += Gravity.Down * (GravityAmount * dt);
        }

        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);

        transform.position += collisionDisplacement;

        #region Footsteps
        if (isGrounded)
        {
            // At the moment of stopping:
            // - force play the sfx, it makes it sound more natural, humans usually stop with an extra step
            // - reset the distance, to make the footsteps ryhtym the same at start of walking every time
            if (_prevVelocity.ToHorizontal().magnitude > 0.01 && _velocity.ToHorizontal().magnitude < 0.01)
            {
                _footstepDistance = 0f;
                _sfx.Footstep();
            }

            var totalDisplacement = displacement + collisionDisplacement;
            _footstepDistance += totalDisplacement.magnitude;

            const float stepDistance = 2f; // Play a footstep after this much of travel
            if (_footstepDistance > stepDistance)
            {
                _footstepDistance = 0f;
                _sfx.Footstep();
            }
        }
        #endregion

        _isGroundedInPrevFrame = isGrounded;
        _prevVelocity          = _velocity;
    }