Unity--Configurable Joint——简单教程,带你入门可配置关节

关节

关节组件将刚体连接到另一个刚体或空间中的固定点,关节施加使刚体移动的力,而关节限制功能可以限制该移动。

就像是动物的关节一样,例如一个关节连接着两个节点,那么其中一个节点的移动或旋转可以带动另外一个与其连接的节点发生相应的改变。

关节赋予刚体以下自由度:
在这里插入图片描述

Configurable Joint

简介

Configurable Joint可配置关节是Unity物理引擎中非常强大的一个部分,该关节包含其他关节类型的所有功能。其它关节包括角色关节 (Character Joint) 、固定关节 (Fixed Joint)、铰链关节 (Hinge Joint)、弹簧关节 (Spring Joint) 。

功能

模拟任何骨骼关节,例如布娃娃中的关节。可以配置此关节以任何自由度驱动和限制刚体的移动。
Configurable Joint可配置关节官方文档

属性

在这里插入图片描述

浅析

1. 锚点、连接锚点和连接体(Anchor、Connected Anchor and Connected Body)

在这里插入图片描述

  • 锚点是相对于本体的位置。
  • 连接锚点是相对于连接体的位置。
  • 连接体必须是刚体。

Unity会尝试通过关节移动对象,直到锚点和连接锚点在同一位置为止。
可以简单的理解为锚点会尽可能地向连接锚点重合(包括position和rotation)。

2. X/Y/Z Motion and Angular X/Y/Z Motion

[图片]

  • X/Y/Z Motion 代表对应轴的位置移动模式,分别有三种模式可选。
  • Angular X/Y/Z Motion 代表对应轴的旋转移动模式,分别有三种模式可选。
    在这里插入图片描述

这里,我们涵盖了三个相似的移动属性:xMotion, yMotion, zMotion。

假设连接锚点的世界坐标是(1, 2, 3),锚点的世界坐标是(-1, -2, -3)。任何关节(Joint)的主要目标就是使锚点和连接锚点处于同一位置,这坐标的位置关系明显与我们的目标不符。想要使它们符合预期,关节就要去改变锚点(anchor)或者连接锚点(connectedAnchor)的位置。我们要么使本体(body,就是绑定Configurable Joint的对象)移动(-2,-4,-6),要么使连接体(connected body)移动(2,4,6),又或者两者都往它们之间移动。当然,你也可以通过微调移动属性(motion properties)来纠正这个偏差(这里的偏差就是指锚点和连接锚点的差值)。

对应Motion的例子

下面这个图是Configurable Joint的部分参数。
在这里插入图片描述
下面这个图是两个Cube的位置
下Cube(统称为Cube1)挂载了Configurable Joint,Connected Body设置为上Cube(统称为Cube2)
[图片]

例子解析

由于Y轴的Motion是被Locked住的,所以锚点和连接锚点的Y轴的位置必须要一致,所以下面的方块就被强行拉上去了。

重点!关于Motion的一些小细节。

现在我们修改一下下面的Cube1的位置,把它的Z轴方向-2。现在是这样的。
[图片]
Motion等一系列条件还是和上一个例子是一样的。
[图片]

结果

我们发现,Cube1并没有被直接拉到上面,而是绕X轴旋转了一个角度。

这里有一个非常重要的细节,在这之前,我们先了解另外一个东西。

坐标轴(Axis)

线性运动(Linear Motion)使用的是本地坐标系,而不是世界坐标系。 这就意味着,我们如果想实习第一个例子的效果只有在所有坐标轴上旋转都为0时才有效。

解析

尽管我们的立方体没有移动一点,但是绕着X轴发生了旋转。当你沿Y轴移动立方体就能纠正偏差,为什么要绕X轴旋转来纠正误差呢?

如果你把图片拉近来看,你会发现这个偏差其实已经完全被纠正了——把锚点和连接锚点放到我们新的坐标系中,Y的值已经一样了(X轴的旋转是自由的,不会纠错,只有Y轴锁定会完全纠错)。
[图片]

但是,为什么关节(Joint)会这么做?再扩展一下,为什么关节们(Joints)要这么做?

假设我们在(1,2,3)有一个连接锚点,以及在(-1,-2,-3)有一个锚点。
一个解决这种情况的合理方式是:我们的本体(body)移动(2,4,6)。但其它的解决方案也可能是本体移动(1002,1004,1006),连接体(connectedBody )移动(1000,1000,1000)。很明显,这样也可以使锚点和连接锚点最终停在相同的位置,使偏差得到完全纠正。这是一个正确的结果,但这样合理吗?明显不合理。那么在关节世界里,怎么才是合理的?

答案很简单——花费最小的能量去做你需要做的事情。例如,移动(2,4,6)就比移动
(1002,1004,1006)节能得多。同理,你稍微转个身,比起移动更节能得多,不是吗?就是
这么简单,如果可以,关节会选择旋转它,而不是移动它。

实战
2.1 Y轴方向进行拉伸
分析
  1. 首先物体只是在Y轴方向上进行位移,所以Y Motion要设置为Limit。
  2. Linear Limit Spring 的 Spring 也要设置,不然没有弹力。
  3. Linear Limit 的 Limit 距离也要设置。
  4. X/Z Motion和Angular X/Y/Z Motion都为Locked。
  5. 重要的是挂载了Configurable Joint的物体的Rigidbody一定要开启重力,即勾选Use Gravity,不然物体不会动。
    [图片]

[图片]

3. 线性限制(Linear Limits)

在这一部分将讨论移动属性(Motion)设置成受限制( Limited)的情况。这个选项告诉关节在对应的轴上允许一定的偏差存在。这个最大偏差的绝对值可以通过线性限制(linearLimit)属性指定。
这个属性结构体包含三个字段:

  • limit:限制,允许最大的偏差值。移动限制的边界,可以理解为可移动偏离关节原点的最大距
  • 离。
  • bounciness:弹跳强度,决定当位置超出限制时是否反弹。值的大小确定反弹的力度。
  • contactDistance:碰触距离,可以防止逼近极限时突然停止。(Unity官方解释为——确定解算器可“看到”关节限制的空间前方的距离。)

它会应用于所有受限制的(Limited)的轴向上。想象一下,我们把限制设置成3。如果只有一个轴向是受限制的,其它轴向是锁定的(Locked),那么对象将在受限制的轴向上来回不超过3个单位的移动。同理,两个轴向受限将提供一个圆形移动区域;而三个轴向都设置成受限制的话,将在一个半径为3的球形区域移动。
[图片]

移动属性在X轴、Y轴上受限制而在Z轴方向锁定,则锚点可以在绿色圆形区域内的任意位置。

默认情况下,到达线性限制(linear limit)阈值会立即停止物体移动。如果你想它有弹跳效果,你可以使用反弹(bounciness) 属性。设置后,本体(body)到达极限时会以一定的速度(velocity = velocityAlongAxis * bounciness)反弹。当设置反弹强度为1时,几乎不会有能量损耗。(但经过测试,每次撞击极限都会有一定的能损。)

你也可以通过线性限制弹力(linearLimitSpring)属性给本体添加一个虚拟弹力。通常,你可以通过弹力(spring)属性设置弹力的刚度,通过阻尼器(damper)属性设置阻尼比。

注意:一旦设置了线性限制弹力(即 LinearLimitSpring下的 spring != 0)之后,线性限制(LinearLimit)下的反弹属性将完全失效。因为它们无法一同运作。
在这里插入图片描述

从左到右,常规设置线性限制;线性限制+反弹;线性限制+弹力;线性限制+ 弹力+阻尼
[图片]

实战
3.1 绕某一点旋转,并且物体本身可以旋转(钟摆)
分析
  1. 首先物体是绕着X轴旋转的,所以X轴的旋转要设置为Free,其他的旋转Mode可以随意,这里就设置为Locked了。
  2. 其次锚点和连接锚点的Z轴距离是需要限制的(本地坐标系,非世界坐标系),所以Z Motion要设置为Limited,并且要设置Linear Limit的Limit数值。
  3. 最后锚点和连接锚点的Y轴距离是一直不变的,也就是被锁住了,所以Y Motion要设置为Locked。
  4. 重要的是挂载了Configurable Joint的物体的Rigidbody一定要开启重力,即勾选Use Gravity,不然物体不会动。
    [图片]

[图片]

3.2 绕某一点旋转,并且物体本身不可以旋转

[图片]

分析

  1. 首先物体是绕着X轴旋转的,所以X轴的旋转要设置为Free,其他的旋转Mode可以随意,这里就设置为Locked了。
  2. 其次锚点和连接锚点的Z轴距离由于发生位移了,所以是需要限制的(本地坐标系,非世界坐标系),所以Z Motion要设置为Limited,并且要设置Linear Limit的Limit数值。
  3. Y Motion同理。
  4. X轴并没有发生位移,所以需要锁住。
  5. 重要的是挂载了Configurable Joint的物体的Rigidbody一定要开启重力,即勾选Use Gravity,不然物体不会动。

4.角度偏移(Augular movement)

可配置关节(ConfigurableJoint)也提供了很多参数让你可以控制物体的旋转。
  在初始化期间,Unity关节会尝试保留本体与连接体之间的旋转差异。这意味着,你旋转其中一个物体,另一个物体也会跟着旋转——保持相同的旋转差异。

角度的偏移通过x轴角度偏移(angularXMotion), y轴角度偏移(angularYMotion), 以及
z轴角度偏移(angularZMotion) 属性控制。你可以决定每一个轴向上出现偏差时的行为——设置成Free可以完全忽略偏差;设置成Locked可以完全纠正偏差;设置成Limited 对偏差作一定限制。
  另外,线性限制(linearLimit)、线性弹力限制(linearLimitSpring)属性控制着所有轴向的线性
偏移。而角度偏移的限制更灵活一些,它有6个属性来控制:

  • lowAngularXLimit
  • highAngularXLimit
  • angularYLimit
  • angularZLimit
  • angularXLimitSpring
  • angularYZLimitSpring

当然上面的参数的含义已经不言自明了。
假设初始角度是45度,最高限制是30度,最低限制是-90度,那么,你的本体(body)将可
以围绕轴向(axis)在[15, 135] 度的区间内任意旋转。
X轴的旋转限制都有弹跳(bounciness )属性。当然,最低X轴角度偏移限制的弹跳
(lowAngularXLimit.bounciness)会同时作用于两个限制属性,而最高X轴角度偏移限制
(highAngularXLimit.bounciness)会被忽略。X轴角度限制弹力(angularXLimitSpring )
会非常好的符合你的期望。但要注意,它比所有的弹跳(bounciness )属性的优先级都要高,也就
是设置了角度限制弹力后,弹跳属性就无效了。
[图片]

从左到右,依次设置bounce = 0;bounce = 1;设置限制弹力。
  其它轴的自由度没那么高,你不能分别控制最高、最低限制。
  例如,设置y轴角度偏移限制为45度,等价于最高限制为45度,最低限制
为-45度。
  你对每个轴都可以使用弹力(spring)属性。再次说明,一旦使用了弹力属性。弹跳属性
(angularYLimit.bounciness / angularZLimit.bounciness)将会被忽略。

5. 线性驱动器(Linear Drives)

也可以通过驱动属性—— 目标位置(targetPosition), x轴驱动(xDrive), y轴驱动
(yDrive), z轴驱动(zDrive)——添加三个方向的弹力。

弹力将作用于本地轴向方向。并通过目标位置属性(targetPosition)定义弹力作用的目标位置。

前提是对应轴向的Mode要设置为Limited。

例子
[图片]

[图片]

  • Y Motion的Mode为Limited,说明Y方向上需要被限制。
  • Linear Limit中Limit参数为4,代表是在位移上,锚点和连接锚点的距离要必须要限制在4以内。
  • Target Position中参数为(0,-2,0),意思是连接锚点需要在锚点的(0,-2,0)上。
  • Y Drive的Position Spring参数为5,代表Y方向上的弹力为5。

最终结果如下:
在这里插入图片描述
我们可以看出锚点的位置在连接锚点的正上方,而且在正上方2个单位处,也就是Target Position的(0,-2,0)。
注意:驱动属性(drives)会配合运动属性(motion)工作,但不会覆盖运动属性。即运动
属性的优先级高于驱动属性。例如,你设置目标位置x轴(targetPosition.X)的值
为-10,以及x轴驱动的弹力(xDrive.positionSpring)为50 。但你把X轴的运动属性
(xMotion)设置成了锁定的(Locked)。那么,你的这个驱动就不会生效。
一些关节需要保持对象以恒定速度移动,例如转动风扇叶片的旋转电机。使用 Target Velocity 和 Target Angular Velocity 属性可为此类关节设置所需的速度。

可以通过目标速度(targetVelocity)属性,给关节添加一个想要的速度。 与目标位置
(targetPosition)相似目标速度应用在驱动弹力(drive.positionSpring)和阻尼
(drive.positionDamper)不同时为0的情况。当驱动弹力不为0时,弹力会尝试把物体拉回目标位置,最终会达到平衡而停止移动。

设置了目标后,X, Y, Z Drive_ 和Angular X/YZ Drive(或者是 Slerp Drive)属性可以指定用于将关节推向目标的作用力。驱动的 Mode 属性选择关节是否应该寻找目标位置和/或速度。在寻找目标位置时,Position Spring 和 Position Damper 的工作方式与关节限制相同。在速度模式下,弹簧力取决于当前速度和目标速度之间的“差距”;阻尼器有助于速度稳定在所选值,而不是在该值周围无限振荡。例如,XDrive 力的公式为:

force = PositionSpring * (target position - position) + PositionDamper * (targetVelocity - velocity)

因此,力会根据当前值与目标值之间的差值成比例增大,并根据当前速度和目标速度之间的差值成比例减小阻尼。Unity 会将力施加到位置驱动和旋转驱动。
Maximum Force 属性用于最终微调,无论关节距其目标有多远,均可防止弹簧施加的力超过限制值。这样可以防止远离目标的关节快速以不受控制的方式将对象拉回。
在使用任何驱动力(下面描述的 Slerp Drive 除外),关节都会在每个轴上单独将力施加到对象。
举例来说,可实现一个航天器,使之具有较高的向前飞行速度,但在侧向转向运动中具有相对较低的速度。

6. 角度驱动器(Angular Drives)

如果选择XYAndZ,则会创建两个弹力(分别由AngularXDrive 、AngularYZDrive属性定义)。如果你选择Slerp,则只会创建一个弹力(由SlerpDrive定义)。
有两种方式可以实现旋转

  1. 第一是应用一个弹力,直接把本体(Body)旋转到目标旋转属性位置。
  2. 第二是应用两个弹力,其中一个沿着x轴,另外一个去调整剩下的旋转差异。
    下图显示了两个粗略近似的结果,你只需要选择你认为合适的旋转驱动模式(RotationDriveMode)。
    [图片]

左边使用X And YZ模式,右边使用Slerp模式。可以得到几乎一样的结果。

和线性驱动类似,目标旋转角速度(targetAngularVelocity)可以给角度驱动添加动力。
  目标旋转角速度实现上就是对象的旋转角速度,这和目标速度(targetVelocity)属性情况相反。

7.其他剩余的属性

  • Projection Mode:此属性定义了当关节意外地超过自身的约束(由于物理引擎无法协调模拟中当前的作用力组合)时如何快速恢复约束。选项为 None 和 Position and Rotation。
  • Projection Distance:关节超过约束的距离,必须超过此距离才能让物理引擎尝试将关节拉回可接受位置。
  • Projection Angle:关节超过约束的旋转角度,必须超过此角度才能让物理引擎尝试将关节拉回可接受位置。
  • Break Force:如果通过大于该值的力推动关节超过约束,则关节将被永久“破坏”并被删除。仅当关节的轴为 Limited 或 Locked 状态时,Break Torque 才会破坏关节。
  • Break Torque:如果通过大于该值的扭矩旋转关节超过约束,则关节将被永久“破坏”并被删除。无论关节的轴为 Free、Limited 还是 Locked 状态,Break Force 都会破坏关节。
  • Enable Collision:启用此属性可以使具有关节的对象与相连的对象发生碰撞。如果禁用此选项,则关节和对象将相互穿过。
  • Mass Scale:要应用于刚体反向质量和惯性张量的缩放比例,范围是从 0.00001 到无穷大。当关节连接质量变化很大的两个刚体时,这很有用。当连接的刚体具有相似的质量时,物理解算器会产生更好的结果。当连接的刚体的质量不同时,将此属性与 Connect Mass Scale 属性一起使用可施加假质量,使它们彼此大致相等。这样可以产生高质量且稳定的模拟,但会降低刚体的物理行为。
  • Connected Mass Scale:要应用于连接的刚体的反向质量和惯性张量的缩放比例,范围是从 0.00001 到无穷大。

猜你喜欢

转载自blog.csdn.net/qq_52855744/article/details/125446959