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 物理系列五 关节的主要内容,如果未能解决你的问题,请参考以下文章

unity5.x中的关节和布料

Unity --- 关节组件

Unity—关节布料角色控制器视频播放

来自 Maya 的 FBX 以错误的关节旋转导入 Unity

[C#]请问如何消除unity3d中ConfigurableJoint关节的停转后的摆动(惯性引起的)?

unity3d FABRIK 关节运动 算法 2021-10-04