最近FairyGui新添了对Spine动画功能的支持,然后项目中就想用Spine动画做一些表现。然后按照官方文档上介绍的步骤在Unity中添加对Spine的支持,搞了半天,项目中运行动态加载Spine,要么就是完全看不到,要么就是一个黑片。通过查看官方问答和询问其它人,也没找到解决方案。最终放弃直接使用FairyGUI的Loader3D加载Spine,改用FairyGui嵌套UGUI加载Spine。Spine对Unity原生的UGUI有更好的支持。操作步骤如下:
1、首先Spine官网下载Spine-unity包(我使用的是spine-unity-3.8),导入Unity;
2、添加做好的Spine动画资源到Unity中;
导入动画资源时要注意,美术给的资源包含三个文件,如图2-1所示,一个图片,一个图集文本文件,一个skel文件。导入Unity前需要将skel文件添加.bytes后缀,然后拖入Unity才能正常生成运行需要的文件。最终生成的文件如图2-2所示,会生成一个图集对应的asset,一个skeletondata对应的asset,一个材质。
3、首先在FairyGUI添加一个Graph组件,作为容器,添加UGUI的Canvas组件;
4、然后添加SkeletonGraphic组件,设置SkeletonGraphic组件使用材质为SkeletonGraphicDefault.material;
5、加载SkeletonDataAsset资源,设置SkeletonGraphic
代码如下:
public static void AddSpine(GGraph holder, string spineName, string aniName, float posX, float posY, float scale = 1)
? ? ? ? {
? ? ? ? ? ? SkeletonGraphic sg;
? ? ? ? ? ? GameObject ngo = new GameObject("Canvas");
? ? ? ? ? ? Canvas canvas = ngo.AddComponent<Canvas>();
? ? ? ? ? ? canvas.renderMode = RenderMode.WorldSpace;
? ? ? ? ? ? canvas.worldCamera = StageCamera.main;? //相机使用FairyGUI的StageCamera
? ? ? ? ? ? GoWrapper gw = new GoWrapper(canvas.gameObject);
? ? ? ? ? ? holder.SetNativeObject(gw);
? ? ? ? ? ?GameObject sgGo = new GameObject("SkeletonGraphic");
? ? ? ? ? ?sgGo.transform.parent = ngo.transform;
? ? ? ? ? ?sg = sgGo.AddComponent<SkeletonGraphic>();
? ? ? ? ? ?sg.gameObject.transform.localScale = Vector3.one;
? ? ? ? ? ?sg.gameObject.transform.localPosition = Vector3.zero;
? ? ? ? ? ?sg.raycastTarget = false;
? ? ? ? ? ?sg.material = Resources.Load<Material>("spine/materials/SkeletonGraphicDefault");
? ? ? ? ? ?sg.skeletonDataAsset = Resources.Load<SkeletonDataAsset>($"spine/{spineName}");? //加载skel资源
? ? ? ? ? ?/*执行以下两步保证资源替换后,能正确渲染
? ? ? ? ? ?sg.Initialize(true);
? ? ? ? ? ?sg.Rebuild(UnityEngine.UI.CanvasUpdate.PreRender);
? ? ? ? ? /*重新设置动画
? ? ? ? ? ?sg.Skeleton.SetToSetupPose();
? ? ? ? ? ?sg.AnimationState.ClearTracks();
? ? ? ? ? ?sg.AnimationState.SetAnimation(0, aniName, true);
? ? ? ? ? ?/*设置偏移和缩放
? ? ? ? ? ?holder.SetScale(scale, scale);
? ? ? ? ? ?holder.SetPosition(posX, posY, holder.position.z);
? ? ? ? ? holder.visible = true;? ? ? ? ? ?
? ? ? ? }