当前位置:   article > 正文

Unity5序列帧动画实现方法及相关问题的解决方案(利用TexturePacker导出图集、自动生成AnimationClip)_unity自动生成动画

unity自动生成动画

最近新加入了一个项目,特效是使用序列帧图片实现的。既然如此,我就准备写点代码根据导出的序列帧图片,网上搜索了一下,发现了雨松MOMO大神的自动生成AnimationClip的文章:

Unity2D研究院之自动生成动画、AnimationController、Prefab(一)

只不过这篇文章已经是两年前的版本了,里面的代码在Unity5里有很多已经不可用了。这篇文章的评论区有朋友写出了一些Unity5需要改动的地方,需要的朋友可以自己翻一下,文章底部也会给出我的完整代码。

这里记录下我遇到的几个问题及解决方法:

1、TexturePacker导出图片,Unity再导入后,锚点全部错乱,导致动画“一直在抖”。
  • 原因:TexturePacker导出图集时有进行透明度裁剪,又没有保留原图的位置信息

  • 解决方案:在TexturePacker设置中将TrimMode设置为Crop, keep position而非Crop, flush
    position

2、UI上是不能直接使用SpriteRenderer的动画的,如果使用Image动画,设置好每帧的Sprite后,即使已经解决了问题1,动画也会一直在抖。
  • 原因:Image里面是使用RectTransform的sizeDelta属性,也就是Inspector面板里的width及height来控制宽高的。锚点则是使用RectTransform的pivot属性。这两个值都要单独设置,且不能有曲线动画。

  • 解决方案:生成AnimationClip时,计算好每张图片的sizeDeltaX\sizeDeltaY\pivotX\pivotY,记录到动画片段里,且设置动画每帧的tangentMode为Constant即可。嗯,好像是解决了问题的样子,但是怎么动画还在抖???这就要看问题3了。

3、将动画片段帧率改为24帧后,Sprite动画就错乱了。比方说正常情况应该是第0帧显示图片1、第1帧显示图片2、第2帧显示图片3….正常情况下第5帧应该显示图片6的,但是这里的动画片段第5帧依然显示图片5(与第4帧显示的图片相同了)。

这个问题就要慢慢说一下了,百度和Google都搜索不到相关的文章(也可能是我搜索的思路不对。。。毕竟英文不是很熟。。。)自己来查又几乎一点头绪都没有。
先上个图给大家看一下:

.anim里的sprite设置

可以看到在我导出的.anim文件里,已经设置好了每帧应该显示的sprite图片,注意下Element5里设置的是名为yaoshi10006的图。但是我在Animation动画编辑器里看到的却是这样:

Animation编辑器中第5帧变成了yaoshi10005

奇了个怪。。我之前一直以为是我导出.anim动画文件时每帧的sprite写入的有问题,这才发现原来不是。然后我想在Animation编辑器里去更改这一帧对应的图片,但无论我改成什么图片都会被还原回去,无法保存。后来一通乱点之后才发现,我可以删除这第3帧的关键帧,重新增加这一帧的关键帧后,就可以设置图片,也可以保存了,动画也就正常了。。。

经过这一通乱点之后,就确认了一定是.anim动画文件的问题。但是如我上图所示,sprite图片设置是对的,那又是哪里有问题呢?我将代码自动生成的.anim额外保存了一份,然后与我修改好的这一份.anim文件用对比工具进行文字对比,发现了一件有意思的事情:

文件对比结果,右图为修改后正常的动画文件

可以看到,原自动生成的动画文件第5帧记录的time是0.20833334,而修改后的动画文件第5帧的time是0.20833333,就是因为这么一点差异,导致了第5帧的图片没有产生变化,依然使用了第4帧的图片。既然知道了问题出在哪里,就容易解决了不是,回头看下生成AnimationClip时这个time是如何设置的:

    float frameTime = 1/clip.frameRate;
    for (int i = 0; i < sprites.Length; i++)
    {
        Sprite sprite = sprites[i];
        keyFrames[i] = new ObjectReferenceKeyframe();
        keyFrames[i].time = frameTime * i;
        keyFrames[i].value = sprite;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

一看time是一个float对象,难道会是由于精度问题所引起的?赶紧将代码进行了如下改动:

        double frameTime = 1d / 24d;
        for (int i = 0; i < sprites.Length; i++)
        {
            Sprite sprite = sprites[i];
            keyFrames[i] = new ObjectReferenceKeyframe();
            keyFrames[i].time = (float)(frameTime * i);
            keyFrames[i].value = sprite;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

到此,终于修复了动画中sprite图片错乱的问题。总算是有一个解决方法了吧,也不知道是否有更加合适的解决方案,如果有欢迎跟我说。。。下面是完整的自动生成动画文件的代码,其中的大部分思路均引用自雨松MOMO大神的文章。

using UnityEngine;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine.UI;

/// <summary>
/// 根据sprites图集自动生成序列帧动画
/// </summary>
public class BuildAnimationEditor : Editor
{
    [MenuItem("Assets/BuildSpriteRenderAnimation")]
    public static
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/138288
推荐阅读
相关标签
  

闽ICP备14008679号