• RuntimesUnity
  • Loading SkeletonData in another thread

Hey there!
We had some performance issues when instantiating SkeletonGraphic components and it seems that loading the skeleton data + atlas is pretty pricey (skeletons are exported as bytes)

We fixed it by loading these assets (calling SkeletonDataAsset.GetSkeletonData) in another thread which seems to be working great; loading time is decreased in about 75% and no exceptions thrown / weird issues occur (for now 🙂)

However I'm not sure it's fully safe - would love to hear some thoughts on where/when it might cause issues/crashes for us

Pseudo code:

//Dummy, we'll probably get these from an asset bundle IRL
[SerializeField] private List<SkeletonDataAsset> skeletonsData;

//Called during the app load phase, so safe to assume there won't be other objects that'll call GetSkeletonData 
 public void LoadSkeletonData()
 {
       UniTask.RunOnThreadPool(LoadSkeletonDataInternal).Forget();
 }

 private void LoadSkeletonDataInternal()
 {
      foreach (SkeletonDataAsset skeletonData in skeletonsData)
          skeletonData.GetSkeletonData(true); //didn't change the source code for now, should we implement a lock? 
 }

*This is for a mobile game

Related Discussions
...

Loading SkeletonData in a separate thread can indeed improve performance significantly, as you've experienced. Since ReadSkeletonData accesses nothing Unity-specific and is contained in spine-csharp, it should generally be safe to run in a separate thread. However, you should be cautious about potential race conditions, especially if other parts of your code might access the same data concurrently. Implementing a lock around the GetSkeletonData call could help ensure thread safety, preventing any concurrent modifications or access issues. Additionally, always test thoroughly to ensure that no unexpected behavior occurs, especially as your application scales or as you integrate more complex features.

Generally the Spine Runtimes aren't thread safe, meaning you should not have multiple threads manipulating or accessing the same objects. However, you can load data on a separate thread, as long as other threads are not using the data yet, then pass it off to the game thread so there is only one thread accessing the objects at any given time. Take special care with textures, as some game toolkits require that to be done on the game thread.

Harald will be able to comment on spine-unity and your specific implementation.

@CandiGal Loading just the SkeletonData from a .skel.bytes file via GetSkeletonData(true) as in your shared code is safe to do, assuming that you perform proper thread-safe waiting or checking for completion of each LoadSkeletonDataInternal call.

I also just noticed that on your other thread you've asked about loading loading SkeletonData while I assumed you were talking about loading skeleton assets. Anyway, using Addressables via the spine-unity on-demand loading UPM packages should help with further off-loading part of your load-times onto utility threads.

Textures pose no issue here, as you certainly know these are not loaded in the GetSkeletonData() call.