Hi all, i decided to make this tutorial, as i didn't find any clear and straight forward information on this topic online and i spent a few days until i got the result i wanted. In the hopes of inspiring others and making a better society and better games, i want to share my findings with you guys.
Please note that this is a series of ideas and info I found on various forums and posts and i put together myself. If you have a better way of doing this, please, by all means, do add a comment or if you are an admin, edit this post with the updated solution.
Before starting the tutorial, let me tell you what I found and why was it so had for me and maybe we can learn something from this and we can do better in the future. I started from the idea that I want to have my equipment (weapons in my case) in a different atlas than my character as i didn't want to have a spritesheet very large, in order to optimize the loading times.
As i was searching the forums and google, I found the following example:
http://en.esotericsoftware.com/spine-loading-skeleton-data
TextureLoader textureLoader = ...
Atlas atlas = new Atlas("myAtlas.atlas", textureLoader);
What is "..." in textureLoader? I mean, if you are going to do an example/tutorial you might as well do a correct one by writing the full code snippet as you are already taking the time to write that tutorial, what's 3 - > 10 more lines of code going to cost you? As for a noob as myself, that is quite new to the Spine I spent quite a lot of time and effort on trying to find what that textureLoader is.
Another example that led me to my final solution was found in a post:
Attachment newAttachment = unitySprite.ToRegionAttachment(sourceMaterial);
But even this wasn't a complete solution as it was only giving you the way to create an attachment and not the way to actually attach it to the skeleton, and i still had a lot of questions about how to choose the weapon i want or how to pivot it.
The bottom line is, if you are going to provide an answer to a problem or a help request, take the time to provide the complete solution as it helps quite a lot other people the stumble upon your post and it saves a lot of time and effort of trying to find the rest of the code online.
Anyway let's get back to the tutorial
Spine:
- Using any tool for your choosing, make the items you would like to include in the atlas in .png format and place them in a folder. For my example, I wanted to create a weapon set that i can swap through and attach to a specific slot defined on my character. I created a folder called "Weapons" and placed my two weapons inside it. ("axe.png" and "spikebat.png").
-The name of the folder will be important later so call it something intuitive and easy to organize. Also please note that if you want to create an inventory list that contains more items (not just weapons) you can easily do that by creating the main folder (let's call it "Inventory") and inside it you can create subfolders where you can store your items (for example "Weapons", "Shields", "Armor", etc). This way you will create only one bigger spritesheet with all you items in one place. Or you can just create multiple, smaller sprite sheets for each set of items. It's up to you.
- In Spine go to Spine menu -> Texture Packer or press "Ctrl + P " to open Texture Packer Menu
- From there, under Input folder, select the folder you have created earlier, in my case that would be Weapons.
- Select the output folder you want to export the atlas and spritesheet to. For this tutorial i chose to export them in the same folder but you can select any other folder you want.
- Set the atlas name to whatever you want. This is not that important, therefor you can name it anything. Just make sure you find it later :lol:
- Hit Pack and that's it for Spine part
Unity
- Drag the two newly generated files (weapons.atlas.txt and weapons.png) in a folder of your choosing inside Unity.
Unity will create 2 additional files for you (One atlas.asset and one material)
Let's create our script that can handle the change of the items we want. I called it skeletalAnimator:
public class SkeletalAnimator : MonoBehaviour
{
// you can just assign an empty sprite, it doesn't matter, as this will be ovewritten by the code below.
public Sprite axe;
public Material axeMaterial;
[SpineSlot]
public string weaponSlot;
public SpineAtlasAsset equipmentAtlas;
public bool overrideAnimation = true;
void Start()
{
if (skeletonAnimation == null)
Debug.LogError("You forgot to set the Skeleton Animation !");
if (skeletonAnimation != null)
{
skeletonAnimation.UpdateComplete -= AnimationOverrideSpriteAttach;
skeletonAnimation.UpdateComplete += AnimationOverrideSpriteAttach;
}
UpdateWeapon();
}
public void UpdateWeapon()
{
// Remember the weapons folder from ealier? This is where you will set the path if you have a larger inventory and you want to select what item you want to attack to your character.
string path = "Weapons/spikebat";
AtlasRegion region = equipmentAtlas.GetAtlas().FindRegion(path);
Attachment newAttachment = axe.ToRegionAttachment(axeMaterial);
newAttachment.SetRegion(region);
skeletonAnimation.skeleton.FindSlot("sword").Attachment = newAttachment;
}
void AnimationOverrideSpriteAttach(ISkeletonAnimation animated)
{
if (overrideAnimation && isActiveAndEnabled)
UpdateWeapon();
}
private void OnDestroy()
{
if (skeletonAnimation != null)
skeletonAnimation.UpdateComplete -= AnimationOverrideSpriteAttach;
}
}
The final piece of the puzzle. How do you set the pivot point ?
Yes, we managed to attach new items to our players but they might be offset from our slot position so we need to move the sprite to the correct position.
The solution I found was to enter playmode with the textures as they were, and while in playmode, I edited the Weapons.atlas.txt file, by changing
to the correct position, and hitting ctrl + r to refresh the changes.
This gave the a quick way to visualize how much I needed to offset them.
What I recommend is, wait until you have the final set of items as if you need to re-export them you will lose the changes made to your offset items.
I hope this helps you and saves you for a few hours / days of googling and searching the internet and again, if you have a better solution of doing these things, please share it with everybody as it helps the community.
Let's all do better and create better tutorials / solutions for our problems/ challenges.
I wish you all the best.
Eli