Skip to main content

Color Customization

Prerequisites

As mentioned on the Marketplace, this feature requires a solid understanding of 3D concepts and texturing.

You should already be familiar with how materials, material instances, UVs, and masking work in Unreal Engine.

To set up meshes that support color customization, we recommend starting from an existing working example — such as SK_ACC_Epic_HMN_Adult_M_Top_001.

We'll use this mesh to explain how the system works.

Material Setup

First, your mesh must be assigned a material — obviously.

Screenshot

However, for color customization to work, the material must expose color parameters that can be modified at runtime.

In our setup, we created a master material with predefined parameters, and then derived material instances from it for each mesh, like so:

Screenshot

Here’s a quick reminder of how those color parameters are defined in the master material:

Screenshot

The actual color logic is encapsulated in a Material Function called MF_ACC_ThreeLayerColor:

Screenshot

T_Base_Mask — Masking Texture

The T_Base_Mask, visible in the screenshot above, is a custom RGB mask texture used to define which parts of the mesh can change color.

Each channel (R, G, B) corresponds respectively to:

  • L1_Color
  • L2_Color
  • L3_Color

This mask must be manually created for each mesh, so if you're using your own meshes, you must author a suitable RGB mask texture to match the UV layout.

Quick Look at the C++ Logic

The default implementation used by ACCItemParamHandler_Default handles the color override logic.

Here’s a simplified example from the OnReceiveEquip method:

FACCParamHandlerResult UACCItemParamHandler_Default::OnReceiveEquip_Implementation(
UACCCreationComponent* CreationComponent, const FACCEquipParam& EquipParam)
{
...
// Apply user customization (e.g., override colors)
ApplyEquipCustom(CreationComponent, EquipParam);
}

That ultimately calls:

void UACCItemParamHandler_Default::ApplyCustomColor(USkeletalMeshComponent* Mesh, const FACCColorCustom& ColorCustom)
{
for (int32 Index = 0; Index < MaxColorSlots; ++Index)
{
const FName ParameterName = BuildColorParamName(Index);

if (!ColorCustom.Colors.IsValidIndex(Index))
{
UACCCoreLibraryStatics::ResetColorParameterValueOnMaterials(Mesh, ParameterName);
continue;
}

const FLinearColor& Color = ColorCustom.Colors[Index];
UACCCoreLibraryStatics::SetColorParameterValueOnMaterials(Mesh, ParameterName, Color);
}
}

Explanation

  • MaxColorSlots defines how many color layers are supported (default: 3).
  • For each index (0 to 2), it constructs a parameter name like "L1_Color", "L2_Color", etc.
  • It then applies the color defined in your ColorCustom.Colors[Index] to the mesh material.

If no color is defined at a given index, the system will reset that parameter.