【问题标题】:Using Unity EditorWindow to Create Animations from Spritesheet?使用 Unity EditorWindow 从 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");

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

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

【问题讨论】:

    标签: c# unity3d unity3d-2dtools unity3d-editor


    【解决方案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”。如果您决定修改此代码,请注意这一点。

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

    【讨论】:

      猜你喜欢
      • 2018-10-10
      • 1970-01-01
      • 1970-01-01
      • 2016-09-30
      • 2017-09-22
      • 1970-01-01
      • 2014-03-25
      • 2012-04-21
      • 1970-01-01
      相关资源
      最近更新 更多