/// <summary> /// calculate the groundnormal from collected collision points /// </summary> private void CalculateVerticalState() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; if (aCharacterController.GetVerticalState() == KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eFalling) //also check jumping because character can jump and lands immediately on higher ground without even start falling { if (itsKGFCharacterData.itsContactPoints.Count != 0) //contact points so land { itsJumping = false; Land(); } } else if (aCharacterController.GetVerticalState() == KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eGrounded) { if (itsKGFCharacterData.itsContactPoints.Count == 0) //no contact points so start falling { Fall(); } } if (aCharacterController.GetVerticalState() == KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eJumping && itsKGFCharacterData.itsRigidBody.velocity.y < -0.2f) { Fall(); } else if (aCharacterController.GetVerticalState() == KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eJumping && Mathf.Abs(itsKGFCharacterData.itsRigidBody.velocity.y) < 0.1f) { Fall(); } }
/// <summary> /// Checks if slope too steep. /// </summary> /// <returns> /// The if slope too steep. /// </returns> /// <param name='theForwardDirection'> /// If set to <c>true</c> the forward direction. /// </param> public bool CheckIfSlopeOK(Vector3 theForwardDirection) { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; if (aCharacterController == null) { return(true); } if (aCharacterController.GetVerticalState() != KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eGrounded) { return(true); } float aValue = Vector3.Dot(theForwardDirection, itsKGFCharacterData.itsLerpedGroundNormalDirection); if (aValue < 0) //character walks up a hill { float anAngleBetweenNormalAndForwardVector = Vector3.Angle(theForwardDirection, itsKGFCharacterData.itsLerpedGroundNormalDirection) - 90.0f; if (anAngleBetweenNormalAndForwardVector > aCharacterController.GetMaxSlope()) { return(false); } } return(true); }
/// <summary> /// /// </summary> private void ApplyRotation() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; float anAxis1Horizontal = aCharacterController.GetAxis1Horizontal(); if (aCharacterController.GetIsTurning()) //accelerate turn speed { aCharacterController.SetCurrentTurnSpeed(Mathf.Lerp(aCharacterController.GetCurrentTurnSpeed(), aCharacterController.GetMaxTurnSpeed(), Time.deltaTime / aCharacterController.GetTurnAccerlerationTime())); } else { aCharacterController.SetCurrentTurnSpeed(aCharacterController.GetMinTurnSpeed()); } float aTurnSpeed = aCharacterController.GetCurrentTurnSpeed(); Vector3 aControllerDirection = Vector3.zero; aControllerDirection.z = aCharacterController.GetAxis1Vertical(); if (aCharacterController.GetAxis1Horizontal() != 0.0f) { aCharacterController.SetIsTurning(true); } else { aCharacterController.SetIsTurning(false); } if (aCharacterController.GetAxis1Horizontal() > 0.0f) { itsTurningLeft = true; } else { itsTurningLeft = false; } if (aControllerDirection.z == 0) { itsKGFCharacterData.itsReoriented = false; } float aTurnSpeedMultiplicator = 1.0f - (aCharacterController.GetSpeedNormalized() * 0.5f); float aFinalTurnSpeed = aTurnSpeedMultiplicator * aTurnSpeed; //speed hack for ludwig if (aFinalTurnSpeed < aCharacterController.GetMinTurnSpeed()) { aFinalTurnSpeed = aCharacterController.GetMinTurnSpeed(); } transform.Rotate(0.0f, aFinalTurnSpeed * anAxis1Horizontal * Time.deltaTime, 0.0f); itsKGFCharacterData.itsCharacterRotator.transform.localRotation = Quaternion.identity; }
/// <summary> /// Rigidbody is landing on ground /// </summary> protected void Land() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; if (aCharacterController.GetVerticalState() == KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eGrounded) { return; //cannot land if already grounded } aCharacterController.SetVerticalState(KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eGrounded); }
/// <summary> /// Character is falling /// </summary> protected void Fall() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; if (aCharacterController.GetVerticalState() == KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eFalling) { return; //no falling if already falling } aCharacterController.SetVerticalState(KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eFalling); }
/// <summary> /// Applies the camera root. Also lerps the character to targeet rotation /// </summary> private void ApplyCameraRoot() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; float aLerpSpeed = aCharacterController.GetLerpSpeed(); itsKGFCharacterData.itsGeometryContainerTransform.rotation = Quaternion.Lerp(itsKGFCharacterData.itsGeometryContainerTransform.rotation, transform.rotation, Time.deltaTime * aLerpSpeed); float anRotationOffset = 0; float aCurrentRotationOffset = itsKGFCharacterData.itsCharacterObject.transform.localEulerAngles.y; aCurrentRotationOffset = Mathf.LerpAngle(aCurrentRotationOffset, anRotationOffset, Time.deltaTime * 4); Quaternion anOffsetQuaternion = Quaternion.Euler(0, aCurrentRotationOffset, 0); itsKGFCharacterData.itsCharacterObject.transform.localRotation = anOffsetQuaternion; itsKGFCharacterData.itsGeometryContainerTransform.position = Vector3.Lerp(itsKGFCharacterData.itsGeometryContainerTransform.position, transform.position, Time.deltaTime * 20.0f); if (!Input.GetButton("Fire2") && itsKGFCharacterData.itsIsMoving) { float anOffsetY = itsKGFCharacterData.itsCameraRootTransform.position.y - itsKGFCharacterData.itsGeometryContainerTransform.position.y; Vector3 aStartPosition = itsKGFCharacterData.itsGeometryContainerTransform.position; aStartPosition.y += anOffsetY; float aDistance = 1f; Vector3 anOffsetPosition = itsKGFCharacterData.itsCameraRootTransform.position; //aStartPosition + (transform.rotation * new Vector3(0,0,aDistance)); anOffsetPosition.x = Mathf.Lerp(anOffsetPosition.x, aStartPosition.x + (transform.rotation * new Vector3(0, 0, aDistance)).x, 3 * Time.deltaTime); anOffsetPosition.z = Mathf.Lerp(anOffsetPosition.z, aStartPosition.z + (transform.rotation * new Vector3(0, 0, aDistance)).z, 3 * Time.deltaTime); itsKGFCharacterData.itsCameraRootTransform.position = anOffsetPosition; } else { float anOffsetY = itsKGFCharacterData.itsCameraRootTransform.position.y - itsKGFCharacterData.itsGeometryContainerTransform.position.y; Vector3 aStartPosition = itsKGFCharacterData.itsGeometryContainerTransform.position; aStartPosition.y += anOffsetY; Vector3 anOffsetPosition = itsKGFCharacterData.itsCameraRootTransform.position; anOffsetPosition.x = Mathf.Lerp(anOffsetPosition.x, aStartPosition.x, 3 * Time.deltaTime); anOffsetPosition.z = Mathf.Lerp(anOffsetPosition.z, aStartPosition.z, 3 * Time.deltaTime); itsKGFCharacterData.itsCameraRootTransform.position = anOffsetPosition; } }
/// <summary> /// initialize jump /// </summary> public void Jump() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; if (aCharacterController.GetVerticalState() != KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eGrounded) { return; //no jumping if no ground beneath feet } aCharacterController.SetVerticalState(KGFCharacterController3rdPerson.GlobalSettings.eVerticalState.eJumping); float aJumpHeight = aCharacterController.GetCurrentJumpHeight(); Vector3 aJumpVelocity = transform.up * Mathf.Sqrt(2.0f * aJumpHeight * Physics.gravity.magnitude); itsKGFCharacterData.itsRigidBody.velocity = itsKGFCharacterData.itsRigidBody.velocity + aJumpVelocity; itsJumping = true; }
/// <summary> /// Sets the module_charactercontroller this container belongs to /// </summary> /// <param name="theModuleCharacterController"></param> public void SetCharacterController(KGFCharacterController3rdPerson theCharacterController) { itsKGFCharacterData.itsCharacterController = theCharacterController; }
/// <summary> /// Calculates the forces that have to be applierd to the character container, based on ground normal direction and controller input /// </summary> private void ApplyForces() { KGFCharacterController3rdPerson aCharacterController = itsKGFCharacterData.itsCharacterController; itsKGFCharacterData.itsResultingControllerDirection = Vector3.zero; Vector3 aLocalControllerInput = Vector3.zero; Vector3 aTargetVelocity = Vector3.zero; float anAxis1Vertical = aCharacterController.GetAxis1Vertical(); if (Mathf.Abs(anAxis1Vertical) > 0) { itsAcceleration = Mathf.Lerp(itsAcceleration, 1, Time.deltaTime * aCharacterController.GetAcceleration()); } else { itsAcceleration = 0; } aCharacterController.SetSpeedNormalized(itsAcceleration); Vector3 aFinalDirection = new Vector3(0.0f, 0.0f, anAxis1Vertical); itsKGFCharacterData.itsResultingControllerDirection.z = aFinalDirection.z; //anAxis1Vertical; aLocalControllerInput = itsKGFCharacterData.itsTransform.TransformDirection(aFinalDirection); itsKGFCharacterData.itsResultingControllerDirection.x = aFinalDirection.x; //aCharacterController.GetAxis1Horizontal (); aLocalControllerInput.Normalize(); //by normalizing this value will always be 1 so acelleration caused by control damping is disabled float aBackWardSpeedMultiplicator = 1.0f; if (itsKGFCharacterData.itsResultingControllerDirection.z < 0.0f) { aBackWardSpeedMultiplicator = aCharacterController.GetBackwardSpeedMultiplicator(); } bool aIsSlopeOK = CheckIfSlopeOK(aLocalControllerInput); if (aIsSlopeOK) //change velocity only if { aTargetVelocity = aLocalControllerInput * aCharacterController.GetCurrentSpeed() * aBackWardSpeedMultiplicator; //multiply direction with desired speed } else { aTargetVelocity = Vector3.zero; } Vector3 aVelocityChange = aTargetVelocity - itsKGFCharacterData.itsRigidBody.velocity; aVelocityChange.y = 0; //TODO: check this? itsKGFCharacterData.itsRigidBody.AddForce(aVelocityChange, ForceMode.VelocityChange); if (itsKGFCharacterData.itsRigidBody.velocity.magnitude < aCharacterController.GetCurrentSpeed() * 0.1f) //if not moving { itsKGFCharacterData.itsIsMoving = false; } else { itsKGFCharacterData.itsIsMoving = true; } itsKGFCharacterData.itsRigidBodyVelocity = itsKGFCharacterData.itsRigidBody.velocity; }
/// <summary> /// Sets the module_charactercontroller this container belongs to /// </summary> /// <param name="theModuleCharacterController"></param> public void SetCharacterController(KGFCharacterController3rdPerson theCharacterController) { itsKGFCharacterData.itsCharacterController = theCharacterController; }