一、序列帧动画
(一)什么是序列帧动画
我们最常见的序列帧动画就是我们看的日本动画片,以固定时间间隔按序列切换图片,就是序列帧动画的本质
当固定时间间隔足够短时,我们肉眼就会认为图片是连续动态的,进而形成动画(会动的画面)
它的本质和游戏的帧率概念有点类似,原理就是在一个循环中按一定时间间隔不停的切换显示的图片
(二)制作序列帧动画
方法一:
-
创建一个空物体
-
创建一个动画
-
直接将某一个动作的序列帧拖入窗口中
方法二:
直接将图片拖入 Hierarchy 层级窗口中
注意:可以修改动画帧率,来控制动画的播放速度
二、骨骼动画 —— 2D Animation
2D 骨骼动画是利用 3D 骨骼动画的制作原理进行制作的
将一张 2D 图片分割成 n 个部位,为每个部位绑上骨骼,控制骨骼旋转移动,达到用最少的 2D 美术资源做出流畅的 2D 动画效果
在 Package Manager 窗口搜索 2D Animation 并安装
导入工具后,在 Sprite Editor 窗口会多一个选项 Skinning Editor
(一)单张图片骨骼编辑
菜单栏按钮:
- Reset Pose:将角色谷歌和关节回复到原始位置
- Sprite Sheet:图集显示(特殊图片格式 psb 才显示)
- Copy:复制当前选择的数据
- Paste:粘贴复制数据
Bones:骨骼
-
Preview Pose:预览模式,可以预览动作并不会真正地改变设置
-
Edit Bone:编辑骨骼,可以改变骨骼位置、长度、方向、名称等
-
Create Bone:创建骨骼,需要双击图片进行选中后才能创建骨骼
左键创建骨骼,默认每一个骨骼是上一个骨骼的子对象
右键取消父子关系继续创建骨骼
-
Split Bone:拆分骨骼,将一个骨骼一分为二
Geometry:蒙皮
蒙皮决定了骨骼主要控制哪一部分
- Auto Geometry:自动蒙皮
- Outline Detail:边缘细节,值越大,轮廓越细致
- Alpha Tolerance:阿尔法公差值,控制蒙皮细节
- Subdivide:细化程度,控制蒙皮细节
- Weights:是否自动设置权重,一般勾选
- Edit Geometry:编辑蒙皮
- Create Vertex:创建顶点
- Create Edge:创建边线
- Split Edge:拆分边,用一个新的顶点分离一个边
Weights:权重
权重决定了当骨骼运动时如何影响顶点和边
- Auto Weights:自动赋予权重
- Weight Slider:编辑顶点和边的权重
- Mode:计算模式
- Add And Subtract:加减法
- Grow And Shrink:增长和搜索
- Smooth:平滑
- Bone:设置权重的骨骼
- Normalize:标准化设置
- Amount:数量级
- Vertex Weight:顶点权重对应的骨骼
- Mode:计算模式
- Weight Brush:用笔刷赋予权重
- Bone Influence:主要用于在 psb 图片中使用骨骼控制点的图片关联
设置完成后,将图片拖入 Hierarchy 窗口中,为其添加 Sprite Skin 脚本,点击 Create Bones 按钮,将生成骨骼
之后便可以通过 Animation 为其添加动画
(二)图集图片骨骼编辑
在编辑之前,我们需要对图片进行如下操作:
- 设置 Sprite 为图集模式
- 对图集图片进行切片
具体对图集中每一张图片的骨骼操作与上述类似
在 Hierarchy 窗口中,创建一个根物体当作图集的父对象,依次将每一张图拖进根物体下。
每次拖入一张图后,为其添加 Sprite Skin 脚本,点击 Create Bones 按钮,将生成骨骼
按照图集中图片的父子关系继续拖入场景中,可以修改图片 Sprite Renderer 组件上的 Order In Layer 参数来调整图片的前后显示
(三)psb 图片骨骼编辑
PS(photoshop)是一款强大的图像处理软件,在各领域都被广泛使用,在游戏行业中也是美术同学使用最多的图像处理软件之一
PSD 和 PSB 两种格式,都是 PS 这款软件用于保存图像处理数据的文件格式
PSD 和 PSB 两种格式并没有太大的区别,最大的区别是 PSD 格式兼容除 PS 以外的其它一些软件,而 PSB 只能用 PS 打开
在 Unity 中官方建议使用 PSB 格式,需要在 Packages Manager 窗口中引入 2D PSD Importer 工具包
PSB 文件关键参数:
PSB 文件也是一种图片文件,因此大多数参数与一般的图片参数一致(见 图片导入与图片设置),这里主要讲解其独有的参数
- Extrude Edges:图片边缘延伸网格,一般不修改
- Import Hidden:是否导入 PSB 文件中隐藏的图层,一般不勾选
- Moszic:启用后,将图层生成 Sprite,并将它们合并成单个纹理,默认勾选
- Character Rig:是否启用人物已经绑定的骨骼,默认勾选
- Use Layer Grouping:使用 PSB 文件中的层分组
- Pivot:轴心点位置
- Reslice:从导入层重新生成 Sprite,并清除对 Sprite 的任何更改,只有启用 Moszic 后有用
- Keep Duplicate Name:让 Sprite 名称保留 PSB 文件中的名字
骨骼编辑界面变化:
在为每一个图层生成蒙皮时,可能会覆盖其他图层的骨骼,这时可以在 Bone Influence 选项界面中设置影响的骨骼
三、反向动力学 IK
在骨骼动画中,构建骨骼的方法被称为正向动力学,它的表现形式是,子骨骼(关节)的位置根据父骨骼(关节)的旋转而改变
用我们人体举例子,当我们抬起手臂时,是肩部关节带动的整个手臂的运动,用父子骨骼理解的话就是父带动了子
IK 全称是 Inverse Kinematics,翻译过来的意思就是反向动力学的意思
它和正向动力学恰恰相反,它的表现形式是,子骨骼(关节)末端的位置改变会带动自己以及自己的父骨骼(关节)旋转
用我们人体举例子,当我们拿起一个杯子的时候是用手掌去拿,以杯子为参照物,我们移动杯子的位置,手臂会随着杯子一起移动
用父子骨骼理解的话就是子带动了父
在 Package Manager 窗口中引入 2D IK 工具包,需要在 Advanced 高级选项中选中 Show preview packages(显示预览包),这样才能看到2D IK相关内容
注意:如果在引入包时报错,需要在 Windows 防火墙中添加入站规则
(一)IK Manager 2D
将上一小节的 PSB 文件拖入 Hierarchy 窗口中,为其创建父对象 Player 来方便管理,给 Player 添加 IK Manager 2D 脚本
- IK Solvers:IK 解算器,在这里添加 IK
- Chain(CCD):可以自定义影响 N 个关节点,不能反向
- Chain(FABRIK):可以自定义影响 N 个关节点,可以反向
- Limb:只会影响 3 个关节点,一般用于控制四肢
- Weight:权重,当有多个 IK 控制同一点时,权重会影响控制的百分比
- Restore Default Pose:恢复默认位置
添加完成后,为需要添加 IK 效果的骨骼新建一个空物体 IK,并将其位置移动到骨骼末端位置处
在 IK Manager 2D 脚本中点击加号,新建一个 IK 对象,会发现在 Player 下面多了一个 IK 对象并挂载了对应的脚本
(二)CCD Solver 2D
- Effector:默认的 IK 点位置
- Target:根据 IK 点位置生成的 IK 对象,
- Chain Length:IK 影响骨骼的数量,设置成功后,会发现被关联的骨骼会出现绿色的圆圈
- Iterations:算法运行的次数,一般不修改
- Tolerance:容错程度,一般不修改
- Velocity:速度,一般不修改
- Constrain Rotation:约束旋转程度
- Solve from Default Pose:从默认姿势进行求解计算
- Weight:权重
设置好参数后,点击 Create Target,Target 会被创建在该脚本挂载的物体的子物体上并被自动关联
(三)Fabrik Solver 2D
- Effector:默认的 IK 点位置
- Target:根据 IK 点位置生成的 IK 对象,
- Chain Length:IK 影响骨骼的数量,设置成功后,会发现被关联的骨骼会出现绿色的圆圈(颜色可以设置)
- Iterations:算法运行的次数,一般不修改
- Tolerance:容错程度,一般不修改
- Constrain Rotation:约束旋转程度
- Solve from Default Pose:从默认姿势进行求解计算
- Weight:权重
(四)Limb Solver 2D
- Effector:默认的 IK 点位置
- Target:根据 IK 点位置生成的 IK 对象,
- Flip:旋转反向,用于控制 IK 的旋转方向
- Constrain Rotation:约束旋转程度
- Solve from Default Pose:从默认姿势进行求解计算
- Weight:权重
IK 的用处:
- 瞄准功能
- 头部朝向功能
- 拾取物品功能
对于有指向性的功能,我们都可以通过 IK 来达到目的最大的作用,可以方便我们进行动画制作
四、换装
(一)在同一个 psb 文件中制作换装资源
- 在 ps 中制作美术资源时,将一个游戏对象的所有换装资源都摆放好位置
- 当我们导入该资源时,要注意是否导入了隐藏的图层
在右侧的 Visibility 面板上为每一个图层设置分类,右边的标签相当于其在分类中的名称
注意事项:
- 每个部位 关联的骨骼要明确设置
- 为同一个部位的不同装备分组
骨骼、蒙皮设置完成后,将图片导入场景中,会发现其自动添加了精灵资料库 Sprite Library,用于确定类别分组信息
同时, Unity 会为每一个设置了类别的装备添加精灵解算器 Sprite Resolver,用于确定部位类别和使用的图片
使用代码进行换装示例:
using UnityEngine.Experimental.U2D.Animation;
private Dictionary<string, SpriteResolver> equipDic = new Dictionary<string, SpriteResolver>();
// 1.获取各部位的SpriteResolver(需要引用命名空间)
// 2.使用SpriteResolver的API进行装备切换
// GetCategory() 获取当前部位默认的类别名
// SetCategoryAndLabel 设置当前部位想要切换的图片信息
private void Start() {
SpriteResolver[] srs = this.GetComponentsInChildren<SpriteResolver>();
for (int i = 0; i < srs.Length; i++) {
equipDic.Add(srs[i].GetCategory(), srs[i]);
}
ChangeEquip("Cask", "CASK 1");
}
public void ChangeEquip(string category, string equipName) {
if (equipDic.ContainsKey(category)) {
equipDic[category].SetCategoryAndLabel(category, equipName);
}
}
(二)在不同 psb 文件中制作换装资源
保证个部位在 PS 文件中的统一,基础部位可选择性隐藏
注意事项:不同文件的骨骼信息必须统一,所以我们直接使用复制的方式
1.首先创建 Sprite Library Asset 数据文件,对参数其进行设置
2.为根对象添加 Sprite Library 并关联数据文件
3.为换装部位关联 Sprite Resolver
换装较少的游戏,比如只有面部表情更换,可以使用同一 psb 文件方案
换装较多的游戏,比如各部位有 n 种装备,可以使用不同 psb 文件方案,拓展性更强
一切根据需求而定
五、骨骼动画 —— Spine
Spine 是一个收费的跨平台的 2D 骨骼动画制作工具,它支持 Unity,UE,Cocos2D,Cocos2D-x 等等游戏引擎
相对 Unity 2018 才推出的 2D Animation,Spine 是目前商业游戏中较为常用的骨骼动画制作方案 稳定且高效
官方地址:http://zh.esotericsoftware.com/
制作骨骼动画是美术人员的工作,除非你是要做独立游戏,美术程序一人包,那么我们没有必要去学习如何通过 Spine 制作骨骼动画
我们只需要学习如何在 Unity 中通过程序使用 Spine 制作的资源
如果想要学习如何制作 Spine 骨骼动画,可以根据官网提供的教学内容进行学习
有了 Spine 提供的支持 Unity 开发的运行库,我们才能在 Unity 中使用 Spine 制作的骨骼动画
你可以简单理解其实就是官方写好的识别文件处理文件呈现效果的代码
我们只需要学习如何使用它提供的 API 即可
(一)骨骼动画使用
Spine 导出的资源有 3 个文件:
- .json 存储了骨骼信息
- .png 使用的图片图集
- .atlas.txt 图片在图集中的位置信息
当我们把这三个资源导入到已经引入了 Spine 运行库的 Unity 工程后,会自动为我们生成:
- _Atlas 材质和 .atlas.txt 文件的引用配置文件
- _Material 材质文件
- _Skeleton Data、json 和 _Atlas 资源的引用配置文件
创建动画的两种方式:
1.直接将 _Skeleton Data 文件拖入到场景中,选择创建 Skeleton Animation 对象
2.创建空对象,然后手动添加脚本 Skeleton Animation 进行关联
(二)骨骼动画参数
骨骼数据文件:
- Skeleton JSON:骨骼数据文件
- Scale:缩放大小
- Skeleton Data Modifiers:骨骼数据修改器
- Blend Mode Materials:混合模式材质
- Apply Additive Material:是否使用叠加材质
- Additive Material:叠加材质
- Multiply Material:相乘材质
- Screen Material:屏幕材质
- Atlas Assets:图集资源
- Mix Setting:混合设置
- Animation State Data:动画状态数据
- Default Mix Duration:默认混合持续时间
- Add Custom Mix:添加自定义混合
- Animations:动画
- Setup Pose:设置姿势
- Create Animation Reference Assets:创建动画参考资源
- Slots:插槽,一个部位有多张图片构成,可以在这里预览
- Skeleton Mecanim:骨骼控制
- Controller:关联动画控制器
骨骼动画脚本:
-
Skeleton Data Asset:关联的骨骼动画信息
-
Sorting Layer:所在排序层
-
Order in Layer:排序层的序号
-
Mask Interaction:与精灵遮罩交互的方式
- None:不与场景中任何精灵遮罩交互
- Visible Inside mask:精灵遮罩覆盖的地方可见,而遮罩外部不可见
- Visible Outside mask:精灵遮罩外部的地方可见,而遮罩覆盖处不可见
-
Advanced:高级设置,一般不修改,了解即可
- Initial Flip X / Y:初始反转 X / Y
- Update When Invisible:不可见时是否更新
- Nothing:不更新
- Only Animation Status:仅动画状态
- Only Event Timelines:仅事件
- Everything Excepts Mesh:除了网格其他都更新
- Full Update:更新所有
- Use Single Submesh:使用单个子网格
- Fix Draw Order:固定提取顺序
- Immutable Triangles:不变三角形
- Clear State On Disable:禁用时清除状态
- Separator Slot Names:分隔符插槽名称
- Z Spacing:Z 间距
- Vertex Data:顶点数据
- PMA Vertex Colors:PMA 顶点颜色
- Tint Black:淡黑色
- Add Normals:添加法线
- Solve Tangents:求解切线
- Add Skeleton Utility:添加骨骼公共程序
-
Animation Name:当前播放的动画名
-
Loop:是否循环
-
Initial Skin:初始蒙皮
美术在制作时可能有几套蒙皮,一般情况下只需要一套
-
Time Scale:时间缩放,值越大,动画播放的越快
-
Root Motion:是否添加根运动的脚本,一般不添加
(三)骨骼动画代码
using Spine;
using Spine.Unity;
using UnityEngine;
private SkeletonAnimation sa;
[SpineAnimation] // 可以在Unity面板中选择动画,而不是填入字符串
public string jumpName;
[SpineBone] // 可以在Unity面板中选择骨骼,而不是填入字符串
public string boneName;
[SpineSlot] // 可以在Unity面板中选择部位,而不是填入字符串
public string slotName;
[SpineAttachment] // 可以在Unity面板中选择附件,而不是填入字符串
public string attachmentName;
// Start is called before the first frame update
void Start() {
sa = this.GetComponent<SkeletonAnimation>();
// 动画播放
// 方法一:直接改变SkeletonAnimation中参数
// 需要先改循环为false后再设置动画
sa.loop = true;
sa.AnimationName = "jump";
// 方法二:使用SkeletonAnimation中动画状态改变的函数
// 马上播放
sa.AnimationState.SetAnimation(0, jumpName, false);
// 排队播放
sa.AnimationState.AddAnimation(0, "walk", true, 0);
// 转向
sa.skeleton.ScaleX = -1;
// 动画事件
// 动画开始播放
sa.AnimationState.Start += (t) => { print(sa.AnimationName + "动画开始播放"); };
// 动画被中断或者清除
sa.AnimationState.End += (t) => { print(sa.AnimationName + "动画中断或者清除"); };
// 播放完成
sa.AnimationState.Complete += (t) => { print(sa.AnimationName + "动画播放完成"); };
// 做动画时添加的自定义事件
sa.AnimationState.Event += (t, e) => { print(sa.AnimationName + "自定义事件"); };
// 便捷特性
// 动画特性 [SpineAnimation]
// 骨骼特性 [SpineBone]
// 插槽特性 [SpineSlot]
// 附件特性 [SpineAttachment]
// 获取骨骼、设置插槽附件
// 获取骨骼
Bone b = sa.skeleton.FindBone(boneName);
sa.skeleton.SetAttachment(slotName, attachmentName);
// 在UI中使用
// SkeletonGraphic(UnityUI)
}