/// <summary> /// The ability has stopped running. /// </summary> protected override void AbilityStopped() { m_ClimbID = ClimbID.None; base.AbilityStopped(); // Reset the variables m_AcceptInput = m_Transitioning = m_Mounted = false; EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorClimbDismount", OnDismount); m_Controller.ForceRootMotion = false; m_Controller.Grounded = true; m_Rigidbody.isKinematic = false; m_AnimatorMonitor.DetermineStates(); // Reenable the collisions between the character and the climbable object. var climbableColliders = m_ClimbableObject.GetComponentsInChildren <Collider>(); for (int i = 0; i < climbableColliders.Length; ++i) { if (climbableColliders[i].enabled) { LayerManager.RevertCollision(climbableColliders[i]); } } }
/// <summary> /// The character has arrived at the target position and the ability can start. /// </summary> private void InPosition() { m_ClimbID = m_ClimbableObject.TopMount() ? ClimbID.MountTop : ClimbID.MountBottom; m_AnimatorMonitor.SetStateValue((int)m_ClimbID); m_AnimatorMonitor.DetermineStates(); #if UNITY_EDITOR || DLL_RELEASE || !UNITY_WEBPLAYER m_MountDistance = Vector3.zero; m_MountStartTime = -1; #endif EventHandler.RegisterEvent(m_GameObject, "OnAnimatorClimbMount", OnMount); }
/// <summary> /// Start the dismounting animation from the climbable object. /// </summary> /// <param name="moveType">The type of movement that caused the dismount.</param> private void StartDismount(ClimbableObject.MoveType moveType) { EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorClimbStateComplete", OnClimbStateComplete); EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorClimbTransitionComplete", OnClimbTransitionComplete); EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorClimbAutomaticMount", OnClimbAutomaticMount); EventHandler.RegisterEvent(m_GameObject, "OnAnimatorClimbDismount", OnDismount); // The character is no longer mounted. m_Mounted = false; // Determine the type of dismount. Vines and pipes are easy to determine how to dismount. if (m_ClimbableObject.Type == ClimbableObject.ClimbableType.Vine || m_ClimbableObject.Type == ClimbableObject.ClimbableType.Pipe) { if (moveType == ClimbableObject.MoveType.Up) { m_ClimbID = ClimbID.DismountTop; } else { m_ClimbID = ClimbID.DismountBottom; } } else { // Ladders require more work to determine the correct dismount animation because the character can start to dismount off of either foot. if (m_ClimbID == ClimbID.ClimbUp || m_ClimbID == ClimbID.ClimbRightUp || m_ClimbID == ClimbID.ClimbLeftUp) { if (m_RightFootUp) { m_ClimbID = ClimbID.DismountTopRight; } else { m_ClimbID = ClimbID.DismountTopLeft; } } else { if (m_RightFootUp) { m_ClimbID = ClimbID.DismountBottomLeft; } else { m_ClimbID = ClimbID.DismountBottomRight; } } } // Start the dismount animation. m_AnimatorMonitor.DetermineStates(); }
/// <summary> /// The mount animation is done playing. /// </summary> private void OnMount() { m_AcceptInput = true; m_Mounted = true; m_RightFootUp = false; #if UNITY_EDITOR || DLL_RELEASE || !UNITY_WEBPLAYER m_MountDistance = Vector3.zero; #endif if (m_ClimbableObject.Type == ClimbableObject.ClimbableType.Vine) { m_ClimbID = ClimbID.ClimbVine; m_AnimatorMonitor.DetermineStates(); } EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorClimbMount", OnMount); }
/// <summary> /// The character should start to transition between a vertical and horizontal climb. /// </summary> private void StartTransition() { // The character should toggle between a vertical and horizontal transition. if (m_Vertical) { if (m_RightTransition = m_ClimbableObject.ShouldTransitionRight()) { m_ClimbID = ClimbID.VerticalHorizontalRightTransition; } else { m_ClimbID = ClimbID.VerticalHorizontalLeftTransition; } m_RightSide = m_ClimbableObject.OnRightSide(); } else { // Always transition to the same side of the object that the character started from. if (m_ClimbID == ClimbID.ClimbHorizontalBackwardLeft) { m_ClimbID = ClimbID.HorizontalVerticalBackwardRightTransition; } else if (m_ClimbID == ClimbID.ClimbHorizontalBackwardRight) { m_ClimbID = ClimbID.HorizontalVerticalBackwardLeftTransition; } else if (m_ClimbID == ClimbID.ClimbHorizontalForwardLeft) { m_ClimbID = ClimbID.HorizontalVerticalForwardLeftTransition; } else { m_ClimbID = ClimbID.HorizontalVerticalForwardRightTransition; } } m_AcceptInput = false; m_Transitioning = true; m_AnimatorMonitor.DetermineStates(); }
/// <summary> /// Update the Animator. /// </summary> /// <returns>Should the RigidbodyCharacterController continue execution of its UpdateAnimator method?</returns> public override bool UpdateAnimator() { // Do not change animation states if the mount, dismount, or transition animations are playing. if (!m_Mounted || m_Transitioning) { return(false); } var moveType = ClimbableObject.MoveType.None; // Vines use a blend tree so they don't require as much logic to change states. if (m_ClimbableObject.Type == ClimbableObject.ClimbableType.Vine) { // Check for a top or bottom dismount. var input = m_RelativeLookDirectionMovement ? m_TargetLookDirection.Invoke(false) : m_Controller.InputVector; if (m_RelativeLookDirectionMovement ? (m_Controller.InputVector.z > 0.1f && (m_Vertical ? input.y > -0.2f : input.z < 0f)) : input.z > 0.1f) { moveType = ClimbableObject.MoveType.Up; } else if (m_RelativeLookDirectionMovement ? (m_Controller.InputVector.z > 0.1f && (m_Vertical ? input.y <-0.2f : input.z> 0f)) : input.z < -0.1f) { moveType = ClimbableObject.MoveType.Down; } if (m_ClimbableObject.CanDismount(moveType, true)) { StartDismount(moveType); return(false); } var canMove = true; // The character should not dismount. Ensure the left or right movement is valid. if (Mathf.Abs(m_Controller.InputVector.x) > 0.01f) { if (Physics.Raycast(m_Transform.TransformPoint(m_ClimbableObject.HorizontalPadding * (m_Controller.InputVector.x < -0.01f ? -1 : 1), 0, 0), m_Transform.forward, out m_RaycastHit, m_StartClimbMaxDistance + m_Controller.CapsuleCollider.radius * 2, m_ClimbableLayer.value, QueryTriggerInteraction.Ignore)) { canMove = m_RaycastHit.transform.Equals(m_ClimbableTransform); } else { canMove = false; } } // Set the parameters for the blend tree if the character can move. m_AnimatorMonitor.SetHorizontalInputValue(canMove ? m_Controller.InputVector.x : 0); m_AnimatorMonitor.SetForwardInputValue(canMove ? input.z : 0); // Forward is "up". return(false); } var changed = false; // Do not change animation states if a climbing state is current playing. if (m_AcceptInput) { var input = m_RelativeLookDirectionMovement ? m_TargetLookDirection.Invoke(false) : m_Controller.InputVector; // If not moving relative to the look direction, move up if vertical, otherwise forward if horizontal. If moving relatove to the look direction, // move when the z input is greater then a minimum value. if (m_RelativeLookDirectionMovement ? (m_Controller.InputVector.z > 0.1f && (m_Vertical ? input.y > -0.2f : input.z < 0f)) : input.z > 0.1f) { if (m_Vertical) { if (m_ClimbableObject.Type == ClimbableObject.ClimbableType.Pipe) { m_ClimbID = ClimbID.ClimbUp; } else { // The ladder and vine require the feet to alternate while moving up. if (m_RightFootUp) { m_ClimbID = ClimbID.ClimbRightUp; } else { m_ClimbID = ClimbID.ClimbLeftUp; } } } else { // Move in the forward direction if horizontal. if (m_RightTransition) { m_ClimbID = ClimbID.ClimbHorizontalForwardRight; } else { m_ClimbID = ClimbID.ClimbHorizontalForwardLeft; } } changed = true; } else if (m_RelativeLookDirectionMovement ? (m_Controller.InputVector.z > 0.1f && (m_Vertical ? input.y <-0.2f : input.z> 0f)) : input.z < -0.1f) { // Move down if vertical, otherwise backward if horizontal. if (m_Vertical) { if (m_ClimbableObject.Type == ClimbableObject.ClimbableType.Pipe) { m_ClimbID = ClimbID.ClimbDown; } else { // The ladder and vine require the feet to alternate while moving down. if (m_RightFootUp) { m_ClimbID = ClimbID.ClimbLeftDown; } else { m_ClimbID = ClimbID.ClimbRightDown; } } } else { // Move in the forward direction if horizontal. if (m_RightTransition) { m_ClimbID = ClimbID.ClimbHorizontalBackwardRight; } else { m_ClimbID = ClimbID.ClimbHorizontalBackwardLeft; } } changed = true; } } // Map the ClimbID to the ClimbableObject MoveType so the climbable object knows which direction the character is moving. // This is used to determine if the character should dismount or transition. if (m_ClimbID == ClimbID.ClimbLeftUp || m_ClimbID == ClimbID.ClimbRightUp || m_ClimbID == ClimbID.ClimbUp) { moveType = ClimbableObject.MoveType.Up; } else if (m_ClimbID == ClimbID.ClimbLeftDown || m_ClimbID == ClimbID.ClimbRightDown || m_ClimbID == ClimbID.ClimbDown) { moveType = ClimbableObject.MoveType.Down; } else if (m_ClimbID == ClimbID.ClimbHorizontalBackwardRight || m_ClimbID == ClimbID.ClimbHorizontalBackwardLeft) { moveType = ClimbableObject.MoveType.HorizontalBackward; } else if (m_ClimbID == ClimbID.ClimbHorizontalForwardRight || m_ClimbID == ClimbID.ClimbHorizontalForwardLeft) { moveType = ClimbableObject.MoveType.HorizontalForward; } // Determine if the character can dismount, trasition, or should just move along the climbable object. if (m_ClimbableObject.CanDismount(moveType, changed)) { StartDismount(moveType); } else if (m_ClimbableObject.ShouldStartPipeTransition(moveType, m_Vertical, m_RightSide)) { if (!m_Vertical) { m_TargetTransitionTransform = m_ClimbableObject.HorizontalVerticalTransitionTargetTransform(); } StartTransition(); } else if (changed) { m_AcceptInput = false; m_ClimbableObject.Move(moveType); m_VerticalDistance = 0; m_AnimatorMonitor.DetermineStates(); } return(false); }