Review
Welcome to the second part of my Character Customization blog post! The first part can be found here if you missed it, and it covers preparing a Blender3D file that contains a rig, several meshes weighted to that rig, and animations, as well as exporting that Blender file to multiple FBX files for Unity3D to use in a game. We ended up with this:
File Naming Convention
Before we go further into this, I need to mention a naming convention for all of these files. Keep in mind that this is only my naming convention. Your system may end up being different in the end, but the point is, in order for a system to be loaded into a game, it works best if the filenames follow a certain convention.
My convention for the input Blender file is:
<base name><rig>.blend
And specifically, my files are named like this:
- HeroA.blend
- HeroB.blend
- etc.
The “A” is my rig identifier. And if I ever create new rigs for new characters, I’d have a HeroB.blend, HeroC.blend, etc.
My convention for the output FBX files is:
- <base name><rig id>[rig]_rigify.FBX
- <base name><rig id>[<character id>.<costume id>]_rigify.FBX
- etc.
For example,
- HeroA[rig]_rigify.FBX
- HeroA[00.0]_rigify.FBX
- HeroA[01.0]_rigify.FBX
- etc.
The main thing to notice here is that one of those files is the rig file which may or may not include the animations (for my purposes, I have included them), and all other files are numerous custom meshes that would be attached to the rig. Each of these files corresponds to a layer in the Blender file, and the layer name is identified with the character string in between the brackets.
The Resources Folder
Unity provides a method for loading resources from disk, and this is the method I use to load my FBX models:
public static Object Resources.Load(string path);
The catch is, any resources loaded with this function must be in a subfolder named “Resources” anywhere in the Unity Assets directory. You can even have multiple folders named “Resources” in the Assets directory if you choose to, but that can sometimes be a little confusing.
Memory for a resource is not allocated until Resources.Load() is called. This is different from the prefab method, which preallocates memory for each prefab, which I’ll discuss below.
Loading the FBX assets from disk is a lot more like traditional game development, and how typical programming works. You get to choose how to load the assets, and when to load them.
Choosing Resources.Load() over the Prefab Method
I chose to use this method because loading up each FBX as a prefab set up in a scene has a number of drawbacks.
- All model resources would have to be preloaded as prefabs, which uses precious memory that could otherwise be used by your actual game. Why load all those custom parts when you’re not even using them?
- They’d have to be manually updated whenever new layers or blend files are created.
- For example, if you were to save a prefab reference in a script called, say, CharacterPrefab.cs, you’d have to update that script manually whenever you add a new character or costume, head, or hair model.
- Alternatively, in CharacterPrefab.cs, you can add an array of GameObjects to store all your prefabs. This way, you can modify the count in the Inspector, and then drag/drop the FBX model into each slot.
- Both of these solutions require you to access a MonoBehaviour script in one way or another. If there was a way to dynamically load those prefabs without having any intervention with the Inspector, then it would cut down on some of the manual processing.
- There is an existing bug in Unity that doesn’t update prefabs that contain an FBX asset that has been updated. There are some suggestions online that mention attaching the FBX model as a child of an empty GameObject, which serves as the actual prefab. This has been a huge pain for me, because I’d have to manually delete the old FBX model from the prefab, and re-drag/drop the FBX model onto the prefab. That’s lots of wasted time.
It’s worth mentioning that it is possible to implement an AssetPostprocessor to update these. The idea is that whenever the FBX file is updated, you can have an AssetPostprocessor target an existing prefab that’s associated with it, say by filename or something, and then modify the prefab all in script. But I decided not to go this route.
That should be it for all of my reasons to NOT use prefabs that reference the FBX files.
Loading the FBX files in Unity
All that talk about Resources.Load() comes down to this section. Before we get into any code we have to get these FBX files loaded into Unity. These files simply need to be copied into the Unity project’s Assets folder tree, remembering that they MUST be contained in, or in a subfolder of, a folder named “Resources”. You can do this by either exporting the FBX files directly into the target Assets folder manually from Blender’s UI, or automatically via a series of scripts as I’ve discussed in my blog post about a Blender-to-Unity Asset Builder. Here’s an example of a folder tree that I have for my own project:
Setup
All right, let’s do some Unity stuff.
To serve as a testing ground, open up a new scene, and place an empty GameObject in the Hierarchy. We’ll attach a script to it which will do all of our resource loading.
using UnityEngine; using System.Collections; public class CustomCharacterTest : MonoBehaviour { // Use this for initialization void Start() { } // Update is called once per frame void Update() { } }
We’ll implement all of the loading code in our MonoBehaviour’s Start()
function.
Loading the Rig
GameObject rigObj = null; GameObject rigPrefab = Resources.Load("models/heroes/HeroA[rig]_rigify") as GameObject; if (rigPrefab != null) { rigObj = GameObject.Instantiate(rigPrefab); rigObj.transform.parent = this.transform; }
Note that when loading from Resources, you’re loading the asset into your project, not loading the object into the scene hierarchy. You can think of it as dynamically loading a prefab to instantiate from. Since Resources.Load() can load any type of asset, it’s not always the case that it’s a GameObject. In this case, it is a GameObject though, so after we create the prefab, we can instantiate it.
After loading the rig, you should see something like this in the Hierarchy:
The rig’s GameObject hierarchy should be kept intact from the Rigify armature imported from Blender, except if you have the RigifyToUnity asset installed, which you should, then the hierarchy should be somewhat stripped down to the essentials as in the screenshot.
Now, WTF is that “Plane” object you ask?
The Dummy Object
Okay, I only glazed over this in Part 1 of this post, so I apologize for that, but here is more detail about it, because it is essential for getting the skinned mesh working later on.
The “Plane” GameObject is a very simple mesh that’s skinned to the rig, and it can actually be named anything. It’s just a “dummy” object that holds a SkinnedMeshRenderer that we need for later. If you select it and check out the Inspector, you’ll see the SkinnedMeshRenderer component assigned to it.
This mesh can actually be any geometric shape that you create in Blender (even a stick dummy if you want to make visualizing animations easier), as long as it resides on the rig’s layer, and gets exported with the rig as a skinned mesh. I just wanted to choose the simplest object I could to reduce memory consumption, but after we’re done with it, it gets deleted anyway.
BoneDebug
At this point, if you’re not visually convinced that the rig is loaded, I found a nifty asset on the Asset Store called BoneDebug. You can drop the BoneDebug.cs script onto the rig or root GameObject, and it will visualize the armature for you!
Utility Functions
Before we get to loading the meshes onto the rig, I need to get some things out of the way. These are a few utility functions that I use in the below code, so know that it’s there.
public class TransformUtils { // Does not support case-sensitive public enum StringMatch { Exact, // Exactly Leading, // Leading the string Partial // Anywhere in the string } // TransformUtils // Recursively look for the bone with specified name public static Transform GetTransformWithName(Transform root, string name, StringMatch match = StringMatch.Exact) { if (match != StringMatch.Exact) { string rootname = root.name.ToLower(); int index = rootname.IndexOf(name.ToLower()); if (match == StringMatch.Leading && index == 0) return root; else if (match == StringMatch.Partial && index != -1) return root; } else { if (string.Compare(root.name, name, true) == 0) return root; } for (int i = 0; i < root.childCount; ++i) { Transform child = root.GetChild(i); Transform sub = GetTransformWithName(child, name, match); if (sub != null) return sub; } return null; } // TransformUtils public static void ResetTransform(Transform transform) { transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; } public static void ResetChildTransforms(Transform parent) { for (int j = 0; j < parent.childCount; ++j) { Transform child = parent.GetChild(j); TransformUtils.ResetTransform(child); } } }
Loading the Model
GameObject modelPrefab = Resources.Load("models/characters/heroA[01.0]_rigify") as GameObject;
This time, instead of instantiating the model prefab wholesale, we’ll “pick at” the prefab in a piecemeal manner. Essentially, we just want to load the head and hair mesh objects, and also the body mesh object. We don’t want to instantiate the rig that they are attached to in the model prefab.
Loading the Head and Hair
The head and hair are relatively simple to load compared to the body, so we’ll start there. The head and hair objects are not skinned to the armature. They are simply parented to a bone on that armature.
GameObject modelPrefab = Resources.Load("models/heroes/HeroA[01.0]_rigify") as GameObject; if (modelPrefab != null) { Transform headXfrm = TransformUtils.GetTransformWithName(modelPrefab.transform, "head", TransformUtils.StringMatch.Leading); Transform parentBoneXfrm = headXfrm.parent; Transform rigHeadBoneXfrm = TransformUtils.GetTransformWithName(rigObj.transform, parentBoneXfrm.name, TransformUtils.StringMatch.Exact); GameObject headObj = GameObject.Instantiate(headXfrm.gameObject) as GameObject; headObj.transform.parent = rigHeadBoneXfrm; GameUtils.ResetTransform(headObj.transform); GameUtils.ResetChildTransforms(headObj.transform); }
If it’s not clear as to what the script is doing, here’s what’s going on in semi-plain English. GetTransformWithName()
gets the head transform in the prefab. We also want to remember the head transform’s parent too. With the parent transform’s name, we look for the bone with that same name in the rig object hierarchy (because the rig object is what’s actually instantiated in the scene). We then instantiate the head object from the prefab, and set its parent to the bone that we spent the last few lines trying to get. After all that’s done, we reset the transforms of the newly created objects, namely the head and hair objects.
With this, you can load up the scene, and see that the head and hair objects are loaded, especially with the BoneDebug component applied to the rig.
I want to mention that the calls to ResetTransform()
and ResetChildTransforms()
are here because I couldn’t get the head and hair to look right after instantiation. I don’t think they’re necessary if you apply your transforms properly in Blender, but for some reason, they still looked wacky to me. Go figure.
Loading the Body
And now for the main event! The body mesh is skinned to the rig with a SkinnedMeshRenderer. However, in terms of the model prefab that we loaded above, this means that the body mesh of the prefab is skinned to the prefab rig with the prefab SkinnedMeshRenderer. This does us no good, because we don’t want a SkinnedMeshRenderer referring to a rig in the prefab. We want to use the rig that’s already loaded in the scene.
But how do we go about doing that?
Let’s forget about the rig in the scene for a second, and focus on getting the mesh from the prefab’s SkinnedMeshRenderer.
Transform bodyPrefabXfrm = TransformUtils.GetTransformWithName(modelPrefab.transform, "body", TransformUtils.StringMatch.Leading); SkinnedMeshRenderer prefabSkinnedMeshRenderer = bodyPrefabXfrm.GetComponent< SkinnedMeshRenderer >(); Mesh mesh = prefabSkinnedMeshRenderer.sharedMesh; Material mat = prefabSkinnedMeshRenderer.sharedMaterial;
We’ll hold on to the Mesh and Material here.
Static Mesh Test
To really understand what’s going on here, let’s load up the body mesh onto a standard, static MeshRenderer. Here’s the function that does the work.
private void CreateStaticModel(Transform parent, Mesh mesh, Material mat) { GameObject bodyObj = new GameObject("body_static"); bodyObj.transform.parent = parent; MeshFilter filter = bodyObj.AddComponent< MeshFilter >(); filter.sharedMesh = mesh; MeshRenderer renderer = bodyObj.AddComponent< MeshRenderer >(); renderer.sharedMaterial = mat; }
And then here’s the function being called, with the Mesh and Material from above.
CreateStaticModel(rigObj.transform, mesh, mat);
What we did here is essentially take the Mesh and Material references that were assigned to the prefab SkinnedMeshRenderer, and attached them to a newly created MeshFilter and MeshRenderer components.
That’s fantastic for making scarecrows. Yes, I know. But what we can take away from this is that if we cache references to the Mesh and Material from the SkinnedMeshRenderer, we can easily apply it back onto a new SkinnedMeshRenderer that’s attached to the rig in our scene.
Swapping the SkinnedMeshRenderer
So for the real deal, we’ll take our rig object that’s in the scene and add a new SkinnedMeshRenderer component to it. The difference between the static MeshRenderer and the SkinnedMeshRenderer is that we need to provide the bones used to skin the mesh. Remember our “Plane” object from a few sections back? That object has a valid SkinnedMeshRenderer, which contains the proper bone mappings from the rig in the scene to the mesh. Also notice that after we’re done with the “Plane” object, we destroy it, because we don’t need it any more. The Mesh and Material assignment is essentially the same as before. Here’s the function.
private void CreateSkinnedModel(Transform parent, Mesh mesh, Material mat) { Transform planeXfrm = TransformUtils.GetTransformWithName(parent, "Plane", TransformUtils.StringMatch.Exact); SkinnedMeshRenderer rigSkinnedRenderer = planeXfrm.GetComponent< SkinnedMeshRenderer >(); if (rigSkinnedRenderer != null) { GameObject obj = new GameObject("body_skinned"); obj.transform.parent = parent; SkinnedMeshRenderer skin = obj.AddComponent< SkinnedMeshRenderer >(); skin.sharedMaterial = mat; skin.sharedMesh = mesh; skin.bones = rigSkinnedRenderer.bones; GameObject.Destroy(planeXfrm.gameObject); } }
And the call.
CreateSkinnedModel(rigObj.transform, mesh, mat);
And finally, we have our fully skinned character model!
Conclusion
With this dynamic model loading process, you can probably see how we can easily load up any FBX resource that we want, dig into the prefab hierarchy, and pull out a mesh or object, skinned or not, and that having a uniform naming convention would help with this. You’d be able to call character “01” with costume “3” by using the string “[01.3]” in the filename to apply to rig “A”, and mix and match accordingly, while loading only the FBX files that you absolutely need to at any given time. It’s probably pretty obvious that this is just the bare bones for getting a custom character system working, but I think this is the core of the work that needs to be done. Another thing we can do is attach an Animator and apply different animation clips, which requires loading an AnimationController, but that’s beyond the scope of this subject. We can also play around with assigning different materials or textures, which is also out of scope of this blog entry. Anyway, I hope this helps some Unity developers who are interested in introducing character customization into their game, or even helps shed some light to non-developers into the work that’s involved in getting such a system working.
Make it fun!
- Unity 5.1.1f1
- Blender 2.74
Dear a_a,
I love the tutorial because I was strugeling with this for days now.
Is it possible that you make a video tutorial about it too?
Because English isn’t my native language so reading english makes me not understand is as well as a video.
Casper
Hello Casper, I’m glad you enjoyed the Character Creation article. I plan on eventually preparing video on the subject, but not for about another month or so. If you have any specific questions, feel free to send me an email and maybe I can help out.
Hi! I’d like to say that your tutorial has helped me a lot in the past! Unity should have a clean solution for this, but it doesn’t seem like a priority…
May I ask a question? If we wanted to create an item that has realtime physics simulation, like a ponytail or a coat, we’d need custom bones just for these items… I’m still confused about this aproach, I really don’t know a way to make it wirk using this method…
Could you please help me? Thank you so much!
Hello Kojiro. Unfortunately, I’m not familiar with how to use realtime physics simulation in Blender. But generally speaking, having custom bones for things like ponytails and coats allows you to manually keyframe animations of those bones, rather than do a physics simulation of them. I suppose in Blender, there may be a way to do physics simulation of those bones, but you would still need to figure out a way to “bake” that into keyframes before exporting to fbx. Realistically, if you wanted a physics simulation in game, you wouldn’t do this in Blender. You would have your Unity scripts identify which items are to be animated (ponytails, coats, etc) in either editor markup or in startup initialization of the game, and then have a physics simulation (you can probably find a suitable one on the Asset Store) animate those items in realtime.
Hi! While I’m not familiar with Blender, in Unity you can easily and also automatically accomplish this with an asset that applies a simple physics simulation based on velocity to the respective parts – for example by using Dynamic Bone or Magica Cloth from the Asset Store. There might be a way to do this with the integrated cloth simulation too, but I’m not sure about that as it operates on vertices rather than on bones/transforms.
Let’s take the hair for example – I haven’t tried this out but I think it should work. In this tutorial, the hair are a static mesh. If you want to have them physically simulated, you could have a GameObject in your Resources folder that has the hair, but also a skinned mesh renderer just for the hair, and child transforms that are the bones of the renderer, so that the hair mesh deforms when the child bones rotate or move. The object should also have the component responsible for rotating the bones according to physics, like a DynamicBone component. If you have set it up like that you can treat the hair object the same as in this tutorial, because it’s skinnedMeshRenderer is encapsulated on it’s own and it is enough because you only need to drive it through physics.
For possible automation, you could
– Set up Preset assets for your DynamicBone (or other component) configurations
– Have the preset file name somewhere in your fbx name convention and try to match the preset settings with the according component, possible in an AssetPostProcessor script.
There are different ways to assign predefined settings to components.
What’s more complex is to choose the bones that are simulated, one suggestion is to just simulate all child bones of your model and assign those bones to the DynamicBone component. And then you can also include colliders, for example if you don’t want the hair to phase through the head easily, you could set up a custom DynamicBone collider for the head. Setting this up automatically might be the hardest part – if it is desired. One possibility I can see is to get the head transform, calculate an approximate radius for the head collider, attach the dynamic bone collision to the head and have that referenced in the hair DynamicBone script.
A note: DynamicBone is computationally pretty costly, depending on the number of transforms you need to simulate, magica cloth can be more performant in that regard.
Hi, I realize this post is kind of old now, but it is still very helpful. Out of curiosity though, after you have done all of this at runtime, how do you go about saving the created character so the game can reload it easily on next start?
Hello Adam, typically you would have some sort of identifier (i.e. string or integer id) to differentiate all the parts, and those “part numbers” are stored along with your character’s save profile, or however you structure your game. For example, each character part already has a name that’s used from the Blender file, so why not use that? Maybe I’ll cover that in a future post some time.
Does this still work? I’m doing some test but it’s not working for me.
skin.bones = rigSkinnedRenderer.bones;
I think the problem is here. Here you are setting the new skin bones to be the same as the Plane skin bones. But in my tests Plane doesnt get the full bone list, just some bones that affect it’s vertexes.
I’m testing with a model from 3dsmax and perhaps an FBX is exported differently from Blender. So, could you post the project? Or at least the blender files to confirm my suspicions?
Thanks
I’d have to dig for the model in my old archives somewhere, so it could take a while. It sounds like this definitely could be a difference between 3dsmax and Blender regarding how bones are stored. I know in Blender, all I do is parent the mesh to the armature, with Automatic Weights. That’s enough to associate the armature to the mesh. 3dsmax may do things differently. Have you tried using BoneDebug to see if the bones show up at all on the Plane? If you’re concerned that not all the bones are weighted to the Plane mesh, how about creating a simple form (i.e. humanoid) to encompass the armature/rig, and then bind the mesh to that rig?
Dear a_a,
I like your article very much and it has helped me a lot.
Now I have a headache. You heard me correctly how to export only one FBX file of animation clips in blender.
What I want is that an FBX file in unity has an animation in a state, and now I export FBX in blender often with many animation clips.
Hi Jonas, I’m glad you liked the article. I hope you’ve made some progress on your problem. Unfortunately, your answer is out of scope for the article’s subject.
I don’t understand exactly the problem you are having. I export from Blender many Actions (animations) created in the DopeSheet’s ActionEditor. I used to use Unity’s Mechanim to manage states, but it got cumbersome to manage. I typically use an AssetPostprocessor to regenerate state info, such that the links are maintained but the referenced actions are updated.
Nowadays, I use Animancer Pro (https://assetstore.unity.com/packages/tools/animation/animancer-pro-116514) as it gives me better control over animation in scripts.