Unity 提供了一个完备且强大物理引擎。但在刚接触的时候,你可能会对它与现实物理规律对应有一些疑惑。
比如:
- 现实中 1N 的力在 Unity 中怎么表现?
- Unity 中物体的质量是计算的?
- Unity 中给物体添加力的方法是 rb.AddForce(),但却又提供了4种力的模式,为什么呢?
本文章,我们就来探讨一下以上的问题。
在 Unity 中,rb.AddForce()
是给物体添加一个力的方法,传参是向量对象,向量的 x ,y,z 代表这方向,值代表力的大小。
这里可能会让人疑惑,这里力的单位是什么呢?是否对应现在中的力的单位 N ?
要验证这个点,最好的办法就算找一个物理学中常量,看这个常量在 Unity 中是多少。
毫无疑问,重力就是我们心中的那个常量。
在现实中,重力约等于 9.81N。
在Unity 中,我们可以在设置里看到重力的默认值,在Y轴方向的大小也是9.81。
所以,我们可以认为,传参向量值的单位等于现实中的 N。
我们可以验证一下。
在一个只有重力的场景,我们添加一个9.81的相对于重力反方向的力,物体时静止的。
代码实现
public class TestGravity : MonoBehaviour
{
private Rigidbody2D _rigidbody2D;
[Header("向上的力")]
[SerializeField]
private float _force;
void Start()
{
_rigidbody2D = transform.GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
_rigidbody2D.AddForce(new Vector3(0, _force, 0));
}
}
运行一下。
一开始,赋予一个9.81N向上的力时,人物时静止的。当逐渐增加力后,人物向上移动了。
在物理学中,涉及到力的计算肯定离不开物体的质量。
在 Unity 中,我们可以认为单位是kg,因为这有助于我们计算。其实这个单位并不太重要,它在 Unity 引擎中的作用只是用于描述两个物体之间相对差异,比如两个物体质量分别是 10 和 100,可以确定的是 100 质量的物体是 10 质量物体的 10 倍重。
举个例子。
从上面公式中得知,同一个力的大小作用在不同物体上,因为质量不同,物体移动的加速度就会不一样。
因此,在游戏里,我们不需要知道质量的单位是多少,只需要维护好每个对象的质量相对值就可以了。
当游戏体量上来后,去维护他们的质量数值也比较麻烦。所以在 2D 模式下,Unity 提供了一个功能,自动计算质量。
当选择启用自动质量后,Unity 会根据 物体的密度和面积自己计算质量。
举个例子。
我们使用相同的力和相同的密度,只改变物体的面积。
效果如下:
从上文我们了解到改变力的大小和质量,从而控制物体的速度。
但是公式 F=ma
中,a 只是加速度,不够直观反馈物体的速度。
我们变换一下公式,
F= ma = m v/t, Ft = m v (t 为时间,v 为速度)
。
这样我们就可以很直观的得到速度 v 的大小,但也引入多了一个数值-时间。
时间 t 在 Unity 中应该怎么表示呢?
我们知道,为了保证物理模拟正常运行都会把逻辑写在 FixedUpdate 方法里。因此时间 t 就等于固定频率,默认为0.02s。
这样力,质量,时间都知道怎么表示了,我们可以快速算出物体的速度。
但且慢,为了改变物体的速度,我需要控制3个变量,那也太麻烦了把。
Unity 为此提供4种模式,目的就是为了减少开发者需要关心这么多的变量。
看起来很棒,但却又多了一对概念-连续力和瞬时力。无语~
什么是连续力,什么是瞬时力呢?
在我看来,他们之间没有区别。因为给物体添加力,都是在当前帧里完成的,与下一帧无关,根本不存在连续添加力的情况。
那这里的连续力是什么意思呢?
其实是将力的大小乘以每一固定帧的时间间隔 ,F * 0.02s = 当前帧的力大小。
相比于瞬时力,瞬时力是没有乘以时间的 ,相当于 F * 1 = 当前帧的力大小。
为了更好说明问题,我们演示一下。
代码如下:
Force 模式下的代码
public class AddForce_Default : MonoBehaviour
{
// 赋予2的力
public float force = 2;
private Rigidbody2D _rigidbody2D;
// 移动方向
private Vector3 dir = Vector3.right;
void Start()
{
_rigidbody2D = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
_rigidbody2D.AddForce(Vector2.right * force,ForceMode2D.Force);
}
}
Impulse 模式下的代码
public class AddForce_Impulse : MonoBehaviour
{
// 赋予2的力
public float force = 2;
private Rigidbody2D _rigidbody2D;
// 移动方向
private Vector3 dir = Vector3.right;
void Start()
{
_rigidbody2D = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
_rigidbody2D.AddForce(Vector2.right * force,ForceMode2D.Impulse);
}
}
运行效果:
可以看到在 Force 模式下,角色移动明显慢得多。
那是因为每一固定帧下,Force 模式下只赋予角色 2*0.02 的力,而 Impulse 模式下,赋予角色 2 的力。
为了验证这一点,我们可以将 Impulse 模式下的力改为0.04。
运行效果:
Acceleration 模式和 VelocityChange 模式
在 3D 模式下 ,还会额外多两个模式。在这两个力模式下,都会忽略物体的质量,默认为1。
所以我们只控制力的大小,就可以控制速度大小了。
求点赞,求关注。