Discord https://discord.com/invite/vMVE2kuwzV
Email Lindborgdev@gmail.com
Import notes
- Adjust light settings if needed
- Import Text Mesh Pro if prompted
- On Built-In you must download the Shader Graph package
- Check that LOD distances are correct for your project/target platform, LOD Bias 2 is recommended (higher LOD bias means distance for each LOD increases)
Modern Clothes Pack import notes
- Make sure to update to CC v2.2 or higher before importing
- To use the new clothes, update the apparel objects on the character prefabs to the new "plus" variants (also make sure characters placed in the scene don't use the old values)

General overview
To get an idea of how Character Customizer works, open CC_Showcase_Scene
-
CharacterParent
- Preset 1
- Preset 2
- Preset 3
- Preset 4
- Preset 5
- Preset 6
-
Camera and camera controller
-
UI_Parent which contains the CC_UI_Manager script
The difference between presets is the prefab (Human_Female.prefab or Human_Male.prefab) and the Character Name field on the CharacterCustomization (CC) component.
CC_UI_Manager is a script for swapping the preset characters under CharacterParent, handling drag customization update, playing UI sounds and some other things. It calls Physics.SyncTransforms every frame so don't put it in an actual gameplay scene.
When characters have a UI assigned in their CC component, the UI prefab will get instantiated at the CC_UI_Manager transform. If you don't want a UI to get spawned (if placing an NPC in a gameplay scene) UI should be left blank.
When the CC component Start() runs it calls the function Initialize() in CC_UI_Util at the root of the UI, which in turn runs the ICustomizerUI interface function InitializeUIElement() for every child component that implements the interface. This is how the UI elements (sliders, pickers etc) are linked to the character's CC script, and how they get updated from the save data.
The CC component contains almost all the functionality for changing properties and blendshapes, saving and loading and managing clothes and hair. The UI elements contain little functionality by themselves and just serve as a graphical interface for the main script.
Much of the customization in the CC component is designed around the class CC_Property. This class is used to define blendshapes, texture properties, float properties and color properties. Certain variables in a CC_Property may be unused depending on the use case.
- CC_Property
- propertyName is the blendshape name or the material property name
- stringValue stores a string, usually a reference to a resource (a texture)
- floatValue stores a float, for example a scalar value or a blendshape value
- materialIndex is the material index the property should be set on, the default -1 means all materials
- meshTag lets you set the property on a mesh renderer gameObject with a specific tag, empty string means all meshes
Character presets
scrObj_Presets is a list of names mapped to character data useful for creating default characters or storing NPCs. Every character should have a presets object assigned on them since this is how default data is stored. You can programatically add customized characters to the character's preset object by running SaveToPreset in CharacterCustomizer. There's a button in the default UI that does this.
For saving characters at runtime (a character that changes gear or other properties throughout the game) you should use SaveToJSON instead (or your own interpretation)
Instantiating a saved character
To spawn a saved character, it's a three step process:
- Get the character save data by name
- Get the prefab name (CharacterPrefab) from the character data and instantiate it
- Apply the character data
This is a minimal example, getting CC_SaveData depends on how your character was saved. You can get it from CharacterCustomization.json using SavePath, you can load it from a presets object, you can download it from a server etc. The instantiating and loading is more or less the same in every case.
UI elements
The included UI (UI_CC) is a pretty simple mix of prefab sliders and pickers. The main scripts are:
- Option_Slider has two modes, Blendshape and Scalar. It sets the blendshape value or scalar property with the assigned name. Range sets the min and max values of the slider. You can add this script to any slider.
- Option_Proportional_Sliders takes a list of properties (blendshape names) and creates one slider for each with a capped sum of 1. This is used for the head shapes to avoid extreme shapes. If the total sum exceeds 1 it subtracts the excess proportionally from the other sliders.
- Option_Color_Picker creates a popup color picker when clicked that sets a color property. Assign a property and an image (Picker Icon). You also need a button that triggers Option_Color_Picker.toggleSliders(). Example prefab: ColorPicker1.prefab
- Option_Tint_Buttons instantiates a color picker button per element in the Tints list. It needs a Grid Layout Group on the script game object.
-
Option_Picker has a list Objects and five modes - Blendshape, Texture, Hair, Color and Stencil:
-
Blendshape mode sets the value to 1 for the current index of Objects and 0 for the other indices.
-
Texture mode loads the resource from the current index of Objects and sets it as a property. In texture mode you can also use comma separated values if you need to set more than one texture with a single picker
-
Hair mode expects an integer "Slot" and sets Options automatically from the Hair scriptable object on the active character's customization script. The slot is the index of the scriptable object (more on this below)
-
Color mode sets the color property at index
-
Stencil is a special case used for more complex parameters like tattoos and make up. There is a separate "Stencil Options" list on the script where you can assign offset X and Y, scale X and Y as well as rotation and whether it's tintable. Check the Stencil case in Option_Picker.cs to get an idea of how that works.
-
Hair/Apparel scriptable objects
Clothes and hair are instantiated from data fetched from scriptable objects, scrObj_Apparel and scrObj_Hair respectively. These scriptable objects are assigned on the CC component under Apparel Tables and Hair Tables and there should be one table per category you want (categories are "Hair", "Beard", "Upper Body", "Footwear" etc). The two scriptable objects are similar but have some key differences.
scrObj_Apparel looks like this:
- Name should be a unique identifier for the item
- Mesh is the prefab containing the mesh and the skeleton and scripts and what not
- Add Copy Pose Script is useful if the skeletal hierarchy of the mesh is different from the character it is attached to. In standard cases the skeletons should be identical, meaning they can be merged to save performance, but in some cases you will want to have extra bones added for physics or some other purpose, and bone transforms will have to be manually copied
- Mask is an optional texture that I use to simplify the character workflow by being able to push in the vertices of the character's body based on the clothing that's equipped, to avoid clipping. There is an assortment of apparel masks in ../Characters/Human/Apparel/Apparel_Masks/
- Foot Offset is part of the body customization system technically (see below) and is used to offset the character from the ground depending on the shoes worn. You can also rotate the feet and toes (ball).
- Materials is a list of CC_Apparel_Material_Collection used for tinting. A "material collection" is:
- Label (a color or a description)
- Material Definitions A list of CC_Apparel_Material_Definition, which set properties found in Shader_Apparel (one element per material in the prefab):
- Material Override (overrides material assigned in the prefab)
- Main Tint (_Tint property in Shader_Apparel)
- Tint R (_Tint_R property in Shader_Apparel)
- Tint G (_Tint_G property in Shader_Apparel)
- Tint B (_Tint_B property in Shader_Apparel)
- Print (_Print property in Shader_Apparel)
- Icon is an optional icon used for the apparel menu
- Neck Shrink sets _Neck_Shrink in Shader_CC_Skin to shrink the neck similar to how Mask shrinks the body
- Hair Compress sets the compress blendshape which hair meshes have, used for shrinking compressing hair for hats
- Hides These Slots can be used for multi-slot apparel to remove other slots, for example if you equip a swimsuit, the main slot is 0, but adding 1 to this list will remove the currently equipped Lower Body item when the swimsuit is equipped
- Menu Category is the category it will appear under in the apparel UI
Then the scriptable object itself has:
- Skin Mask Property which is the name of the masking property in the skin shader
- Label which is the name of the type (Footwear, Upper Body etc) which could be used as an identifier
scrObj_Hair works similarly with some differences
- Shadow Map is (optionally) used to apply a shadow map on the character's head material to help blend the hair and the scalp, the property is defined in Skin Shadow Map Property on the scriptable object
- Tint Property is the color equivalent of Skin Shadow Map Property, used for tinting the scalp to match the hair color
If you want to add more clothes/hair, you just need to add the item to the appropriate object in /Characters/Human/Apparel/Scriptable_Objects or Hair/Scriptable_Objects.
For more details on how that works, check out setHair and setApparel in CharacterCustomization.cs
Body customization
Body customization is handled from the ModifyBone_Manager script. Blendshape properties that begin with "BodyCustomization" get hijacked in the CharacterCustomization setBlendshapeByName function and passed onto ModifyBone_Manager. In the characters bone hierarchies there are a bunch of ModifyBone scripts that do various things. Some set bone scale (waist size etc) and some create constaints for offsetting the bone transforms (shoulder width etc). Check out ModifyBone_Manager.cs for an overview of what each parameter does.
Facial animation
CC characters have facial bones for animation that can be activated via animator parameters. These bones are specifically made for translation-only animation. Rotating these bones is not recommended because blendshapes will "offset" the vertices pivot from the bone.
In the included animator there's parameters and blend trees for visemes and FACS shapes. To set expressions you simply do animator.SetFloat(parameter, value) on the character.
If you want something more clean, you can create your own blend trees, for example here is a LookAt blend tree:

I added three parameters: LookLeft and LookUp (-1 to 1), and LookAt (to control the strength).
Then I created a 2D directional blend tree with the two parameters (LookLeft, LookUp) and five fields:
- Motion field with FACS_000 for (0, 0)
- Direct blend tree with FACS_005 and FACS_012 for looking up (0, 1)
- Direct blend tree with FACS_002 and FACS_009 for looking down (0, -1)
- Direct blend tree with FACS_003 and FACS_011 for looking right (-1, 0)
- Direct blend tree with FACS_004 and FACS_010 for looking left (1, 0)
To control the look at, you would just call something like
animator.SetFloat("LookUp", lookUpValue) animator.SetFloat("LookLeft", lookLeftValue)
Randomizer
On the character's CharacterCustomization script you can assign a randomizer. There's a base scrObj_Randomizer class which has a virtual randomizeAll() which gets called in the UI. This function is overwritten in scrObj_Randomizer_Standard which is a randomizer designed for the CC characters specifically. It's somewhat complex but you should check out how it works.
Outfits
scrObj_Outfits is the outfits base class. It has virtual function GetRandomOutfit() which has to be implemented, and GetRandomApparel() which just picks a random clothing item and material selection from the input choices.
scrObj_Outfits_Standard is a child class of scrObj_Outfits designed for the CC characters that defines and randomizes outfits with a little more sophistication than just setting a random apparel item per slot.
The outfit object assigned on the CC component (Outfits_M or Outfits_F) has a list of outfits, which are lists of clothing combinations. The names (TShirt_01, Tank_Top_01...) are the same names as in the apparel objects assigned in the CC component.
In addition there is
- Default Chance (the % chance to equip DefaultApparel assigned on the CC component instead of an item from the outfits list, useful when you only want for example glasses a certain % of the time)
- Match Materials (tries to match the material of one slot to another slot. For example if you wanted to match lower body material with upper body, you would check Match Materials on the Lower Body element and set Index To Match to 0)


