Optimize GameObject选项对骨骼Transform的影响

一、问题描述

相同的角色FBX,一个使用Optimize GameObject选项并暴露相应的骨骼,一个不使用,分别创建各自的Prefab,播放相同动画后,发现同一骨骼的朝向不一致(但位置是一致的)。


二、问题复现

我们使用研发团队提供的Package中的模型,复现了该问题。播放相同动画时,sk_palm_I的朝向如下图:

请输入图片描述
左:使用 Optimize, 右:不使用 Optimize


三、问题分析

我们首先进行一系列实验,试图从例子中发现一些有用的线索。

  1. 我们将更多的骨骼暴露出来,来看是否所有的骨骼朝向都不相同。结果发现,朝向不同的骨骼只是个例,进而发现sk_palm_I这根骨骼不存在对应的动画曲线,并且没有蒙皮对应的顶点。暴露其他没有动画曲线和蒙皮顶点的骨骼,发现骨骼朝向也不相同。

  2. 再来对比骨骼的朝向,发现不开启Optimize选项的sk_palm_l的transform.rotation(相对父骨骼)保持不变,手动将其设为(0,0,0)后朝向与开启Optimize选项的sk_palm_l朝向一致。因此,我们推测Optimize选项后无动画的骨骼的Rotation被归零,在其他无动画的骨骼上得到验证。

  3. 发现朝向不一致问题的角色使用了Humanoid模式,将其切换至Generic模式观察骨骼朝向。然后发现,在Generic模式下,不管骨骼有无动画曲线,其开启Optimize前后的朝向都是一致的。这说明朝向不一致问题只出现在Humanoid模式下。

通过这些实验,可以得出骨骼朝向不一致的条件:Humanoid模式,骨骼没有对应的动画曲线和蒙皮顶点。而开启Optimize后的朝向是开启前对应骨骼的Rotation归零后的朝向。

参阅 Unity关于Humanoid 以及 Optimize选项的相关描述:
Humanoid会将骨架(Skeleton)信息映射到另一个空间(通过Configure Avatar)。开启Optimize选项后,Unity更新骨骼矩阵时将不再考虑场景中骨骼Transform,而是直接使用Internal Skeleton。

综合上述这些信息,我们推测Humanoid的映射过程中骨骼Transform信息发生了变化。骨架映射可以在Configure Avatar中设置。下图验证了我们的想法:
请输入图片描述

在映射时,sk_palm_I的Rotation已经归零。

发现了问题原因,解决方法就很明了,在映射时修正Rotation信息。通过Pose->reset,所有骨骼的Transform就会与原始骨骼的Transform一致。然后再Enforce T,来进行映射。之后开启Optimize GameObject前后的骨骼朝向基本一致。


四、结论

Pose->Biped Pose(默认)会把所有不带动画、没有蒙皮顶点且不在Muscle中的骨骼的Rotation归零,所以对于类似该案例中的这类模型,映射时需要Reset。这个问题也验证了在开启Optimize GameObject之后,场景中的骨骼Transform信息不再影响到骨骼矩阵运算,也就省略了Mono到Native的信息传递,因此会使骨骼矩阵运算的速度得以提升。所以建议开发团队尽量地开启该选项。






原文出处:侑虎科技
本文作者:admin
转载请与作者联系,同时请务必标明文章原始出处和原文链接及本声明。

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEditor;public class SetAndProducePrefab : Editor{ [MenuItem("XSJArtEditorTools/ʾ一键设置并打包")] static void TempFunc() { GameObject models = GameObject.Find("Models"); if (models) { GameObject test = GetChildObject(models, "Test"); GameObject[] selectedObjs = Selection.gameObjects; //如果在Project栏目中选中了文件 if (selectedObjs != null) { foreach (GameObject obj in selectedObjs) { //写逻辑判断如果不是动画文件的FBX,即判断命名中是否有@字符 if (obj.name) Debug.Log(obj.name); obj.transform.parent = test.transform; } } //如果选中的是文件夹且命名为Fbx(不分大小写) else if (Selection.gameObjects) { //遍历文件夹的直接子目录,找到其中所有的FBX资产,对资产进行设置,不要管该文件夹目录下其他文件夹中的资产 } Selection.objects = selectedObjs; } } static GameObject GetChildObject(GameObject parent, string name) { GameObject res; Transform T = parent.transform.Find(name); if (!T) { res = new GameObject(); res.name = name; res.transform.parent = parent.transform; } else { res = T.gameObject; } return res; } //功能为对FBX文件的rig进行设置,设置其animation type为humanoid,avator Definition可自定义,其他保持默认 private SetFbxRig(GameObject fbxModels, String avatorDefinition) { } //功能为对FBX文件的Materials进行设置 private SetFbxMaterials(GameObject fbxModels) { }}这是我正在开发unity的一个插件,该插件用于调整导入的仍于资产管理器中的FBX资产的设置,请你参考我的注释实现我的功能
07-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值