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

714 lines
22 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class gravityWallRunSystem : MonoBehaviour
{
[Header ("Main Settings")]
[Space]
public bool wallWalkEnabled;
public float wallWalkRotationSpeed = 10;
public bool setAnimSpeedMultiplierOnWallRun = true;
public float animSpeedMultiplierOnWallRun = 2;
public bool useExtraRaycastDetectionOnWallWalkEnabled = true;
public bool stopGravityAdherenceWhenStopRun = true;
public bool avoidRigidbodiesOnRaycastEnabled;
public bool rotateToOriginalNormalOnAirEnabled = true;
[Space]
[Header ("Player Render Setting")]
[Space]
public Material runMat;
public LayerMask layer;
public bool trailsActive = true;
public bool changePlayerMaterialsOnWallRun;
[Space]
[Header ("Player GameObject List")]
[Space]
public List<GameObject> playerGameObjectList = new List<GameObject> ();
public List<GameObject> playerGameObjectWithChildList = new List<GameObject> ();
[Space]
[Header ("Debug")]
[Space]
public bool showDebugPrint;
public bool wallWalkActive;
public bool mainCoroutineActive;
public bool forceWalkWallActiveExternally;
[Space]
public List<Renderer> rendererParts = new List<Renderer> ();
public List<Material> materialList = new List<Material> ();
public List<TrailRenderer> trails = new List<TrailRenderer> ();
[Space]
[Header ("Events Settings")]
[Space]
public bool useEventOnWallWalkStart;
public bool useEventOnWallWalkEnd;
[Space]
public UnityEvent eventOnWallWalkStart;
public UnityEvent eventOnWallWalkEnd;
[Space]
[Header ("Components")]
[Space]
public playerController mainPlayerController;
public gravitySystem mainGravitySystem;
public ragdollActivator mainRagdollActivator;
public GameObject trailsPrefab;
public Transform playerTransform;
float lastTimeRunActivated;
float lastTimeWallWalkActive;
bool resetingSurfaceRotationAfterWallWalkActive;
float lastTimeResetSurfaceRotationBelow;
float trailTimer = -1;
RaycastHit hit;
bool checkRunGravity;
Vector3 originalNormal;
bool materialsStored;
Coroutine mainCoroutine;
float originalAnimSpeedMultiplierOnWallRun;
void Start ()
{
if (wallWalkEnabled) {
mainCoroutine = StartCoroutine (updateCoroutine ());
mainCoroutineActive = true;
}
originalAnimSpeedMultiplierOnWallRun = animSpeedMultiplierOnWallRun;
}
public void stopUpdateCoroutine ()
{
if (mainCoroutine != null) {
StopCoroutine (mainCoroutine);
}
mainCoroutineActive = false;
}
IEnumerator updateCoroutine ()
{
var waitTime = new WaitForFixedUpdate ();
while (true) {
if (!mainPlayerController.playerIsBusy ()) {
checkIfActivateWallWalk ();
updateWallWalkState ();
}
//just a configuration to the trails in the player
if (trailsActive) {
if (trailTimer > 0) {
trailTimer -= Time.deltaTime;
for (int j = 0; j < trails.Count; j++) {
if (trails [j] != null) {
trails [j].time -= Time.deltaTime;
}
}
}
if (trailTimer <= 0 && trailTimer > -1) {
for (int j = 0; j < trails.Count; j++) {
if (trails [j] != null) {
trails [j].enabled = false;
}
}
trailTimer = -1;
}
if (trailTimer == -1) {
if (!wallWalkEnabled) {
stopUpdateCoroutine ();
}
}
}
yield return waitTime;
}
}
void updateWallWalkState ()
{
if (wallWalkActive && wallWalkEnabled) {
if (resetingSurfaceRotationAfterWallWalkActive) {
if (mainGravitySystem.isCharacterRotatingToSurface ()) {
return;
} else {
resetingSurfaceRotationAfterWallWalkActive = false;
lastTimeResetSurfaceRotationBelow = Time.time;
}
}
if (lastTimeResetSurfaceRotationBelow > 0) {
if (Time.time > lastTimeResetSurfaceRotationBelow + 1) {
lastTimeResetSurfaceRotationBelow = 0;
} else {
return;
}
}
if (mainPlayerController.isWallRunningActive () || mainPlayerController.isExternalControlBehaviorForAirTypeActive ()) {
stopWallWalk ();
}
//check a surface in front of the player, to rotate to it
bool surfaceInFrontDetected = false;
Vector3 playerPosition = playerTransform.position;
Vector3 playerTransformUp = playerTransform.up;
Vector3 playerTransforForward = playerTransform.forward;
Vector3 raycastPosition = playerPosition + playerTransformUp;
Vector3 raycastDirection = playerTransforForward;
bool ignoreSurfaceDetected = false;
if (Physics.Raycast (raycastPosition, raycastDirection, out hit, 2, layer)) {
if (avoidRigidbodiesOnRaycastEnabled) {
if (hit.rigidbody != null) {
ignoreSurfaceDetected = true;
}
}
if (!hit.collider.isTrigger && !ignoreSurfaceDetected) {
mainGravitySystem.checkRotateToSurfaceWithoutParent (hit.normal, wallWalkRotationSpeed);
mainPlayerController.setCurrentNormalCharacter (hit.normal);
surfaceInFrontDetected = true;
}
}
if (useExtraRaycastDetectionOnWallWalkEnabled) {
if (!surfaceInFrontDetected && mainPlayerController.isPlayerOnGround () && !mainGravitySystem.isCharacterRotatingToSurface ()) {
Vector3 heading = (playerPosition + playerTransforForward) - raycastPosition;
float distance = heading.magnitude;
raycastDirection = heading / distance;
ignoreSurfaceDetected = false;
if (Physics.Raycast (raycastPosition, raycastDirection, out hit, 4, layer)) {
if (avoidRigidbodiesOnRaycastEnabled) {
if (hit.rigidbody != null) {
ignoreSurfaceDetected = true;
}
}
if (!ignoreSurfaceDetected && !hit.collider.isTrigger && mainGravitySystem.getCurrentNormal () != hit.normal) {
mainGravitySystem.checkRotateToSurfaceWithoutParent (hit.normal, wallWalkRotationSpeed);
mainPlayerController.setCurrentNormalCharacter (hit.normal);
surfaceInFrontDetected = true;
if (showDebugPrint) {
print ("surface detected below 1");
}
}
}
if (!surfaceInFrontDetected) {
raycastPosition = playerPosition + playerTransformUp + playerTransforForward;
raycastDirection = -playerTransformUp;
ignoreSurfaceDetected = false;
if (Physics.Raycast (raycastPosition, raycastDirection, out hit, 2, layer)) {
if (avoidRigidbodiesOnRaycastEnabled) {
if (hit.rigidbody != null) {
ignoreSurfaceDetected = true;
}
}
if (!ignoreSurfaceDetected && !hit.collider.isTrigger && mainGravitySystem.getCurrentNormal () != hit.normal) {
mainGravitySystem.checkRotateToSurfaceWithoutParent (hit.normal, wallWalkRotationSpeed);
mainPlayerController.setCurrentNormalCharacter (hit.normal);
surfaceInFrontDetected = true;
if (showDebugPrint) {
print ("surface detected below 2");
}
}
}
}
}
}
//check if the player is too far from his current ground, to rotate to his previous normal
if (rotateToOriginalNormalOnAirEnabled) {
if (!surfaceInFrontDetected && !Physics.Raycast (playerPosition + playerTransformUp, -playerTransformUp, out hit, 5, layer)) {
if (mainGravitySystem.getCurrentRotatingNormal () != originalNormal && !checkRunGravity) {
checkRunGravity = true;
if (mainGravitySystem.isCharacterRotatingToSurface ()) {
mainGravitySystem.stopRotateToSurfaceWithOutParentCoroutine ();
}
mainGravitySystem.checkRotateToSurface (originalNormal, 2);
mainPlayerController.setCurrentNormalCharacter (originalNormal);
resetingSurfaceRotationAfterWallWalkActive = true;
}
if (checkRunGravity && mainGravitySystem.getCurrentRotatingNormal () == originalNormal) {
checkRunGravity = false;
}
}
}
}
}
public void checkIfActivateWallWalk ()
{
if (wallWalkEnabled) {
if (!wallWalkActive && !mainPlayerController.isWallRunningActive () || mainPlayerController.isExternalControlBehaviorForAirTypeActive ()) {
if (forceWalkWallActiveExternally && mainPlayerController.isPlayerMoving (1) && mainPlayerController.isPlayerOnGround ()) {
mainPlayerController.inputStartToRun ();
originalNormal = mainGravitySystem.getCurrentRotatingNormal ();
lastTimeRunActivated = Time.time;
wallWalkActive = true;
activateWallWalk ();
return;
}
if (lastTimeWallWalkActive > 0) {
if (Time.time > lastTimeWallWalkActive + 1) {
lastTimeWallWalkActive = 0;
}
}
//check the amount of time that the button is being pressed
if (lastTimeRunActivated == 0) {
if (mainPlayerController.isPlayerRunning ()) {
originalNormal = mainGravitySystem.getCurrentRotatingNormal ();
lastTimeRunActivated = Time.time;
}
}
if (lastTimeRunActivated > 0) {
if (mainPlayerController.getRunButtonPressedTimer () > 0.5f) {
if (!resetingSurfaceRotationAfterWallWalkActive || !mainGravitySystem.isCharacterRotatingToSurface ()) {
if (!mainGravitySystem.isCurcumnavigating ()) {
wallWalkActive = true;
activateWallWalk ();
}
}
}
if (!mainPlayerController.isPlayerRunning ()) {
lastTimeRunActivated = 0;
}
}
} else {
if (!mainPlayerController.isPlayerRunning ()) {
lastTimeRunActivated = 0;
stopWallWalk ();
}
}
}
}
//if the player runs, a set of parameters are changed, like the speed of movement, animation, jumppower....
public void activateWallWalk ()
{
if (wallWalkEnabled) {
if (rendererParts.Count == 0) {
storePlayerRenderer ();
}
if (!materialsStored) {
getMaterialList ();
materialsStored = true;
}
bool firstPersonActive = mainPlayerController.isPlayerOnFirstPerson ();
if (trailsActive && !firstPersonActive) {
for (int j = 0; j < trails.Count; j++) {
if (trails [j] != null) {
trails [j].enabled = true;
trails [j].time = 1;
}
}
trailTimer = -1;
}
if (changePlayerMaterialsOnWallRun) {
int rendererPartsCount = rendererParts.Count;
for (int i = 0; i < rendererPartsCount; i++) {
Renderer currentRenderer = rendererParts [i];
if (currentRenderer != null) {
int materialsLength = currentRenderer.materials.Length;
Material [] allMats = currentRenderer.materials;
for (int j = 0; j < materialsLength; j++) {
allMats [j] = runMat;
}
currentRenderer.materials = allMats;
}
}
}
if (setAnimSpeedMultiplierOnWallRun) {
mainPlayerController.setReducedVelocity (animSpeedMultiplierOnWallRun);
}
checkEventsOnWallWalk (true);
}
}
//when the player stops running, those parameters back to their normal values
public void stopWallWalk ()
{
if (wallWalkActive) {
resetingSurfaceRotationAfterWallWalkActive = false;
if (trailsActive) {
trailTimer = 2;
}
if (changePlayerMaterialsOnWallRun) {
int rendererPartsCount = rendererParts.Count;
int currentMaterialIndex = 0;
for (int i = 0; i < rendererPartsCount; i++) {
Renderer currentRenderer = rendererParts [i];
if (currentRenderer != null) {
int materialsLength = currentRenderer.materials.Length;
Material [] allMats = currentRenderer.materials;
for (int j = 0; j < materialsLength; j++) {
allMats [j] = materialList [currentMaterialIndex];
currentMaterialIndex++;
}
currentRenderer.materials = allMats;
}
}
}
if (stopGravityAdherenceWhenStopRun) {
if (mainGravitySystem.getCurrentRotatingNormal () != originalNormal) {
if (mainGravitySystem.isCharacterRotatingToSurface ()) {
mainGravitySystem.stopRotateToSurfaceWithOutParentCoroutine ();
}
mainGravitySystem.checkRotateToSurface (originalNormal, 2);
resetingSurfaceRotationAfterWallWalkActive = true;
}
mainPlayerController.setCurrentNormalCharacter (originalNormal);
} else {
if (mainGravitySystem.isUsingRegularGravity ()) {
mainGravitySystem.changeColor (false);
} else {
mainGravitySystem.changeColor (true);
}
}
wallWalkActive = false;
lastTimeWallWalkActive = Time.time;
lastTimeResetSurfaceRotationBelow = 0;
if (setAnimSpeedMultiplierOnWallRun) {
mainPlayerController.setNormalVelocity ();
}
checkEventsOnWallWalk (false);
}
}
public void setAnimSpeedMultiplierOnWallRunValue (float newValue)
{
animSpeedMultiplierOnWallRun = newValue;
}
public void setOriginalAnimSpeedMultiplierOnWallRunValue ()
{
setAnimSpeedMultiplierOnWallRunValue (originalAnimSpeedMultiplierOnWallRun);
}
public bool isWallWalkActive ()
{
return wallWalkActive;
}
public void setWalkWallEnabledState (bool state)
{
wallWalkEnabled = state;
if (wallWalkEnabled) {
mainCoroutine = StartCoroutine (updateCoroutine ());
mainCoroutineActive = true;
} else {
if (wallWalkActive) {
stopWallWalk ();
}
if (!trailsActive) {
stopUpdateCoroutine ();
}
}
}
public void toggleWalkWallEnabledState ()
{
setWalkWallEnabledState (!wallWalkEnabled);
}
public void disableWalkWallState ()
{
if (wallWalkActive) {
stopWallWalk ();
}
setWalkWallEnabledState (false);
}
public void setForceWalkWallActiveExternallyState (bool state)
{
forceWalkWallActiveExternally = state;
}
public void enableOrDisableWalkWallExternally (bool state, bool activateRunAction)
{
if (state) {
toggleWalkWallEnabledState ();
if (activateRunAction) {
if (!mainPlayerController.isPlayerRunning ()) {
mainPlayerController.inputStartToRun ();
originalNormal = mainGravitySystem.getCurrentRotatingNormal ();
lastTimeRunActivated = Time.time;
wallWalkActive = true;
activateWallWalk ();
}
}
} else {
disableWalkWallState ();
lastTimeRunActivated = 0;
if (!activateRunAction) {
if (mainPlayerController.isPlayerRunning ()) {
mainPlayerController.forceStopRun ();
}
}
}
}
void checkEventsOnWallWalk (bool state)
{
if (state) {
if (useEventOnWallWalkStart) {
eventOnWallWalkStart.Invoke ();
}
} else {
if (useEventOnWallWalkEnd) {
eventOnWallWalkEnd.Invoke ();
}
}
}
public void setMeshesInfo ()
{
trails.Clear ();
if (trailsPrefab != null) {
List<Transform> trailsPositions = mainRagdollActivator.getBodyPartsTransformList ();
for (int i = 0; i < trailsPositions.Count; i++) {
GameObject trailClone = (GameObject)Instantiate (trailsPrefab, Vector3.zero, Quaternion.identity);
//remove the clone string inside the instantiated object
trailClone.name = "Run Power Trail " + (i + 1).ToString ();
trailClone.transform.SetParent (trailsPositions [i]);
trailClone.transform.localPosition = Vector3.zero;
//trailClone.transform.localRotation = Quaternion.identity;
TrailRenderer currentTrailRenderer = trailClone.GetComponent<TrailRenderer> ();
currentTrailRenderer.enabled = false;
trails.Add (currentTrailRenderer);
}
}
storePlayerRendererFromEditor ();
updateComponent ();
}
public void getMaterialList ()
{
if (materialList.Count == 0) {
int rendererPartsCount = rendererParts.Count;
for (int i = 0; i < rendererPartsCount; i++) {
Renderer currentRenderer = rendererParts [i];
if (currentRenderer != null) {
int materialsLength = currentRenderer.materials.Length;
for (int j = 0; j < materialsLength; j++) {
Material currentMaterial = currentRenderer.materials [j];
if (currentMaterial != null) {
materialList.Add (currentMaterial);
}
}
}
}
}
}
public void clearRendererList ()
{
rendererParts.Clear ();
}
public void storePlayerRenderer ()
{
clearRendererList ();
for (int i = 0; i < playerGameObjectList.Count; i++) {
GameObject currentObject = playerGameObjectList [i];
if (currentObject != null) {
Renderer currentRenderer = currentObject.GetComponent<Renderer> ();
rendererParts.Add (currentRenderer);
}
}
for (int i = 0; i < playerGameObjectWithChildList.Count; i++) {
GameObject currentObject = playerGameObjectWithChildList [i];
if (currentObject != null) {
Component [] components = currentObject.GetComponentsInChildren (typeof (Renderer));
foreach (Renderer child in components) {
rendererParts.Add (child);
}
}
}
if (showDebugPrint) {
print ("Total amount of " + rendererParts.Count + " render found");
}
}
public void addplayerGameObjectListFromEditor (GameObject newObject)
{
if (!playerGameObjectList.Contains (newObject)) {
playerGameObjectList.Add (newObject);
}
updateComponent ();
}
public void storePlayerRendererFromEditor ()
{
storePlayerRenderer ();
updateComponent ();
}
public void updateComponent ()
{
GKC_Utils.updateComponent (this);
GKC_Utils.updateDirtyScene ("Update Gravity Wall Run System", gameObject);
}
}