文章目录
- 一、架构(Architecture)
- 1.1 Obi解算器(ObiSolver)
- 1.2 ObiUpdater
- 1.3 ObiActorBlueprint
- 1.4 Obi参与者(ObiActor,如ObiRope等)
- 二、Obi解算器(ObiSolver)
- 2.1 解算器(Solver)组件
- 2.1.1 解算器设置(Solver settings)
- 01 Backend
- 02 Mode
- 03 Interpolation
- 2.1.2 模拟设置(Simulation settings)
- 01 重力空间(Gravity Space)
- 02 重力(Gravity)
- 03 睡眠阈值(Sleep threshold)
- 04 阻尼(Damping)
- 05 世界线性惯性标度(World linear inertia scale)
- 06 世界角惯性标度(World angular inertia scale)
- 06 最大各向异性(Max Anisotropy)
- 07 隐形时模拟(Simulate when invisible)
- 2.1.3 碰撞设置(Collision settings)
- 01 连续碰撞检测(Continuous collision detection (CCD))
- 02 碰撞外边距(Collision margin)
- 03 最大穿透力(Max depenetration)
- 04 冲击波传播(Shock propagation)
- 05 表面碰撞迭代(Surface collision iterations)
- 06 表面碰撞容限(Surface collision tolerance)
- 2.1.4 限制设置(Constraint settings)
- 01 已启用(约束名称旁边的复选框)(Enabled (checkbox right next to the constraint's name))
- 02 迭代(Iterations)
- 03 评估模式(Evaluation mode)
- 04 松弛因子(Relaxation Factor)
- 三、更新器(Updaters)
- 3.1 Obi固定更新(Obi Fixed Updater)组件
- 解算器(Solvers)
- 子步骤(Substeps)
- 3.2 Obi Late Fixed Updater组件
- 3.3 Obi Late Updater组件
- 解算器(Solvers)
- Δ平滑(Delta smoothing)
- 四、参与者(Actors)
由于项目遇到相关问题,固参考Obi官网做了较为详尽的翻译。此文章描述了Obi的架构(解算器ObiSolver、更新器ObiUpdater、参与者ObiActor)之间的关系,并且对解算器组件做了详尽的参数说明,也对列举了三种更新器(Obi Fixed Updater, Obi Late Fixed Updater, Obi Late Updater)进行说明。
一、架构(Architecture)
Obi的核心组件和它们所扮演的角色:
1.1 Obi解算器(ObiSolver)
**求解器(解算器)**是执行物理模拟的组件。求解器暴露了一些全局模拟参数,如重力、惯性尺度或速度阻尼,以及求解器中所有约束的全局参数。每个求解器将模拟它在其层次结构中找到的所有子actor,为此它可以使用多个后端(仅适用于Obi 5.5及以上版本)。
1.2 ObiUpdater
更新器是一个组件,它可以推进一个或多个解算器的模拟,使它们与Unity自己的物理引擎保持同步。Obi包含几种类型的更新程序,以涵盖常见的用例,但如果需要精确控制模拟更新周期,可以编写自己的更新程序。
1.3 ObiActorBlueprint
蓝图是存储一堆粒子和约束的资产。它本身不执行任何模拟或渲染。它只是一个数据容器,不像纹理或音频文件。蓝图是从网格(ObiCloth和ObiSoftbody)、曲线(ObiRope)或材料定义(ObiFluid)生成的。
1.4 Obi参与者(ObiActor,如ObiRope等)
actor(参与者)是在求解器中实例化蓝图的组件。所有的 actors 都必须是解算者(解算器)的子物体。多个参与者可以共享相同的蓝图,实际上,鼓励尽可能多地重用相同的蓝图。actor(参与者)的例子有绳子、旗帜、有弹性的果冻或水发射器。
这是一个带有两个解算器的场景:一个模拟3块相同的布,另一个模拟2条相同的绳子:
每个求解器维护几个列表或每个粒子的属性:位置、速度、半径等。最初,这些列表没有元素。每当向求解器中添加新actor时,将执行以下步骤:
- actor 要求解算器分配蓝图所需的尽可能多的粒子。求解器在其内部数组中维护一个自由索引列表,并为每个粒子分配它能找到的第一个自由索引。这个指标成为粒子的解算指标。当从求解器中移除角色时,在求解器的内部粒子数组中会出现间隙。因此,属于同一个 actor 的粒子可能不会在求解器数组中相邻。如果分配了前194个(0-193)粒子索引,则参与者索引为0的粒子(参与者蓝图中的第一个粒子)可能最终位于求解器索引194中。
- actor 复制蓝图中的所有约束,并更新它们的粒子引用,以便它们指向正确的求解器数组位置。
- 更新求解器中的活动粒子数。
一旦参与者被添加到求解器中,它就会被包含在模拟计算中。
二、Obi解算器(ObiSolver)
ObiSolver组件可以说是Obi中最重要的组件。它负责模拟粒子物理和执行约束。关于解算器,要记住三个重要的事情:
- 它们可以添加到场景中的任何游戏对象中,并且可以在同一个场景中同时有多个解算器。
- 为了更新和渲染,每个角色都需要在其层次结构上有一个求解器。
- 每个解算器都是完全独立于其他解算器的。因此,被不同求解器更新的actor不会相互作用/碰撞。只有同一个求解器中的参与者才会对彼此做出反应。
求解器总是在局部空间进行模拟。这意味着平移,旋转或缩放求解器将严格地将模拟作为一个整体进行转换。
你可以将一定比例的解算器线性/旋转运动以惯性力的形式注入到模拟中。例如,你可能想要控制角色整体运动对服装模拟的影响程度。为此,求解器暴露了两个参数来独立控制线性和旋转惯性力(见下文)。
2.1 解算器(Solver)组件
求解器组件中有4个可折叠面板,每个面板包含影响求解器行为的一个特定方面的参数。
2.1.1 解算器设置(Solver settings)
这些设置控制求解器的内部工作方式:
01 Backend
使用哪个模拟后端。如果任何给定的后端不可用,Obi将尝试返回到Oni后端。
02 Mode
求解器可以在2D或3D模式下进行模拟。在2D模式下,模拟只发生在XY平面上。
2D模式通常伴随着2D碰撞器的使用。但是,为了方便起见,也可以将3D碰撞器与2D模式一起使用。
03 Interpolation
用于渲染粒子的插值模式。没有更快的计算,但 Interpolate 将提供更视觉上令人愉悦的结果。然而,Interpolate会在粒子的实际物理位置和它们被渲染的位置之间引入1帧延迟。当在场景中的其他物体周围使用插值时,请记住这一点。如果你有刚体与Obi相互作用,通常最好对两者都使用插值,或者完全不使用它。
“Interpolate”在慢动作效果中表现最佳,因为它可以避免当Unity的时间尺度小于1时出现卡顿。
请记住,插值引入了1帧延迟。在将actor附加到其他对象时,记住这一点尤为重要。
2.1.2 模拟设置(Simulation settings)
关于外部/内部力的各种全局参数,如重力、阻尼、惯性等参数:
01 重力空间(Gravity Space)
是在求解器的局部空间(Self)还是在世界空间(world)中应用重力。如果设置为“Self”,则重力方向将与求解器一起旋转。
02 重力(Gravity)
在解算器中作用于粒子的重力方向和大小,用解算器的局部空间表示。
03 睡眠阈值(Sleep threshold)
任何动能低于这个值的粒子都会被冻结在原地。当你不想让速度或力的微小变化干扰角色时,这很有用,使它看起来像是在抖动或移动得很慢。如果你想让粒子的位置受到作用在它们身上的任何力的影响,将它设置为零,不管这个力有多小。
与大多数刚体引擎中的休眠刚体不同,休眠粒子不会从模拟中取出,也不会节省性能。他们的位置根本没有更新。
04 阻尼(Damping)
应用于粒子速度的速度阻尼。增加它来减少它们的动能。
高阻尼值可用于模拟水下效果。低非零值(如:0.15)可以在大多数情况下提高模拟的真实感,考虑到空气动力阻力。
05 世界线性惯性标度(World linear inertia scale)
控制求解器变换的世界空间线性惯性有多少应用于粒子。取值范围从0(无)到1(100%)。
包含一块布的移动求解器,其线性惯性刻度设置为1。请注意,当解算器突然停止时,布是如何继续向前移动的,而当解算器恢复运动时,布是如何向后发射的。
06 世界角惯性标度(World angular inertia scale)
类似于前一个属性,但控制角惯性(旋转)而不是线性惯性(平移)。注意离心力和科里奥利力都算在内。
包含一块布的旋转求解器,其角惯性刻度设置为1。注意在旋转时离心力是如何把它举起来的。
06 最大各向异性(Max Anisotropy)
在Obi中,流体粒子的形状可以是椭圆形的,而不是完全球形的。这是为了更好地适应它们所代表的物体的表面,实现更准确的碰撞检测和更平滑的渲染。最大各向异性允许您确定椭圆体的半径之间的最大比率:值为1将强制所有粒子为球形(停用各向异性),大于1的值将允许粒子在更高的最大各向异性下变得更椭圆形。
流体渲染可以从启用各向异性(最大各向异性> 1)中受益匪浅。它将允许您使用较低的流体分辨率并获得更光滑的流体表面。
07 隐形时模拟(Simulate when invisible)
当所有摄像机都不可见时,这个解算器是否应该让模拟继续进行?如果你的模拟需要随时更新,请启用此选项,当场景中存在多个解算器但它们并不总是可见时,请禁用此选项以提高性能。
2.1.3 碰撞设置(Collision settings)
控制求解器的碰撞检测管道:
01 连续碰撞检测(Continuous collision detection (CCD))
在碰撞检测期间用于扩展其边界框的粒子/刚体速度百分比。值为1将使用100%的速度,从而产生完全连续的碰撞检测。值为0将导致纯静态碰撞检测。
02 碰撞外边距(Collision margin)
边缘添加到粒子边界框(CCD扩展后),用于生成接触。在粒子边界框内的任何碰撞器/粒子将被考虑用于接触生成。这个值应该保持相对较低。较大的值将产生更多的接触,这可以提高非常复杂场景中的鲁棒性,但会对性能产生负面影响。
一个移动的粒子和它的边界框(蓝色),它包含了粒子的当前位置和预测位置。边界框由碰撞边界展开。粒子可能与任何与此框相交的对撞机产生接触。
03 最大穿透力(Max depenetration)
使粒子脱离对撞机的最大速度(以米/秒为单位)。这只适用于已经在对撞机中启动物理步骤的粒子。较低的值将轻轻地将粒子从对撞机中取出。高值允许求解器立即将粒子取出,使其“跳”出对撞机。
布从地面内部开始,穿透设置为0.1 m/s,产生温和的碰撞分辨率。
穿透力设置为10米/秒,使其“跳”出地板。
04 冲击波传播(Shock propagation)
高数值会人为地增加支持其他粒子的粒子的质量。使用它可以获得更好的堆叠稳定性。
05 表面碰撞迭代(Surface collision iterations)
为优化表面碰撞而执行的最大迭代量。
06 表面碰撞容限(Surface collision tolerance)
低于此公差阈值,表面碰撞细化将停止。增加一点它可以帮助在平面上获得更稳定的表面碰撞。
2.1.4 限制设置(Constraint settings)
您可以全局地启用/禁用 Solver 管理的所有 actor 的每种约束类型。以这种方式禁用约束(与禁用单个参与者的约束组件相反)将允许求解器完全跳过与特定约束类型相关的任何计算。
例如,如果禁用碰撞约束和粒子碰撞约束,整个碰撞检测管道将被跳过。这允许自定义在引擎盖下所做的工作,并摆脱不必要的开销。
ObiSolver为每个约束类型公开了4个参数:
01 已启用(约束名称旁边的复选框)(Enabled (checkbox right next to the constraint’s name))
这些约束是否进行了任何更新?默认情况下,所有约束类型都是启用的,尽管这很少是您希望用于生产就绪的模拟的。您应该禁用对您的模拟的最终外观不是关键的任何约束。
如果没有参与者使用某些约束组,则它们在启用时不会降低性能。例如,密度约束仅用于流体。因此,如果场景中没有流体发射器,启用密度约束根本不会影响性能。
02 迭代(Iterations)
每个子步骤中应该评估这些约束多少次?较高的迭代次数会使模拟更接近真实解。如果这些约束对您特定的目的并不非常重要,并且您希望获得更好的性能,请将其保持较低。默认值为3。
在某些情况下,将给定约束组的迭代次数提高到3以上是有意义的。例如,使用距离约束迭代计数大于15的绳索并不罕见。
03 评估模式(Evaluation mode)
确定如何执行此类约束。有两种模式:
- 在顺序模式中,所有约束都按照它们被创建的顺序进行评估(这是由每个特定的ObiActor决定的),并且每个约束“看到”之前所有约束所做的调整。这确保了快速收敛,因此您的约束将需要很少的迭代才能看起来很好。然而,当几个约束争夺控制权时,它不是很稳定——它会引入抖动——所以在一些用例中,这种模式不是一个好的选择。它是顺序相关的,所以在低预算的情况下(少量粒子,少量迭代和/或大的时间步),这可以在粒子排列中产生可见的模式。对于那些对技术有点了解的人来说,这是一个高斯-赛德尔类型的求解器。
- 在并行模式下,所有的约束都被评估,但是它们的调整不会立即应用到粒子上。相反,它们被存储,平均,然后最终结果用于调整粒子位置。这产生了一个非常稳定的模拟,即使一次应用了很多约束,但是“硬”约束需要更多的迭代,因为它的收敛速度更慢。它也是顺序无关的,所以它保证了粒子的平滑排列。如果您想以高迭代次数的性能或低迭代次数的质量换取稳定性和平滑性,请使用此模式。同样,对于技术用户:这是类似雅可比矩阵的求解。
并行模式收敛缓慢,并不能保证动量守恒(有时事物可能会获得能量)。因此,在可能的情况下使用顺序模式,而在必要时使用并行模式。
下面的图片显示了一根绳子被拉伸到超过它的静止长度,使用不同的评估模式对距离约束。在顺序模式(左)中,由顺序依赖的评估引起的粒子放置中的团块模式清晰可见。在平行模式下(右图),所有的粒子都是均匀间隔的,但由于收敛速度的降低,绳子会下垂一些。
这是另一个例子:一些刚体在蹦床上。为了可视化的目的,布料的张力被映射到一个颜色梯度上。在顺序模式(左)中,张力在布料表面不均匀分布,导致嘈杂的颜色图案。在并行模式(右)中,张力均匀分布,但由于收敛速度的降低,布料更具弹性。
04 松弛因子(Relaxation Factor)
连续过度松弛(SOR)因子。当试图满足约束时,提高收敛性的一种方法是“过度放松”约束。也就是说,如果一个粒子向左移动2个单位现在可以满足约束条件,为什么不移动3个单位呢?这就是这个因子的作用。1是默认值,它根本不执行过度松弛。2是最大值,它允许你在约束上执行两倍(200%)的放松。高值可用于帮助加速两种模式(顺序或并行)中的任何一种的收敛,但请记住,模拟稳定性可能会降低。小于1的值只会部分地执行约束。例如,松弛系数为0.25的约束将只具有其正常效果的25%。
三、更新器(Updaters)
ObiUpdater 是一个组件,它在执行过程中的某个特定时刻推进一个或多个求解器的模拟。在 FixedUpdate() 期间,您通常希望同步更新求解器模拟与物理系统的其余部分。有时,您可能希望在骨骼动画之后或 LateUpdate() 期间更新物理系统。您甚至可能希望编写自己的更新器组件,以完全控制何时以及如何更新模拟。
通常,您希望在场景中只有一个updater。这允许由updater中的所有解算器调度的任务并行执行。
在你的场景中可以有多个updater,但是你必须避免同一个求解器被多个updater引用,因为这会每帧更新求解器不止一次,导致不可预测的结果。还请记住,未被任何updater引用的求解器将不会更新其模拟。
3.1 Obi固定更新(Obi Fixed Updater)组件
固定 updater 将在 fixeduupdate() 期间更新模拟。这是物理上最正确的方法,也是你大多数时候应该使用的方法。
解算器(Solvers)
此updater选中的解算器列表。
子步骤(Substeps)
更新程序(updater)可以将每个物理步骤分解成多个更小的子步骤。例如,如果Unity的固定时间步长设置为0.02,更新程序中的子步长设置为4,则每个子步将使模拟提前0.02/4 = 0.005秒。像这样在更小的时间块内推进模拟将大大提高精度,但代价是性能。碰撞检测仍然是每一步只执行一次,并在所有子步骤中平摊。
调整子步骤来控制整体仿真精度。如果希望优先考虑某些约束,请调整约束迭代。欲了解更多信息,请阅读有关Obi的模拟方法。
3.2 Obi Late Fixed Updater组件
Obi Late Fixed Updater 将在 WaitForFixedUpdate() 之后更新模拟,一旦对所有组件调用了FixedUpdate(),并且所有设置为 update Physics 的Animators都已更新。在动画师设置为“更新物理”后,使用它来更新模拟。
这种更新器是你大部分时间想要用于角色服装或任何由角色动画驱动的演员的。只需确保你的角色的Animator设置为更新物理!
3.3 Obi Late Updater组件
此更新程序将在LateUpdate()期间推进模拟。这是
高度非物理的,因为它引入了可变的时间步长。只有在不能以固定频率更新模拟时才使用它。有时用于低质量的角色服装,或次要的视觉效果,不需要太多的物理精度。
解算器(Solvers)
此更新程序勾选的求解器列表。
Δ平滑(Delta smoothing)
此更新程序将尝试通过对增量时间应用低通滤波器来最小化使用可变时间步导致的伪影。此值控制此过滤的积极程度。高值将积极过滤时间步长,最小化连续帧上的增量时间变化。值为0将使用这一帧的实际时间增量。
四、参与者(Actors)
Actor可以是绳子、布料等组件。
一块布、一根绳子(Obi Rope)、一个流体发射器或一个软体,它们都是参与者(Actor)。所有参与者都将蓝图作为输入。参与者将实例化包含在蓝图中的信息(粒子和约束),以便求解器可以模拟它。您可以跨多个参与者重用相同的蓝图。
如果您希望将 actor 包含在模拟中,则 actor 必须是求解器的子对象。在运行时,您可以将actor表示为一个新的求解器,或者根据需要将其从当前求解器的层次结构中取出。
作为求解器子程序的流体发射器和软体。
不管你要创建什么类型的 Actor,启动和运行模拟所需的步骤都非常相似:
- 创建适当类型的蓝图资产。生成它,然后根据需要编辑它。
- 创建参与者(actor),并为其提供蓝图。
你可以通过GameObject->3DObject->Obi创建任何 actor。例如,要创建一个布料Actor。或者,你需要进入GameObject->3DObject->Obi->Obi cloth,要创建一个绳子,你需要进入GameObject->3DObject->Obi->Obi rope等等。
当你第一次在场景中创建一个 actor 时,Obi将寻找一个ObiSolver组件来添加这个角色。如果它找不到合适的解算器,它将创建一个。当创建求解器时,它也会自动将其添加到场景中发现的第一个ObiFixedUpdater中。
actor 暴露了一些参数,让你可以修改它的行为(例如,你可以改变撕裂布所需的力,或者柔软体的可塑性)。更改这些参数不会以任何方式影响原始蓝图,只会影响 actor 生成的实例。
转到每个 actor 蓝图页面以了解更多关于特定演员/蓝图的信息:
- 布料
- 绳/杆
- 流体
- 软体
绳:建模为一个粒子链,通过约束将它们连接在一起,迫使它们彼此保持一定的距离(距离约束)。
布:在这里,一块正方形的布被表示为粒子的二维网格,通过距离和弯曲约束连接在一起。
液体排放:产生新的粒子,排斥或吸引周围的其他粒子,试图保持恒定的密度(每体积单位的质量)。
最后提个问题:你们都有什么方法使绳子变为刚性的?类似于钢筋那种不可伸缩的