Hey guys , I finally resolve this problem . The flow is you have seperate these steps :
1/ Write a postprocess script to auto slice single sprite into many when import , save those assets by assetdatabase
2/ After saving above assets , load sprites into animations on Unity Editor , you could use my scripts bellow
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
#if UNITY_EDITOR
public class PostProcessImportTexutre : AssetPostprocessor
{
//Custom your wished size here
public static readonly Vector2 SPRITE_SIZE = Vector2.one * 105f;
[MenuItem("Tool/PostImportTexture/Enable")]
public static void EnableAnimGenerator()
{
EnableImageToAnimImport = true;
Debug.Log($"ENABLE import to anim successfully, content path check = {PathContains}");
}
[MenuItem("Tool/PostImportTexture/Disable")]
public static void DisableAnimGenerator()
{
EnableImageToAnimImport = false;
Debug.Log($"DISABLE import to anim successfully, content path check = {PathContains}");
}
//Sprite path to check ,custom here
protected const string PathContains = "NFT_CHAR";
protected static string _processedFile;
protected static bool EnableImageToAnimImport = false;
void OnPreprocessTexture()
{
if (!EnableImageToAnimImport) return;
if (!this.assetPath.Contains(PathContains)) return;
Debug.Log("OnPreprocessTexture(): Processing File: " + this.assetPath);
TextureImporter importer = (TextureImporter)this.assetImporter;
importer.spriteImportMode = SpriteImportMode.Multiple;
}
void OnPostprocessTexture(Texture2D texture)
{
if (!EnableImageToAnimImport) return;
if (!this.assetPath.Contains(PathContains)) return;
Debug.Log("OnPostprocessTexture(): Processing File " + this.assetPath);
// Used to ignore the re-import
if (_processedFile != null)
{
_processedFile = null;
return;
}
_processedFile = this.assetPath;
// cut spritesheet into pieces
TextureImporter importer = (TextureImporter)this.assetImporter;
if (importer.spriteImportMode != SpriteImportMode.Multiple) return;
Rect[] rects = InternalSpriteUtility.GenerateGridSpriteRectangles(
texture,
Vector2.zero,
SPRITE_SIZE,
Vector2.zero,
false
);
Debug.Log("rect width,height :" + rects[0].width + "," + rects[0].height);
int index = 0;
importer.spritesheet = rects.Select(rect => new SpriteMetaData
{
pivot = Vector2.down,
alignment = (int)SpriteAlignment.BottomCenter,
rect = rect,
name = texture.name + "_" + ++index
}).ToArray();
AssetDatabase.ForceReserializeAssets(new List<string> { this.assetPath });
}
}
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Color = UnityEngine.Color;
#if UNITY_EDITOR
public class ImageToAnimGenerator
{
//Custom path here
public static string NFTAssetPath = Path.Combine(Utilities.DataPath, "InHouse", "Art", "NFT_Char");
[MenuItem("Tool/LoadImageToAnim")]
public static void LoadImageToAnim()
{
try
{
var pngFilePaths = Directory.GetFiles(NFTAssetPath, "*.png", SearchOption.AllDirectories);
var fLength = pngFilePaths.Length;
Debug.Log($"There're {fLength} images");
int curIndex = 0;
foreach (var pngPath in pngFilePaths)
{
++curIndex;
var progress = (float)curIndex / fLength;
EditorUtility.DisplayCancelableProgressBar("Loading png to texture", "", progress);
var relativePath = pngPath.FullPathToUnityRelativePath();
GenerateAnim(relativePath);
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
finally
{
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
}
}
public static void GenerateAnim(string relativeAssetPath)
{
var sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(relativeAssetPath).Select(x => (Sprite)x)
.ToList();
sprites.ForEach(x => Debug.Log(x.name));
Debug.Log($"{sprites.Count} sprite at {relativeAssetPath}");
AnimationClip clip = new AnimationClip { frameRate = TOOLANIMCONFIG.ANIM_FRAME_RATE };
EditorCurveBinding spriteBinding = new EditorCurveBinding
{
type = typeof(SpriteRenderer), path = "", propertyName = "m_Sprite"
};
ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[sprites.Count];
for (int i = 0; i < sprites.Count; i++)
{
spriteKeyFrames[i] = new ObjectReferenceKeyframe
{
time = i * TOOLANIMCONFIG.FRAME_TIME,
value = sprites[i] // The frames cease to exist after this function call
};
}
AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames);
var animPath = GetAnimSavePath(relativeAssetPath);
AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames);
AssetDatabase.CreateAsset(clip, animPath);
AssetDatabase.ForceReserializeAssets(new[] { animPath });
}
public static string GetAnimSavePath(string inputPath)
{
var result = inputPath.Replace("Art", "Animation").Replace(".png", ".anim");
Debug.Log($"Anim path : {result}".ToColor(Color.cyan));
var fileName = Path.GetFileName(result);
var parentPath = result.Replace(fileName, string.Empty);
//Write your own method to create directory here
Utilities.CreateDirectoryIfNotExist(Path.Combine(Utilities.GetCurrentDir, parentPath));
return result;
}
}
public static class TOOLANIMCONFIG
{
public const int ANIM_FRAME_RATE = 30;
public const float FRAME_TIME = 0.066f;
}
#endif