- Bearbeitet
XNA/MonoGame Runtime - Animation Frame Setting/JSon Parsing
Hey guys!
My name's Daniel and I'm a developer with FrostTree Games. We're making an action game in XNA and Spine for the Xbox 360, and we'll be publishing on Xbox Live Indie Games likely at the end of the summer! Spine has been a great framework to use, as it's empowered our artists to do some really sweet animations and deploy them rapidly to our game's build.
We're hitting a bit of a snag though. We're having difficulties placing multiple Spine animations of the same skeleton/atlas simultaneously. Originally, we were loading just one Skeleton and having instances of the same game object share a reference to it. This became difficult, as animations needed to individually modify the skeleton and messed with each other's appearance during rendering. To alleviate this, we loaded individual skeletons from JSon for each game object. This was great when testing on the PC, but parsing the JSon on the Xbox 360 caused for very long "load times". As far as we know, C# lacks deep copy functionality, so we can't simply load one JSon and distribute copies to the game objects.
Would you guys have any insights into getting around this? We were thinking of skipping the JSon parser altogether and shipping with serialized binaries of the Skeleton class. We'd appreciate anything!
// the following code is found in an individual game object (C#/MonoGame)
// logic method...
{
animation_time += currentTime.ElapsedGameTime.Milliseconds / 1000f;
current_animation.Apply(current_skeleton, animation_time, true);
}
// draw method...
{
current_skeleton.RootBone.X = Position.X;
current_skeleton.RootBone.Y = Position.Y;
current_skeleton.UpdateWorldTransform();
renderer.Draw(current_skeleton);
}
I think Nate's still out. But unofficially speaking:
I think a Clone method just needs to be implemented in the Skeleton class.
You can imagine that deep copying behavior can't be implemented automatically for many kinds of data structures. The Skeleton object model just happens to be one of those things.
The Skeleton class's stateful members (and their elements) hold several references to each other which makes deep-copying a very specific task (but maybe not a difficult one).
Just as an example of where this is true (not exhaustive, I don't know all there is to know about Spine-C#):
The Bone objects in the Bones List is actually also in a tree ADT: each bone holds a reference to its parent.
Slots hold references to the bones they belong to.
The DrawOrder List has the same elements in the Slots List.
Slots and Bones each have Data fields which are references to kinda-stateless data loaded from the JSON. Making deep copies of these are an ambiguous matter. These mostly define the setup pose which all animations are based on. Whether that's something you want shared over all instances or something each instance of Skeleton can manage by itself depends on your use.
Additionally, I'm not sure how a Clone() function might change when animated draw order will eventually get implemented.
Assuming you use your own class to hold a Spine.AnimationState (which takes care of keeping time and a Spine.Animation reference or two) and an instance of a Spine.Skeleton, I don't think anything else would need to be deep-copied.
First, why do you need to load the JSON multiple times? If you are not doing procedural animation which requires you to programmatically modify the setup pose, then you should be able to reuse the SkeletonData for multiple Skeleton instances. An animation only modifies the bones in the Skeleton, it doesn't touch the BoneData, SlotData, Animations, etc in the SkeletonData. The SkeletonData is intended to be used this way, to avoid having the load all the data more than once.
One option would be to use the binary format instead of JSON. This is implemented only for spine-libgdx, it needs to be ported to spine-csharp and the other runtimes.
Otherwise we can do as Pharan suggest, SkeletonData can know how to copy itself.