Just following up... I have been working on my own integration between Spine and AC. It's definitely coming along.
I'm setting up a bunch of GameObjects as children of the "Sprite Child" of the Root Character GameObject. These GameObjects represent a different direction for the character, each with their own Spine SkeletonAnimation and Skeleton Mesh Renderer.
I'm not sure how generic it will be, as I'm just focusing on making it work for my particular game right now, but it will hopefully be a good starting point for others to work from.
Anyway, just letting you all know this is not dead, but I am quietly working on it in the background.
You don't need to structure your Player GameObject in that way, just do as I did (and how @Ressie told me): add the various animations to the same Spine GameObject, and then a script like this:
void FixedUpdate() { // I read the direction & speed parameters from an animator component if (anim.GetFloat("Speed") != 0) { int dir = anim.GetInteger("Direction"); // then, if speed > 0.1, I play a different animation according to the direction switch (dir) { case 3: SetAnim("walk_180_top"); break; case 0: SetAnim("walk_0_bottom"); break; case 1: SetAnim("walk_270_left"); break; case 2: SetAnim("walk_90_right"); break; case 4: SetAnim("walk_315_bottom_left"); break; case 5: SetAnim("walk_45_bottom_right"); break; case 6: SetAnim("walk_225_top_left"); break; case 7: SetAnim("walk_135_top_right"); break; } } else // if speed == 0, then I play some Idle animation. { anim.SetInteger("Direction", 4); SetAnim("idle_315_bottom_left"); } // While here I define the routine SetAnim void SetAnim(string name) { if (name == currentAnimation) return; // If I remove the next two lines, the character has wrong rotation values for its bones, missing parts, and also does not swap images in the proper frames. // If I keep the next two lines, the character does not have ANY transition between states at all, the animations are all super stiff skeletonanim.skeleton.SetToSetupPose(); skeletonanim.state.ClearTracks();
In this animated GIF there are some mixing and mirroring problem that I could solve in the end. The original posts on the Spine forums you can find here:
Quick question: does that mean you have all of your directions under the one skeleton root, basically like "sub-skeletons"? That's how I am understanding it as you are just changing animations and not skeletons. If so. in Spine, how easy is it to manage all animations for all directions under the one skeleton root? My animator tells me it's a pain in the tuchus.
My Spine project is setup to have multiple skeletons (5, each for a different direction - obviously flipping left, up-left, down-left). As such, there are 5 json files, 5+ atlases (going to have some shared), 5 SkeletonDataAssets etc. etc.
I have all animations under only one skeleton. You are right, I just switch animations, not the skeletons.
For me managing everything under one skeleton is quite simple: please see attached screenshot. I have an animation for each of the directions, which are defined by the degrees (from 0 to 360, every 45°).
I would consider this approach simpler and more efficient than having multiple skeletons. The only code I use for switching anims is what you see above in my previous post.
My only problem is that my character slides a bit when it reaches the position, as the "anti-glide" feature does not apply to Spine objects but only to plain sprites.
I'm going to have to disagree with you there on that approach being simpler and more efficient, based on what I have researched on the Esoteric Spine forums with regards to the mesh processing, as well as what I've experienced as increased complexity in the Spine editor.
I don't want to talk too deeply about Spine itself on these forums, and I am by no means a Spine Unity expert, but the fundamentals from what I understand are that there will be unnecessary processing if you have one skeleton with many different bones for different directions/angles, which will not be optimal. i.e. for each direction you are currently in, there will be a whole lot of unused bones that still need to be processed or something like that.
The other thing, and this is just my opinion working in Spine and certainly not gospel, but it is actually very confusing to have different directions in a single skeleton. You have to keep switching bones and slots on and off depending on the direction you want to be in. And you will end up with HEAPS of animations in that single skeleton.
Anyway, I have now created an alternative to the multiple GameObjects (for each skeleton/direction) under the Sprite Child and switching between them. I have done it so that there is a single Sprite Child with a SkeletonAnimation attached to it. The SkeletonDataAssets get replaced depending on the direction the character is facing and it is all working really well. I have even created a custom Character: Animate action for a custom Spine animation engine where it will enable the developer to type in custom animation names and they will play, loop or not, start the animation at a particular time etc. etc. I'll post something soon.
sorry for my late reply, have been busy lately. I see your point, and incidentally it is something that has been described by Spine-guru Pharan at this link just few days ago: here is the link.
I believe that the two approaches are equally good, depending on what you are most comfortable with. And please, if you have something to post, please do so: I am always curious to see approaches of fellow AC devs
I see you both seem to have found two different approaches to Spine integration with AdventureCreator, though I'm more interested in @ezsilman different skeletons solution, since it's more similar to what I've been creating.
The thing is, I have one Spine project for each direction and for each one of the characters, and I've achieved to create a working one-direction skeleton, with different animations and combining them through Unity Sprites Complex (mecanim instantiated skeletons), but I'm stuck at the multiple directions part since I'm no unity specialist.
From what I understood, I should change the skeletons based on the angle parameter (or direction) given by AC, but I'm really lost here. Is it possible for you to share the alternative you found in your previous post so we can learn the best approach? :P
Regarding each direction for each character in a different Spine project:
It is important to understand that Spine Unity doesn't know anything about a Spine project, per se. When you export out of a Spine project it exports each skeleton and its relevant files (.png, .atlas.txt, .json). How you organise your skeletons in your Spine projects is completely up to you and how you want to work, but what has been easy for me is to have each character in their own Spine file, with each of their directions as different skeletons in that respective Spine project.
i.e.
.spine project file: Character.spine
Inside that project, the skeletons: Left, Right, Up, Down, UpLeft, UpRight, DownLeft, DownRight
Next, regarding the crux of your question, you are correct in what you are saying regarding the angle/direction changing the skeleton. I ended up creating my own AnimationEngine script based on the Unity Sprites Complex script and have been meaning to upload it somewhere to the community, but I've still been tweaking it and have been a bit hesitant to upload it.
I'd be happy to send you the scripts, but I'll also explain here the fundamentals of what I did:
1. On the root object, I created a script that has an array of those 8 directions for the character, with variables for each SkeletonDataAsset in each "direction" array element, as well as some animation names for "idle", "walk", "run" etc.
2. On the child object (which I'll refer to as the 'sprite child' even though we're obviously not using sprites), I added the Spine SkeletonAnimation script.
3. In my custom AnimEngine script, I created a function called SetDirection where it firstly checks if the new direction is equal to the current direction, and if not then changes the skeleton animation to relevant SkeletonDataAsset stored in the "direction" array element for that direction, sets any standard animations it needs to set as well (i.e. walk, run, idle), and then sets the currentDirection to that current direction. Whenever the character moves, the SetDirection function is called.
That's the essence of it, with obviously a bunch of little bits and pieces that makes it all work properly, such as custom actions for "Play Animation", "Face Direction", "Change Material Colour" etc. etc.
If you've got Skype I'd be happy to share files etc. with you. I don't know the rules of uploading files to AC forums.
Regarding Spine Mecanim, this was something I tried using early on and it was absolutely painful. There are loads of errors in the Spine Mecanim system. Maybe things have improved in the Esoteric updates, but at the time it was a disaster. Generally speaking, the direct API for Spine Unity is the best way to go, and that's what I've been using in my custom scripts. I'm not using Unity Sprites Complex, I'm using a custom animation engine script that I based off the Unity Sprites Complex script just to get the fundamentals right.
Let me know what you think of this very EARLY DRAFT version of the integration tutorial on Wikia.
I was working on a custom script too, but also tried to work with Sprites Complex script since it already had a Direction controller, only had to switch skeletons etc.. but i didn't go further either.
As for your implementation, I believe we're using different Unity runtimes or something? I don't have any CharSpine.as.
Have there been any more updates/advances to the AC/spline integration? I tried following the wiki posted above, but it was outdated (tried to fix the scripts myself, but there are like 12 scripts, and I could not completely understand how they all work in order to fix the issues) -
And also, a question to all the people that have migrated their 2D project from sprites to bones animation: Have you been able to make it work to a near flawless degree? Is it worth the effort? Of course this question is all in the AC context.
The reason we are thinking of switching to bone based animation is due to program size considerations, and the fact that bone based animation can ahieve really smooth transitions and animations.
No, this is not up-to-date. Esoteric have released new versions of Spine2D that have made old API code redundant. I haven't yet updated any of my Spine projects to the new versions for the reason that it would break everything. I'll try and have a look at it as I'm sure people love to use the new features that the new versions offer.
Hi !, i have been working with AC for a while , but now i need to change my animations to spine , i would like to know if someone have wrote a new script to make it work , thanks!
Comments
// I read the direction & speed parameters from an animator component
if (anim.GetFloat("Speed") != 0) {
int dir = anim.GetInteger("Direction");
// then, if speed > 0.1, I play a different animation according to the direction
switch (dir)
{
case 3:
SetAnim("walk_180_top");
break;
case 0:
SetAnim("walk_0_bottom");
break;
case 1:
SetAnim("walk_270_left");
break;
case 2:
SetAnim("walk_90_right");
break;
case 4:
SetAnim("walk_315_bottom_left");
break;
case 5:
SetAnim("walk_45_bottom_right");
break;
case 6:
SetAnim("walk_225_top_left");
break;
case 7:
SetAnim("walk_135_top_right");
break;
}
}
else
// if speed == 0, then I play some Idle animation.
{
anim.SetInteger("Direction", 4);
SetAnim("idle_315_bottom_left");
}
// While here I define the routine SetAnim
void SetAnim(string name) {
if (name == currentAnimation)
return;
// If I remove the next two lines, the character has wrong rotation values for its bones, missing parts, and also does not swap images in the proper frames.
// If I keep the next two lines, the character does not have ANY transition between states at all, the animations are all super stiff
skeletonanim.skeleton.SetToSetupPose();
skeletonanim.state.ClearTracks();
if (name == "idle_315_bottom_left") {
skeletonanim.state.SetAnimation(0,"idle_315_bottom_left", true);
return;
};
skeletonanim.state.SetAnimation(0, name, true);
currentAnimation = name;
}