详解Unity中的刚体和碰撞体组件_unity刚体和碰撞体_梦小天幼的博客-程序员宅基地

技术标签: unity  详解Unity  

前言

Unity 中内置了一套完成的物理引擎,能够完成现实世界的近似模拟。而在 Unity 物理引擎中,刚体组件和碰撞体组件则是无法避开的,刚体组件是让物体产生物理行为的组件,而碰撞体组件则是让刚体与物体产生碰撞的组件,今天就来简要认识一下这种组件吧。

前排提醒:本文仅代表个人观点,以供交流学习,若有不同意见请评论留言,笔者一定好好学习,天天向上。
阅读此文章时,若有不理解的地方,推荐观看本文列出的参考资料来对照阅读。

Unity 版本[2019.4.10f1] 梦小天幼 & 禁止转载

视频讲解:
详解Unity的刚体和碰撞体_BiLiBiLi

掌握基础物理常识再阅读本篇会较为容易


一、刚体(Rigidbody)组件参数

刚体组件有两种,分别是 Rigidbody 组件和 Rigidbody2D 组件,本篇只谈前一种刚体组件。
在 Unity 中,若想要一个物体具有在现实世界中的物理效果,比如受重力影响,就要为其添加 Rigidbody 组件,该组件是让物体产生物理行为的组件。通过刚体组件可以给物体添加一些常见的物理属性,如质量、摩擦力、碰撞参数等。
在物理学中,刚体是一个理想模型,通常把在外力作用下,物体的形状和大小保持不变,而且内部各部分相对位置保持恒定的理想模型称为刚体。
按下物体对象的 Inspector 面板的 Add Component 按钮,搜索 Rigidbody 即可添加该组件。(或通过 Physics->Rigidbody 分类)

在这里插入图片描述在这里插入图片描述

1.Mass 质量

设置物体的质量,默认质量是 1 千克(KG),这时根据物理学原理来讲,只需要给这个物体一个向上的力(9.8N),就可以抵消重力,稍微大于 9.8N,便可以上升。

2.Drag 阻力

设置物体的阻力,默认为 0,则没有阻力。阻力的方向与物理运动方向相反,该参数数值越大,所受到的阻力也就越大,速度的衰减也就越快。极大时物体将会立即停止运动。
在这里插入图片描述

3.Angular Drag 角阻力

设置物体的角阻力(旋转阻力),与该物体的旋转方向相反,默认为 0.05。设置该值后,物体在任何方向上的旋转运动都将受到影响。若设置为 0,则物体一旦开始旋转就不会停止(无重力状态下)。该值越大,旋转衰减越快。
在这里插入图片描述

该例子中,下面的物理没有勾选使用重力选项,用以模拟无重力,当该物体收到外力影响,若没有角阻力的影响,则会不停旋转,若没有阻力的影响,则该物体会不断移动。

4.Use Gravity 使用重力

设置该物体是否受重力影响,模拟现实世界中自由落体运动。勾选则受到影响,不勾选则模拟无重力环境下的运动状态。
在这里插入图片描述

底下三个物体没有勾选此项,若你看到这里了,别光看着,自己动手玩玩,还挺好玩的。

5. Is Kinematic 是否遵循动力学

设置该物体是否受动力学模拟,勾选则表示该物体不受重力、速度、阻力、质量等物理模拟的影响,只受脚本和动画的影响而运动。这个有什么用呢,比如当你首先勾选肯定能降低性能消耗,物理系统已经不会计算它了,其次它虽然不受物理模拟的影响,但是它依旧是可以影响其他物体的,比如移动通过脚本移动它的 transform,依旧可以撞击其他刚体!注意仅影响到刚体!
在这里插入图片描述

如图所示,图中的两个障碍物仅添加了碰撞体,而没有勾选此选项的刚体会受到碰撞体的影响,勾选之后则不会受到碰撞体的影响,但是依旧能影响且推动同样有着刚体组件的物体。至于用途,就要读者自行发挥想象了,游戏就是想象!
移动的物体是使用脚本驱动的,不受物理世界影响的:代码如下。很简单的一句

    public float speed = 3;
    void Update()
    {
        transform.position += new Vector3(0, 0, Time.deltaTime * speed * -1);
    }

6.Interpolate 插值

该参数用于解决Unity中物理模拟和画面渲染不同步的问题,当不进行插值处理时,计算得到的物理数据是上一个物理模拟时间点的数据,而插值则是获取最近似当前渲染时间点数据的一种手段。当你发现刚体移动时会发生抖动,建议调整一下此选项。
一共两个参数

  • Interpolate:根据前一帧来平滑变换
  • Extrapolate:根据下一帧来平滑变换

7.Collision Detection 碰撞检测

该属性用于控制避免高速运动的物体穿过其他对象而没有发生碰撞。

  • Discrete 离散碰撞检测(默认,适用于大部分刚体,这个肯定是最省资源的,毫无疑问,一般情况下默认这个,不要改)
  • Continuous 连续碰撞检测(适用于被高速撞击的物体)
  • Continuous Dynamic 连续动态碰撞检测(适用于高速移动的物体)
  • Continuous Speculative 连续扫描碰撞检测(emmm,不知道,资料好难找)
    给大家举个例子,就明白了
    在这里插入图片描述

在这里插入图片描述
第一个的碰撞检测是默认的离散检测,物体直接掉下去了,第二个则是连续动态检测,成功拦住了,这方面资料较少,个人没这个能力就不往深处讲了。

8.Constraints 约束条件

约束物体在某一个方向上的运动和旋转,默认不约束,各轴的运动旋转受物理系统控制。这个应该很好理解,举个例子。
在这里插入图片描述

这里我冻结了这扇门的 XYZ 轴的运动和 XZ 轴的旋转,现在使用物体推门,一个简单的门就做好了。若想要单扇门的推动效果(不过这里用 Joints 物理关节更简单,以后我会写相关的文章的),读者自行拓展吧。


二、基本碰撞体(Collider)组件参数

当一个物理添加了碰撞体组件后,它会默认阻挡刚体的运动,如上述例子中,我添加了一块 Plane,它就会默认阻挡受重力影响的刚体的下坠。这是因为当我创建它的时候它就自带了一个碰撞体组件。
碰撞体组件定义了物体的物理形状,且碰撞体本身是隐形的,大家可以想想空气墙的例子。
当你创建了一个 Cube,该物体就自带了一个 Box Collider。最简单且最节省计算资源的碰撞体就是一系列基本碰撞体。当你右键创建一系列基本模型时,它们就自带了一系列基本碰撞体。
一个物体可以带有多个碰撞体组件,这样就形成了组合碰撞体。

在这里插入图片描述

1.基本参数

在这里插入图片描述

基本碰撞体组件的参数如下,Edit Collider用于编辑碰撞体大小,Center和Size用于指定中心和范围,就不多说了,下面重点说说Is Trigger属性和Material属性

2. Is Trigger

前面说过,碰撞体会默认阻挡刚体的运动,但是有些时候需要检测两个物体发生重叠但又不想引起物理上的碰撞,就需要勾选此选项,将碰撞体变成一个触发器
当勾选此项后,该物体就不会再阻挡刚体运动了,但当有刚体与当前物体发生重叠的时候,会调用 OnTriggerEnter()方法。
在这里插入图片描述

这里我给底下的平面加了触发函数的脚本,然后将其碰撞体设置成了触发器。也就是勾选了 Is Trigger

    private void OnTriggerEnter(Collider other) {
        Debug.Log("检测到物体【" + other.name + "】与当前碰撞体发生重叠!");
    }

3.Material 物理材质

这个选项用于模拟物体表面的物理材质,对于地面而言,比如冰面、木板、水泥板这些。对于物体本身而言,比如物理自身的弹性,物理自身的平滑度之类的,都会直接影响到物理模拟的效果。

创建物理材质和创建普通材质的方法是一样的,右键菜单里面找到 Physic Material,物理材质参数如图所示
在这里插入图片描述

  • Dynamic Friction 运动摩擦力
    • 取值范围 0~1
  • Static Friction 静止摩擦力
    • 取值范围 0~1
  • Bounciness 表面弹性
    • 取值范围 0~1,值为 0 时无弹性
  • Friction Combine 摩擦力混合
    • 发生碰撞的两个碰撞体对象的摩擦力的混合方式
    • Maximum 取最大值
    • MuItiply 取相乘值
    • Minimum 取最小值
    • Average 取平均值
  • Bounce Combine 弹性混合
    • 发生碰撞的两个碰撞体对象的摩擦力的弹性方式
    • Maximum 取最大值
    • MuItiply 取相乘值
    • Minimum 取最小值
    • Average 取平均值

来举个例子,比如模拟冰块在冰面上
在这里插入图片描述

我同时给三个碰撞体和 Plane 都给了如下参数的物理材质,同时给 Plane 加了一点倾斜角度
在这里插入图片描述


三、碰撞体的分类

碰撞体因为是否具有刚体组件以及刚体组件上是否设置动力学刚体等,都会导致具有该组件的物体的物理碰撞特性发生变化,所以根据以上不同之处,将碰撞体分为三类:静态碰撞体、刚体碰撞体、动力学刚体碰撞体。

1.静态碰撞体(Static Collider)

没有挂载刚体组件的碰撞体叫做静态碰撞体。
常用于制作游戏中的固定部分,比如地形,障碍物,树木等,因为这些部分一般没有移动的需求,刚体撞击的时候,位置也不会变化,比如大名鼎鼎的 GTA5 里面,树木就是无敌的。
对于有移动碰撞体的需求,建议使用刚体碰撞体或动力学刚体碰撞体。请不要使用此种方式,否则会增大物理系统的计算量。

2.刚体碰撞体(Rigidbody Collider)

挂载了刚体组件的碰撞体叫做刚体碰撞体。
物理引擎会一直计算该碰撞体的物理状态。

3.动力学刚体碰撞体(Kinematic Rigidbody Collider)

挂载了刚体组件且刚体组件设置为动力学刚体的碰撞体叫做动力学刚体碰撞体。(好绕)
常用于制作如门,固定轨迹移动的关卡道具等。


四、刚体的休眠

上面关于碰撞体的分类中说过,刚体碰撞体会被物理引擎一直计算物理状态。但是!这样会不会太耗费资源了呢?Unity 中怎么解决的呢,这就引入了一个概念,刚体的休眠。

当一个刚体的移动速度和旋转已经慢于某个事先定义的阈值了(一般很小很小,可修改),并且保持了一定的时间,那是否可以说,这个刚体短时间内已经相对静止了,这时就可以说该物体进入了“休眠”状态,休眠状态中的刚体会被物理系统视而不见,所以自然就节约了运算资源,直到它被重新“唤醒”为止,也就是移动速度和旋转高于预定值了,开始运动了。

请注意,刚体的休眠完全是自动发生的,唤醒刚体自然也是自动发生的。

在 Rigidbody 组件中,带有 sleepVelocity 和 sleepAngularVelocity 属性,Unity 就是通过这两个属性来判定刚体是否需要进入休眠状态的。但需要特别注意的是!Unity 目前已经弃用这两个属性,转而使用 sleepThreshold,根据官方 API 的描述,“该属性经过质量标准化的能量阈值,当低于该阈值时,对象开始进入休眠状态”。说人话,就是将上述两个属性通过一些算法合二为一了,只需要判断 sleepThreshold 是否低于预设的阈值就可以判断该刚体是否休眠了。该阈值一般为 0.005,可通过,[Edit]->[Project Settings]->[Physics]来设置,如下图所示。
在这里插入图片描述

在 Rigidbody 组件中,你也可以通过 IsSleeping()函数来判断刚体是否正在休眠。但是该函数的本质还是判断 sleepThreshold。

当刚体进入休眠状态,是无法和碰撞体发生碰撞的,因为刚体进入休眠状态,其物理系统就已经不再计算了,自然也无法产生碰撞信息和触发碰撞事件。

你也可以 WakeUp()来强制唤醒一个刚体。

下图这个例子中演示了刚体休眠时,则刚体不会对碰撞体产生碰撞
在这里插入图片描述

大正方体带有刚体组件,其他仅有碰撞体,当大正方体下落时,受物理系统重力影响,自由下落,与其他碰撞体发生碰撞,当落下静止时,刚体立刻休眠,这时拖动底下的碰撞体,则直接穿过,这时刚体处于悬空状态,被物理系统唤醒,又受到重力影响,开始下落,又与地面发生碰撞,立刻休眠。

    public Rigidbody rig;
    public bool IsSleeping;
    void FixedUpdate()
    {
        IsSleeping = rig.IsSleeping();
    }

五、刚体和碰撞体的碰撞测试及触发方法

写到这,基本可以画上句号了,但是这里还是单开一小节,列举一下刚体和碰撞体之间,到底需要满足何种条件才会发生碰撞呢?需要满足何种条件才会触发事件呢?

首先必须两个都是碰撞体,且运动一方为非运动学刚体,才可以发生碰撞!碰撞时会产生碰撞事件,OnCollision()
其次,一方碰撞体必须勾选 Is Trigger 才会触发 OnTrigger()事件

1.什么时候才会发生碰撞

第三小节我们说过关于碰撞体的分类,一共分为三类静态碰撞体、刚体碰撞体、运动学刚体碰撞体,我们把它两两组合,下面简要罗列一下可能出现的情况,一共 9 种情况。

在这里插入图片描述

这里如果看不明白,建议再去第三小节反复观看!
注意:当发生碰撞,双方都会触发 OnCollision()事件,当不发生碰撞,则双方都不会触发事件。

2.什么时候才会触发 OnTrigger

这里请回到第二小节看看关于碰撞体变成触发器的说明,明白了请往下看。根据上文可得,当碰撞体勾选了 Is Trigger 之后才可能触发 OnTrigger()事件,若不勾选,那只能触发 OnCollision()事件,这里希望读者思路清晰,别乱。每看一段,就自己做一次实验,慢慢来。
下面罗列一下可能触发 OnTrigger 的情况,一共有…36 种

在这里插入图片描述

注意:这里绝对不会出现一个触发 OnCollision,另一个触发 OnTrigger 的情况,如果在表格中打勾,这就说明,双方必定都会触发 OnTrigger 事件!上一个图也一样,若表格打勾,则双方必定都会触发 OnCollision 事件!

3.碰撞和触发方法

上面你能看懂,这些肯定不成问题,就不废话了。

触发检测
1.OnTriggerEnter( Collider other )当进入触发器
2.OnTriggerExit( Collider other )当退出触发器
3.OnTriggerStay( Collider other )当逗留触发器

碰撞检测:
1.OnCollisionEnter( Collision other ) 当进入碰撞器
2.OnCollisionExit( Collision other ) 当退出碰撞器
3.OnCollisionStay( Collision other ) 当逗留碰撞器


六、总结与参考资料

1.总结

  • 关于碰撞体组件中还有 Mesh(网格)碰撞体、Wheel(车轮)碰撞体和 Terrain(地形)碰撞体,篇幅有限,这些组件以后详说。
  • 双方必须都要有碰撞器,且运动的一方必须是非运动学刚体才可以发生碰撞(N 次强调,这句话很重要!)
  • 碰撞体分类:静态碰撞体,刚体碰撞体,运动学刚体碰撞体。
  • 当刚体进入休眠状态,无法与碰撞体发生碰撞
  • 勾选Is Trigger可以将碰撞体变为触发器

2.参考资料

[1]吴亚峰.《Unity3D游戏开发标准教程》
[2]马瑶.《Unity 3D脚本编程与游戏开发》
[3]郑洪智.Unity刚体详解
[4]冬菊子.unity3d 理解刚体(Rigidbody)和碰撞体(Collider)以及触发器(Is Trigger),边学边更新
[5]一白梦人.【Untiy学习笔记】Rigidbody组件及其常用函数
[6]亿洋.Unity 理解刚体(Rigidbody)和碰撞体(Collider)和触发器(Is Trigger)以及刚体休眠(Rigidbody Sleeping)
[7]Tonge.Unity3D深入浅出-物理材质(Physics Materials)
[8]只待苍霞.论Collision Detection的作用
[9]月落乌啼霜月落.【Unity 22】 Unity 力,扭矩,刚体,触发器的简单使用
[10]网络.解决Unity物体速度过快无法进行碰撞检测(碰撞检测穿透)
[11]网络.Unity圣典和官方API以及部分百度百科

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43147385/article/details/124042051

智能推荐

php的准备查询,php – 取消分配准备好的查询_weixin_39662462的博客-程序员宅基地

编辑:我感谢丹尼尔和丹尼斯.这个问题现在已经解决了,正如他们巧妙地指出的那样,这个案例中的问题是程序员(特别是没有考虑到这一点)我希望我能接受这两个作为答案.注意:说我是postgresql的新手是侮辱新手!我正在编写一个Web应用程序,它将利用PostgreSQL数据库进行数据存储.在我到目前为止所做的工作中,我已经很好地掌握了创建查询和从中检索结果的语法,无论是查找,删除,插入还是更新.然而,...

Elementui el-input 输入框校验以及校验表单校验_element input输入框的验证_长春小霸王的博客-程序员宅基地

一. 常用的 element-ui el-input 输入框1. 过滤字母e,在js中属于数字,但是正则表达式 \d 是拦不住字母e 的<el-input type="number" placeholder="请输入" min="1" onKeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode || event.which))) || event.which === 8" v-model.number="count"&g_element input输入框的验证

隐私存储好手段,安全空间一触即达,忆捷FU68指纹加密U盘体验_忆捷fu68贴吧_科技领袖的博客-程序员宅基地

现在手机和电脑里的资料越来越多,要想备份一些比较重要的内容,U盘是个很方便的工具,现在大容量的U盘很常见,而且有些还支持手机使用,平时拿来备份聊天记录、数据资料都很方便。不过保存了重要内容的U盘,要如何确保安全性呢?最近我入手的一款忆捷EAGET FU68指纹加密U盘,就很好的解决了这个问题。现在数据安全是很多人工作生活中特别关注的问题,指纹识别功能这些年在手机、笔记本等设备上已经得到了普及,大家也都习惯了这种加密方式,忆捷这款带有指纹加密功能的U盘,不仅用起来容易,而且还很可靠。这款忆捷F_忆捷fu68贴吧

IS-IS知识_zzfcnc的博客-程序员宅基地

IS-IS路由 一. 背景介绍   1. CLNP是什么?   CLNP:   是OSI模型中网络层中的一种不面向连接的网络协议,和ip有相同的特质。但是它是纯粹的OSI模型的一个,而IP现在是我们熟悉的TCP/IP协议栈中的网络层协议。他们两个在OSI模型

App微信支付 php后台接口_Gy__My的博客-程序员宅基地

App微信支付 php后台接口本问将介绍App微信支付(2016.10.11)的php(7.0)后台支付和回调接口,框架是Thinkphp5.0...

C#如何实现窗体控件大小随窗体大小变化(包括字体)_c#控件随窗口大小变化_查无此人2021的博客-程序员宅基地

如图,拖动窗体即可改变控件大小(包括字体)窗体尺寸:345*315窗体尺寸:603*509项目资源如下源码如下using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing..._c#控件随窗口大小变化

随便推点

Kubernetes集群如何重启_kubesphere 如何重启应用_软件工程小施同学的博客-程序员宅基地

一、切换到root账号检查各个节点检验相关组件安装结果:# kubeadm version# kubectl version# cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf# systemctl status kubelet二、_kubesphere 如何重启应用

axis2作为客户端产生大量文件的解决方案_axis2 生成的客户端java代码文件很大_王克兵的博客-程序员宅基地

问题:使用axis2调用远程webservice时,产生大量临时文件写入磁盘,降低程序运行效率,占用磁盘空间前提:使用axis2客户端版本:1.7.4解决方案:1:在初始化RPCServiceClient 使用构造器RPCServiceClient(ConfigurationContext configContext, AxisService service) 替换默认构造器在ws..._axis2 生成的客户端java代码文件很大

升级node到最新版_waketzheng的博客-程序员宅基地

yarn add nuxt时报错了,大致意思是node版本不兼容node -v13.x.x机器为阿里云ubuntu18搜索了一下,找到了解决方案,一试果然成功了Ref:https://askubuntu.com/questions/426750/how-can-i-update-my-nodejs-to-the-latest-versionsudo npm cache clean -fsudo npm install -g nsudo n latestnode -vv1

jemalloc 3.6.0源码详解—[3]Run and bins_jemalloc bins_杏林小轩的博客-程序员宅基地

2.4 Run (arena_run_t)如同在2.1节所述, 在jemalloc中run才是真正负责分配的主体(前提是对small region来说). run的大小对齐到page size上, 并且在内部划分成大小相同的region. 当有外部分配请求时, run就会从内部挑选一个free region返回. 可以认为run就是small region仓库. **注:**run的大小就是其内_jemalloc bins

计算机科学是期刊核心2类,属于计算机技术类的北大核心期刊有哪些-程序员宅基地

属于计算机技术类的北大核心期刊有哪些作者:核心期刊目录查询 发布时间:2016-12-02现在计算机技术方面的期刊有:省级期刊、国家级期刊、核心期刊,但是对于晋升职称来说很多人会选择核心期刊来进行投稿,期原因就是核心论文对于在晋升时对于加分的环节较多,并且对于评审考核通过的几率也较大。但是核心类的期刊往往要求都十分的严格,在收录属于计算机技术类的北大核心期刊有哪些现在计算机技术方面的期刊有:省级期..._计算机科学是核心期刊吗

银行科技岗位 笔试 专业方向重点 + 面试一般问题_银行科技岗面试题_努 力 小 子的博客-程序员宅基地

1.数据库SQL语句快速回忆——SQL基础知识点汇总2.排序算法3.设计模式_银行科技岗面试题

推荐文章

热门文章

相关标签