michalvadak
For Spine GameObjects, it's always best to have all character images on a single texture atlas page whenever possible. This ensures the character can be rendered without breaking batching.
The addSlotObjects
method is merely a convenience function and should be avoided when possible. Typically, the Pixi object drawn using addSlotObjects
comes from a different texture, which breaks batching. If the slot is in the middle, rendering the character would now require three draw calls.
Spine atlases are primarily designed for Spine GameObjects, but nothing prevents you from reusing the character’s images for other purposes. However, individual character images are not recreated as Pixi sub-textures from the texture atlas PNG. Instead, meshes and UVs are used to achieve this.
If you want to reuse an image packed into an atlas page outside of a Spine GameObject, it’s your responsibility to create a Pixi sub-texture for it. You can use the atlas data to determine the image’s position and size within the respective texture atlas page.
I did a quick experiment with this—here’s the code:
// load the atlas and automatically the textures
const atlas = await PIXI.Assets.load("https://esotericsoftware.com/files/examples/latest/spineboy/export/spineboy-pma.atlas");
// util to get a new sprite, given an attachment name
const getSprite = attachmentName => {
// find the region with the given attachment name
const region = atlas.regions.find(element => element.name === attachmentName);
// get the respective page texture
const originalTexture = region.texture.texture;
// determine the position of the desired attachment, considering rotation
const frame = {
x: region.x,
y: region.y,
width: region.rotate === undefined ? region.width : region.height,
height: region.rotate === undefined ? region.height : region.width,
};
// creating the new sub texture
const texture = new PIXI.Texture({
source: originalTexture.baseTexture,
crop: new PIXI.Rectangle(frame.x, frame.y, frame.width, frame.height),
frame,
});
// creating a new sprite
return new PIXI.Sprite(texture);
}
const miniSpineBoy = new PIXI.Container();
const footR = getSprite("front-foot");
footR.x = 85;
footR.y = 135;
footR.scale.set(.70)
miniSpineBoy.addChild(footR);
const head = getSprite("head");
miniSpineBoy.addChild(head);
const eyeL = getSprite("eye-surprised");
eyeL.x = 45;
eyeL.y = 75;
eyeL.scale.set(.75)
miniSpineBoy.addChild(eyeL);
const eyeR = getSprite("eye-indifferent");
eyeR.x = 70;
eyeR.y = 80;
eyeR.scale.set(.75)
miniSpineBoy.addChild(eyeR);
const mouth = getSprite("mouth-oooo");
mouth.x = 50;
mouth.y = 120;
miniSpineBoy.addChild(mouth);
const footL = getSprite("front-foot");
footL.x = 25;
footL.y = 135;
footL.scale.set(.70)
miniSpineBoy.addChild(footL);
miniSpineBoy.x = window.innerWidth / 2 - miniSpineBoy.width / 2;
miniSpineBoy.y = window.innerHeight / 2 - miniSpineBoy.height / 2;;
app.stage.addChild(miniSpineBoy);
And here the result:

As you can see, I’m not even creating a Spine GameObject here, just loading the atlas. I haven’t considered any special cases related to how the texture packing is done, but for reusing a few images, this approach should work.