I always found it useful to have something tangible in my hand when trying to solve issues or debugging. I've been known to print out code or game data just to have a condensed overview of what it is I'm working with.
At some point I figured it might actually be useful to be able to print out game data directly from the game editor. It might be even better if the data was formatted in an easy to read way.
So... After a couple of evenings looking through how printing in Java works, and trying out different approaches, finally the Zone Editor has a proper printing feature :)
It prints out the data in a hierarchical way, where definitions which are linked to are shown next to the field they are being linked from. The result looks a bit like YAML, but is only meant for human readability. The actual data is still stored in the form of (customized) JSON.
Tuesday 16 July 2019
Thursday 11 July 2019
Automating Asset Creation
I really hate repeating tasks.
That's one of the reasons why creating art assets can be such a drag for me: because a lot of actions need to be repeated over and over (plus the requirement for manual precision, but that's a different story).
Thankfully most of the tools out there can be automated to some extent. Allowing for certain tasks to be scripted out, rather than clicked/typed out again and again.
Good case study would character animation in the isometric RPG I'm working on right now:
And believe me, initially I did all of this by hand. But with every character I would automate more and more. And at this point adding a new character in game takes about 45 minutes, instead of days, out of which most is waiting for scripts to finish.
What I would like to show here is specific to my use case (2D isometric RPG using my Zaria Framework). However the logic and principles can be adapted to pretty much everything. Plus I'll add some useful Blender Python scripts.
What we will be doing here, is importing a humanoid character and applying to it already prepared, rigged skeletal animations.
Therefore we will need a character model. In this case, a royalty free model in FBX format, in the (kind of) T-pose.
We will also need all of the animations used, set up for a base character. With the camera positioned at the proper angle and distance as well.
Essentially what we will be doing, is substituting the character in the base animations for the new imported character, using the existing rig and rendering for all 8 directions.
If you have a different way of preparing rigged characters in a consistent manner, you can skip this step.
To get the model correctly into Mixamo it needs to be exported as FBX, with only the mesh and texture inside.
Thankfully Blender can do just that. Just click export to FBX and use the settings below:
One of the most important elements being setting Path Mode to Copy and making sure that textures are packed inside the output file (icon next to Path Mode).
When uploading to Mixamo you will be asked to locate a set of main bones, for the auto-rigger to kick in.
Once that is done, download the rigged T-pose as FBX.
This one imports the input FBX file into the input blend scene and substitutes already existing model for the imported one. The way it does that, is relying on names, therefore naming of (at least) the model root needs to be consistent in all animations.
Source: https://wtools.io/paste-code/y3A
This script renders all frames of an animation into png files. It also takes into consideration all of the directions. What is also important here, is that the naming is consistent. Each animation, for each direction, has the same name for each character. This will be useful later.
Source: https://wtools.io/paste-code/y3B
Finally we will run the scripts.
I ran them from a bash script which would run the first (to create the animation blend file) and the the other (to create the animation frame sprites) for all blend files in the input directory.
I also ran two of them at the same time to max out all of my processor cores.
Source of the bash script: https://wtools.io/paste-code/z1q
Here are both scripts hard at work.
The processor usage is quite significant. I found that running two of them at the same time is most optimal. And in my case generating all sprites took about 20 minutes.
The result ended up being over 7000 frames of animation.
For that we will be using the Texture Atlas Builder in the Zone Editor.
It has a number of ways to optimize the texture:
The process (especially looking for duplicates part) can be quite CPU heavy, and take a good while. However it is definitely worth it.
The result is a 8192x4096 pixels texture.
At some point during development I realized that I'm doing a lot of very mundane things in the Zone Editor. Hooking up components to objects, setting animation transitions etc. I realised that all of that can be automated. So I decided to reuse the script engine (based on Java Script) I put in the game, in the editor to be able to automate it's functions.
With the API I created, in practice anything that can be done through the UI can be scripted out. This turned out to be very powerful and very useful.
In this case we will be running script that sets up all of animation related data for a character. It will set up which frames correspond to which logical animations, set up animation events and transition animations.
Sources for the editor scripts:
With the characters being available in game soon after:
Employing this process saves me days of work for initial setup as well as for any further tweaks.
It is not perfect however. Some models might need some tweaking for some animations, due to mesh deforming imperfectly. Even that being the case, the minority of animations for which this happens, can be tweaked and with the used scripts re-rendered quite quickly.
That's one of the reasons why creating art assets can be such a drag for me: because a lot of actions need to be repeated over and over (plus the requirement for manual precision, but that's a different story).
Thankfully most of the tools out there can be automated to some extent. Allowing for certain tasks to be scripted out, rather than clicked/typed out again and again.
Good case study would character animation in the isometric RPG I'm working on right now:
- Each character has 29 animations.
- Each animation requires 8 sides to be rendered.
- All individual sprites need to be added to a texture atlas.
- Sprites in the texture atlas need to have empty margins removed, in order not to store useless information.
- The texture atlas itself needs to be compressed.
- Texture atlas requires information for the game engine where all sprites are.
- Animations need to be mapped to actions in game.
- Animations need to be mapped to specific directions in the isometric world.
- Certain animations need to be marked as looping.
- Certain animations need to be mapped to tags, which are used to start animations in-game "by type".
And believe me, initially I did all of this by hand. But with every character I would automate more and more. And at this point adding a new character in game takes about 45 minutes, instead of days, out of which most is waiting for scripts to finish.
What I would like to show here is specific to my use case (2D isometric RPG using my Zaria Framework). However the logic and principles can be adapted to pretty much everything. Plus I'll add some useful Blender Python scripts.
1. Prequisites
First of all some preparation.What we will be doing here, is importing a humanoid character and applying to it already prepared, rigged skeletal animations.
Therefore we will need a character model. In this case, a royalty free model in FBX format, in the (kind of) T-pose.
We will also need all of the animations used, set up for a base character. With the camera positioned at the proper angle and distance as well.
Essentially what we will be doing, is substituting the character in the base animations for the new imported character, using the existing rig and rendering for all 8 directions.
2. Mixamo
For the second step we will be using Mixamo. Its auto-rigger is just the help we need. The additional fact of having A LOT of good looking animations ready to use, makes it even more appealing of a tool.If you have a different way of preparing rigged characters in a consistent manner, you can skip this step.
To get the model correctly into Mixamo it needs to be exported as FBX, with only the mesh and texture inside.
Thankfully Blender can do just that. Just click export to FBX and use the settings below:
When uploading to Mixamo you will be asked to locate a set of main bones, for the auto-rigger to kick in.
Once that is done, download the rigged T-pose as FBX.
3. Blender
Now that our model is rigged exactly as our prepared animations, we can run some magic Blender Python scripts.This one imports the input FBX file into the input blend scene and substitutes already existing model for the imported one. The way it does that, is relying on names, therefore naming of (at least) the model root needs to be consistent in all animations.
Source: https://wtools.io/paste-code/y3A
This script renders all frames of an animation into png files. It also takes into consideration all of the directions. What is also important here, is that the naming is consistent. Each animation, for each direction, has the same name for each character. This will be useful later.
Source: https://wtools.io/paste-code/y3B
Finally we will run the scripts.
I ran them from a bash script which would run the first (to create the animation blend file) and the the other (to create the animation frame sprites) for all blend files in the input directory.
I also ran two of them at the same time to max out all of my processor cores.
Source of the bash script: https://wtools.io/paste-code/z1q
Here are both scripts hard at work.
The processor usage is quite significant. I found that running two of them at the same time is most optimal. And in my case generating all sprites took about 20 minutes.
The result ended up being over 7000 frames of animation.
4. Zone Editor: Texture Atlas
Now that we have all animation frames, we need to put them in a single texture. As this is a 2D game, graphics memory will be used heavily. Therefore we need to optimize our textures as much as possible.For that we will be using the Texture Atlas Builder in the Zone Editor.
It has a number of ways to optimize the texture:
- It removes all duplicate frames.
- It cuts out all of the empty margins from all of the images.
- It can compress the texture using DXT.
The process (especially looking for duplicates part) can be quite CPU heavy, and take a good while. However it is definitely worth it.
The result is a 8192x4096 pixels texture.
Some closeup on the result:
5. Zone Editor: Game Assets
The final piece of the puzzle is putting all of this together.At some point during development I realized that I'm doing a lot of very mundane things in the Zone Editor. Hooking up components to objects, setting animation transitions etc. I realised that all of that can be automated. So I decided to reuse the script engine (based on Java Script) I put in the game, in the editor to be able to automate it's functions.
With the API I created, in practice anything that can be done through the UI can be scripted out. This turned out to be very powerful and very useful.
In this case we will be running script that sets up all of animation related data for a character. It will set up which frames correspond to which logical animations, set up animation events and transition animations.
Sources for the editor scripts:
- https://wtools.io/paste-code/z1J
- https://wtools.io/paste-code/z1K
- https://wtools.io/paste-code/z1L
- https://wtools.io/paste-code/z1M
With the characters being available in game soon after:
6. Conclusion
In short: Anything that can be automated should be automated.Employing this process saves me days of work for initial setup as well as for any further tweaks.
It is not perfect however. Some models might need some tweaking for some animations, due to mesh deforming imperfectly. Even that being the case, the minority of animations for which this happens, can be tweaked and with the used scripts re-rendered quite quickly.
Subscribe to:
Posts (Atom)