实现游戏中抛体运动的方案

在游戏中经常要用到类似箭矢一样的抛物线运动的效果,在最近的一个项目中就有这样一个需求。此前在之前项目中有用到过这种效果,在此做一个总结。

方案

我们项目的需求是在没有物理引擎的情况下模拟抛体运动,故此次介绍的是一个通用的方案。
项目中的需求是已知起点终点,模拟从起点射到终点的抛物线。在此情况下,初速度,初始角度都能影响终点位置。
现在介绍的是基于初始速度的方案。

步骤

img

  • 1,确定top的位置,只需要确定Y坐标即可,一般的做法是,从StartTarget两个点中选取一个较高的点加上一定距离,Top点的X值不需要确定。
  • 2,根据top的位置可以确定下落的距离和上升的距离,即图中的h_uph_down。根据h_down和公式 h = 0.5 * gt^2^ 推算出下落的时间 tdown
  • 3,h_up算出上升时间 tup,根据tup和公式v0 = -gt 推算出初速度V0;
  • 4,此时我们已经确定了初始上升速度V0,总时间 t = tup + tdown,水平速度 = (target.x - start.x) / 总时间t

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Start()
{
float topY = m_startPos.y > endPos.y ? m_startPos.y + 100 : endPos.y + 100; //选一个最高点
float h_down = topY - endPos.y; //下落距离
float t_down = Mathf.Sqrt(h_down * 2 / G); //下落时间
float h_up = topY - m_startPos.y;//上升距离
float t_up = Mathf.Sqrt(h_up * 2 / G);//上升时间
V0 = G * t_up;//上升初速度
float curDisX = endPos.x - m_startPos.x;//水平距离
m_speedX = Mathf.Abs(curDisX / (t_up + t_down));//水平速度
}
void Update()
{
float speedY = (float)V0;
float speedX = m_dir * m_speedX ;
transform.localPosition = new Vector3(transform.localPosition.x + speedX, transform.localPosition.y + speedY, 0);
V0 -= G;
//刷新物体角度
float angle = Mathf.Atan2(speedY, speedX);
transform.localEulerAngles = new Vector3(0, 0, angle * 180 / Mathf.PI);
}

效果

在这里插入图片描述