Creating a Simple Character Customiser using Blendshapes(Shape Keys)
Everyone's favourite part of starting an RPG (don't correct me :D ) is customising your own character.

Everyone knows these 2 versions.

A basic character customiser lets you change:

  • Body shape
  • Face features
  • Hair
  • Colors

So let's see how we can set something like this up in Unity.

Base Model

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)

Body Blendshapes

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

Blender


For Blender you can find the setting at  Properties editor ‣ Object Data ‣ Shape Keys 

Use the + icon to add a new Shape Key

(Link to ShapeKey Workflow from Blender Documentation) 

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)
{
        BodyModel.SetBlendShapeWeight(0, sliValue);
       BodyModel.SetBlendShapeWeight(1, -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


Face Blendshapes

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)
{
 FaceModel.SetBlendShapeWeight(0, 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.

Scaling Bones

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++)
    {
         HairStyles[i].SetActive(false);
      }
    HairStyles[(int)sliValue].SetActive(true);
}


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!

Here's a link to the code up to this point (PasteBin) 

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.

And this script for a color picker from SnapShot Games on Github 

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;
CharacterMaterial.SetColor(ColorName, 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.

Blender

In Blender the modifier has the same name

ShrinkWrap Manual from Blender Documentation 


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!

WEBGL Demo


Link To WEBGL Demo On Itch.io 

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


By becoming a patron, you'll instantly unlock access to 107 exclusive posts
205
Images
1
Poll
21
Writings
By becoming a patron, you'll instantly unlock access to 107 exclusive posts
205
Images
1
Poll
21
Writings
Tier Benefits
Recent Posts