Everyone knows these 2 versions.
A basic character customiser lets you change:
- Body shape
- Face features
So let's see how we can set something like this up in Unity.
First we need to go into a 3D modelling package to set up a base body and Blendshapes/ShapeKeys
I'm working in MayaLT but will add Blender workflow.
Here's the base model I'll be working with. Not as low-poly as my usual work but this allows for nicer blendshape manipulation.
The Face and Body are two separate objects so it's easier to make blendshapes for.
They are both already rigged/skinned (I used Maya's basic skeleton and very slightly adjusted auto-skinning)
Let's set up a few blendshapes.
Duplicate the body and make some global adjustments.
I changed one copy to look more muscular, and another copy to look very skinny
Select both copies and the original and create a blendshape
Now you can adjust the body type on the original mesh using the Blendshape sliders
For Blender you can find the setting at Properties editor ‣ Object Data ‣ Shape Keys
Use the + icon to add a new Shape Key
Export the mesh (Check if the export includes Blendshapes!) and rig and bring it into Unity
Access Blendshapes in Unity
When you drop the exported model into the scene, the Skinned Mesh Renderer will have a Blendshapes array with all the shapes we added, with a value range of 0 to 100 percent
Adjusting from the Inspector at run-time
Controlling from UI
You can change the shape by setting the number in the inspector, but we want to do this from the UI.
Add a Slider for Body Shape
Now it's time to dive into scripting
SkinnedMeshRenderer.SetBlendShapeWeight(index in Blendshape, weight percentage);
To adjust the Blendshapes you need to use SetBlendShapeWeight on a Skinned Mesh
public SkinnedMeshRenderer BodyModel;
Declare a SkinnedMesh to drop the body model into
Now make a public function that takes a Float (the slider value)
public void SetBodySlider(float sliValue)
And set the Blendshape weight for the Muscular blendshape (0), and the Skinny blendshape (1).
The Skinny blendshape gets the inverted value so only one of the two blendshapes are active at a time
Set the slider to -100 to 100 (%) and add the right function to On Value Changed
Note: I'm letting the value go negative because Unity Clamps blendshapes between 0 and 100, so the negative value has no impact.
In Unity 2018.3+ the value can be unclamped, so you might want to clamp manually if you use that version
Adjusting the body isn't enough, so it's time to repeat the same steps for the face.
I duplicated the face 10 times and made adjustments to the eyes, ears, mouth, nose, and overall shape. This is just an example, you can change a lot more stuff of course!
Here are all the blendshapes on the exported model
public void SetSliderFace0(float sliValue)
Set the BlendShape weight of the FaceModel to the slider Value this time.
This time the Min value should be 0, because we are adding a single blendshape.
Repeat for the amount of shapes you have.
I added sliders for the first 4 Blendshapes in the array. As you can see you can combine multiple Blends for very different results.
Another way to customise is to scale Bone/Joint size.
public void SetBoneSize(float sliValue)
Bone.localScale = new Vector3(sliValue, sliValue , sliValue );
You can simply do this by attaching a slider to the LocalScale of selected bones
The values for scaling bones should be much lower, 1 is the base size so only minor differences are used.
Scaling bones shouldn't break any animations, so it's a nice extra.
Array of Hairstyles
Time for a haircut! I created 2 hairstyles and added them to the face bone.
public GameObject HairStyles;
The hairstyles go in an array of GameObjects.
public void SetHairStyle(float sliValue)
for (int i = 0; i < HairStyles.Length; i++)
I'm doing this by turning off the objects not selected by the slider, and turning on the on that is, there are better ways then keeping all objects active on the character model, but this is simplest.
For setting the index of hairstyle we want, the slider float value needs to be cast as an (int)
The slider for choices needs to be set to Whole Numbers.
Also make sure to set the Max value to the amount of styles you have in the array -1, or the code will go out of range
(You can dynamically set the size by adding it as a public slider and setting the max value to HairStyles.Length-1 in code)
Looks much better with hair!
Code link intermission!
Color customisation Shader
A very important part is of course choosing colors.
For this I'm using a modified version of the Color Mask Shader from an earlier tutorial.
Mask Shader on a plane next to the Mask used to seperate the Primary(R), Secondary(G), and Tertiary(B) colors
The shader has 6 colors (2 for Skin, Hair, and Eyes) and 3 sliders to move the position of the gradient between the 2 colors.
image.color = colorPicker.Color;
To select the colors from the UI I'm using toggles that take the ColorPicker.Color from the GitHub script when they are active (And a Toggle Group Component so only one is active at a time).
This material color is then set to the selected color.
public void SetSliderPrimaryColor(float sValue)
CharacterMaterial .SetFloat("_Weight1", sValue);
For the gradient weight sliders it's a very similar story to all the other sliders we made. Just link this up in the On Value Changed box.
Shader I used in this tutorial: PasteBin Link
Shrinkwrap modifier to make clothes/armor work with Blendshapes
When you change the shape of the body, the clothing/armor/ equipment modelled for the base body won't fit anymore.
Recreating the blendshapes on clothing manually is a ton of work. Luckily theres a modifier called ShrinkWrap that can make a mesh conform to the underlying mesh.
Select the Clothing mesh and the body mesh and create a ShrinkWrap (Closest Result)
The initial result looks bad because it's fully wrapped to the body mesh.
If you select Deform> Paint Weights > Shrinkwrap you can see the mesh is fully white.
By painting the parts that should stick out, darker you can make it look how you want.
In Blender the modifier has the same name
We can't use Shrinkwrap in Unity directly, so it's time to make a new blendshape for the clothing.
Duplicate the clothing mesh with no body blendshape active, this is a new base.
Now duplicate the mesh while the body blendshapes are active and create new blendshapes with the base mesh.
In script set the armor blendshapes at the same time as the body blendshapes.
Now the armor adjusts to the body!
I uploaded the customiser to Itch.io so you can check it out yourself :)
Thanks for reading!
PS: Files from the WEBGL Demo will be up soon