RubenPG Posted April 2 Share Posted April 2 Hello, I'm running into some unexpected caching behavior with Spine in PixiJS. Package versions: "pixi.js": "8.17.1" "@esotericsoftware/spine-pixi-v8": "4.2.107" Code example: // STEP 1 — Load bundle await Assets.loadBundle('preloader'); // Assets are now available console.log([...Cache.keys()]); // = ['logoSkeleton', 'logoAtlas'] Assets.cache.has('logoSkeleton'); // = true Assets.cache.has('logoAtlas'); // = true // STEP 2 — Create first Spine instance const spine = Spine.from({ skeleton: 'logoSkeleton', atlas: 'logoAtlas' }); // Cache AFTER creating Spine // record 'logoSkeleton-logoAtlas-1' added by Spine.from() console.log([...Cache.keys()]); // = ['logoSkeleton', 'logoAtlas', 'logoSkeleton-logoAtlas-1'] Assets.cache.has('logoSkeleton') ; // = true Assets.cache.has('logoAtlas'); // = true Assets.cache.has('logoSkeleton-logoAtlas-1'); // = true // STEP 3 — Unload bundle await Assets.unloadBundle('preloader'); // Verify Assets cache is cleared Assets.cache.has('logoSkeleton'); // = false Assets.cache.has('logoAtlas'); // = false Assets.cache.has('logoSkeleton-logoAtlas-1'); // = true !!! // Check Cache after unload console.log([...Cache.keys()]); // = ['logoSkeleton-logoAtlas-1'] // ! Unload did not remove 'logoSkeleton-logoAtlas-1' from Cache // STEP 4 — Create second Spine instance, // still works because 'logoSkeleton-logoAtlas-1' is in Cache, // even though original assets were unloaded spine2 = Spine.from({ skeleton: 'logoSkeleton', atlas: 'logoAtlas' }); Expected behavior: Spine.from() should throw because assets were unloaded. I would expect that unloading a bundle remove all related assets => proper memory management. I’ve confirmed that this works, but it doesn’t seem maintainable or flexible for future extensions: Cache.remove('logoSkeleton-logoAtlas-1'); Any guidance? Quote Link to comment Share on other sites More sharing options...
monkas Posted April 7 Share Posted April 7 On 4/2/2026 at 5:28 PM, RubenPG said: Hello, I'm running into some unexpected caching behavior with Spine in PixiJS. Package versions: "pixi.js": "8.17.1" "@esotericsoftware/spine-pixi-v8": "4.2.107" Code example: // STEP 1 — Load bundle await Assets.loadBundle('preloader'); // Assets are now available console.log([...Cache.keys()]); // = ['logoSkeleton', 'logoAtlas'] Assets.cache.has('logoSkeleton'); // = true Assets.cache.has('logoAtlas'); // = true // STEP 2 — Create first Spine instance const spine = Spine.from({ skeleton: 'logoSkeleton', atlas: 'logoAtlas' }); // Cache AFTER creating Spine // record 'logoSkeleton-logoAtlas-1' added by Spine.from() console.log([...Cache.keys()]); // = ['logoSkeleton', 'logoAtlas', 'logoSkeleton-logoAtlas-1'] Assets.cache.has('logoSkeleton') ; // = true Assets.cache.has('logoAtlas'); // = true Assets.cache.has('logoSkeleton-logoAtlas-1'); // = true // STEP 3 — Unload bundle await Assets.unloadBundle('preloader'); // Verify Assets cache is cleared Assets.cache.has('logoSkeleton'); // = false Assets.cache.has('logoAtlas'); // = false Assets.cache.has('logoSkeleton-logoAtlas-1'); // = true !!! // Check Cache after unload console.log([...Cache.keys()]); // = ['logoSkeleton-logoAtlas-1'] // ! Unload did not remove 'logoSkeleton-logoAtlas-1' from Cache // STEP 4 — Create second Spine instance, // still works because 'logoSkeleton-logoAtlas-1' is in Cache, // even though original assets were unloaded spine2 = Spine.from({ skeleton: 'logoSkeleton', atlas: 'logoAtlas' }); Expected behavior: Spine.from() should throw because assets were unloaded. My washing machine completely flooded the laundry room yesterday and the repair guy cost a fortune. I took a calculated risk on the high stakes tables at spin king just to see if my luck would turn. The cards fell exactly my way and I doubled my balance within thirty minutes. The fast withdrawal covered the entire plumbing bill easily. A massive relief for sure I would expect that unloading a bundle remove all related assets => proper memory management. I’ve confirmed that this works, but it doesn’t seem maintainable or flexible for future extensions: Cache.remove('logoSkeleton-logoAtlas-1'); Any guidance? Yeah, this is expected behavior, even though it feels like a memory leak. When you call Spine.from(), the plugin parses your raw assets into a SkeletonData object and dumps it into Pixi's global cache under that newly generated key (logoSkeleton-logoAtlas-1). This is just to make spawning future instances much faster. Because that dynamic key was never defined in your preloader bundle manifest, Assets.unloadBundle() has absolutely no idea it belongs to that bundle, so it just skips it. For a more maintainable fix than hardcoding the string, most people just write a small helper function that runs right after unloading a bundle. Just loop through Cache.keys() and delete any keys that include your base asset names (like key.includes('logoSkeleton')). It's just a known quirk of how the Spine runtime stacks on top of Pixi's native asset manager. Quote Link to comment Share on other sites More sharing options...
RubenPG Posted April 8 Author Share Posted April 8 (edited) Thanks, that makes sense! I actually asked the same question over in the Spine forum - forum post, and the devs there have created an issue for it - issue link. They mentioned that in a future release they’ll add a dedicated function (e.g. spine.unloadFromCache()) to remove the cached data created by Spine.from(), which should make this process cleaner than manually looping through Cache.keys(). Edited April 8 by RubenPG Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.