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

619 lines
19 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
public class matchPlayerToTargetSystem : MonoBehaviour
{
[Header ("Main Settings")]
[Space]
public bool matchSystemEnabled = true;
public float matchSpeed = 10;
public float positionOffset;
public bool ignoreCustomPositionOffset;
public bool useDistancePercentageAsOffset;
[Range (0, 1)] public float positionOffsetPercentage;
[Space]
[Space]
public float minDistanceToMatchPosition;
public float maxDistanceToMatchPosition;
[Space]
public float minAngleToMatchRotation;
public float maxAngleToMatchRotation;
public bool adjustRotationEvenIfNotMoved;
public float minDistanceToMatchRotation;
public float maxDistanceToMatchRotation;
[Space]
public bool useMaxDistanceToCameraCenter;
public float maxDistanceToCameraCenter;
public bool useMoveInputAsDirectionToClosestTarget;
[Space]
[Header ("Vertical Distance Settings")]
[Space]
public bool adjustVerticalPositionEnabled;
public float raycastDistanceForVerticalPosition;
public LayerMask layerMaskForVerticalPosition;
[Space]
public bool checkMaxVerticalDistanceWithTarget;
public float maxVerticalDistanceWithTarget;
[Space]
public bool checkIfObstaclesToTarget;
public LayerMask layerToCheckTarget;
[Space]
[Header ("Front Position Settings")]
[Space]
public bool useFrontPositionAsPositionToMatch;
public Vector3 frontPositionAsPositionToMatchOffset;
[Space]
[Header ("Other Settings")]
[Space]
public bool addMainPlayerOnListForAI;
[Space]
[Header ("Debug")]
[Space]
public bool showDebugPrint;
public bool movementActive;
public bool matchPositionPaused;
public bool getClosestTargetWithoutConditionsActive;
public List<Transform> charactersAround = new List<Transform> ();
[Space]
[Header ("Events")]
[Space]
public bool useEventsOnTargetsChange;
public UnityEvent eventOnTargetsDetected;
public UnityEvent eventOnTargetsRemoved;
public bool useEventOnFirstTargetDetected;
public UnityEvent eventOnFirstTargetDetected;
public bool useEventOnLastTargetRemoved;
public UnityEvent eventOnLastTargetRemoved;
[Space]
[Header ("Components")]
[Space]
public Transform playerTransform;
public Transform debugTargetToMatchTransform;
public Camera mainCamera;
public playerCamera mainPlayerCamera;
public playerController mainPlayerController;
public playerInputManager mainPlayerInputManager;
Coroutine movementCoroutine;
Vector3 screenPoint;
Vector3 characterPosition;
Vector3 centerScreen;
Vector3 currentPlayerPosition;
bool playerCheckInitialized;
public void findPlayerOnScene ()
{
addCharacterAround (GKC_Utils.findMainPlayerTransformOnScene ());
}
public void addCharacterAround (Transform newCharacter)
{
if (newCharacter == null) {
return;
}
if (!charactersAround.Contains (newCharacter)) {
charactersAround.Add (newCharacter);
checkRemoveEmptyObjects ();
if (charactersAround.Count == 1) {
checkEventOnFirstTargetDetected ();
}
checkEventsOnTargetsChange (true);
if (showDebugPrint) {
print ("Adding target " + newCharacter.name);
}
}
}
public void removeCharacterAround (Transform newCharacter)
{
if (charactersAround.Contains (newCharacter)) {
charactersAround.Remove (newCharacter);
checkRemoveEmptyObjects ();
if (showDebugPrint) {
print ("Removing target " + newCharacter.name);
}
}
if (charactersAround.Count == 0) {
checkEventsOnTargetsChange (false);
checkEventOnLastTargetRemoved ();
}
}
public void clearAllCharactersAround ()
{
if (charactersAround.Count > 0) {
charactersAround.Clear ();
}
checkEventsOnTargetsChange (false);
checkEventOnLastTargetRemoved ();
}
public void setMatchPositionPausedState (bool state)
{
matchPositionPaused = state;
}
public void setMatchSystemEnabledstate (bool state)
{
matchSystemEnabled = state;
}
public void setAddMainPlayerOnListForAIState (bool state)
{
addMainPlayerOnListForAI = state;
}
public void activateMatchPosition (float customOffset)
{
if (!matchSystemEnabled) {
return;
}
if (matchPositionPaused) {
return;
}
if (!playerCheckInitialized) {
if (matchSystemEnabled && addMainPlayerOnListForAI) {
findPlayerOnScene ();
}
playerCheckInitialized = true;
}
if (debugTargetToMatchTransform != null) {
activateMatchPosition (debugTargetToMatchTransform, customOffset);
return;
}
Transform transformToMatchPosition = getCurrentTargetToMatchPosition ();
if (transformToMatchPosition != null) {
activateMatchPosition (transformToMatchPosition, customOffset);
if (showDebugPrint) {
print ("activating match position for " + transformToMatchPosition.name);
}
} else {
if (showDebugPrint) {
print ("no target to match found");
}
}
if (charactersAround.Count == 0) {
checkEventsOnTargetsChange (false);
checkEventOnLastTargetRemoved ();
}
}
public void activateMatchPosition (Transform targetToUse, float customOffset)
{
stopMovement ();
if (targetToUse == null) {
return;
}
movementCoroutine = StartCoroutine (activateMatchPositionCoroutine (targetToUse, customOffset));
}
public void stopMovement ()
{
if (movementCoroutine != null) {
StopCoroutine (movementCoroutine);
}
movementActive = false;
}
public void setUseFrontPositionAsPositionToMatchState (bool state)
{
useFrontPositionAsPositionToMatch = state;
}
IEnumerator activateMatchPositionCoroutine (Transform targetToUse, float customOffset)
{
movementActive = true;
Vector3 targetToUsePosition = targetToUse.position;
if (useFrontPositionAsPositionToMatch) {
targetToUsePosition += targetToUse.right * frontPositionAsPositionToMatchOffset.x +
targetToUse.up * frontPositionAsPositionToMatchOffset.y +
targetToUse.forward * frontPositionAsPositionToMatchOffset.z;
}
Vector3 currentPosition = playerTransform.position;
Vector3 direction = new Vector3 (targetToUsePosition.x, currentPosition.y, targetToUsePosition.z) - currentPosition;
direction = direction / direction.magnitude;
float angle = Vector3.SignedAngle (playerTransform.forward, direction, playerTransform.up);
if (useFrontPositionAsPositionToMatch) {
angle = Vector3.SignedAngle (playerTransform.forward, -targetToUse.forward, playerTransform.up);
}
float distanceToTarget = GKC_Utils.distance (targetToUsePosition, currentPosition);
float currentPositionOffset = positionOffset;
if (useFrontPositionAsPositionToMatch) {
currentPositionOffset = customOffset;
} else {
if (customOffset != 0 && !ignoreCustomPositionOffset) {
currentPositionOffset = customOffset;
} else {
if (useDistancePercentageAsOffset) {
currentPositionOffset = distanceToTarget * positionOffsetPercentage;
}
}
float targetToUseRadius = GKC_Utils.getCharacterRadius (targetToUse);
currentPositionOffset += mainPlayerController.getCharacterRadius () + targetToUseRadius;
}
if (adjustVerticalPositionEnabled) {
direction = targetToUsePosition - currentPosition;
direction = direction / direction.magnitude;
}
Vector3 targetPosition = currentPosition + direction * (distanceToTarget - currentPositionOffset);
if (showDebugPrint) {
print (targetPosition + " " + currentPosition + " " + currentPositionOffset);
}
if (adjustVerticalPositionEnabled) {
RaycastHit hit;
if (Physics.Raycast (targetPosition + playerTransform.up * 1.2f, -playerTransform.up, out hit, raycastDistanceForVerticalPosition, layerMaskForVerticalPosition)) {
targetPosition = hit.point;
}
}
Quaternion targetRotation = Quaternion.Euler (playerTransform.eulerAngles + playerTransform.up * angle);
bool targetReached = false;
float angleDifference = 0;
float positionDifference = 0;
float t = 0;
float movementTimer = 0;
float dist = GKC_Utils.distance (targetPosition, currentPosition);
float duration = dist / matchSpeed;
bool positionChangeActive = false;
bool rotationChangeActive = false;
if (distanceToTarget > minDistanceToMatchPosition && distanceToTarget < maxDistanceToMatchPosition) {
positionChangeActive = true;
}
if (positionChangeActive ||
(adjustRotationEvenIfNotMoved && distanceToTarget > minDistanceToMatchRotation && distanceToTarget < maxDistanceToMatchRotation)) {
if (Mathf.Abs (angle) > minAngleToMatchRotation && Mathf.Abs (angle) < maxAngleToMatchRotation) {
rotationChangeActive = true;
}
}
while (!targetReached) {
t += Time.deltaTime / duration;
if (positionChangeActive) {
playerTransform.position = Vector3.Lerp (playerTransform.position, targetPosition, t);
}
if (rotationChangeActive) {
playerTransform.rotation = Quaternion.Lerp (playerTransform.rotation, targetRotation, t);
}
angleDifference = Quaternion.Angle (playerTransform.rotation, targetRotation);
positionDifference = GKC_Utils.distance (playerTransform.position, targetPosition);
movementTimer += Time.deltaTime;
if (positionChangeActive && rotationChangeActive) {
if (positionDifference < 0.01f && angleDifference < 0.2f) {
targetReached = true;
}
} else {
if (rotationChangeActive) {
if (angleDifference < 0.2f) {
targetReached = true;
}
}
if (positionChangeActive) {
if (positionDifference < 0.01f) {
targetReached = true;
}
}
}
if (movementTimer > (duration + 1)) {
targetReached = true;
}
if (!positionChangeActive && !rotationChangeActive) {
targetReached = true;
}
yield return null;
}
movementActive = false;
}
public Transform getCurrentTargetToMatchPosition ()
{
if (!matchSystemEnabled) {
return null;
}
if (matchPositionPaused) {
return null;
}
if (!playerCheckInitialized) {
if (matchSystemEnabled && addMainPlayerOnListForAI) {
findPlayerOnScene ();
}
playerCheckInitialized = true;
}
float maxDistanceToTarget = Mathf.Infinity;
Transform transformToMatchPosition = null;
float currentDistance = 0;
float currentDistanceToScreenCenter = 0;
centerScreen = mainPlayerCamera.getScreenCenter ();
bool ignoreRestOfChecks = false;
float maxAngleWithTarget = Mathf.Infinity;
currentPlayerPosition = playerTransform.position;
Transform currentLockedCameraTransform = mainPlayerCamera.getCurrentLockedCameraTransform ();
if (mainCamera == null) {
mainCamera = mainPlayerCamera.getMainCamera ();
}
for (int i = charactersAround.Count - 1; i >= 0; i--) {
if (charactersAround [i] != null) {
if (!applyDamage.checkIfDead (charactersAround [i].gameObject)) {
characterPosition = charactersAround [i].position;
if (getClosestTargetWithoutConditionsActive) {
currentDistance = GKC_Utils.distance (characterPosition, currentPlayerPosition);
if (currentDistance < maxDistanceToTarget) {
maxDistanceToTarget = currentDistance;
transformToMatchPosition = charactersAround [i];
}
} else {
screenPoint = mainCamera.WorldToScreenPoint (characterPosition);
currentDistanceToScreenCenter = GKC_Utils.distance (screenPoint, centerScreen);
bool canBeChecked = false;
if (useMoveInputAsDirectionToClosestTarget) {
Vector2 rawAxisvalues = mainPlayerInputManager.rawMovementAxis;
if (rawAxisvalues != Vector2.zero) {
Vector3 direction = new Vector3 (characterPosition.x, currentPlayerPosition.y, characterPosition.z) - currentPlayerPosition;
direction = direction / direction.magnitude;
Vector3 inputDirection = Vector3.zero;
if (mainPlayerCamera.isCameraTypeFree ()) {
inputDirection = (rawAxisvalues.y * mainPlayerCamera.transform.forward + rawAxisvalues.x * mainPlayerCamera.transform.right);
} else {
inputDirection = (rawAxisvalues.y * currentLockedCameraTransform.forward + rawAxisvalues.x * currentLockedCameraTransform.right);
}
inputDirection.Normalize ();
float angle = Vector3.SignedAngle (inputDirection, direction, playerTransform.up);
ignoreRestOfChecks = true;
if (Mathf.Abs (angle) < maxAngleWithTarget) {
maxAngleWithTarget = Mathf.Abs (angle);
transformToMatchPosition = charactersAround [i];
}
}
}
if (!ignoreRestOfChecks) {
//unity takes the resolution of the main screen if the press or input is done on
//the editor it self, instead of taking the resolution of the game window
if (useMaxDistanceToCameraCenter && mainPlayerCamera.isCameraTypeFree ()) {
if (currentDistanceToScreenCenter < maxDistanceToCameraCenter) {
canBeChecked = true;
}
} else {
canBeChecked = true;
}
if (checkMaxVerticalDistanceWithTarget) {
float verticalDistance = Mathf.Abs (characterPosition.y - currentPlayerPosition.y);
if (verticalDistance > maxVerticalDistanceWithTarget) {
canBeChecked = false;
if (showDebugPrint) {
print ("vertical distance too long " + verticalDistance);
}
}
}
if (checkIfObstaclesToTarget) {
RaycastHit hit;
Vector3 raycastPosition = currentPlayerPosition + playerTransform.up;
Vector3 targetPosition = charactersAround [i].position + charactersAround [i].up;
Vector3 raycastDirection = raycastPosition - targetPosition;
raycastDirection = raycastDirection / raycastDirection.magnitude;
float raycastDistance = GKC_Utils.distance (raycastPosition, targetPosition);
if (Physics.Raycast (raycastPosition, raycastDirection, out hit, raycastDistance, layerToCheckTarget)) {
canBeChecked = false;
if (showDebugPrint) {
print ("obstacle detected " + hit.collider.name);
}
}
}
if (canBeChecked) {
currentDistance = GKC_Utils.distance (characterPosition, currentPlayerPosition);
if (currentDistance < maxDistanceToTarget) {
maxDistanceToTarget = currentDistance;
transformToMatchPosition = charactersAround [i];
}
}
}
}
} else {
charactersAround.RemoveAt (i);
}
} else {
charactersAround.RemoveAt (i);
}
}
return transformToMatchPosition;
}
void checkEventsOnTargetsChange (bool state)
{
if (useEventsOnTargetsChange) {
if (state) {
eventOnTargetsDetected.Invoke ();
} else {
eventOnTargetsRemoved.Invoke ();
}
}
}
void checkEventOnFirstTargetDetected ()
{
if (useEventOnFirstTargetDetected) {
eventOnFirstTargetDetected.Invoke ();
}
}
void checkEventOnLastTargetRemoved ()
{
if (useEventOnLastTargetRemoved) {
eventOnLastTargetRemoved.Invoke ();
}
}
void checkRemoveEmptyObjects ()
{
for (int i = charactersAround.Count - 1; i >= 0; i--) {
if (charactersAround [i] == null) {
charactersAround.RemoveAt (i);
}
}
}
public void setGetClosestTargetWithoutConditionsActiveState (bool state)
{
getClosestTargetWithoutConditionsActive = state;
}
}