Files
Robii Aragon fd87a6ffd5 add ckg
plantilla base para movimiento básico
2026-02-05 05:07:55 -08:00

1139 lines
42 KiB
C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class vehicleGravityControl : gravityObjectManager
{
[Header ("Main Settings")]
[Space]
public bool useGravity = true;
public float gravityForce = 9.8f;
public bool searchNewSurfaceOnHighFallSpeed = true;
public bool shakeCameraOnHighFallSpeed = true;
public float minSpeedToShakeCamera = 10;
public bool checkSurfaceBelowOnRegularState;
public float timeToSetNullParentOnAir = 0.5f;
float lastTimeParentFound;
public bool changeDriverGravityWhenGetsOff = true;
public bool setVehicleRegularGravityOnDriverGetOff;
[Space]
[Header ("Circumnavigation Settings")]
[Space]
public float circumnavigateRotationSpeed = 10;
public bool circumnavigateCurrentSurfaceActive;
public bool useLerpRotation;
public bool checkSurfaceBelowLedge;
public float surfaceBelowLedgeRaycastDistance = 3;
public float belowLedgeRotationSpeed = 10;
public float minAngleDifferenceToAdhereToSurface = 4;
[Space]
[Header ("Current Normal/Gravity Settings")]
[Space]
public Vector3 regularGravity = new Vector3 (0, 1, 0);
public Vector3 currentNormal = new Vector3 (0, 1, 0);
[Space]
[Header ("Gravity At Start Settings")]
[Space]
public bool startWithNewGravity;
public bool useVehicleRotation;
public bool adjustRotationToSurfaceFound;
public Vector3 newGravityToStart;
[Space]
[Header ("Others Settings")]
[Space]
public otherSettings settings;
[Space]
[Header ("Debug")]
[Space]
public bool gravityControlEnabled;
public bool OnGround;
public bool gravityPowerActive;
public bool powerActivated;
public bool recalculatingSurface;
public bool searchingSurface;
public bool searchingNewSurfaceBelow;
public bool searchAround;
public bool rotating;
public bool circumnavigableSurfaceFound;
public bool useCenterPointActive;
public Transform currentCenterPoint;
[Space]
[Header ("Gizmo Settings")]
[Space]
public bool showGizmo;
[Space]
[Header ("Components")]
[Space]
public Transform gravityAdherenceRaycastParent;
public Transform surfaceBelowRaycastTransform;
public vehicleController mainVehicleController;
public Collider gravityCenterCollider;
public Rigidbody mainRigidbody;
public vehicleCameraController vehicleCameraManager;
public vehicleHUDManager HUDManager;
public inputActionManager actionManager;
Vector3 previousNormalDetected;
Transform vehicleCamera;
bool conservateSpeed;
bool accelerating;
Vector3 forwardAxisCamera;
Vector3 rightAxisCamera;
Vector3 forwardAxisMovement;
Vector3 surfaceNormal;
Vector3 previousVelocity;
float normalGravityMultiplier;
float horizontalAxis;
float verticalAxis;
Transform pivot;
GameObject fatherDetected;
RaycastHit hit;
Coroutine rotateCharacterState;
Vector2 axisValues;
Coroutine rotateVehicleCoroutine;
bool gravityForcePaused;
bool onGroundChecked;
float currentCircumnagivateRotationSpeed;
bool surfaceFound;
RaycastHit currentSurfaceFound;
Vector3 currentPosition;
Vector3 rayPosition;
Vector3 rayDirection;
float gravityAdherenceRaycastParentAngleRotation;
bool checkDownSpeedActive = true;
GameObject currentObjectBelowVehicle;
GameObject previousSurfaceBelowVehicle;
Vector3 pos;
Vector3 dir;
Vector3 currentUp;
bool mainVehicleControllerLocated;
float originalGravityForce;
bool addPreviousVelocityMagnitude;
float previousVelocityMagnitude;
float lastTimeRotateVehicleToRaycastDirection;
void Start ()
{
//set the current normal in the vehicle controller
if (mainVehicleController == null) {
mainVehicleController = GetComponent<vehicleController> ();
}
mainVehicleControllerLocated = mainVehicleController != null;
if (mainVehicleControllerLocated) {
mainVehicleController.setNormal (currentNormal);
}
if (startWithNewGravity) {
if (useVehicleRotation) {
currentUp = transform.up;
Vector3 normalDirection = -currentUp;
if (adjustRotationToSurfaceFound) {
if (Physics.Raycast (transform.position, -currentUp, out hit, Mathf.Infinity, settings.layer)) {
normalDirection = hit.normal;
}
}
if (currentUp != currentNormal) {
setCustomNormal (normalDirection);
}
} else {
setCustomNormal (newGravityToStart);
}
}
vehicleCamera = vehicleCameraManager.transform;
originalGravityForce = gravityForce;
}
void Update ()
{
currentPosition = transform.position;
//if the vehicle is searching a new surface
if (searchingSurface) {
//set the vehicle movement direction in the air (local X and Y axis)
forwardAxisCamera = pivot.TransformDirection (Vector3.up);
rightAxisCamera = pivot.TransformDirection (Vector3.right);
//new position and direction of a raycast to detect a surface
pos = Vector3.zero;
dir = Vector3.zero;
//if the player has activate the gravity control in the vehicle, then apply force in the camera direction and set the raycast position in the center of mass
if (!searchingNewSurfaceBelow) {
//this function apply force to the vehicle in the new direction and allows to move it in the air in the left, right, forward and backward direction using the direction
//of the movement as local Y axis
moveInTheAir ((gravityForce * (mainRigidbody.mass / settings.massDivider) * settings.speed) * forwardAxisMovement, settings.speed, mainRigidbody.mass / settings.massDivider, forwardAxisMovement);
pos = settings.centerOfMass.position;
dir = forwardAxisMovement;
}
//else, the player is falling in the air while the gravity control was enabled, so the ray direction is the negavite local Y axis or -currentNormal and the position is the
//vehicle itself
else {
pos = currentPosition;
dir = -currentNormal;
}
if (showGizmo) {
Debug.DrawRay (pos, settings.vehicleRadius * dir, Color.yellow);
}
//if the raycast found a new surface, then
if (Physics.Raycast (pos, dir, out hit, settings.vehicleRadius, settings.layer)) {
//check is not a trigger or a rigidbody
if (!hit.collider.isTrigger && hit.rigidbody == null) {
//a new valid surface has been detected, so stop the search of a new surface
searchingNewSurfaceBelow = false;
searchingSurface = false;
searchAround = false;
powerActivated = false;
//set to 0 the vehicle velocity
mainRigidbody.linearVelocity = Vector3.zero;
//disable the collider in the center of mass
gravityCenterCollider.enabled = false;
//if the surface can be circumnavigate
if (hit.collider.gameObject.CompareTag (settings.tagForCircumnavigate)) {
circumnavigableSurfaceFound = true;
}
//if the surface is moving
if (hit.collider.gameObject.CompareTag (settings.tagForMovingObjects)) {
addParent (hit.collider.gameObject);
}
//if the new normal is different from the current normal, which means that is other surface inclination, then
if (hit.normal != currentNormal) {
//rotate the vehicle according to that normal
if (rotateVehicleCoroutine != null) {
StopCoroutine (rotateVehicleCoroutine);
}
rotateVehicleCoroutine = StartCoroutine (rotateToSurface (hit.normal, 2));
}
//disable the gravity control in the vehicle controller
if (mainVehicleControllerLocated) {
mainVehicleController.changeGravityControlUse (false);
}
vehicleCameraManager.usingBoost (false, "StopShake", true, true);
}
}
}
//if the gravity control is enabled, and the vehicle falls in its negative loxal Y axis,
//then check if there is any surface below the vehicle which will become the new ground surface
//in case the vehicle reachs a certain velocity
if (!OnGround && !powerActivated) {
if (checkDownSpeedActive && shakeCameraOnHighFallSpeed && transform.InverseTransformDirection (mainRigidbody.linearVelocity).y < -minSpeedToShakeCamera) {
vehicleCameraManager.usingBoost (true, "Regular Gravity Control", true, true);
}
if (searchNewSurfaceOnHighFallSpeed && transform.InverseTransformDirection (mainRigidbody.linearVelocity).y < -settings.velocityToSearch && !searchingNewSurfaceBelow && !powerActivated) {
//check that the current normal is not the regular one
if (currentNormal != regularGravity) {
//enable the collider in the center of mass
gravityCenterCollider.enabled = true;
//searching a new surface
searchingNewSurfaceBelow = true;
searchingSurface = true;
//stop to recalculate the normal of the vehicle
recalculatingSurface = false;
circumnavigableSurfaceFound = false;
//enable the gravity control in the vehicle controller
if (mainVehicleControllerLocated) {
mainVehicleController.changeGravityControlUse (true);
}
}
}
}
//if the vehicle is above a circumnavigable object, then recalculate the current normal of the vehicle according to the surface normal under the vehicle
if (!searchingSurface && (circumnavigableSurfaceFound || fatherDetected != null) && recalculatingSurface) {
//set the distance of the ray, if the vehicle is not on the ground, the distance is higher
float distance = settings.rayDistance + 0.05f;
if (!OnGround) {
distance = 10;
}
surfaceFound = false;
//if the vehicle founds a surface below it, get its normal
if (Physics.Raycast (settings.centerOfMass.position, -currentNormal, out hit, distance, settings.layer)) {
currentSurfaceFound = hit;
surfaceFound = true;
currentCircumnagivateRotationSpeed = circumnavigateRotationSpeed;
}
currentUp = transform.up;
//Get the correct raycast orientation according to input, for example, it is no the same ray position and direction if the vehicle is moving forward or backward
if (checkSurfaceBelowLedge) {
rayPosition = currentPosition + 0.1f * currentUp;
gravityAdherenceRaycastParentAngleRotation = Vector3.SignedAngle (transform.forward, mainRigidbody.linearVelocity, currentUp);
gravityAdherenceRaycastParent.localRotation = Quaternion.Euler (new Vector3 (0, gravityAdherenceRaycastParentAngleRotation, 0));
}
if (checkSurfaceBelowLedge) {
rayDirection = -currentUp;
if (showGizmo) {
Debug.DrawRay (rayPosition, rayDirection, Color.white);
}
if (!Physics.Raycast (rayPosition, rayDirection, out hit, 1, settings.layer)) {
if (showGizmo) {
Debug.DrawRay (rayPosition, rayDirection, Color.green);
}
rayPosition = surfaceBelowRaycastTransform.position;
rayDirection = surfaceBelowRaycastTransform.forward;
if (Physics.Raycast (rayPosition, rayDirection, out hit, surfaceBelowLedgeRaycastDistance, settings.layer)) {
if (showGizmo) {
Debug.DrawRay (rayPosition, hit.distance * rayDirection, Color.yellow);
}
currentSurfaceFound = hit;
surfaceFound = true;
currentCircumnagivateRotationSpeed = belowLedgeRotationSpeed;
} else {
if (showGizmo) {
Debug.DrawRay (rayPosition, surfaceBelowLedgeRaycastDistance * rayDirection, Color.red);
}
}
} else {
if (showGizmo) {
Debug.DrawRay (rayPosition, hit.distance * rayDirection, Color.red);
}
}
}
if (surfaceFound) {
if (!currentSurfaceFound.collider.isTrigger && currentSurfaceFound.rigidbody == null) {
//the object detected can be circumnavigate, so get the normal direction
if (currentSurfaceFound.collider.gameObject.CompareTag (settings.tagForCircumnavigate)) {
if (useCenterPointActive) {
Vector3 heading = settings.centerOfMass.position - currentCenterPoint.transform.position;
surfaceNormal = heading / heading.magnitude;
} else {
surfaceNormal = currentSurfaceFound.normal;
}
}
//the object is moving, so get the normal direction and set the player as a children of the moving obejct
else if (currentSurfaceFound.collider.gameObject.CompareTag (settings.tagForMovingObjects)) {
if (useCenterPointActive) {
Vector3 heading = settings.centerOfMass.position - currentCenterPoint.transform.position;
surfaceNormal = heading / heading.magnitude;
} else {
surfaceNormal = currentSurfaceFound.normal;
}
if (fatherDetected == null) {
addParent (currentSurfaceFound.collider.gameObject);
}
}
}
} else {
if (fatherDetected != null) {
removeParent ();
}
}
if (useLerpRotation) {
//set the current normal according to the hit.normal
currentNormal = Vector3.Lerp (currentNormal, surfaceNormal, currentCircumnagivateRotationSpeed * Time.deltaTime);
if (Vector3.Angle (previousNormalDetected, surfaceNormal) > minAngleDifferenceToAdhereToSurface) {
previousNormalDetected = surfaceNormal;
Vector3 myForward = Vector3.Cross (transform.right, currentNormal);
Quaternion dstRot = Quaternion.LookRotation (myForward, currentNormal);
transform.rotation = Quaternion.Lerp (transform.rotation, dstRot, currentCircumnagivateRotationSpeed * Time.deltaTime);
Vector3 myForwardCamera = Vector3.Cross (vehicleCamera.right, currentNormal);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, currentNormal);
vehicleCamera.rotation = Quaternion.Lerp (vehicleCamera.rotation, dstRotCamera, currentCircumnagivateRotationSpeed * Time.deltaTime);
}
} else {
//set the current normal according to the hit.normal
currentNormal = Vector3.Slerp (currentNormal, surfaceNormal, currentCircumnagivateRotationSpeed * Time.deltaTime);
if (Vector3.Angle (previousNormalDetected, currentNormal) > minAngleDifferenceToAdhereToSurface) {
previousNormalDetected = surfaceNormal;
Vector3 myForward = Vector3.Cross (transform.right, currentNormal);
Quaternion dstRot = Quaternion.LookRotation (myForward, currentNormal);
transform.rotation = Quaternion.Slerp (transform.rotation, dstRot, currentCircumnagivateRotationSpeed * Time.deltaTime);
}
Vector3 myForwardCamera = Vector3.Cross (vehicleCamera.right, currentNormal);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, currentNormal);
vehicleCamera.rotation = Quaternion.Slerp (vehicleCamera.rotation, dstRotCamera, currentCircumnagivateRotationSpeed * Time.deltaTime);
}
if (mainVehicleControllerLocated) {
mainVehicleController.setNormal (currentNormal);
}
}
//if the vehicle is being rotated to a new surface, set its velocity to 0
if (rotating) {
mainRigidbody.linearVelocity = Vector3.zero;
}
if ((gravityPowerActive || circumnavigateCurrentSurfaceActive) && !powerActivated) {
if (currentObjectBelowVehicle != null) {
//check if the object detected can be circumnavigate
if (currentObjectBelowVehicle.CompareTag (settings.tagForCircumnavigate)) {
circumnavigableSurfaceFound = true;
} else {
circumnavigableSurfaceFound = false;
}
//check if the object is moving to parent the player inside it
if (currentObjectBelowVehicle.CompareTag (settings.tagForMovingObjects)) {
if (previousSurfaceBelowVehicle != currentObjectBelowVehicle) {
previousSurfaceBelowVehicle = currentObjectBelowVehicle;
addParent (currentObjectBelowVehicle);
}
} else if (fatherDetected != null && !currentObjectBelowVehicle.transform.IsChildOf (fatherDetected.transform)) {
removeParent ();
}
//if the surface where the player lands can be circumnavigated or an moving/rotating object, then keep recalculating the player throught the normal surface
if (circumnavigableSurfaceFound || fatherDetected != null) {
recalculatingSurface = true;
}
//else disable this state
else {
recalculatingSurface = false;
}
} else {
if (previousSurfaceBelowVehicle != null) {
previousSurfaceBelowVehicle = null;
}
if (rotating) {
circumnavigableSurfaceFound = false;
}
}
} else {
if ((circumnavigableSurfaceFound || fatherDetected != null) && rotating) {
circumnavigableSurfaceFound = false;
}
if (checkSurfaceBelowOnRegularState && !gravityPowerActive && !HUDManager.isVehicletAsChildOfParent ()) {
if (currentObjectBelowVehicle != null) {
//check if the object is moving to parent the player inside it
if (currentObjectBelowVehicle.CompareTag (settings.tagForMovingObjects)) {
if (previousSurfaceBelowVehicle != currentObjectBelowVehicle) {
previousSurfaceBelowVehicle = currentObjectBelowVehicle;
addParent (currentObjectBelowVehicle);
lastTimeParentFound = Time.time;
}
} else if (fatherDetected != null && !currentObjectBelowVehicle.transform.IsChildOf (fatherDetected.transform)) {
removeParent ();
}
} else {
if (previousSurfaceBelowVehicle != null) {
previousSurfaceBelowVehicle = null;
}
if (Time.time > timeToSetNullParentOnAir + lastTimeParentFound) {
removeParent ();
}
}
}
}
}
void FixedUpdate ()
{
// If the gravity control is not being used
if (!powerActivated && !gravityForcePaused) {
// Apply force to the vehicle in the negative local Y axis, so the vehicle has a regular gravity
if (useGravity) {
mainRigidbody.AddForce ((-gravityForce * mainRigidbody.mass * settings.gravityMultiplier) * currentNormal);
}
// If the vehicle is search a new surface, and previously the gravity control was enabled, then
if (searchingNewSurfaceBelow) {
// Apply force in the negative local Y axis of the vehicle, and allow to move it left, right, backward and forward
moveInTheAir (mainRigidbody.linearVelocity, 1, 1, -currentNormal);
}
// Check if the vehicle is on the ground
OnGround = false;
// Use a raycast to it, with the center of the mass as position and the negative local Y axis as direction, using the ray distance configured in the inspector
if (Physics.Raycast (settings.centerOfMass.position, -currentNormal, out hit, settings.rayDistance, settings.layer)) {
if (showGizmo) {
Debug.DrawLine (settings.centerOfMass.position, hit.point, Color.cyan);
}
// If the hit is not a trigger
if (!hit.collider.isTrigger) {
// The vehicle is on the ground
OnGround = true;
currentObjectBelowVehicle = hit.collider.gameObject;
}
} else {
// Else the vehicle is in the air
OnGround = false;
currentObjectBelowVehicle = null;
}
} else {
// The vehicle is searching a new surface, so it is in the air
OnGround = false;
}
if (OnGround) {
if (!onGroundChecked) {
vehicleCameraManager.usingBoost (false, "stopShake", true, true);
onGroundChecked = true;
// If the gravity control is enabled, and the surface below the vehicle can be circumnavigate or is a moving object, allow to recalculate the normal
if ((circumnavigableSurfaceFound || fatherDetected != null) && gravityPowerActive) {
recalculatingSurface = true;
} else {
recalculatingSurface = false;
}
}
} else {
if (onGroundChecked) {
onGroundChecked = false;
}
}
}
void moveInTheAir (Vector3 newVel, float speedMultiplier, float massMultiplier, Vector3 movementDirection)
{
//get the new velocity to apply to the vehicle
Vector3 newVelocity = newVel;
//get the current values of the horizontal and vertical axis, from the input manager
if (actionManager != null) {
axisValues = actionManager.getPlayerMovementAxis ();
} else {
axisValues = Vector3.zero;
}
horizontalAxis = axisValues.x;
verticalAxis = axisValues.y;
//allow to move the vehicle in its local X and Y axis while he falls or move in the air using the gravity control
Vector3 newmoveInput = verticalAxis * forwardAxisCamera + horizontalAxis * rightAxisCamera;
if (newmoveInput.magnitude > 1) {
newmoveInput.Normalize ();
}
//if the input axis are being used, set that movement to the vehicle
if (newmoveInput.magnitude > 0) {
newVelocity += (settings.speed * (mainRigidbody.mass / settings.massDivider) * speedMultiplier) * newmoveInput;
}
//if the player is accelerating in the air, add more velocity to the vehicle
if (accelerating) {
newVelocity += (settings.accelerateSpeed * massMultiplier) * forwardAxisMovement;
}
//if the current local Y velocity is lower than the limit, clamp the velocity
if (Mathf.Abs (transform.InverseTransformDirection (newVelocity).y) > 40) {
newVelocity -= Mathf.Abs (transform.InverseTransformDirection (newVelocity).y) * movementDirection;
newVelocity += 40 * movementDirection;
}
//set the new velocity to the vehicle
mainRigidbody.linearVelocity = Vector3.Lerp (mainRigidbody.linearVelocity, newVelocity, Time.deltaTime * 2);
}
//when the colliders of the vehicle hits another surface
public void setCollisionDetected (Collision currentCollision)
{
//if the vehicle was searching a new surface using the gravity control, then
if (searchingSurface && searchAround) {
//check the type of collider
if (!currentCollision.gameObject.CompareTag ("Player") && currentCollision.rigidbody == null && !currentCollision.collider.isTrigger) {
//using the collision contact, get the direction of that new surface, so the vehicle change its movement to the position of that surface
//like this the searching of a new surface is more accurate, since a raycast and collisions are used to detect the new surface
Vector3 hitDirection = currentCollision.contacts [0].point - settings.centerOfMass.position;
//set the current direction of the vehicle
hitDirection = hitDirection / hitDirection.magnitude;
forwardAxisMovement = hitDirection;
//stop to search collisions around the vehicle
searchAround = false;
}
}
}
//set and remove the parent of the vehicle according to the type of surface
void addParent (GameObject obj)
{
fatherDetected = obj;
parentAssignedSystem currentParentAssignedSystem = obj.GetComponent<parentAssignedSystem> ();
if (currentParentAssignedSystem != null) {
fatherDetected = currentParentAssignedSystem.getAssignedParent ();
}
setFatherDetectedAsParent ();
}
void removeParent ()
{
setNullParent ();
fatherDetected = null;
}
public void setFatherDetectedAsParent ()
{
transform.SetParent (fatherDetected.transform);
vehicleCamera.SetParent (fatherDetected.transform);
}
public void setNullParent ()
{
transform.SetParent (null);
vehicleCamera.SetParent (null);
}
//activate the collider in the center of mass of the vehicle to dectect collisions with a new surface when the gravity control is enabled
IEnumerator activateCollider ()
{
//wait to avoid enable the collider when the vehicle stills in the ground
yield return new WaitForSeconds (0.2f);
//if the vehicle is searching surface, then active the collider
if (searchingSurface || searchingNewSurfaceBelow || searchAround) {
gravityCenterCollider.enabled = true;
}
}
//enable the gravity control in the direction of the camera
public void activateGravityPower (Vector3 dir, Vector3 right)
{
StartCoroutine (activateCollider ());
searchingNewSurfaceBelow = false;
removeParent ();
circumnavigableSurfaceFound = false;
searchingSurface = true;
searchAround = true;
gravityPowerActive = true;
forwardAxisMovement = dir;
rightAxisCamera = right;
powerActivated = true;
//enable the gravity control in the vehicle controller
vehicleCameraManager.usingBoost (true, "Regular Gravity Control", true, true);
if (mainVehicleControllerLocated) {
mainVehicleController.changeGravityControlUse (true);
}
}
//disaable the gravity control, rotatin the vehicle to the regular gravity
public void deactivateGravityPower ()
{
//check that the vehicle was searching a new surface, or that the gravity is different than vector3.up
if (searchingSurface || searchingNewSurfaceBelow || searchAround || currentNormal != regularGravity) {
conservateSpeed = true;
gravityCenterCollider.enabled = false;
accelerating = false;
circumnavigableSurfaceFound = false;
removeParent ();
searchingNewSurfaceBelow = false;
searchingSurface = false;
searchAround = false;
recalculatingSurface = false;
powerActivated = false;
//if the current normal before reset the gravity to the regular one is different from vectore.up, then rotate the vehicle back to the regular state
if (currentNormal != regularGravity) {
if (rotateVehicleCoroutine != null) {
StopCoroutine (rotateVehicleCoroutine);
}
rotateVehicleCoroutine = StartCoroutine (rotateToSurface (regularGravity, 2));
}
gravityPowerActive = false;
//set the normal in the vehicle controller
if (mainVehicleControllerLocated) {
mainVehicleController.setNormal (regularGravity);
}
//disable the gravity control in the vehicle controller
vehicleCameraManager.usingBoost (false, "stopShake", true, true);
if (mainVehicleControllerLocated) {
mainVehicleController.changeGravityControlUse (false);
}
}
}
//the player is getting on or off from the vehicle, so enable or disable the graivty control component
public void changeGravityControlState (bool state)
{
gravityControlEnabled = state;
//if the vehicle is not being driving, and it wasn't in the ground, deactivate the gravity control
if (!gravityControlEnabled && !OnGround) {
deactivateGravityPower ();
accelerating = false;
}
}
//rotate the vehicle and its camera to the new found surface, using the normal of that surface
public IEnumerator rotateToSurface (Vector3 normal, int rotSpeed)
{
previousVelocity = mainRigidbody.linearVelocity;
//the vehicle is being rotate, so set its velocity to 0
rotating = true;
currentNormal = normal;
//set the new normal in the vehicle controller
if (mainVehicleControllerLocated) {
mainVehicleController.setNormal (currentNormal);
}
//get the current rotation of the vehicle and the camera
Quaternion currentVehicleRotation = transform.rotation;
Quaternion currentVehicleCameraRotation = vehicleCamera.rotation;
Vector3 currentVehicleForward = Vector3.Cross (transform.right, normal);
Quaternion targetVehicleRotation = Quaternion.LookRotation (currentVehicleForward, normal);
Vector3 currentVehicleCameraForward = Vector3.Cross (vehicleCamera.right, normal);
Quaternion targetVehicleCameraRotation = Quaternion.LookRotation (currentVehicleCameraForward, normal);
//rotate from their rotation to thew new surface normal direction
for (float t = 0; t < 1;) {
t += Time.deltaTime * rotSpeed;
vehicleCamera.rotation = Quaternion.Slerp (currentVehicleCameraRotation, targetVehicleCameraRotation, t);
transform.rotation = Quaternion.Slerp (currentVehicleRotation, targetVehicleRotation, t);
yield return null;
}
rotating = false;
//store the current vehicle velocity to set it again once the rotation is finished, is only applied when the gravity control is disabled
if (conservateSpeed) {
mainRigidbody.linearVelocity = previousVelocity;
}
conservateSpeed = false;
}
public void setUseCenterPointActiveState (bool state, Transform newCenterPoint)
{
useCenterPointActive = state;
currentCenterPoint = newCenterPoint;
}
public void rotateVehicleToRaycastDirection (Vector3 raycastDirection)
{
if (rotating) {
return;
}
print ("ROTATE");
if (lastTimeRotateVehicleToRaycastDirection != 0) {
if (Time.time < lastTimeRotateVehicleToRaycastDirection + 0.5f) {
return;
}
}
lastTimeRotateVehicleToRaycastDirection = Time.time;
pos = settings.centerOfMass.position;
dir = raycastDirection;
//if the raycast found a new surface, then
if (Physics.Raycast (pos, dir, out hit, Mathf.Infinity, settings.layer)) {
//check is not a trigger or a rigidbody
if (!hit.collider.isTrigger && hit.rigidbody == null) {
//a new valid surface has been detected, so stop the search of a new surface
searchingNewSurfaceBelow = false;
searchingSurface = false;
searchAround = false;
powerActivated = false;
addPreviousVelocityMagnitude = true;
if (mainRigidbody.linearVelocity.magnitude != 0) {
previousVelocityMagnitude = mainRigidbody.linearVelocity.magnitude;
}
//set to 0 the vehicle velocity
mainRigidbody.linearVelocity = Vector3.zero;
//disable the collider in the center of mass
gravityCenterCollider.enabled = false;
//if the surface can be circumnavigate
if (hit.collider.gameObject.CompareTag (settings.tagForCircumnavigate)) {
circumnavigableSurfaceFound = true;
}
//if the surface is moving
if (hit.collider.gameObject.CompareTag (settings.tagForMovingObjects)) {
addParent (hit.collider.gameObject);
}
//if the new normal is different from the current normal, which means that is other surface inclination, then
if (hit.normal != currentNormal) {
//rotate the vehicle according to that normal
if (rotateVehicleCoroutine != null) {
StopCoroutine (rotateVehicleCoroutine);
}
rotateVehicleCoroutine = StartCoroutine (rotateToSurface (hit.normal, 2));
}
//disable the gravity control in the vehicle controller
if (mainVehicleControllerLocated) {
mainVehicleController.changeGravityControlUse (false);
}
vehicleCameraManager.usingBoost (false, "StopShake", true, true);
if (rotateVehicleCoroutine != null) {
StopCoroutine (rotateVehicleCoroutine);
}
rotateVehicleCoroutine = StartCoroutine (rotateVehicleToLandSurfaceCoroutine (hit.normal));
}
}
}
public void rotateVehicleToLandSurface (Vector3 hitNormal)
{
if (rotating && hitNormal == currentNormal) {
return;
}
if (rotateVehicleCoroutine != null) {
StopCoroutine (rotateVehicleCoroutine);
}
rotateVehicleCoroutine = StartCoroutine (rotateVehicleToLandSurfaceCoroutine (hitNormal));
}
public IEnumerator rotateVehicleToLandSurfaceCoroutine (Vector3 hitNormal)
{
rotating = true;
currentNormal = hitNormal;
//set the new normal in the vehicle controller
if (mainVehicleControllerLocated) {
mainVehicleController.setNormal (currentNormal);
}
//get the current rotation of the vehicle and the camera
Quaternion currentVehicleRotation = transform.rotation;
Quaternion currentVehicleCameraRotation = vehicleCamera.rotation;
Vector3 currentVehicleForward = Vector3.Cross (transform.right, hitNormal);
Quaternion targetVehicleRotation = Quaternion.LookRotation (currentVehicleForward, hitNormal);
Vector3 currentVehicleCameraForward = Vector3.Cross (vehicleCamera.right, hitNormal);
Quaternion targetVehicleCameraRotation = Quaternion.LookRotation (currentVehicleCameraForward, hitNormal);
//rotate from their rotation to thew new surface normal direction
for (float t = 0; t < 1;) {
t += Time.deltaTime * 2;
vehicleCamera.rotation = Quaternion.Slerp (currentVehicleCameraRotation, targetVehicleCameraRotation, t);
transform.rotation = Quaternion.Slerp (currentVehicleRotation, targetVehicleRotation, t);
yield return null;
}
rotating = false;
pauseDownForce (false);
if (addPreviousVelocityMagnitude) {
mainRigidbody.linearVelocity += previousVelocityMagnitude * (-currentNormal);
addPreviousVelocityMagnitude = false;
}
}
//get the current camera pivot, according to the vehicle view, in fisrt or third person
public void getCurrentCameraPivot (Transform newPivot)
{
pivot = newPivot;
}
public void pauseDownForce (bool state)
{
useGravity = !state;
}
public void setCustomNormal (Vector3 normal)
{
Quaternion currentVehicleRotation = transform.rotation;
Quaternion currentVehicleCameraRotation = vehicleCamera.rotation;
Vector3 currentVehicleForward = Vector3.Cross (transform.right, normal);
Quaternion targetVehicleRotation = Quaternion.LookRotation (currentVehicleForward, normal);
Vector3 currentVehicleCameraForward = Vector3.Cross (vehicleCamera.right, normal);
Quaternion targetVehicleCameraRotation = Quaternion.LookRotation (currentVehicleCameraForward, normal);
transform.rotation = targetVehicleRotation;
vehicleCamera.rotation = targetVehicleCameraRotation;
currentNormal = normal;
}
public override Vector3 getCurrentNormal ()
{
return currentNormal;
}
public float getGravityForce ()
{
return gravityForce;
}
public void setNewGravityForce (float newValue)
{
gravityForce = newValue;
}
public void setOriginalGravityForce ()
{
setNewGravityForce (originalGravityForce);
}
public override bool isUsingRegularGravity ()
{
return currentNormal == regularGravity;
}
public Vector3 getRegularGravity ()
{
return regularGravity;
}
public void updateCurrentNormalExternally (Vector3 newValue)
{
currentNormal = newValue;
}
public bool changeDriverGravityWhenGetsOffActive ()
{
return changeDriverGravityWhenGetsOff;
}
public bool isSetVehicleRegularGravityOnDriverGetOffActive ()
{
return setVehicleRegularGravityOnDriverGetOff;
}
public void setGravityForcePausedState (bool state)
{
gravityForcePaused = state;
}
public bool isGravityPowerActive ()
{
return gravityPowerActive;
}
public bool isGravityControlEnabled ()
{
return gravityControlEnabled;
}
//CALL INPUT FUNCTIONS
public void inputEnableOrDisableGravityControl (bool enableGravityControl)
{
if (HUDManager.vehicleIsDestroyed ()) {
return;
}
if (!mainVehicleController.isPlayerMovingOn3dWorld ()) {
return;
}
//if the vehicle is being driving
if (gravityControlEnabled && settings.canUseGravityControl) {
//activate the gravity control to search a new surface in the camera direction
if (enableGravityControl) {
activateGravityPower (pivot.TransformDirection (Vector3.forward), pivot.TransformDirection (Vector3.right));
} else {
//deactivate the gravity control
deactivateGravityPower ();
}
}
}
public void inputIncreasOrDecreaseGravitySpeed (bool increaseGravitySpeed)
{
if (HUDManager.vehicleIsDestroyed ()) {
return;
}
if (gravityControlEnabled && settings.canUseGravityControl) {
if (searchingSurface || searchingNewSurfaceBelow || gravityPowerActive) {
//if the vehicle is searching a new surface, increase its velocity, only when the gravity power is active
if (increaseGravitySpeed) {
accelerating = true;
vehicleCameraManager.usingBoost (true, "Quick Gravity Control", true, true);
} else {
//stop to increase the velocity of the vehiclee in the air
accelerating = false;
vehicleCameraManager.usingBoost (true, "Regular Gravity Control", true, true);
}
}
}
}
public void setCheckDownSpeedActiveState (bool state)
{
checkDownSpeedActive = state;
}
#if UNITY_EDITOR
//draw the ray distance radius in the vehicle
void OnDrawGizmosSelected ()
{
if (showGizmo) {
if (settings.centerOfMass != null) {
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere (settings.centerOfMass.position, settings.vehicleRadius);
Gizmos.color = Color.cyan;
Gizmos.DrawLine (settings.centerOfMass.position, settings.centerOfMass.position - settings.rayDistance * settings.centerOfMass.up);
}
}
}
#endif
[System.Serializable]
public class otherSettings
{
public LayerMask layer;
public float speed = 10;
public float accelerateSpeed = 20;
public float velocityToSearch = 10;
public float gravityMultiplier = 1;
public float rayDistance;
public float vehicleRadius;
public Transform centerOfMass;
public bool canUseGravityControl;
public float massDivider = 1000;
public string tagForCircumnavigate = "sphere";
public string tagForMovingObjects = "moving";
}
}