My goal was to create an import script (AssetPostprocessor), that handles a few things for me whenever I drag a spritesheet (a picture that contains multiple frames for an animation) into a specific Unity folder.
I want the script to split the picture up into multiple frames (similar to when its done manually, with Sprite Mode = Multiple), and then create an animation out of it. I parse the instructions (name, sprite frame size, frame holds) from the file name that gets handled.
Example: "Player_Walk_200x100_h3-3-3-3-3.png"
So far, I managed to accomplish all of those points, but whenever I create an animation and link the given Sprites to it, the resulting animation is "empty". As far as I could figure out, that's because the Texture2D and Sprite[] given to OnPostprocessSprites() seems to be temporary. The object exists during creation, but seemingly gets discarded later on. How can I solve this? How can I grab a reference to Sprite[] that doesn't get dropped?
Here is a stripped down version of my current core:
void OnPostprocessTexture( Texture2D texture ) {
// the texture is split into frames here, code not included since this part works fine and would complicate things.
}
void OnPostprocessSprites( Texture2D texture, Sprite[] sprites ) {
if( !this.assetPath.Contains( 'spritetest' ) ) return;
Debug.Log( "Number of Sprites: " + sprites.Length ); // shows the correct number of sprites
if( sprites.Length == 0 ) {
AssetDatabase.ImportAsset( this.assetImporter.assetPath );
return;
}
int frameRate = 24;
AnimationClip clip = new AnimationClip();
clip.frameRate = frameRate;
EditorCurveBinding spriteBinding = new EditorCurveBinding();
spriteBinding.type = typeof( SpriteRenderer );
spriteBinding.path = "";
spriteBinding.propertyName = "m_Sprite";
ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[ sprites.Length ];
for( int i = 0; i < sprites.Length; i++ ) {
spriteKeyFrames[ i ] = new ObjectReferenceKeyframe();
spriteKeyFrames[ i ].time = i;
spriteKeyFrames[ i ].value = sprites[ i ]; // these sprites are empty in the editor
}
AnimationUtility.SetObjectReferenceCurve( clip, spriteBinding, spriteKeyFrames );
AssetDatabase.CreateAsset( clip, "Assets/Assets/spritetest/Test.anim" );
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
I've looked up forum posts, documentations, and even questions here (like Unity Editor Pipeline Scripting: how to Pass Sprite to SpriteRenderer in OnPostprocessSprites() Event? ) but none really managed to resolve this problem: whenever I try to grab the "real" sprite or texture via AssetDatabase, the resulting object is always just null.
For example, if I try doing this:
// attempt 1
Sprite sprites = AssetDatabase.LoadAssetAtPath<Sprite>( this.assetPath );
Debug.Log( "Real Sprite: " + sprite ); // sprite is null
// attempt 2
Object[] objects = AssetDatabase.LoadAllAssetRepresentationsAtPath( this.assetPath );
Debug.Log( "Real Objects: " + objects.Length ); // is always 0
Calling AssetDatabase.SaveAssets() or AssetDatabase.Refresh() beforehand doesn't change the result. I find plenty of people with similar issues, but no code or examples that seem to really resolve this issue.
Here is another person with a similar issue: ( source: https://answers.unity.com/questions/1080430/create-animation-clip-from-sprites-programmaticall.html )
The given link didn't resolve my problem either.
Essentially: How can I create an animation from an imported asset, by using my generated sprites, in AssetPostprocessor?
