|
|
@@ -0,0 +1,86 @@ |
|
|
using UnityEngine; |
|
|
using System.Collections; |
|
|
|
|
|
public class TrajectoryCalculation : MonoBehaviour |
|
|
{ |
|
|
public Rigidbody projectile; |
|
|
public Transform target; |
|
|
[Header("CalculateBestThrowSpeed")] |
|
|
public float timeToTarget = 1f; |
|
|
[Header("CalculateTrajectory")] |
|
|
public float speed = 10; |
|
|
[Range(0, 1)] public float arc = 0; |
|
|
|
|
|
|
|
|
void Update() |
|
|
{ |
|
|
if (Input.GetKeyDown("a")) |
|
|
{ |
|
|
GameObject p = Instantiate(projectile, transform.position, transform.rotation) as GameObject; |
|
|
p.GetComponent<Rigidbody>().AddForce(CalculateBestThrowSpeed(transform.position, target.position, timeToTarget), ForceMode.VelocityChange); |
|
|
Destroy(p, 10); |
|
|
} |
|
|
|
|
|
if (Input.GetKeyDown("b")) |
|
|
{ |
|
|
Vector3 velocity; |
|
|
if (CalculateTrajectory(transform.position, target.position, speed, out velocity, arc)) |
|
|
{ |
|
|
GameObject p = Instantiate(projectile, transform.position, transform.rotation) as GameObject; |
|
|
p.GetComponent<Rigidbody>().AddForce(velocity, ForceMode.VelocityChange); |
|
|
Destroy(p, 10); |
|
|
} |
|
|
else |
|
|
{ |
|
|
Debug.Log("Target cannot be reached. Increase speed or reduce distance."); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// from http://answers.unity3d.com/answers/456066/view.html |
|
|
static Vector3 CalculateBestThrowSpeed(Vector3 origin, Vector3 target, float timeToTarget) |
|
|
{ |
|
|
Vector3 toTarget = target - origin; |
|
|
Vector3 toTargetXZ = toTarget; |
|
|
toTargetXZ.y = 0; |
|
|
float y = toTarget.y; |
|
|
float xz = toTargetXZ.magnitude; |
|
|
float v0y = y / timeToTarget + 0.5f * Physics.gravity.magnitude * timeToTarget; |
|
|
float v0xz = xz / timeToTarget; |
|
|
Vector3 result = toTargetXZ.normalized; |
|
|
result *= v0xz; |
|
|
result.y = v0y; |
|
|
return result; |
|
|
} |
|
|
|
|
|
|
|
|
// based on http://gamedev.stackexchange.com/questions/114522/how-can-i-launch-a-gameobject-at-a-target-if-i-am-given-everything-except-for-it/114547 |
|
|
static bool CalculateTrajectory(Vector3 origin, Vector3 target, float speed, out Vector3 velocity, float arc = 0f) |
|
|
{ |
|
|
Vector3 toTarget = target - origin; |
|
|
Vector3 toTargetXZ = toTarget; |
|
|
toTargetXZ.y = 0; |
|
|
float y = toTarget.y; |
|
|
float xz = toTargetXZ.magnitude; |
|
|
float gravity = Physics.gravity.magnitude; |
|
|
float b = speed*speed - y * gravity; |
|
|
float discriminant = b * b - gravity * gravity * (xz * xz + y * y); |
|
|
if (discriminant < 0) // out of range, need higher shot speed |
|
|
{ |
|
|
velocity = Vector3.zero; |
|
|
return false; |
|
|
} |
|
|
float discRoot = Mathf.Sqrt(discriminant); |
|
|
float minTime = Mathf.Sqrt((b - discRoot) * 2) / Mathf.Abs(gravity); // impact time for the most direct shot that hits |
|
|
float maxTime = Mathf.Sqrt((b + discRoot) * 2) / Mathf.Abs(gravity); // impact time for the highest shot that hits |
|
|
float time = (maxTime - minTime) * arc + minTime; |
|
|
float v0xz = xz / time; |
|
|
float v0y = y / time + time * gravity / 2; |
|
|
velocity = toTargetXZ.normalized; |
|
|
velocity *= v0xz; |
|
|
velocity.y = v0y; |
|
|
return true; |
|
|
} |
|
|
|
|
|
} |