草庐IT

【Unity】[帮助文档] AddForce函数详解,参数ForceMode(Acceleration、Force、Impulse 和 VelocityChange)的选择

gongfpp 2023-11-05 原文

背景

经常忘,经常查,倒不如我自己写一篇给自己方便参考,毕竟每次都在某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的在中文互联网上查资料的你,求点点赞,点点收藏,谢谢你了。

有关【Unity】[帮助文档] AddForce函数详解,参数ForceMode(Acceleration、Force、Impulse 和 VelocityChange)的选择的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  3. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  4. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  5. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  6. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  7. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  10. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

随机推荐