Unity3D脚印6——模型动画
原地址:http://www.cnblogs.com/ybgame/archive/2013/02/21/2920009.html
如何导入一个模型,导入的模型在unity3d的project面板中是怎样显示的?包含什么内容?如何加载到场景中?怎样去控制它?模型和动画之间的关系?
【模型导入】:
Unity可以读取fbx,dae,3ds,dxf,obj等格式的文件,可以在这里找到FBX导出器,
每一个被导入的项目中的模型,都包含下面这些东西:
Meshes 网格,每个模型都是由无数的三角面组合而成
相关选项:
Scale Factor 缩放系数 调整模型的比例
Use File Units 使用此文件单位 只适用于3dsMax文件,启用时1Max=1Unity,否则1厘米Max=1Unity
Mesh Compression 网格压缩 在差异允许的范围内,尽量调高这个值
Mesh Optimization 网格优化 决定网格中的三角形排列顺序
Generate Colliders 生成碰撞体 是否生成网格碰撞体
Swap UVs 交换UV 当有光照贴图的物体的UV通道不正确时启用此选项
Generate Lightmap UVs 产生光照贴图UV 为光照贴图创建第二个UV通道
Normals & Tangents 法线和切线,这主要是用来描述三角面朝向用的,可以应用在裁切(只显示正面,不显示背面)光照上
相关选项:
Normals 法线 默认导入法线,可选Calculate根据平滑度计算法线,也可禁用
Tangents 切线 当启用法线时,切线才有作用,默认为自动计算,可以选择导入和禁用
Smoothing Angle 平滑角 设置边角的平滑程度,用来切分法线贴图切线?
Split Tangents 分离切线 如果您的网格上的接缝破坏了法线贴图光照,启用此选项。这通常只适用于角色
Materials 材质,主要是描述颜色,在各种光照效果下的显示,以及上面的贴图!
相关选项:
Import Materials 导入材质 禁用则所有材质为漫反射
Material Naming 材质命名 贴图名,材质名,模型-材质名等等命名方式
Material Search 材质搜索 决定如何根据材质命名查找已有的材质
Animations 动画,如果这个文件附带了动画的话,可以在这里看到
相关选项:
Generation 生成 控制动画的导入,以及动画存储的位置(Root还是Node)
Bake Animations 烘焙动画 用于使用了IK的动画
Animation Wrap mode 动画循环模式
Split Animations 分割动画
Anim.Compression 动画压缩的方法
Anim.Compression.Errors 当压缩关键帧的时候,设置误差控制
需要注意的是!我们导入的模型,并不包含贴图,要导入一个模型需要同时导入模型材质用到的贴图! u3d搜索贴图的规则是模型所在路径下的Textures文件夹,然后逐步搜索上级目录的Textures文件夹,搜索不到就进行全局搜索(慢,而且当两张纹理同名的话,可能会找错)
每一个导入的材质,Unity使用下列规则:
1. 如果禁用了导入材质选项,所有材质默认为漫反射材质
2. 根据材质名设置为Unity的材质名
3. 在已有的材质中寻找名字相同的材质
4. 找到该材质则直接赋给对象,否则生成新的材质
Unity提供了两种碰撞器,一种Mesh Colliders 网格碰撞器,可以精确地检测碰撞,而Primitive Colliders 原始碰撞器,虽然没有前者精确,但效率高很多,应该尽量使用这种
如果你有一个从高精度多边形版本生成的带法线贴图的角色,你应该以180度的平滑角度(Smoothing angel)导入此角色的游戏质量版本。这将防止由于切线切割在光照中产生的奇怪的接缝。如果在应用了这些设置后仍然存在接缝,启用在UV接缝处分割切线选项(Split tangents across UV seams)。
【动画导入】
Maya的.mb,.ma文件,Cinema 4D的c4d文件和fbx文件都支持导出动画,当我们导入这些模型的时候,可以顺带导入动画
1.分割动画 使用动画分割导入动画,所有的动作都放在同一个模型中,最为节省资源,导入模型的时候,分割动画会被自动导入,可以在拆分动画表中看到所有的动画片段
2.@动画 创建单独的模型文件,并按照"模型名"@"动画名".fbx这样的格式命名,导入模型文件时,Unity会自动导入该模型相关的动画文件,在导出这样的文件时,单独导出模型,另外再导出所有动作的剪辑。
3.反向动力学 设置烘焙IK和仿真箱????
【动画脚本】
如果想播放一个简单的动画,可以使用Animation.Play;
如果想在动画之间交叉淡入,可以使用Animation.CrossFade;
如果想改变动画模式(循环,一次,乒乓),可以改变动画导入设置里面的动画帧的WrapMode,或者在运行时改变AnimationState.wrapMode的值;
AnimationState可以用于改变动画的层,修改播放速度,并且直接控制融合与混合。
动画叠加,混合,分层等等——参考u3d的hello world——angrybots
Animation是一个组件,可以被添加到GameObject上,当我们把脚本挂载到一个GameObject上的时候,可以通过animation成员变量来访问挂载在它身上的动画,动画的方法有这些
- Animation
- AddClip添加剪辑
- animateOnlyIfVisible可见时动画
- animatePhysics是否物理动画
- Blend混合
- clip剪辑
- CrossFadeQueued淡入淡出队列
- CrossFade淡入淡出
- cullingType消隐类型
- GetClipCount获取剪辑数
- IsPlaying是否在播放?
- isPlaying是否在播放?
- localBounds本地边界框
- playAutomatically自动播放
- PlayQueued播放队列
- Play播放
- RemoveClip移除剪辑
- Rewind倒回
- Sample采样
- Stop停止
- SyncLayer同步层
- this [string name]操作名字
- wrapMode循环模式
动画融合:
用于确保角色的平滑动画,当我们在游戏中要从一个动画过渡的另外一个动画,我们不希望这两个动作之间是突然跳转,而希望平滑地过渡。
我们使用CrossFade("animate name")来平滑地切换到另外一个动画(这中间可能是做了一个补间动画)
动画层:
层允许群组动画和优先级别,动画之间的过渡,可以用CrossFade或者指定手工融合权重来自动处理动画的权重,当两个动画的权重都是100%,Unity生成最终动画会规格化权重,这意味着两者都占50%的权重,但在考虑优先级的情况下,需要设置哪个动画的权重更高,还要确保权重之和为100%,使用层的话会容易很多。
要做到这点最简单的方法是在射击时简单的保持行走和空闲动画,然后我们需要确保射击动画比空闲和行走动画在更高的层。这意思是射击动画将首先接收融合权重。行走和空闲动画仅当射击动画不使用融合权重100%时,接收权重。因此,交叉淡入淡出射击动画时,权重将从0开始很短时间内变为100%,在开始时步行和空闲层仍然会收到融合权重,但当射击动画完全切入时,它们不再接收权重,这正是我们所需要的!
1 function Start () { 2 // Set all animations to loop 3 animation.wrapMode = WrapMode.Loop; 4 // except shooting 5 animation["shoot"].wrapMode = WrapMode.Once; 6 7 // Put idle and walk into lower layers (The default layer is always 0) 8 // This will do two things 9 // - Since shoot and idle/walk are in different layers they will not affect 10 // each other's playback when calling CrossFade. 11 // - Since shoot is in a higher layer, the animation will replace idle/walk 12 // animations when faded in. 13 animation["shoot"].layer = 1; 14 15 // Stop animations that are already playing 16 //(In case user forgot to disable play automatically) 17 animation.Stop(); 18 } 19 20 function Update () { 21 // Based on the key that is pressed, 22 // play the walk animation or the idle animation 23 if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1) 24 animation.CrossFade("walk"); 25 else 26 animation.CrossFade("idle"); 27 28 // Shoot 29 if (Input.GetButtonDown ("Fire1")) 30 animation.CrossFade("shoot"); 31 }
Animation Playback and Sampling 动画播放和取样:
取样这个词可能不大好理解,取样在Unity里面是涉及到渲染的一个术语,就是对像素取样来进行综合运算,我们的动画是在不断运动的,将动画当前的运动状态提取出来,并渲染到屏幕上,这是我理解的取样。
我们在3ds Max或者Maya等模型编辑工具中编辑一个动画,我们按照某个帧速率(FPS)来创建这个动画,在动画被导入到U3D的时候,这个帧速率也会被导入,所以会跟编辑器的速率保持一致。
但我们游戏的运行帧速率并不稳定,可能有硬件的原因或者要渲染的对象,处理的逻辑复杂度不一样,而导致的帧速率不稳定,如果我们按照它设定的帧率来播放,动画就会一卡一卡的。Unity是在变化的帧频中对动画进行取样,而不在制作时的帧频。3D电脑图形动画不是由分散的动画组成,而是连续的曲线。这些曲线可以让我们在任何时间点取样,而不只是对应某一个原始帧的时间点。这样当我们的电脑比较快的时候,动画将会更加地平滑和流畅。
对于大多数的实际应用,事实上Unity对变化帧速的采样不是我们需要关切的,然而,如果你的某个游戏逻辑依赖于动画变换或属性的动画在一个非常特殊的配置,那必须知道这一点。例如,如果有一个动画是把一个物体30帧内从0旋转到180度,想从代码中知道当它已达到了一半,你不能写一段条件语句来检查现在旋转值是不是90度。因为 Unity 依照游戏的变化速率来对动画取样,它可能在旋转快到90度时进行取样,或刚好过90度的时候取样。当在一个动画指定一个点到达时,需要通知, 应该使用AnimationEvent来代替。
还要注意的变化帧速率采样的结果,一个使用WrapMode.Once模式播放的动画的采样不一定是精确的最后一帧。在游戏中很有可能是刚好结束前的某一帧,在下一帧时间可能超过动画的长度,所以它被禁用,而不再采样。如果需要动画的最后一帧取样精确,你可以使用WrapMode.ClampForever。
如在这种情况下,动画在这种情况下,动画将保持无限取样最后一帧,直到你停止动画。
【动画视图】
按下Ctrl+6,可以弹出动画编辑视图,选择Hierarchy面板上的任意对象,可以编辑它们的动画。