To eliminate the blank time when swapping skeletons, you should pre-load the next level's assets before switching, rather than creating a new SpinePlayer instance on demand. Here are a few approaches:
Best Approach: Pre-load and Swap Skeleton Data
Instead of creating a new SpinePlayer instance each time, create it once and then swap out the skeleton data:
// Initialize player once
const player = new spine.SpinePlayer("player-container", {
skeleton: "/assets/level1/skeleton.json",
atlas: "/assets/level1/skeleton.atlas",
// ... other config
});
// Pre-load next level's assets
const assetManager = new spine.AssetManager("/assets/level2/");
assetManager.loadText("skeleton.json");
assetManager.loadTextureAtlas("skeleton.atlas");
assetManager.loadAll(() => {
// When ready to switch levels
const atlas = assetManager.require("skeleton.atlas");
const atlasLoader = new spine.AtlasAttachmentLoader(atlas);
const skeletonJson = new spine.SkeletonJson(atlasLoader);
const skeletonData = skeletonJson.readSkeletonData(assetManager.require("skeleton.json"));
// Swap the skeleton
player.skeleton = new spine.Skeleton(skeletonData);
player.state = new spine.AnimationState(new spine.AnimationStateData(skeletonData));
player.skeleton.setToSetupPose();
});
Alternative: Hidden Pre-loading
Create the next level's SpinePlayer in a hidden div while the current level is playing:
// Current level playing
const currentPlayer = new spine.SpinePlayer("player-container", {
skeleton: "/assets/level1/skeleton.json",
atlas: "/assets/level1/skeleton.atlas",
});
// Pre-load next level in hidden container
const hiddenContainer = document.createElement('div');
hiddenContainer.style.display = 'none';
document.body.appendChild(hiddenContainer);
const nextPlayer = new spine.SpinePlayer(hiddenContainer, {
skeleton: "/assets/level2/skeleton.json",
atlas: "/assets/level2/skeleton.atlas",
});
// When switching levels
currentPlayer.dispose();
document.getElementById("player-container").appendChild(nextPlayer.canvas);
hiddenContainer.remove();
Pre-load During Current Level
Start loading the next level's assets while the player is still playing the current level. Use the player's success callback to know when assets are ready:
let nextLevelReady = false;
// Start pre-loading next level
const preloadPlayer = new spine.SpinePlayer(hiddenDiv, {
skeleton: "/assets/level2/skeleton.json",
atlas: "/assets/level2/skeleton.atlas",
success: () => {
nextLevelReady = true;
}
});
// When level changes and assets are ready
if (nextLevelReady) {
currentPlayer.dispose();
// Instantly show pre-loaded player
}
The key is to load assets before you need them so the swap is instantaneous. This eliminates the blank loading time by ensuring the next skeleton is ready to display immediately.