准备工作
使用UE版本为4.27,Vs为2022。
在官网下载Spine插件,下载链接:https://github.com/EsotericSoftware/spine-runtimes
在EpieGame中安装PaperZD插件
安装PaperZDForSpine2D插件以在PaperZD中使用Spine动画,下载链接:https://github.com/heavybullets/PaperZDForSpine2D
在Build.cs中添加”Paper2D”以后续编译可以通过。
使用Spine动画
创建Spine动画
导入Spine动画,要注意安装插件版本和动画版本要保持一致。
在所有的插件都安装完成以后在内容浏览器中右键可以看到PaperZD选项,选择AnimSource,就可以看到由Spine动画的额外选项(PaperZD默认的为Flipbook动画,安装插件后可以选择spine动画)。
选择AnimSource后,进入选择碎图集和骨骼信息,随后新建动画(AddNew),可以在细节面板中预览和选择动画。
此外在动画下方还有时间轴,可以在这里添加事件通知。
使用Spine动画
新建一个C++类,在选择父类时选择PaperZDCharacter或者PaperZDCharacter_Spine2D,两者都可以,以后者为父类创建一个新的类(命名为Hero),跳转到PaperZDCharacter_Spine2D中可以看到为我们提供了两个组件,为了后续方便使用可以新增两个函数来获取这两个组件,添加完成后类如下:
1 | UCLASS() |
回到Hero类中,添加摄象机吊臂和摄象机组件并初始化,在编辑器中以Hero类新建一个蓝图类BP_Hero,其中主要包括:胶囊体。摄象机以吊臂、两个渲染组件、两个动画组件、Movement组件。
在SpineAnimation组件中选择碎图集和骨骼,并调整到合适大小。
使用Spine动画状态机
回到内容浏览器,在PaperZD中选中AnimBP来构建我们的状态机,2D状态机的使用与普通的状态机类似,基本功能都有。
在AnimBP的事件图表中有EventOnInit和EventOnTick两个事件,对应可以理解为BeginPlay和UpdateAnimation;在类默认设置中可以选择ParentClass。
我们要使用自己的AnimInstance,所以新建一个C++类,继承自PaperZDAnimInstance,跳转到PaperZDAnimInstance中可以找到OnInit和OnTick两个函数,我们需要重写这两个函数,并添加我们自定义的角色:
1 | UCLASS(Blueprintable) |
PaperZD为我们提供了一些获取属性的接口,可以通过GetPaperCharacter来获取到角色。
回到编辑器,继承自AnimBP类创建一个蓝图ABP_Hero,并在AnimBP中的ParentClass选择该类,这样就可以获取到该类中的各种自定义属性;在BP_Hero中的AnimatinComponent中的AnimInstanceClass选择ABP_Hero。
UCLASS中必须加Blueprintable,否则无法被设置为父类
一些方法
在动画轨道中可以直接新建通知,使用时转到AnimBP中,可以看到左侧的Functions中有新建的通知,可以在其中编写逻辑。
但使用AnimState在需要新建一个state,才能在轨道中选择。新建一个蓝图类,继承自PaperZDAnimNotifyState,其中包含3个重载函数:Begin、End、Tick,可以在其中完成不同的逻辑。
JumpToNode节点,在动画图表中有Jump节点可以用于跳转,可以用来从一个状态强制跳转到另一个状态。
Hero->GetAnimInstance->JumpToNode
使用Playbacks,Playbacks是PaperZD在UE5中新增的功能,功能与蒙太奇类似,可以用于播放插槽内的动画。
Hero->GetAnimInstance->PlayAnimationplaybacks,使用时指定插槽的名称,并在动画图表中新增一个插槽(AddNewSlot)
使用Muti-Directional Sequence,是一个多角度动画集合,可以根据不同的角度播放不同的动画,使用时选择SetDirectionality节点来选择不同角度的动画。
让角色翻转,可以使用SetScaleX或SetScaleY来设置:
GetSpineSkeletonAnimationComponent()->SetScaleX(ScaleValue)
使用骨骼插槽,Spine动画是骨骼动画,同样可以使用骨骼插槽来实现一些功能。在导入的骨骼资源中可以看到Bones、Slots、Skins、Animations四个选项,在创建完成角色后,可以给Bones上添加一些碰撞框等。
例如在root上增加一个box,在蓝图的BeginPlay里选择box->AttachComponentToComponent,Parent选择SpineRender组件,Socket在骨骼资产中选择,这里选择root,如果添加成功,我们可以打印一句AttachOK,失败的话打印AttackFilded,并把box的HiddenInGame设置为false。这就在开始游戏后就可以看到屏幕上打印AttachOK并且能在角色脚底看到box的跟随角色移动。
这可以用来完成一些角色的攻击判定,利用动画通知来决定何时开启和关闭检测,这与一般的攻击响应是类似的。
让Spine动画称为原地动画。如果导入的Spine动画带有位移,但是并不想使用自带的位移动画,可以去Bone的源码中改变WorldX/Y。
对于UE,在安装完成插件后,可以在Plugins/SpinePlugin/Source/SpinePlugin/Public/Spine-cpp/src/spine/Bone.cpp中找到:
void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY),在if(!parent)中将_worldX与_worldY注释掉
Unity也是类似逻辑,找到该函数后将worldX与worldY注释掉。
参考
PaperZD的官方文档:https://www.criticalfailure-studio.com/paperzd-documentation/
- 本文作者: KongXinQing
- 本文链接: https://13114987559.github.io/2024/01/23/essay/使用Spine动画/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!