• Editor
  • Working on a C# runtime

Hey all,

I took a keen interest in this tool and decided to start implementing the C# run-time for Unity.

spine-csharp

I've got the core data serialization/animation generalized so any C# library can use it. I let the library specific implementations be handled by external "controllers" while the generic library only holds an interface for working with the controllers.

I have an example of Unity controllers that can draw/animate debug lines.

Right now I've got the transformation timelines implemented with stepped and linear curves. Bezier curves should be coming soon. I also still need to work on the Attachment and Color timelines.

Hope I'm not stepping on any toes by diving into this. Hope it helps, cheers!

Related Discussions
...
  • 編集済み

I think you're making Nate's life easier. 😉

Oh, this is cool! :clap: What license are you releasing the code under?

I'm glad you are staying similar to the libgdx (Java) runtime, but I would prefer if it were modeled exactly after it. I think it's important to keep the APIs identical, as it gives feature parity and makes it easier to document, debug, maintain, and implement new features.

You seem to be missing the BoneData, SlotData, SkeletonData, etc stuff. This is important, as it holds the setup pose information. This information can be reused for many Skeleton instances. Also the setup pose needs to be combined at runtime with the animation to allow for procedural effects.

It would all make more sense if it were documented, sorry about that. I've been in multi platform build/packaging/installer hell for 5 days now, but it looks like I'll be able to go back to working on the runtimes very soon.

The official C# runtime will need to match the libgdx, Corona, and C++ runtime APIs exactly. If you'd rather not do that, I may still be able to make use of a good deal of your work, if you are willing to release the code under the same license as the official runtimes (Simplified BSD License). :happy:

Oh, I get what the data classes are used for now. Instancing the same skeletons/animations multiple times. Shouldnt be too hard to refactor, just moving serialization out into those specified classes. I'll push to follow the libgdx runtime more exactly. I aimed to release under the same license as the current runtimes, no sense in duplicating the work.

I was mostly just trying to get the workflow into in Unity as a proof of concept for future projects. I felt my work would be useful to the community. The less runtimes you all have to write, the more you can work on improving the toolset.

Really great stuff ngomes82. Personally I'm not much of a coder, but I do know that with stuff like this we will be able to put extra focus on the tools. So thanks a bunch for sharing it.

Just a quick update - I added the Bone, Skeleton, and Slot data classes which are now used to initialize instances. I've got bones drawing and transforming in the proper hierarchy in Unity. Each bone is a unity game object that updates its own local transform using bone data. I plan on implementing the actual sprite drawing using Orthello and Texture Packer.

At the moment Unity handles updating the world transforms so I haven't implemented that code generically yet. I hope to get to it once I finish the sprite rendering.

Here's a quick screen cap of the current progress using Spineboy's walk:

HTTPS をサポートしていないため、画像は非表示になっています。 | まだ表示する

Cool stuff ngomes82! 8) I have a feeling that adding each bone as a game object won't perform well. Imagine 25 bones per character and 20 characters on screen on a mobile device. 🙂 It'd probably be better to do the calculations in the runtime and just use Unity to draw. Probably you have one game object per skeleton that represents the skeleton's root bone 0,0. Maybe using game objects would make sense for some Unity usage, I don't know, I have little Unity experience (so far!). 🙂

That makes sense since I believe Unity uses some sort of reflection for their Update calls. So having that many game objects/reflective calls might incur quite a bit of CPU overhead. I was planning on using Unity's colliders attached to the bones for collisions which is why I used game objects.

I'll have do some profiling to see what the performance looks like with rendering. But it will definitely perform better by handling the animation logic under one object's update call.

Here is a near exact port to C#.

https://www.dropbox.com/s/o8w9rwvl025hpf0/Spine.rar?m

Only a few things still need fixed/finished -

  • Binary files are not read correctly yet, I need to find out exactly how java writes stuff to disk.

  • I am using XNA for rendering so I used XNA's Color class instead of writing a simple class for it.

  • Json still needs more testing. The way the Json is parsed is pretty complex and silly looking in code. I don't like it at all and it needs to be fixed in both the Java and C# version IMHO.

  • Attachments are mostly ported, but not tested at all. I.E. no textures render yet. I feel like a true vanilla C# library should simply require the user to implement a few simple interfaces to enable texture rendering. So I feel like this needs rethought out and fixed.

Both tests from the LibGDX runtime are ported. To switch between them comment/uncomment the define in Program.cs. This switches between Spine Test and Mix Test.

Please take a look at this code and use it for your port, at least as a good base. I really tried to keep it as close as possible to the java source in git.
Please remember it is not 100% finished as I wanted a vanilla library and don't feel like that's really possible porting from the java version without guidance from the lead dev's (Nathan).
I am more then willing to continue work on this with that guidance...however I feel like the way the code is written in java once ported to C# results in poorly written C# code. With guidance I could make the C# vanilla library much better and more in line with C#'s style.

Sorry for ranting, I just want to help.

iAlwaysLoseThis, that souinds great, thanks! Will have a look tomorrow (4:30am here :sleepy: ).

I've done a little more work on a few things and will upload the new code tonight.

Some more stuff that needs fixed...

  • Currently the Json loader is not written very robustly for C# as it is a pretty direct port to C#. Checks for each key must be added.

  • Still need to write a TextureAtlas loader...but I'm working on that now.

Hey iAlwaysLoseThis,

It looks like you followed the libgdx runtime almost exactly. That's definitely more desirable than the work I did initially. Right now my focus is more on the Unity side of the C# runtime, where as you look like you're focusing on XNA. Perhaps it would be good if we combined our efforts. I could merge over your core code into the repository and add you as a dev if you'd like. That way we can work in parallel :rock:.

Also just an update on the unity side. It looks like I won't be using a game object per bone after all! There was an issue in Orthello were Sprites set the Game Object's scale to the pixel dimensions of the sprite....made some very interesting relative scaling artifacts haha. I switched the debug drawing to use world transforms as calculated by Spine.

Hey ngomes82,

Sorry for the slow response, there has been a stomach bug going around my house :puke:

It would be fine for you to copy my code into your repository, I really only did that initial port for Nate's benefit though. I have fixed up a few other parts of the code in my custom XNA version.

I really don't want to do to much work on the direct port until Nate gets time to look at it and at least decide what direction he wants to take it.

My XNA version might get hosted on Codeplex once it's done.

Yea I realized that any work I did on the port would make the cross-runtime management a little difficult. I've started to undo most of the custom stuff because of that. I thought it'd be useful for bug tracking, updating and integrating with the official run-times if most of the C# stuff was centralized.

Also here's an Update on my work in Unity:

I've got basic non-sequential attachments resolving!

HTTPS をサポートしていないため、画像は非表示になっています。 | まだ表示する

I did run into an issue in Orthello after a quick first pass. It appears that individual sprites in Orthello need to be attached to individual game objects. I had to flatten the Game Object hierarchy as well because of the relative scaling issue I was running into. There's probably a workaround but i'm going to focus on profiling the performance hit first.

I suspect this may be the case with other Unity 2D plugins.

Eagerly watching your work here ngomes, will start drafting off of you 🙂

Finished the Attachment Timeline work. So now you can swap out attachment images as seen in the dragon example.

I've done a bit of research into what it would take to have only one GameObject rendering all of the bones and it seems a little more complex. You would have one GameObject with the following: a mesh renderer, multiple meshes created for each sprite, and a material with the sprite atlas. You would then have to set each meshes' Texture UV co-ordinates and Position vertices. This would probably have to be done before a draw call inside of PreRender() using Graphics.DrawMesh(). I think this might??? still have the downside of multiple draw calls but it will eliminate the overhead of GameObjects.

I believe using this method would be plugin independent. Here are some links I used as references:

-Third Helix - Making 2D Games with Unity
-Unity Script Execution Order
-Unity Draw Mesh Reference
-Unity 2D Performance

Awesome, thanks for the research! 🙂 Can't wait to move on to work on Unity!

12日 後

Hey all just a quick update on the status of my work. I've been a little too busy to profile on an ios device/research more efficient rendering methods. I might be able to do that this week.

Here is a screencap of the AttachmentTimeline in action.

HTTPS をサポートしていないため、画像は非表示になっています。 | まだ表示する

Thanks a TON for laying the ground work here ngomes, and for having the foresight to factor the code in a way where other runtimes could plugin (seriously awesome).

I went ahead and rolled some prelim support for 2D Toolkit today. Available in this gist here:

https://gist.github.com/jmcguirk/5218443

Running here (actual runtime is a lot smoother, jing FPS capture sucks):

http://screencast.com/t/SBFEZL837q3S

This is a single spine exported rig with two skins - the assets for each are sourced from separate tk2d texture atlases.

I made a few tiny modifications to the base controller to allow for changing anims and setting a default anim. Also had to modify tk2d slightly to get rig scaling and direction to work properly (arguably something that should be in tk2d to begin with).

One thing I noticed - and this is likely true of Orthello (and perhaps any unity development) is the draw calls spike immensely when the skeletons are drawn on the same Z layer. This is because individual bones begin Z-fighting and batching is broken, causing a draw call per bone instead of a draw call per utilized texture atlas. Make sure to give your skeletons enough Z breathing room or your draw calls will get hosed.