Files

521 lines
17 KiB
C#
Raw Permalink Normal View History

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class attrackObjectsSystem : MonoBehaviour
{
2026-03-29 23:03:14 -07:00
[Header ("Main Settings")]
[Space]
2026-03-29 23:03:14 -07:00
public bool attractionEnabled;
2026-03-29 23:03:14 -07:00
public bool attractionApplyForce = true;
public float attractionRadius = 20;
2026-03-29 23:03:14 -07:00
public LayerMask layerToSearch;
2026-03-29 23:03:14 -07:00
[Space]
2026-03-29 23:03:14 -07:00
public float attractionVelocity = 10;
public float attractionForce = 1000;
public ForceMode forceMode;
2026-03-29 23:03:14 -07:00
public float maxThrowForce = 3500;
public float increaseThrowForceSpeed = 1500;
2026-03-29 23:03:14 -07:00
public List<string> tagToLocate = new List<string> ();
2026-03-29 23:03:14 -07:00
public LayerMask layerToDamage;
2026-03-29 23:03:14 -07:00
[Space]
[Header ("Remote Events Settings")]
[Space]
2026-03-29 23:03:14 -07:00
public bool useRemoteEventOnObjectsFound;
public List<string> remoteEventNameListOnGrabObject = new List<string> ();
public List<string> remoteEventNameListOnDropObject = new List<string> ();
2026-03-29 23:03:14 -07:00
[Space]
[Header ("Debug")]
[Space]
2026-03-29 23:03:14 -07:00
public bool carryingObjects;
public bool attractionActive;
2026-03-29 23:03:14 -07:00
[Space]
[Header ("Events Settings")]
[Space]
2026-03-29 23:03:14 -07:00
public UnityEvent eventsOnActivateAttraction;
public UnityEvent eventOnDeactivateAttraction;
2026-03-29 23:03:14 -07:00
[Space]
[Header ("Components")]
[Space]
2026-03-29 23:03:14 -07:00
public Slider powerSlider;
public Transform mainCameraTransform;
public Transform attractionPosition;
public Collider playerCollider;
public GameObject playerGameObject;
2026-03-29 23:03:14 -07:00
public playerWeaponSystem mainPlayerWeaponSystem;
2026-03-29 23:03:14 -07:00
float currentForceToLaunchObjects;
2026-03-29 23:03:14 -07:00
Rigidbody currentRigidbody;
2026-03-29 23:03:14 -07:00
Vector3 attractDirection;
2026-03-29 23:03:14 -07:00
Vector3 currentPosition;
2026-03-29 23:03:14 -07:00
RaycastHit hit;
2026-03-29 23:03:14 -07:00
List<grabbedObject> grabbedObjectList = new List<grabbedObject> ();
2026-03-29 23:03:14 -07:00
float lastTimeActivateAttraction;
2026-03-29 23:03:14 -07:00
Vector3 nextObjectHeldPosition;
Vector3 currentObjectHeldPosition;
2026-03-29 23:03:14 -07:00
Coroutine grabObjectsCoroutine;
2026-03-29 23:03:14 -07:00
bool componentsInitialized;
2026-03-29 23:03:14 -07:00
Coroutine updateCoroutine;
2026-03-29 23:03:14 -07:00
void Awake ()
{
if (mainCameraTransform == null) {
mainCameraTransform = transform;
}
2026-03-29 23:03:14 -07:00
if (playerGameObject == null) {
playerGameObject = gameObject;
}
}
2026-03-29 23:03:14 -07:00
public void stopUpdateCoroutine ()
{
if (updateCoroutine != null) {
StopCoroutine (updateCoroutine);
}
}
2026-03-29 23:03:14 -07:00
IEnumerator updateSystemCoroutine ()
{
var waitTime = new WaitForFixedUpdate ();
2026-03-29 23:03:14 -07:00
while (true) {
updateSystem ();
2026-03-29 23:03:14 -07:00
yield return waitTime;
}
}
2026-03-29 23:03:14 -07:00
void updateSystem ()
{
if (attractionActive) {
2026-03-29 23:03:14 -07:00
if (!carryingObjects) {
return;
}
2026-03-29 23:03:14 -07:00
currentPosition = attractionPosition.position;
2026-03-29 23:03:14 -07:00
int grabbedObjectListCount = grabbedObjectList.Count;
2026-03-29 23:03:14 -07:00
for (int i = 0; i < grabbedObjectListCount; i++) {
if (grabbedObjectList [i].objectToMove != null) {
currentRigidbody = grabbedObjectList [i].mainRigidbody;
2026-03-29 23:03:14 -07:00
if (currentRigidbody != null) {
2026-03-29 23:03:14 -07:00
if (attractionApplyForce) {
attractDirection = currentPosition - currentRigidbody.position;
2026-03-29 23:03:14 -07:00
currentRigidbody.AddForce (attractDirection.normalized * (attractionForce * currentRigidbody.mass * Time.fixedDeltaTime), forceMode);
} else {
nextObjectHeldPosition = currentPosition + attractionPosition.forward;
2026-03-29 23:03:14 -07:00
currentObjectHeldPosition = currentRigidbody.position;
2026-03-29 23:03:14 -07:00
currentRigidbody.linearVelocity = (nextObjectHeldPosition - currentObjectHeldPosition) * attractionVelocity;
}
}
}
}
}
}
2026-03-29 23:03:14 -07:00
public void setAttractionEnabledState (bool state)
{
attractionEnabled = state;
2026-03-29 23:03:14 -07:00
if (!attractionEnabled) {
updateSystemCoroutine ();
}
}
2026-03-29 23:03:14 -07:00
public void checkGrabObject ()
{
if (grabObjectsCoroutine != null) {
StopCoroutine (grabObjectsCoroutine);
}
2026-03-29 23:03:14 -07:00
grabObjectsCoroutine = StartCoroutine (checkGrabObjectCoroutine ());
}
2026-03-29 23:03:14 -07:00
IEnumerator checkGrabObjectCoroutine ()
{
yield return new WaitForSeconds (0.05f);
2026-03-29 23:03:14 -07:00
if (attractionEnabled && !carryingObjects) {
lastTimeActivateAttraction = Time.time;
2026-03-29 23:03:14 -07:00
initializeComponents ();
2026-03-29 23:03:14 -07:00
attractionActive = true;
2026-03-29 23:03:14 -07:00
updateCoroutine = StartCoroutine (updateSystemCoroutine ());
2026-03-29 23:03:14 -07:00
grabCloseObjects ();
2026-03-29 23:03:14 -07:00
if (carryingObjects) {
eventsOnActivateAttraction.Invoke ();
}
}
}
2026-03-29 23:03:14 -07:00
public void inputGrabObjects ()
{
checkGrabObject ();
}
2026-03-29 23:03:14 -07:00
public void inputHoldToLaunchObject ()
{
if (!attractionEnabled) {
return;
}
2026-03-29 23:03:14 -07:00
if (carryingObjects) {
if (Time.time > lastTimeActivateAttraction + 0.5f) {
addForceToLaunchObjects ();
}
}
}
2026-03-29 23:03:14 -07:00
public void inputReleaseToLaunchObject ()
{
if (!attractionEnabled) {
return;
}
2026-03-29 23:03:14 -07:00
if (carryingObjects) {
if (Time.time > lastTimeActivateAttraction + 0.5f) {
dropObjects ();
2026-03-29 23:03:14 -07:00
attractionActive = false;
2026-03-29 23:03:14 -07:00
stopUpdateCoroutine ();
2026-03-29 23:03:14 -07:00
eventOnDeactivateAttraction.Invoke ();
}
}
}
2026-03-29 23:03:14 -07:00
public void grabCloseObjects ()
{
//if the player has not grabbedObjects, store them
if (grabbedObjectList.Count == 0) {
//check in a radius, the close objects which can be grabbed
currentPosition = attractionPosition.position;
2026-03-29 23:03:14 -07:00
int ignoreRaycastLayerIndex = LayerMask.NameToLayer ("Ignore Raycast");
2026-03-29 23:03:14 -07:00
Collider [] objects = Physics.OverlapSphere (currentPosition, attractionRadius, layerToSearch);
foreach (Collider currentCollider in objects) {
2026-03-29 23:03:14 -07:00
Rigidbody currentRigidbody = currentCollider.GetComponent<Rigidbody> ();
2026-03-29 23:03:14 -07:00
if (tagToLocate.Contains (currentCollider.tag) && currentRigidbody != null) {
if (currentRigidbody.isKinematic) {
currentRigidbody.isKinematic = false;
}
2026-03-29 23:03:14 -07:00
grabbedObject newGrabbedObject = new grabbedObject ();
//removed tag and layer after store them, so the camera can still use raycast properly
2026-03-29 23:03:14 -07:00
GameObject currentObject = currentCollider.gameObject;
newGrabbedObject.objectToMove = currentObject;
newGrabbedObject.objectTag = currentObject.tag;
newGrabbedObject.objectLayer = currentObject.layer;
newGrabbedObject.mainRigidbody = currentRigidbody;
2026-03-29 23:03:14 -07:00
if (useRemoteEventOnObjectsFound) {
remoteEventSystem currentRemoteEventSystem = currentObject.GetComponent<remoteEventSystem> ();
2026-03-29 23:03:14 -07:00
if (currentRemoteEventSystem != null) {
for (int i = 0; i < remoteEventNameListOnGrabObject.Count; i++) {
2026-03-29 23:03:14 -07:00
currentRemoteEventSystem.callRemoteEvent (remoteEventNameListOnGrabObject [i]);
}
}
}
2026-03-29 23:03:14 -07:00
currentObject.tag = "Untagged";
2026-03-29 23:03:14 -07:00
currentObject.layer = ignoreRaycastLayerIndex;
2026-03-29 23:03:14 -07:00
currentRigidbody.useGravity = false;
2026-03-29 23:03:14 -07:00
//get the distance from every object to left and right side of the player, to set every side as parent of every object
//disable collisions between the player and the objects, to avoid issues
if (playerCollider != null) {
Physics.IgnoreCollision (currentCollider, playerCollider, true);
}
2026-03-29 23:03:14 -07:00
//if any object grabbed has its own gravity, paused the script to move the object properly
artificialObjectGravity currentArtificialObjectGravity = currentObject.GetComponent<artificialObjectGravity> ();
2026-03-29 23:03:14 -07:00
if (currentArtificialObjectGravity != null) {
currentArtificialObjectGravity.setActiveState (false);
}
2026-03-29 23:03:14 -07:00
grabObjectProperties currentGrabObjectProperties = currentObject.GetComponent<grabObjectProperties> ();
2026-03-29 23:03:14 -07:00
if (currentGrabObjectProperties != null) {
currentGrabObjectProperties.checkEventsOnGrabObject ();
}
2026-03-29 23:03:14 -07:00
grabbedObjectState currentGrabbedObjectState = currentObject.GetComponent<grabbedObjectState> ();
2026-03-29 23:03:14 -07:00
if (currentGrabbedObjectState == null) {
currentGrabbedObjectState = currentObject.AddComponent<grabbedObjectState> ();
}
2026-03-29 23:03:14 -07:00
objectToPlaceSystem currentObjectToPlaceSystem = currentObject.GetComponent<objectToPlaceSystem> ();
2026-03-29 23:03:14 -07:00
if (currentObjectToPlaceSystem != null) {
currentObjectToPlaceSystem.setObjectInGrabbedState (true);
}
2026-03-29 23:03:14 -07:00
//if any object is pickable and is inside an opened chest, activate its trigger or if it has been grabbed by the player, remove of the list
pickUpObject currentPickUpObject = currentObject.GetComponent<pickUpObject> ();
2026-03-29 23:03:14 -07:00
if (currentPickUpObject) {
currentPickUpObject.activateObjectTrigger ();
}
2026-03-29 23:03:14 -07:00
deviceStringAction currentDeviceStringAction = currentObject.GetComponentInChildren<deviceStringAction> ();
2026-03-29 23:03:14 -07:00
if (currentDeviceStringAction != null) {
currentDeviceStringAction.setIconEnabledState (false);
}
2026-03-29 23:03:14 -07:00
if (currentGrabbedObjectState != null) {
currentGrabbedObjectState.setCurrentHolder (gameObject);
2026-03-29 23:03:14 -07:00
currentGrabbedObjectState.setGrabbedState (true);
}
2026-03-29 23:03:14 -07:00
grabbedObjectList.Add (newGrabbedObject);
}
}
2026-03-29 23:03:14 -07:00
//if there are not any object close to the player, cancel
if (grabbedObjectList.Count > 0) {
carryingObjects = true;
} else {
attractionActive = false;
2026-03-29 23:03:14 -07:00
stopUpdateCoroutine ();
}
2026-03-29 23:03:14 -07:00
powerSlider.maxValue = maxThrowForce;
2026-03-29 23:03:14 -07:00
currentForceToLaunchObjects = 0;
}
}
2026-03-29 23:03:14 -07:00
//drop or throw the current grabbed objects
public void dropObjects ()
{
//get the point at which the camera is looking, to throw the objects in that direction
Vector3 hitDirection = Vector3.zero;
2026-03-29 23:03:14 -07:00
bool surfaceFound = false;
2026-03-29 23:03:14 -07:00
if (Physics.Raycast (mainCameraTransform.position, mainCameraTransform.forward, out hit, Mathf.Infinity, layerToDamage)) {
if (hit.collider != playerCollider) {
surfaceFound = true;
} else {
if (Physics.Raycast (hit.point + mainCameraTransform.forward, mainCameraTransform.forward, out hit, Mathf.Infinity, layerToDamage)) {
surfaceFound = true;
}
}
}
2026-03-29 23:03:14 -07:00
if (surfaceFound) {
hitDirection = hit.point;
}
2026-03-29 23:03:14 -07:00
for (int j = 0; j < grabbedObjectList.Count; j++) {
dropObject (grabbedObjectList [j], hitDirection);
}
2026-03-29 23:03:14 -07:00
carryingObjects = false;
grabbedObjectList.Clear ();
2026-03-29 23:03:14 -07:00
powerSlider.value = 0;
}
2026-03-29 23:03:14 -07:00
public void addForceToLaunchObjects ()
{
if (currentForceToLaunchObjects < maxThrowForce) {
//enable the power slider in the center of the screen
currentForceToLaunchObjects += Time.deltaTime * increaseThrowForceSpeed;
2026-03-29 23:03:14 -07:00
if (currentForceToLaunchObjects > 300) {
2026-03-29 23:03:14 -07:00
powerSlider.value = currentForceToLaunchObjects;
}
}
}
2026-03-29 23:03:14 -07:00
public void dropObject (grabbedObject currentGrabbedObject, Vector3 launchDirection)
{
GameObject currentObject = currentGrabbedObject.objectToMove;
2026-03-29 23:03:14 -07:00
Rigidbody currentRigidbody = currentGrabbedObject.mainRigidbody;
2026-03-29 23:03:14 -07:00
if (useRemoteEventOnObjectsFound) {
remoteEventSystem currentRemoteEventSystem = currentObject.GetComponent<remoteEventSystem> ();
2026-03-29 23:03:14 -07:00
if (currentRemoteEventSystem != null) {
for (int i = 0; i < remoteEventNameListOnDropObject.Count; i++) {
2026-03-29 23:03:14 -07:00
currentRemoteEventSystem.callRemoteEvent (remoteEventNameListOnDropObject [i]);
}
}
}
2026-03-29 23:03:14 -07:00
currentObject.transform.SetParent (null);
2026-03-29 23:03:14 -07:00
currentObject.tag = currentGrabbedObject.objectTag;
currentObject.layer = currentGrabbedObject.objectLayer;
2026-03-29 23:03:14 -07:00
//drop the objects, because the grab objects button has been pressed quickly
if (currentForceToLaunchObjects < 300) {
if (playerCollider != null) {
Physics.IgnoreCollision (currentObject.GetComponent<Collider> (), playerCollider, false);
}
}
//launch the objects according to the amount of time that the player has held the buttton
if (currentForceToLaunchObjects > 300) {
//if the objects are launched, add the script launchedObject, to damage any enemy that the object would touch
currentObject.AddComponent<launchedObjects> ().setCurrentPlayerAndCollider (playerGameObject, playerCollider);
//if there are any collider in from of the camera, use the hit point, else, use the camera direciton
if (launchDirection != Vector3.zero) {
Vector3 throwDirection = launchDirection - currentObject.transform.position;
throwDirection = throwDirection / throwDirection.magnitude;
currentRigidbody.AddForce (throwDirection * currentForceToLaunchObjects * currentRigidbody.mass);
} else {
currentRigidbody.AddForce (mainCameraTransform.TransformDirection (Vector3.forward) * currentForceToLaunchObjects * currentRigidbody.mass);
}
}
//set again the custom gravity of the object
artificialObjectGravity currentArtificialObjectGravity = currentObject.GetComponent<artificialObjectGravity> ();
if (currentArtificialObjectGravity != null) {
currentArtificialObjectGravity.setActiveState (true);
}
grabObjectProperties currentGrabObjectProperties = currentObject.GetComponent<grabObjectProperties> ();
if (currentGrabObjectProperties != null) {
currentGrabObjectProperties.checkEventsOnDropObject ();
}
deviceStringAction currentDeviceStringAction = currentObject.GetComponentInChildren<deviceStringAction> ();
if (currentDeviceStringAction != null) {
currentDeviceStringAction.setIconEnabledState (true);
}
objectToPlaceSystem currentObjectToPlaceSystem = currentObject.GetComponent<objectToPlaceSystem> ();
if (currentObjectToPlaceSystem != null) {
currentObjectToPlaceSystem.setObjectInGrabbedState (false);
}
grabbedObjectState currentGrabbedObjectState = currentObject.GetComponent<grabbedObjectState> ();
if (currentGrabbedObjectState != null) {
bool currentObjectWasInsideGravityRoom = currentGrabbedObjectState.isInsideZeroGravityRoom ();
currentGrabbedObjectState.checkGravityRoomState ();
currentGrabbedObjectState.setGrabbedState (false);
if (!currentObjectWasInsideGravityRoom) {
currentGrabbedObjectState.removeGrabbedObjectComponent ();
currentRigidbody.useGravity = true;
}
}
}
public void checkIfDropObject (GameObject objectToCheck)
{
for (int j = 0; j < grabbedObjectList.Count; j++) {
if (grabbedObjectList [j].objectToMove == objectToCheck) {
dropObject (grabbedObjectList [j], Vector3.zero);
grabbedObjectList [j].objectToMove = null;
return;
}
}
}
void initializeComponents ()
{
if (componentsInitialized) {
return;
}
if (mainPlayerWeaponSystem != null) {
playerGameObject = mainPlayerWeaponSystem.getPlayerWeaponsManger ().gameObject;
playerComponentsManager mainPlayerComponentsManager = playerGameObject.GetComponent<playerComponentsManager> ();
if (mainPlayerComponentsManager != null) {
playerCollider = mainPlayerComponentsManager.getPlayerController ().getMainCollider ();
mainCameraTransform = mainPlayerComponentsManager.getPlayerCamera ().getCameraTransform ();
}
}
componentsInitialized = true;
}
[System.Serializable]
public class grabbedObject
{
public GameObject objectToMove;
public string objectTag;
public int objectLayer;
public Rigidbody mainRigidbody;
}
}