工作中,遇到了一个需求是要实现获得道具和货币的飞动效果:

  1. 根据道具的多少生成不同数目的道具
  2. 货币首先要有一个炸开的效果,然后向一个点汇集;道具从原位置沿直线飞过去
  3. balabala

这里只讨论货币飞行路线的问题。

贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。PS中的钢笔工具就是使用贝塞尔曲线来绘制矢量曲线的。

这里使用简单的,四个点确定的贝塞尔曲线来实现飞行轨迹。首先p0和p3分别是移动的起点和终点。为了模拟爆炸效果,可以通过随机选取以p0为圆心,长度为R的圆上的点,调整曲线的第一次弯折位置实现。这一点定为P1。最后,根据P1点和P0点之间的关系,进行x轴或者y轴的修正,实现曲线平滑延申到p3,这一点是p2点。

p1点(爆炸点)的获取方式:

1
2
3
4
5
private static Vector3 GetRandomPosition(Vector3 vec)
{
float sita = UnityEngine.Random.Range(-Mathf.PI, Mathf.PI);
return new Vector3(vec.x + Mathf.Cos(sita) * Screen.width / 8, vec.y + Mathf.Sin(sita) * Screen.width / 8);
}

p2点(修正点)的获取方式:

1
2
3
4
private static Vector3 GetFixedPoint(Vector3 start, Vector3 end)
{
return new Vector3(start.x + 3*(end.x - start.x)/4, start.y + 3 * (end.y - start.y) / 4 + p1.y > start.y ? Screen.height / 15 : - Screen.height / 15);
}

根据已知的四个点,实现物体延贝塞尔曲线移动的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/// <summary>
/// 延贝塞尔曲线移动
/// </summary>
private static IEnumerator MoveBezier(GComponent gcom, float time, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
for (float t = 0; t < time; t += Time.deltaTime)
{
gcom.position = CalculateCubicBezierPoint(t / time, p0, p1, p2, p3);
yield return 0;
}
gcom.position = p3;
gcom.Dispose();
}

/// <summary>
/// 计算贝塞尔曲线点的坐标
/// </summary>
private static Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;

Vector3 p = uuu * p0;
p += 3 * uu * t * p1;
p += 3 * u * tt * p2;
p += ttt * p3;

return p;
}