Spine 是什么
Spine 是什么?
Spine 是一款针对游戏开发的 2D 骨骼动画编辑工具。 Spine 旨在提供更高效和简洁的工作流程,以创建游戏所需的动画。
关于 Spine 如何制作动画,制作动画的原理,这里不涉及。设计师给到前端的导出文件有多种方式:
- json
- .json
- .atlas
- .png
- skel
- .skel
- .atlas
- .png
- skel.bytes
- .skel.bytes
- .atlas.txt
- .png
总结一下,主要是 3 类文件:
- .json 文件和 .skel 文件:这个文件包含了 Spine 动画的骨架数据、动画数据以及附带的所有信息。它是一个文本文件,包含了动画的所有关节、插槽、皮肤、事件等信息。而 .skel 文件为二进制格式的 Spine 骨架文件,功能和 .json 文件类似,但是二进制更加紧凑和高效。
- .atlas 文件:这个文件包含了贴图集的元数据,指示哪些图像文件被用作素材以及这些图像在纹理图集中的位置。
- .png 文件:这些是实际的纹理图像文件,包含了骨骼动画中使用的所有图片资源。
.skel.bytes 文件通常在特定的引擎(如 Unity)中用来加载和解析动画数据。
在 Web 中的使用
在官网对运行时页面:zh.esotericsoftware.com/spine-runti… 有介绍各种平台和框架中使用的方法。
网上搜了一下 Spine 在 Web 前端中的应用,没有多少应用,掘金的一篇前端播放在线spine方案,介绍了在 Cocos Creator 和 h5 中的使用,其中在 h5 中使用了 pixi,而且是直接 script 引入的,没有 npm 使用的案例。
首先我们肯定要用一下官方运行时,其次项目是使用 Vite + Vue3,自然尽量使用 npm 的形式而不是直接在 script 中引入,这样和项目更融合,使用更方便。最后基本确定先尝试使用 spine-player。
缺少 npm 使用案例
确实,网上也很难找到 npm 使用的案例。
官方的 Github 仓库:github.com/EsotericSof… 虽然介绍了很多技术方案的使用案例,但是还是不熟悉:
- 下载官方的代码一直失败
- spine-ts 中的 spine-core 似乎是其他方式的依赖
- example 中的代码都是 script 引入的方式,没有 npm 使用方式
- example 中的各种文件功能不清晰
官方的 Spine Web Player 同样看着问题很多,没有 npm 的使用案例。直接原样复制,竟然也会报错,最后使用 spine-player 的时候才发现,是参数不对,没有 skeleton 和 atlas?
NPM 上也有包 www.npmjs.com/package/@es… 也是来自 GitHub,没有更多的信息。
即使能找到 Spine goes NPM 的官方文章,依然有很多的问题。
多种文件的区别
官方案例中也有多种文件的使用,各不相同,让人不明白到底什么时候应该用什么文件。
比如 en.esotericsoftware.com/blog/Spine-… 示例中使用 .skel 文件;
比如 github.com/EsotericSof… 中也是用 .skel 文件
比如 github.com/EsotericSof… 中既有使用 .skel 文件,也有使用 .json 文件方式。
版本一致问题
使用的过程中,发现报错:Spine web player: Animation bounds are invalid: fadein
搜索发现:esotericsoftware.com/forum/d/250…
这可能是动画的 Spine Editor 版本和库的版本不一致问题,问设计师,才发现,我们也有使用 3.8.99,不过也能用 4.1.xx 制作,于是要了一个 4.1 版本的动画素材尝试。
参数问题
不得不说,除了文档不够清晰之外,示例用法和版本似乎也不能对应,可能是文档没更新。
查看源代码 github.com/EsotericSof…
/* The URL of the skeleton JSON (.json) or binary (.skel) file */
skeleton?: string;
/* @deprecated Use skeleton instead. The URL of the skeleton JSON file (.json). Undefined if binaryUrl is given. */
jsonUrl?: string
/* @deprecated Use atlas instead. The URL of the skeleton atlas file (.atlas). Atlas page images are automatically resolved. */
atlasUrl?: string
/* The URL of the skeleton atlas file (.atlas). Atlas page images are automatically resolved. */
atlas?: string;
确实存在多种写法,但是明明说的是 jsonUrl 和 atlasUrl 已经废弃了?实际上只能使用这两个,而不是文档中的 skeleton 和 atlas。
动画无法自动播放
最后在使用 spine-player 显示动画之后,动画不能自动播放。
咨询 ChatGPT 之后,查看源码,并没有设置自动播放的参数 play 之类的。ChatGPT 也是各种给出错误答案,比如:
play: true // 自动播放
// 监听加载完成事件
player.on('ready', () => { player.play(); });
并表示:由于 SpinePlayer 库的文档和类型声明可能不完全一致。
解决:传入 animate 动画名称。如果有多个动画,传入参数 animates 动画列表数组。
animates: ['in', 'loop']
但是 spine 动画是否是自动播放的?设计反馈之前对接其他项目并不需要告知动画名称,开发只需要文件即可。
如果需要传入动画名称,那文档也有问题:
默认情况下, Web Player会播放在skeleton中找到的第一个动画. 默认动画也可以在配置中明确指定:
动画似乎有锯齿
最后,终于让动画动起来了,但是设计认为动画有锯齿,有点画质不好的感觉,图像的边缘应该是光滑的。
难道是背景透明的问题,尝试其他背景色,但是我们的效果肯定需要背景透明的。
偶然又看了一眼 Spine goes NPM,有个参数 premultipliedAlpha,看源码意思为:Whether the skeleton's atlas images use premultiplied alpha,默认值为 true,尝试设置为 false,然后锯齿问题就解决了。
我们建议对所有Spine Web Player需显示的资产均使用premultiplied alpha. 它减少了不使用premultiplied alpha时可能出现的伪影和接缝问题.
premultipliedAlpha 叫预乘 alpha,这个参数的含义,可以自行搜索。具体使用,可能还要看具体的动画效果而定。
参考代码
<template>
<div ref="spineContainer" class="spine h-full w-full"></div>
</template>
<script setup lang="ts">
import {
SpinePlayer,
type SpinePlayerConfig,
} from '@esotericsoftware/spine-player'
interface Props {
jsonPath: string
atlasPath: string
animations: string[]
}
const props = defineProps<Props>()
const spineContainer = ref<HTMLElement | null>(null)
onMounted(() => {
if (!spineContainer.value) return
const config: SpinePlayerConfig = {
jsonUrl: props.jsonPath,
atlasUrl: props.atlasPath,
animations: props.animations,
alpha: true,
premultipliedAlpha: false,
backgroundColor: '#00000000',
preserveDrawingBuffer: false,
showControls: false,
}
const player = new SpinePlayer(spineContainer.value, config)
// 清理函数,当组件卸载时销毁 player
return () => {
player.dispose()
}
})
</script>
最终代码很简单,spine-player 使用了最新版本。