Hi there, I’ve been trying to update a sprite’s bones using the sprite data extensions but I can’t get it to save to the asset.
Thanks
Hi there, I’ve been trying to update a sprite’s bones using the sprite data extensions but I can’t get it to save to the asset.
Thanks
Hello @keeperman ,
Could you share with us the code you use, and what happens when you run it?
Nothing happens when I apply the bones, and I’m unsure if this is the correct way off applying as I can’t seem find anything useful on google.
var path = AssetDatabase.GetAssetPath(tex);
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
var test = AssetDatabase.LoadMainAssetAtPath(path) as Texture2D;
tex.SetBones(bones);
EditorUtility.SetDirty(tex);
EditorUtility.SetDirty(textureImporter);
EditorUtility.SetDirty(a);
// AssetDatabase.AddObjectToAsset(tex, test);
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
The data that makes up a Sprite object is stored in the Texture’s metafile in the form of a SpriteRect object. On asset import, we go through all the SpriteRects inside the metadata and create Sprite objects. Sprites only live throughout the session, and will not write back the data into the metafiles. So any changes you make to a Sprite will only affect that Sprite.
If you would like to inject data into a Sprite, I would suggest you to look into injecting the data on AssetImport. Have a look at this AssetPostProcess hook to see if it can solve your problem.
Thanks, I tried using the injection method but I can’t get the any of the extension types like bones to save, while other non U2D things seem to be able to. Am I doing it wrong?
Also the bones have a different values in the SpriteBone than they do in the meta file, and the AssetPostProcessor example seem to have a typo in the second ‘P’.
void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
{
TextureImporter imp = assetImporter as TextureImporter;
var bones = new List<ScaleBones.BoneData>();
foreach (var data in imp.userData.Split('|'))
{
var boneData = new ScaleBones.BoneData();
object boxed = boneData;
EditorJsonUtility.FromJsonOverwrite(data, boxed);
boneData = (ScaleBones.BoneData)boxed;
bones.Add(boneData);
}
foreach (var sprite in sprites)
{
var boneData = bones.First(x => x.spriteName == sprite.name);
var bone = boneData.GetBones();
foreach (var b in bone)
{
Debug.Log(b.name);
Debug.Log(b.position);
Debug.Log(b.length);
}
Debug.Log(sprite.GetSpriteID());
sprite.SetBones(bone);
// EditorUtility.SetDirty(sprite);
}
// EditorUtility.SetDirty(texture);
// EditorUtility.SetDirty(imp);
// AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
// imp.userData = string.Empty;
}
Thanks for letting me know, I’ve reported this issue to the Docs team.
Using OnPostprocessSprites allows you to inject data into a Sprite on import, but this data will not be stored in the metafile.
Saving bone data into the metafile is currently not a public API. If this is your goal, could you tell me a bit more about what you are trying to accomplish? This would help us in planning future updates to the 2D feature set.
That is the goal. I’m trying to create a custom importer for 2D blender animations, so I need to transfer the weights and bones to the 2D animation framework
I took a closer look at this, and there is a way for you to create your own custom importer. If you use OnPostprocessSprites, you will override the 2D Animations own setup of the Sprite. You could implement your own import variant, and take inspiration from the one we ship in the 2D Animations package (SpritePostProcess.cs). Mind you, we do not have any documentation for this flow, and you might meet some errors we don’t fully catch.
I’m also curious about this approach. How come you would like to create your own custom importer for Blender? Are there some limitations you have experienced from using a 3D model with animations and mixing it with 2D content?
Hi! I’m having a similar issue to @keeperman 's one.
I’m trying to copy a reference’s mesh and bones to similar sprites (I know there’s Sprite Swap for this, but switching to experimental features might bring issues anywhere else in the 2d animation package).
Got to modify the Sprite’s object with the new geometry and bones, but they aren’t being saved to the asset.
If I modify normal sprite’s properties (i.e, it’s name) they save properly. Also noted that the name is not saved inside the texture’s .meta
Couldn’t access or modify sprite’s bones from the texture itself as SpriteMetaData does not contain 2d animation’s fields.
The SpritePostProcess you mentioned seems to be doing exactly what I’m trying to do, it looks like I need to work around with something called ISpriteEditorDataProvider, will give it a try.
If this doesn’t works, I guess I’ll have to modify the .meta by hand to get the results that I want (as sugested in this question)
Got it to work by using ISpriteEditorDataProvider. Far from ideal but works fine
Hello @iJuan ,
In the Skinning Editor, we have Copy and Paste implemented to copy the bone and mesh data over to another Sprite. Is this what you are looking for?
You mention that you do not wish to use experimental features, so this might not be for you, but in the 2021.1 version of PSD Importer we have added the ability to share skeletons between .psb files. This eases the setup of bone structures. You can read more about it here.
Hey @Ted_Wikman ,
What I did is actually very similar to the skinning editor’s copy and paste. Main difference being that I can modify my reference asset and all the other assets will be updated with those changes automatically.
With Copy and paste, I would have to open all the images with an affected mesh and update it manually. Right now that isn’t an issue in my project to be fair, but we’re planning on having potentially hundreds of images so this would become very time consuming.
Didn’t know about the skeleton assets. I’ll definitely check it out (might even try hooking it up with sprite libraries so that all sprites in the same category share a skeleton). Eventhough, I’ll wait for it to be released before using it in real projects
There doesn’t seems to be any mention to sharing meshes with the Skeleton Asset. I think having both shared meshes (vertices/indices/edges/bone weights) and skeletons would be very handy to simplify sprite swapping (i.e, changing shirts on a character where all shirts share the same outline).
Another use case I’m thinking of is playing animations inside a skinned sprite, where the general outline of the sprite stays untouched. If I were to do that, I would want to replace only the texture itself while keeping all the data from the previous one (Like, in this scenario there’s no need to recalculate the deformations + uvs as the previous one would work)
Yeah, this sounds like a great candidate for the skeleton feature. But you are correct that we only share bone data, and not skinning or mesh data.
Your two suggestions are interesting, and maybe what we should look into is the ability to swap the texture used by the SpriteRenderer in an easier way, instead of adding even more functionality into the skinning editor/2d animation package. I’ll bring this back to the team. Good points.
I am also curious to hear from you the same question I had for @keeperman ; this would be very easy to do with an ordinary mesh and swapping the texture in a material. What is the reason you stick with the 2d feature set, and not just roll with full 3d?
Mostly due to stubbornness I guess.
Another member from my team actually proposed using 3d meshes, it seems to work fine as long as you use a 2d shader, but we opted for giving 2d a try.
Also with 2d we can have our mesh being auto generated to fit a sprite and edit it from inside unity’s editor. If we wanted to add more meshes to our project or modify existing ones using 3d, we would have to manage the models in an external tool, so that’s a plus for 2d.
Currently you’re saving all the mesh data inside the .meta file from the texture, you might need to decouple that data somewhere else before swapping a texture in the SpriteRenderer, otherwise the repeated data would lead to confusion on which data file is currently affecting the renderer (If you take, for example, the data which was present when you create the renderer and then modify the texture, accessing this data from the renderer would give a different result than accessing it from the texture/sprite)