【Unity300个技巧】牛顿的学问!如何优雅地使用力?

Unity 提供了一个完备且强大物理引擎。但在刚接触的时候,你可能会对它与现实物理规律对应有一些疑惑。
比如:

  • 现实中 1N 的力在 Unity 中怎么表现?
  • Unity 中物体的质量是计算的?
  • Unity 中给物体添加力的方法是 rb.AddForce(),但却又提供了4种力的模式,为什么呢?

本文章,我们就来探讨一下以上的问题。

额外资源

Unity 中力的单位

在 Unity 中,rb.AddForce()是给物体添加一个力的方法,传参是向量对象,向量的 x ,y,z 代表这方向,值代表力的大小。
image.png
这里可能会让人疑惑,这里力的单位是什么呢?是否对应现在中的力的单位 N ?
要验证这个点,最好的办法就算找一个物理学中常量,看这个常量在 Unity 中是多少。
毫无疑问,重力就是我们心中的那个常量。
在现实中,重力约等于 9.81N。
在Unity 中,我们可以在设置里看到重力的默认值,在Y轴方向的大小也是9.81。
image.png
所以,我们可以认为,传参向量值的单位等于现实中的 N。
我们可以验证一下。
在一个只有重力的场景,我们添加一个9.81的相对于重力反方向的力,物体时静止的。
image.png
代码实现

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 中物体的质量

在物理学中,涉及到力的计算肯定离不开物体的质量。
在 Unity 中,我们可以认为单位是kg,因为这有助于我们计算。其实这个单位并不太重要,它在 Unity 引擎中的作用只是用于描述两个物体之间相对差异,比如两个物体质量分别是 10 和 100,可以确定的是 100 质量的物体是 10 质量物体的 10 倍重。
images.png
举个例子。
从上面公式中得知,同一个力的大小作用在不同物体上,因为质量不同,物体移动的加速度就会不一样。
质量不同.gif
因此,在游戏里,我们不需要知道质量的单位是多少,只需要维护好每个对象的质量相对值就可以了。
当游戏体量上来后,去维护他们的质量数值也比较麻烦。所以在 2D 模式下,Unity 提供了一个功能,自动计算质量。
image.png
当选择启用自动质量后,Unity 会根据 物体的密度和面积自己计算质量。
image.png

自动计算质量.gif

举个例子。
我们使用相同的力和相同的密度,只改变物体的面积。
效果如下:
自动质量,.gif

力的模式

从上文我们了解到改变力的大小和质量,从而控制物体的速度。
但是公式 F=ma中,a 只是加速度,不够直观反馈物体的速度。
我们变换一下公式,
F= ma = m v/t, Ft = m v (t 为时间,v 为速度)

这样我们就可以很直观的得到速度 v 的大小,但也引入多了一个数值-时间。

时间 t 在 Unity 中应该怎么表示呢?
我们知道,为了保证物理模拟正常运行都会把逻辑写在 FixedUpdate 方法里。因此时间 t 就等于固定频率,默认为0.02s。
这样力,质量,时间都知道怎么表示了,我们可以快速算出物体的速度。

但且慢,为了改变物体的速度,我需要控制3个变量,那也太麻烦了把。
Unity 为此提供4种模式,目的就是为了减少开发者需要关心这么多的变量。

image.png
看起来很棒,但却又多了一对概念-连续力和瞬时力。无语~
什么是连续力,什么是瞬时力呢?
在我看来,他们之间没有区别。因为给物体添加力,都是在当前帧里完成的,与下一帧无关,根本不存在连续添加力的情况。
那这里的连续力是什么意思呢?
其实是将力的大小乘以每一固定帧的时间间隔 ,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);
    }
}

运行效果:
两种模式下,速度不同.gif
可以看到在 Force 模式下,角色移动明显慢得多。
那是因为每一固定帧下,Force 模式下只赋予角色 2*0.02 的力,而 Impulse 模式下,赋予角色 2 的力。

为了验证这一点,我们可以将 Impulse 模式下的力改为0.04。
运行效果:
两种模式下,速度相同.gif

Acceleration 模式和 VelocityChange 模式
在 3D 模式下 ,还会额外多两个模式。在这两个力模式下,都会忽略物体的质量,默认为1。
所以我们只控制力的大小,就可以控制速度大小了。
在这里插入图片描述

求点赞,求关注。

猜你喜欢

转载自blog.csdn.net/GG_and_DD/article/details/127928483