UE4 – Blender – Makehuman workflow cheat sheet

Good evening! Tonight’s entry is my attempt to document a few things I have picked up this past weekend as I start to develop my next project. I decided to make some animations using blender. I have mostly created static meshes in blender, but I decided to try to make my own character animations. Here are some of the things I have found.

 

Workflow from makehuman to UE4

I used makehuman to create a pretty decent looking character. I created some custom cloths for the character and exported the model with rigging (basic game rigging in makehuman) to Collada format. I tried using the special blender-makehuman format, but I had issues when the skeleton was imported to blender.

I imported the model into blender. I read that UV unwrap is necessary for textures to appear in Ue4, but I didn’t have to perform this step. I simply went into UV editing mode and selected the textures and made sure they were scaled and position correctly on the faces.

I am not going into any detail about how to animate, I found it to be pretty intuitive. Change to animation mode, pose the character and then hit I to insert keyframe.

When you are ready to export to FBX for UE4, set the Unit Scale under Scene to 100 units metric (or whatever you want. It will equate to the same number of ue4 units) Make sure that whatever unit scale is set matches on the FBX export dialog.

 

Other stuff I always have to lookup :)

Fly Mode - Click the camera icon under the scene and then Shift + F to enter fly mode. ASWD to move, left click to return mouse control, right click to return the camera to the previous location.

Keying animation frames – To insert a keyframe in animation mode, make sure pose is selected and hit I (Insert Keyframe) and then ‘Whole Character’

deleting animation frames – This only works on the dope sheet. Make sure to right click to deselect all, then hit B to rectangle select any frames to delete. Hit X to delete selected keyframes

To rotate meshes, select the mesh and hit R and then whatever axis (X Y or Z)

 

 

 

 

 

Daddy, I have an idea for a video game. Its called Stop the Droid!

Actually, the exchange between me and my 5yr old son (Ill call him J) went something like this.

J: “Daddy, I have an idea for a video game. Its called Stop the Droid! Do you like that name?”

Me: “Shouldn’t it be Stop the Droids?”

J: “NO! Stop the Droid! Stop the Droid!”

Me: “Ok, so what is this game all about?”

J: “Droids are attacking you, and you have to fight them!.. and when they get hit, they make explosions! And when you get hit you make this sound. ‘ugggharg!!’ Is that funny? Do you like this game?”

Me: “Sounds pretty cool to me!”

And it was at this point that I realized I was completely tangled in his web, and that I would be spending the next few months working on this game. To be fair, I had been looking for any reason to make another game for XBLIG, and as it turns out, J’s first demand was that it be released to the XBox 360. (He said XBox to be fair, Ill just assume he does not know about XBox One ;)
I was also looking for any excuse to use Spine and the XNA/C# runtime. Spine is an amazing 2d skeletal animation program with tons of supported runtimes.  (Checkout Spine Here)

 

A lesson about originiality

So the next thing I had to do was to find out what this “Stop the Droid!” game was all about. The central idea for Stop the Droid! is a battle against wave after wave of droids from a droid army that is invading your planet. As it turned out, many of the first ideas that were presented to me were very VERY similar to concepts and characters from a certain wildly popular movie franchise that J totally adores. May the force be with you while you try to guess it. We had to have another talk.

Me: “I will make Stop the Droid!, but we cannot use Anakin, and we may not use Obi Wan. They are not our own ideas. We have to be original. Do you know what I mean?”

J: Blank stare

Me: “You need to think of exactly what will happen in this game, but most importantly, we must come up with our own characters and game-play.”

And that is when it started to get really fun.

 

Taking direction from a 5yr old.

I decided that my part in this wacky journey would be to develop for J as if he was the project manager. I started to treat every one of J’s ideas as something to consider seriously (and I continue to help out whenever he crosses the line with IP). I would not make any unilateral decisions, and I would run every idea I have by J. If he shoots it down, then it is done. I will come up with a different idea. And that’s the way we have worked for the last six weeks or so.  Just about every day, J looks over what I have done, plays it for 10-15 minutes, and then gives me 500 other ideas. I have been totally astounded by the level of specific detail he has been able to provide. Everything from the sound effects and music to the box art, he has had a large hand in creating.

jonah_and Me

 

 Current State

Stop The Droid! is still in early development, but we are progressing slowly. Just trying to manage the multitude of ideas that J has is like another job all by itself!
We are currently trying to:

  • Narrow the list of upgrades and weapons that will be available.
  • Decide whether or not to add “side kick” droids. (An idea J had yesterday!)
  • Decide what droids will make the final cut.
  • Incorporate the item and upgrade system.
  • Finish Multi-player coop mode

Here is a short video of Stop the Droid! in its current state.

 

BoxArt

XNA Tutorial: HLSL and SpriteBatch for 2D effects.

After writing most of my first XNA game using the built in sorting capability of SpriteBatch, I ran into a pretty big problem. I wanted to add a HLSL effect to certain sprites. I followed the instructions I found, setting the SpriteSortMode to Immediate. What I did not realize at the time is Immediate means IMMEDIATE.

spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);

This means that you cannot rely on the spriteBatch.Draw method to sort for you, and must sort yourself.

I posted in the XNA forums, and learned that it is actually better to sort yourself. This way you know exactly how everything is working behind the scenes, and you can really improve upon the look by implementing same neat HLSL effects. Rewriting my draw functionality was not a huge undertaking but it did take some time.

For my purposes, I decided to create an object for handling everything needed to draw later on.

 class DrawableObject
    {
 
        public Texture2D Texture;
        public Vector2 Position;
        public Vector2 Origin;
        public Color Color;
        public float Rotation;
        public float Scale;
        public float Z_Index;
        public Rectangle DisplayRect;
        public DrawType DrawType;
        public Effect Effect;
        public Object ObjectRef;
 
        public DrawableObject(Texture2D texture, Vector2 position,Rectangle displayRect, Color color, float rotation, Vector2 origin, float scale, float z_Index, DrawType drawType, Effect effect, Object objectRef)
        {
            this.Texture = texture;
            this.Position = position;
            this.Origin = origin;
            this.Color = color;
            this.Rotation = rotation;
            this.Z_Index = z_Index;
            this.Scale = scale;
            this.DisplayRect = displayRect;
            this.DrawType = drawType;
            this.Effect = effect;
            this.ObjectRef = objectRef;
 
        }
    }

In this Object, DrawType is an enumeration used to mark each object so drawing can be handled differently depending on its type. For my purposes I had Player, Projectile, Shadow, etc
I then create a list of DrawableObjects to sort based on the z index.

List listToDraw = new List();
 
            for (int x = 0; x < playerManager.Players.Count; x++)
            {
                    //Add all my players as drawable objects
                    listToDraw.Add(new DrawableObject(playerManager.Players[x].PlayerAnimation.CurrentTexture, playerManager.Players[x].PlayerAnimation.ScreenPosition ,                   playerManager.Players[x].PlayerAnimation.DisplayRect, Color.White, 0f, Vector2.Zero, 1f, playerManager.Players[x].PlayerAnimation.ScreenPosition.Y) / Map.Height, DrawType.Player, playerManager.Players[x].PlayerAnimation.PlayerEffect,  playerManager.Players[x]));
              }

I then sort ….

           //Sort for the right order
            listToDraw.Sort(delegate (DrawableObject d1, DrawableObject d2) {return d2.Z_Index.CompareTo(d1.Z_Index);});

and then draw the list

 for (int x = 0; x < DrawObjectList.Count; x++)
                {
                    if (DrawObjectList[x].DrawType == DrawType.Player)
                    {
                        Player pn = (Player)DrawObjectList[x].ObjectRef;
 
                        spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
                        if (DrawObjectList[x].Effect != null )
                        {
                            DrawObjectList[x].Effect.Begin();
                            DrawObjectList[x].Effect.CurrentTechnique.Passes[0].Begin();
                        }
                        spriteBatch.Draw(DrawObjectList[x].Texture, DrawObjectList[x].Position, DrawObjectList[x].DisplayRect, DrawObjectList[x].Color,
                                         DrawObjectList[x].Rotation, DrawObjectList[x].Origin, DrawObjectList[x].Scale, SpriteEffects.None, DrawObjectList[x].Z_Index);
 
                        if (DrawObjectList[x].Effect != null)
                        {
                            DrawObjectList[x].Effect.CurrentTechnique.Passes[0].End();
                            DrawObjectList[x].Effect.End();
                        }
 
                        //etc etc.
                 }

Well I hope this helps someone looking for the same thing.

~J