using System.Collections; using System.Collections.Generic; using UnityEngine; public class throwObjectTrayectorySystem : MonoBehaviour { [Header ("Main Settings")] [Space] public bool throwObjectEnabled = true; public LayerMask layerToCheckThrowObject; public float maxRaycastDistance = 30; public bool useInfiniteRaycastDistance; public bool useMaxDistanceWhenNoSurfaceFound; public float maxDistanceWhenNoSurfaceFound; [Space] public Transform throwPosition; [Space] public GameObject objectToThrow; [Space] [Header ("Other Settings")] [Space] public bool addLaunchObjectComponent; public bool addGrabbedObjectStateComponent; public bool rotateObjectTowardThrowDirection; public bool checkIfLockedCameraActive; public bool ignoreCollisionsWithPlayerEnabled = true; [Space] [Header ("Custom Throw Direction Settings")] [Space] public bool throwInCustomTransformDirection; public Transform customTransformDirection; public float customThrowDirectionAmount = 400; [Space] public bool useCustomThrowPosition; public bool useCustomThrowLocalPosition; public Vector3 customThrowPosition; public Vector3 customThrowRotation; [Space] [Header ("Debug")] [Space] public bool showGizmo; public GameObject currentObjectToThrow; public Vector3 currentThrowSpeed; [Space] [Header ("Components")] [Space] public playerCamera mainPlayerCamera; public GameObject playerControllerGameObject; public Transform targetPositionTransform; public Transform playerCameraGameObject; public Transform mainCameraTransform; public Collider playerCollider; Rigidbody newObjectToThrowRigidbody; RaycastHit hit; Vector3 currentTargetPosition; Vector3 raycastDirection; Vector3 raycastOrigin; Ray newRay; public void setCurrentObjectToThrow (GameObject newObject) { if (throwPosition == null) { throwPosition = transform; } currentObjectToThrow = newObject; currentObjectToThrow.transform.SetParent (throwPosition); Vector3 objectPosition = throwPosition.position; if (useCustomThrowPosition) { objectPosition = customThrowPosition; } if (useCustomThrowLocalPosition) { currentObjectToThrow.transform.localPosition = objectPosition; currentObjectToThrow.transform.localRotation = Quaternion.Euler (customThrowRotation); } else { currentObjectToThrow.transform.position = objectPosition; } currentObjectToThrow.SetActive (true); newObjectToThrowRigidbody = currentObjectToThrow.GetComponent (); if (newObjectToThrowRigidbody != null) { newObjectToThrowRigidbody.isKinematic = true; } if (ignoreCollisionsWithPlayerEnabled) { if (playerCollider != null) { Component [] components = currentObjectToThrow.GetComponentsInChildren (typeof (Collider)); foreach (Collider child in components) { Physics.IgnoreCollision (playerCollider, child, true); } } } } public void instantiateObject () { if (currentObjectToThrow == null) { if (throwPosition == null) { throwPosition = transform; } Vector3 objectPosition = throwPosition.position; Quaternion objectRotation = throwPosition.rotation; if (useCustomThrowPosition) { objectPosition = customThrowPosition; objectRotation = Quaternion.Euler (customThrowRotation); } GameObject newObjectToThrow = (GameObject)Instantiate (objectToThrow, objectPosition, objectRotation); setCurrentObjectToThrow (newObjectToThrow); } } public void calculateThrowDirection () { raycastDirection = mainCameraTransform.TransformDirection (Vector3.forward); raycastOrigin = mainCameraTransform.position; bool isPlayerMovingOn3dWorld = !mainPlayerCamera.is2_5ViewActive (); if (checkIfLockedCameraActive) { if (mainPlayerCamera != null) { if (!mainPlayerCamera.isCameraTypeFree () && isPlayerMovingOn3dWorld) { newRay = mainPlayerCamera.getCameraRaycastDirection (); raycastDirection = newRay.direction; raycastOrigin = newRay.origin; } } } currentTargetPosition = targetPositionTransform.position; float currentRaycastDistance = maxRaycastDistance; if (useInfiniteRaycastDistance) { currentRaycastDistance = Mathf.Infinity; } if (Physics.Raycast (raycastOrigin, raycastDirection, out hit, currentRaycastDistance, layerToCheckThrowObject)) { currentTargetPosition = hit.point; if (hit.collider == playerCollider) { Vector3 newRaycastPosition = hit.point + raycastDirection * 0.2f; if (Physics.Raycast (newRaycastPosition, raycastDirection, out hit, currentRaycastDistance, layerToCheckThrowObject)) { currentTargetPosition = hit.point; } } } else { if (useMaxDistanceWhenNoSurfaceFound) { currentTargetPosition = raycastOrigin + raycastDirection * maxDistanceWhenNoSurfaceFound; } else { if (Physics.Raycast (targetPositionTransform.position, raycastDirection, out hit, Mathf.Infinity, layerToCheckThrowObject)) { currentTargetPosition = hit.point; if (hit.collider == playerCollider) { Vector3 newRaycastPosition = hit.point + raycastDirection * 0.2f; if (Physics.Raycast (newRaycastPosition, raycastDirection, out hit, Mathf.Infinity, layerToCheckThrowObject)) { currentTargetPosition = hit.point; } } } } } if (showGizmo) { Debug.DrawLine (raycastOrigin, currentTargetPosition, Color.black, 5); } } public void throwObject () { if (throwPosition == null) { throwPosition = transform; } if (currentObjectToThrow == null) { instantiateObject (); } if (throwInCustomTransformDirection) { currentThrowSpeed = customTransformDirection.forward * customThrowDirectionAmount; } else { currentThrowSpeed = getParableSpeed (currentObjectToThrow.transform.position, currentTargetPosition); } if (showGizmo) { Debug.DrawLine (currentObjectToThrow.transform.position, currentTargetPosition, Color.black, 5); } if (rotateObjectTowardThrowDirection) { currentObjectToThrow.transform.LookAt (currentTargetPosition); } currentObjectToThrow.transform.SetParent (null); if (currentThrowSpeed == -Vector3.one) { currentThrowSpeed = currentObjectToThrow.transform.forward * 100; } if (newObjectToThrowRigidbody != null) { newObjectToThrowRigidbody.isKinematic = false; newObjectToThrowRigidbody.AddForce (currentThrowSpeed, ForceMode.VelocityChange); } if (addLaunchObjectComponent) { launchedObjects currentLaunchedObjects = currentObjectToThrow.GetComponent (); if (currentLaunchedObjects == null) { currentLaunchedObjects = currentObjectToThrow.AddComponent (); } currentLaunchedObjects.setCurrentPlayer (playerControllerGameObject); } if (addGrabbedObjectStateComponent) { applyDamage.checkGravityRoomForGrabbedObject (currentObjectToThrow, playerControllerGameObject); } currentObjectToThrow = null; } //calculate the speed applied to the launched projectile to make a parable according to a hit point Vector3 getParableSpeed (Vector3 origin, Vector3 target) { //get the distance between positions Vector3 toTarget = target - origin; Vector3 toTargetXZ = toTarget; //remove the Y axis value toTargetXZ -= playerCameraGameObject.transform.InverseTransformDirection (toTargetXZ).y * playerCameraGameObject.transform.up; float y = playerCameraGameObject.transform.InverseTransformDirection (toTarget).y; float xz = toTargetXZ.magnitude; //get the velocity accoring to distance ang gravity float t = GKC_Utils.distance (origin, target) / 20; float v0y = y / t + 0.5f * Physics.gravity.magnitude * t; float v0xz = xz / t; //create result vector for calculated starting speeds Vector3 result = toTargetXZ.normalized; //get direction of xz but with magnitude 1 result *= v0xz; // set magnitude of xz to v0xz (starting speed in xz plane), setting the local Y value result -= playerCameraGameObject.transform.InverseTransformDirection (result).y * playerCameraGameObject.transform.up; result += playerCameraGameObject.transform.up * v0y; return result; } public void inputThrowObject () { if (throwObjectEnabled) { throwObject (); } } public void inputInstantiateObject () { if (throwObjectEnabled) { instantiateObject (); } } public void inputCalculateThrowDirection () { if (throwObjectEnabled) { calculateThrowDirection (); } } }