Esempio n. 1
0
    public void Climb(WallClimbMovement climbMovement = WallClimbMovement.Begin)
    {
        // If we are already climbing to a point, then we wait till we get to the point position
        if (_climbToPointCoroutine != null)
        {
            return;
        }

        _climbToPointCoroutine = ClimbToPointCoroutine(climbMovement);
        StartCoroutine(_climbToPointCoroutine);
    }
 override protected void _Start()
 {
     wallClimbMovement = GetComponent <WallClimbMovement>();
 }
Esempio n. 3
0
    private IEnumerator ClimbToPointCoroutine(WallClimbMovement climbMovement)
    {
        RaycastHit climbHitInfo;

        // When we start playing the climbing animation coroutine, it means that the canclim will return false for the playeranimator script.
        // It means, it's safe to resest the HasJustTriggeredClimAnimation to false. We know for a fact that the playerAnimator script won't be able to trigger another climb animation now that we have the current one playing
        _player.PlayerWallClimbAnimator.HasJustTriggeredClimAnimation = false;

        Transform climbChecker = null;

        switch (climbMovement)
        {
        case WallClimbMovement.Begin:
            climbHitInfo = _beginClimbHitInfo;
            break;

        case WallClimbMovement.Up:
            climbHitInfo = _upClimbHitInfo;
            climbChecker = _upClimbChecker;
            break;

        case WallClimbMovement.Down:
            climbHitInfo = _downClimbHitInfo;
            climbChecker = _downClimbChecker;
            break;

        case WallClimbMovement.Right:
            climbHitInfo = _rightClimbHitInfo;
            climbChecker = _rightClimbChecker;
            break;

        case WallClimbMovement.Left:
            climbHitInfo = _leftClimbHitInfo;
            climbChecker = _leftClimbChecker;
            break;

        case WallClimbMovement.AfterWallRun:
            climbHitInfo = _wallRunHitInfo;
            break;

        default:
            climbHitInfo = _beginClimbHitInfo;
            break;
        }

        _player.CharacterController.enabled = false;

        if (climbHitInfo.normal == Vector3.zero)
        {
            CancelClimb();
            yield break;
        }

        _player.transform.forward = -new Vector3(climbHitInfo.normal.x, 0, climbHitInfo.normal.z);

        float   time            = 0f;
        Vector3 initialPosition = _player.transform.position;

        while (time < _climbTime)
        {
            time += Time.deltaTime;
            float normalizedTime = time / _climbTime;

            bool reachedAnEnd = false;

            // If while climbing, the climb checker's raycast is no longer colliding with anything, it means we reached the end of what we are climbing, so we stop the climbing
            bool canStillClimb = true;
            if (climbChecker != null)
            {
                reachedAnEnd  = !Physics.Raycast(climbChecker.position, climbChecker.transform.forward, _checkForwardDistance, LayerMask.GetMask("Default", "Wood", "Gravel", "Metal", "Grass"));
                canStillClimb = !reachedAnEnd;
            }

            // If we can still climb, we need to check if the roof is inclined
            if (canStillClimb && climbChecker != null)
            {
                RaycastHit reachedEndHitInfoChecker;
                Physics.Raycast(climbChecker.position, climbChecker.transform.forward, out reachedEndHitInfoChecker, _checkForwardDistance, LayerMask.GetMask("Default", "Wood", "Gravel", "Metal", "Grass"));
                // If the normal of the next hitinfo is inclined (it's an inclined roof), then we reached an end
                if (Mathf.Abs(reachedEndHitInfoChecker.normal.y) > _maxMountableNormalYValue)
                {
                    reachedAnEnd = true;
                }
            }

            // If we haven't reached an end yet
            if (!reachedAnEnd)
            {
                Vector3 nextPosition = climbHitInfo.point + (climbHitInfo.normal * _climbOffset);

                // We need to keep the player's position aligned with the hit of his upper check (that of his hands)
                // So that we don't see his hands inside the geometry when climbing
                // We don't want to apply this behavior when we are the top of a building with an inclined roof (problems)
                // We need to test if we can actually climb up so that our _upClimbHitinfo is not set to the previous one (possibly in  far away building: as in the last building we climbing)
                bool canClimbUp = Physics.Raycast(_upClimbChecker.position, _upClimbChecker.transform.forward, out _upClimbHitInfo, _checkForwardDistance, LayerMask.GetMask("Default", "Wood", "Gravel", "Metal", "Grass"));
                if (_upClimbHitInfo.normal.y < .3f && canClimbUp)
                {
                    Vector3 currentHitPointProjectedOnPlane = Vector3.ProjectOnPlane(climbHitInfo.point, _upClimbHitInfo.normal);
                    Vector3 upClimbHitPointProjectedOnPlane = Vector3.ProjectOnPlane(_upClimbHitInfo.point, _upClimbHitInfo.normal);

                    Vector3 differenceWithUpHitInfo = currentHitPointProjectedOnPlane - upClimbHitPointProjectedOnPlane;

                    Vector3 currentHitPoint = _upClimbHitInfo.point + differenceWithUpHitInfo;

                    nextPosition = currentHitPoint + (climbHitInfo.normal * _climbOffset);
                }

                _player.transform.position = Vector3.Lerp(initialPosition, nextPosition, normalizedTime);
            }

            yield return(null);
        }

        _player.CharacterController.enabled = true;

        _climbToPointCoroutine = null;
    }