无论是愤怒的小鸟,还是弓箭发射功能,亦或者模拟炮弹受重力影响等抛物线轨迹,都可以使用本文的方法,模拟绝对真实。
和往常一样,先说原理。就是抛物运动,在垂直方向上做加速度运动,在水平方向上,做匀速运动。
在unity上的具体实现为,使用transform进行位移模拟。至于为何不使用刚体的物理模拟,大家自行脑补或者测试。
那么如何使用transform模拟呢?让物体同时在两个方向产生位移就行了,一个是初速度方向,一个是垂直方向。
垂直方向的速度 = a*t,a代表重力加速度,t代表已经运行的时间。
好现在我们来看看一个简单的弓箭轨迹是怎么产生的吧,上代码:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
using
UnityEngine;
using
System.Collections;
/// <summary>
/// 弓箭轨迹模拟
/// 阿亮设计,欢迎交流经验
/// </summary>
public
class
TestRay : MonoBehaviour {
public
float
Power=10;
//这个代表发射时的速度/力度等,可以通过此来模拟不同的力大小
public
float
Angle=45;
//发射的角度,这个就不用解释了吧
public
float
Gravity = -10;
//这个代表重力加速度
private
Vector3 MoveSpeed;
//初速度向量
private
Vector3 GritySpeed = Vector3.zero;
//重力的速度向量,t时为0
private
float
dTime;
//已经过去的时间
// Use this for initialization
void
Start () {
//通过一个公式计算出初速度向量
//角度*力度
MoveSpeed = Quaternion.Euler(
new
Vector3(-Angle, 0, 0)) * Vector3.forward * Power;
}
// Update is called once per frame
void
FixedUpdate () {
//计算物体的重力速度
//v = at ;
GritySpeed.y = Gravity * (dTime += Time.fixedDeltaTime);
//位移模拟轨迹
transform.Translate(MoveSpeed * Time.fixedDeltaTime);
transform.Translate(GritySpeed * Time.fixedDeltaTime);
}
}
|
怎么样够简单吧?直接把这个脚本托给一个物体,效果就有了。但是等一下,这个纯位移模拟是没错,但是物体移动时的角度变化却是没有了,根本不像弓箭呢!
要解决这个,其实也很简单呢,相信你也能写出来吧。
如何模拟阻力,我就不用解释了吧,在运行过程中,将垂直速度和初速度在水平方向上的速度分量逐渐减小(注意值范围)就行了。
好,大家晚安好梦!
鉴于很多人私下留言说搞不定角度问题,好吧,我自己挖的坑自己填好。
再说说原理,如何同步这个角度呢?三角函数的图我就不划了,估计大家也不想听那些物理或者数学公式,只需要知道,通过垂直方向和水平方向的比值就行了,然后
转化为角度赋值给对象。好了,我知道你最关心的是代码呢?代码如下:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
using
UnityEngine;
using
System.Collections;
/// <summary>
/// 弓箭轨迹模拟
/// 阿亮设计,欢迎交流经验
/// </summary>
public
class
Radar : MonoBehaviour
{
public
float
Power = 10;
//这个代表发射时的速度/力度等,可以通过此来模拟不同的力大小
public
float
Angle = 45;
//发射的角度,这个就不用解释了吧
public
float
Gravity = -10;
//这个代表重力加速度
public
bool
IsOne =
false
;
private
Vector3 MoveSpeed;
//初速度向量
private
Vector3 GritySpeed = Vector3.zero;
//重力的速度向量,t时为0
private
float
dTime;
//已经过去的时间
private
Vector3 currentAngle;
// Use this for initialization
void
Start()
{
//通过一个公式计算出初速度向量
//角度*力度
MoveSpeed = Quaternion.Euler(
new
Vector3(0, 0,Angle)) * Vector3.right * Power;
currentAngle = Vector3.zero;
}
// Update is called once per frame
void
FixedUpdate()
{
//计算物体的重力速度
//v = at ;
GritySpeed.y = Gravity * (dTime += Time.fixedDeltaTime);
//位移模拟轨迹
transform.position += (MoveSpeed + GritySpeed) * Time.fixedDeltaTime;
currentAngle.z = Mathf.Atan((MoveSpeed.y + GritySpeed.y) / MoveSpeed.x) * Mathf.Rad2Deg;
transform.eulerAngles = currentAngle;
}
}
|
注意,为什么使用FixedUpdate而不是Update,因为FixedUpdate是固定频率执行的,累加时间比较真实。另,代码的运行结果和
通过数学计算出的相差无几,大家可以自行测试。