处理播放器对象时,什么时候应该使用力度而不是addForce?


18

我对Unity框架中的这两种方法感到困惑。两者都会使播放器对象移动,停止,改变方向等。何时应该在另一个之上使用一个,何时合适?



@ Byte56这两个问题都在询问不同的问题
罗伯特·罗伯特(Robert Robert),

1
不同,但相关。这就是为什么它们只是链接而不是重复的原因。显示它显示在右侧的链接列中。
MichaelHouse

Answers:


13

velocity通常会以恒定的速度移动物体(例如,子弹)并AddForce()增加运动(例如,太空飞船的推进器)。还请注意,运动有两种“类型”。力量和冲动。对于宇宙飞船推进器,您会使用脉冲。


4
您能描述一下为什么您更喜欢使用宇宙飞船推进器吗?如果您要随着时间推移逐渐施加加速度,而不是由于武器撞击等导致的动量瞬时变化,那么这实际上可能是不理想的选择。在一个时间窗口上应用时,通常会需要力(如果不想让质量成为一个因素,则需要加速度),而瞬时则使用脉冲(或相应地使用VelocityChange)
DMGregory

@DMGregory是的,这取决于您要添加的力量类型。在我的飞船推进器示例中,这是一瞬间的能量爆发,然后冲动是正确的选择。
trojanfoe 2015年

2
目前尚不清楚您是要短时发射姿态喷气式飞机还是连续燃烧主机(有时在科幻小说中通常使用“推力器”),所以我想澄清一下,以免有人尝试使用脉冲作为火箭助推器。;)
DMGregory

@DMGregory确实;我的太空技术术语主要基于电影:)
trojanfoe 2015年

@trojanfoe去玩KSP。就像,现在。
user253751

21

尽管已经有一个可接受的答案,但我认为还有一些其他细节值得介绍。

使用速度

设置速度时,您将完全覆盖可能影响该对象运动的所有其他因素。在某些情况下,这是合乎需要的,例如,在发射子弹时立即设置一次子弹的初始速度,例如trojanfoe的示例。请小心,因为在错误的情况下使用它可能会引起问题:

  • 如果多个源/脚本试图通过直接设置相同的刚体速度来修改它(即 body.velocity = foo),则最后一个运行获胜,而另一个则无效。这可能会导致更新错误的顺序,特别是导致实体悬停或缓慢掉落(因为重力导致的向下加速度在累积之前就被覆盖了)

  • 如果您要设置每帧的速度,则与其他对象的碰撞可能会有些奇怪。就像您的物体被无限扭矩的发动机推动一样-不管物体在撞击中损失多少速度,在接下来的物理步骤中它都会恢复到最高速度,并且其速度不会偏离撞击。这可能会导致发射与您碰撞的对象,或者使小对象比看起来应该容易地推动大对象,或者使对象沿着静态障碍物缓慢滑动而不是偏离它们。

有时可能会同时需要这两种效果。例如,当我制作Kinect游戏并希望玩家的虚拟化身的肢体能够与物理场景进行交互时,我通常使用直接速度设置来移动这些身体。因为玩家的实际手在已知位置并且没有因与该虚拟对象碰撞而减速,所以他们的虚拟手需要做同样的事情以保持对齐,因此在这种情况下,我们实际上想要覆盖所有其他物理效果以到达那里。

AddForce和朋友

加力相比之下,和类似的辅助函数可以与物理世界中发生的所有其他事情进行协作。如果将多个源/脚本AddForce添加到一个刚体,则所有这些效果都将加在一起以在对象的运动中产生净变化(取决于运动的计算方式,该变化也可能与顺序无关)。这有助于避免一个脚本完全踩踏其他物理效果。

通过指定可选的ForceMode参数,AddForce有四种形式,它们可用于不同的事情:

ForceMode       |   Use
-----------------------------------------------------------------------
Force (default) |   Accelerate an object over 1 time step, based on its mass.
                |   Units: Newtons = kg * m/s^2
                |
Acceleration    |   Accelerate an object over 1 time step, ignoring its mass. (like gravity)
                |   Units: m/s^2
                |
Impulse         |   Instantaneously propel an object, based on its mass
                |   Units: N * s = kg * m/s
                |
VelocityChange  |   Instantaneously propel an object, ignoring its mass
                |   (like body.velocity = foo, except multiple scripts can stack)
                |   Units:  m/s

如果您想模拟一段时间内的连续推动(例如,您正在应用每个FixedUpdate的东西),例如汽车行驶,火箭燃烧或重力井拉力,则需要“力”或“加速度”。(取决于您是否想让重物加速得更慢)

如果您要模拟运动的突然急剧变化,例如发射子弹,爆炸后弹或从障碍物弹起,那么您更可能需要Impulse或VelocityChange。

使用AddForce可以帮助您获得更多的物理真实感,但是它还可能需要您花费更多的时间来思考行为的物理原理。例如,如果您希望身体在达到目标速度之前具有有限的加速度,以使其对碰撞的反应比在每一帧中设置速度更真实,那么您可能希望进行类似于此辅助函数的计算:

public static void AccelerateTo(this Rigidbody body, Vector3 targetVelocity, float maxAccel)
{
    Vector3 deltaV = targetVelocity - body.velocity;
    Vector3 accel = deltaV/Time.deltaTime;

    if(accel.sqrMagnitude > maxAccel * maxAccel)
        accel = accel.normalized * maxAccel;

    body.AddForce(accel, ForceMode.Acceleration);
}

我之所以将所有这些“帮助函数”称为“原因”,是因为从技术上讲,您可以通过以下方式实现所有相同的目的:

 body.velocity += suitablyCalculatedDeltaV;

我认为。基于Unity的PhysX / Box2D的物理求解器有可能通过AddForce分别缓冲更改,但是我没有看到明显的后果)

因此,归根结底,这些功能真正为我们带来的是意图的明确化。当我想施加渐进力时,我不需要记住将我的deltaV乘以Time.deltaTime并除以质量,我只是说我想要ForceMode.Force,它以正确且一致的方式处理。当我或其他人稍后对我的代码进行迭代时,可以立即明白我的意思,而无需解码时间和质量计算就可以了。


6

除了trojanfoe的答案,《愤怒的小鸟vs赛车》。这些方法(两个主要的和不同的例子AddForce,并velocity分别)。例如,在《愤怒的小鸟》中,使用速度要困难得多,因为您必须自己设置弹丸的轨迹,例如,

当我在《愤怒的小鸟》中使用AddForce时,我会使用,

_birdRigidbody.AddForce(new Vector2(5,5));

当我使用速度时,我会使用

x = v*t*Cos(theta) y = v*t*Sin(theta) - 0.5 * g * t *t

或类似的东西。

在赛车游戏中,您必须始终控制速度,这与《愤怒的小鸟》(即《射击》等)不一样。因此,在这种情况下,handle velocity比有用AddForce

希望你能理解。至少一点点。


1
当释放弹弓时,您的AngryBirds示例可能应该使用动量的瞬时变化(例如Impulse或VelocityChange),而不是使用默认的ForceMode.Force来模拟其在时间范围内的效果,而不是使用默认的ForceMode.Force。您可以调整数字以从两种方法中获得相同的行为,但是如果更改固定时间步长,则力解将具有不同的输出(因为它是在更长或更短的时间间隔内对力进行积分),而脉冲仍保持一致理想的,因为它仅表示发布的时刻。
DMGregory

0

刚体速度和刚体Addforce是Unity 3D中的两个令人困惑的功能,并且初学者常常无法理解它们之间的区别。在本文中,我们将讨论RigidBody.velocity和RigidBody.addforce之间的区别。

在这两种情况下,无论是Addforce还是速度函数,我们都将使用术语力来解释它们。

当我们使用Rigidbody.velocity时,在那种情况下,我们正在向对象添加力,但是除非并且直到我们继续施加力,否则该力只会移动对象。

例如

body.velocity = new Vector3(0,0,5);

假设您在z位置添加了5f,当您按下W键时将添加该力。因此,当您按W键时,对象将立即以5的速度启动。这就像您在汽车上使用此功能施加力时一样,该汽车将以5的速度启动。

body.velocity = new Vector3(0,0,200);

如果您说将值更改为200,然后在保存后按W键。汽车将从启动时以200的速度开始运行,这在现实世界中是不可能的。

现在,如果您谈论Rigidbody.addforce

通过继续我们的汽车示例。如果将200的力加到汽车上

body.addforce(0,0,200);

如果我们按W键,小车将不会以200的速度开始移动,但是它会从慢速开始,然后根据阻力值增加速度并停止。

Rigidbody.addforce开始缓慢,然后加速,就像您拖动沉重的桌子一样,首先您将开始推动该桌子,该桌子会从其位置稍微移动一点,但是如果您继续推动该桌子,它将开始移动&如果您离开那张桌子,它会覆盖一定的距离,具体取决于表面,并且刚体.addforce也一样。

您可以使用Rigidbody.velocity,您只想移动对象即可像玩家跳跃那样立即做出反应,并且该力的结果会在跳跃后消失,您可以使用Rigidbody.addforce,在您需要缓慢启动然后进行连续运动的情况下一枚火箭。如果在jump中使用Rigidbody.addforce,则Player / Object将在空间中停留一段时间,然后返回地面。

(资源)


您至少应该尝试使您的帖子适应Stack Exchange答案的格式:)
Vaillancourt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.