使用 Unity EditorWindow 从 Spritesheet 创建动画?

Posted

技术标签:

【中文标题】使用 Unity EditorWindow 从 Spritesheet 创建动画?【英文标题】:Using Unity EditorWindow to Create Animations from Spritesheet? 【发布时间】:2021-08-08 06:17:06 【问题描述】:

目前我正在 Unity 中开发一款 2D 游戏。我正在使用 EditorWindow 对导入的 spritesheet 进行切片并从这些 sprite 中创建动画。

目前,我有代码来分割电子表格的功能,下面为有兴趣参考的人详细介绍:

public void Slice()

    var textures = Selection.GetFiltered<Texture2D>(SelectionMode.Assets);

    foreach (var texture in textures)
    
        ProcessTexture(texture, pixelPerUnit, spriteSize, pivot, alignment);
    


static void ProcessTexture(Texture2D texture, int pixelPerUnit, 
    Vector2Int spriteSize, Vector2 pivot, Alignment alignment)

    string path = AssetDatabase.GetAssetPath(texture);
    
        TextureImporter textureImporter = 
            TextureImporter.GetAtPath(path) as TextureImporter;

        //Set characteristics for spritesheet
        textureImporter.textureType = TextureImporterType.Sprite;
        textureImporter.spriteImportMode = SpriteImportMode.Multiple;
        textureImporter.spritePixelsPerUnit = pixelPerUnit;
        textureImporter.filterMode = FilterMode.Point;
        textureImporter.textureCompression = TextureImporterCompression.Uncompressed;

        int colCount = texture.width / spriteSize.x;
        int rowCount = texture.height / spriteSize.y;

        //Create Spritesheet Metadata based on characteristics
        List<SpriteMetaData> metas = new List<SpriteMetaData>();
        for (int c = 0; c < colCount; c++)
        
            for (int r = 0; r < rowCount; r++)
            
                SpriteMetaData meta = new SpriteMetaData();
                meta.rect = new Rect(c * spriteSize.x, 
                    r * spriteSize.y, 
                    spriteSize.x, spriteSize.y);

                meta.name = (rowCount - r - 1) + "-" + c;
                meta.alignment = (int)alignment;
                meta.pivot = pivot;
                metas.Add(meta);
            
        
        //Apply the metadata to the spritesheet
        textureImporter.spritesheet = metas.ToArray();
        AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
    

目前让我感到悲伤的部分是通过脚本将这个新切片的电子表格转换为动画。

目前我可以使用下面的代码sn-p在spritesheet的目录中创建一个空的动画剪辑:

string path = AssetDatabase.GetAssetPath(texture);
string newPath = Path.GetDirectoryName(path);

AnimationClip clip = new AnimationClip();
AssetDatabase.CreateAsset(clip, newPath + "\\" + spriteName ".anim");

我很难找到如何将精灵添加到这个新创建的动画中。我查看了AnimationCurves 和AnimationEvents,但似乎找不到通过编辑器将精灵链接到动画的步骤。

如果有人对通过脚本创建统一动画剪辑有经验或知识,任何见解将不胜感激。如果我需要更多信息,请告诉我。这是我第一次使用这项服务。谢谢大家的帮助!

【问题讨论】:

【参考方案1】:

我在这里发布我的决议,以防其他人想参考它!我最终参考了Create Animation Clip from Sprite[] (Programmatically) 和How to get child sprites from a 'Multiple Sprite' Texture 的文章。

通过编辑器窗口从选定的精灵表创建动画的结果代码粘贴在下面:

public void Animate()

    var textures = Selection.GetFiltered<Texture2D>(SelectionMode.Assets);

    foreach (var texture in textures)
    
        GenerateAnimations(texture, spriteSize, spriteName);
    


static void GenerateAnimations(Texture2D texture, Vector2Int spriteSize, string spriteNameGlobal)

    //Create an Array of all sprites in the selected texture
    string path = AssetDatabase.GetAssetPath(texture);
    Sprite[] allSprites = AssetDatabase.LoadAllAssetsAtPath(path).OfType<Sprite>().ToArray();
    string newPath = Path.GetDirectoryName(path);

    //Determine the number of rows & columns based on preset "spriteSize" Vector2
    int colCount = texture.width / spriteSize.x;
    int rowCount = texture.height / spriteSize.y;

    //Loop through each row of the spritesheet to make an animation
    for (int i = 0; i < rowCount; i++)
    
        //Create a sprite subsection for a row of sprites
        Sprite[] batchSprites = new Sprite[colCount];
        for (int j = 0; j < batchSprites.Length; j++)
        
            batchSprites[j] = allSprites[i * colCount + j];
        

        //Create the base AnimationClip
        AnimationClip clip = new AnimationClip();
        clip.frameRate = 12f;

        //Create the CurveBinding
        EditorCurveBinding spriteBinding = new EditorCurveBinding();
        spriteBinding.type = typeof(SpriteRenderer);
        spriteBinding.path = "";
        spriteBinding.propertyName = "m_Sprite";

        //Create the KeyFrames
        ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[colCount];
        for (int j = 0; j < spriteKeyFrames.Length; j++)
        
            spriteKeyFrames[j] = new ObjectReferenceKeyframe();
            spriteKeyFrames[j].time = j/clip.frameRate;
            spriteKeyFrames[j].value = batchSprites[j];
        
        AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames);

        //Set Loop Time to True
        AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);
        settings.loopTime = true;
        AnimationUtility.SetAnimationClipSettings(clip, settings);

        //Save the clip
        AssetDatabase.CreateAsset(clip, newPath + "\\" + spriteNameGlobal + i + ".anim");
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    

在使用此代码时,如果不小心会弹出一些有趣的问题。一个主要的问题是没有将 spriteBinding.propertyname 设置为“m_Sprite”。如果您决定修改此代码,请注意这一点。

我希望这被证明是有用的!如果有任何不清楚的地方,或者有进一步的澄清建议,请回复,我可以尝试改进此回复。

【讨论】:

以上是关于使用 Unity EditorWindow 从 Spritesheet 创建动画?的主要内容,如果未能解决你的问题,请参考以下文章

csharp EditorWindow示例来自Unity Asia Bootcamp 12演讲“简化您的Unity编辑器”。基于节点的简单编辑器。

[UnityAPI]EditorWindow类 & Editor类

Unity扩展编辑器二

Unity3D编辑器扩展——定义自己的窗口

Unity基础-编辑器

Unity资源热更