Unity 动画

DOTween

通过简化的代码为任何内容制作动画。DOTween 是一个快速、高效、完全类型安全的面向对象的动画引擎,针对 C# 进行了优化(它是以前的 Unity 补间引擎 HOTween 的演变)。

  1.   特性

    • 速度和效率:所有内容都被缓存和重用

    • IntelliSense 和类型安全

      • IntelliSense [ɪn'telisns]:代码补全辅助工具

      • 类型安全:任何地方都没有字符串

    • 快捷方式:直接扩展常见对象的快捷方式

     

    // Move a transform to position 1,2,3 in 1 second transform.DOMove(new Vector3(1,2,3), 1); // Scale the Y of a transform to 3 in 1 second transform.DOScaleY(3, 1); // Pause a transform's tween transform.DOPause();

    • 极其准确:时间是以非常精确的方式计算

    • 逻辑且易于使用的 API

    • 为一切制作动画(几乎):可以对每个数值以及一些非数值进行动画处理。它甚至可以对字符串进行动画处理,并支持富文本

    • 模块:可以通过 DOTween Modules 激活/停用对 Unity 系统(物理/音频/UI/等)的引用。

    • 完全控制:播放,暂停,倒带,重新启动,完成,转到以及大量其他有用的方法来控制补间。

    • 分组:将补间组合成序列以创建复杂的动画(不需要在序列中:它们也可以相互重叠)。

    • 可混合补间:一些补间可以实时相互混合。

    • 路径:沿着线性和曲线路径制作动画

    • 在播放时更改值和持续时间

  1. 使用

    1. 在资源商店下载并安装DOTween

      1. 在PackageManager导入到要使用的项目中。

      2. 安装完成后点击 Setup DOTween 会自动根据unity的版本导入/重新导入内部的一些文件,激活或者停用一些模块。

      3. Tools/Demigiant/DOTween Utility Panel 打开该面板。

    2. 在使用DOTween需引入对应的命名空间:

     

    using DG.Tweening;

    1. 初始化DOTween,设置一些全局设置。

      1. 默认的设定可以在初始面板中的首选项(Preferences)中更改。

     

    DOTween.Init();

    参数

    功能

    recycleAllByDefault

    bool类型,如果为true,所有的 动画补间将会在调用完后被回收放入一个对象池中,而不是直接被销毁。

    useSafeMode

    bool类型,如果为true,补间会变慢,但是会更加安全,允许补间照顾一些东西,当一个物体被销毁时,补间仍然执行。

    logBehaviour

    据所选模式,DOTween 将只记录错误(ErrorsOnly)或者错误和警告(Default),或所有内容以及其他信息(Verbose)

      命名法

    • Tweener :补间,控制值并为其生成动画。

    • Sequence:序列,控制多个补间作为组来处理。

    • Tween:通用词,通用词表示补间和序列。

    • Nested tween:嵌套补间,序列中包含的补间。

      前缀

    • DO:所有快速实现一些补间效果的前缀(如变换Transform)的前缀。

    • Set:对当前效果进行设置。

    • On:一系的列回调。

DOTween详情:https://dotween.demigiant.com/documentation.php#globalSettings

spine动画

详情:https://zh.esotericsoftware.com/spine-unity

插件库导入

  1. 从开源库导入:

    1. 克隆 spine-runtimes Git repository.

    2. spine-runtimes/spine-unity/Assets/ 里的文件拷贝到你项目里的 Assets/ 文件夹里.

    3. spine-runtimes/spine-csharp/src 文件夹拷贝到你项目里的 Assets/Spine/Runtime/spine-csharp 文件夹中.

  2. 从官网插件导入

    1. 下载 最新的 spine-unity 组件包.

    2. 导入这个Unity组件包 (双击它就可以让Unity打开).

通过软件包管理器安装spine-unity运行时

使用Unity的包管理器-'Add package from git URL'而非直接打开Unity组件包(unitypackage) 如果你的Unity版本比较新, 且你的Unity包管理器提供了 Add package from git URL... 选项, 你也可以直接使用下方的三个URL来添加这三个包:

  1. https://github.com/EsotericSoftware/spine-runtimes.git?path=spine-csharp/src#4.1

  2. https://github.com/EsotericSoftware/spine-runtimes.git?path=spine-unity/Assets/Spine#4.1

  3. https://github.com/EsotericSoftware/spine-runtimes.git?path=spine-unity/Assets/Spine Examples#4.1

要打开Spine Examples包的示例场景请使用操作系统的文件管理器(ExplorerFinder), 应将场景文件从包目录复制到你的 Assets目录. 因为如果你试图直接打开通过git URL下载的包中的场景, Unity中的一个bug会导致出现"Opening scene in read-only package!"错误:

在Unity中导入Spine 资产

  1. Json格式

  2. 二进制数据格式

  1. 打开导出文件的文件夹

  2. 将导出的文件(或包含它们的文件夹)复制到项目的 Assets 文件夹中

  3. spine-unity自动生成文件

    1. _Atlas 文件是texture atlas文件 (.atlas.txt). 它包含对material和 .atlas.txt 文件的引用.

    2. _Material 包含了各个 texture atlas页 (.png). 它包含对着色器和 .png texture的引用.

    3. _SkeletonData 存储了skeleton数据 (.json, .skel.bytes). 它包含了对 .json.skel.bytes 文件以及生成的 _Atlas 资产的引用. 它还为skeleton提供了自定义的导入和动画设置, 详见 Skeleton Data 资产部分.

将Skeleton添加到场景中

  • 方法1:

    • _SkeletonData 资产拖入Scene视图或Hierarchy面板然后选择 SkeletonAnimation. 这将实例化一个带有所需Spine组件的新GameObject.

  • 方法2:

    • GameObject -> Create Empty 菜单创建一个新的空GameObject.

    • 在检查器中选择GameObject然后点击 Add Component, 然后选择 SkeletonAnimation. 这会自动为GameObject添加 MeshRendererMeshFilter 组件.

    • SkeletonAnimation 组件中, 把所需的 _SkeletonData 资产赋值给 Skeleton Data Asset 属性

三种实例化skeleton的方法

  1. SkeletonAnimation - 使用Spine定制的动画和事件系统, 提供最高的可定制性. 渲染使用的是 MeshRenderer, 可以像Unity sprite一样与 SpriteMask 等遮罩进行交互. 在Unity中推荐以这种方式使用Spine skeleton.

  2. SkeletonGraphic (UI) - 与Unity Canvas一起作为UI元素使用. 像内置的Unity UI元素一样渲染并与UI遮罩(如 RectMask2D )交互. 动画和事件行为与 SkeletonAnimation相同.

  3. SkeletonMecanim - 使用Unity的Mecanim动画和事件系统来启动、mix和过渡动画. 与SkeletonAnimation相比,提供的动画mix和过渡选项较少.当使用 SkeletonMecanim 时, 无法保证动画过渡看起来和Spine Editor中的预览一致.

高级 - 运行时实例化

注意: 推荐通过正常的工作流将skeleton添加到场景中, 并将其存储于prefabs内, 而非从实例池中取出池化对象来复用. 这样会使得修改和调整更加容易.

 

// 从 SkeletonDataAsset 实例化 SkeletonAnimation 游戏对象 SkeletonAnimation instance = SkeletonAnimation.NewSkeletonAnimationGameObject(skeletonDataAsset); // 从 SkeletonDataAsset 实例化 SkeletonGraphic 游戏对象 SkeletonGraphic instance = SkeletonGraphic.NewSkeletonGraphicGameObject(skeletonDataAsset, transform, skeletonGraphicMaterial);

 

// 从导出的资产实例化,无需事先导入 // 1. 创建 AtlasAsset(需要 Atlas 文本资源和纹理,以及材质/着色器); SpineAtlasAsset runtimeAtlasAsset = SpineAtlasAsset.CreateRuntimeInstance(atlasTxt, textures, materialPropertySource, true); // 2. 创建 SkeletonDataAsset(需要 json 或二进制资产文件,以及 AtlasAsset) SkeletonDataAsset runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true); // 3. 创建 SkeletonAnimation(需要有效的 SkeletonDataAsset) SkeletonAnimation instance = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);

SkeletonAnimation

  参数
  1. Initial Skin:该皮肤将在动画开始时显示.注意:如果你看到的skeleton没有附加任何图像,可以切换到 default 以外的皮肤来显示皮肤.

  2. Animation Name.:该动画将在开始时播放.

  3. Loop:定义初始动画是循环播放还是只播放一次.

  4. Time Scale:设置时间比例来减慢或加快动画的播放速度.

  5. Unscaled Time:当置为true时, 更新将根据Time.unscaledDeltaTime时间而非Time.deltaTime进行. 这对于不适用慢动作效果的动画UI元素来说非常有用.

SkeletonAnimation Update 回调
  • SkeletonAnimation.BeforeApply 事件在应用该帧动画之前被引发. 当你想在动画应用到skeleton上之前改变skeleton的状态时, 请使用这个回调.

  • SkeletonAnimation.UpdateLocal 事件在该帧动画更新完成并应用于skeleton的局部值之后被引发. 如果你需要读取或修改骨骼的局部值, 请使用它.

  • SkeletonAnimation.UpdateComplete 在计算完Skeleton中所有骨骼的世界值后被引发. SkeletonAnimation在这之后不会在Update中做进一步的操作. 如果你只需要读取骨骼的世界值, 就使用它. 如果有代码在SkeletonAnimation的Update之后修改了这些值, 这些值可能仍会发生变化.

  • SkeletonAnimation.UpdateWorld 是在计算了Skeleton中所有骨骼的世界值后引发的. 若订阅了该事件则将二次调用 skeleton.UpdateWorldTransform. 如果你的skeleton复杂或正在执行其他计算, 那这将是多余甚至是浪费的行为. 如果需要根据骨骼的世界值来修改骨骼的局部值, 请使用该事件. 它在Unity代码中实现自定义约束很有用.

SkeletonRenderer Update 回调
  • OnRebuild 在skeleton成功初始化后触发.

  • OnMeshAndMaterialsUpdated 会在更新完网格和所有material后, 于LateUpdate()结束时触发.

Skeleton

SkeletonAnimation 组件通过 SkeletonAnimation.Skeleton 属性提供对底层skeleton的访问. 一个Skeleton存储了对一个skeleton data资产的引用,而skeleton data又引用了一个或多个atlas资产.

通过Skeleton可以设置皮肤、附件、重置骨骼为setup pose、比例以及翻转整个skeleton.

  设置附件

  设置一个附件需要提供槽位和附件名称.

 

bool success = skeletonAnimation.Skeleton.SetAttachment("slotName", "attachmentName");

  重置为Setup Pose
 

skeleton.SetToSetupPose(); skeleton.SetBonesToSetupPose(); skeleton.SetSlotsToSetupPose();

  设置皮肤
 

bool success = skeletonAnimation.Skeleton.SetSkin("skinName"); skeletonAnimation.Skeleton.SetSlotsToSetupPose(); // see note below

  组合皮肤
 

var skeleton = skeletonAnimation.Skeleton; var skeletonData = skeleton.Data; var mixAndMatchSkin = new Skin("custom-girl"); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("skin-base")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("nose/short")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("eyelids/girly")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("eyes/violet")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("hair/brown")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("clothes/hoodie-orange")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("legs/pants-jeans")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("accessories/bag")); mixAndMatchSkin.AddSkin(skeletonData.FindSkin("accessories/hat-red-yellow")); skeleton.SetSkin(mixAndMatchSkin); skeleton.SetSlotsToSetupPose(); skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);

  运行时重打包

  在组合皮肤时会有多个material累积, 这将引发额外的绘制调用. 使用Skin.GetRepackedSkin() 方法可以在运行时将收集到的皮肤中使用过的texture区域合并为一个texture.

 

using Spine.Unity.AttachmentTools; // Create a repacked skin. Skin repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial, out runtimeMaterial, out runtimeAtlas); collectedSkin.Clear(); // Use the repacked skin. skeletonAnimation.Skeleton.Skin = repackedSkin; skeletonAnimation.Skeleton.SetSlotsToSetupPose(); skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); // skeletonMecanim.Update() for SkeletonMecanim // You can optionally clear the cache after multiple repack operations. AtlasUtilities.ClearCache();

重要提示: 如果重打包失败或产生意外问题, 可能源于以下原因:

  1. 禁用了读/写. 你可能需要在并入重打包texture的源textures上设置 Read/Write Enabled 参数.

  2. 启用了压缩: 需要确保源texture的Texture导入设置中 CompressionNone , 而不是 Normal Quality.

  3. 质量层使用了half/quarter分辨率的textures: 这个是Unity的bug, 当使用half/quarter分辨率的texture时会复制错误区域. 确保项目设置中的所有质量层都使用全分辨率texture.

  4. 源texture不是2次texture但Unity将其放大为了最接近次数:a)从Spine导出时启用 Pack Settings 中的 Power of two, 或者b)确保Unity的Atlas Texture导入设置中将 Non-Power of Two 置为 None.

动画 - AnimationState
  生命周期

  SkeletonAnimation 组件实现了 Update 方法,它根据delta时间更新底层 AnimationState, 将 AnimationState 应用于skeleton上, 并更新skeleton上所有骨骼的世界transforms.

  skeleton动画组件通过 SkeletonAnimation.AnimationState 属性暴露了AnimationState API.

  时间比例(Scale)

  你可以设置skeleton动画组件的时间比例, 以减慢或加快动画的播放速度. 用于推进动画的delta时间会乘上时间比例来决定动画播放速度, 例如时间比例为0.5时, 动画会减慢到正常速度的一半, 时间比例为2时, 动画会加速为正常速度的两倍.

 

float timeScale = skeletonAnimation.timeScale; skeletonAnimation.timeScale = 0.5f;

  设置动画

  要设置一个动画,需要确定轨道索引(index)、动画名称和是否循环动画.

 

TrackEntry entry = skeletonAnimation.AnimationState.SetAnimation(trackIndex, "walk", true);

  也可以传入 AnimationReferenceAsset 作为参数而非动画名字.

 

// using AnimationReferenceAsset public AnimationReferenceAsset animationReferenceAsset; // assign a generated AnimationReferenceAsset to this property ... TrackEntry entry = skeletonAnimation.AnimationState.SetAnimation(trackIndex, animationReferenceAsset, true);

  动画队列:要排队动画, 需要提供轨道索引、动画名称、是否循环播放该动画, 以及该动画在轨道上开始播放的延迟时间(以秒计).

 

TrackEntry entry = skeletonAnimation.AnimationState.AddAnimation(trackIndex, "run", true, 2);

  设置和队列空动画, 清空轨道

 

TrackEntry entry = skeletonAnimation.AnimationState.SetEmptyAnimation(trackIndex, mixDuration); entry = skeletonAnimation.AnimationState.AddEmptyAnimation(trackIndex, mixDuration, delay); skeletonAnimation.AnimationState.ClearTrack(trackIndex); skeletonAnimation.AnimationState.ClearTracks();

  轨道条目(Entry)

    所有的方法都会返回一个 TrackEntry 对象,可以通过它来进一步定制具体动画的回放,以及定制绑定到轨道条目的具体事件的委托.

注意: 返回的轨道条目只在底层动画状态中删除了对应动画之前有效. Unity的垃圾收集器会自动释放它们. 在接收到轨道条目的销毁事件(dispose event)后, 它就无法再被存储或访问.

 

TrackEntry entry = ... entry.EventThreshold = 2; float trackEnd = entry.TrackEnd;

处理AnimationStates事件

  底层的 AnimationState 回放动画时,将引发下列事件来通知监听器(listener):

  1. 动画已开始(started) .

  2. 动画被中断(interrupted), 例如清空了一条轨道或设置了一个新的动画.

  3. 动画无中断地播放已完成(completed) , 如果是循环动画, 该事件可能会多次出现.

  4. 动画已停止(ended) .

  5. 动画和其所处的 TrackEntry 已被销毁(disposed) .

  6. 触发了用户定义的事件(event).

注意: 当设置了一个新动画时, 如果中断了之前的动画, 将不会引发完成(complete)事件,而会引发中断(interrupt)和停止(end)事件.

Skeleton动画组件提供了C#代码可以绑定的委托, 以便对全部轨道上全部队列中的全部动画的事件做出反应. 监听器也可以只与特定 TrackEntry 的委托绑定.所以你可以注册到如 AnimationState.Complete 事件来处理任何后续的动画 Complete 事件的事件回调(event callbacks),或者注册到 TrackEntry.Complete 事件来处理由某个入队动画引发的 Complete 事件.

常见问题

https://zh.esotericsoftware.com/spine-unity#%E5%B7%B2%E7%9F%A5%E9%97%AE%E9%A2%98

  • 28
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity动画的基础可以分为两个方面:动画制作和动画控制。 动画制作是指通过制定关键帧来构建动画序列。在Unity中,我们可以使用两种方式来创建动画:一是使用骨骼动画,也称为骨骼绑定动画,这种方式通过在角色上绑定骨骼节点,并控制节点的位置和旋转来实现动作的变化;二是使用关键帧动画,也称为基于时间变化的动画,这种方式通过逐帧地改变角色模型的属性,例如位置、旋转、缩放等来实现动画效果。在动画制作过程中,我们可以使用Unity内置的动画编辑器或其他外部工具,如Maya或Blender来进行制作。 动画控制是指在游戏中通过代码控制和管理动画的播放。Unity内置了Animator组件来实现动画的控制。通过Animator组件,我们可以定义一系列的动画状态和过渡条件,以及在不同状态之间的转换方式。Animator组件提供了一些方法和属性,可以在代码中实时改变动画状态、调节动画播放速度,或者手动触发特定的动画效果。通过编写脚本并与Animator组件进行交互,我们可以实现角色的移动、攻击、跳跃等动作的播放和控制。 总结起来,Unity动画的基础包括动画制作和动画控制两个方面。在动画制作方面,我们可以选择骨骼动画或关键帧动画来创建动画效果;在动画控制方面,我们可以利用Animator组件和编写脚本来控制和管理动画的播放。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值