using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Parabola : MonoBehaviour
{
[Range(0.01f, 10.0f)]
public float Gravity = 9.8f;
public float VerticalVelocity = 10;
public Vector3 TargetPos = Vector3.zero;
protected Vector3 mLaunchPosition = Vector3.zero;
protected bool mIsLaunching = false;
protected ED_Void_Go mOnArrived = null;
protected float mElapseTime = 0;
protected float mLaunchTime = 0;
void Start ()
{
mLaunchPosition = transform.position;
mIsLaunching = false;
SuperStart();
}
void Update ()
{
if (mIsLaunching)
{
mElapseTime += Time.deltaTime;
float t;
float xv, zv;
t = Mathf.Clamp(mElapseTime, 0, mLaunchTime);
xv = (TargetPos.x - mLaunchPosition.x) / mLaunchTime;
zv = (TargetPos.z - mLaunchPosition.z) / mLaunchTime;
transform.position = mLaunchPosition + new Vector3(xv * t, VerticalVelocity * t - 0.5f * t * t * Gravity, zv * t);
if (mElapseTime >= mLaunchTime)
{
mIsLaunching = false;
if (mOnArrived != null)
mOnArrived(gameObject);
}
}
OnUpdate();
}
#if UNITY_EDITOR
void OnDrawGizmosSelected()
{
if (mIsLaunching == false)
{
mLaunchPosition = transform.position;
}
Gizmos.color = Color.red;
Gizmos.DrawSphere(TargetPos, 0.3f);
float t;
float tstep;
t = CalcVerticalVelocityAndTime();
int num = 10;
float xv, zv;
xv = (TargetPos.x - mLaunchPosition.x) / t;
zv = (TargetPos.z - mLaunchPosition.z) / t;
tstep = t / (float)(num);
for (int i = 0; i <= num; ++i)
{
t = tstep * (float)i;
Vector3 pos1, pos2;
pos1 = mLaunchPosition + new Vector3(xv * t, VerticalVelocity * t - 0.5f * t * t * Gravity, zv * t);
t = tstep * (float)(i + 1);
pos2 = mLaunchPosition + new Vector3(xv * t, VerticalVelocity * t - 0.5f * t * t * Gravity, zv * t);
Gizmos.color = Color.green;
Gizmos.DrawSphere(pos1, 0.2f);
if (i < num)
{
Gizmos.color = mIsLaunching ? Color.gray : Color.white;
Gizmos.DrawLine(pos1, pos2);
}
}
}
#endif
//return time.
float CalcVerticalVelocityAndTime()
{
float dis;
dis = TargetPos.y - mLaunchPosition.y;
if (dis >= 0)
{
// min v
// s = vt - 0.5 * gt^2
// t = v/g
// s = (v^2/2*g)
// v^2 = 2*g*s;
float minv;
minv = Mathf.Sqrt(Gravity * dis * 2.0f);
VerticalVelocity = Mathf.Clamp(VerticalVelocity, Mathf.Max(minv, 0.1f), float.MaxValue);
}
float t;
t = 0;
if (VerticalVelocity > 0)
{
float d;
t = VerticalVelocity / Gravity;
d = VerticalVelocity * t - 0.5f * Gravity *t*t;
if (dis > 0 && Mathf.Abs(dis - d) < 0.01f)
{
return t;
}
else
{
// s = 0.5 * gt^2
// t = sqrt(2s/g)
dis = d - dis;
t += Mathf.Sqrt(2.0f * dis / Gravity);
return t;
}
}
else
{
// vt - 0.5*gt^2 = s
float v_g;
v_g = (VerticalVelocity/Gravity);
t = Mathf.Sqrt(v_g * v_g - (2.0f * dis / Gravity)) + v_g;
return t;
}
}
public float Launch(ED_Void_Go callback, Vector3 targetPos, float verticalVelocity = 1.0f, float gravity = 9.8f)
{
TargetPos = targetPos;
VerticalVelocity = verticalVelocity;
Gravity = gravity;
mLaunchPosition = transform.position;
mOnArrived = callback;
mIsLaunching = true;
mElapseTime = 0;
mLaunchTime = CalcVerticalVelocityAndTime();
return mLaunchTime;
}
}