一、理解抛物线
- 抛射物是在上抛过程中受到唯一重力影响。举一个抛射物的例子,一颗从加农炮中射出的炮弹;一块被扔到空中的石头;或者一个从桌边掉落的小球;这些物体走过的曲线路径称之为运动轨迹。当空气阻力被忽略时,其运动的路径是抛物线形状。
二、抛物运动的分类
许多类型的抛物运动不仅遵循垂直运动,也遵循水平运动。也就是说,抛物运动在水平方向移动的同时,也在做垂直方向的运动。表明抛物运动包含水平和垂直两方向的运动。
在垂直运动过程中,重力作用于物体,并给与物体一个反方向的加速度“-9.8m/s²"(地球的重力加速度)。这就意味着物体的速度在单位时间内降低”-9.8m/s²“。自由落地的速度为:
V y = g t V_y=gt Vy=gt
如果物体具有初速度,那么下落物体的速度方程为(g的值为-9.8m/s²):
V y = V 0 + g t ; V_y=V_0+gt; Vy=V0+gt;
自由落体的距离公式为:
S = 1 / 2 ∗ g ∗ t 2 S=1/2*g*t^2 S=1/2∗g∗t2
基于物体具有初速度的情况,物体的位移公式为:
S v = V 0 t − 1 / 2 ∗ g ∗ t 2 S_v=V_0t-1/2*g*t^2 Sv=V0t−1/2∗g∗t2
此为物体的上抛运动,重力方向向下。
在水平运动过程中,运动将是恒定的,因为没有力作用于物体(忽略空气阻力)。因此,速度在水平方向的分量是恒定的,其加速度为0,则水平方向的位移公式为:
S h = V 0 ∗ t S_h=V_0*t Sh=V0∗t
三、具体实现
下方的C#代码将展示当加农炮发射炮弹时,炮弹的运动轨迹。
添加下面的脚本到一个加农炮对象上。为炮弹和轨迹点制作预制件(prefab),它们将会在运行时被实例化,炮弹必须具有Collider组件和Rigidbody组件
截图:

/// <summary>
/// 设置弹道点的位置
/// </summary>
/// <param name="startPos">炮弹的起始坐标</param>
/// <param name="pVelocity">炮弹在对应时间点的速度</param>
public void SetTrajectPointPos(Vector3 startPos,Vector3 pVelocity){
float velocity=Mathf.Sqrt((pVelocity.x*pVelocity.x)+(pVelocity.y*pVelocity.y));
float angle=Mathf.Atan2(pVelocity.y,pVelocity.x)*Mathf.Rad2Deg;
float stepTime=0;
stepTime+=0.1f;
for (int i = 0; i < trajectPointsList.Count; i++)
{
float dx=velocity*stepTime*Mathf.Cos(angle*Mathf.Deg2Rad);
float dy=velocity*stepTime*Mathf.Sin(angle*Mathf.Deg2Rad)-
(Physics.gravity.magnitude*stepTime*stepTime/2);
Vector3 pos=new Vector3(startPos.x+dx,startPos.y+dy,2);
trajectPointsList[i].transform.position=pos;
trajectPointsList[i].GetComponent<SpriteRenderer>().enabled=true;
trajectPointsList[i].transform.eulerAngles=
new Vector3(0,0,
Mathf.Atan2(pVelocity.y - (Physics.gravity.magnitude)*stepTime,pVelocity.x)*
Mathf.Rad2Deg);
stepTime+=0.1f;
}
}
void Update () {
if (isFalling) return;
if (Input.GetMouseButtonDown (0)) {
isPressed = true;
if (currentBulletObj == null) {
currentBulletObj = CreateBullet (cannonTrans.position);
}
} else if (Input.GetMouseButtonUp (0)) {
if (currentBulletObj == null) return;
isPressed = false;
if (isFalling == false) {
FireBullet (CalculationFireForce (currentBulletObj.transform.position,
Camera.main.ScreenToWorldPoint (Input.mousePosition)));
}
}
if (isPressed) {
Vector3 direction = CalculationFireForce (currentBulletObj.transform.position,
Camera.main.ScreenToWorldPoint (Input.mousePosition));
float angle = Mathf.Atan2 (direction.y, direction.x) * Mathf.Rad2Deg;
cannonTrans.eulerAngles = new Vector3 (0, 0, angle);
parabolaController.SetTrajectPointPos (cannonTrans.position,
direction / currentBulletObj.GetComponent<Rigidbody> ().mass);
}
}
/// <summary>
/// 计算发射时,鼠标按下位置到炮弹初始位置的向量(方向)
/// </summary>
/// <param name="fromPos">炮弹的位置</param>
/// <param name="toPos">鼠标按下时的位置</param>
/// <returns></returns>
private Vector2 CalculationFireForce (Vector3 fromPos, Vector3 toPos) {
return (new Vector2 (toPos.x, toPos.y) -
new Vector2 (fromPos.x, fromPos.y)) * firePower;
}
自此,实现的大致思路就是这样,具体大家可以在公众号里下载Demo研究下。
翻译自: http://www.theappguruz.com/blog/display-projectile-trajectory-path-in-unity
- 代码做了一些修改。运行环境Unity 2017-4.10
扫码关注->历史消息->当前文章->末尾->Demo地址:
