using System.Collections; using System.Collections.Generic; using UnityEngine; public class joinObjectsPower : MonoBehaviour { [Header ("Main Settings")] [Space] public bool powerEnabled = true; public float joinObjectsForce = 40; public float timeToRemoveJoin = 5; public float extraForceOnVehicles = 1; public bool useForceMode; public ForceMode forceModeObject1; public ForceMode forceModeObject2; [Space] [Header ("Debug")] [Space] public bool joinObjects; public Transform joinObject1; public Transform joinObject2; public bool joinKinematic1; public bool joinKinematic2; [Space] [Header ("Components")] [Space] public otherPowers powersManager; public LayerMask layer; public Transform mainCameraTransform; public GameObject impactParticles; public GameObject playerGameObject; GameObject joinParticles1; GameObject joinParticles2; Vector3 joinDirection1; Vector3 joinDirection2; Vector3 joinPosition1; Vector3 joinPosition2; RaycastHit hit; checkCollisionType currentCheckCollisionType1; checkCollisionType currentCheckCollisionType2; public Rigidbody currentRigidbody1; public Rigidbody currentRigidbody2; Vector3 heading1; Vector3 heading2; ParticleSystem particles1; ParticleSystem particles2; bool currentRigidbody1IsVehicle; bool currentRigidbody2IsVehicle; float lastTimeJoined; Coroutine updateCoroutine; public void stopUpdateCoroutine () { if (updateCoroutine != null) { StopCoroutine (updateCoroutine); } } IEnumerator updateSystemCoroutine () { var waitTime = new WaitForFixedUpdate (); while (true) { updateSystem (); yield return waitTime; } } void updateSystem () { //two objects are going to be attracted each other if (joinObjects) { if (Time.time > lastTimeJoined + timeToRemoveJoin) { removeObjectsjoin (); return; } //when both objects are stored, then it is checked if any of them have a rigidbody, to add force to them or not //to this, it is used checkCollisionType, a script that allows to check any type of collision with collider or triggers and enter or exit //and also can be configurated if the player want to check if the collision is with a particular object, in this case to both join object //the collision to check is the opposite object //once the script is added to every object, then the direction of the force to applied is calculated, and checking to which object can be applied if (currentCheckCollisionType1 && currentCheckCollisionType2) { //check if the player has not rigidbody, so the position to follow is the hit point if (joinKinematic1) { joinParticles2.transform.transform.LookAt (joinPosition1); heading1 = joinObject2.position - joinPosition1; } else { //else, the position of the direction is the position of the object //also a couple of particles are added joinParticles2.transform.transform.LookAt (joinObject1.position); heading1 = joinObject2.position - joinObject1.position; } joinDirection1 = heading1 / heading1.magnitude; if (joinKinematic2) { joinParticles1.transform.transform.LookAt (joinPosition2); heading2 = joinObject1.position - joinPosition2; } else { joinParticles1.transform.transform.LookAt (joinObject2.position); heading2 = joinObject1.position - joinObject2.position; } joinDirection2 = heading2 / heading2.magnitude; if (!particles1) { particles1 = joinParticles1.GetComponent (); } if (particles1) { var particles1Main = particles1.main; particles1Main.startSpeed = GKC_Utils.distance (joinParticles1.transform.position, joinObject2.position) / 2; } if (!particles2) { particles2 = joinParticles2.GetComponent (); } if (particles2) { var particles2Main = particles2.main; particles2Main.startSpeed = GKC_Utils.distance (joinParticles2.transform.position, joinObject1.position) / 2; } //add force to the object, according to the direction of the other object if (currentRigidbody1 && currentRigidbody2) { addForce (-joinDirection2 * (joinObjectsForce * currentRigidbody1.mass), currentRigidbody1, forceModeObject1, currentRigidbody1IsVehicle); addForce (-joinDirection1 * (joinObjectsForce * currentRigidbody2.mass), currentRigidbody2, forceModeObject2, currentRigidbody2IsVehicle); } else if (currentRigidbody1 && !currentRigidbody2) { addForce (-joinDirection2 * (joinObjectsForce * currentRigidbody1.mass), currentRigidbody1, forceModeObject1, currentRigidbody1IsVehicle); } else if (!currentRigidbody1 && currentRigidbody2) { addForce (-joinDirection1 * (joinObjectsForce * currentRigidbody2.mass), currentRigidbody2, forceModeObject2, currentRigidbody2IsVehicle); } else { //if both objects have not rigidbodies, then cancel the join removeObjectsjoin (); return; } //if the collision happens, the scripts are removed, and every object return to their normal situation if (currentCheckCollisionType1.active || currentCheckCollisionType2.active) { removeObjectsjoin (); } } } } public void addForce (Vector3 direction, Rigidbody rigidbodyAffected, ForceMode forceModeToUsse, bool isVehicle) { if (isVehicle) { direction *= extraForceOnVehicles; } if (useForceMode) { rigidbodyAffected.AddForce (direction, forceModeToUsse); } else { rigidbodyAffected.AddForce (direction); } } public void activatePower () { if (!powerEnabled) { return; } //this power allows the player to join two objects, and add force to both in the position of the other, checking if any of the objects //has rigidbody or not, and when both objects collide, the join is disabled if (joinObject1 == null || joinObject2 == null) { powersManager.createShootParticles (); //get every object using a raycast if (Physics.Raycast (mainCameraTransform.position, mainCameraTransform.forward, out hit, Mathf.Infinity, layer)) { if (joinObject1 == null) { joinObject1 = hit.collider.transform; GameObject characterDetected = applyDamage.getCharacterOrVehicle (joinObject1.gameObject); if (characterDetected != null) { currentRigidbody1IsVehicle = applyDamage.isVehicle (characterDetected); joinObject1 = characterDetected.transform; } if (!applyDamage.canApplyForce (joinObject1.gameObject)) { joinKinematic1 = true; joinPosition1 = hit.point; } joinParticles1 = (GameObject)Instantiate (impactParticles, hit.point, Quaternion.LookRotation (hit.normal)); joinParticles1.transform.SetParent (joinObject1); joinParticles1.SetActive (true); return; } if (joinObject2 == null && joinObject1 != hit.collider.transform && !hit.collider.transform.IsChildOf (joinObject1)) { joinObject2 = hit.collider.transform; GameObject characterDetected = applyDamage.getCharacterOrVehicle (joinObject2.gameObject); if (characterDetected != null) { currentRigidbody2IsVehicle = applyDamage.isVehicle (characterDetected); joinObject2 = characterDetected.transform; } if (!applyDamage.canApplyForce (joinObject2.gameObject)) { joinKinematic2 = true; joinPosition2 = hit.point; } joinParticles2 = (GameObject)Instantiate (impactParticles, hit.point, Quaternion.LookRotation (hit.normal)); joinParticles2.transform.SetParent (joinObject2); joinParticles2.SetActive (true); } } } if (joinObject1 != null && joinObject2 != null) { lastTimeJoined = Time.time; joinObjects = true; currentCheckCollisionType1 = joinObject1.GetComponent (); currentCheckCollisionType2 = joinObject2.GetComponent (); currentRigidbody1 = applyDamage.applyForce (joinObject1.gameObject); currentRigidbody2 = applyDamage.applyForce (joinObject2.gameObject); if (currentCheckCollisionType1 == null && currentCheckCollisionType2 == null) { joinObject1.gameObject.AddComponent (); joinObject2.gameObject.AddComponent (); currentCheckCollisionType1 = joinObject1.GetComponent (); currentCheckCollisionType2 = joinObject2.GetComponent (); currentCheckCollisionType1.onCollisionEnter = true; currentCheckCollisionType2.onCollisionEnter = true; currentCheckCollisionType1.objectToCollide = joinObject2.gameObject; currentCheckCollisionType2.objectToCollide = joinObject1.gameObject; if (currentRigidbody1 != null) { currentRigidbody1.useGravity = false; } if (currentRigidbody2 != null) { currentRigidbody2.useGravity = false; } //a join object can be used to be launched to an enemy, hurting him, to check this, it is used launchedObjects if (!joinKinematic1) { joinObject1.gameObject.AddComponent ().setCurrentPlayer (playerGameObject); } if (!joinKinematic2) { joinObject2.gameObject.AddComponent ().setCurrentPlayer (playerGameObject); } } stopUpdateCoroutine (); updateCoroutine = StartCoroutine (updateSystemCoroutine ()); } } //if none of the objects join have rigidbody, the join is cancelled public void removeObjectsjoin () { if (currentCheckCollisionType1 != null) { Destroy (currentCheckCollisionType1); } if (currentCheckCollisionType2 != null) { Destroy (currentCheckCollisionType2); } launchedObjects currentLaunchedObjects1 = joinObject1.GetComponent (); if (currentLaunchedObjects1 != null) { Destroy (currentLaunchedObjects1); } launchedObjects currentLaunchedObjects2 = joinObject2.GetComponent (); if (currentLaunchedObjects2 != null) { Destroy (currentLaunchedObjects2); } if (currentRigidbody1 != null) { currentRigidbody1.useGravity = true; currentRigidbody1 = null; } if (currentRigidbody2 != null) { currentRigidbody2.useGravity = true; currentRigidbody2 = null; } stopUpdateCoroutine (); joinObjects = false; joinObject1 = null; joinObject2 = null; joinKinematic1 = false; joinKinematic2 = false; Destroy (joinParticles1); Destroy (joinParticles2); particles1 = null; particles2 = null; currentRigidbody1IsVehicle = false; currentRigidbody2IsVehicle = false; } }