The full asset is now available as open source, check it now -> Character Customization
This tutorial is intended to game developers and modellers of medium and advanced levels, and assumes that you have knowledge of C#, Unity Architecture and 3D modelling and rigging.
Note: I’m aware of the problem with the models. I’m working in a new version of the tutorial, with fixed models, as well in the new asset for customization with this method and another one more flexible. I hope I can publish the update and the new asset soon.
I will not explain everything here, I’ll only show how you can achieve the results show in the video presentation. So, don’t expect a step-by-step tutorial. The source code have a lot of comments, so it can be easy to follow it.
The character customization works with two type of objects:
– rigid objects that aren’t deformed by bones, like helmets, weapons, rings
– clothes that need to be deformed by bones, to follow the movements of the character
These two types of objects have different forms of use.
The rigid objects are instantiated and assigned as a child of a bone. It can be used for clothes too? Well, yes, but doesn’t work very well. For clothes we use a nice component that Unity has: SkinnedMeshRenderer.
As the documentation says, Unity uses the Skinned to render bones animations, that perform deformations in the mesh of the object. So, when you import a model that have a skeleton system (called armature), Unity create a skinned mesh for the object, to interact with the bones. The bones are invisible, but you can access then in the editor (or in a script in runtime).
Let’s take a look at our model, the chibi, to understand how the Skinned Mesh works.
As you can see, the object have the mesh (in this case, various meshes, it will be explained later) and the bones armature (named metarig). If you expand the metarig object, you can see the bones hierarchy of the chibi.
When selecting one of the meshes, we have access to its Skinned Mesh Renderer and Materials assigned to it. So, every mesh that have influence of a bone will have its own Skinned Mesh Renderer.
The Skinned Mesh Renderer have various properties, but the one that make our “magic” happens is the property Mesh. This one tells what mesh it uses. You can change it to another mesh of another object.
How exactly it works? When a bone is assigned to a mesh, every vertex of this mesh store information on how the bone will deform it. Because that you can chance the mesh to another one. But the other mesh need to have the appropriate weight map for the bone.
What my system does is take the mesh of another object, an armor for example, and assign it to the part of the body I want to change. Once the char’s body and the armor was made with the same armature, they share the same bones information in their weight mappings, and with this information the Skinned Mesh Renderer will know how to render the mesh.
The chibi model consist on its body, divided into sections (head, arms, legs, and so on), its armature, and objects that represents each cloth type available, like upper (for shirts), lower (for pants), shoes and gloves. These cloth parts are the ones that will receive the meshes to make the clothes the char is wearing.
For example, I want to put a Christmas jumper in the chibi, so I get the jumper object mesh and assign it to the mesh of the upper cloth object. Then I apply the material and, voilá, the chibi is wearing now a nice red jumper. No need to remove an existing object and instantiating a new one in the place. Only changing the mesh and the texture. Easy, no?
Why I divided the body in various parts, and have another ones to the clothes? Because some clothes doesn’t cover the entire part of the body, like a sleeveless t-shirt. Part of the torso will appear, so there is no need to model the parts of the torso in the t-shirt, only the t-shirt itself. Because that the model have the body part and the cloth part. With the jumper the torso and the arms can be hidden, to have less tris to be rendered.
Take a look at the pictures bellow:
This is the chibi body with the clothes parts hidden. There is only its skin.
The chibi with the clothes parts visible, all with a magenta material. As you can see, the clothes parts doesn’t need to be complete and doesn’t need to have a texture (any material can be used), once they work as a placeholder only.
To make it work correctly, all the objects (char body, clothes and the placeholders) need to have the point of origin (or anchor) in the same place. It can be seen in games like Oblivion/Skyrim, their models have their point of origin in the ground, between the feet. It ensures that the placement of the parts will be correct. And check if all the objects have the same scale, because, you now, bones can change the size of the mesh if the scales are different.
You don’t need to create the clothes inside the same file as the body of the character, only the placeholders. You can have one file for each cloth part; they need only to have the same armature and same point of origin.
In the folder Models of the project there is all the models files:
– chibi, that is the character file with the character mesh, armature and clothes placeholders
– each file for each cloth file, with the cloth mesh and the armature
– infiback, that is the model used to make the infinite background, instead of using a plane and a skybox.
The animation is in a separate file, inside the folder Animations. All model files, and the animation, are in Blender format. I don’t use fbx exported from Blender because I’m having some weird issues with animations. Once Unity imports the Blender file, I use it.
Now, how it works in code? It’s very simple: change the shared mesh of the SkinnedMeshRendener of the object by a new one:
//Load mesh from source object GameObject sourceObject = Resources.Load("Clothes/"+cloth.MeshName) as GameObject; Mesh mSource = sourceObject.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh; //Assign to final object GameObject objDest = ClothesParts.Find(x => x.ClothType == cloth.TypeCloth).ObjectCPart; objDest.GetComponent<SkinnedMeshRenderer>().sharedMesh = mSource; objDest.SetActive(true); //Ensure that the cloth object is visibe
The source object is a prefab, stored inside the Resources folder. You don’t need to create a prefab for each texture of each cloth, only one prefab of the cloth to act as a donor of the mesh, the texture will be applied later in the cloth placeholder:
Material sourceMat = Resources.Load<Material>("Clothes/Materials/"+material); GameObject objDest = ClothesParts.Find(x => x.ClothType == objToChange).ObjectCPart; objDest.GetComponent<Renderer>().material = sourceMat;
So, you need to have each material to each texture of clothes. In this example, we have one prefab called jumper and two materials for jumper’s texture: jumper_black and jumper_red.
I this example project I used relation tables, to tell to script what object represents what part of body, or what type of cloth. So, I don’t need to find each part by name inside the script. The relation tables are public Lists, that can be accessed in the Inspector allowing to set what object belongs to what part of body or cloth directly in the editor.
The script CustomizeObject has all the code to change the clothes meshes, apply the textures, and assign other objects (like hair) to bones. It also have enumerations of body and cloth parts, and the relation tables for body parts, cloth placeholders and bones that can receive addons. This script is added to the character model.
The panel with the cloth options is controlled by the script ChangeClothes. It’s added to an empty GameObject in the scene. When a cloth is selected, the script calls the CustomizeObject method to change the clothes. The panel is made with UI controls (scrollview, and the buttons are created at runtime).
The script ClothesDB holds the information about all the clothes and addons available, loading it from a JSON file called clothes_db.json, and storing in collections. The clothes panel is built with information from this class. It’s also added to an empty GameObject in the scene. To parse the JSON file I’m using the SimpleJSON plugin (you can found it here: http://wiki.unity3d.com/index.php/SimpleJSON).
You can make your own system to store information about the clothes, as well to save the information about the character. The objective of this tutorial was only to show how you can implement a cloth system using only the objects of unity and to show the power of the SkinnedMeshRenderer.
For more information about how Unity works with meshes, check the documentation: http://docs.unity3d.com/Manual/comp-MeshGroup.html
- Tips for creating the models
This matter is very extensive, but here I will highlight some hints about creating the models.
– As said before, all models that will be used by the SkinnedMeshRenderer need to have the same Center of Origin.
– For the rigid elements that are added to bones, the Center of Origin need to be the same as the base of the bone that will receive the object.
Note here: I work only with Blender. Objects in Unity are aligned by their anchors (or center of origin), so you will need to check it in your modelling software.
– The clothes doesn’t need to be in the same file as the model, they only need to use the same armature (bones names).
– If you want to hide some body parts of the char, you need to “cut” your models into different objects. First, model you char as one object, them select the parts and separate them. All objects will retain the weight mappings.
It’s useful to create clothes. In Blender go to Edit mode, select the faces you want to use as base, duplicate it and then create a new object with those duplicated faces. Create your cloth from here. Don’t forget to check the Weight Mapping later.
– Its better to use only one material for clothes, to make it simple to change the material of the mesh later. If you need to have more than one material, you will need to make your code to work with multiples materials.
- Final Considerations:
– Can I use your models?
Yes, you can. I only warn you that they are old models, from when I was learning to modelling, so the topology isn’t good and the polys is a little high.
– When importing a model, what Animation Type of Rig I need to use?
Generic or Humanoid, both works. But you can have problems if you use an Humanoid model with a Generic model.
– How the mirror was made?
With a second camera (Mirror Camera) rendering to a texture (Target Texture property of the camera). Then the texture was applied to a 3D plane (Mirror).
– What software you’ve used to make the models?
Blender3d, version 2.72b. Any 3D modelling software that can work with rigging do the job.
– If I have problem implementing it with my own code, you will help me?
No. As I said in the beginning, this tutorial is for advanced developers. Khajiit helps if you have coin 😉
– Why a tutorial? Why do you not sell it as an asset?
Well, this module was only possible after reading a lot of others people talks about it. I needed only to join the pieces I’ve found to make it work. So, I will not sell it. But if someone wants to make a donation as a gratitude for my effort, this one will be very glad 😉
- Source Project