
上次我们说到在 IKinema 中添加自定义模型。方法很简单,就是利用运行时重定向,这次为大家介绍一下具体做法。
Unity 中的重定向(retargeting)大家应该不陌生,重定向使得 Humanoid 模型间可以共享骨骼动画,大大降低了动画的制作成本。但是 Unity 系统的重定向是基于文件的,对于我们使用 Orion 来说,我们需要在 IKinemaMale 模型获得动作信息的同时,将这些信息应用到我们自定义的模型上,这就需要我们在运行时进行重定向。
首先我们需要搞清楚的是,在重定向时发生了什么。Unity 系统中如何实现重定向我们无从得知,而从一段 UE4 的官方视频中,我们可以得到蛛丝马迹:重定向时,(UE4)复制了各关节的旋转角度,想来 Unity 应该也类似。这其实不难理解,因为人的骨骼关节不能位移只能旋转,所以可以忽略位移信息。同时,即使两个人的骨骼比例相差很大,如果他们的每个关节都进行了同样角度的旋转的话,那他们的身体姿势应该也是相同的。所以我们需要做的,就是在运行时,将 IKinemaMale 的各个关节的旋转角度复制到我们的模型上,我们的模型就应该和 IKinameMale 做出同样的动作。这样我们就可以在动捕中用到我们的自定义模型了。
知道了如何重定向,我们来看看在 Unity 中的实现。Unity 内部使用四元数进行旋转运算。根据上面的叙述,我们知道涉及两种运算。一种是四元数相减,即我们需要在运行时将源模型某个关节的所处角度减去该关节的初始角度,得到它的旋转量。另一种当然是四元数相加,我们需要将旋转量,加到目标模型的对应关节上。在四元数中,计算 A 与 B 的差的运算为 A * Inverse(B),而计算 A 与 B 的和则为 A * B。
实际代码如下。
using
代码主体就是在 Start() 中记录下各关节初始角度,然后在 LateUpdate() 复制旋转角度。
为了测试这段代码,我们可以在商店中下载 RCP - Caucaisan Character Models。我们将用到其中的 CaucasianMale 模型。之所以选这个模型,是因为它是 AssetStore 中少数几个免费的、binding pose 为 TPose 的模型。如果你想使用非 TPose 的模型,则需要在在取得初始角度 SetJointsInitRotation() 之前进行一次校正,这里就略过了。
将 CaucasianMale 加入场景,添加我们的组件,srcModel 置为场景中已有的 IKinemaMale。
启动 Orion,就能看到两个模型共舞了。
需要指出的是,上述代码主要演示骨骼旋转角度的复制,在实际使用中,我们还需要考虑模型脚部着地,是否为 root motion 等情况,这里就不展开了。
以上就是在 Unity 中进行运行时重定向的方法,至少两周前我还是这样想的,直到发现了 HumanPoseHandler。
根据文档,HumanPoseHandler 是
A handler that lets you read or write a HumanPose from or to a humanoid avatar skeleton hierarchy.
简直就是为重定向而生的。于是我们的代码,由,
变为
using
代码量减少很多,而且重要的是我们可以不用关心四元数的取逆与交换律了。当然,用四元数处理的好处在于我们可以在 UE4 中如法炮制,因为据笔者了解现在 UE4 中还没有类似 HumanPoseHandler 的功能。
总的来说,运行时重定向有两个好处,其一,是在 IKinema Orion 这种只能对预设模型进行动捕的系统中,也能实时用上我们自己的模型。其二,即便不用 Orion,而是使用 FinalIK 之类的动捕方案,对于身体比例与常人相差较大的模型,如果直接在其上套用 IK,可能很难得到令人满意的结果,这时,就可以选用正常的人型模型进行 IK,同时将结果重定向到目标模型上去。比如下面的动画所示。
https://www.zhihu.com/video/1147614851324076032
在这里我们使用的是 FinalIK 进行全身动捕。图左的皮卡丘直接进行 IK,中间的皮卡丘,则是通过右侧人型模型进行 IK 之后,重定向之后的结果。可以看到中间的皮卡丘姿势更加自然,穿模现象也少。
最后附上代码方便取用。
https://github.com/fengkan/RuntimeRetargeting