Skip to content

Instantly share code, notes, and snippets.

@Mesidin
Forked from brettmjohnson/TrajectoryCalculation.cs
Created October 15, 2016 04:54
Show Gist options
  • Save Mesidin/cdd139bd913a6b6b7918c589fba8b9e2 to your computer and use it in GitHub Desktop.
Save Mesidin/cdd139bd913a6b6b7918c589fba8b9e2 to your computer and use it in GitHub Desktop.

Revisions

  1. @brettmjohnson brettmjohnson created this gist Jul 10, 2016.
    86 changes: 86 additions & 0 deletions TrajectoryCalculation.cs
    Original file line number Diff line number Diff line change
    @@ -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;
    }

    }