- 수정됨
How to use spine without atlas
Hi!
I am a programmer using Spine with Unity.
Our project allows you to put on a variety of clothes for your Spine character.
That is why the folder structure is as follows.
-outer
-outer1.png
...
-acc
-acc_ring.png
-vest
-top
-bottom
-hair
-nose
-mouth
....
There are so many types, so there are only 1500 png files.
So, when packing, the same kind of clothes are packed together, and a total of 18 files of 2048 size come out.
(For example, one texture has only pants, another texture has only a dress.)
However, in the game, only one of the many clothes is used.
Therefore, when you are done wearing clothes, a lot of draw calls occur and the heat of the mobile device becomes severe.
(Runtime repacking is turned off on phones below Galaxy S8.)
By not using the atlas, it would be good to reduce the draw call even if there are many exported textures.
Is it possible to export without using the atlas in Spine?
And can I use it in Unity?
There are multiple ways to bypass using or loading many large atlases:
- You can use single Unity
Sprites
and use them e.g. as a replacement for Spine attachments. You would then export e.g. only a single skin and then swap out other attachments programmatically. Please check out theMix and Match
andMix and Match Equip
example scenes that come with the spine-unity unitypackage. - You can move packing to the Unity Editor by using a Unity SpriteAtlas, creating the sprite atlas from the same single images and creating a
SpriteAtlasAsset
for it. See the documentation page section
here for details.
- You could dynamically load/unload atlas textures or atlas assets (this thread deals with loading/unloading skeletons and textures). If using asset bundles/etc you would need to make sure to first unlink and later re-assign any asset references between asset bundles.
In general you can use runtime-repacking instead of many atlases to reduce draw calls.
spine-unity Runtime Documentation: Combining Skins
While the above shows repacking of skins (which can be populated and combined at runtime), there is also a method AtlasUtilities.GetRepackedAttachments()
available.
Please let us know if any of the above suits your needs.
Thank you!
Let’s go over the top,
Is there a way to just completely avoid using the Atlas?
And can the information repacked at runtime be stored locally and used it?
For example scenario
After changing clothes in scene A, when it is finished, save the repacked result.
Using what was saved in scene B.
ly0738 wroteIs there a way to just completely avoid using the Atlas?
Do you mean avoiding creating any altas? Neither in Spine, nor Unity's Sprite Atlas?
ly0738 wroteAnd can the information repacked at runtime be stored locally and used it?
For example scenario
After changing clothes in scene A, when it is finished, save the repacked result.
Using what was saved in scene B.
I assume that moving from scene A to scene B is not the main issue, but rather you would want to save it between play sessions, is this correct?
Otherwise, you could always move whole GameObject over from one scene to another. I see no reason why you would then want to carry only a repacked texture over but not any other information of the character, such as it's game state, and the like. Repacking does not take long, it would be done in a few milliseconds (in worst case it would cause the framerate to stutter).
Currently we don't provide a method that performs re-packing but takes an existing already re-packed texture as input, as this is a rather rare scenario.
What you perhaps might instead want to do is save all slot's attachments of a skeleton to disk along with the repacked texture. Then you could restore this state later, as it needs to be consistent between the repacked atlas texture and the attachments regions mapping to this texture. This would require a bit of coding however.
Thank you so much for your kind answer.
Do you mean avoiding creating any altas? Neither in Spine, nor Unity's Sprite Atlas?
=> Yes avoiding createing any atlas.
If I simply move scene a -> b, it's a very easy situation.
But our situation depends on the scene and platform.
For example
Scene a is
Customize various costumes with the PC costume tool, pack the results, and save the results
I'm trying to get (by requesting the server) the contents packed in scene b, which is used on mobile, at runtime.
(Repacking at runtime is not only disconnected from mobile, but also turns off the app. It uses a 15-sheet 2048 atlas file.
If you can't imagine the situation, it would be convenient to confirm that I sent the Spine data by email because Nate asked for our Spine file due to a problem with Spine 4.0 beta export.)
The current situation seems to have succeeded in creating an atlas file by taking all region information from the repacked skin and making it in runtime to fit the spine atlas file (.atlas.txt). (Refer to the load function in atlas.cs in spine-unity.)
To summarize what I did,
- After choosing all the clothes in scene a
- Save 1 repacked png file
- Create atlas.txt in scene A with regions of the repacked skin object (see load function of atlas.cs in spine-unity, see Atlas export format)
Unity seems to recognize the atlas.txt of my repack.
But I don't know what to do as there is no repacked object of type skin in scene b.
Because scene a and scene b are independent.
I want to do something like this
SkeletonAnimation.Skeleton.SetSkin(RepackedSkin); //RepackedSkin is a skin packed in `a scene`
I think this is the
"save all slot's attachments of a skeleton to disk"
you mentioned.
How should I save it?
If I understood you correctly, then you would need to find a way to serialize the RepackedSkin
object and save it to disk, as you did with writing the repacked custom .atlas.txt
file, is this correct?
If so, then you would need to serialize at least the Skin.Attachments
content to your saved file. The easiest way might be to modify the spine-csharp code and add System.Serializable
attributes to the required classes (and potentially adjust protected or private members as well). Then you could use the more comfortable means of C# serializing and deserializing functionality.
The manual way would be to iterate over the Skin.Attachments
and serialized the values of each element. Then when you want to load it, you would then do something similar to this code to reconstruct everything:
Skin LoadSkin (File file, Texture2D yourPackedPNGTexture) {
Skin loadedSkin = new Skin("LoadedRepackedSkin");
// go through your serialized file for each attachment:
foreach (serializedAttachmentLineInFile) {
int slotIndex = ..; // read from file
string name = ..; // read from file
Attachment attachment;
bool isRegionAttachment = true; // loaded from file;
if (isRegionAttachment) {
RegionAttachment regionAttachment = new RegionAttachment(name);
regionAttachment.Width = ...; // load all values from file.
var atlasRegion = new AtlasRegion();
atlasRegion.u = ..; // load all values from file
atlasRegion.page.rendererObject = yourPackedPNGTexture;
atlasRegion.page.width = ...; // load all values from file.
regionAttachment.RendererObject = atlasRegion;
attachment = regionAttachment;
}
else {
// same for mesh attachment
}
loadedSkin.SetAttachment(slotIndex, name, attachment);
}
return loadedSkin;
}
Thank you very much for always the best answer.
If only the atlas information used for runtime repacking was put in atlas.txt, an import error occurred because there were no other regions. To bypass that, I changed only the coordinates of the runtime repacking regions in the existing atlas.txt, and it seems to work well.
It seems I didn't think of making the skin System.Serializable!
Thank you.
You're welcome, thanks for your kind words! Very glad to hear you've got a working version already.