Unity 物理系列五 关节
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 物理系列五 关节相关的知识,希望对你有一定的参考价值。
参考技术A 参考
https://docs.unity.cn/cn/2019.4/Manual/Joints.html
Unity物理关节全解析
关节组件将刚体连接到另一个刚体或空间中的固定点。关节施加使刚体移动的力,而关节限制功能可以限制该移动。
Unity 提供的以下关节可以对刚体组件施加不同的力和限制,从而使这些刚体具有不同的运动。
https://docs.unity.cn/cn/2019.4/Manual/class-CharacterJoint.html )
角色关节 (Character Joint) 主要用于布娃娃效果。此类关节是延长的球窝关节,可在每个轴上限制该关节,例如臀部或肩膀。沿所有线性自由度约束刚体移动,并实现所有角度自由度。连接到角色关节 (Character Joint) 的刚体围绕每个轴进行定向并从共享原点开始转动。
关于布娃娃和角色关节,本系列后续专门搞一篇来研究一下。
https://docs.unity.cn/cn/2019.4/Manual/class-ConfigurableJoint.html
模拟任何骨骼关节,例如布娃娃中的关节。您可以配置此关节以任何自由度驱动和限制刚体的移动。
当您想要自定义布娃娃的运动并对角色强制实施某些姿势时,这种关节特别有用。使用可配置关节还可以将关节修改为您自行设计的高度专业化关节。
https://docs.unity.cn/cn/2019.4/Manual/class-FixedJoint.html
限制刚体的移动以跟随所连接到的刚体的移动。当您需要一些可以轻松相互分离的刚体,或者您想连接两个刚体的移动而无需在 Transform 层级视图中进行父级化时,这种关节很有用。
固定关节 (Fixed Joint) 将对象的移动限制为依赖于另一个对象。这有点类似于 管控 (Parenting),但是实现的方式是通过物理系统而不是 变换 (Transform) 层级视图。使用固定关节的最佳场合是在希望对象可以轻松相互分离时,或者在没有管控情况下连接两个对象的移动。
在游戏中有时可能希望对象永久或暂时粘在一起。固定关节可能是比较适合用于这些情况的 组件 ,因为不必通过脚本更改对象的层级视图来实现所需的效果。代价是所有使用固定关节的对象都必须使用 刚体 。
例如,如果要使用“粘性手榴弹”,可写一个脚本来检测与另一刚体(如敌人)的碰撞,然后创建一个固定关节并附加到该刚体。然后,当敌人四处移动时,关节将使手榴弹紧贴在他们身上。
https://docs.unity.cn/cn/2019.4/Manual/class-HingeJoint.html
在一个共享原点将一个刚体连接到另一个刚体或空间中的一个点,并允许刚体从该原点绕特定轴旋转。用于模拟门和手指关节。 也可用于模拟链条、钟摆等对象。
参考 Unity 关节
在这个例子中,车头转向前进时,会带动车厢。
https://docs.unity.cn/cn/2019.4/Manual/class-SpringJoint.html
使刚体彼此分开,但使刚体之间的距离略微拉伸。弹簧就像一块弹性物,试图将两个锚点一起拉到完全相同的位置。 拉力的强度与两个点之间的当前距离成比例,其中每单位距离的力由 Spring 属性设定。为了防止弹簧无休止振荡,可以设置 Damper 值,从而根据与两个对象之间的相对速度按比例减小弹簧力。值越高,振荡消失的速度越快。
默认的小球是有弹簧关节的,发射出去后,取消关节,小球就会飞出去
Unity物理系统物理系统相关组件
一、物理系统相关组件
Unity中的物理系统涉及的组件分为如下几类:
- 刚体
- 角色控制器
- 碰撞体
- 布料
- 关节
- 力场
二、刚体(Rigidbody)
Rigidbody(刚体)组件可以使游戏对象在物理系统的控制下进行运动,Rigidbody 可接受外力与扭矩力,用以保证游戏对象像在真实世界中那样进行运动。任何游戏对象只有添加了Rigidbody 组件之后才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过 NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加 Rigidbody 组件。
Rigidbody组件的属性如下:
属性 | 作用 |
---|---|
Mass | 质量 |
Drag | 阻力。指物体受力运动时受到的空气阻力 |
Angular Drag | 角阻力。指物体受力旋转时受到的阻力 |
Use Gravity | 是否启用重力 |
Is Kinematic | 是否开启动力学。如果开启,则游戏物体不再受物理引擎影响,只能通过Transform控制 |
Interpolate | 插值。用来控制刚体运动时的抖动情况。包括如下选项:「None」没有插值;「Interpolate」内插值,基于前一帧的Transform平滑此次Transform;「Extrapolate」外插值,基于下一帧的Transform平滑此次Transform |
Collision Detection | 碰撞检测模式。包括如下选项:「Discrete」离散碰撞检测;「Continuous」连续碰撞检测;「Continuous Dynamic」连续动态碰撞检测;「Continuous Speculative」连续推断碰撞检测 |
Constraints | 约束。「Freeze Position」冻结指定轴向的位移;「Freeze Rotation」冻结指定轴向的旋转 |
2.1 关于碰撞检测模式(Collision Detection)
Rigidbody组件内置了四种碰撞检测模式,官方的解释有些晦涩,这里借用一张贴吧大佬的图(原帖地址)。图中箭头指的是采用A模式的物体撞击采用B模式的物体,箭头中间的值表示两个物体碰撞时实际采用的检测模式。
比如说采用了「Continuous」模式的物体,撞击不带刚体的物体(也就是图中的Static),最终将采用「Continuous」模式进行碰撞检测。而如果两个采用「Continuous」模式的物体相撞,则会采用「Discrete」模式进行检测。
对于离散碰撞检测(Discrete),因为是以帧为单位进行检测,所以如果遇到高速移动的物体A,在上一帧还在B物体的外侧,而下一帧就已经穿过A到达另一侧,就会出现碰撞检测没有触发的情况。因此才有了两种连续碰撞检测模式。其中连续碰撞检测(Continuous)适用于可能被高速对象撞击的对象,连续动态碰撞检测(Continuous Dynamic)适用于可能发生碰撞的高速对象。
需要注意:
- 连续碰撞检测会增加额外的性能消耗,因此在没有相应需求的情况下不要使用。
- 只有盒型碰撞体、球形碰撞体和胶囊碰撞体支持连续碰撞检测。
连续推断碰撞检测(Continuous Speculative)是一种新增的碰撞检测模式,它相对于前两种连续碰撞检测更加节省性能,但也可能会导致穿隧效应和幽灵碰撞。详情可以查看官方文档
2.2 通过刚体控制角色移动
一种是通过设置刚体的线速度和角速度实现角色移动
private void FixedUpdate()
var horizontal = Input.GetAxis("Horizontal");
var vertical = Input.GetAxis("Vertical");
// 设置线速度
_rigidbody.velocity = transform.forward * (vertical * moveSpeed);
// 设置角速度
_rigidbody.angularVelocity = transform.up * (horizontal * rotateSpeed);
效果如下
另一种是通过MovePosition()
和MoveRotation()
方法控制
private void FixedUpdate()
var horizontal = Input.GetAxis("Horizontal");
var vertical = Input.GetAxis("Vertical");
// 控制位移
_rigidbody.MovePosition(transform.position+transform.forward * (vertical * moveSpeed*Time.deltaTime));
// 控制旋转
_rigidbody.MoveRotation(transform.rotation*Quaternion.Euler(transform.up * (horizontal * rotateSpeed*Time.deltaTime)));
效果如下
三、角色控制器(Character Controller)
Character Controller(角色控制器)主要用于对第三人称或第一人称游戏主角的控制,并不使用刚体物理效果。
Character Controller组件的属性如下:
属性 | 作用 |
---|---|
Slope Limit | 坡度限制。游戏物体可以爬上度数小于等于该参数的斜坡 |
Step Offset | 台阶高度。游戏物体可以爬上高度小于等于该参数的台阶 |
Skin Width | 皮肤厚度。决定了两个碰撞体可以相互渗入的深度,建议设置为半径的10% |
Min Move Distance | 最小移动距离。如果游戏对象的移动距离小于这个值,则不会移动 |
Center | 用来调整胶囊碰撞体与游戏物体的相对位置 |
Radius | 胶囊碰撞体的半径 |
Height | 胶囊碰撞体的高度 |
需要注意的是Character Controller 组件不会对施加给它的作用力做出反应,也不会作用于其他的刚体。
当我们给角色挂载「Rigidbody」时,是可以将前方的方块撞开的
如果挂载的是「Character Controller」则不会对方块产生任何效果
如果希望在挂载「Character Controller」的情况下,对撞击的物体产生力的作用,可以通过OnControllerColliderHit()
函数对其施加一个作用力
private void OnControllerColliderHit(ControllerColliderHit hit)
if (hit != null && hit.gameObject.name=="Cube")
hit.rigidbody.AddForce(hit.point*500);
效果如下
附上通过「Character Controller」控制物体移动的代码
private void FixedUpdate()
var horizontal = Input.GetAxis("Horizontal");
var vertical = Input.GetAxis("Vertical");
_controller.Move(transform.forward * (moveSpeed * vertical * Time.deltaTime));
transform.Rotate(Vector3.up * (rotateSpeed * horizontal * Time.deltaTime));
四、碰撞体(Collider)
碰撞体是物理组件中的一类,3D 物理组件和 2D 物理组件有独立的碰撞体组件,它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞。在物理模拟中,没有碰撞体的刚体会彼此相互穿过。
4.1 基本碰撞体
Unity内置的基本碰撞体包括盒型碰撞体(Box Collider)、球形碰撞体(Sphere Collider)和胶囊碰撞体(Capsule Collider)。 这三种碰撞体的属性基本相同,这里以「Box Collider」为例简单说明
属性 | 作用 |
---|---|
Edit Collider | 编辑碰撞体 |
Is Trigger | 触发器。勾选后碰撞体可用于触发事件,并失去物理效果 |
Material | 材质。采用不同的物理材质类型决定了碰撞体与其他对象的交互形式。如冰面摩擦力较小,弹球富有弹性等 |
Center | 碰撞体的相对位置 |
Size | 碰撞体的大小 |
4.2 网格碰撞体(Mesh Collider)
网格碰撞体通过获取物体上的网格来构建碰撞体。优点是构建出的碰撞体非常精细,缺点是更加消耗性能。
属性 | 作用 |
---|---|
Convex | 两个网格碰撞体都不开启该选项时,它们之间无法发生碰撞。任何一方开启该选项,就可以发生碰撞。如果不开启该选项,物体的刚体必须开启「isKinematic」选项。另外,只有当网格三角形数量少于255时,该选项才会生效 |
Cooking Options | 物理引擎对网格的处理方式。「Cook for Faster Simulation」启用时,物理引擎会做一些额外步骤,确保烘焙出的网格在运行时是最优的。如果禁用,则会选择最快速的烘焙方式。这样得出的网格不一定最优;「Enable Mesh Cleaning」启用时清理网格上的退化三角形 1 ^1 1及一些几何构件,使碰撞检测更精确;「Weld Colocated Vertices」启用后合并相同位置的顶点 |
①退化三角形:面积为0的三角形。满足下列条件之一的三角形即可称为退化三角形:三个内角的度数为 (180°,0°,0°) 或 (90°,90°,0°);三边其中一条边的长度为0;一条边的长度等于另外两条之和。
4.3 车轮碰撞体(Wheel Collider)
车轮碰撞体是一种针对地面车辆的特殊碰撞体。它有内置的碰撞检测、车轮物理系统及有滑胎摩擦的参考体。除了车轮,该碰撞体也可用于其他的游戏对象。参数比较专业,具体各项参数的意义可以查看官方文档
4.4 地形碰撞体(Terrain Collider)
地形碰撞体就是专为地形构建的碰撞体。
属性 | 作用 |
---|---|
Material | 材质 |
Terrain Data | 地形数据。采用不同的地形数据决定了地形的外观 |
Enable Tree Colliders | 开启树的碰撞体。开启后地形上的树也会开启碰撞体 |
4.5 物理材质
前面提到的大部分碰撞体都具有「Material」这一属性,即物理材质。物理材质用于调整碰撞物体的摩擦和弹跳效果。我们可以通过右键「Create->Physic Material」进行创建。
属性 | 作用 |
---|---|
Dynamic Friction | 滑动摩擦系数 |
Static Friction | 静摩擦系数 |
Bounciness | 弹性系数 |
Friction Combine | 两个碰撞体之间的摩擦混合方式。「Average」取均值;「Minimum」取最小值;「Maximum」取最大值;「Multiply」取乘积 |
Bounce Combine | 两个碰撞体之间的弹性混合方式。选项同上 |
需要注意,假如两个接触的碰撞体设置了不同的混合方式,则会按照下面的优先级取值:
Average<Minsmum<Multiply<Maximum
五、布料组件
布料组件可以模拟类似布料的行为状态,如飘动的旗帜、角色身上的衣服等。布料组件需要「Skinned Mesh Renderer」(蒙皮网格渲染器)和「Cloth」组件协同运作。
5.1 蒙皮网格渲染器
属性 | 作用 |
---|---|
Bounds | 设置网格范围 |
Quality | 品质。定义蒙皮时每个顶点使用的最大骨骼数量,数量越多,渲染质量越高 |
Update When Offscreen | 蒙皮网格自动更新。如果启用,即使没有摄像机观察,Skinned Mesh也会更新;如果禁用,没有摄像机观察时,动画就会停止运行 |
Mesh | 网格。指定对象使用的网格渲染器 |
Root Bone | 指定骨骼的根节点 |
Cast Shadows | 投射阴影 |
Receive Shadows | 接收阴影 |
Light Probes | 设置渲染器如何从光照探针系统接收光照数据。可以参考官方文档:传送门。「Off」不使用任何插值的光照探针;「Blend Probes」使用一个插值的光照探针;「Use Proxy Volume」使用插值光照探针的3D网格;「Custom Provided」渲染器从MaterialPropertyBlock中提取光照探针着色器的统一值 |
Reflflection Probes | 设置渲染器如何从反射探针系统接收反射数据。可以参考官方文档:传送门。「Off」禁用反射探针,使用一个天空盒进行反射;「Blend Probes」只混合反射探针;「Blend Probes and Skybox」混合反射探针之间或反射探针与天空盒;「Simple」启用反射探针,但当有两个重叠的网格时,反射探针不会发生混合 |
Anchor Override | 当使用光照探针和反射探针时,用来确定插值位置的Transform |
Skinned Motion Vectors | 开启会使用双缓冲网格蒙皮数据,这样Unity就可以对蒙皮运动进行插值,并将其导入运动矢量纹理。这可以得到更正确的运动矢量,但会占用更多显存 |
Dynamic Occlusion | 动态遮挡。开启后,当渲染器被静态遮挡物挡住时,Unity会剔除该渲染器,否则不会剔除 |
5.2 布料
Cloth组件为模拟织物提供基于物理的解决方案。它必须与蒙皮网格渲染器一起工作。
属性 | 作用 |
---|---|
Stretching Stiffness | 抗拉伸程度,数值越大越不容易拉伸 |
Bending Stiffness | 抗弯曲程度,数值越大越不容易弯曲 |
Use Tethers | 启用限制。防止布料粒子远离固定点,有助于减少过度拉伸 |
Use Gravity | 启用重力 |
Damping | 布料的运动阻尼 |
External Acceleration | 应用到布料身上的外部加速度 |
Random Acceleration | 应用到布料身上的随机外部加速度 |
World Velocity Scale | 世界速度比例。决定了角色在世界空间中的运动对布料顶点的影响。数值越大反应越剧烈 |
World Acceleration Scale | 世界加速度比例。决定了角色在世界空间中的加速度对布料顶点的影响。数值越大反应越剧烈 |
Friction | 摩擦系数 |
Collision Mass Scale | 碰撞粒子的质量大小 |
Use Continuous Collision | 使用连续碰撞检测提高碰撞稳定性 |
Use Virtual Particles | 每个三角形添加一个虚拟粒子,从而提高连续碰撞的稳定性 |
Solver Frequency | 解算器每秒迭代次数 |
Sleep Threshold | 布料的睡眠阈值 |
Capsule Colliders | 与布料发生碰撞的胶囊碰撞体列表 |
Sphere Colliders | 与布料发生碰撞的球形碰撞体列表 |
Virtual Particles Weights | 虚拟粒子权重。通过设置虚拟粒子的数量和每个粒子的权重提高碰撞稳定性 |
布料不响应场景中的任何碰撞体,也不会将力反射回世界。添加 Cloth 组件后,该组件完全不会响应和影响任何其他实体。因此在手动将碰撞体从世界添加到 Cloth 组件之前,布料和世界无法识别或看到彼此。即使执行了此操作,模拟仍是单向的:布料可以响应实体,但不会反向施力。
此外,只能对布料使用三种类型的碰撞体:球体、胶囊体以及使用两个球形碰撞体构造而成的圆锥胶囊碰撞体。之所以存在这么多限制是为了帮助提高性能。
六、关节组件(Joint)
关节组件用来模拟物体与物体之间的连接关系,必须依赖于刚体组件。
6.1 铰链关节(Hinge Joint)
铰链关节将两个刚体组合在一起,对刚体进行约束,让它们就像通过铰链连接一样移动。铰链关节非常适合用于门,但也可用于模拟链条、钟摆等对象。
属性 | 作用 |
---|---|
Connected Body | 连接刚体。该项用于为关节指定要连接的刚体,若不指定则该关节将与世界连接 |
Connected Articulation Body | 连接接合体 |
Anchor | 锚点。刚体可围绕锚点进行摆动 |
Axis | 轴。定义了刚体摆动的方向 |
Auto Confifigure Connected Anchor | 自动设置连接锚点。勾选该项,连接锚点会自动设置 |
Connected Anchor | 连接锚点。当 Auto Confifigure Connected Anchor 项开启时,该项会自动设置 |
Use Spring | 使用弹簧。勾选该项,则弹簧会使刚体与其连接的主体形成一个特定的角度 |
Spring | 弹簧力。该项用于设置推动对象使其移动到相应位置的作用力、 |
Damper | 阻尼。该项用于设置对象的阻尼值,数值越大则对象移动得越缓慢 |
Target Position | 目标角度。该项用于设置弹簧的目标角度,弹簧会拉向此角度,以度为测量单位 |
Use Motor | 使用马达。勾选该项,马达会使对象发生旋转 |
Target Velocity | 目标速度。该项用于设置对象预期将要达到的速度值 |
Force | 作用力。该项用于设置为了达到目标速度而施加的作用力 |
Free Spin | 自由转动。勾选该项,则马达永远不会停止,旋转只会越转越快 |
Use Limits | 使用限制。勾选该项,则铰链的角度将被限定在最大值和最小值之间 |
Min | 最小值。该项用于设置铰链能达到的最小角度 |
Max | 最大值。该项用于设置铰链能达到的最大角度 |
Bounciness | 当对象达到了最小或最大停止限制时对象的反弹力大小 |
Bounce Min Velocity | 造成连接体反弹的最小速度 |
Contact Distance | 极限接触距离。在距离极限位置的接触距离内,接触将持续存在以免发生抖动 |
Break Force | 断开力。该项用于设置铰链关节断开的作用力 |
Break Torque | 断开扭矩。该项用于设置断开铰链关节所需要的扭矩 |
Enable Collision | 激活碰撞。若勾选该项,则关节之间也会检测碰撞 |
Enable Preprocessing | 启用预处理。禁用预处理有助于稳定无法执行的配置 |
Mass Scale | 质量的缩放值。该项用于设置关节自身刚体的质量缩放值 |
Connected Mass Scale | 连接刚体的质量缩放值。该项用于设置关节连接的刚体的质量缩放值 |
下面来通过铰链组件实现开关门的效果。首先创建出门和门框的模型,都挂载上刚体。给门挂载「Hinge Joint」组件,将其「Connected Body」属性指定为门框。然后将锚点个轴移动到门框所在位置
接下来给门创建一个脚本,当鼠标点击时给予门一个力
private void OnMouseDown()
_rigidbody.AddForce(transform.forward*100);
运行游戏看下效果
可以看到,门虽然打开了,但会一直转下去。这时「Spring」和「Limits」部分的属性就派上了用场。首先启用「Use Spring」,并增加「Damper」的数值,以提供阻力。然后再启用「Use Limits」,设置最大旋转角度「Max」为120,设置弹性「Bounciness」为0.5。
运行再看下效果
6.2 固定关节(Fixed Joint)
固定关节组件用于约束一个游戏对象对另一个游戏对象的运动。类似于对象的父子关系,但它是通过物理系统来实现而不像父子关系通过 Transform 属性来进行约束。其属性在之前的铰链关节中都可以找到,这里不再赘述。
固定关节就像是在两个物体之间连接了一根木杆。这里我们使用两个球体进行简单演示。首先创建一大一小两个球体,并都挂载上刚体。大球的刚体设置冻结位置,小球不做调整。然后在小球上添加固定关节,并连接到大球上。为了看清楚大球的转动情况,这里给大球添加了一个贴图
给小球添加一个鼠标点击时施加力的脚本
private void OnMouseDown()
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
_rigidbody.AddForce(ray.direction*Force);
运行游戏看下效果
6.3 弹簧关节(Spring Joint)
弹簧关节组件可将两个刚体连接在一起,使其像连接着弹簧那样运动。
它的效果很好理解,这里不再详述
角色关节(Character Joint)和可配置关节(Configurable Joint)没有使用过,可以参考官方文档:角色关节、可配置关节
七、力场组件(Constant Force)
力场可以为刚体快速添加恒定作用力,适用于类似火箭发射出来的对象,这些对象在起初并没有很大的速度但是在不断地加速的。
属性 | 作用 |
---|---|
Force | 用于设定物体在世界坐标系中受到的力 |
Relative Force | 用于设定物体在物体局部坐标系中受到的力 |
Torque | 用于设定物体在世界坐标系中受到的扭矩力 |
Relative Torque | 用于设定在物体局部坐标系中受到的扭矩力 |
以上是关于Unity 物理系列五 关节的主要内容,如果未能解决你的问题,请参考以下文章
来自 Maya 的 FBX 以错误的关节旋转导入 Unity