pathfinder a écrit:Im investigating this approach since it should be easier to implement from what I understand.
I have been testing the barebones needed to support changing this on runtime and I have it partially working.
skeletonAnim.SkeletonDataAsset.atlasAssets = new AtlasAssetBase[1];
skeletonAnim.SkeletonDataAsset.atlasAssets[0] = atlas;
skeletonAnim.SkeletonDataAsset.Clear();
skeletonAnim.Initialize(true);
After doing this, im able to create a skin, set it and the slots and the skin renders.
I don't quite understand why you are creating an atlas asset via code here. The use case would rather be to assign an already prepared existing
SpineAtlasAsset
.
Apart from that you should be creating an instance of
SpineAtlasAsset
instead of the common base class
AtlasAssetBase
. Also, depending on what you are intending (editor scripting?), creating an instance of a
ScriptableObject
subclass should be done via
ScriptableObject.CreateInstance
instead of via
new
.
I tried accessing to this for modification but looks like the AtlasAssetBase.Materials is only readable. I could not find any way to modify at runtime this so far.
See above, you should be using
SpineAtlasAsset
instead of
AtlasAssetBase
.
If in doubt, you can always have a look at what the spine-unity source code does in the normal import scenario:
https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs#L516I see that there is a static method to create at runtime a SkeletonDataAsset, where I need to provide the mats + the .txt. The issue I see here is that I would need to recreate each time I change any skin (because the intention is to provide only the needed materials, by changing the skin I would need others).
Could you provide some more info on how to go to continue from here?
In general I would not recommend creating an atlas asset programmatically at runtime. You should instead prepare atlas assets ahead of time and then just assign the asset reference.
The best solution would be of course just changing the materials.
Yes, this would be best, if possible.
I also saw in another post that after doing that I should call skeletonDataAsset.Clear() and then Init the skeletonAnimator.
Basically yes, but note that calling
skeletonAnimation.Initialize(true)
(
override == true
here) will reload the complete skeleton, which might be tolerable, but costs the full loading time. Only switching Material references is free in comparison.
- 1. The skeletonJSON that comes from the export contains all the data, including the skins info.
- 2. The skeletonData needs to have all the regions from skins referenced (via atlases). (please confirm)
All references of active attachments need to be setup so that from each
RegionAttachment
or
MeshAttachment
it links to the respective atlas array's
AtlasRegion
, and has its uv coords setup accordingly.
You can have a look at the
NewRegionAttachment
and
NewMeshAttachment
code here, which sets up all references needed for both attachment types:
https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs#L47https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs#L62(
attachment.RendererObject = region;
assigns the reference from skeleton to the atlas here, together with setting up all uv and offset parameters)
You can however create a Skin separately which is not yet assigned at any skeleton. At the time you set this skin as
skeletonAnimation.Skeleton.Skin = customSkin
, all
RegionAttachment
and
MeshAttachment
region references and uv coords need to be setup accordingly beforehand.
3. I tried exporting manually each skin, getting a more modular organization (1 atlas per skin)4. Doing a material override doesnt work on this case because each skins possibility also change positions (not just a recolor).
So from this setup I think it would be a good idea to keep 1 atlas per skin, but the main issue still persists.
Now I see why you don't want to switch out Materials only. Basically the regions should match up when whitespace stripping is disabled upon atlas export. When whitespace stripping is enabled, differently transparent regions of the same Attachment in two skins will end up being placed at different locations in the respective output atlas, that is correct. This only applies to
RegionAttachments
,
MeshAttachments
always use the mesh boundaries for packing, transparent areas within the mesh cannot be cut-off and used by other attachments aparently.
So, if the blocker is that the skeletonData expects to have all the skins, the only viable solution I see is changing the json and creating a skeletonData at runtime with one containing only the skins I need.
It would be something like this:
1. Export from Spine and manually remove the skins on the json (leave the skin[] empty)
2. Pack and export 1 atlas per skin, an additionally add a json that would be the skin entry (that I previously removed)
3. Get the json with the empty skins, concat each skin I need on the empty array
4. Create the skeletonData at runtime providing the modified json + array of atlases that should cover whats only needed.
This is not recommended. Instead it would be better to just assign pre-built atlas assets at the skeletonData's atlas assets array. You could then either perform a full reload of the
SkeletonData
via
skeletonAnimation.Initialize(true)
, or perform only reloading of the attachments. The latter would however involve some coding I'm afraid.