背景
经常忘,经常查,倒不如我自己写一篇给自己方便参考,毕竟每次都在某N站查出来的都是不知道互抄到哪一年的机翻文章。
本文涉及代码与测试参考unity版本为2021.3,
AddForce
用于对rigidbody组件对象添加力的作用。
其参数决定了添加力的作用方式,因此参数不同,其获得的效果(动量、动能)也不同。
另外unity重力加速度默认为9.81左右,随着物体的状况会有改变。使用Debug.Log("Gravity: " + Physics.gravity);
查看重力加速度(重力加速度也有方向!所以也是Vector3)。
要点
你需要了解并理解以下内容
-
力是矢量,有方向,因此调用时的第一个参数是Vector3类型
-
无论选什么参数施力,力都不会自动应用于后续帧。它只会在您调用AddForce函数的那一刻应用。区别仅在于它如何计算要施加多少力,而不在于它如何施加力。 https://answers.unity.com/questions/696068/difference-between-forcemodeforceaccelerationimpul.html
-
使用 AddForce 时,不用手动使用 Time.deltaTime 或
fixedDeltaTime,其内部的物理函数会自动将时间纳入计算。
https://answers.unity.com/questions/1752181/does-addforce-with-forcemodeforce-use-timedeltatim.html -
物理相关的代码最好在fixUpdate函数而不是update内进行,因为fixupdate的时间间隔是固定的,update的时间间隔取决于帧率,且每次都不确定。
-
持续的力(fixUpdate内的持续调用)使用Force、Acceleration参数,单次的力使用Impulse参数,对速度的改变使用VelocityChange参数
ForceMode
Force(力):
通过 AddForce 函数添加力,单位为 N。如果我们在FixUpdate内持续调用AddForce(Vector3.up *100,ForceMode.Force)
,那一秒内的50次调用(默认情况下FixUpdate 0.02秒调用一次)即为对该物体产生一个向上的100N的力持续一秒。
这两行代码是一样的
rigidbody.AddForce(Vector3.forward*1.0f,ForceMode.Force);
rigidbody.velocity += Vector3.forward*1.0f * Time.fixedDeltaTime / (rigidbody.mass);
Impulse(冲量):
通过 AddForce 函数添加冲量,单位为 N /s(牛顿每秒)。冲量是一个在一瞬间产生的力,AddForce(Vector3.up *100,ForceMode.Impulse)
调用1次与AddForce(Vector3.up *100,ForceMode.Force)
调用50次(一秒)的总力一样。
这两行代码是一样的
rigidbody.AddForce(Vector3.forward*1.0f,ForceMode.Impulse);
rigidbody.velocity += Vector3.forward*1.0f / rigidbody.mass;
Acceleration(加速度):
通过 AddForce 函数添加加速度。忽略对象的质量,AddForce(Vector3.left*100,ForceMode.Acceleration)
在fixupdate内执行一秒(默认50次),即视作一秒内物体保持了一个向左的100的加速度,静止的物体会在一秒后速度变为100.
这两行代码是一样的
rigidbody.AddForce(Vector3.forward*1.0f,ForceMode.Acceleration);
rigidbody.velocity += Vector3.forward*1.0f * Time.fixedDeltaTime;
VelocityChange(变速):
通过 AddForce 函数添加的速度变化,单位为 m/s。忽略对象的质量,速度变化是一个直接改变物体速度的量,它可以在一次调用后立即影响物体的运动状态。
这两行代码是一样的
rigidbody.AddForce(Vector3.forward*1.0f,ForceMode.VelocityChange);
rigidbody.velocity += Vector3.forward*1.0f;
参考:
https://answers.unity.com/questions/802181/trying-to-understand-rigidbody-forcemode-derivatio.html?childToView=802667#answer-802667
是否与质量有关
参数 | 质量有关 |
---|---|
Force | 是 |
Impulse | 是 |
Acceleration | 否 |
VelocityChange | 否 |
为了深化理解,做点实验
VelocityChange
用一个左平抛运动的物体举例,物体在(0,0,0)生成。初速为0,有重力加速度,所以我们只用关注x轴向速度。
private void FixedUpdate()
{
rb.AddForce(Vector3.left * 10, ForceMode.VelocityChange);
//当对象y坐标小于0,摧毁该对象,并输出当前坐标
if (transform.position.y < 0)
{
Destroy(gameObject);
Debug.LogWarning("Position: " + transform.position);
}
//输出物体当前速度
Debug.Log("Velocity: " + rb.velocity);
}
每次调用使得x轴向速度增加10。相当于
rigidbody.velocity += Vector3.left*10f;
Acceleration 和Force
用一个左平抛运动的物体举例,物体在(0,0,0)生成。初速为0,有重力加速度,所以我们只用关注x轴向速度。
private void FixedUpdate()
{
rb.AddForce(Vector3.left * 10, ForceMode.Acceleration);
//当对象y坐标小于0,摧毁该对象,并输出当前坐标
if (transform.position.y < 0)
{
Destroy(gameObject);
Debug.LogWarning("Position: " + transform.position);
}
//输出物体当前速度
Debug.Log("Velocity: " + rb.velocity);
}
一次调用使得x方向速度改变0.2(即一秒调用使x方向速度变为10,与代码中Vector3.left * 10一致)
Acceleration可以理解为 ,函数内部的执行效果相当于,参数为Force的力的大小自动乘以了对象的质量,即以下俩代码效果相同
rb.AddForce(Vector3.left * 10 * rb.mass, ForceMode.Acceleration);
rb.AddForce(Vector3.left * 10, ForceMode.Force);
即当物体质量为1的时候,参数为Acceleration或Force的函数调用,使得对象获得相同的效果。验证如下
- Acceleration
private void FixedUpdate()
{
rb.AddForce(Vector3.left * 10 * rb.mass, ForceMode.Acceleration);
//当对象y坐标小于0,摧毁该对象,并输出当前坐标
if (transform.position.y < 0)
{
Destroy(gameObject);
Debug.LogWarning("Position: " + transform.position);
}
//输出物体当前速度
Debug.Log("Velocity: " + rb.velocity);
}
- Force
private void FixedUpdate()
{
rb.AddForce(Vector3.left * 10, ForceMode.Force);
//当对象y坐标小于0,摧毁该对象,并输出当前坐标
if (transform.position.y < 0)
{
Destroy(gameObject);
Debug.LogWarning("Position: " + transform.position);
}
//输出物体当前速度
Debug.Log("Velocity: " + rb.velocity);
}
参考:
我自己
后记
一篇文章查资料做实验写了一晚上,学到了很多,但是有用的都是英文的资料,中文的没怎么搜到,所以也想分享给同是学unity的在中文互联网上查资料的你,求点点赞,点点收藏,谢谢你了。