Skip to content
avatar-ugc logo

Avatar & UGC Customization

avatar-ugc

Programmatically apply UGC (User-Generated Content) to characters including clothing, accessories, and avatar customization. Use when dressing NPCs, building avatar editors, or creating character customization systems.

SKILL.md

Full skill instructions

Avatar & UGC Customization

Quick Reference Links

Official Documentation:

Wiki References:


Two Approaches to Avatar Customization

1. HumanoidDescription (Recommended)

Best for: Comprehensive avatar changes, player characters, loading from asset IDs

2. Direct Clothing Instances

Best for: NPCs, simple clothing changes, runtime modifications


HumanoidDescription Approach

Key Properties

PropertyTypeDescription
ShirtnumberShirt asset ID
PantsnumberPants asset ID
GraphicTShirtnumberT-shirt asset ID
FacenumberFace asset ID
HeadnumberHead mesh asset ID
TorsonumberTorso mesh asset ID
LeftArm, RightArmnumberArm mesh asset IDs
LeftLeg, RightLegnumberLeg mesh asset IDs
HatAccessorystringComma-separated hat asset IDs
HairAccessorystringComma-separated hair asset IDs
FaceAccessorystringComma-separated face accessory IDs
NeckAccessorystringComma-separated neck accessory IDs
ShouldersAccessorystringComma-separated shoulder accessory IDs
FrontAccessorystringComma-separated front accessory IDs
BackAccessorystringComma-separated back accessory IDs
WaistAccessorystringComma-separated waist accessory IDs

Creating HumanoidDescription

-- Method 1: Create new empty description
local humanoidDescription = Instance.new("HumanoidDescription")

-- Method 2: Get from existing character
local function getDescriptionFromCharacter(character)
    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if humanoid then
        return humanoid:GetAppliedDescription()
    end
    return nil
end

-- Method 3: Get from player's avatar
local Players = game:GetService("Players")
local function getDescriptionFromUserId(userId)
    local success, description = pcall(function()
        return Players:GetHumanoidDescriptionFromUserId(userId)
    end)
    return success and description or nil
end

-- Method 4: Get from outfit ID
local function getDescriptionFromOutfit(outfitId)
    local success, description = pcall(function()
        return Players:GetHumanoidDescriptionFromOutfitId(outfitId)
    end)
    return success and description or nil
end

Modifying HumanoidDescription

local function customizeDescription(humanoidDescription)
    -- Set clothing (use asset IDs, not content URLs)
    humanoidDescription.Shirt = 6536023867        -- Shirt asset ID
    humanoidDescription.Pants = 6536027646        -- Pants asset ID
    humanoidDescription.GraphicTShirt = 1711661   -- T-shirt asset ID

    -- Set accessories (comma-separated strings for multiple)
    humanoidDescription.HatAccessory = "2551510151,2535600138"
    humanoidDescription.HairAccessory = "4819740796"
    humanoidDescription.FaceAccessory = ""
    humanoidDescription.BackAccessory = "4447084948"

    -- Set body parts
    humanoidDescription.Face = 86487700
    humanoidDescription.Head = 0  -- 0 = default

    -- Set body colors
    humanoidDescription.HeadColor = Color3.fromRGB(234, 184, 146)
    humanoidDescription.TorsoColor = Color3.fromRGB(234, 184, 146)
    humanoidDescription.LeftArmColor = Color3.fromRGB(234, 184, 146)
    humanoidDescription.RightArmColor = Color3.fromRGB(234, 184, 146)
    humanoidDescription.LeftLegColor = Color3.fromRGB(234, 184, 146)
    humanoidDescription.RightLegColor = Color3.fromRGB(234, 184, 146)

    -- Set scale
    humanoidDescription.HeightScale = 1.0
    humanoidDescription.WidthScale = 1.0
    humanoidDescription.HeadScale = 1.0
    humanoidDescription.BodyTypeScale = 0.0  -- 0 = blocky, 1 = realistic
    humanoidDescription.ProportionScale = 0.0

    return humanoidDescription
end

Setting Multiple Accessories with SetAccessories

local function setMultipleAccessories(humanoidDescription)
    local accessories = {
        {
            Order = 1,
            AssetId = 6984769289,
            AccessoryType = Enum.AccessoryType.Hat
        },
        {
            Order = 2,
            AssetId = 6984767443,
            AccessoryType = Enum.AccessoryType.Hair
        },
        {
            Order = 3,
            AssetId = 4447084948,
            AccessoryType = Enum.AccessoryType.Back
        }
    }

    humanoidDescription:SetAccessories(accessories, false)  -- false = don't include rigid accessories
end

Applying HumanoidDescription

-- Apply to existing character
local function applyToCharacter(character, humanoidDescription)
    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if humanoid then
        humanoid:ApplyDescription(humanoidDescription)
    end
end

-- Apply to NPC
local function dressNPC(npc, shirtId, pantsId, hatIds)
    local humanoid = npc:FindFirstChildOfClass("Humanoid")
    if not humanoid then return end

    local description = humanoid:GetAppliedDescription()
    description.Shirt = shirtId or description.Shirt
    description.Pants = pantsId or description.Pants
    description.HatAccessory = hatIds or description.HatAccessory

    humanoid:ApplyDescription(description)
end

-- Load character with description (for spawning)
local function spawnWithDescription(player, humanoidDescription)
    player:LoadCharacterWithHumanoidDescription(humanoidDescription)
end

Direct Clothing Instances (Classic Method)

Apply Shirt to Character/​NPC

local function applyShirt(character, shirtAssetId)
    -- Find or create Shirt instance
    local shirt = character:FindFirstChildOfClass("Shirt")
    if not shirt then
        shirt = Instance.new("Shirt")
        shirt.Parent = character
    end

    -- Set template (use rbxassetid:// format)
    shirt.ShirtTemplate = "rbxassetid://" .. shirtAssetId
end

Apply Pants to Character/​NPC

local function applyPants(character, pantsAssetId)
    local pants = character:FindFirstChildOfClass("Pants")
    if not pants then
        pants = Instance.new("Pants")
        pants.Parent = character
    end

    pants.PantsTemplate = "rbxassetid://" .. pantsAssetId
end

Apply T-Shirt to Character/​NPC

local function applyTShirt(character, tshirtAssetId)
    local tshirt = character:FindFirstChildOfClass("ShirtGraphic")
    if not tshirt then
        tshirt = Instance.new("ShirtGraphic")
        tshirt.Parent = character
    end

    tshirt.Graphic = "rbxassetid://" .. tshirtAssetId
end

Apply Complete Outfit

local function applyOutfit(character, outfit)
    -- outfit = { shirt = id, pants = id, tshirt = id }

    if outfit.shirt then
        applyShirt(character, outfit.shirt)
    end

    if outfit.pants then
        applyPants(character, outfit.pants)
    end

    if outfit.tshirt then
        applyTShirt(character, outfit.tshirt)
    end
end

-- Usage
applyOutfit(npc, {
    shirt = 6536023867,
    pants = 6536027646,
    tshirt = 1711661
})

Loading Accessories with InsertService

local InsertService = game:GetService("InsertService")

-- IMPORTANT: Can only load assets accessible to experience creator
local function loadAccessory(accessoryAssetId)
    local success, model = pcall(function()
        return InsertService:LoadAsset(accessoryAssetId)
    end)

    if success and model then
        local accessory = model:FindFirstChildOfClass("Accessory")
        if accessory then
            accessory.Parent = nil  -- Remove from model container
            model:Destroy()
            return accessory
        end
        model:Destroy()
    end

    return nil
end

-- Apply loaded accessory to character
local function giveAccessory(character, accessoryAssetId)
    local accessory = loadAccessory(accessoryAssetId)
    if accessory then
        local humanoid = character:FindFirstChildOfClass("Humanoid")
        if humanoid then
            humanoid:AddAccessory(accessory)
        end
    end
end

AvatarEditorService (Catalog Integration)

Get Item Details

local AvatarEditorService = game:GetService("AvatarEditorService")

local function getItemDetails(assetId)
    local success, details = pcall(function()
        return AvatarEditorService:GetItemDetails(assetId, Enum.AvatarItemType.Asset)
    end)

    if success then
        return {
            name = details.Name,
            assetType = details.AssetType,
            price = details.Price,
            isOwned = details.IsOwned,
            isFavorited = details.IsFavorited,
            creatorId = details.CreatorTargetId,
            creatorName = details.CreatorName
        }
    end

    return nil
end

Get Player's Inventory

local function getPlayerInventory(player, assetTypes)
    -- assetTypes = array of Enum.AvatarAssetType
    local success, inventory = pcall(function()
        return AvatarEditorService:GetInventory(assetTypes)
    end)

    if success then
        return inventory:GetCurrentPage()
    end

    return {}
end

-- Example: Get player's hats
local hatTypes = {Enum.AvatarAssetType.Hat}
local playerHats = getPlayerInventory(player, hatTypes)

Get Outfit Details

local function getOutfitDetails(outfitId)
    local success, details = pcall(function()
        return AvatarEditorService:GetOutfitDetails(outfitId)
    end)

    return success and details or nil
end

Complete NPC Dressing System

local Players = game:GetService("Players")

local NPCOutfits = {
    Guard = {
        shirt = 6536023867,
        pants = 6536027646,
        hats = "2551510151",
        bodyColors = {
            head = Color3.fromRGB(234, 184, 146),
            torso = Color3.fromRGB(234, 184, 146)
        }
    },
    Merchant = {
        shirt = 398633610,
        pants = 398635927,
        tshirt = 0,
        hats = "4819740796"
    }
}

local function createDressedNPC(npcModel, outfitName)
    local outfit = NPCOutfits[outfitName]
    if not outfit then return end

    local humanoid = npcModel:FindFirstChildOfClass("Humanoid")
    if not humanoid then return end

    -- Get current description or create new one
    local description = humanoid:GetAppliedDescription()

    -- Apply outfit
    if outfit.shirt then
        description.Shirt = outfit.shirt
    end
    if outfit.pants then
        description.Pants = outfit.pants
    end
    if outfit.tshirt then
        description.GraphicTShirt = outfit.tshirt
    end
    if outfit.hats then
        description.HatAccessory = outfit.hats
    end

    -- Apply body colors
    if outfit.bodyColors then
        if outfit.bodyColors.head then
            description.HeadColor = outfit.bodyColors.head
        end
        if outfit.bodyColors.torso then
            description.TorsoColor = outfit.bodyColors.torso
        end
        -- ... etc for other body parts
    end

    -- Apply the description
    humanoid:ApplyDescription(description)
end

UGC Catalog Search (Server-Side)

local AvatarEditorService = game:GetService("AvatarEditorService")

-- Search catalog for items
local function searchCatalog(keyword, assetType, sortType)
    local searchParams = CatalogSearchParams.new()
    searchParams.SearchKeyword = keyword
    searchParams.AssetTypes = {assetType}
    searchParams.SortType = sortType or Enum.CatalogSortType.Relevance

    local success, results = pcall(function()
        return AvatarEditorService:SearchCatalog(searchParams)
    end)

    if success then
        return results:GetCurrentPage()
    end

    return {}
end

-- Example: Search for hats
local hats = searchCatalog("crown", Enum.AvatarAssetType.Hat)
for _, hat in ipairs(hats) do
    print(hat.Name, hat.Id)
end

AccessoryType Enum Reference

Enum ValueDescription
Enum.AccessoryType.HatHats, helmets
Enum.AccessoryType.HairHair styles
Enum.AccessoryType.FaceGlasses, masks
Enum.AccessoryType.NeckNecklaces, scarves
Enum.AccessoryType.ShoulderShoulder pads
Enum.AccessoryType.FrontFront accessories
Enum.AccessoryType.BackBackpacks, wings
Enum.AccessoryType.WaistBelts, tails
Enum.AccessoryType.TShirtLayered t-shirts
Enum.AccessoryType.ShirtLayered shirts
Enum.AccessoryType.PantsLayered pants
Enum.AccessoryType.JacketLayered jackets
Enum.AccessoryType.SweaterLayered sweaters
Enum.AccessoryType.ShortsLayered shorts
Enum.AccessoryType.LeftShoeLeft shoe
Enum.AccessoryType.RightShoeRight shoe
Enum.AccessoryType.DressSkirtDresses/​skirts

Important Considerations

Asset ID vs Content ID

  • Asset ID: The numeric ID (e.g., 6536023867)
  • Content ID: The full URL format (e.g., rbxassetid://6536023867)
  • HumanoidDescription properties use Asset IDs (numbers)
  • Shirt/​Pants/​ShirtGraphic templates use Content IDs (strings)

Security & Permissions

  • InsertService:LoadAsset() only works with assets accessible to the experience creator
  • For UGC items from other creators, use HumanoidDescription with asset IDs instead
  • Player inventory access requires appropriate permissions

Classic vs Layered Clothing

  • Classic Clothing: Shirt, Pants, ShirtGraphic (2D textures)
  • Layered Clothing: 3D clothing that deforms with the avatar body
  • Layered clothing uses AccessoryType values like TShirt, Jacket, Sweater

Best Practices

  1. Always wrap asset loading in pcall() for error handling
  2. Cache HumanoidDescriptions when making multiple changes
  3. Use GetAppliedDescription() to preserve existing appearance when making partial changes
  4. For NPCs, apply description once after all changes rather than multiple times

Checklist for Avatar Customization

  • Determine approach (HumanoidDescription vs Direct Instances)
  • Collect asset IDs for clothing/​accessories
  • Handle pcall for all async operations
  • Test with R6 and R15 rigs
  • Consider body colors and scale
  • Verify asset permissions for InsertService usage
  • Cache descriptions for performance

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View