2D Player Characters in 3D World using Spine Animations

Hello!

I’m in the very early phases on working on a new game project which uses 2D characters and a 3D world using a fixed isometric camera. Think Final Fantasy Tactics.

I’m new to MonoGame and am currently just moving through a series of proof of concept tests to make sure I have all the tech needed to do everything the design calls for. So far I’ve been able to figure out most of the issues I’ve come across, but I haven’t been able to find a complete answer on how I want to achieve our desired look.

In a nutshell, I’m wondering what the best way to get 2D Characters drawn in my 3D environment while still supporting a few requirements:

  1. We’re planning on using Spine for our animation.
  2. We’'re going to need to support lighting that affects both our 2D characters and 3D environment. I’m currently planning on doing something as described here: http://www.gamasutra.com/blogs/OliverFranzke/20140828/224326/Dynamic_2D_Character_Lighting.php though I don’t think it should affect this particular discussion much.
  3. The 2D characters need to be able to properly depth test against the 3D world.

My idea right now is just using billboarded quads to achieve my effect. Lighting would be done with custom shaders, and the depth testing would just work since they’re actually 3D objects. However I have one major concern with this approach: whether it plays nicely with Spine.

While I have not delved too deeply into Spine as of yet, it does look like it ultimately renders using SpriteBatch Draw. I’m unsure how this would couple with my idea of using 3D quads with textures on them. Off the top of my head this could probably be solved by doing all the SpriteBatch calls to a render target and using that as the texture for the quad, I’m just concerned about performance issues if I have a lot of characters on screen.

I’m curious if anyone has had success using Spine with billboards? Or even if anyone has used the SpriteBatch draw to render out to a large number of billboarded quads? I’m also open to suggestions of other ways to approach this problem if anyone has done anything similar.

Worth noting that I’m fine with higher level ideas at this point (though if you happen to have details or examples of having done this they are very greatly appreciated). Primarily I just want to avoid going down this billboarded quad road if it turns out it isn’t going to work for me and someone could have pointed it out.

I appreciate any feedback!

For reference, a snippet of code from Randolph Burt’s tutorial for using Spine with Monogame:

    protected override void Draw (GameTime gameTime)
    {
        this.spriteBatch.Begin ();

        this.GraphicsDevice.Clear (Color.CornflowerBlue);

        // In reality you'd probably pass in some time related variable to this rather than
        // my crude timer variable for demonstration purposes.
        // Also you'd probably want to perform the UpdateWorldTransform outside of the draw method
        // Should probably be in the Update method
        this.crabAnimationWalk.Apply(crabSkeleton, timer++ / 100, true);
        this.crabSkeleton.UpdateWorldTransform();
        this.crabSkeleton.Draw(this.spriteBatch);

        this.spriteBatch.End ();

        base.Draw (gameTime);
    }

Ya you are probably going to want to make your own text rendering code for 3d text.
Spritebatch imho is not suitable for 3d text beyond simple things.

This is just primarily because it uses a position vector or rectangle vector and bakes these positions for calls to be batched. Its not a fun idea dealing with that(general notion) between begin end calls, for dynamic text which must be positioned and rotated in relation to 3d objects under a 3d camera on a per object basis.
I.E. spritebatch was made for 2d text it has minor capability to do 3d stuff but wasn’t made with that in mind.

Apologies I should have been more specific. When I say “Characters” I meant player entities, not actual alphanumeric characters.

Fairly new to monogame myself but have been playing with Spine recently, am up for having a stab at some suggestions

My first thought was why not use the projection matrix assigned to the spine batch instance, line from a test project I been messing with:

((BasicEffect)spineBatch.Effect).Projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 1, 0) * scaleMatrix;

But then I figured if the spine is always facing front on, maybe this is more than is needed? Also your case is a lot simpler if the player can’t rotate the camera, in which case you should be able to just do some basic rule of repeating triangles type projection to scale the spine animation.

Sorting I’d of thought would be pretty straightforward? As long as you can get stuff into the same space stuff should just work, collision testing, depth etc

Just a few thoughts that came into my head. Good luck, sounds like an interesting project. Always quite fancied making a 2.5D type game along the lines of Don’t Starve, which seems to be the type of engine your building.

Good idea I hadn’t really even thought of altering the projection matrix to do what I had needed. Going to give that a test and will post results up here whenever I get things running.

So for anyone else who may end up having this question, things actually work out pretty easily. It is very easy to hook up a custom shader to a Spine SkeletonRenderer and render it however you’d like. Example of my rendering code for a Spine 2D object in the 3D world (pulled primarily from the Spine runtime example code):

if ( skeletonRenderer.Effect is BasicEffect )
{
	((BasicEffect)skeletonRenderer.Effect).Projection = projMat;
	((BasicEffect)skeletonRenderer.Effect).View = viewMat;
}
else
{
	skeletonRenderer.Effect.Parameters["World"].SetValue( Matrix.CreateScale( 0.2f, 0.2f, 0.2f ) * Matrix.CreateTranslation( spineCharPos ) );
	skeletonRenderer.Effect.Parameters["Projection"].SetValue( projMat );
	skeletonRenderer.Effect.Parameters["View"].SetValue( viewMat );
}
skeletonRenderer.Begin();
skeletonRenderer.Draw( skeleton );
skeletonRenderer.End();

Here’s a picture of it in action.

You can see the really simple lighting effect from the point light, and though you can’t tell from the screenshot it is animating properly. All that needs done (aside from polishing things up of course) is billboarding the object properly, but that should be easy enough to get working. I just currently have my 2D objects rendering along that plane so I can rotate the camera and easily see how things affect them versus the 3D ground object differently.

So yeah - in a nutshell everything works well and Spine is greatly customizable for the type of game you’re making.