当3dMax遇上Unity3d

您所在的位置:网站首页 玻璃瓶生产原理 当3dMax遇上Unity3d

当3dMax遇上Unity3d

2023-03-26 11:29| 来源: 网络整理| 查看: 265

0.前序

自己是一个使用Unity3d的游戏制作者,学习3dMax也是为了能将FBX模型导入Unity里进行使用,而不是为了一张渲染图

那么在模型导入的前后,都需要注意些什么,才能导出正确的,方便使用的模型呢?

自己的一点总结和分享,之后的学习过程中遇到了新的问题,有了新的总结,也会回来这里更新这篇文章,算是当作一个记录吧,知乎的文章发布之后还能能反复编辑也是很赞啦

也欢迎dalao留言指正,或是赐教一些我不知道的点,鄙人先谢为敬

以下要点可能比较散乱且不分先后,针对3dMax->fbx->Unity3d的资源传递流程,仅个人习惯总结不代表行业标准

最近的一次更新记录:

为了节约篇幅,我们只会在这里展示最近的一次更新记录,本文在初次完成后的所有更新记录会被记录在评论区中

2022/05/01 更新

距离这篇文章发布已经过去三年了

最近也是一直在做土木这边的毕设,也有在学动画,数学相关的一些东西,但实在没精力发文

趁着五一假期来更一下有关转轴布置的问题,详见 3.4 节转轴的精确布置

顺带给这篇文章打一下目录索引

1.转换多边形导出与回导入解析检查---1.1 转换为多边形/网格再导出

3dsMax提供了很多修改器让我们快速建立多边形网格的大型,例如挤出、放样、倒角剖面、车削,而当我们直接导出这些修改器生成的模型时,3dsMax会给出以下警告

“该模型可能在某些环境下不被正确的渲染”

这是由于在导出时3dMax需要将这些修改器的效果,转换为网格进行导出

而这个转换可能导致法线翻转,平滑组改变等等问题,以至于导出结果与我们当前视口中预览的效果不符

因此我们应当在导出模型前,应先转换为可编辑多边形/可编辑网格,检查效果,修正错误

---1.2 回导入解析检查

我们需要在导出fbx后,将fbx导回3dMax中解析,检查模型的效果

这称之为回导入解析检查,我们导出的fbx被应用到Unity之中时,也是一个Unity对fbx解析的过程

模型从创建到应用是经历了 Max场景中建模--->模型导出为fbx--->Unity解析fbx应用模型 这样的一个过程

对fbx进行解析得到的效果有可能与我们在Max中建模视口预览的效果不符

因此将fbx导回3dMax中进行解析,就可能发现一些原先观测不到的错误

例如:

旋转问题:

例如这样的一个摆球动画的模型,在Max中是完全正常的但我们导出fbx之后,应用到Unity之中会发现这个摆球的Base旋转坐标多了180度的旋转事实上如果我们将导出后的fbx重导入回3dMax中进行检查就可以发现这个错误并予以修正

修正错误后,重新导出fbx,再一次回导入检查,直到我们在Max中导入fbx解析效果符合预期,这个fbx才可以被应用到Unity之中

我们修正了错误重新导出fbx,回导入检查效果无误,没有错误此时模型导入到Unity中应用,可以看到没有任何问题

针对蒙皮-骨骼动画根节点位差问题:

另一种情况是针对蒙皮-骨骼动画,没有遵守标准工作流程,在蒙皮之后移动了骨架的根节点,导致骨架根节点0帧位置与蒙皮时的位置出现位差,原工程中制作动画一切表现正常但导出FBX后就会出现这种网格没有蒙在骨骼上,位差被表现出来,并且网格产生扭曲的问题

关于这种情况的修正可以参阅这篇文章

2.模型尺寸与缩放问题---2.0 关于模型尺寸的基础理论

渲染在屏幕上模型有多大?

模型在游戏世界中的大小这取决于:模型网格的坐标尺寸,模型物体的缩放尺寸,模型空间的物理单位尺寸,游戏世界的物理单位尺寸,游戏场景的解析尺寸

坐标尺寸是模型网格的固有属性,它是模型空间下,网格顶点的位置坐标,是记录在FBX模型文件中的网格顶点信息,是通过DCC建模时,我们所调整的东西

缩放尺寸,描述模型空间相对于游戏世界空间的缩放比例,缩放尺寸是记录在物体Transfom矩阵中的,受到FK正向运动效应的影响,父物体的缩放会影响子物体相对于世界空间的缩放

物理单位尺寸描述模型空间/世界空间,每1单位坐标尺寸对应多长的物理距离。游戏世界的物理单位尺寸取决于游戏引擎的设置,通常是固定的。模型空间的物理单位尺寸,取决于DCC软件的环境设置,为了更好的建模不同尺寸的物体,通常是可调整的

游戏场景的解析尺寸,描述游戏场景中的摄像机在以怎样的坐标尺寸解析游戏场景,将游戏世界的坐标尺寸转换到屏幕空间上。解析尺寸本质上,取决于模型与摄像机的相对位置,以及摄像机的参数(摄像机投影矩阵)

网格在模型空间的坐标尺寸*模型空间物理单位尺寸 = 网格的物理尺寸

\frac{网格物理尺寸}{世界空间物理单位尺寸} * 缩放尺寸 = 网格在世界空间的坐标尺寸

模型在世界空间的坐标尺寸 * 解析尺寸 = 网格在屏幕上渲染的尺寸

---2.1 模型的尺寸规范

3D游戏中,不同物体间会有复杂的父子关系嵌套,形成父子关系树

这种父子关系嵌套会带来FK正向运动效应,父物体的位移/旋转/缩放会影响子物体相对于世界的位移/旋转/缩放

父子关系树不仅要在游戏运行前,设计摆放游戏场景,搭建游戏人物时进行设置,还需要在游戏运行中动态的被更新

针对模型的尺寸大小,为了保证在任意父子嵌套下,模型在世界中的尺寸不受影响

我们在建模时不能通过缩放来调整模型的尺寸,所有模型导出时都应处于无缩放的状态(XYZ100%缩放),并表现出正确的物理尺寸

---2.2 Unity的物理单位尺寸与模型的尺寸要求

Unity中物理单位尺寸默认是1m

也就是说:

Transform中的1个Position单位坐标对应1m的物理长度

Unity Scence窗口中参考线中的最小的方格边长是1m的物理长度

并且Unity中的Box,默认状态是1m棱长的立方体网格

图左正方体是Unity中创建的,图右正方体是来自3dMax中导出的棱长为1m的正方体(两者大小一样)

通常游戏中一个正常的人物模型(不考虑特殊Boss怪物,设定需要的缩放等情况)对它在Unity世界中的的物理尺寸参照如下(两种):

---1.胶囊替代:通常3d游戏中一个正常的人物模型大小相当于Unity中创建的一个默认胶囊体的大小,经常在模型师未给出人物模型情况下使用一个默认胶囊体暂时替代人物模型

---2.棺材参照:通常3d游戏中一个正常的人物模型应能够应被放置进一个底面积 1m^2 高度2m的长方体(棺材)内,也就是将Unity中创建出的两个默认Box叠放在一起

Unity中的PhyX物理系统,也大致按照m为数量级进行物理模拟

过大或是过小的物理尺寸,都会对物理系统的模拟产生影响

---2.3 3dsMax的尺寸设置与控制

包括3dsMax在内的大多数DCC软件,物理单位尺寸都是可调整的,以便于建模不同大小的物体

为了能够建立出物理尺寸正确的模型,在建模前,我们就需要检查/设置Max中的系统单位它决定了我们在Max中使用的1个单位坐标长度对应的物理长度

这里的厘米就是物理单位尺寸,决定了当前Max世界1单位坐标尺寸对应的物理尺寸长度

在导入模型时,Unity会根据模型文件中标记的物理单位尺寸以及自身的物理单位尺寸,对模型空间下的坐标尺寸进行解析,转换到游戏世界中的坐标尺寸,转换后会维持模型物理尺寸的不变性

Max在导入fab时,如果是转为可编辑多边形/网格进行导出,模型同样会维持原先的物理尺寸的不变性

(如果是长方体,球体这类基本参数形体,不转换为可编辑多边形导出,导入后会维持尺寸参数/数值的不变而不是原先物理尺寸的不变)

我们还需要保持考虑文件中的系统单位勾选

从而在我们打开.max场景时,如果原先场景中的系统物理尺寸和当前Max设置的系统物理尺寸不相同,会出现这样的提示

选择按系统单位比例重缩放文件对象,会将.max场景中的物体进行尺寸数值的调整(不是通过物体级别的Scale调整),将场景中的模型依照之前的物理尺寸大小,呈现在当前的场景中

选择采用文件单位比例,则会替换当前的系统物理尺寸为场景/文件的物理尺寸

如果你在调整模型尺寸时存在疑惑,那么你可以参照当前的单位尺寸,去创建一个长方体,并将其设置为之前提到的参照棺材的尺寸,以此为参照进行模型的尺寸设定/检查

如图我们创建了一个长方体棺材去检查柜子的尺寸是否正确

一个人物模型的尺寸参照这个长方体棺材的大小,对比这个长方体棺材,结合真实世界的物理尺寸,以及游戏的设定要求,我们就可以对其它模型进行尺寸的调整/检查---2.4 Max建模时正确的尺寸调整方法

我们在建模时,不能通过物体的Scale缩放去调整模型的尺寸/比例

不只是在对接Unity时有这样的要求,不使用物体的缩放调整尺寸/比例本身就是建模时的一种规范

对于模型的尺寸,我们需要将调整植入到顶点中即调整模型在Max世界的坐标尺寸进而调整模型的物理尺寸,而不是在物体级别Transform矩阵中进行调整,可以采用下面的方法进行调整:

可以通过长方体/球体/圆形本身就有的参数设置进行调整

通过参数形体自带的尺寸参数进行调整

转为可编辑多边形/网格,在元素子层级下对物体进行缩放调整,此时尺寸缩放是被植入到了顶点中

同样的,在元素子层级下进行的旋转/移动也都会被植入到顶点中

如果我们不经意的使用了物体缩放进行了尺寸调整,我们可以通过重置变换来进行修正

选中物体,实用工具---重置变换---重置选定内容

使用重置变换前应断开所有子物体,并且还需检查子物体的缩放是否均为100%对有缩放的子物体也要进行重置变换

此时物体会被添加一个X变换命令,物体的Scale缩放会被重置为1,物体的世界朝向/渲染会被清0,物体之前的Transform旋转/缩放产生的影响都被植入到了顶点中

我们可以进入到X变换命令的Gizmo子层级中对物体进行缩放,旋转调整,缩放渲染的效果同样是植入到顶点中,并不会对Transform矩阵产生影响

调整完成后我们右键物体转换为可编辑多边形/网格,或是塌陷X变换命令

调整物体轴心的朝向时会发现物体产生了诡异的变形,这是由于物体进行了XYZ轴不等的Scale缩放导致的,同样可以通过重置变换,将缩放植入到顶点中,之后再调整轴心朝向来解决

---2.5 如果模型尺寸错误Unity中的补救办法

使用导入fbx模型Inspector编辑面板 Model->Scale Factor 进行调整

默认Scale Factor为1,模型的原尺寸*Scale Factor作为模型Scale为1时表现出的大小,也就是模型的物理尺寸

我们可以通过Scale缩放将模型尺寸与游戏场景适配,之后将Scale数值填入到Scale Factor中,从而改变模型的物理尺寸

但这只作为最后手段,使用Max的模型师应按照游戏需要模型尺寸进行建模,出现这种情况就已经给使用Unity的开发者带来了麻烦

---2.6 模型应用到Unity之后的默认缩放植入

一个重点问题,作为Unity的使用者你在应用模型时可能会发现这样的情况:

我们将一个场景模型应用到Unity场景中,可以看到模型默认有一个30.48的缩放

这里必须XYZ的默认缩放量必须都是一致的,否则就需要在Max中重置变换再导入模型

请注意,我们在3dMax中建模时就已经考虑到了模型的尺寸大小问题,我们放入一个胶囊体进行比对会发现,场景在模型默认缩放下,尺寸是正确的

前面有提到Unity中默认胶囊大小等同于一个人物的尺寸大小,这里用胶囊比对场景尺寸会发现场景尺寸在默认缩放下是正常的

这里模型会有一个默认的缩放值是因为Max和Unity中的物理单位尺寸的不同导致的(Unity是1m而Max通常设定为1cm),因而在解析fbx时给予了一个默认的Scale值用于补正单位长度的差异,模型在这个默认Scale下会表现出Max中的尺寸大小

但是这里呢我们需要手动将30.48这个默认缩放大小植入到模型的Scale Factor中

应用模型时我们需要对Transform进行ReSet,将缩放归1

这样我们就将修正Max和Unity单位长度的默认缩放值,植入到了模型的Scale Factor中,Unity中Scale为1时模型就能表现出原先Max建模时设定的正常物理尺寸

模型应用到场景中时,Scale为1并表现正确尺寸如果放任场景模型通过默认的Scale缩放表现正常尺寸,我们添加子物体时就会产生不必要的麻烦,图中我们添加了一个默认的Cube,但受模型Scale的影响,默认的Cube被放大了30.48倍3.轴心调整问题

我们需要对模型的轴心的位置和朝向进行调整,让模型适应Unity中的环境

不止是由于Unity和Max对于物体的轴向的标准上有所区别,更是由于轴心会决定物体的位置定位点,以及物体进行本地旋转时的旋转中心

3D游戏数学中提到的

模型的物体坐标系由美术在建立模型时确定

这就是指对模型的轴心调整问题

轴心的调整分为对轴心的位置调整,和对轴心的朝向调整,在解释时我们也会结合一些实例来帮助大家理解

---3.1 Unity和3dMax坐标系/轴向的区别

Unity坐标系以Y轴向上作为高度,XZ平面作为底面,的左手坐标系,而通用建模软件(以3dMax为例)使用Z轴向上作为高度,XY平面作为底面,的右手坐标系

Unity中有Z轴正方向为LookAt方向一说 ,可使用像Transform.LookAt(目标点或目标方向)方法让物体Z轴正方向冲向某一方向

---3.2 轴心的朝向调整

轴心的朝向调整主要针对Y轴和Z轴这两个在Max和Unity中有区别标准的轴心朝向

------3.2.1 3dMax调整轴心朝向的操作轴心调整时,受到物体的世界旋转/世界朝向的影响,我们需要使用局部旋转结合捕捉来调整轴心朝向,更多有关轴心调整的方法这里就不过多赘述了先点击对齐到世界再进行调整我们调整时物体如果物体产生翻转变化,那么该物体需要被重置旋转变换重置变换Gizmo子层级旋转,将物体至于原先设定的方位重置变换可能导致法线翻转,我们可以通过法线命令解决重置变换后物体的轴心朝向会发生变化但此时我们再进行轴心朝向调整,物体不会发生翻转导入Unity中,物体默认有Y轴的本地旋转,但轴心朝向正确,并且这个Y轴的旋转并不碍事

这个Y轴的旋转值只要ReSet一下Transform即可,正确调整了轴向的模型,应当只有默认的Y轴旋转值,并且这个Y轴的默认本地旋转值,对于不含动画的网格模型而言,并没有任何影响,在游戏开发时,我们在Unity中进行我们需要的本地旋转即可

但如果模型含有动画,那么我们就需要进行更加高级的物体轴心朝向调整-----世界旋转归0调整(后面会提到)

------3.2.2 Y轴旋转冲上

Unity中是以Y轴作为高度轴的,而Max中是以Z轴作为高度轴

因而我们需要旋转Y轴冲向模型的高度方向(Y轴旋转冲上)

导出模型前请手动旋转Y轴冲上,不要相信什么自动轴转化设置

如果调整轴心时物体产生了变形,那么是由于进行了XYZ轴的不等缩放导致的,可以通过之前在2.4中提到的重置变换来修正

虽然不进行Y轴冲上调整的模型也可以正常拖入场景中,利用Unity的投影正常的放置在场景中,但由于轴向不同,模型自身的物体坐标系中会保留3dMax的Z轴向上做高度轴,而Y轴才是Unity中的高度轴,这样的冲突可能为之后的开发带来不必要的麻烦

------3.2.3 Z轴旋转冲前

其次是对于模型的Z轴,由于Unity中有Z轴正方向为LookAt方向一说

因此,有明确正面朝向的模型,可能使用Transform.LookAt方法控制朝向的模型,可能被旋转进行LookAt跟随的模型,

应旋转Z轴冲向模型正面方向(Z轴旋转冲前)

例如:

一架简易的飞机模型(枪支模型同理)

一个简易的飞机模型Z轴旋转冲向飞机的正前方从而在Unity控制飞行时,能够正确的控制飞机的飞行方向

一个箭矢的模型(子弹,导弹同理)

调整箭矢的Z轴冲向前方从而Unity制作游戏时,我们可以控制箭矢飞向正确的方向------3.2.4 更加高级的轴心朝向调整-----物体世界旋转归0 我们按上面的要求调整了轴心朝向但我们发现物体相对于世界坐标有一个旋转,这个旋转会被记录到物体的Transfrom矩阵中,并在Unity拖入模型到场景中后表现为Transfrom组件中的本地旋转在Unity中拖入模型,默认会有一个Y轴-125度的旋转

这里Max中的世界旋转,和Unity中表现出的默认旋转是不同,这是由于之前3.1提到的Max和Unity在坐标系,和坐标朝向上存在区别,因而Unity解析fbx时对模型的本地旋转也会有一个转换存在

3.2.1 中已经提到了,对于一般不含动画的网格模型,模型轴心朝向正确,默认存在的Y轴本地旋转是没有影响的

但对于含动画的模型,尤其是需要结合Apply Root Motion不勾选,围绕Max世界原点运动,将根节点的坐标/朝向,转换为在Unity中相对父节点下的本地坐标/朝向,这种动画表现形式的模型

我们就需要进行物体世界旋转归0,保证物体的本地旋转在导入Unity中是归0的,之后再开始动画的制作

有关Unity动画系统Apply Root Motion的三种模式,以及物体世界旋转归0的调整方法,可以见这篇文章中的一个章节,和最下方第一个附录

---3.3 轴心的位置调整

轴心的位置决定了物体的定位点,以及物体的本地旋转中心,因而在调整好物体的轴心朝向后,我们还需要对物体轴心的位置进行调整

------3.3.1 Y轴底面&放置表面问题

有明确底面的需要放置在场景中的物体应将Y轴置于物体底面

需要被放置在场景中的补给箱Y轴置于底面

模型的某一高度的表面上需要放置其他物体的模型,其Y轴应置于待放置平面上,尤其是场景模型应特别注意该问题

可能需要放置物体的桌子表面其Y轴被置于桌面可能需要放入物体的抽屉其Y轴被置于抽屉面按上述要求设置了轴向,让补给箱作为抽屉的子物体Y轴高度设置为0,调整XZ平面位置,很轻松且标准的就将补给箱放入了抽屉中

如果模型既要被放置在场景中,又具有放置表面(例如一个桌子),此时应优先满足放置表面的要求,并记录正确的放置悬浮高度提供给使用Unity的开发者

------3.3.2 位置定位问题

模型轴心的位置决定了模型的定位点

模型的世界位置是模型轴心相对世界坐标系原点的位移量,模型的本地位置是模型的轴心相对父节点(父物体坐标系)原点的位移量

调整轴心位置时,我们可以先使用居中到对象,让轴心位置位于模型网格的中心位置,之后进行移动调整

通常对于一般的网格模型,由于轴心要作为模型的定位点,因而轴心的位置应当靠近模型的网格并满足Y轴底面&放置规则,但更加高级的应用中会利用这个特性,刻意的让轴心在于父物体轴心位置重叠时,网格被放置在正确的位置,从而实现场景的插件摆放扩展

这里先举一个简单的轴心定位的例子

如图是一个游标卡尺的模型,分为主尺,子游尺,以及四个用于Collider展开的Box游尺作为主尺的子物体,我们让其在父物体坐标下X的本地偏移为0时,游标卡尺正好合上从而在Unity中我们就可以直接以游尺的localPosition.x作为输出读数我们还令主尺的轴心位置正好在其宽度的中心位置球体的轴心在球心位置,从而在球体和游标卡尺Z轴位置一致时,球体正好被放置在了游标卡尺的中间,能够测得其直径

更加高级的轴心定位应用,以子物体插件的形式实现场景的摆放扩展

在游戏开发的进程当中,游戏的整个场景建模工作,与Unity的开发工作是同步进行的

美术会在一开始提交场景的大致架构建模,包含全部的地面,与剧情/设定密切相关的建筑,此时Unity那边就可以开始进行游戏玩法,游戏架构的制作,而美术将进行场景中一些细节物体的建模

这就为Max和Unity的对接工作提出了一个问题,我们之后不断加入的模型不能影响到Unity中已经摆放好的模型,或者说我们不能更换Unity中已有的场景模型(否则就会影响到Unity的开发工作)

这里我们可以应用物体轴心的定位作用实现场景的摆放扩展

例如我们先提交了一个这样的场景模型,我们需要设定一个最终父物体(通常是场景的地面)Unity获取这个大致的场景模型就可以开始进行游戏玩法,游戏架构的制作了后期在进行场景扩展时,对于单个/一组模型,我们需要通过轴心位置调整,使其在地面父物体下的本地坐标归0时正好被摆放到需要的位置

调整方法是先在Max中将模型摆放到正确的位置,之后调整轴心位置对齐到地面的轴心

此时我们就可以只导出新建的模型

Unity中导入这个模型,将其作为最高父物体(地面)的子物体,之后ReSet Transform将位置归0,这个模型就被摆放到了正确的位置如果要加入的模型较多,我们可以创建一个与地面轴心位置重合的虚拟对象,将要加入的模型链接到虚拟对象上选择虚拟对象和子模型一并导出Unity导入模型,虚拟对象会成为一个最高空父节点,将其作为地面的子物体,Reset Transform,我们要加入的模型就被摆放到了正确的位置

导出模型时,应在正确的摆放位置导出(否则可能位置出错),上图中抽离只是为了说明只需导出添加的模型即可

运用这一套方法,我们可以在Max中完成模型的摆放,并在不影响Unity已有模型的基础上,以子物体插件的形式将摆放结果提供给Unity,从而在不影响Unity中已有场景的前提下现实现了场景的扩展

------3.3.3 旋转定位问题

物体的轴心位置决定了物体的本地旋转中心,因而对于一些需要绕特定轴旋转的模型,我们需要将轴心设置到对应的位置

一个最常见的例子---门

我们需要将门的轴心位置设置到门的一侧,从而在进行本地旋转时能够正确的将门旋开从而在Unity中,门板可以通过一个Y轴的本地旋转正确的被旋开

这里还需要注意Unity的一个bug

Scence场景窗口中,物体的移动/旋转Gizmo,可能并不在DCC调整好的轴心位置处(可能存在偏差)

尤其是针对旋转定位的时候,往往旋转Gizmo被错误的放置在网格的中心位置

这里我们需要调整Transfom组件中的XYZ旋转,或是通过代码来旋转物体,不要用Scence场景中的Gizmo进行旋转

---3.4 转轴的精确布置

像上面3.3.3节中门的例子,我们只要求物体的本地旋转中心能够在正确的位置上(门能够绕着附着门框的一侧被旋开),对于具体旋转哪一个转轴(Y还是XZ)并没有特定的要求,这种情况下一般只需将物体的轴心位置调整正确即可

然而另一种情况下,我们可能需要对物体的转轴进行精确的布置,不仅需要本地旋转中心位置正确,还希望旋转的转轴是某个特定的轴向(旋转的中心位置要对,转轴的朝向也要对)

例如下面这篇回答中,设计机械臂的平面内IK问题,我们不仅希望机械臂的节点的旋转中心位置正确,还希望它们都能以Y轴作为其转轴

通常在Unity中,如果可以的话,我们都会希望能使用Y轴能够作为特定转轴

一方面是由于Unity的欧拉角轴嵌套使用了 Y(Heading) - X(Pitch) - Z(Bank)的模式,因而Y轴(Heading)作为欧拉角的第一序旋转是最为可靠的,X(Pitch)Z(Bank)都存在着各种问题

X(Pitch)作为中间转轴受限制欧拉角影响,其输出只有180度半域,Z(Bank)则会在万向锁位置被强制归0,将其变化反向作用到Y(Heading)

更详细的介绍可参见下面这篇回答

这里以一个Box盒子为例,我们希望上方的子盒盖能够使用Y轴进行旋开

遵照上面的轴向位置和朝向原则,下方的父盒体,我们将其Y轴旋转冲上,Z轴冲前,并将Y+位置至于底部面

调整子盒盖轴心的位置和朝向

然而导入进Unity中我们会发现,子盒盖的Y轴并不是预期的翻盖转轴

这是由于子物体/子空间相对于父物体/父空间的的R旋转偏移,其旋转的中心点位置,是由子物体/子空间,相对父物体/父空间的T位移所决定的,但旋转的轴向,是继承自上一级父物体的轴向

我们虽然调整了子盒盖轴心的位置和朝向,但这仅仅只保证了R旋转的中心位置正确,实际旋转的轴向是由父盒体的所定义的

父盒体Y轴冲上做高度轴,因而上面我们会发现旋转子盒盖的Y轴会绕父盒体的Y轴方向形成水平的转动

为此我们还需创建一个点辅助物体,将其位置和朝向对齐到子盒盖

之后将点辅助物体作为一个中继节点

原先父子关系: 父盒体 --> 子盒盖

调整为 : 父盒体 --> 中级节点 --> 子盒盖

从而子盒盖的上一级父物体变为了位置和朝向与之对齐的中继节点

此时子盒盖就能以Y轴作为其翻盖的转轴了

我们也就完成了对转轴的精确布置,即保证了旋转的中心点位置正确,还保证了所使用的转轴是我们希望的Y轴

原理内核解析:

下面有关线性变换的内核,需要有足够深入的关于线性代数的知识基础

起码要能读懂这篇文章

纯美术人员不必过多纠结,只需要会用上面的中继节点法即可

以下以行向量左乘书写,

列向量右乘可根据 (AB)^{T} = B^{T}A^{T} 及其在n个矩阵上的推广,将相乘序列反序,再将矩阵转置

但无论行左乘还是列右乘,向量/点与矩阵相乘的结合顺序并不会改变

在3D游戏中我们可以对物体进行S缩放R旋转T位移,三种相对于父物体的变换操作

在底层的实现上每一个物体都会有一个Transform矩阵用于记录其与父物体的相对偏移,记为矩阵 M

M矩阵是三个矩阵的相乘叠加,分别是 S缩放 R旋转 T位移

M_{Transform矩阵} =SRT (行左乘)

在空间变换上,对于 M=SRT,T位移是最高父变换,R旋转继承T位移后的位置,S缩放继承T位移后的位置与R旋转后的轴向

物体上的顶点在渲染时需要计算其世界位置(相对于世界坐标系的偏移)

在空间变换上,对于父子关系嵌套下的子物体相对世界坐标系偏移计算,其父物体的Transform矩阵也是子物体Transform矩阵的父变换

物体上的顶点世界位置计算的算法如下

p_{顶点在物体空间下的位置记录}M_{物体}M_{上一级父物体}...M_{最高父物体}

这里点与矩阵相乘的顺序,和空间变换上的父子变换嵌套顺序是相反的,向量/点先乘末端子变换对应的矩阵,再乘父变换对应的矩阵

上面那个式子展开就有

pS_{物体}R_{物体}T_{物体}S_{上一级父物体}R_{上一级父物体}T_{上一级父物体},,,S_{最高父物体}R_{最高父物体}T_{最高父物体}

那么来到 R_{物体} 的时候,前项的父变换矩阵链包括:

T_{物体}S_{上一级父物体}R_{上一级父物体}T_{上一级父物体},,,S_{最高父物体}R_{最高父物体}T_{最高父物体}

注意到前项父变换包括 T_{物体} ,因此物体相对父物体的R旋转偏移,在旋转中心的位置上受物体的T偏移影响

而旋转的轴向,则是之前所有父物体累积旋转后的轴向所决定的(S缩放和T位移不会影响到轴心的朝向,进而不会影响旋转的轴方向)

或者说物体的R相对父物体的旋转偏移,是从相对父物体的惯性轴向转出来的(位置由自己的T偏移决定,但轴向上对齐自父物体)

这里根据欧拉角轴嵌套,R还能再展开为 R_{物体} = R_{Bank}R_{Pitch}R_{Heading}

因此Heading的转轴朝向完全由父物体轴心的朝向决定,Pitch的转轴朝向是父物体轴心叠加Heading之后的朝向,Bank转轴则是父轴心朝向得加Heading和Pitch之后的朝向

同理来到 S_{物体} 的时候,根据前项父链矩阵,不难发现,S缩放的轴心,位置由物体自己的T偏移决定,轴向也有物体的R旋转决定,S缩放是完全处在物体空间下的

物体的 T_{位移} ,根据前项父链矩阵,不难发现,位移偏移的轴向是由父物体的轴向所决定的

一些DCC的动画系统中,可能会有编辑物体Transform变换的功能,例如3dsMax中的位移/旋转列表,能够在原先的SRT上,额外叠加新的一次偏移

相应的这也会改变SRT的参照,如果我们新加了一次R,即M=SR2R1T,那么第一序的R1是继承父物体轴向的,第二序的R2则是父物体叠加R1之后的轴向

具体介绍详见这篇回答

---3.5 错误设置轴心的模型,Unity中的补救方法

当轴向设置错误且在开发中产生一定问题时,可以利用Unity中的空物体挂轴向错误的模型做子物体,进行旋转和移动来调整轴向,并将空物体生成一个Prefab进行使用

使用空物体下挂错误轴向的木桶模型,移动/旋转子木桶,调整出正确的轴向

但这只作为最后手段,物体轴心应当在Max中调整正确,而不是依靠Unity

4.模型贴图与光照渲染问题---4.0 模型的光照表现

这里来讲解一下光照效果在3D渲染时的作用

我们最终会将一个3D的虚拟场景渲染为一张二维的图像并展示在屏幕上,这个过程即发生在Max建模时的视口渲染为建模者展示三维网格,亦发生在Unity进行实时渲染应用的开发为用户展示三维场景,更发生在我们平时用双眼去观察世界的过程

虽然我们这些三维生物看到的是一张二维的图像,但我们却能从中理解三维空间,这是由于渲染出的二维图像包含了两个必不可少的属性

一个是物体与物体之间的遮挡关系,又称深度关系,这使得二维图像正确展现了三维场景投影到二维,所缺失的那个维度的表现,深度关系是在渲染时通过深度缓冲算法,或者在明确物体深度方向上的精确排序顺序(通过多边形对齐BSP树,或者Layer&Sprite技术)时使用画家算法来正确表现,因而就和本文关系不大了

另一个是物体的光照效果,光照效果是表现空间感很重要的一个属性,想想画素描,为表现体积感/空间感,我们绘制的明暗/阴影都是光照效果

注意立方体三个面的明暗差别,Max的视口中包含了一束跟随视口观察方向的光源,视口渲染时拥有光照效果,从而能够让建模者理解模型网格在三维空间中的结构

计算光照效果时,标准光照方程可以表示为

C_{lit}=C_{spec}+C_{diff}+C_{amb}

C_{lit} 是启用光照情况下,物体的色值,关闭光照时的物体表现出的色值,对应最强无差白色环境光下表现出的颜色,因而烘焙漫反射纹理时,我们不会添加任何光源,而将Max中的环境光设置为最强白光

C_{spec} 是镜面反射分量,也称高光反射值,是由光源和材质的高光颜色,光泽度,光源照射方向,观察方向等因素共同决定的

C_{diff} 漫反射分量,是由光源,材质的漫反射颜色,光源的照射方向等因素决定的

C_{amb} 环境光分量,是由材质的漫反射颜色和环境光照值决定的

我们会将Max中制作好的模型,场景提交到Unity中,由Unity来进行渲染的效果的设置和表现,因而最终的渲染环境是在Unity中

光源的布置,光照模型的选取,最终效果的调整,都是由Unity完成的

Max需要做的是提供模型的网格,并通过烘焙贴图为Unity中的材质属性提供一个参考值

---4.1 Unity对fbx材质的默认解析与材质重映射------4.1.1 Unity默认解析后与Max中渲染存在差异

模型在导入到Unity中时,Unity会对fbx中的材质进行解析并转换为Unity的官方默认材质(使用StandardShader),解析的过程中一些属性会被保留,一些属性则会丢失,一些属性在Unity中的表现和Max中存在差异(着色器编码的不同)

一个经典的漫反射贴图与漫反射颜色叠加的差异问题

一个比较经典的问题是在Max漫反射使用.png .jpg格式的贴图时,会根据下方的贴图权重值决定漫反射颜色和贴图颜色的混合权重,由于下方的权重值默认是100%,因而默认完全表现贴图中获取到的颜色但在导入Unity中时,Unity解析FBX文件生成材质,会获取到材质的漫反射贴图,也会获取材质的漫反射颜色,Unity中的StandardShader会直接使用rgb向量乘法混合色值,而不是权重混合,这就导致了最终效果与Max中的不符

有时我们可能不经意的在Max中调整了漫反射颜色,又添加上了贴图,导致了导入Unity后的效果出现了大的偏差

一个方法是在Max中将漫反射色值设置为255白色,这样导入Unity后默认解析下贴图的颜色偏差较小,但依然存在一些问题

这就导致了一个问题,图中气球兵贴图绘制时取用的黑色与球体的黑色是相同的,Max中完全表现贴图颜色,因而贴图与球体是融合在一起的但在Unity中受到默认解析效果的影响,最终效果是贴图区域的颜色出现了偏差------4.1.2 使用Unity创建材质并进行模型材质的重映射

事实上我们不应纠结于这个默认解析的转换效果,它存在有很多的问题

为了更好在Unity中更好进行渲染并实现一些特殊效果,会由技术美术编写特定的着色器(shader)并在Unity中创建材质,布置Unity中的渲染环境,详细设置材质的各项参数

DCC会通过烘焙贴图来保存漫反射颜色,高光颜色,光泽度等等属性,为Unity中的材质属性提供参考值(后面会详细讲的烘焙贴图的方法)

此时我们需要将Unity中准备好的材质,应用对应的贴图资源,并映射替换掉模型中默认解析生成的材质

如图,在FBX-Material中映射替换材质这里左侧的材质名,取决于DCC中对网格引用材质的命名

一般来说一个物体网格我们会通过烘焙贴图来制造某些属性的各向异性,尽量让一个物体使用一个材质,避免产生额外的drawcall

但如果物体网格中确实存在需要应用不同材质的部分(例如一个手持光剑的人物模型,人和光剑渲染的Shader实现完全不同,无法借由纹理各向异性统一材质),那么DCC中就需要引用不同的材质,并对材质做好命名,做到“故名思位”

在Materia

---4.2 Max进行UV展开调整

fbx中包含的网格顶点有一个很重要的信息---顶点UV

对于漫反射颜色,高光颜色我们可以进行统一的指定在顶点上

也可以通过纹理贴图技术在不增加顶点的情况下让其在物体表面上表现出各向异性,纹理贴图技术中顶点UV需要DCC进行模型的UV展开调整,有关纹理贴图技术和MaxUV展开技法,可以参见这篇文章,本文就不赘述了

一个网格是可以有多道UV的(uv1,uv2,uv3...),取决于DCC在UV展开时的通道设置

这里3dsMax中UVW展开修改器,贴图通道设置,就决定了当前这一套UV展开会被放在第几道

这里补充一下,麦老师在评论区里提到的,模型的UV不要拖泥带水,漫反射,法线,高光,最好共用一套UV进行贴图的烘焙和应用,从而方便Unity那边编写shader时不必为不同类型的贴图应用不同的UV索引数据

------4.2.1 UV接缝问题

这里我们着重讲一下UV接缝会带来的问题

首先是对绘制连续性的影响,如果我们想要在UV接缝处进行连续纹理的绘制,那么不要指望画师在UV模板上,两块多边形分裂的情况下给你画的多么的好

我们应通过缝合接缝将两块多边形的接缝边拼接在一起,方便绘制

其次是对于法线贴图烘焙,UV接缝对硬边的影响,拆开UV,制造顶点细分,从而承载法线突变,才能使低模正确表现出高模的硬边效果

有关3dsMax法线UV展开,法线烘焙相关技术总结,详见下面这篇文章

最后是UV接缝对于贴图烘焙的影响,在UV接缝处可能会出现纹理烘焙的瑕疵

本质上是由于纹理采样时的滤波需要设置一定的掩膜范围

UV接缝对应纹理空间下面片的边缘位置,边缘采样在滤波作用下会超出面片本身的范围,导致粘混到临近的其它颜色

如图,粘混到了临近的白色如果在Max中用多维子材质设置颜色,再烘焙漫反射纹理

那么应当使用.tga格式保存纹理,因为这种格式烘焙填色后,会自行将漫反射颜色从边缘处推出一圈,从而保证边缘处采样的正确性

一些仍然粘混到邻近色的边缘可以在烘焙贴图后手动调整

.tga格式保存烘焙效果,可以看到边缘处被推出了一圈,保证了边缘采样的正确性

另一种情况是我们展开UV后导出UV模板,使用PS/GIMP进行漫反射的填色,纹理绘制

这种情况需要根据漫反射/法线信息的有无,对UV进行排版调整

绘制时注意要超出边缘部分一圈的大小,保证边缘采样的正确性

超出一圈,保证覆盖到边缘位置纹理采样滤波的掩膜范围

---4.3 模型贴图问题------4.3.1 光照原则

之前已经提到,Max需要提交的是模型的网格,以及通过贴图烘焙为漫反射,高光颜色,光泽度这些材质属性提供参考值,最终的渲染环境是在Unity中,光源的布置也是在Unity中进行的

因而在烘焙漫反射纹理时,一个重要的原则是不在Max中进行光源的布置,不将Max中的光照效果烘焙进漫反射纹理内,模型的光照效果通过Unity中的光源布置,以及展开光照UV进行光照烘焙来表现,这是使用Max&Unity进行游戏开发,尤其是使用PBR时应遵循的原则

但使用Max进行光照布置渲染有光照纹理,一个好处是可以针对单个模型,进行针对性的光照布置以达到特殊的效果,如果Unity对应场景渲染的布置不严格,或者说希望某个模型能够带有固定的额外光照效果,此时我们也可以使用Max渲染有光照纹理

渲染标准的漫反射纹理,以及通过Max布置光照渲染有光照纹理的具体方法会在下面的章节讲到

------4.3.2 Max的渲染器设置

这里我们介绍一下,Max自带的扫描线渲染器的设置,使用Max自带的扫描线渲染器能够应付一些最基本的烘焙/渲染情况,但相比专业的渲染器仍存在很多的不足,更高级的渲染/烘焙需求,可能需要使用像v-ray/Substance这样的专业DCC软件

渲染---渲染设置(F10)打开设置面板

渲染器设置一栏注意关闭阴影(无论烘焙漫反射还是高光效果都要关闭阴影)

注意启用抗锯齿,贴图过滤,超级采样

尤其是在烘焙法线贴图时以定要开启超级采样

渲染---曝光控制,设置场景光照相关

我们要注意调整的是全局照明染色,和环境光

首先着两个颜色都是有强度RGB颜色向量,既有光照的颜色属性,也有光照的强度属性

如果使用HSV模型光照的强度可以直接通过V明度的大小进行控制

全局照明染色,调整的是场景中布置的所有光源的颜色及光照强度的偏移

环境光颜色则是之前提到的光照方程中的,全局无差别环境光照效果

------4.3.3 烘焙漫反射纹理及其必要性

---------4.3.3.1 烘焙漫反射纹理的必要性

好的我们先来做一个测试

我们在Unity中导入了两个模型,右侧的模型是Max中使用多维子材质,对网格上不同的多边形应用不同的材质进行了漫反射颜色设定,并被Unity默认解析后的效果

右侧的模型是我们不烘焙漫反射纹理的情况下,使用Max正常建模产生的效果

左侧的模型我们进行了漫反射颜色烘焙,所有使用Max多维子材质进行漫反射颜色设定的多边形,我们一起进行了UV展开并进行了漫反射纹理的烘焙,最终网格上的多边形都应用一个挂载了烘焙出的漫反射纹理的材质

塔上的旗帜使用了渐变坡度贴图,额外进行了烘焙并使用了一个单独的材质,其它部分均使用一个材质

当然Unity的默认解析存在漫反射颜色的矫正色问题,因而左侧的模型材质使用了我们特别准备的shader,目前场景中可以看到左右两侧的模型表现效果基本一致

我们来对比一下渲染两个模型的draw call,当前场景中没有任何光源,由于绘制阴影也需要消耗额外的draw call

场景中没有任何光照,摄像机为soild color模式,运行游戏不渲染任何模型只有一个draw call用于绘制背景右侧的防御塔单独渲染,产生了17个额外的draw call,正好对应它使用的17个材质数量左侧防御塔单独渲染,产生3个额外的draw call,恰好是1个父物体和2个子物体,3个物体的数量,这里子物体弓箭手和塔使用了同一个材质

呃...其实你可以问一下身边懂渲染,做Unity优化的人,这样的draw call差别意味着什么(应该他们会比我下面解释的更清楚更详细)

所谓的draw call就是CPU(应用程序)准备一组多边形,向图形硬件发送并完成一次绘制的过程,渲染优化的一大任务就是尽可能的降低draw call,一次性绘制尽可能多的多边形,从而提高渲染的效率

右侧使用大量材质的模型,因为材质的不同,而产生了额外的draw call,绘制每个材质对应的多边形都需要一个draw call,尽管右侧模型只有防御塔(含旗帜)以及弓箭手两个物体

而左侧,进行了漫反射颜色烘焙的模型,由于一个物体只使用一个材质,因而也就只产生一个draw call

事实上这就是我们使用Max进行漫反射烘焙,以及进行高光贴图烘焙,光泽度贴图烘焙的必要性所在,我们要让原本需要使用多个材质设置不同属性的物体,利用贴图来产生材质属性的变化,让一个物体只使用一个材质,从而有效的降低draw call

当然再补充一点,左侧的模型弓箭手和防御塔是使用同一个材质的,因而还存在着进一步优化的空间,通过一定的算法我们可以借助它们共用材质的特性,向图形硬件一次性提交网格(称之为合批),但讲解这个技术就超出本文的范围了

不过在制作一些场景模型的时候,我们可以选中场景中尽可能多的物体(最好是整个场景中的所有物体)一并进行贴图的烘焙,让它们使用同一个材质,从而为之后的渲染优化铺平道路

---------4.3.3.2 烘焙漫反射纹理的方法

这里我们大致讲一下使用Max扫描线渲染器烘焙漫反射纹理的方法

这里针对于使用多维子材质后,烘焙漫反射纹理

另一种绘制贴图是展开UV后,进行排版,导出UV模板,作为PS/GIMP绘制纹理、填色时的参照

UVW编辑器---工具---渲染UVW模板,建议保存为带Alpha通道的.png格式

使用Max正常建模结合多维子材质设置多边形的颜色,高光属性,最终你会得到这样的一个模型

这里我们将需要统一材质的所有多边形都附加结合到一起,并添加UV展开修改器

打开UV编辑器,选中所有多边形,使用自动计算展平UV

通常可以勾选按材质ID,从而相同材质(相同颜色)的面片会被放置在一起

也可以通过3dsMaxUVW展开修改器中的各种功能,手动展开UV,可以参考这篇文章

摁数字0键打开贴图烘焙器,先进行渲染设置,注意关闭阴影

曝光控制,由于要烘焙漫反射纹理,场景中不应布置任何光源,我们将环境光至于rgb255最亮白光

使用现有UV展开,通道标号选定与UVW展开修改器贴图通道一致,通常是uv1

添加diffuseMap输出项

烘焙会产生一张.tga纹理,我们需要设置它的保存路径,调整贴图尺寸

注意!!!一定要使用.tga纹理而不是手动保存的.bmp/.png 否则会出现很大的接缝瑕疵,.tga纹理在烘焙保存后,会将漫反射颜色沿UV接缝边缘自行推出一圈,保证边缘采样的正确性

烘焙完成后我们复制出一个模型,设置所有多边形材质ID为1,新建一个材质引用我们烘焙出的.tga贴图将其赋给模型,从而整个模型就只使用这一个材质

随后我们再进行网格的分离,轴心调整,父子关系的链接,导出FBX即可

(引用.tga纹理后,Max中的漫反射颜色就类似Unity使用乘法叠加了,但你并不需要去调整那个漫反射颜色,让Max中渲染贴图模型和原来多维子材质的模型看起来多么的接近)

我们不必在意Max渲染模型的效果是否与原来使用多维子材质一致,因为最终渲染是在Unity中进行布置,Max只需要烘焙漫反射纹理为材质颜色提供参考值即可

当然由于Unity对fbx材质默认解析存在诸多问题,我们需要在Unity中使用特定的shader,创建材质并映射替换默认解析生成的材质,来对接烘焙了漫反射纹理的模型,详见上面的章节

------4.3.4 高光烘焙实现特殊效果

有时候我们也会需要Max烘焙出带光照效果的纹理,因为Unity固然是进行全局的光源设置,一些需要表现特殊光照效果的模型难以进行针对性的照顾

但烘焙带光照效果的纹理是一种非常危险的行为,这可能激怒与你一起工作的技术美术,除非是渲染要求不严格(起码没在走PBR的流程),或者确实有一点特殊的需求

在征得技术美术同意的情况下,我们可以使用Max对模型进行针对性的光源布置,并将光照效果通过烘焙高光贴图保存下来

漫反射贴图里保留了3dMax中针对性布置的光照渲染的模型保留了3dMax中光线追踪结果的钻石

---------4.3.4.1 烘焙高光贴图,漫反射贴高光图保留3dMax光照渲染,光线追踪效果

1.首先在3dMax中调整出一个合适的渲染效果(包括环境/光源布置,展开UV)

这里用到的光线追踪贴图,在通过fbx导入时无法被unity正确解读,且unity中是不同的场景渲染环境。但我们希望这颗钻石能保留当前光线追踪反射出的效果

2.展开好UV的情况下选中物体按数字0键打开纹理烘焙渲染器

3.使用现有通道,添加烘焙图片LightMap

这里已经完成UV展开,应使用现有通道,注意贴图通道务必使用通道1,贴图才能在unity导入fbx时被正确链接贴图

4.点击渲染,得到.tga高光贴图

5.创建一个新的材质,参考原材质调整其他属性,但漫反射颜色白色,并贴位图,找到我们保存的那张高光贴图

6.将材质赋给物体

由于所使用的贴图烘焙时的UV和当前物体UV是一致的,我们贴上的高光贴图按照UV的引导会被正确的贴在物体表面

如果原本物体使用了多维子材质,建议复制一份物体,所有多边形材质ID改为1,让所有多边形使用一个贴好高光贴图的单材质即可

点击在视口中明暗处理材质或渲染,察看贴图效果

7.导出fbx,注意fbx文件和贴图文件的保存

------4.3.5 烘焙渐变贴图/渐变坡度贴图

渐变/渐变坡度贴图是Max中一个非常好用的,快速生成程序贴图功能

但在对接Unity时存在一个问题,这个贴图只是Max创建的一张程序贴图,Unity并不能从fbx中正确的解析出Max设置的渐变/渐变坡度贴图,因而我们需要手动将渐变/渐变坡度贴图烘焙出来,从而导入到Unity中使用(将程序贴图渲染到纹理)

例如这个气球兵的两种麻绳,就用了两张渐变坡度贴图来表现

似乎右键选项中渲染贴图是一个渲染到纹理的方法,但烘焙出的贴图效果经常不尽如人意,与原效果存在一定的差异

这里一个比较好的方法是我们创建出一个承载贴图的正方形平面,将渐变/渐变坡度贴图对应的材质赋给这个平面,随后对这个平面进行漫反射纹理的烘焙(称之为烘焙板法)

烘焙出的贴图较右键渲染贴图质量更高,能更好的还原渐变/渐变坡度贴图的效果

漫反射烘焙的方法见上面的章节,烘焙完成后我们将材质对应的渐变/渐变坡度贴图替换为我们烘焙出的.tga贴图即可

当然这里由于模板内部不存在UV接缝,使用手动保存的.bmp/.png/.jpg贴图也可以

------4.3.6 FBX模型与贴图资源的管理

新版本fbx中并不会嵌入贴图,Max还需要将模型用到的贴图进行整理与FBX一并导出

通常我们会针对每个模型创建这样的一个文件夹专门存放导出的各个版本的FBX文件,以及使用到的所有贴图

对于贴图我们还需做好命名处理,标明贴图应用的位置(Diffuse漫反射/NormalMap法线),贴图应用的物体(Mortar迫击炮)

---4.4 Unity模型导入及后续调整------4.4.1 导入的具体操作

导入的方法,将FBX和贴图文件拖入到Unity的Assert目录下即可

当然如果你不会在Unity中使用针对性的shader创建材质,映射替换原材质,而是依赖于Unity对于FBX默认解析生成的材质,那么就需要注意FBX文件和贴图的导入顺序:

导入时应先拖入所有需要的贴图文件,再拖入FBX文件,或FBX文件与所有需要的贴图文件一起拖入,否则解析生成的默认材质将无法正确的链接原有的贴图

当然,需要在Unity中使用针对性的shader创建材质,进行映射替换

就不必在意什么顺序了,都拖进来就行,只有创建材质时能找到对应的贴图挂载即可

------4.5.2 导入uinty后的相关设置

在导入模型后,点击模型文件,Inspector窗口会显示unity为该模型的一个设置面板,这里来细说一下这个设置面板应如何设置

---------4.5.2.1 Model窗口------------4.5.2.1.1 Model->Scence

该窗口主要用于设置模型的缩放属性,是否导入灯光和照相机

1.Scale Factor与Convert Units

前面也有提到模型的尺寸会乘缩放因子Scale Factor作为默认1单位的尺寸

这里的Convert Units勾选与否,是决定是否启用模型自身的尺寸单位,一般我们会按照1中提到的正常模型比例在3dMax中就设置好需要的模型的尺寸大小,并启用Convert Units

如果不勾选Conver Units 则会使得模型自身的尺寸设置失效,即忽略3dMax中的单位设置,3dMax中模型尺寸的1单位被直接解释为unity中的1m

2.导入 BlendShape(通常启用)

这里Blend Shape 是一种脸部动画的播放方式,通过预设脸部网格对应不同通道值的扭曲程度,来进行脸部动画的播放

Blend Shape其实实质是一种网格扭曲的混合通道绑定,其实也可以用于实现其他的网格混合扭曲效果

Blend Shape是Maya所创建的一种混合扭曲的组件,3dMax中使用Morpher完成同样的功能,同样需要勾选这个设置属性来完成导入

3.导入可见属性(通常启用)

导入可见属性用以保证可以读取FBX中的可见属性来禁用或启用unity中的MeshRender组件去渲染物体

模型动画如果涉及了模型可见属性的改变则需要勾选,来保证unity正常读取可见属性

4.导入Camera 导入Lights(可忽略)

前面有提到过我们不推荐从3dMax中导入摄像机与灯光,而使用unity中创建的摄像机,灯光,来完成渲染

5.Preserve Hierarchy是否保留层次结构(通常禁用,只包含动画的FBX文件需启用)

如果不勾选,则unity会自行剔除模型中的所有空节点,对于那些只包含空节点用以表现模型动画的FBX文件来说,这会导致动画Rig不匹配

如果勾选,即使只有Root节点unity也会创建一个显示的预制根节点作为父物体

勾选后unity为FBX中的模型创建了预制父物体,并自行添加了一个Animation组件用以记录模型动画,因为大多数情况勾选Preserve Hierarchy意味着这是一个只含动画的FBX模型

并且我们发现3dMax中导出时的自动轴转转化设置在勾选了之后Preserve Hierarchy才会生效,但我们更推荐按3中提到的,来手动设置出合适轴向,一般我们保持这一项不勾选,所以导出时也不必在意是否勾选了自动轴转化,而使用我们手动旋转好的轴向

------------4.5.2.1.2 Model->Mesh

用于调整模型网格数据相关设置

1.是否启用网格压缩(通常禁用,优化渲染和发布文件大小时启用)

启用网格压缩,unity会按照一定的级别来压缩网格数据

压缩级别越高,网格的精度越低,这对于渲染优化和发布时游戏文件大小的降低很有用

2.CPU读写权限(通常禁用,动态网格时勾选)

启用与否决定了模型网格数据是否会被加载到CPU的可寻址内存上,来保证CPU的读写权限

大多数情况下应禁用此选项来优化运行时的内存使用

但如果我们真的需要通过脚本修改网格数据,生成动态网格,则可以启用此选项

3.顶点及顶点索引优化(通常勾选)

unity会优化FBX中的顶点和顶点索引排列,以获得更好的GPU性能

4.是否展开网格碰撞(需要所有网格展开网格碰撞器的模型可勾选)

勾选后unity会将FBX中所有的网格展开为网格碰撞器

即FBX预制体所有有网格的节点会自带一个MeshColider组件并使用对应的网格数据

------------4.5.2.1.2 Model->Geometry

用于设置模型的拓扑,法线,UV等

1.保持四边形(通常不勾选)

是否需要unity保持模型中的四边形面,不向三角形转化

通常任何3D模型的面都应由一个三角形或一个四边形构成,五边形及以上的n边形都会被优化为四边形或三角形

通常我们不启用这一个选项,来保证四边形被优化

但如果使用曲面细分着色器时应勾选此项,因为曲面细分着色器在四边形上的细分效果比三角形好

unity在导入模型时总将五边形及以上的面转换为三角形(无论是否勾选此项),但若勾选此项后,unity会创建两个子网个来分别包含四边形和三角形

“如果要从3ds Max将四边形导入Unity,则必须将其转换为可编辑多边形”

2.顶点焊接(通常勾选,存在需要脚本动态控制而故意设置的重复顶点时应取消勾选)

是否需要unity自行焊接位置相同切属性相同的顶点(包括UV,法线,切线和VertexColo)

通过顶点焊接可以优化顶点数量,获得更好的渲染性能

但如果需要脚本中动态控制网格,模型故意设有位置相同的顶点时应取消勾选

3.索引格式(通常Auto,在使用基于GPU的渲染管线编程时,通常使用32位)

unity在导入网格时使用的索引表示长度

Auto时将取决于网格的大小

16bit时若网格顶点较多将进行顶点分块,分块后每个顶点块

定义模型网格的法线使用怎样的生成方式

Import从FBX资源文件中导入法线

Calculate根据下面的法线模式由unity计算出网格面的法线

Node不使用法线,如果网格不需要法线贴图,也不受实时光照影响(各光照模型的计算都需要法线数据)应选择此项

5.网格混合法线来源

Scence菜单启用BlendShape引入后在此调整网格混合的法线生成方式

与Normals法线来源设置相同

6.法线模式

“定义Unity如何计算法线。仅当“法线来源”设置为“Calculate”时,此选项才可用”

“为导入法线时该项也可显示,但没有效果”

定义unity如何进行法线的计算

Unweighted Legacy旧式不加权计算,使用unity 2017.1及以前版本的计算方法,若某些Prefab从之前的旧版本(2017.1及以前)中迁移到新版本,可使用旧的计算方法尽量保证与迁移之前法线效果一致(但某些情况会有偏差)

Unweighted不加权的法线计算

Area Weighted依照模型每个网格面的面积加权

Angle Weighted依照每个面上的顶角加权

Area and Angle Weighted 面积加权+角度加权(默认选项)

7.平滑方式

“定义Unity如何计算法线。仅当“法线来源”设置为“Calculate”时,此选项才可用”

设置如何进行多边形平滑

Prefer Smoothing Groups尽可能依照FBX中的多边形平滑组进行平滑,但受到平滑角度的限制

From Smoothing Groups仅依照FBX中的平滑组

From Angle仅依照平滑角度设置进行平滑

None不进行平滑

8.平滑角度

仅在4法线来源为计算,且7中需要进行平滑处理切不只依照FBX中的平滑组时可用(4中法线来源为导入时,也可以显示此项但此项的设置没有效果)

调整是否为小于该角度的硬边分割顶点,过小的值将导致更多的顶点分割,更高的顶点渲染压力

9.切线来源

定义应如何导入或计算顶点切线。仅当“法线来源”设置为“Calculate”或“Import”时,此选项才可用

Import仅在法线来源设置为“Import”时可选,从FBX文件中导入切线数据

Calculate MikkTSpace/Calculate Tangent Space使用MikkTSpace标准进行切线计算,但不适用于法线贴图着色器

Calculate Legacy传统的切线计算

Calculate Legacy - Split Tangent使用传统的切线计算,并在UV图表中拆分“如果正常的地图照明被网格上的接缝破坏,请使用此选项。”通常只适用于人物模型

None不导入也不计算顶点切线,这不适用于法线贴图着色器

10.交换UV

是否在网格中交换UV,如果漫发射贴图使用了来自光照贴图的UV

11.展开光照烘焙UV(默认不勾选)

为模型展开一道UV以接受unity中的光照烘焙(非实时的渲染光照)效果,从而将烘焙光照以光照贴图的形式表现在模型表面

注意!!!场景中的静态物体模型,需要接受Unity光照烘焙的物体模型,一定要进行这个UV展开

---------4.5.2.2 Rig窗口

Rig窗口用以控制模型的骨骼绑定信息,Avatar替身的来源

1.骨骼绑定类型

FBX中使用的骨骼动画的类型,并影响Rig窗口的各项后序设置

None无骨骼动画,unity将忽略FBX中的所有骨骼绑定信息,选择None不一定模型中就不包含动画,动画包含引入的设置在Animation窗口中完成,一种情况是我们使用了非骨骼动画时,选择了None

Legacy旧版本的unity动画绑定(unity 3.x版本及以前)

Generic非人形骨骼动画绑定

Humanoid人形骨骼动画绑定

2.Avatar Definition替身来源

Avatar替身是unity为管理骨骼动画所创建的一种保持节点信息的文件

通过在Animator中指定所需要用到的Avatar,Animator动画状态机在运行时就能根据Avatai中提供的节点信息,寻找子物体中的对应节点并对其赋予动画的控制,完成骨骼动画与含骨骼绑定的模型的适配

这里的替身来源主要有两个,

1.从该模型创建出一个Avatar替身

2.使用其他模型配置好的Avatar替身

创建出的Avatat替身文件,尤其是人形骨骼的Avatar替身需要进行配置工作,绑定骨骼,设置初始T-Pos,通过复用其他模型创建好的Avatar替身可以减少繁杂的配置操作,尤其是我们导入只包含骨骼动画的FBX时,复用角色模型的Avatar替身就可以快速完成骨骼动画于人物模型的适配

3.Optimize Game Object骨骼节点嵌入优化

仅在替身来源为从该模型创建时可用

选择后将在实际应用模型时,剔除FBX中的骨骼节点,节点信息将保持在Avatar 和 Animator中,即将骨骼节点嵌入到动画系统内部,以保证更高效的节点提取和变换

模型的SkinnedMeshRenderers蒙皮渲染使用动画系统内部的骨骼节点,蒙皮网格的矩阵提取也将变为多线程,从而提高渲染效率

3.1 导出保留与剔除节点

配合骨骼节点嵌入优化使用,勾选与否决定了是否会将该节点当作骨骼节点在最终使用模型时,进行剔除和动画系统的嵌入

通常我们设置好父子关系,并将骨骼节点单独保存在一起,不勾选,让unity完成剔除嵌入

模型的蒙皮渲染及其他配饰,我们进行勾选来保证不将其剔除

通常情况下我们不需要设置此项(不进行任何勾选时),unity会根据Avatar替身绑定时使用到的节点来进行剔除和嵌入

但一种情况是我们在标准骨骼节点之外创建了额外的骨骼节点,比如人物的翅膀,没有在创建标准人物Avatar替身时被用到,但我们并也希望完成剔除嵌入,我们就需要手动设置此项

另一种情况是由于骨骼节点的剔除导致最终模型中不包含骨骼节点,而我们可能需要在脚本中获取某些骨骼的完成一些动态操作,我们可以部分勾选我们需要在脚本中获取到的骨骼,让它不被剔除

4.Generic时,根节点指定

仅在骨骼类型为非人形骨骼,且从该模型创建Avatar替身时可选

为非人形骨骼绑定指定一个根节点骨骼

5.Humanoid时,人形骨骼绑定设置

左边的小图标,对勾或叉,代表unity是否自动完成了模型骨骼与标准人形骨骼的绑定

但由于T-Pos标准姿态问题,即使为对勾,我们也需要点击该项去检查T-Pos是否正确

具体设置在下文 7.人物动画,0帧T-Pos问题 中提到

---------4.5.2.3 Animation窗口

用于从FBX文件中引入动画,动画剪辑的设定

1.是否导入解析约束组件

如果FBX中的动画中使用了约束则需要勾选

unity会对FBX中的约束信息进行解析,并添加添加相应的Constraint组件并完成对应的链接

2.是否需要导入动画

是否从FBX中导入读取动画,如果FBX文件中包含了动画则需要勾选

下方所有选项仅在勾选导入动画时可以进行设置

3.动画烘焙

解析并烘焙使用了 IK反向动力学 或 Simulation仿真模拟 创建的非帧动画,转化为使用关键帧储存运动信息的通用动画格式

通常不可用,因为我们通常导入的FBX文件中如果包含动画,本身就是帧动画的形式

4.曲线重采样(unity 2019版本)

解析动画曲线,并重采样为四元数的形式

默认启用,在原动画存在关键帧间差值时,为保持原有曲线应禁用此项

5.动画压缩

这里一般使用默认的Optimal最佳模式就好

但Optimal最佳模式仅适用于骨骼动画,其他设置选项:

Off禁止动画压缩,Unity不会减少关键帧中的导入计数,这可以提高动画的精细程度,如果原动画在制作时有强调精细程度,比如齿轮的咬合转动。但这回导致更高的内存消耗,降低运行时的性能,以及更高的发布打包时的文件大小

Keyframe Reduction关键帧缩减,通过“导入时减少冗余关键帧”来降低文件大小和运行时的内存消耗

Keyframe Reduction and Compression关键帧缩进与压缩(unity2019版本可用),在Keyframe Reduction关键帧缩减的基础上,通过“动画中存储动画时,减少导入和压缩关键帧时的关键帧”,进一步缩减文件大小

6.压缩比率设置

决定压缩多大精度变化下的旋转,移动,缩放曲线,值越小精度越高,值越大压缩比率越高

7.自定义属性导入

通过FBX文件中设置用户自定义属性,以及extraUserProperties传入与FBX中相同的名称,unity可以通过传入Assert后处理器,来链接FBX中的用户自定义属性设置

那么下面的Animation Clip动画剪辑的相关设置是为结合unity的Miscellaneos动画系统,剪辑FBX文件中帧动画,生成动画切片的相关设置部分。学习过unity的动画系统的话自然会有所了解,或者可以参见这篇文章中的一个章节,本文就不过多赘述了

---------4.5.2.4 Materials窗口

设置FBX模型的材质导入以及相关链接

1.是否从FBX文件中引入材质

2.设置材质颜色反射率

启用时为伽马颜色空间的反射率

禁用时为线性颜色空间

3.材质位置

Use Embedded Materials 材质被嵌入保存在FBX文件中,这是现在3dMax导出FBX时的材质保存模式

Use External Materials (Legacy) 材质从外部提取,这是旧的材质保存模式,在导入FBX文件的同时会在FBX文件外部创建出材质

4.Use Embedded Materials 嵌入式材质保存相关设置

这是当前unity的默认材质位置设置,也是包括3dMax在内的通用建模软件导出FBX的材质储存模式

这种材质储存模式你应该可以在Assert窗口的FBX卷展中看到有材质的储存

嵌入FBX内部的材质是只读的,并不能进行修改

此外可以通过下方的材质选择,来重建映射

从而你可以在Unity中使用特定的shader创建出材质,映射到模型上

5.Use External Materials (Legacy)外部材质提取式的相关设置

可通过下方的Naming 以及 设置 范围选项来查找对应范围的材质,并按照FBX文件中的材质映射赋予材质

无法重建材质映射

使用了新版的Use Embedded Materials 嵌入式材质保存的FBX模型也可以选择使用这个旧模式来将内部储存的材质外放

这可以使得材质能够被再次修改,且如果外部材质丢失,会自行从FBX中尝试提取一次材质,包括材质贴图,有时具有找回材质的作用

目前Revit导出的FBX模型仍是使用这种旧版的材质储存模式,需要通过选择这个模式将跟随FBX的隐藏文件夹中的材质解析出来,材质的贴图也被保存在外部的隐藏文件中,需要通过这个模式进行解析获取

6.3dMax层级关系与导入后的表现---6.1 3dMax中的层级关系

在使用3dMax进行建模时,我们主要会通过以下4种方式来调整模型/物体之间的层级关系

元素包含关系

同一可编辑多边形/网格/面片中的元素包含

链接关系

通过链接来绑定父物体

使用虚拟物体

层组关系

---6.2 3dMax中的层级关系在导入Unity之后的表现

元素包含关系并不能转换为父子关系,导入unity后同一个物体的所有元素仍是一体的

链接关系会被转换为unity中的父子关系表现

因而使用Max的链接是我们构建父子关系的方法

虚拟物体会形成一个空节点

使用虚拟物体作为父节点组合多个物体是十分好用的策略

层组会形成一个以层组命名的空节点,组内的物体会是这个空节点的子物体

通常不建议在对接Unity时使用嵌套层组

使用层组进行物体的组合管理是建模---动画时的一个习惯,但最好不要在对接Unity时使用层组,由于层组会形成空父节点,大量的进行层组嵌套会产生许多不必要的空节点,造成冗余

在进行Unity对接时,我们更多的是通过元素包含来嵌套多个网格为一个物体(并且也只产生一个draw call),并通过链接关系来设置模型之间的父子关系,利用虚拟物体参与链接进行物体的组合

(关于元素包含多个网格,是否会影响传输效率,造成瓶颈,建模时保持物体网格拓扑性相关将在以后的更新中讨论)

此外如果不进行链接,一次选中多个没有父子关系的物体导出,导入到unity中,会自行生成一个以FBX文件名称命名的空的父物体节点来包含一次性导出的多个物体

---6.3 3dMax中的层级设置建议

不可以用元素来区分出不同物体

如果父子关系要求比较复杂,应使用链接绑定正确的父子关系

可以选中多个物体一起导出,会自行生成父物体,所有选中的物体作为一级子物体,如果你对这种包含关系满意的话

7.人物动画,0帧T-Pos问题

前面有提到过,即使模型设置中的人物骨骼,configure前方出现对勾,你还是要点击它去调整Avatar的T-Pos状态,因为对勾这是骨骼绑定与标准绑定一致,但T-Pos不一定正确,

configer前出现了对勾

仅是右边的骨骼绑定与标准人物骨骼设置相同,可以看到左边场景窗口的红色骨骼是T-Pos拾取不正确的骨骼

除非你从别的地方复用Avatar,否则用于创建Avatar的模型一定要检查T-Pos是否正确

---7.1 用于创建人物Avatar的标准人物模型,0帧务必摆标准T-Pos不要做动作

尤其这个人物模型是要用于创建Avatar的时候,后序的含人物骨骼动画的FBX如果已经创建好了人物的Avatar,直接复用就行,0帧就不必非得是T-Pos

但如果创建人物Avatar的标准人物模型0帧不是T-Pos,可能出现人物动画的错误

因为unity的动画系统是以T-Pos为标准姿态,在此基础上进行演算,来进行动画控制的,T-Pos的不正确会导致人物骨骼动画变得奇奇怪怪

向右跑的动画,由于T-Pos的不正确导致无法进行正常的动画控制演算---7.1.1 依然有可能出现的僵局

case 1:

由于复用Avatar的条件是骨骼的层级关系和命名必须一致

我们拖入人物模型创建的Avatar给下载的动作资源FBX进行Avatar复用,由于骨骼命名的不一致而出现了错误

某些情况我们是从不同的地方分别获取了人物模型的资源,和动作资源,由于骨骼命名的不一致我们无法直接复用Avatar

case 2:

美术给你的人物模型TA都做了动画,导致0帧不是T-Pos,而且没有给出标准T-Pos的人物模型

一般这种情况你应该找美术,要求给出有标准T-Pos的人物模型,用于创建Avatar

但如果TA由于各种原因不给你标准的T-Pos人物模型,你就只能自己调整了

---7.2 0帧不是T-Pos unity中的正确调整与补救方法

1.使用自动Pos纠正选项最坏的情况,最下方的选项,环境T-Pos也是可以用的,尝试用使用自动纠正

一般来说,使用自动Pos纠正能够完T-Pos的纠正

但某些坏的情况下使用了自动Pos纠正也无法完成纠正,动画显示依然不正确

尽管使用环境T-Pos纠正后显示全绿但我们发现播放动画时,人物的左脚似乎并不正确,好像左脚多扭了一圈

这是因为某些情况可能人物的某些关节被多扭了一圈两圈,尽管转对了T-Pos但因为多转了一圈两圈,导致Base姿态依然不对

2.对症下药法

我们发现只有人物左脚不对

先使用和之前一样的T-Pos纠正观察左脚的旋转参数对比姿态正确的相似骨骼的旋转数据拷贝正确姿态的相似骨骼数据,在加以手动旋转调整3.从0帧手转出T-Pos

首先是一个原则,绝对不要一次旋转超过90度(任何一个轴),要耐心不要心急,否则转不对,或者转对了(全绿)却是错的

手动旋转的意义在于,0帧的时候不管人物摆什么姿势,都能通过各骨骼小于360度的旋转转回标准的T-Pos,不存在自动纠正多转一圈两圈的问题

先使用ReSet使人物返回0帧状态反复点击环境T-Pos和ReSet确定中心的那块三角形骨骼Hips需要旋转的方向腰部三角骨骼Hips是人物骨骼的组高级父骨骼,先使用世界旋转,转向环境T-Pos中确认的朝向Local旋转使Hips转对位置向上依次使用Local旋转调整骨骼的位置,保证骨骼变绿为向两边依次使用Local旋转调整手臂及手指骨骼从侧面切换视角,对齐手臂骨骼从正面切换视角,对齐手臂骨骼正侧面对齐后,再加上没有用到的那个轴旋选转一下,一般就可以使骨骼正确还是转不对手臂,反复切换各个角度,仔细检查对齐调整手指骨骼前,先调平手掌按照之前的要领旋转令人抓狂的手指骨骼

参考正确的骨骼Local旋转轴的朝向去旋转相似的骨骼参考正确的指尖骨,对齐红绿两轴,再转蓝轴,完成调整结合实际分析转轴,对齐前的骨骼位置,完成调整

一块一块调整,调整对一块再转下一块,多次旋转调整不对,应回退到最初状态,重新调整

T-Pos时人物骨骼四肢出于同一竖平面上,以此为参考旋转四肢的根骨骼手指实在转不对,且没有手指骨骼动画时可以放弃,但人物躯干头部,腿脚,以及到手掌骨之前的手臂必须旋转正确

4.你可以尝试获取相同来源的骨骼命名相同的其他FBX动画资源或人物模型,找一个手转T-Pos容易点的,转出来之后复用给需要的FBX动画资源OK经过T-Pos的调整动画终于正常了

/*

null

*/



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3