Pharan

@glogic
You want to subscribe to yourSkeletonAnimation.state.Complete

If you don't know how C# delegates work and to subscribe in C#, look it up.
It basically looks like this:
yourSkeletonAnimation.state.Complete += YourHandleCompleteMethod;
It will pass parameters and stuff to your method that you'll find useful.

For more info on the difference between Complete and End, see the information linked below (eh?? Unity inside joke):
viewtopic.php?f=8&t=4050
User avatar
Pharan

Pharan
Posts: 4542

glogic

Thanks @clandestine and @Pharan

These are both the answers I was looking for. I now have it both working with mecanim and using the spine delegates :) Now I just need to decide which way I want to go with for future work.

Thanks for quick replies
glogic
Posts: 6

Mitch

It's worth mentioning that the SpineAnimation way with delegates is more predictable as there can be weird things that happen with keys during mecanim blending.
User avatar
Mitch

Mitch
Posts: 966

clandestine

Mitch wrote:It's worth mentioning that the SpineAnimation way with delegates is more predictable as there can be weird things that happen with keys during mecanim blending.
What kind of weird things? Strange blending of some kind, or inconsistent clarity on the "end" of an animation state?
User avatar
clandestine
Posts: 48

ChestnutGames

[EDIT]
Nevermind I figured it out myself following this Unity forum thread -> http://forum.unity3d.com/threads/drawing-order-of-meshes-and-sprites.212006/

However if you have a better/simpler idea please let me know :)

---------------------------------------------------------

Hello Mitch,
my name's Marco and I'm the founder and main programmer at Chestnut Games. :)
We are planning to buy Spine since it's an amazing piece of software and seems a great fit for our latest project, but we have one main concern regarding Spine and Unity 2D integration.

- How does Spine deal with Unity 2D sprites and sprite packer? While the sprite packer is not a must (even though it would be super great to have it work to keep our workflow consistent), our new game 2D engine heavily relies on sprite layers and orders.
We basically have a 2D/fake 3D environment and we change the sprites sorting order at runtime to make dynamic 2D objects to move back and forward other 2D sprites. Is this something we can easily achieve with Spine animated characters? I don't care about changing the internal hierarchy of the character itself, but it's very important that we can kinda set a general sorting order for the whole skeleton, so it can go behind a in front of other game objects as it moves in the world (it's a 2D world, so just X/Y without Z dimension). Hope I was clear. :)
Thanks and keep up the great work!
ChestnutGames
Posts: 1

whaison

Do'not work Spine on Unity5 (5.0.0f4)
https://unity3d.com/jp/get-unity/download?ref=personal
http://netstorage.unity3d.com/unity/5b98b70ebeb9/UnityDownloadAssistant.dmg
I try this url
http://esotericsoftware.com/files/runtimes/unity/spine-unity.unitypackage
and
https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip




import to
Spine Trial/examples/hero/export
renamed this files.
hero-mesh.atlas-->hero_atlas.txt
hero-mesh.json-->hero-mesh_json.txt
hero-mesh.png
hero.atlas-->hero_atlas.txt
hero.json-->hero_json.txt
hero.png

but

Do'not work Spine on Unity5 (5.0.0f4)

and I try this forum

http://ja.esotericsoftware.com/forum/search.php?keywords=Unity5
http://ja.esotericsoftware.com/forum/viewtopic.php?f=7&t=3713


but i can’t.

please help me.
whaison
Posts: 2

Mitch

hero.atlas.txt
hero-mesh.json
User avatar
Mitch

Mitch
Posts: 966

MarkB

Hi Mitch,
I'm running Unity 5.0.0b18 and Spine 2.1.25 but when I import the runtimes from here http://esotericsoftware.com/files/runtimes/unity/spine-unity.unitypackage I get a whole bunch of errors when I try to run one of the example scenes

Any ideas what I might be doing wrong please?

Thanks,
Mark
MarkB
Posts: 3

acorrow

Is there any way to REMOVE an attachment in code? I prob missed something in the videos, but just curious if anyone knows off hand. Thanks!
acorrow
Posts: 3

Mitch

MarkB wrote:Hi Mitch,
I'm running Unity 5.0.0b18 and Spine 2.1.25 but when I import the runtimes from here http://esotericsoftware.com/files/runti ... itypackage I get a whole bunch of errors when I try to run one of the example scenes

Any ideas what I might be doing wrong please?

Thanks,
Mark
Looks like they changed how they did script updates... latest github repo (not hte unity package) shouldn't need to be API-updated for Unity 5. try doing a clean pull. I'll try and address this with a few other Unity 5 issues sometime today.
User avatar
Mitch

Mitch
Posts: 966

Kevin Keyser

Hey Mitch,

Just wanted to say thanks for the tutorials. I just made a switch to unity from monogame and your tutorials and implementations are making my life so much easier.

Kevin
Kevin Keyser
Posts: 16

Javier13om

Hi, is there still a bug in the latest version of Spine? Because when I export my project it doesn't make a prefab or anything automatically which I really wouldn't mind but after setting everything up my character has white boxes around it and the art is a faint black on the inside, I tried playing with texture setting and atlas export setting but nothings worked so far...
Javier13om
Posts: 1

glogic

Hi, I am having some difficulty with Spine and Unity when using slots. I followed your video and was able to attach weapons to a slot no problem. When I run it within Unity everything is great I can see the weapons correctly attached to the slot I provided. Then when I create a build for other people to try out the weapons are missing. They seem to appear for 1 frame when I add them but then disappear immediately. This happens for both windows and mac builds.

Here is an example of code I am using for adding to the slot

skeletonAnimation.state.SetAnimation(0,"Idle",false);
skeletonRenderer.skeleton.AttachUnitySprite("blank_weapon",weaponSprite) ;

so I am attaching the weapon right after starting the idle animation.
Works fine when run in Unity :(
Any ideas what I am missing here? I just seen in an above post that I should use the scripts in the repo and not the spine package provided. Is this still the case? Ill try this when I get home from work. If anyone has any other ideas about what could be the issue here I am all ears!
Thanks
G

Edit: Ok I tried using the repo instead of the package but the issues remain when I make a build. I am using unity 5 if that matters?
glogic
Posts: 6

Mitch

Works fine for me.

Do you have any Attachment Keys in your animation for Idle that are effecting the blank_weapon slot?
Are you calling "SetToSetupPose" or assigning a skin anywhere?

PS:
Generally the unity package is kept up to date with the repo, but it might take a day or so before I get around to repacking it.
User avatar
Mitch

Mitch
Posts: 966

glogic

Hi Mitch,
Yes I am calling SetToSetupPose at the start of all animations like this

void StartAnimation(Spine.AnimationState currentState, int i){
skeletonAnimation.skeleton.SetToSetupPose ();
}

I have tried removing this and also just calling it before the idle animation is called.

I will have to talk to the artist about the attachment keys and see if there is anything effecting the slot. Is there a reason why this would work when run from Unity IDE but not from a build?

I also updated to Unity 5.0.1 in the last 30 mins to see if that helped but no joy.
glogic
Posts: 6

Mitch

Can you send me your exported Spine data? Preferably everything included, but I only really need the .json and the .atlas.txt if something is super secret.
(PM me a private link or some such)

---

Received.

Still works fine on my end. Sending you a packaged project (import into a blank Unity 5 project)
User avatar
Mitch

Mitch
Posts: 966

glogic

Just want to say for the record that Mitch is a legend and was able to fix the issue even with a face full of burrito!
Just in case anyone comes across this same issue I had to set the sprite material of the weapon to match the sprite that contained the weapon slot. I was using Spine/Skeleton lit

skeletonRenderer.skeleton.AttachUnitySprite("blank_weapon",.weaponSprite,"Spine/Skeleton Lit") ;

thanks again
G
glogic
Posts: 6

Aggressor

Could you explain what you are doing in this code?
Texture2D tex = sprite.texture;
int instanceId = tex.GetInstanceID();
AtlasRegion atlasRegion;

//check cache first
if (atlasTable.ContainsKey(instanceId)) {
atlasRegion = atlasTable[instanceId];
} else {
//Setup new material
Material mat = new Material(shader);
if (sprite.packed)
mat.name = "Unity Packed Sprite Material";
else
mat.name = sprite.name + " Sprite Material";
mat.mainTexture = tex;

//create faux-region to play nice with SkeletonRenderer
atlasRegion = new AtlasRegion();
AtlasPage page = new AtlasPage();
page.rendererObject = mat;
atlasRegion.page = page;

//cache it
atlasTable[instanceId] = atlasRegion;
}

Rect texRect = sprite.textureRect;

//normalize rect to UV space of packed atlas
texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);
Aggressor
Posts: 45

Mitch

No.










j/k

It creates an easy way to interface the Unity Sprite-packing system with the RendererObject system of the Spine SkeletonRenderer. It also caches a particular sprite/attachment in case it has already been converted. Unity Packed Sprite Altases must also be Pre-multiplied at runtime, so i some code near where you pasted that from does that as well and caches the instance id of the texture to a static lookup table to prevent premultiplying a texture twice.
User avatar
Mitch

Mitch
Posts: 966

Aggressor

Hehe

Im trying to re-write this script so it can equip 4 slots (helmet, armor, weapons). Right now its working if I do 1 attacher script per unit, but I want to change it so I can have 1 attacher script that handles all 4 equipment slots.

One part of your code I still dont get is this:

//normalize rect to UV space of packed atlas
texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);

Why do you have to InverseLerp this? Whats going on here? :)

(Also whats pre-multiplying a texture?)
Aggressor
Posts: 45

Pharan

UVs are expressed as values 0 to 1. InverseLerp converts the part/total (x/width or y/height) ratio into the appropriate number.
Though it could have just as well been that simple division since the first parameter of InverseLerp is 0.
Except InverseLerp clamps? And handles negatives? I'm not actually sure what other contribution it has.

Check the links provided here to see what Premultiply Alpha means: Premultiply Alpha
tl;dr. You need to pre-process the pixels so it shows up correctly with the Spine/Skeleton shader (which is a premultiply-alpha shader).
User avatar
Pharan

Pharan
Posts: 4542

Aggressor

Ahh Ok I will read up on that thanks.
//create faux-region to play nice with SkeletonRenderer
atlasRegion = new AtlasRegion();
AtlasPage page = new AtlasPage();
page.rendererObject = mat;
atlasRegion.page = page;

//cache it
atlasTable[instanceId] = atlasRegion;
Does this keep creating an Atlas page for EACH sprite?

If so can I take an existing Atlas page and see if there's room and then add the sprite to that? Or am I not understanding how this is working ? :)
Aggressor
Posts: 45

Pharan

Those objects (AtlasRegion and AtlasPage) are just dummy objects here. They don't actually create extra textures that hold the sprite.
User avatar
Pharan

Pharan
Posts: 4542

Aggressor

Ok Im going to give this a good 4 hours tonight and get back to you with my progress. I'd be happy to share my multi-item adder if I get it working :)

---

Ok I've made some good progress. I successfully have it adding and item of the correct sprite to the correct spot. Its working via the inspector so this should help people if they want it. I am going to tweak it to work via code too.

Question:
You guys have a really awesome [SpineSlot] serializable thingy. Can I do this for sprites too and get a list of all my sprite objects?

Sometimes it is, sometimes its not. For example, here is one of my characters with the weapons and armor working fine, but the helmet is the wrong direction. The sprite is rendered upright, but its being rendered at 90*.

I've pasted my code below but I have a 2 issues:
1. My sprite packer is always empty (even if I set packing tags and click pack). I have Unity 5 pro.
2. The sprite.packed value is false.


Is there a way I can set the rotation of the sprite in the below code? Where is this rotation data actually parsed and used and how can I catch issues like that in my code.

Here is my code for multi-slot attachment
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Spine;

public class ItemAttacher : MonoBehaviour {


public bool attachOnStart = true;
public bool keepLoaderInMemory = true;

public SlotAttachment[] slotAttachments;

[System.Serializable]
public class SlotAttachment
{
[SpineSlot]
public string slot;
public Sprite sprite;
}

private ItemAttachmentLoader loader;
private RegionAttachment attachment;

void Start () {
if (attachOnStart)
Attach();
}

public void Attach () {
var skeletonRenderer = GetComponent<SkeletonRenderer>();

foreach(SlotAttachment slotAttachment in slotAttachments)
{
//create loader instance, tell it what sprite and shader to use
loader = new ItemAttachmentLoader(slotAttachment.sprite, Shader.Find("Sprites/Default"));

attachment = loader.NewRegionAttachment(null, slotAttachment.sprite.name, "");

skeletonRenderer.skeleton.FindSlot(slotAttachment.slot).Attachment = attachment;

if (!keepLoaderInMemory)
loader = null;
}
}
}

public class ItemAttachmentLoader : AttachmentLoader {

//TODO: Memory cleanup functions

//IMPORTANT: Make sure you clear this when you don't need it anymore. Goodluck.
public static Dictionary<int, AtlasRegion> atlasTable = new Dictionary<int, AtlasRegion>();

//Shouldn't need to clear this, should just prevent redoing premultiply alpha pass on packed atlases
public static List<int> premultipliedAtlasIds = new List<int>();

Sprite sprite;
Shader shader;

public ItemAttachmentLoader (Sprite sprite, Shader shader) {

if (sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
Debug.LogError("Tight Packer Policy not supported yet!");
return;
}

this.sprite = sprite;
this.shader = shader;

Texture2D tex = sprite.texture;
//premultiply texture if it hasn't been yet
int instanceId = tex.GetInstanceID();
if (!premultipliedAtlasIds.Contains(instanceId)) {
try {
var colors = tex.GetPixels();
Color c;
float a;
for (int i = 0; i < colors.Length; i++) {
c = colors[i];
a = c.a;
c.r *= a;
c.g *= a;
c.b *= a;
colors[i] = c;
}

tex.SetPixels(colors);
tex.Apply();

premultipliedAtlasIds.Add(instanceId);
} catch {
//texture is not readable! Can't pre-multiply it, you're on your own.
Debug.Log("Texture was not readable");
}
}
}

public RegionAttachment NewRegionAttachment (Skin skin, string name, string path)
{
RegionAttachment attachment = new RegionAttachment(name);

Texture2D tex = sprite.texture;
int instanceId = tex.GetInstanceID();
AtlasRegion atlasRegion;

//check cache first
if (atlasTable.ContainsKey(instanceId)) {
atlasRegion = atlasTable[instanceId];
} else {
//Setup new material
Material mat = new Material(shader);
if (sprite.packed)
mat.name = "Unity Packed Sprite Material";
else
mat.name = sprite.name + " Sprite Material";
mat.mainTexture = tex;

//create faux-region to play nice with SkeletonRenderer
atlasRegion = new AtlasRegion();
AtlasPage page = new AtlasPage();
page.rendererObject = mat;
atlasRegion.page = page;

//cache it
atlasTable[instanceId] = atlasRegion;
}

Rect texRect = sprite.textureRect;

//normalize rect to UV space of packed atlas
texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);

Bounds bounds = sprite.bounds;
Vector3 size = bounds.size;

//TODO: make sure this rotation thing actually works
bool rotated = false;
Debug.Log("Sprite is" + sprite.packed);
if (sprite.packed)
rotated = sprite.packingRotation == SpritePackingRotation.Any;

//do some math and assign UVs and sizes
attachment.SetUVs(texRect.xMin, texRect.yMax, texRect.xMax, texRect.yMin, rotated);
attachment.RendererObject = atlasRegion;
attachment.SetColor(Color.white);
attachment.ScaleX = 1;
attachment.ScaleY = 1;
attachment.RegionOffsetX = sprite.rect.width * (0.5f - Mathf.InverseLerp(bounds.min.x, bounds.max.x, 0)) / sprite.pixelsPerUnit;
attachment.RegionOffsetY = sprite.rect.height * (0.5f - Mathf.InverseLerp(bounds.min.y, bounds.max.y, 0)) / sprite.pixelsPerUnit;
attachment.Width = size.x;
attachment.Height = size.y;
attachment.RegionWidth = size.x;
attachment.RegionHeight = size.y;
attachment.RegionOriginalWidth = size.x;
attachment.RegionOriginalHeight = size.y;
attachment.UpdateOffset();

return attachment;
}

public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
//TODO: Unity 5 only
throw new System.NotImplementedException();
}

public SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, string name, string path) {
throw new System.NotImplementedException();
}

public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
throw new System.NotImplementedException();
}
}
Aggressor
Posts: 45

MarkB

Mitch wrote:Looks like they changed how they did script updates... latest github repo (not hte unity package) shouldn't need to be API-updated for Unity 5. try doing a clean pull. I'll try and address this with a few other Unity 5 issues sometime today.
Do you know if this is sorted now, please? Still doesn't seem to be working for me no matter how I try and run it.
MarkB
Posts: 3


Return to Unity
cron