大江湖-分析篇-角色动画实现
分析篇-角色动画与特效
大江湖作为 2D 像素类独立游戏,没有采用传统的序列帧动画来实现角色动作和特效,而是采用了 Spine
骨骼动画进行实现
两者对比如下:
- 序列帧动画:传统的动画方式,需要画师一帧一帧绘制,优点是动画效果可以更细腻,缺点是工作量大成本高
- 骨骼动画:画出一个角色后,给角色的各个组件绑上骨骼就可以动起来,添加新动作或者实现换装等功能只要替换各个组件即可实现,优缺点与序列帧动画正好相反。主流的工具有收费版的
Spine
和开源版的dragonbones
spine 资源还原
spine3.8
之后的版本提供了将导出文件还原为原始工程的方法,可以更方便我们分析动画的制作细节
提取导出文件
spine
导出的动画文件一般包含以下几个文件,这些文件放入 unity
后,通过 spine-runtime
库进行加载和运行
male-01-protagonist-LEFT.png
: 所有动画涉及的图片打包成一张图片-
-
male-01-protagonist-LEFT.atlas
: 包含了png
中各个图片的切片信息1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
male-01-protagonist-LEFT.png size: 256,64 format: RGBA8888 filter: Linear,Linear repeat: none L-clothes-01 rotate: false xy: 142, 4 size: 34, 24 orig: 34, 24 offset: 0, 0 index: -1 L-head-01 rotate: true xy: 82, 30 size: 32, 44 orig: 32, 44 offset: 0, 0 index: -1
male-01-protagonist-LEFT.json
: 包含了骨骼/皮肤等信息1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
{ "skeleton": { "hash": "YFQbOucL7uz+Cn1iJIwrY/+ZyAY", "spine": "3.8.84", "x": -37.08, "y": -11, "width": 106.5, "height": 81.63, "images": "./images/", "audio": "" }, "bones": [ { "name": "root" }, { "name": "bone", "parent": "root", "length": 11.56, "rotation": 89.3, "x": -0.18, "y": -17.99 }, ], "slots": [ { "name": "hand-2-feng", "bone": "root" }, ], "skins": [ { "name": "role-01-protagonist", "attachments": { "clothes-huang": { "clothes-huang": { "name": "L-clothes-01", "x": 10.97, "y": -0.6, "rotation": -90.4, "width": 34, "height": 24 } }, "eyes-chen": { "eyes-huang": { "name": "eye-01", "x": 0.32, "y": -2.86, "rotation": -0.87, "width": 18, "height": 8 }, "eyes-behit": { "name": "eyes-manbehit", "x": -0.59, "y": -1.3, "rotation": -0.87, "width": 18, "height": 10 } }, } } ], "events": { "behit": {}, "seal": {} }, "animations": { "A01-stand": { "slots": { "weapon-knife": { "attachment": [ { "name": null } ] }, "weapon-stick": { "attachment": [ { "name": null } ] }, "weapon-sword": { "attachment": [ { "name": null } ] } }, "bones": { "clothes-huang": { "translate": [ { "curve": 0.25, "c3": 0.75 }, { "time": 0.1667, "x": 2.01, "y": 0.04, "curve": 0.25, "c3": 0.75 }, { "time": 0.3333, "curve": 0.25, "c3": 0.75 }, { "time": 0.5, "x": 2.01, "y": 0.04, "curve": 0.25, "c3": 0.75 }, { "time": 0.6667 } ] } } }, } }
从项目中提取要还原的动画文件:
- Assets/Texture2D/male-01-protagonist-TOP.png => male-01-protagonist-TOP.png
- Assets/ScriptableObject/male-01-protagonist-LEFT_Atlas.asset => male-01-protagonist-LEFT.atlas
- Assets/ScriptableObject/male-01-protagonist-TOP_SkeletonData.asset => male-01-protagonist-LEFT.json
纹理解包
打开 spine
工具,点击纹理解包器
选择 male-01-protagonist-LEFT.atlas
文件,输出到 images
目录,点击解开
此处为何要输出到 images
目录?因为在 male-01-protagonist-LEFT.json
文件中定义了图片的根目录为 ./images
|
|
提示解开完成,images
目录中多了很多图片文件,已经成功将图集还原成单张图片
导入数据
点击导入数据
选择 male-01-protagonist-LEFT.json
文件,点击导入
此时已经可以看到完整骨骼数据了,但是发现人物画面并没有出现,原因是皮肤没有勾选
将皮肤 role-01-protagonist
前面的小圆点点亮后,发现人物和动画可以正常展示了
角色动画
prefab
角色的 prefab
存放在 Assets/Resources/prefabs/character
目录,以主角为例:
Protagonist.prefab
body_top
- Assets/Material/male-01-protagonist-TOP_Material.mat
- Assets/Texture2D/male-01-protagonist-TOP.png
- Assets/ScriptableObject/male-01-protagonist-TOP_Atlas.asset
- Assets/ScriptableObject/male-01-protagonist-TOP_SkeletonData.asset
body_left
- Assets/Material/male-01-protagonist-LEFT_Material.mat
- Assets/Texture2D/male-01-protagonist-LEFT.png
- Assets/ScriptableObject/male-01-protagonist-LEFT_Atlas.asset
- Assets/ScriptableObject/male-01-protagonist-LEFT_SkeletonData.asset
body_back
- Assets/Material/male-01-protagonist-BACK_Material.mat
- Assets/Texture2D/male-01-protagonist-BACK.png
- Assets/ScriptableObject/male-01-protagonist-BACK_Atlas.asset
- Assets/ScriptableObject/male-01-protagonist-BACK_SkeletonData.asset
每个角色都制作了三个朝向的动画
-
body_top
: 正面 -
body_left
:左面,通过 180 度翻转为右面 -
body_back
:背面视角
每一个朝向都制作了 1 个皮肤和 18 个动作
动画列表:
动画名称 | 说明 |
---|---|
A01-stand | 站立 |
A02-walk | 行走 |
B01-attack-sword | 使用剑攻击 |
B01-attack-sword-notuse | 使用剑攻击 - 未使用 |
B02-attack-knife | 使用刀攻击 |
B03-attack-stick | 使用棍攻击 |
B04-attack-hand | 拳法攻击 |
B05-attack~~-~~finger | 指法攻击 |
B06-attack-heart | 治疗 |
C01-attackstand-sword | 剑攻击-等待状态 |
C02-attackstand-knife | 刀攻击-等待状态 |
C03-attackstand-stick | 棍攻击-等待状态 |
C04-attackstand-hand | 拳法攻击-等待状态 |
C05-attackstand-finger | 指法攻击-等待状态 |
C06-attackstand-heart | 治疗-等待状态 |
D01-behit | 被攻击 |
D02-die | 死亡 |
D02-die-02 | 死亡 |
播放动画
角色控制的代码在 Assets\Scripts\Assembly-CSharp\OhPlayerController.cs
中
|
|
核心是调用 Spine-runtime
提供的接口进行动画播放
-
skeleton.SetToSetupPose
:将骨骼重置为初始状态 -
AnimationState.ClearTracks
:将动画重置 -
AnimationState.SetAnimation(0, animation, loop)
:设置动画效果
|
|
控制角色朝向
代码较为简单,每个角色的 prefab
中都放置了不同朝向的角色实体。其中左右共用一个实体,通过设置 skeleton.ScaleX
对左右进行翻转,指定朝向时将其他朝向的实体设置为禁用状态。
|
|
其余动画
其它的动画类型就比较简单了,都只有一个动画 animation
,自动播放或者调用接口播放即可
比如标题动画,设置了动画名称为 animation
,勾选 Loop
表示循环播放
而在 spine
设计界面,可以看到只有一个动画
调用 Spine-Runtime
接口播放
|
|