Unity---Spine动画

这篇具有很好参考价值的文章主要介绍了Unity---Spine动画。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.介绍

2.优点

3.spine导出的unity资源

4.导入

5.导入报错的解决方案

6.使用

7.代码示例

1.加载Spine骨骼动画:

2.控制Spine动画的播放:

3.暂停和恢复动画播放:

4.监听动画事件:

5.切换皮肤(换装)

6.获取骨骼的Transform信息:

7.控制骨骼动画的混合和交叉淡入:

8.控制动画的速度:

9.获取动画状态信息:

10.动态替换骨骼纹理:

11.播放Spine动画的指定轨道:

12.获取当前动画的时间和持续时间:

13.控制动画循环次数:

14.动态更改动画混合的权重:

15.暂停和恢复所有动画轨道:

16.动态创建并替换插槽的Attachment:

17.使用Spine动画事件触发Unity事件:

18.控制动画播放速度随机化:

19.动态切换Spine Atlas图集:

20.动态创建骨骼动画:

21.骨骼动画的事件监听与处理:

8.unity-spine运行库下载


1.介绍

Unity Spine是一个收费的跨平台的强大的2D骨骼动画工具,它能够轻松创建复杂的角色动画。

要在unity中使用spine动画的话,需要下载对应的spine运行库

⚠️注意使用的spine运行库版本要与unity版本相对应,

对应关系见下图:

spine动画 unity,unity-插件,unity,spine,动画,spine动画,unity spine

 

2.优点

  1. 轻量级和高效:Spine动画使用基于骨骼的动画技术,相比传统的逐帧动画,它们具有更小的文件大小和更低的内存占用。这使得Spine动画在移动设备和低端硬件上的性能更好。

  2. 灵活性:使用Spine,你可以创建高度可定制的动画,包括骨骼的变形、缩放、旋转和平移。你可以轻松地调整动画的速度、混合不同的动画,以及实现复杂的角色动画控制。

  3. 运行时动画:Spine动画可以在运行时进行实时修改和控制。这意味着你可以通过代码来改变动画的播放状态,根据角色的行为和环境条件进行相应的动画交互。

  4. 平台兼容性:Unity支持多个平台,包括PC、移动设备和主机,而Spine动画可以轻松地在这些平台上进行部署和播放。

3.spine导出的unity资源

一般情况下,美术会导出下列3个文件

.json 存储骨骼信息
.png 使用的图片图集
.atlas.txt 图片在图集中的位置信息
当我们把这三个资源导入到已经引入了Spine运行库的Unity工程后会自动为我们生成

_Atlas 材质和.atlas.txt文件的引用配置文件
_Material 材质文件
_SkeletonData json和_Atlas资源的引用配置文件

⚠️:但使用 .json 格式读取动画数据是比较慢且运行效率较低的方式。

因为spine动画使用json文件后期优化效果不太好,容易造成卡顿,加载过慢等。而二进制文件加载速度就比较快了。

Spine 支持Binary format ,二进制的数据导出,采用这种方式导出的格式是:.png 、.skel 和 .atlas 

4.导入

1.在图集.atlas后面加上.txt后缀

2.在二进制文件.skel后面加上.betys后缀

5.导入报错的解决方案

1.可能是美术那边导出时出现的问题。你可以让美术那边再导出一次。同一个spine动画让美术导出json文件和二进制文件。如果json文件导入也出现错误,那就是美术那边导出的问题。

  2.如果导入json没问题。导入二进制有问题,那么可能是运行库版本和spine版本不一致的问题。首先你可以查看一下untiy中spine运行库的版本是多少。是否和spine版本一致。

 3.二进制文件导入unity中后如果没有自动实例化对象,那么你需要手动创建。在创建的过程中有时候你会发现你创建的对象在场景中使用的时候变大了。具体说是变大了100倍。有人说我创建的时候也修改scale的大小了啊(0.01),怎么还会那么大呢?这其中就有些技巧了,你创建的时候先修改scale值,修改完之后再将需要的文件拖到相应的位置。那么你创建的大小就是缩放后的正常的大小。在场景中直接使用就是美术给你的正常大小了。

6.使用

1.unity中添加spine的三种方式 ,如下图:

spine动画 unity,unity-插件,unity,spine,动画,spine动画,unity spine

 2.ugui中使用SkeletonGraphic(UnityUI)

spine动画 unity,unity-插件,unity,spine,动画,spine动画,unity spine

 

3. 其他使用SkeletonAnimation

spine动画 unity,unity-插件,unity,spine,动画,spine动画,unity spine

4.一般来说,在以下情况下你可能会使用SkeletonRenderer:

  1. 角色动画:如果你的游戏中有2D角色需要进行复杂的骨骼动画,你可以使用Spine创建角色的动画,并将SkeletonRenderer组件添加到Unity场景中的角色对象上。然后,该组件将负责在运行时渲染角色的骨骼动画。

  2. UI动画:你可以使用Spine创建2D UI元素的动画,例如按钮、图标、菜单等。通过将SkeletonRenderer添加到UI元素上,你可以在运行时播放Spine动画来增强用户界面的交互和视觉效果。

  3. 敌人/怪物动画:如果你的游戏中有敌人、怪物或NPC需要复杂的动画效果,你可以使用Spine创建骨骼动画,并将SkeletonRenderer组件添加到相应的游戏对象上。

  4. 特效动画:Spine还可以用于创建2D特效动画,比如爆炸、火焰、魔法等。将SkeletonRenderer组件与特效对象一起使用,可以实现更加生动逼真的效果。

7.代码示例

1.加载Spine骨骼动画:

使用Spine的SkeletonDataAsset类来加载Spine骨骼数据,并通过SkeletonAnimation组件来播放动画。

using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }
}

解释:

  • 首先,您需要在Unity中创建一个空GameObject,并附加SkeletonAnimation组件。这个组件用于播放Spine动画。
  • 创建一个public字段来存储SkeletonDataAsset,这是Spine动画的骨骼数据。
  • 在Start()方法中,获取SkeletonAnimation组件的引用,并将SkeletonDataAsset赋值给skeletonAnimation.skeletonDataAsset。
  • 调用Initialize(true)方法来初始化SkeletonAnimation。传入true表示启用MeshRenderer,以便在场景中显示骨骼动画。
2.控制Spine动画的播放:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            skeletonAnimation.AnimationState.SetAnimation(0, "walk", true);
        }
    }
}

解释:

  • 在Update()方法中,我们可以使用Input.GetKeyDown(KeyCode.Space)来检测是否按下了空格键。
  • 如果按下了空格键,我们通过skeletonAnimation.AnimationState.SetAnimation()方法来播放名为"walk"的动画。
  • 第一个参数0表示trackIndex,表示要将动画放置在哪个轨道(track)上。Spine允许在同一时间在多个轨道上播放多个动画,0是默认的轨道。
  • 第二个参数是动画名称,这里是"walk"。您可以将其替换为其他Spine动画的名称。
  • 第三个参数true表示循环播放动画,如果设置为false,则动画只会播放一次。
3.暂停和恢复动画播放:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            skeletonAnimation.AnimationState.SetAnimation(0, "walk", true);
        }

        if (Input.GetKeyDown(KeyCode.P))
        {
            if (skeletonAnimation.AnimationState.GetCurrent(0) != null)
            {
                skeletonAnimation.AnimationState.GetCurrent(0).TimeScale = 0f; // Pause animation
            }
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            if (skeletonAnimation.AnimationState.GetCurrent(0) != null)
            {
                skeletonAnimation.AnimationState.GetCurrent(0).TimeScale = 1f; // Resume animation
            }
        }
    }
}

解释:

  • 在Update()方法中,我们添加了检测按下"P"和"R"键的代码来实现暂停和恢复动画的播放。
  • 当按下"P"键时,我们通过GetCurrent(0)方法获取当前正在播放的动画轨道,并将其TimeScale设置为0,这会将动画暂停。
  • 当按下"R"键时,我们将动画轨道的TimeScale设置为1,这会恢复动画的正常播放。
4.监听动画事件:
using Spine;
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);

        // 订阅动画事件
        skeletonAnimation.AnimationState.Event += HandleAnimationEvent;
    }

    private void HandleAnimationEvent(TrackEntry trackEntry, Spine.Event e)
    {
        Debug.Log("Animation Event: " + e.Data.Name);
        // 在此处执行事件相关的逻辑
    }
}

解释:

  • 在Start()方法中,我们通过skeletonAnimation.AnimationState.Event += HandleAnimationEvent;订阅了动画事件。
  • 创建HandleAnimationEvent方法来处理动画事件。
  • 当Spine动画的事件被触发时,HandleAnimationEvent将会被调用,并且您可以在其中执行与事件相关的逻辑。例如,您可以在Spine编辑器中为某个动画帧添加事件,并在代码中根据事件的名称来触发相应的逻辑。
5.切换皮肤(换装)
using Spine.Unity;

public class SpineSkinController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    private string currentSkinName;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);

        // 设置初始皮肤
        currentSkinName = "default";
        skeletonAnimation.Skeleton.SetSkin(currentSkinName);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            // 切换到另一个皮肤
            string newSkinName = "alternate";
            skeletonAnimation.Skeleton.SetSkin(newSkinName);
            skeletonAnimation.Skeleton.SetSlotsToSetupPose(); // 刷新插槽以更新换装后的显示
            skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);
        }
    }
}

解释:

  • 在Start()方法中,我们通过skeletonAnimation.Skeleton.SetSkin(currentSkinName)设置了初始的皮肤,这里使用了"default"皮肤。
  • 在Update()方法中,当按下"S"键时,我们通过skeletonAnimation.Skeleton.SetSkin(newSkinName)来切换到另一个皮肤,这里使用了"alternate"皮肤。
  • 切换皮肤后,为了确保新的皮肤在场景中立即显示,我们还需要调用skeletonAnimation.Skeleton.SetSlotsToSetupPose()刷新插槽,以更新换装后的显示。最后,通过skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton)将更改应用到动画状态。
6.获取骨骼的Transform信息:
using Spine.Unity;
using UnityEngine;

public class SpineBoneTransform : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.G))
        {
            // 获取指定骨骼的Transform信息
            Bone bone = skeletonAnimation.Skeleton.FindBone("boneName");
            if (bone != null)
            {
                Vector3 bonePosition = new Vector3(bone.WorldX, bone.WorldY, 0f);
                Quaternion boneRotation = Quaternion.Euler(0f, 0f, bone.WorldRotationX);
                Vector3 boneScale = new Vector3(bone.WorldScaleX, bone.WorldScaleY, 1f);

                Debug.Log("Bone Position: " + bonePosition);
                Debug.Log("Bone Rotation: " + boneRotation.eulerAngles);
                Debug.Log("Bone Scale: " + boneScale);
            }
        }
    }
}

解释:

  • 在Update()方法中,我们通过Input.GetKeyDown(KeyCode.G)检测是否按下"G"键。
  • 当按下"G"键时,我们使用skeletonAnimation.Skeleton.FindBone("boneName")查找指定名称的骨骼(需要将"boneName"替换为实际的骨骼名称)。
  • 如果找到了该骨骼,我们可以使用骨骼的WorldX、WorldY、WorldRotationX和WorldScaleX、WorldScaleY属性来获取骨骼的位置、旋转和缩放信息。注意,这些属性表示骨骼在世界坐标系中的信息。
7.控制骨骼动画的混合和交叉淡入:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            // 播放动画1,并在1秒内淡入混合到目标动画
            skeletonAnimation.AnimationState.SetAnimation(0, "animation1", true);
        }

        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            // 播放动画2,并在0.5秒内交叉淡入混合到目标动画
            skeletonAnimation.AnimationState.SetAnimation(1, "animation2", true).MixDuration = 0.5f;
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.Alpha1)和Input.GetKeyDown(KeyCode.Alpha2)来检测是否按下数字键1和2。
  • 当按下数字键1时,我们通过skeletonAnimation.AnimationState.SetAnimation()来播放名为"animation1"的动画。由于没有设置MixDuration,这里使用默认的混合时间(通常是0.2秒)。
  • 当按下数字键2时,我们通过skeletonAnimation.AnimationState.SetAnimation()来播放名为"animation2"的动画,并设置了MixDuration为0.5秒。这将导致动画2和当前正在播放的动画在0.5秒内交叉淡入混合。
8.控制动画的速度:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    public float animationSpeed = 1.0f;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            // 增加动画速度
            animationSpeed += 0.5f;
            skeletonAnimation.timeScale = animationSpeed;
        }

        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            // 减少动画速度,但不低于0.1
            animationSpeed -= 0.5f;
            animationSpeed = Mathf.Max(animationSpeed, 0.1f);
            skeletonAnimation.timeScale = animationSpeed;
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.UpArrow)和Input.GetKeyDown(KeyCode.DownArrow)来检测是否按下上箭头键和下箭头键。
  • 当按下上箭头键时,我们增加animationSpeed变量的值,并将新的值应用到skeletonAnimation.timeScale,从而增加动画的播放速度。
  • 当按下下箭头键时,我们减少animationSpeed变量的值,并确保其不会低于0.1,然后将新的值应用到skeletonAnimation.timeScale,从而减少动画的播放速度。
9.获取动画状态信息:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        TrackEntry currentAnimation = skeletonAnimation.AnimationState.GetCurrent(0);
        if (currentAnimation != null)
        {
            Debug.Log("Current Animation: " + currentAnimation.Animation.Name);
            Debug.Log("Animation Time: " + currentAnimation.Time);
            Debug.Log("Animation Is Complete: " + currentAnimation.IsComplete);
        }
    }
}

解释:

  • 在Update()方法中,我们通过skeletonAnimation.AnimationState.GetCurrent(0)获取当前正在播放的动画状态(TrackEntry)。
  • 然后,我们可以通过TrackEntry的属性来获取有关当前动画的信息,例如动画名称、动画播放时间和动画是否已经播放完成。
10.动态替换骨骼纹理:
using Spine.Unity;
using UnityEngine;

public class SpineTextureReplacement : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    public Texture2D newTexture;
    public string slotName;

    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            // 获取插槽的当前Attachment并替换纹理
            Slot slot = skeletonAnimation.Skeleton.FindSlot(slotName);
            if (slot != null)
            {
                Attachment currentAttachment = slot.Attachment;
                if (currentAttachment is RegionAttachment)
                {
                    RegionAttachment regionAttachment = (RegionAttachment)currentAttachment;
                    regionAttachment.SetRegion(newTexture);
                    skeletonAnimation.Update(0f); // 强制更新以显示新纹理
                }
            }
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.T)检测是否按下"T"键。
  • 当按下"T"键时,我们通过skeletonAnimation.Skeleton.FindSlot(slotName)找到指定名称的插槽(需要将"slotName"替换为实际的插槽名称)。
  • 然后,我们获取该插槽的当前Attachment,并进行类型检查,以确保该Attachment是RegionAttachment(纹理类型的Attachment)。
  • 如果是RegionAttachment,我们将其转换为RegionAttachment,并使用SetRegion方法将其纹理替换为newTexture。
  • 由于更改了Attachment,我们需要调用skeletonAnimation.Update(0f)来强制更新SkeletonAnimation,以便在场景中显示新的纹理。
11.播放Spine动画的指定轨道:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    public int trackIndex = 0;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            // 播放动画1在指定轨道
            skeletonAnimation.AnimationState.SetAnimation(trackIndex, "animation1", true);
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.Alpha1)来检测是否按下数字键1。
  • 当按下数字键1时,我们通过skeletonAnimation.AnimationState.SetAnimation()来播放名为"animation1"的动画,并指定了trackIndex作为第一个参数。trackIndex是轨道的索引,用于在多个轨道上播放不同的动画。默认情况下,使用0作为轨道索引。
12.获取当前动画的时间和持续时间:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    public int trackIndex = 0;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        TrackEntry currentAnimation = skeletonAnimation.AnimationState.GetCurrent(trackIndex);
        if (currentAnimation != null)
        {
            float currentTime = currentAnimation.Time;
            float animationDuration = currentAnimation.Animation.Duration;

            Debug.Log("Current Animation Time: " + currentTime);
            Debug.Log("Animation Duration: " + animationDuration);
        }
    }
}

解释:

  • 在Update()方法中,我们通过skeletonAnimation.AnimationState.GetCurrent(trackIndex)获取当前正在播放的动画状态(TrackEntry)。
  • 然后,我们使用currentAnimation.Time来获取当前动画的播放时间,以及currentAnimation.Animation.Duration来获取当前动画的总持续时间。
13.控制动画循环次数:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            // 播放动画1并设置循环次数
            TrackEntry trackEntry = skeletonAnimation.AnimationState.SetAnimation(0, "animation1", true);
            trackEntry.Loop = false; // 关闭循环
            trackEntry.LoopCount = 2; // 设置循环次数为2次
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.Alpha1)来检测是否按下数字键1。
  • 当按下数字键1时,我们通过skeletonAnimation.AnimationState.SetAnimation()来播放名为"animation1"的动画,并获取返回的TrackEntry。
  • 然后,我们可以通过设置TrackEntry的Loop属性为false来关闭动画的循环播放。
  • 同时,通过设置LoopCount属性为2来指定动画的循环次数为2次。
14.动态更改动画混合的权重:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            // 播放动画1并增加混合权重
            TrackEntry trackEntry = skeletonAnimation.AnimationState.SetAnimation(0, "animation1", true);
            trackEntry.Alpha = 0.5f; // 设置混合权重为0.5
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.Alpha1)来检测是否按下数字键1。
  • 当按下数字键1时,我们通过skeletonAnimation.AnimationState.SetAnimation()来播放名为"animation1"的动画,并获取返回的TrackEntry。
  • 然后,我们可以通过设置TrackEntry的Alpha属性来调整动画的混合权重。Alpha的取值范围是0到1,1表示完全显示动画,0表示完全隐藏动画。在这个例子中,我们将混合权重设置为0.5,使得动画以一半的透明度进行混合。
15.暂停和恢复所有动画轨道:
using Spine.Unity;

public class SpineAnimationController : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 切换暂停和恢复动画
            bool isPaused = skeletonAnimation.timeScale == 0f;
            skeletonAnimation.timeScale = isPaused ? 1f : 0f;
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.Space)来检测是否按下空格键。
  • 当按下空格键时,我们检查当前动画的时间缩放(timeScale)是否为0。如果为0,则表示当前动画处于暂停状态,我们将时间缩放设置为1以恢复动画播放。如果不为0,则表示当前动画正在播放中,我们将时间缩放设置为0以暂停动画。
16.动态创建并替换插槽的Attachment:
using Spine;
using Spine.Unity;
using UnityEngine;

public class SpineAttachmentReplacement : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    public string slotName;
    public Sprite newSprite;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            // 获取插槽并替换Attachment为新的Sprite
            Slot slot = skeletonAnimation.Skeleton.FindSlot(slotName);
            if (slot != null)
            {
                Attachment currentAttachment = slot.Attachment;
                if (currentAttachment is RegionAttachment)
                {
                    RegionAttachment regionAttachment = (RegionAttachment)currentAttachment;
                    Material material = new Material(Shader.Find("Sprites/Default"));
                    Material newMaterial = new Material(material); // 复制原始Material
                    newMaterial.mainTexture = newSprite.texture; // 设置新的Sprite纹理
                    regionAttachment.GetRegion().RenderObject.SetMeshMaterial(newMaterial);
                    skeletonAnimation.Update(0f); // 强制更新以显示新Attachment
                }
            }
        }
    }
}
  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.R)来检测是否按下'R'键。
  • 当按下'R'键时,我们通过skeletonAnimation.Skeleton.FindSlot(slotName)找到指定名称的插槽(需要将'slotName'替换为实际的插槽名称)。
  • 然后,我们获取插槽当前的Attachment,并进行类型检查,以确保该Attachment是RegionAttachment(纹理类型的Attachment)。
  • 如果是RegionAttachment,我们创建一个新的Material,并将新的Sprite纹理赋值给它。
  • 然后,我们使用regionAttachment.GetRegion().RenderObject.SetMeshMaterial(newMaterial)来将新的Material应用到Attachment,并强制调用skeletonAnimation.Update(0f)来更新SkeletonAnimation,以显示新的Attachment。
17.使用Spine动画事件触发Unity事件:
using Spine.Unity;
using UnityEngine;
using UnityEngine.Events;

public class SpineAnimationEventTrigger : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    public UnityEvent onAnimationEvent;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);

        // 订阅动画事件
        skeletonAnimation.AnimationState.Event += HandleAnimationEvent;
    }

    private void HandleAnimationEvent(TrackEntry trackEntry, Spine.Event e)
    {
        if (e.Data.Name == "eventName") // 将"eventName"替换为实际动画中设置的事件名称
        {
            onAnimationEvent.Invoke(); // 触发Unity事件
        }
    }
}

解释:

  • 在Update()方法中,我们使用skeletonAnimation.AnimationState.Event += HandleAnimationEvent;订阅了动画事件。
  • 在Start()方法中,我们创建了一个Unity事件(UnityEvent),名为onAnimationEvent。在Spine动画中设置的事件名称(例如"eventName")需要替换为实际动画中设置的事件名称。
  • 当Spine动画的事件被触发时,HandleAnimationEvent方法将会被调用。在这个方法中,我们检查事件的名称是否匹配设定的名称,如果匹配,则触发Unity事件onAnimationEvent.Invoke()。
18.控制动画播放速度随机化:
using Spine.Unity;
using UnityEngine;

public class SpineRandomAnimationSpeed : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    public float minSpeed = 0.8f;
    public float maxSpeed = 1.2f;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 播放动画,并随机设置播放速度
            float randomSpeed = Random.Range(minSpeed, maxSpeed);
            skeletonAnimation.timeScale = randomSpeed;
            skeletonAnimation.AnimationState.SetAnimation(0, "animation1", true);
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.Space)来检测是否按下空格键。
  • 当按下空格键时,我们随机生成一个播放速度(randomSpeed)在minSpeed和maxSpeed之间。
  • 然后,我们将randomSpeed设置为skeletonAnimation.timeScale,以调整动画的播放速度,并使用skeletonAnimation.AnimationState.SetAnimation()来播放名为"animation1"的动画。
19.动态切换Spine Atlas图集:
using Spine;
using Spine.Unity;
using UnityEngine;

public class SpineAtlasSwitch : MonoBehaviour
{
    public TextAsset newAtlasText;
    public Material newMaterial;
    public SkeletonDataAsset skeletonDataAsset;

    private SkeletonData currentSkeletonData;
    private Atlas currentAtlas;

    void Start()
    {
        LoadNewAtlas();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            LoadNewAtlas();
        }
    }

    private void LoadNewAtlas()
    {
        if (currentAtlas != null)
        {
            currentAtlas.Dispose();
        }

        currentAtlas = new Atlas(newAtlasText, "", newMaterial);
        currentSkeletonData = SkeletonData.CreateFromatlas(currentAtlas);

        skeletonDataAsset.Clear();
        skeletonDataAsset.Reset();
        skeletonDataAsset.atlasAssets[0].materials[0] = newMaterial;
        skeletonDataAsset.atlasAssets[0].materials = new Material[] { newMaterial };
        skeletonDataAsset.skeletonJSON = new TextAsset(currentSkeletonData.Json.ToString());
        skeletonDataAsset.GetSkeletonData(true);

        skeletonDataAsset.GetSkeletonData(false).AssetAtPath("path/to/asset");

        skeletonDataAsset.GetSkeletonData(false).FindSlot("slotName");

        skeletonDataAsset.GetSkeletonData(false).FindAnimation("animationName");

        skeletonDataAsset.GetSkeletonData(false).FindSkin("skinName");
    }
}

解释:

  • 这是一个更复杂的用例,用于动态切换Spine Atlas图集。我们通过Input.GetKeyDown(KeyCode.S)来检测是否按下"S"键,以触发图集的切换。
  • 在LoadNewAtlas()方法中,加载新的Atlas并创建新的SkeletonData。然后,更新SkeletonDataAsset以使用新的Atlas和SkeletonData。
20.动态创建骨骼动画:
using Spine;
using Spine.Unity;
using UnityEngine;

public class SpineDynamicAnimation : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;
    public string newAnimationName;
    public AnimationReferenceAsset newAnimationReference;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.N))
        {
            // 动态创建并播放新的骨骼动画
            Animation newAnimation = new Animation(newAnimationName, newAnimationReference.GetAnimation().Timelines);
            skeletonAnimation.Skeleton.Data.AddAnimation(newAnimationName, newAnimation, skeletonAnimation.Skeleton.Data.FindAnimation(skeletonAnimation.AnimationState.GetCurrent(0).Animation.Name).Duration, true);

            skeletonAnimation.AnimationState.SetAnimation(1, newAnimationName, false);
        }
    }
}

解释:

  • 在Update()方法中,我们使用Input.GetKeyDown(KeyCode.N)来检测是否按下"N"键。
  • 当按下"N"键时,我们动态创建一个新的骨骼动画(newAnimation)并将其添加到SkeletonData中。这里使用了newAnimationName和newAnimationReference作为新动画的名称和参考动画。
  • 然后,我们使用skeletonAnimation.AnimationState.SetAnimation()来播放新创建的动画。
21.骨骼动画的事件监听与处理:
using Spine;
using Spine.Unity;
using UnityEngine;

public class SpineAnimationEvent : MonoBehaviour
{
    public SkeletonDataAsset skeletonDataAsset;
    private SkeletonAnimation skeletonAnimation;

    void Start()
    {
        skeletonAnimation = GetComponent<SkeletonAnimation>();
        skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
        skeletonAnimation.Initialize(true);

        // 订阅动画事件
        skeletonAnimation.AnimationState.Event += HandleAnimationEvent;
    }

    private void HandleAnimationEvent(TrackEntry trackEntry, Spine.Event e)
    {
        // 根据动画事件名称做相应处理
        if (e.Data.Name == "event_name_1")
        {
            Debug.Log("Event 1 triggered!");
            // 在这里添加处理事件1的逻辑
        }
        else if (e.Data.Name == "event_name_2")
        {
            Debug.Log("Event 2 triggered!");
            // 在这里添加处理事件2的逻辑
        }
    }
}

解释:

  • 在Update()方法中,我们使用skeletonAnimation.AnimationState.Event += HandleAnimationEvent;订阅了动画事件。
  • 在HandleAnimationEvent方法中,我们根据动画事件的名称(例如"event_name_1"和"event_name_2")来执行不同的处理逻辑。您可以根据动画中设置的事件名称,添加相应的逻辑来响应这些事件。

⚠️注意:这里的用法可能会因Spine版本和Unity项目结构而有所变化。请根据您的具体情况进行调整。

8.unity-spine运行库下载

官网

本地下载文章来源地址https://www.toymoban.com/news/detail-688527.html

到了这里,关于Unity---Spine动画的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spine动画导入unity后有白边的解决方法

     可以看官方视频[spine-unity] 常见导入问题解答_哔哩哔哩_bilibili 里面第四个问题就是讲的这个 如果你的spine文件导出用的是默认的情况,那么在导入unity后就有可能会出现透明贴图出现白边的情况 如下 此时先打开导入的图片文件  将右侧的sRGB选项取消选中(官方视频是这么

    2024年02月04日
    浏览(53)
  • 快速解决Spine动画导入Unity后需要设置Straight Alpha Texture的问题

    在导入Spine资源后,Unity会根据不同的后缀,自动化构建出不同格式的资源。导入后,会发现播放的动画和导入前的动画的图片不一样。这时上网查基本都是需要手动吧材质资源的Straight Alpha Texture 勾上。 查看材质的Shader可以看出这个选项是用来选择颜色是否加了透明度的计算

    2024年02月16日
    浏览(37)
  • 【Unity】GPU骨骼动画 GPU Spine动画 2D/3D渲染性能开挂 动画合批 支持武器挂载 支持实时获取骨骼位置

     GPU 3D骨骼动画和 GPU 2D Spine动画插件均包含在【万人同屏整合方案】中,老板们可在某宝搜:[游戏开发资源商店] 以获取全套方案的所有源码插件。 插件功能: 1. 支持3D动画转GPU动画  2. 支持2D Spine动画转GPU动画 3. 支持挂点、支持挂载物、动态切换挂载物、实时获取挂点T

    2024年01月18日
    浏览(44)
  • 【Unity】GPU骨骼 GPU Spine动画 2D/3D渲染性能开挂 合批渲染 支持武器挂载 动画事件 动画融合 实时获取骨骼位置

     GPU 3D骨骼动画和 GPU 2D Spine动画插件均包含在【万人同屏整合方案】中,老板们可在某宝搜:[游戏开发资源商店] 以获取全套方案的所有源码插件。   万人同屏渲染避障锁敌方案实现对抗战斗demo 展示GPU动画高级功能 动画事件 动画平滑过渡 融合   插件功能: 1. 支持3D动画

    2024年02月22日
    浏览(48)
  • Spine(Unity)

    1.当前动画播放完毕后自动播放下一个动画 2.自动动画补偿问题 1)由于spine在切换动画的时候自动补偿,用于动画的平稳过度。但是会导致残影等bug,这时候需要在SetAnimation前调用 skeletonAnimation.skeleton.SetToSetupPose (); spineAnimationState.ClearTracks ();    或 skeletonGraphic.AnimationState

    2024年02月11日
    浏览(46)
  • Unity Spine帧事件

    编辑窗口 点坐边的那个小灰点来切换 亮点代表当前动画 可以一个事件 添加多个监听 一个事件可以添加多个监听

    2024年02月12日
    浏览(43)
  • unity spine 进阶使用

    在项目实践中,我们常常遇到收集金币,钻石等这样的特效需求,最初我们也是全靠代码实现,效果总是差点,偶然和我们动画师聊天确定了一种新的实现方案。 大概流程是动画师在spine软件中实现炸金币+飞金币的过程 输出文件给到程序,程序需要在代码中动态修改节点位

    2023年04月08日
    浏览(74)
  • 随笔-Unity中修改Spine材质

            我们在Unity中使用Spine动画时,往往需要在材质上添加一些效果,比如描边、闪光等等。              这些效果其实在Spine插件中就给我们提供好了对应的Shader,路径分别是: Spine/Outline/Skeleton、Spine/Skeleton Fill。 虽然有插件上给我提供好了这些常用的Shader,单独

    2024年02月11日
    浏览(55)
  • Unity 2D Spine 外发光实现思路

    前言 对于3D骨骼,要做外发光可以之间通过向法线方向延申来实现。 但是对于2D骨骼,各顶点的法线没有向3D骨骼那样拥有垂直于面的特性,那我们如何做2D骨骼的外发光效果呢? 理论基础 我们要知道,要实现外发光效果,首先得先实现外描边效果。对于2D图片的描边实现有

    2024年02月22日
    浏览(43)
  • 如何将spine的素材导入unity

    最近做项目,想将少前里的小人素材导入到unity里,于是乎便去捣鼓了一下,随便记录一下方便以后查看。 第一步:将素材导入spine(如果你已经有素材了,直接跳到第二步即可) 这里参考b站的一个教程:【少前/教程/小人动画】3分钟学会如何提取少前小人制作小人动画_哔

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包