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

2523 lines
85 KiB
C#

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.Events;
using System.Linq;
public class gravitySystem : gravityObjectManager
{
public bool gravityPowerEnabled;
public bool gravityPowerInputEnabled;
public Transform gravityCenter;
public GameObject playerCameraGameObject;
public bool liftToSearchEnabled;
public bool randomRotationOnAirEnabled;
public GameObject cursor;
public LayerMask layer;
public float searchSurfaceSpeed = 5;
public float accelerateSpeed = 20;
public float airControlSpeed = 5;
bool cursorActive;
bool cursorLocated;
public bool preserveVelocityWhenDisableGravityPower;
float extraMultiplierPreserveVelocity;
public float highGravityMultiplier;
public List<bool> materialToChange = new List<bool> ();
public bool changeModelColor;
public Color powerColor;
public float hoverSpeed;
public float hoverAmount;
public float hoverSmooth;
public GameObject arrow;
bool arrowLocated;
public bool powerActivated;
public bool recalculatingSurface;
public bool searchingSurface;
public bool searchingNewSurfaceBelow;
public bool searchAround;
public Vector3 currentNormal = new Vector3 (0, 1, 0);
public bool dead;
public bool firstPersonView;
public Renderer playerRenderer;
public bool usedByAI;
public string tagForCircumnavigate = "sphere";
public string tagForMovingObjects = "moving";
public float rotateToSurfaceSpeed = 2;
public float rotateToRegularGravitySpeed = 2;
public Vector3 regularGravity = new Vector3 (0, 1, 0);
public bool gravityPowerActive;
public bool startWithNewGravity;
public bool usePlayerRotation;
public bool adjustRotationToSurfaceFound;
public Vector3 newGravityToStart;
public bool zeroGravityModeOn;
public bool startWithZeroGravityMode;
public bool canResetRotationOnZeroGravityMode;
public bool canAdjustToForwardSurface;
public Transform forwardSurfaceRayPosition;
public float maxDistanceToAdjust;
public float resetRotationZeroGravitySpeed;
public float adjustToForwardSurfaceSpeed;
public bool canActivateFreeFloatingMode;
public bool freeFloatingModeOn;
public bool useCustomDirectionOnResetZeroGravityRotation;
public Vector3 customDirectionOnResetZeroGravityRotation;
public bool useEventsOnFreeFloatingModeStateChange;
public UnityEvent evenOnFreeFloatingModeStateEnabled;
public UnityEvent eventOnFreeFloatingModeStateDisabled;
public bool useEventsOnZeroGravityModeStateChange;
public UnityEvent evenOnZeroGravityModeStateEnabled;
public UnityEvent eventOnZeroGravityModeStateDisabled;
public bool useEventsOnUseGravityPowerStateChange;
public UnityEvent eventsOnUseGravityPowerStateEnabled;
public UnityEvent eventsOnUseGravityPowerStateDisabled;
public float circumnavigateRotationSpeed = 10;
public bool circumnavigateCurrentSurfaceActive;
public bool useLerpRotation;
public Transform gravityAdherenceRaycastParent;
public bool checkSurfaceBelowLedge;
public float surfaceBelowLedgeRaycastDistance = 3;
public float belowLedgeRotationSpeed = 10;
public Transform surfaceBelowRaycastTransform;
public bool checkSurfaceInFront;
public float surfaceInFrontRaycastDistance = 0.5f;
public float surfaceInFrontRotationSpeed = 10;
public Transform surfaceInFrontRaycastTransform;
public bool checkCircumnavigateSurfaceOnZeroGravity = true;
public bool searchNewSurfaceOnHighFallSpeed = true;
public float minSpeedToSearchNewSurface = 15;
bool searchNewSurfaceOnHighFallSpeedPaused;
public bool pauseSearchNewSurfaceOnHighFallSpeedOnReverseGravityInput = true;
public bool shakeCameraOnHighFallSpeed = true;
public float minSpeedToShakeCamera = 15;
bool cameraShakeCanBeUsed = true;
public bool checkSurfaceBelowOnRegularState;
public float timeToSetNullParentOnAir = 0.5f;
float lastTimeParentFound;
public bool stopAimModeWhenSearchingSurface;
public Transform pivotCameraTransform;
public SphereCollider gravityCenterCollider;
public playerController playerControllerManager;
public otherPowers powers;
public CapsuleCollider playerCollider;
public playerInputManager playerInput;
public playerWeaponsManager weaponsManager;
public Rigidbody mainRigidbody;
public playerCamera playerCameraManager;
public Transform mainCameraTransform;
public Vector3 debugGravityDirection;
public bool hovering;
public bool turning;
public bool checkGravityArrowStateActive = true;
public float raycastDistanceToCheckBelowPlayer = 10;
public bool useInfiniteRaycastDistanceToCheckBelowPlayer;
public bool updateCurrentNormalByExternalTransformActive;
Transform currentUpdateCurrentNormalByExternalTransform;
public bool allowCircumnavigationOnAllSurfacesWithIgnoretagList;
public List<string> circumnavigationOnAllSurfacesWithIgnoretagList = new List<string> ();
bool circumnavigationOnAllSurfacesWithIgnoretagListAssigned;
bool ignoreUseGravityCenterForRotationActive;
public bool setOnGroundStateOnTeleportToSurfaceOnZeroGravity;
bool ignoreRecalculateSurface;
Transform currentCenterPoint;
bool currentCenterPointAssigned;
zeroGravityRoomSystem currentZeroGravityRoom;
Transform playerCameraTransform;
Vector3 currentPlayerPosition;
Quaternion arrowRotation;
Color originalPowerColor;
bool accelerating;
bool rotating = false;
Vector3 gravityDirection;
Vector3 rightAxis;
float timer = 0.75f;
float rotateAmount = 40;
float normalGravityMultiplier;
Vector3 surfaceNormal;
Vector3 turnDirection;
bool playerIsChildOfParentActive;
GameObject fatherDetected;
bool circumnavigableSurfaceFound;
RaycastHit hit;
Ray ray;
public bool choosingDirection;
bool onGround;
bool lifting;
Coroutine rotateCharacterState;
Coroutine rotateToSurfaceState;
Transform externalGravityCenter;
Transform currentSurfaceBelowPlayer;
Transform previousSurfaceBelowPlayer;
Vector3 currentPosition;
bool preservingVelocity;
Vector3 previousRigidbodyVelocity;
bool playerInsideGravityRoom;
Vector3 rayPosition;
Vector3 rayDirection;
Vector3 currentRotatingNormal;
Coroutine colorCoroutine;
public setGravity currentSetGravityManager;
bool surfaceFound;
RaycastHit currentSurfaceFound;
float currentCircumnagivateRotationSpeed;
Vector2 axisValues;
float verticalInput;
float horizontalInput;
Vector3 moveInput;
float gravityAdherenceRaycastParentAngleRotation;
Coroutine zeroGravityModeRotateCharacterCoroutine;
Coroutine teleportCoroutine;
Coroutine freeFloatingModeCoroutine;
bool gravityArrowCurrentlyActive;
Transform playerTransform;
bool teleportInProcess;
bool startWithZeroGravityModeChecked;
bool cameraShakeActive;
//Editor variables
public bool showCircumnavigationhSettings;
public bool showZeroGravitySettings;
public bool showFreeFloatingModeSettings;
public bool showEventsSettings;
public bool showOtherSettings;
public bool showDebugSettings;
public bool showAllSettings;
public bool showComponents;
public bool showGizmo;
Vector3 vector3Zero = Vector3.zero;
Quaternion quaternionIdentity = Quaternion.identity;
void Awake ()
{
normalGravityMultiplier = playerControllerManager.getGravityMultiplier ();
playerTransform = transform;
//get the pivot of the camera
playerCameraTransform = playerCameraGameObject.transform;
}
void Start ()
{
mainRigidbody.freezeRotation = true;
//the gravity center has a sphere collider, that surrounds completly the player to use it when the player searchs a new surface,
//detecting the collision with any object to rotate the player to that surface
//this is done like this to avoid that the player cross a collider when he moves while he searchs a new surface
//get all the neccessary components in the player
//get the original value of some parameters
originalPowerColor = powerColor;
GameObject newGravityCenter = new GameObject ();
externalGravityCenter = newGravityCenter.transform;
externalGravityCenter.name = "External Gravity Center";
externalGravityCenter.SetParent (playerTransform);
if (startWithNewGravity) {
if (usePlayerRotation) {
Vector3 normalDirection = -playerTransform.up;
if (adjustRotationToSurfaceFound) {
if (Physics.Raycast (playerTransform.position, -playerTransform.up, out hit, Mathf.Infinity, layer)) {
normalDirection = hit.normal;
}
}
if (playerTransform.up != currentNormal) {
setNormal (normalDirection);
}
} else {
setNormal (newGravityToStart);
}
}
currentRotatingNormal = currentNormal;
if (arrow != null) {
arrowLocated = true;
if (checkGravityArrowStateActive) {
if (arrow.activeSelf) {
arrow.SetActive (false);
}
} else {
gravityArrowCurrentlyActive = true;
}
}
if (cursor != null) {
cursorLocated = true;
}
}
void Update ()
{
currentPosition = playerTransform.position;
checkGravityArrowState ();
if (!startWithZeroGravityModeChecked) {
if (startWithZeroGravityMode) {
setZeroGravityModeOnState (true);
}
startWithZeroGravityModeChecked = true;
}
//elevate the player above the ground when the gravity power is enabled and the player was in the ground before it
if (lifting) {
bool surfaceAbove = false;
//check if there is any obstacle above the player while he is being elevated, to prevent he can cross any collider
ray = new Ray (currentPosition + 1.5f * playerTransform.up, playerTransform.up);
if (Physics.SphereCast (ray, 0.4f, out hit, 0.5f, layer)) {
surfaceAbove = true;
} else {
//if the ray doesn't found any surface, keep lifting the player until the timer reachs its target value
timer -= Time.deltaTime;
playerTransform.Translate ((Time.deltaTime * 4) * Vector3.up);
playerCameraTransform.Translate ((Time.deltaTime * 4) * Vector3.up);
}
//if the timer ends or a surface is found, stop the lifting and start rotate the player to float in the air
if (surfaceAbove || timer < 0) {
lifting = false;
timer = 0.75f;
searchingSurface = false;
searchAround = false;
if (canRotatePlayer ()) {
rotateMeshPlayer ();
}
setHoverState (true);
}
}
//moving in the air with the power gravity activated looking for a new surface
if (searchingSurface) {
//parameters to store the position and the direction of the raycast that checks any close surface to the player
rayPosition = vector3Zero;
rayDirection = vector3Zero;
//set the size of the ray
float rayDistance = 0;
//if the player has set the direction of the air movement, the raycast starts in camera pivot position
//else the player is falling and reach certain amount of velocity, so the next surface that he will touch becomes in his new ground
//and the raycast starts in the player position
if (!searchingNewSurfaceBelow) {
rayDistance = 2;
Vector3 newVelocity = (Mathf.Abs (playerControllerManager.getGravityForce ()) * mainRigidbody.mass * searchSurfaceSpeed) * gravityDirection;
//when the player searchs a new surface using the gravity force, the player can moves like when he falls
if (!playerControllerManager.isPlayerRunning ()) {
//get the global input and convert it to the local direction, using the axis in the changegravity script
Vector3 forwardAxis = Vector3.Cross (gravityDirection, rightAxis);
Vector3 newMoveInput = playerControllerManager.getVerticalInput () * forwardAxis + playerControllerManager.getHorizontalInput () * rightAxis;
if (newMoveInput.magnitude > 1) {
newMoveInput.Normalize ();
}
if (newMoveInput.magnitude > 0) {
newVelocity += airControlSpeed * newMoveInput;
}
}
//apply and extra force if the player increase his movement
if (accelerating) {
newVelocity += accelerateSpeed * gravityDirection;
}
//make a lerp of the velocity applied to the player to move him smoothly
mainRigidbody.linearVelocity = Vector3.Lerp (mainRigidbody.linearVelocity, newVelocity, Time.deltaTime * 2);
//set the direction of the ray that checks any surface
rayPosition = pivotCameraTransform.position;
rayDirection = gravityDirection;
if (currentNormal == regularGravity) {
rayDistance = GKC_Utils.distance (rayPosition, currentPosition) + 0.5f;
}
}
//else, the player is falling in his ground direction, so the ray to check a new surface is below his feet
else {
rayPosition = currentPosition;
rayDirection = -playerTransform.up;
rayDistance = 0.6f;
}
if (showGizmo) {
//launch a raycast to check any surface
Debug.DrawRay (rayPosition, rayDistance * rayDirection, Color.yellow);
}
if (Physics.Raycast (rayPosition, rayDirection, out hit, rayDistance, layer)) {
//if the object detected has not trigger and rigidbody, then
if (!hit.collider.isTrigger && hit.rigidbody == null) {
//disable the search of the surface and rotate the player to that surface
playerControllerManager.setGravityPowerActiveState (false);
playerCameraManager.sethorizontalCameraLimitActiveOnAirState (true);
setPowerActivateState (false);
searchingNewSurfaceBelow = false;
searchingSurface = false;
searchAround = false;
mainRigidbody.linearVelocity = vector3Zero;
//disable the collider in the gravity center and enable the capsule collider in the player
gravityCenterCollider.enabled = false;
playerCollider.isTrigger = false;
//check if the object detected can be circumnavigate
if (hit.collider.gameObject.CompareTag (tagForCircumnavigate) || canCircumnavigateObject (hit.collider.transform)) {
circumnavigableSurfaceFound = true;
}
//check if the object is moving to parent the player inside it
if (hit.collider.gameObject.CompareTag (tagForMovingObjects)) {
addParent (hit.collider.gameObject);
}
//set the camera in its regular position
playerCameraManager.changeCameraFov (false);
//if the new normal is different from the previous normal in the gravity power, then rotate the player
if (hit.normal != currentNormal) {
checkRotateToSurface (hit.normal, rotateToSurfaceSpeed);
}
//if the player back to the regular gravity value, change its color to the regular state
if (hit.normal == regularGravity) {
changeColor (false);
}
}
}
if (!turning && canRotatePlayer ()) {
rotateMeshPlayer ();
}
}
//if the player falls and reachs certain velocity, the camera shakes and the mesh of the player rotates
//also, if the gravity power is activated, look a new surface to change the gravity to the found surface
if (!freeFloatingModeOn &&
!zeroGravityModeOn &&
!onGround &&
!searchingNewSurfaceBelow &&
!choosingDirection &&
!powerActivated &&
!playerControllerManager.isFlyingActive () &&
!playerControllerManager.isSwimModeActive () &&
!playerControllerManager.isPauseCameraShakeFromGravityActive ()) {
if (shakeCameraOnHighFallSpeed && playerTransform.InverseTransformDirection (mainRigidbody.linearVelocity).y < -minSpeedToShakeCamera) {
if (!playerControllerManager.isSlowFallExternallyActive ()) {
enableCameraShake ();
if (!weaponsManager.isCarryingWeaponInThirdPerson ()) {
rotateMeshPlayer ();
}
}
}
if (searchNewSurfaceOnHighFallSpeed &&
!searchNewSurfaceOnHighFallSpeedPaused &&
playerTransform.InverseTransformDirection (mainRigidbody.linearVelocity).y < -minSpeedToSearchNewSurface) {
//if the gravity of the player is different from the regular gravity, start searchin the new surface
if (currentNormal != regularGravity) {
searchingNewSurfaceBelow = true;
searchingSurface = true;
recalculatingSurface = false;
circumnavigableSurfaceFound = false;
}
}
}
//walk in spheres and moving objects, recalculating his new normal and lerping the player to the new rotation
if (!lifting && !searchingSurface && (circumnavigableSurfaceFound || playerIsChildOfParentActive) && recalculatingSurface && !rotating) {
float rayDistance = 0.5f;
if (!onGround) {
if (!freeFloatingModeOn && !zeroGravityModeOn) {
rayDistance = raycastDistanceToCheckBelowPlayer;
if (useInfiniteRaycastDistanceToCheckBelowPlayer) {
rayDistance = 1000;
}
}
}
surfaceFound = false;
//get the normal direction of the object below the player, to recalculate the rotation of the player
if (Physics.Raycast (currentPosition + 0.1f * playerTransform.up, -playerTransform.up, out hit, rayDistance, layer)) {
currentSurfaceFound = hit;
surfaceFound = true;
currentCircumnagivateRotationSpeed = circumnavigateRotationSpeed;
}
//Get the correct raycast orientation according to input, for example, it is no the same ray position and direction if the player is walking forward or backward on
//first person or if he is aiming
if (checkSurfaceBelowLedge || checkSurfaceInFront) {
rayPosition = currentPosition + 0.1f * playerTransform.up;
if (playerControllerManager.isLookingInCameraDirection ()) {
axisValues = playerInput.getPlayerRawMovementAxis ();
verticalInput = axisValues.y;
horizontalInput = axisValues.x;
rayPosition += (verticalInput * 0.2f) * playerTransform.forward;
rayPosition += (horizontalInput * 0.2f) * playerTransform.right;
moveInput = (verticalInput * playerTransform.forward + horizontalInput * playerTransform.right);
gravityAdherenceRaycastParentAngleRotation = Vector3.SignedAngle (playerTransform.forward, moveInput, playerTransform.up);
if (verticalInput == 0 && horizontalInput == 0) {
gravityAdherenceRaycastParentAngleRotation = 0;
}
} else {
rayPosition += 0.2f * playerTransform.forward;
gravityAdherenceRaycastParentAngleRotation = 0;
}
gravityAdherenceRaycastParent.localRotation = Quaternion.Euler (new Vector3 (0, gravityAdherenceRaycastParentAngleRotation, 0));
}
if (checkSurfaceBelowLedge) {
rayDirection = -playerTransform.up;
if (showGizmo) {
Debug.DrawRay (rayPosition, rayDirection, Color.white);
}
if (!Physics.Raycast (rayPosition, rayDirection, out hit, 1, layer)) {
if (showGizmo) {
Debug.DrawRay (rayPosition, rayDirection, Color.green);
}
rayPosition = surfaceBelowRaycastTransform.position;
rayDirection = surfaceBelowRaycastTransform.forward;
if (Physics.Raycast (rayPosition, rayDirection, out hit, surfaceBelowLedgeRaycastDistance, 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 (checkSurfaceInFront) {
rayPosition = surfaceInFrontRaycastTransform.position;
rayDirection = surfaceInFrontRaycastTransform.forward;
if (Physics.Raycast (rayPosition, rayDirection, out hit, surfaceInFrontRaycastDistance, layer)) {
currentSurfaceFound = hit;
surfaceFound = true;
currentCircumnagivateRotationSpeed = surfaceInFrontRotationSpeed;
}
}
bool surfaceNormalFound = false;
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 (tagForCircumnavigate) || canCircumnavigateObject (currentSurfaceFound.transform)) {
surfaceNormal = currentSurfaceFound.normal;
surfaceNormalFound = true;
}
//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 (tagForMovingObjects)) {
surfaceNormal = currentSurfaceFound.normal;
if (!playerIsChildOfParentActive) {
addParent (currentSurfaceFound.collider.gameObject);
}
surfaceNormalFound = true;
}
}
} else {
if (playerIsChildOfParentActive) {
removeParent ();
}
}
if (currentCenterPointAssigned) {
if (surfaceNormalFound) {
Vector3 heading = playerTransform.position - currentCenterPoint.position;
float distance = heading.magnitude;
Vector3 direction = heading / distance;
surfaceNormal = direction;
}
}
if ((!zeroGravityModeOn && !freeFloatingModeOn) || onGround) {
if (useLerpRotation) {
//recalculate the rotation of the player and the camera according to the normal of the surface under the player
currentNormal = Vector3.Lerp (currentNormal, surfaceNormal, currentCircumnagivateRotationSpeed * Time.deltaTime);
Vector3 myForward = Vector3.Cross (playerTransform.right, currentNormal);
Quaternion dstRot = Quaternion.LookRotation (myForward, currentNormal);
playerTransform.rotation = Quaternion.Lerp (playerTransform.rotation, dstRot, currentCircumnagivateRotationSpeed * Time.deltaTime);
Vector3 myForwardCamera = Vector3.Cross (playerCameraTransform.right, currentNormal);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, currentNormal);
playerCameraTransform.rotation = Quaternion.Lerp (playerCameraTransform.rotation, dstRotCamera, currentCircumnagivateRotationSpeed * Time.deltaTime);
} else {
currentNormal = Vector3.Slerp (currentNormal, surfaceNormal, currentCircumnagivateRotationSpeed * Time.deltaTime);
Vector3 myForward = Vector3.Cross (playerTransform.right, currentNormal);
Quaternion dstRot = Quaternion.LookRotation (myForward, currentNormal);
playerTransform.rotation = Quaternion.Slerp (playerTransform.rotation, dstRot, currentCircumnagivateRotationSpeed * Time.deltaTime);
Vector3 myForwardCamera = Vector3.Cross (playerCameraTransform.right, currentNormal);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, currentNormal);
playerCameraTransform.rotation = Quaternion.Slerp (playerCameraTransform.rotation, dstRotCamera, currentCircumnagivateRotationSpeed * Time.deltaTime);
}
updateCurrentRotatingNormal (currentNormal);
}
//set the normal in the playerController component
playerControllerManager.setCurrentNormalCharacter (currentNormal);
}
if (updateCurrentNormalByExternalTransformActive) {
currentNormal = currentUpdateCurrentNormalByExternalTransform.up;
playerControllerManager.setCurrentNormalCharacter (currentNormal);
updateCurrentRotatingNormal (currentNormal);
}
if (ignoreRecalculateSurface) {
recalculatingSurface = false;
gravityPowerActive = false;
}
if (zeroGravityModeOn && !onGround && !rotating) {
currentNormal = playerTransform.up;
playerControllerManager.setCurrentNormalCharacter (currentNormal);
updateCurrentRotatingNormal (currentNormal);
}
//set a cursor in the screen when the character can choose a direction to change his gravity
if (!usedByAI) {
if (cursorLocated) {
if (choosingDirection) {
if (!cursorActive) {
cursor.SetActive (true);
cursorActive = true;
}
}
if (!choosingDirection) {
if (cursorActive) {
cursor.SetActive (false);
cursorActive = false;
}
}
}
}
//if the player can choosed a direction, lerp his velocity to zero
if (choosingDirection) {
mainRigidbody.linearVelocity = Vector3.Lerp (mainRigidbody.linearVelocity, vector3Zero, Time.deltaTime * 2);
}
if (rotating && !playerControllerManager.isPlayerRunning ()) {
mainRigidbody.linearVelocity = vector3Zero;
}
if ((gravityPowerActive || circumnavigateCurrentSurfaceActive || (zeroGravityModeOn && checkCircumnavigateSurfaceOnZeroGravity)) && !powerActivated) {
currentSurfaceBelowPlayer = playerControllerManager.getCurrentSurfaceBelowPlayer ();
if (currentSurfaceBelowPlayer != null) {
//check if the object detected can be circumnavigate
if (currentSurfaceBelowPlayer.CompareTag (tagForCircumnavigate) || canCircumnavigateObject (currentSurfaceBelowPlayer)) {
circumnavigableSurfaceFound = true;
} else {
circumnavigableSurfaceFound = false;
if (checkSurfaceInFront) {
rayPosition = surfaceInFrontRaycastTransform.position;
rayDirection = surfaceInFrontRaycastTransform.forward;
if (Physics.Raycast (rayPosition, rayDirection, out hit, surfaceInFrontRaycastDistance, layer)) {
currentSurfaceBelowPlayer = hit.collider.transform;
if (currentSurfaceBelowPlayer.CompareTag (tagForCircumnavigate) || canCircumnavigateObject (currentSurfaceBelowPlayer)) {
circumnavigableSurfaceFound = true;
}
}
}
}
//check if the object is moving to parent the player inside it
if (currentSurfaceBelowPlayer.CompareTag (tagForMovingObjects)) {
if (previousSurfaceBelowPlayer != currentSurfaceBelowPlayer) {
previousSurfaceBelowPlayer = currentSurfaceBelowPlayer;
addParent (currentSurfaceBelowPlayer.gameObject);
}
} else if (playerIsChildOfParentActive && !currentSurfaceBelowPlayer.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 || playerIsChildOfParentActive) {
recalculatingSurface = true;
}
//else disable this state
else {
recalculatingSurface = false;
}
} else {
if (previousSurfaceBelowPlayer) {
previousSurfaceBelowPlayer = null;
}
if (rotating) {
circumnavigableSurfaceFound = false;
}
}
} else {
if ((circumnavigableSurfaceFound || playerIsChildOfParentActive) && rotating) {
circumnavigableSurfaceFound = false;
}
if (checkSurfaceBelowOnRegularState && !gravityPowerActive && !zeroGravityModeOn && !playerControllerManager.isPlayerSetAsChildOfParent ()) {
currentSurfaceBelowPlayer = playerControllerManager.getCurrentSurfaceBelowPlayer ();
if (currentSurfaceBelowPlayer != null) {
//check if the object is moving to parent the player inside it
if (previousSurfaceBelowPlayer != currentSurfaceBelowPlayer) {
previousSurfaceBelowPlayer = currentSurfaceBelowPlayer;
if (currentSurfaceBelowPlayer.CompareTag (tagForMovingObjects)) {
addParent (currentSurfaceBelowPlayer.gameObject);
lastTimeParentFound = Time.time;
} else if (playerIsChildOfParentActive && !currentSurfaceBelowPlayer.IsChildOf (fatherDetected.transform)) {
removeParent ();
}
}
} else {
if (previousSurfaceBelowPlayer != null) {
previousSurfaceBelowPlayer = null;
}
if (Time.time > timeToSetNullParentOnAir + lastTimeParentFound) {
if (playerIsChildOfParentActive) {
removeParent ();
}
}
}
} else {
if (currentSurfaceBelowPlayer != null) {
currentSurfaceBelowPlayer = null;
}
if (previousSurfaceBelowPlayer != null) {
previousSurfaceBelowPlayer = null;
}
}
}
}
public void setAllowCircumnavigationOnAllSurfacesWithIgnoretagListState (bool state)
{
allowCircumnavigationOnAllSurfacesWithIgnoretagList = state;
}
public void setCircumnavigationOnAllSurfacesWithIgnoretagList (List<string> newList)
{
circumnavigationOnAllSurfacesWithIgnoretagList = newList;
circumnavigationOnAllSurfacesWithIgnoretagListAssigned = circumnavigationOnAllSurfacesWithIgnoretagList.Count != 0;
}
bool canCircumnavigateObject (Transform objectToCheck)
{
bool result = false;
if (allowCircumnavigationOnAllSurfacesWithIgnoretagList) {
if (circumnavigationOnAllSurfacesWithIgnoretagListAssigned) {
if (!circumnavigationOnAllSurfacesWithIgnoretagList.Contains (objectToCheck.tag)) {
result = true;
}
} else {
result = true;
}
}
return result;
}
public void setUpdateCurrentNormalByExternalTransformState (bool state, Transform newTransform, bool ignoreRecalculateSurfaceValue)
{
updateCurrentNormalByExternalTransformActive = state;
currentUpdateCurrentNormalByExternalTransform = newTransform;
ignoreRecalculateSurface = ignoreRecalculateSurfaceValue;
if (!state) {
Vector3 newNormal = currentUpdateCurrentNormalByExternalTransform.up;
float currentAngleDifference = Vector3.Angle (regularGravity, newNormal);
if (Mathf.Abs (currentAngleDifference) < 1) {
newNormal = regularGravity;
}
currentNormal = newNormal;
playerControllerManager.setCurrentNormalCharacter (currentNormal);
updateCurrentRotatingNormal (currentNormal);
ignoreRecalculateSurface = false;
}
}
public void setIgnoreRecalculateSurfaceState (bool state)
{
ignoreRecalculateSurface = state;
}
//rotate randomly the mesh of the player in the air, also make that mesh float while chooses a direction in the air
void FixedUpdate ()
{
if (turning) {
if (randomRotationOnAirEnabled || powerActivated) {
gravityCenter.transform.Rotate ((rotateAmount * Time.deltaTime) * turnDirection);
}
if (weaponsManager.isCarryingWeaponInThirdPerson () || powers.isAimingPowerInThirdPerson ()) {
turning = false;
checkRotateCharacter (vector3Zero);
}
}
if (hovering) {
float posTargetY = Mathf.Sin (Time.time * hoverSpeed) * hoverAmount;
mainRigidbody.position = Vector3.MoveTowards (mainRigidbody.position, mainRigidbody.position + posTargetY * playerTransform.up, Time.deltaTime * hoverSmooth);
}
}
void checkGravityArrowState ()
{
//the arrow in the back of the player looks to the direction of the real gravity
if (arrowLocated) {
if (gravityArrowCurrentlyActive) {
currentPlayerPosition = new Vector3 (currentPosition.x, 0, currentPosition.z);
if (currentPlayerPosition != vector3Zero) {
arrowRotation = Quaternion.LookRotation (currentPlayerPosition);
if (arrowRotation.eulerAngles != vector3Zero) {
arrow.transform.rotation = arrowRotation;
}
}
if (checkGravityArrowStateActive) {
if (!powerActivated && !searchingSurface && currentNormal == regularGravity) {
gravityArrowCurrentlyActive = false;
arrow.SetActive (false);
}
}
} else {
if (powerActivated || searchingSurface || currentNormal != regularGravity) {
gravityArrowCurrentlyActive = true;
arrow.SetActive (true);
}
}
}
}
public void checkOnGroundOrAirState ()
{
onGroundOrOnAir (playerControllerManager.isPlayerOnGround ());
}
//playerController set the values of ground in this script and in the camera code
public override void onGroundOrOnAir (bool state)
{
onGround = state;
if (onGround) {
//the player is on the ground
//set the states in the camera, on ground, stop any shake of the camera, and back the camera to its regular position if it has been moved
playerCameraManager.onGroundOrOnAir (true);
disableCameraShake ();
playerCameraManager.changeCameraFov (false);
//stop rotate the player
turning = false;
//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 || playerIsChildOfParentActive) && (gravityPowerActive || circumnavigateCurrentSurfaceActive || (zeroGravityModeOn && checkCircumnavigateSurfaceOnZeroGravity))) {
recalculatingSurface = true;
}
//else disable this state
else {
recalculatingSurface = false;
}
//set the gravity force applied to the player to its regular state
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
//set the model rotation to the regular state
checkRotateCharacter (vector3Zero);
accelerating = false;
if (currentNormal != regularGravity) {
gravityPowerActive = true;
}
} else {
//the player is on the air
playerCameraManager.onGroundOrOnAir (false);
}
}
//when the player searchs a new surface using the gravity power on button, check the collisions in the gravity center sphere collider, to change the
//gravity of the player to the detected normal direction
void OnCollisionEnter (Collision collision)
{
//check that the player is searching a surface, the player is not running, and that he is searching around
if (searchingSurface && turning && searchAround && !playerControllerManager.isPlayerRunning ()) {
//check that the detected object is not a trigger or the player himself
if (!collision.gameObject.CompareTag ("Player") && collision.rigidbody == null && !collision.collider.isTrigger) {
//get the collision contant point to change the direction of the ray that searchs a new direction, setting the direction from the player
//to the collision point as the new direction
Vector3 hitDirection = collision.contacts [0].point - pivotCameraTransform.position;
hitDirection = hitDirection / hitDirection.magnitude;
gravityDirection = hitDirection;
searchAround = false;
}
}
}
//now the gravity power is in a function, so it can be called from keyboard and a touch button
public void activateGravityPower ()
{
gravityPowerActive = true;
// print ("activate gravity power");
//if the option to lift the player when he uses the gravity power is disable, then searchs an new surface in the camera direction
if (!liftToSearchEnabled) {
changeOnTrigger (mainCameraTransform.TransformDirection (Vector3.forward), mainCameraTransform.TransformDirection (Vector3.right));
}
//else lift the player, and once that he has been lifted, then press again the gravit power on button to search an new surface
//or disable the gravity power
else {
//enable the sphere collider in the gravity center
gravityCenterCollider.enabled = true;
//disable the capsule collider in the player
playerCollider.isTrigger = true;
//get the last time that the player was in the air
playerControllerManager.lastTimeFalling = Time.time;
recalculatingSurface = false;
accelerating = false;
//change the color of the player's textures
changeColor (true);
searchingNewSurfaceBelow = false;
removeParent ();
circumnavigableSurfaceFound = false;
playerControllerManager.setGravityPowerActiveState (true);
playerCameraManager.sethorizontalCameraLimitActiveOnAirState (false);
setPowerActivateState (true);
//calibrate the accelerometer to rotate the camera in this mode
playerCameraManager.calibrateAccelerometer ();
//drop any object that the player is holding and disable aim mode
if (stopAimModeWhenSearchingSurface) {
checkKeepPower ();
checkKeepWeapons ();
}
playerCameraManager.checkIfDropObjectIfNotPhysical (false);
//the player is in the ground, so he is elevated above it
if (onGround) {
lifting = true;
choosingDirection = true;
}
//the player set the direction of the movement in the air to search a new surface
if (!lifting && choosingDirection) {
enableCameraShake ();
setHoverState (false);
if (canRotatePlayer ()) {
rotateMeshPlayer ();
}
searchingSurface = true;
circumnavigableSurfaceFound = false;
removeParent ();
choosingDirection = false;
searchAround = true;
gravityDirection = mainCameraTransform.forward;
//get direction and right axis of the camera, so when the player searchs a new surface, this is used to get the local movement,
//which allows to move the player in his local right, left, forward and back while he also displaces in the air
rightAxis = mainCameraTransform.right;
if (canRotatePlayer ()) {
checkRotateCharacter (-gravityDirection);
}
return;
}
//the player is in the air, so he is stopped in it to choose a direction
if (!onGround && !choosingDirection && !lifting) {
disableCameraShake ();
playerCameraManager.changeCameraFov (false);
setHoverState (true);
if (canRotatePlayer ()) {
rotateMeshPlayer ();
}
choosingDirection = true;
searchingSurface = false;
searchAround = false;
}
}
}
//now the gravity power is in a function, so it can be called from keyboard and a touch button
public void deactivateGravityPower ()
{
//check that the power gravity is already enabled
if ((choosingDirection || searchingSurface || currentNormal != regularGravity) && !playerControllerManager.isUsingDevice ()) {
// print ("deactivate gravity power");
//disable the sphere collider in the gravity center
gravityCenterCollider.enabled = false;
//enable the capsule collider in the player
playerCollider.isTrigger = false;
//get the last time that the player was in the air
playerControllerManager.lastTimeFalling = Time.time;
accelerating = false;
//set the force of the gravity in the player to its regular state
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
//change the color of the player
changeColor (false);
choosingDirection = false;
circumnavigableSurfaceFound = false;
removeParent ();
setHoverState (false);
turning = false;
searchingSurface = false;
searchAround = false;
lifting = false;
recalculatingSurface = false;
timer = 0.75f;
//stop to shake the camera and set its position to the regular state
disableCameraShake ();
playerCameraManager.changeCameraFov (false);
//if the normal of the player is different from the regular gravity, rotate the player
if (currentNormal != regularGravity) {
if (preserveVelocityWhenDisableGravityPower) {
previousRigidbodyVelocity = mainRigidbody.linearVelocity;
preservingVelocity = true;
extraMultiplierPreserveVelocity = 1;
}
checkRotateToSurface (regularGravity, rotateToRegularGravitySpeed);
}
//rotate the mesh of the player also
checkRotateCharacter (regularGravity);
playerControllerManager.setGravityPowerActiveState (false);
playerCameraManager.sethorizontalCameraLimitActiveOnAirState (true);
setPowerActivateState (false);
//set the value of the normal in the playerController component to its regular state
playerControllerManager.setCurrentNormalCharacter (regularGravity);
gravityPowerActive = false;
currentSetGravityManager = null;
searchNewSurfaceOnHighFallSpeedPaused = false;
}
}
public void checkKeepWeapons ()
{
if (weaponsManager.isAimingInThirdPerson () || weaponsManager.isCarryingWeaponInThirdPerson ()) {
weaponsManager.checkIfKeepSingleOrDualWeapon ();
}
}
public void checkKeepPower ()
{
if (powers.isAimingPowerInThirdPerson ()) {
powers.deactivateAimMode ();
}
}
//now the change of velocity is in a function, so it can be called from keyboard and a touch button
public void changeMovementVelocity (bool value)
{
//if the player is not choosing a gravity direction and he is searching a surface or the player is not in the ground and with a changed normal, then
if (!choosingDirection && (powerActivated || (!playerControllerManager.isPlayerOnGround () && currentNormal != regularGravity))) {
accelerating = value;
//move the camera to a further away position, and add extra force to the player's velocity
if (accelerating) {
playerCameraManager.changeCameraFov (true);
playerControllerManager.setGravityMultiplierValueFromExternalFunction (highGravityMultiplier);
//when the player accelerates his movement in the air, the camera shakes
//if the player accelerates his movement in the air and shake camera is enabled
if (playerCameraManager.settings.enableShakeCamera) {
playerCameraManager.accelerateShake (true);
}
}
//else, set the camera to its regular position, reset the force applied to the player's velocity
else {
playerCameraManager.changeCameraFov (false);
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
playerCameraManager.accelerateShake (false);
}
}
}
//convert the character in a child of the moving object
public void addParent (GameObject obj)
{
fatherDetected = obj;
parentAssignedSystem currentParentAssignedSystem = obj.GetComponent<parentAssignedSystem> ();
if (currentParentAssignedSystem != null) {
fatherDetected = currentParentAssignedSystem.getAssignedParent ();
}
if (rotating) {
externalGravityCenter.SetParent (fatherDetected.transform);
} else {
setFatherDetectedAsParent ();
}
if (fatherDetected != null) {
playerIsChildOfParentActive = true;
} else {
playerIsChildOfParentActive = false;
}
}
//remove the parent of the player, so he moves freely again
public void removeParent ()
{
if (rotating) {
setExternalGravityCenterAsParent ();
} else {
setNullParent ();
}
fatherDetected = null;
playerIsChildOfParentActive = false;
}
public void setExternalGravityCenterAsParent ()
{
setNewParent (externalGravityCenter);
}
public void setFatherDetectedAsParent ()
{
setNewParent (fatherDetected.transform);
}
public void setNullParent ()
{
setNewParent (null);
}
public void setNewParent (Transform newParent)
{
if (playerTransform == null) {
playerTransform = transform;
}
// if (newParent != null) {
// print (newParent.name);
// } else {
// print ("removing parent");
// }
playerTransform.SetParent (newParent);
playerCameraTransform.SetParent (newParent);
}
public void setCorrectParent ()
{
if (playerIsChildOfParentActive) {
setFatherDetectedAsParent ();
} else {
setNullParent ();
}
}
//the funcion to change camera view, to be called from a key or a touch button
public void changeCameraView (bool state)
{
firstPersonView = state;
//disable or enable the mesh of the player
setGravityArrowState (!firstPersonView);
}
//set a random direction to rotate the character
void rotateMeshPlayer ()
{
if (!turning) {
turning = true;
turnDirection = new Vector3 (Random.Range (-1, 1), Random.Range (-1, 1), Random.Range (-1, 1));
if (turnDirection.magnitude == 0) {
turnDirection.x = 1;
}
}
}
//set if the player is hovering or not
void setHoverState (bool state)
{
hovering = state;
}
public bool canRotatePlayer ()
{
return (stopAimModeWhenSearchingSurface || (!weaponsManager.isCarryingWeaponInThirdPerson () && !powers.isAimingPowerInThirdPerson ()));
}
//change the gravity of the player when he touchs the arrow trigger
public void changeOnTrigger (Vector3 dir, Vector3 right)
{
//set the parameters needed to change the player's gravity without using the gravity power buttons
searchingNewSurfaceBelow = false;
removeParent ();
circumnavigableSurfaceFound = false;
searchingSurface = true;
searchAround = true;
changeColor (true);
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
playerControllerManager.setGravityPowerActiveState (true);
playerCameraManager.sethorizontalCameraLimitActiveOnAirState (false);
setPowerActivateState (true);
playerCameraManager.calibrateAccelerometer ();
if (canRotatePlayer ()) {
rotateMeshPlayer ();
}
enableCameraShake ();
gravityDirection = dir;
rightAxis = right;
if (canRotatePlayer ()) {
checkRotateCharacter (-gravityDirection);
}
gravityPowerActive = true;
}
//stop the gravity power when the player is going to drive a vehicle
public void stopGravityPower ()
{
//disable the sphere collider in the gravity center
gravityCenterCollider.enabled = false;
//get the last time that the player was in the air
playerControllerManager.lastTimeFalling = Time.time;
accelerating = false;
//set the force of the gravity in the player to its regular state
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
choosingDirection = false;
circumnavigableSurfaceFound = false;
removeParent ();
setHoverState (false);
turning = false;
searchingSurface = false;
searchAround = false;
lifting = false;
recalculatingSurface = false;
timer = 0.75f;
//stop to shake the camera and set its position to the regular state
disableCameraShake ();
playerCameraManager.changeCameraFov (false);
playerControllerManager.setGravityPowerActiveState (false);
playerCameraManager.sethorizontalCameraLimitActiveOnAirState (true);
setPowerActivateState (false);
//reset the player's rotation
playerTransform.rotation = quaternionIdentity;
gravityCenter.transform.localRotation = quaternionIdentity;
//set to 0 the current velocity of the player
mainRigidbody.linearVelocity = vector3Zero;
gravityPowerActive = false;
}
//rotate the player, camera and mesh of the player to the new surface orientation
//public
public void checkRotateToSurface (Vector3 normal, float rotSpeed)
{
stopRotateToSurfaceCoroutine ();
rotateCharacterState = StartCoroutine (rotateToSurface (normal, rotSpeed));
}
public void stopRotateToSurfaceCoroutine ()
{
//get the coroutine, stop it and play it again
if (rotateCharacterState != null) {
StopCoroutine (rotateCharacterState);
}
}
public IEnumerator rotateToSurface (Vector3 normal, float rotSpeed)
{
updateCurrentRotatingNormal (normal);
externalGravityCenter.SetParent (null);
if (ignoreUseGravityCenterForRotationActive) {
if (playerControllerManager.isPlayerOnGround ()) {
externalGravityCenter.position = playerTransform.position + 1.1f * playerTransform.up;
} else {
externalGravityCenter.position = gravityCenter.position;
}
} else {
externalGravityCenter.position = gravityCenter.position;
}
ignoreUseGravityCenterForRotationActive = false;
externalGravityCenter.rotation = playerTransform.rotation;
setExternalGravityCenterAsParent ();
setRotatingToSurfaceState (true);
Quaternion currentPlayerRotation = externalGravityCenter.rotation;
Vector3 currentPlayerForward = Vector3.Cross (externalGravityCenter.right, normal);
if (currentPlayerForward == Vector3.zero) {
externalGravityCenter.eulerAngles += externalGravityCenter.up * 2;
currentPlayerRotation = externalGravityCenter.rotation;
currentPlayerForward = Vector3.Cross (externalGravityCenter.right, normal);
}
Quaternion playerTargetRotation = Quaternion.LookRotation (currentPlayerForward, normal);
Quaternion currentGravityCenterRotation = gravityCenter.localRotation;
Quaternion gravityCenterTargetRotation = quaternionIdentity;
bool resetCameraTransformRotationResult = false;
if (deactivatingZeroGravityModeActive) {
float playerCameraAngle = Vector3.Angle (playerTransform.up, playerCameraTransform.up);
if (Mathf.Abs (playerCameraAngle) > 0.0000001f) {
resetCameraTransformRotationResult = true;
}
deactivatingZeroGravityModeActive = false;
}
bool targetReached = false;
float currentTimer = 0;
float normalAngle = 0;
float rotateTimer = 0;
while (!targetReached) {
rotateTimer += Time.deltaTime * rotSpeed;
currentTimer += Time.deltaTime;
externalGravityCenter.rotation = Quaternion.Slerp (currentPlayerRotation, playerTargetRotation, rotateTimer);
gravityCenter.transform.localRotation = Quaternion.Slerp (currentGravityCenterRotation, gravityCenterTargetRotation, rotateTimer);
if (resetCameraTransformRotationResult) {
playerCameraTransform.localRotation = Quaternion.Slerp (playerCameraTransform.localRotation, quaternionIdentity, rotateTimer);
}
normalAngle = Vector3.Angle (playerTransform.up, normal);
if (normalAngle < 0.001f || currentTimer > 3) {
targetReached = true;
}
yield return null;
}
//for (float t = 0; t < 1;) {
// t += Time.deltaTime * rotSpeed;
// externalGravityCenter.rotation = Quaternion.Slerp (currentPlayerRotation, playerTargetRotation, t);
// gravityCenter.transform.localRotation = Quaternion.Slerp (currentGravityCenterRotation, gravityCenterTargetRotation, t);
// yield return null;
//}
setCorrectParent ();
externalGravityCenter.SetParent (playerTransform);
currentNormal = normal;
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
playerControllerManager.setCurrentNormalCharacter (normal);
if (currentNormal == regularGravity) {
gravityPowerActive = false;
}
setRotatingToSurfaceState (false);
//adjust gravity rotation for locked camera
playerCameraManager.setLockedMainCameraTransformRotation (normal);
if (zeroGravityModeOn || freeFloatingModeOn) {
disableCameraShake ();
}
if (preservingVelocity) {
preservingVelocity = false;
yield return new WaitForSeconds (0.02f);
playerControllerManager.addExternalForce (extraMultiplierPreserveVelocity * previousRigidbodyVelocity);
}
checkOnGroundOrAirState ();
}
public override bool isPlayerSearchingGravitySurface ()
{
return powerActivated;
}
public bool isCharacterRotatingToSurface ()
{
return rotating;
}
void setRotatingToSurfaceState (bool state)
{
rotating = state;
playerControllerManager.setCharacterRotatingToSurfaceState (state);
playerCameraManager.setCharacterRotatingToSurfaceState (state);
}
public void checkRotateToSurfaceWithoutParent (Vector3 normal, float rotSpeed)
{
stopRotateToSurfaceWithOutParentCoroutine ();
rotateCharacterState = StartCoroutine (rotateToSurfaceWithOutParent (normal, rotSpeed));
}
public void stopRotateToSurfaceWithOutParentCoroutine ()
{
//get the coroutine, stop it and play it again
if (rotateCharacterState != null) {
StopCoroutine (rotateCharacterState);
}
}
public IEnumerator rotateToSurfaceWithOutParent (Vector3 normal, float rotSpeed)
{
updateCurrentRotatingNormal (normal);
setRotatingToSurfaceState (true);
Quaternion currentPlayerRotation = playerTransform.rotation;
Vector3 currentPlayerForward = Vector3.Cross (playerTransform.right, normal);
Quaternion playerTargetRotation = Quaternion.LookRotation (currentPlayerForward, normal);
Quaternion currentCameraRotation = playerCameraTransform.rotation;
Vector3 currentCameraForward = Vector3.Cross (playerCameraTransform.right, normal);
Quaternion cameraTargetRotation = Quaternion.LookRotation (currentCameraForward, normal);
Quaternion currentGravityCenterRotation = gravityCenter.localRotation;
Quaternion gravityCenterTargetRotation = quaternionIdentity;
for (float t = 0; t < 1;) {
t += Time.deltaTime * rotSpeed;
playerTransform.rotation = Quaternion.Slerp (currentPlayerRotation, playerTargetRotation, t);
playerCameraTransform.rotation = Quaternion.Slerp (currentCameraRotation, cameraTargetRotation, t);
gravityCenter.transform.localRotation = Quaternion.Slerp (currentGravityCenterRotation, gravityCenterTargetRotation, t);
yield return null;
}
currentNormal = normal;
playerControllerManager.setGravityMultiplierValueFromExternalFunction (normalGravityMultiplier);
playerControllerManager.setCurrentNormalCharacter (normal);
if (currentNormal == regularGravity) {
gravityPowerActive = false;
}
setRotatingToSurfaceState (false);
//adjust gravity rotation for locked camera
playerCameraManager.setLockedMainCameraTransformRotation (normal);
if (zeroGravityModeOn || freeFloatingModeOn) {
disableCameraShake ();
}
if (preservingVelocity) {
preservingVelocity = false;
mainRigidbody.linearVelocity = 2 * previousRigidbodyVelocity;
}
}
public void setNormal (Vector3 normal)
{
Vector3 myForwardPlayer = Vector3.Cross (playerTransform.right, normal);
Vector3 myForwardCamera = Vector3.Cross (playerCameraTransform.right, normal);
Quaternion dstRotPlayer = Quaternion.LookRotation (myForwardPlayer, normal);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, normal);
playerTransform.rotation = dstRotPlayer;
playerCameraTransform.rotation = dstRotCamera;
currentNormal = normal;
playerControllerManager.setCurrentNormalCharacter (normal);
if (currentNormal != regularGravity) {
gravityPowerActive = true;
changeColor (true);
} else {
changeColor (false);
}
updateCurrentRotatingNormal (currentNormal);
currentSetGravityManager = null;
}
public override Vector3 getCurrentNormal ()
{
return currentNormal;
}
public void setCurrentNormal (Vector3 newValue)
{
currentNormal = newValue;
}
public override bool isUsingRegularGravity ()
{
return currentNormal == regularGravity;
}
public Vector3 getRegularGravity ()
{
return regularGravity;
}
public void updateCurrentRotatingNormal (Vector3 newNormal)
{
currentRotatingNormal = newNormal;
}
public Vector3 getCurrentRotatingNormal ()
{
return currentRotatingNormal;
}
//rotate the mesh of the character in the direction of the camera when he selects a gravity direction in the air
// and to the quaternion identity when he is on ground
public void checkRotateCharacter (Vector3 normal)
{
float angle = Vector3.Angle (gravityCenter.up, playerTransform.up);
if (Mathf.Abs (angle) > 0 || currentNormal == regularGravity) {
//get the coroutine, stop it and play it again
if (rotateToSurfaceState != null) {
StopCoroutine (rotateToSurfaceState);
}
rotateToSurfaceState = StartCoroutine (rotateCharacter (normal));
}
}
public IEnumerator rotateCharacter (Vector3 normal)
{
Quaternion orgRotCenter = gravityCenter.transform.localRotation;
Quaternion dstRotCenter = new Quaternion (0, 0, 0, 1);
//check that the normal is different from zero, to rotate the player's mesh in the direction of the new gravity when he use the gravity power button
//and select the camera direction to search a new surface
//else, the player's mesh is rotated to its regular state
if (normal != vector3Zero) {
orgRotCenter = gravityCenter.transform.rotation;
Vector3 myForward = Vector3.Cross (gravityCenter.transform.right, normal);
dstRotCenter = Quaternion.LookRotation (myForward, normal);
}
for (float t = 0; t < 1;) {
t += Time.deltaTime * 3;
if (normal == vector3Zero) {
gravityCenter.transform.localRotation = Quaternion.Slerp (orgRotCenter, dstRotCenter, t);
} else {
gravityCenter.transform.rotation = Quaternion.Slerp (orgRotCenter, dstRotCenter, t);
}
yield return null;
}
}
public void changeGravityDirectionDirectlyInvertedValue (Vector3 gravityDirection, bool preserveVelocity)
{
changeGravityDirectionDirectly (-gravityDirection, preserveVelocity);
}
public void changeGravityDirectionDirectly (Vector3 gravityDirection, bool preserveVelocity)
{
if (!rotating) {
//disable the search of the surface and rotate the player to that surface
playerControllerManager.setGravityPowerActiveState (false);
playerCameraManager.sethorizontalCameraLimitActiveOnAirState (true);
setPowerActivateState (false);
searchingNewSurfaceBelow = false;
searchingSurface = false;
searchAround = false;
if (preserveVelocity) {
previousRigidbodyVelocity = mainRigidbody.linearVelocity;
preservingVelocity = true;
extraMultiplierPreserveVelocity = 2;
}
mainRigidbody.linearVelocity = vector3Zero;
//disable the collider in the gravity center and enable the capsule collider in the player
gravityCenterCollider.enabled = false;
playerCollider.isTrigger = false;
//set the camera in its regular position
playerCameraManager.changeCameraFov (false);
//if the new normal is different from the previous normal in the gravity power, then rotate the player
if (gravityDirection != currentNormal) {
checkRotateToSurface (gravityDirection, rotateToSurfaceSpeed);
}
//if the player back to the regular gravity value, change its color to the regular state
if (gravityDirection == regularGravity) {
changeColor (false);
} else {
changeColor (true);
}
}
}
public void setCurrentSetGravityManager (setGravity currentSetGravity)
{
currentSetGravityManager = currentSetGravity;
}
public void setCurrentGravityCenterPoint (Transform newTransform)
{
currentCenterPoint = newTransform;
currentCenterPointAssigned = currentCenterPoint != null;
}
public setGravity getCurrentSetGravityManager ()
{
return currentSetGravityManager;
}
public void changeColor (bool state)
{
if (!changeModelColor) {
return;
}
if (colorCoroutine != null) {
StopCoroutine (colorCoroutine);
}
colorCoroutine = StartCoroutine (changeColorCoroutine (state));
}
//change the mesh color of the character according to the gravity power
public IEnumerator changeColorCoroutine (bool value)
{
if (playerRenderer != null) {
if (value) {
powerColor = originalPowerColor;
} else {
powerColor = Color.white;
}
int propertyNameID = Shader.PropertyToID ("_Color");
for (float t = 0; t < 1;) {
t += Time.deltaTime;
for (int i = 0; i < materialToChange.Count; i++) {
if (playerRenderer.materials.Length >= materialToChange.Count) {
if (materialToChange [i] == true && playerRenderer.materials [i].HasProperty (propertyNameID)) {
playerRenderer.materials [i].color = Color.Lerp (playerRenderer.materials [i].color, powerColor, t);
}
}
}
yield return null;
}
}
}
public void setMeshCharacter (SkinnedMeshRenderer currentMeshCharacter)
{
if (currentMeshCharacter != null) {
playerRenderer = currentMeshCharacter.GetComponent<Renderer> ();
}
updateComponent ();
}
//change the object which the camera follows and disable or enabled the powers according to the player state
public void death (bool state)
{
dead = state;
if (state) {
deactivateGravityPower ();
turning = false;
setHoverState (false);
checkRotateCharacter (vector3Zero);
}
}
public void setGravityArrow (GameObject obj)
{
arrow = obj;
}
public void setGravityArrowState (bool state)
{
if (arrow != null) {
if (arrow.activeSelf != state) {
arrow.SetActive (state);
}
gravityArrowCurrentlyActive = state;
}
}
public void setFirstPersonView (bool state)
{
firstPersonView = state;
}
public override Transform getGravityCenter ()
{
return gravityCenter;
}
public bool isCurcumnavigating ()
{
return circumnavigableSurfaceFound;
}
public override bool isSearchingSurface ()
{
return searchingSurface;
}
public bool isGravityPowerActive ()
{
return gravityPowerActive;
}
public void startOverride ()
{
overrideTurretControlState (true);
}
public void stopOverride ()
{
overrideTurretControlState (false);
}
public void overrideTurretControlState (bool state)
{
usedByAI = !state;
}
public bool isZeroGravityModeOn ()
{
return zeroGravityModeOn;
}
public void toggleZeroGravityModeOnState ()
{
setZeroGravityModeOnState (!zeroGravityModeOn);
}
bool deactivatingZeroGravityModeActive;
public void setZeroGravityModeOnState (bool state)
{
if (freeFloatingModeOn) {
setfreeFloatingModeOnState (false);
}
zeroGravityModeOn = state;
disableCameraShake ();
playerControllerManager.setZeroGravityModeOnState (zeroGravityModeOn);
playerCameraManager.setZeroGravityModeOnState (zeroGravityModeOn);
if (!zeroGravityModeOn) {
if (currentNormal != regularGravity) {
deactivatingZeroGravityModeActive = true;
deactivateGravityPower ();
}
}
checkEventsOnZeroGravityModeStateChange (zeroGravityModeOn);
}
public void setZeroGravityModeOnStateWithOutRotation (bool state)
{
if (freeFloatingModeOn) {
setfreeFloatingModeOnState (false);
}
zeroGravityModeOn = state;
disableCameraShake ();
playerControllerManager.setZeroGravityModeOnState (zeroGravityModeOn);
playerCameraManager.setZeroGravityModeOnState (zeroGravityModeOn);
checkEventsOnZeroGravityModeStateChange (zeroGravityModeOn);
}
public void disableFreeFloatingModeOnIfActive ()
{
if (freeFloatingModeOn) {
setfreeFloatingModeOnState (false);
}
}
public void setfreeFloatingModeOnState (bool state)
{
if (zeroGravityModeOn) {
return;
}
if (!canActivateFreeFloatingMode) {
return;
}
freeFloatingModeOn = state;
disableCameraShake ();
checkEventsOnFreeFloatingModeStateChange (freeFloatingModeOn);
playerControllerManager.setfreeFloatingModeOnState (freeFloatingModeOn);
playerCameraManager.setfreeFloatingModeOnState (freeFloatingModeOn);
stopSetfreeFloatingModeOnStateWithDelayCoroutine ();
}
public void checkEventsOnFreeFloatingModeStateChange (bool state)
{
if (useEventsOnFreeFloatingModeStateChange) {
if (state) {
evenOnFreeFloatingModeStateEnabled.Invoke ();
} else {
eventOnFreeFloatingModeStateDisabled.Invoke ();
}
}
}
public void checkEventsOnZeroGravityModeStateChange (bool state)
{
if (useEventsOnZeroGravityModeStateChange) {
if (state) {
evenOnZeroGravityModeStateEnabled.Invoke ();
} else {
eventOnZeroGravityModeStateDisabled.Invoke ();
}
}
}
public void checkEventsOnUseGravityPowerStateChange (bool state)
{
if (useEventsOnUseGravityPowerStateChange) {
if (state) {
eventsOnUseGravityPowerStateEnabled.Invoke ();
} else {
eventsOnUseGravityPowerStateDisabled.Invoke ();
}
}
}
public void setPowerActivateState (bool state)
{
powerActivated = state;
checkEventsOnUseGravityPowerStateChange (state);
}
public void changeFreeFloatingModeOnState ()
{
setfreeFloatingModeOnState (!freeFloatingModeOn);
}
public void setfreeFloatingModeOnStateWithDelay (float delayAmount, bool state)
{
stopSetfreeFloatingModeOnStateWithDelayCoroutine ();
freeFloatingModeCoroutine = StartCoroutine (setfreeFloatingModeOnStateWithDelayCoroutine (delayAmount, state));
}
public void stopSetfreeFloatingModeOnStateWithDelayCoroutine ()
{
if (freeFloatingModeCoroutine != null) {
StopCoroutine (freeFloatingModeCoroutine);
}
}
public IEnumerator setfreeFloatingModeOnStateWithDelayCoroutine (float delayAmount, bool state)
{
yield return new WaitForSeconds (delayAmount);
setfreeFloatingModeOnState (state);
}
public void setCanActivateFreeFloatingModeState (bool state)
{
canActivateFreeFloatingMode = state;
}
public void rotateCharacterInZeroGravityMode (Vector3 normal, float rotSpeed)
{
//get the coroutine, stop it and play it again
if (zeroGravityModeRotateCharacterCoroutine != null) {
StopCoroutine (zeroGravityModeRotateCharacterCoroutine);
}
zeroGravityModeRotateCharacterCoroutine = StartCoroutine (rotateCharacterInZeroGravityModeCoroutine (normal, rotSpeed));
}
public IEnumerator rotateCharacterInZeroGravityModeCoroutine (Vector3 normal, float rotSpeed)
{
externalGravityCenter.SetParent (null);
externalGravityCenter.position = playerTransform.position + playerTransform.up;
externalGravityCenter.rotation = playerCameraTransform.rotation;
setExternalGravityCenterAsParent ();
setRotatingToSurfaceState (true);
Quaternion currentPlayerRotation = playerCameraTransform.rotation;
Vector3 currentPlayerForward = Vector3.Cross (playerCameraTransform.right, normal);
Quaternion playerTargetRotation = Quaternion.LookRotation (currentPlayerForward, normal);
Quaternion currentGravityCenterRotation = gravityCenter.localRotation;
Quaternion gravityCenterTargetRotation = quaternionIdentity;
for (float t = 0; t < 1;) {
t += Time.deltaTime * rotSpeed;
externalGravityCenter.rotation = Quaternion.Lerp (currentPlayerRotation, playerTargetRotation, t);
gravityCenter.transform.localRotation = Quaternion.Lerp (currentGravityCenterRotation, gravityCenterTargetRotation, t);
yield return null;
}
setCorrectParent ();
externalGravityCenter.SetParent (playerTransform);
setRotatingToSurfaceState (false);
}
public void teleportPlayer (Vector3 teleportPosition, float teleportSpeed, Vector3 normal, float rotSpeed)
{
stopTeleporting ();
teleportCoroutine = StartCoroutine (teleportPlayerCoroutine (teleportPosition, teleportSpeed, normal, rotSpeed));
}
public void stopTeleporting ()
{
if (teleportCoroutine != null) {
StopCoroutine (teleportCoroutine);
}
setPlayerControlState (true);
}
public void setPlayerControlState (bool state)
{
playerControllerManager.changeScriptState (state);
playerControllerManager.setGravityForcePuase (!state);
playerControllerManager.setRigidbodyVelocityToZero ();
playerControllerManager.setPhysicMaterialAssigmentPausedState (!state);
if (!state) {
playerControllerManager.setZeroFrictionMaterial ();
if (!playerControllerManager.isPauseCheckOnGroundStateZGActive ()) {
playerControllerManager.setCheckOnGrundStatePausedFFOrZGState (false);
}
}
}
IEnumerator teleportPlayerCoroutine (Vector3 targetPosition, float currentTeleportSpeed, Vector3 normal, float rotSpeed)
{
teleportInProcess = true;
externalGravityCenter.SetParent (null);
externalGravityCenter.position = playerTransform.position + playerTransform.up;
externalGravityCenter.rotation = playerCameraTransform.rotation;
setExternalGravityCenterAsParent ();
setPlayerControlState (false);
if (setOnGroundStateOnTeleportToSurfaceOnZeroGravity) {
playerControllerManager.setIgnoreSetCheckOnGrundStatePausedFFOrZGStateActive (true);
}
setRotatingToSurfaceState (true);
Quaternion currentPlayerRotation = playerCameraTransform.rotation;
Vector3 currentPlayerForward = Vector3.Cross (playerCameraTransform.right, normal);
Quaternion playerTargetRotation = Quaternion.LookRotation (currentPlayerForward, normal);
float dist = GKC_Utils.distance (externalGravityCenter.position, targetPosition);
float duration = dist / currentTeleportSpeed;
float translateTimer = 0;
float rotateTimer = 0;
float teleportTimer = 0;
float normalAngle = 0;
Vector3 targetPositionDirection = targetPosition - externalGravityCenter.position;
targetPositionDirection = targetPositionDirection / targetPositionDirection.magnitude;
bool targetReached = false;
while (!targetReached) {
translateTimer += Time.deltaTime / duration;
externalGravityCenter.position = Vector3.Lerp (externalGravityCenter.position, targetPosition, translateTimer);
rotateTimer += Time.deltaTime * rotSpeed;
externalGravityCenter.rotation = Quaternion.Lerp (currentPlayerRotation, playerTargetRotation, rotateTimer);
teleportTimer += Time.deltaTime;
normalAngle = Vector3.Angle (playerTransform.up, normal);
if ((GKC_Utils.distance (externalGravityCenter.position, targetPosition) < 0.2f && normalAngle < 1) || teleportTimer > (duration + 5)) {
targetReached = true;
}
yield return null;
}
setPlayerControlState (true);
setRotatingToSurfaceState (false);
setCorrectParent ();
externalGravityCenter.SetParent (playerTransform);
teleportInProcess = false;
if (setOnGroundStateOnTeleportToSurfaceOnZeroGravity) {
playerControllerManager.setCheckOnGrundStatePausedFFOrZGState (false);
}
}
public bool isTeleportInProcess ()
{
return teleportInProcess;
}
public void setGravityPowerEnabledState (bool state)
{
gravityPowerEnabled = state;
}
public void setGravityPowerState (bool enablePower)
{
//activate the power of change gravity
//one press=the player elevates above the surface if he was in the ground or stops him in the air if he was not in the ground
//two press=make the player moves in straight direction of the camera, looking a new surface
//three press=stops the player again in the air
if (!dead && !playerControllerManager.isUsingDevice () && gravityPowerEnabled) {
if (enablePower) {
activateGravityPower ();
} else {
deactivateGravityPower ();
}
}
}
public void disableGravityPowerIfOnAir ()
{
if (choosingDirection || searchingSurface) {
deactivateGravityPower ();
}
}
public void enableCameraShake ()
{
if (cameraShakeCanBeUsed) {
playerCameraManager.startShakeCamera ();
cameraShakeActive = true;
}
}
public void disableCameraShake ()
{
if (cameraShakeCanBeUsed) {
if (cameraShakeActive) {
playerCameraManager.stopShakeCamera ();
cameraShakeActive = false;
}
}
}
public void setCameraShakeCanBeUsedState (bool state)
{
cameraShakeCanBeUsed = state;
if (!cameraShakeCanBeUsed) {
playerCameraManager.stopShakeCamera ();
}
}
public void setGravityPowerInputEnabledState (bool state)
{
gravityPowerInputEnabled = state;
}
//CALL INPUT FUNCTIONS
public void inputSetGravityPowerState (bool enablePower)
{
if (gravityPowerInputEnabled) {
setGravityPowerState (enablePower);
}
}
public void inputChangeGravitySpeed (bool increaseSpeed)
{
if (!dead && !playerControllerManager.isUsingDevice () && gravityPowerEnabled) {
if (increaseSpeed) {
changeMovementVelocity (true);
} else {
changeMovementVelocity (false);
}
}
}
public void inputAdjustToSurfaceOnZeroGravity ()
{
if (!dead && !playerControllerManager.isUsingDevice () && zeroGravityModeOn && !onGround && !rotating && canAdjustToForwardSurface) {
if (playerControllerManager.isPlayerMovingOn2_5dWorld ()) {
return;
}
if (Physics.Raycast (forwardSurfaceRayPosition.position, forwardSurfaceRayPosition.forward, out hit, maxDistanceToAdjust, layer)) {
if (currentNormal != regularGravity) {
teleportPlayer (hit.point + 0.6f * hit.normal, adjustToForwardSurfaceSpeed, hit.normal, resetRotationZeroGravitySpeed);
}
}
}
}
public void setCustomDirectionOnResetZeroGravityRotationValue (Vector3 newValue)
{
customDirectionOnResetZeroGravityRotation = newValue;
}
public void setCustomDirectionOnResetZeroGravityRotationValue (Transform newTransform)
{
setCustomDirectionOnResetZeroGravityRotationValue (newTransform.up);
}
public void inputResetRotationOnZeroGravity ()
{
if (!dead &&
!playerControllerManager.isUsingDevice () &&
zeroGravityModeOn &&
!onGround &&
!rotating &&
canResetRotationOnZeroGravityMode) {
bool canResetRotationResult = false;
Vector3 targetGravityDirection = regularGravity;
if (useCustomDirectionOnResetZeroGravityRotation) {
targetGravityDirection = customDirectionOnResetZeroGravityRotation;
}
if (currentNormal != targetGravityDirection) {
canResetRotationResult = true;
}
if (canResetRotationResult) {
rotateCharacterInZeroGravityMode (targetGravityDirection, resetRotationZeroGravitySpeed);
}
}
}
public void inputToggleReverseGravity ()
{
if (!dead && !playerControllerManager.isUsingDevice () && gravityPowerEnabled) {
ignoreUseGravityCenterForRotationActive = true;
if (currentNormal != regularGravity) {
deactivateGravityPower ();
} else {
changeGravityDirectionDirectlyInvertedValue (currentNormal, true);
if (pauseSearchNewSurfaceOnHighFallSpeedOnReverseGravityInput) {
searchNewSurfaceOnHighFallSpeedPaused = true;
}
}
}
}
public void setCurrentZeroGravityRoom (zeroGravityRoomSystem gravityRoom)
{
currentZeroGravityRoom = gravityRoom;
if (currentZeroGravityRoom != null) {
playerInsideGravityRoom = true;
} else {
playerInsideGravityRoom = false;
}
}
public bool isPlayerInsiderGravityRoom ()
{
return playerInsideGravityRoom;
}
public zeroGravityRoomSystem getCurrentZeroGravityRoom ()
{
return currentZeroGravityRoom;
}
public Transform getCurrentSurfaceBelowPlayer ()
{
return currentSurfaceBelowPlayer;
}
public void addObjectToCurrentZeroGravityRoomSystem (GameObject objectToAdd)
{
if (currentZeroGravityRoom != null) {
currentZeroGravityRoom.addObjectToRoom (objectToAdd);
}
}
public void setCircumnavigateSurfaceState (bool state)
{
circumnavigateCurrentSurfaceActive = state;
if (!circumnavigateCurrentSurfaceActive) {
if (circumnavigableSurfaceFound || playerIsChildOfParentActive) {
circumnavigableSurfaceFound = false;
if (playerIsChildOfParentActive) {
removeParent ();
}
}
recalculatingSurface = false;
}
}
public void setCheckSurfaceInFrontState (bool state)
{
checkSurfaceInFront = state;
}
public void setCheckSurfaceBelowLedgeState (bool state)
{
checkSurfaceBelowLedge = state;
}
public void setUsedByAIState (bool state)
{
usedByAI = state;
}
void updateComponent ()
{
GKC_Utils.updateComponent (this);
}
}