/// <summary> /// Returns the CameraState for the given CoverID. /// </summary> /// <param name="coverID">The CoverID to retrieve the state of.</param> /// <returns>The CameraState for the given CoverID.</returns> private string GetCoverCameraState(CoverIDs coverID) { if (coverID == CoverIDs.CrouchPopCenterLeft) { return("CoverCenterLeft"); } else if (coverID == CoverIDs.CrouchPopCenterRight) { return("CoverCenterRight"); } else if (coverID == CoverIDs.CrouchPopLeft || coverID == CoverIDs.StandPopLeft) { return("CoverLeft"); } return("CoverRight"); }
/// <summary> /// The ability has stopped running. /// </summary> protected override void AbilityStopped() { base.AbilityStopped(); m_UsePredeterminedCoverPoint = false; m_ShouldPopFromCover = false; m_Controller.ForceRootMotion = false; if (m_ChangeCameraState != null) { m_ChangeCameraState.Invoke(GetCoverCameraState(m_CurrentCoverID), false); } m_CurrentCoverID = CoverIDs.None; EventHandler.UnregisterEvent <bool>(m_GameObject, "OnAbilityHeightChange", OnHeightChange); EventHandler.UnregisterEvent(m_GameObject, "OnControllerStartAim", OnStartAim); EventHandler.UnregisterEvent <bool>(m_GameObject, "OnControllerAim", OnAim); EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorInCover", InCover); EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorPoppedFromCover", PoppedFromCover); }
/// <summary> /// Update the Animator. /// </summary> /// <returns>Should the RigidbodyCharacterController continue execution of its UpdateAnimator method?</returns> public override bool UpdateAnimator() { m_AnimatorMonitor.SetForwardInputValue(0, 0.1f); if (Mathf.Abs(m_Controller.RelativeInputVector.x) > 0.1f) { m_LookRight = m_Controller.RelativeInputVector.x < 0; } m_AnimatorMonitor.SetFloatDataValue(m_LookRight ? 1 : -1, 0.1f); switch (m_CurrentCoverID) { case CoverIDs.StandStill: case CoverIDs.CrouchStill: m_AnimatorMonitor.SetHorizontalInputValue(m_CanMove ? m_Controller.InputVector.x * m_NormalizedStrafeSpeed : 0, 0.1f); if (m_CanTogglePop && m_ShouldPopFromCover && m_AgainstCover) { var popCoverID = CoverIDs.None; var popOffset = m_Controller.CapsuleCollider.radius + m_PopDistance.x + m_CoverOffset; var canStand = false; if (!m_StandingCover) { canStand = !Physics.Raycast(m_Transform.position + (m_Transform.up * (m_Controller.CapsuleCollider.height + m_CanStandOffset)), -m_CoverNormal, out m_RaycastHit, m_Controller.CapsuleCollider.radius + m_CoverOffset + 0.1f, m_CoverLayer.value, QueryTriggerInteraction.Ignore); } if (canStand) // Can the character pop in the center? { popCoverID = m_LookRight ? CoverIDs.CrouchPopCenterRight : CoverIDs.CrouchPopCenterLeft; } else if (!IntersectObject(-popOffset, m_StandingCover ? m_Controller.CapsuleCollider.height / 2 : 0, m_PopDistance.z, -1)) // Can the character pop to the right? { popCoverID = m_StandingCover ? CoverIDs.StandPopRight : CoverIDs.CrouchPopRight; } else if (!IntersectObject(popOffset, m_StandingCover ? m_Controller.CapsuleCollider.height / 2 : 0, m_PopDistance.z, -1)) // Can the character pop to the left? { popCoverID = m_StandingCover ? CoverIDs.StandPopLeft : CoverIDs.CrouchPopLeft; } if (popCoverID != CoverIDs.None) { m_CurrentCoverID = popCoverID; m_UseCoverNormal = m_CanTogglePop = false; m_PoppedFromCover = true; m_PopPosition = m_Transform.position; m_AnimatorMonitor.SetStateValue((int)popCoverID); } } break; case CoverIDs.StandPopLeft: case CoverIDs.StandPopRight: case CoverIDs.CrouchPopLeft: case CoverIDs.CrouchPopRight: case CoverIDs.CrouchPopCenterRight: case CoverIDs.CrouchPopCenterLeft: if (m_CanTogglePop && !m_ShouldPopFromCover) { m_PrevCoverID = m_CurrentCoverID; if (m_StandingCover) { m_CurrentCoverID = CoverIDs.StandStill; } else { m_CurrentCoverID = CoverIDs.CrouchStill; } m_CanTogglePop = false; if (m_ChangeCameraState != null) { m_ChangeCameraState.Invoke(GetCoverCameraState(m_PrevCoverID), false); } m_AnimatorMonitor.SetStateValue((int)m_CurrentCoverID); } break; } return(false); }
/// <summary> /// Only allow movement on the relative x axis to prevent the character from moving away from the cover point. /// </summary> /// <returns>Should the RigidbodyCharacterController continue execution of its UpdateMovement method?</returns> public override bool UpdateMovement() { // Return to the exact position that the character popped from. if (m_PoppedFromCover && !m_ShouldPopFromCover && (m_CurrentCoverID == CoverIDs.StandStill || m_CurrentCoverID == CoverIDs.CrouchStill)) { var position = m_Transform.position; var moveDelta = Mathf.Max(m_Controller.RootMotionForce.magnitude, 0.01f); position.x = Mathf.MoveTowards(position.x, m_PopPosition.x, moveDelta); position.z = Mathf.MoveTowards(position.z, m_PopPosition.z, moveDelta); m_Controller.SetPosition(position); m_Controller.RootMotionForce = Vector3.zero; // The character is done returning to cover when they have arrived at the pop position. if ((m_Transform.position - m_PopPosition).sqrMagnitude < 0.001f) { m_Controller.SetPosition(m_PopPosition); m_UseCoverNormal = m_CanTogglePop = true; m_PoppedFromCover = false; } return(false); } var coverNormalRotation = Quaternion.LookRotation(m_CoverNormal); var relativeForce = Quaternion.Inverse(coverNormalRotation) * m_Controller.RootMotionForce; // While in cover the character can only strafe if there continues to be cover in the direction that the character should strafe. if (m_UseCoverNormal) { m_CanMove = m_AIAgent.Invoke(); if (!m_CanMove && Mathf.Abs(m_Controller.RelativeInputVector.x) > 0) { m_CanMove = IntersectObject((m_Controller.CapsuleCollider.radius + m_StrafeCoverOffset.x) * (m_Controller.RelativeInputVector.x > 0 ? 1 : -1), 0, m_StrafeCoverOffset.z, m_CoverLayer.value); } if (!m_CanMove) { relativeForce.x = 0; } relativeForce.z = 0; } m_Controller.RootMotionForce = coverNormalRotation * relativeForce; // Don't use the velocity if popping. if (m_CurrentCoverID != CoverIDs.CrouchStill && m_CurrentCoverID != CoverIDs.StandStill) { m_Controller.SetPosition(m_Transform.position + m_Controller.RootMotionForce); m_Controller.RootMotionForce = Vector3.zero; } // Stop taking standing cover if there is only crouching cover available. if (m_HeightChange != null && !m_HeightChange.IsActive && m_UseCoverNormal) { var canStand = Physics.Raycast(m_Transform.position + (m_Transform.up * m_CanStandOffset), -m_CoverNormal, out m_RaycastHit, m_Controller.CapsuleCollider.radius + m_CoverOffset + 0.1f, m_CoverLayer.value, QueryTriggerInteraction.Ignore); if (canStand != m_StandingCover) { m_StandingCover = canStand; m_CurrentCoverID += (int)CoverIDs.CrouchStill * (canStand ? -1 : 1); m_AnimatorMonitor.SetStateValue((int)m_CurrentCoverID); m_AnimatorMonitor.DetermineStates(); } } return(true); }