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