Hello developers,
We are excited to announce that 3D Layered Clothing technology is now available!
Layered clothes are specially modeled 3D assets that any avatar can wear with any combination of other layered accessories. Layered clothing naturally layers and stretches over an avatar body and other layered clothing items without clipping or breaking.
You design Layered Clothing in Maya or Blender, import them into Roblox Studio and apply it to an avatar body using WrapLayer
and WrapTarget
. These two new instances drive the technology behind Layered Clothing.
This post contains details on the structure of Layered Clothing and how to enable, create and add Layered Clothing in your own experience.
Experience Note: Layered clothes will not be available on the Avatar Shop Catalog or the Avatar Editor at this time. Similarly, accessories and clothes obtained or equipped in layered clothing experiences will not persist outside of that experience during this stage of release.
Roblox discourages developers from engaging in monetization related to layered clothing assets within experiences at this time.
Experiences with Layered Clothing will generally be more performance intensive. Please report any performance related bugs along with any specifications on devices and hardware in the forum post below.
Layered Clothing Structure
Layered clothing are 3D accessories that connect to the body parts of an avatar using attachments.
Layered clothing fits and forms over avatars and accessories because of additional geometry that you create during the modelling process. These invisible inner and outer surfaces, or the Inner Cage and Outer Cage, act similarly to a collision box and ensure that one clothing item doesn’t clip through another in 3D space.
Layered Clothing Asset Requirements describes specific details and requirements for modelling Layered clothes in Blender or Maya.
Setting Inner and Outer Cages in Studio
If the 3D asset is properly modelled, the asset will be imported into Studio as a MeshPart with one of the following instances that define the cages:
-
WrapTarget
defines the first outer surface that accessories can layer on. In the case of layered clothing, WrapTargets almost always refer to an avatar’s Outer Cage. The Outer Cage is set by the CageMeshID. -
WrapLayer
defines the Inner and Outer Cage of the parented accessory so the accessory knows how to sit on top of an existing surface, as well as provide an outer surface for additional layers above it. The Inner Cage is set by the ReferenceMeshID.
Creating Layered Clothing
Model your layered clothing in Blender and Maya and export as a .fbx. A layered clothing asset must implement the following requirements:
- The asset must contain an inner mesh cage and an outer mesh cage.
- Cage layers within an asset must have the same UV maps.
- The asset must be weighted and parented to the correct bone or armature.
For details on prepping a 3D asset for use in layered clothing, refer to Layered Accessory Asset Requirements.
Sample 3D Assets and Project Files
Reference files are available and include the following:
- Clothing_Editor_Baseplate.rbxl - A space with over 100 layered clothing accessories to explore and test
- Various accessories (.fbx) - Studio-ready 3D accessory models. (See below)
Expand the table below for accessory details.
View Accessories
Accessory | Accessory Name | Accessory ID | Accessory Type |
---|---|---|---|
Tshirt_ArmyPrint_001 | 7192457690 | Tshirt | |
TShirt_TyeDye_001 | 6984732580 | TShirt | |
TShirt_LongSleeve_Raglan_001 | 7178740556 | Shirt | |
Shirt_LongSleeve_Flannel_001 | 7178744611 | Shirt | |
Jacket_Hoodie_001 | 6984765766 | Jacket | |
Jacket_PufferCoat_001 | 7192543873 | Jacket | |
Pants_CargoPants_001 | 6984740059 | Pants | |
Pants_Female_Jeans_001 | 7192668209 | Pants | |
Shorts_Cargo_001 | 7192683061 | Pants | |
Shorts_Female_Jeans_001 | 7192686536 | Shorts | |
Skirt_Tennis_001 | 7192686536 | DressSkirt | |
Shoes_WorkBoots_001 | 7193170137/7193171232 | LeftShoe/RightShoe | |
Shoes_Skate_001 | 7192850635/7192852086 | LeftShoe/RightShoe | |
Male_Hair_003 | 7193405096 | Hair | |
Male_Hair_004 | 7193419595 | Hair | |
Hair_Female_004 | 7193448988 | Hair | |
Hair_Female_005 | 7193451306 | Hair |
Enabling Layered Clothing in Experiences
First step is to enable the Studio Beta Feature. In the File menu, select Beta Features and enable 3D Layered Clothing.
Layered clothing requires enabling LoadCharacterLayeredClothing
to allow avatars to equip 3D accessories. To enable layered clothing rendering in your experience:
- In the Explorer, select StarterPlayer and navigate to the Character section in the Properties window.
Set LoadCharacterLayeredClothing
property to Enabled.
Importing Layered Clothing Creations
Import the .fbx into Studio using the Avatar Importer plugin. Make sure that the .fbx and the associated texture .pngs are in the same directory. To import a layered clothing file:
-
In the Plugins tab, select Avatar Importer
-
Select Custom
-
Select your .fbx file. The asset populates in the workspace as a
MeshPart
named FBXImportGeneric.
Optional: Add PBR textures to your Asset
Many of the provided asset files include additional PBR textures for realistic lighting and surface effects. Add these texture files to to a MeshPart using SurfaceAppearance:
Upload the associated .PNG files using the Asset Manager.
Note: Importing assets requires the experience to be published first.Select the Tshirt_001 MeshPart inside the FBXImportGeneric model and add a SurfaceAppearance object.
Set the appearance maps in SurfaceAppearance with the corresponding texture IDs created. Use the filename suffixes to appropriately map the textures:
- ColorMap: “_DIF”
- MetalnessMap: “_MET”
- NormalMap: “_NOR”
- RoughnessMap: “_RGH”
Setting the MeshPart as an Accessory
Organize the MeshPart
as an Accessory instance to be equipped by an avatar:
-
Add an Accessory instance in the Workspace with the name of your layered clothing accessory “Tshirt_001”.
-
Drag and drop the Tshirt_001
MeshPart
into the Accessory instance to parent theMeshPart
. -
Rename the “Tshirt_001”
MeshPart
to “Handle” to follow the standard Accessory naming convention. -
Verify that the “Handle”
MeshPart
has theWrapLayer
Instance.
-
Add an Attachment within your Handle.
-
Rename the Attachment “BodyFrontAttachment” to ensure that it gets attached to the corresponding body part. See attachment points for a list of valid attachment names.
Apply Layered Clothing to an Avatar
There are two primary ways to equip accessories in this developer release:
- Equip the accessory without an Asset ID through Humanoid:AddAccessory()
- Equip the accessory using an Asset ID through the HumanoidDescription System.
In a future release, you will be able to upload layered clothes assets to generate your own Asset IDs.
Equipping Without an Asset ID
This method should be used for equipping a layered clothing accessory if an Asset ID is not yet available. To equip your accessory in-game:
-
Drag and drop the Tshirt_001 Accessory in ServerStorage.
-
In ServerScriptStorage, add a Script with the following:
local myAccessoryAsset = "Tshirt_001" --replace Tshirt_001 with the name of your accessory
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAppearanceLoaded:Connect(function(character)
while nil == character.Parent do
wait()
end
local humanoid = character:WaitForChild("Humanoid")
if humanoid then
humanoid:AddAccessory(game.ServerStorage:WaitForChild(myAccessoryAsset))
end
end)
end)
Equipping With an Asset ID
HumanoidDescription
describes all the assets equipped by a Humanoid character. The AccessoryBlob is a table of all accessories equipped by the Humanoid and can be edited directly in the HumanoidDescription Properties panel or programmatically through HumanoidDescription.SetAccessories().
An Asset ID can be obtained by uploading the asset or using an existing Catalog Asset ID. Until uploading layered clothing is available, use an existing Asset ID in the code samples or the example assets.
Equipping via Properties Panel
To edit the Accessory Blob in the Properties Panel and equip layered clothing:
- Select the Workspace and Add “HumanoidDescription”.
In Properties, set the “Accessory Blob” property with the following format:
[{"AssetId": 6984765766, "Order":1, "AccessoryType":"Jacket", "Puffiness":0.5}]
In the case of multiple accessories, use the following format:
[{"Order":1, "AccessoryType":"Jacket", "Puffiness":0.5, "AssetId":6984765766},
{"Order":2, "AccessoryType":"Sweater", "Puffiness":0.7, "AssetId":6984771334}]
Note: Puffiness is an optional key here that affects the volume of the clothing item.
Now that a HumanoidDescription
has been created, you can use the following code sample in a Script in the Workspace to apply the HumanoidDescription
to all players when they are spawned:
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAppearanceLoaded:Connect(function(character)
while nil == character.Parent do
wait()
end
local humanoid = character:WaitForChild("Humanoid")
if humanoid then
humanoid:ApplyDescription(game.Workspace.HumanoidDescription)
end
end)
end)
Since HumanoidDescription only contains data for a single accessory, the player spawns as a default blocky character with one accessory equipped.
Equipping Programmatically
To equip layered clothing via through HumanoidDescription.SetAccessories():
-
In ServerScriptService, create a Script.
-
Copy the sample below and select Play.
-- Prevent the experience from autoloading the player before we apply accessories
game.Players.CharacterAutoLoads = false
-- This table sets the order of layered clothing items. Higher numbers will layer on top of lower numbers.
local DefaultLayeredClothingOrder = {
[Enum.AccessoryType.LeftShoe] = 3,
[Enum.AccessoryType.RightShoe] = 3,
[Enum.AccessoryType.Pants] = 4,
[Enum.AccessoryType.Shorts] = 5,
[Enum.AccessoryType.DressSkirt] = 6,
[Enum.AccessoryType.TShirt] = 7,
[Enum.AccessoryType.Shirt] = 8,
[Enum.AccessoryType.Sweater] = 9,
[Enum.AccessoryType.Jacket] = 10,
[Enum.AccessoryType.Hair] = 11,
}
-- Create an entry for the new layered clothing accessory (an orange jacket):
local lcAccessoryData = {}
lcAccessoryData["AccessoryType"] = Enum.AccessoryType.Jacket
lcAccessoryData["AssetId"] = 6984765766 -- Orange jacket
lcAccessoryData["Order"] = DefaultLayeredClothingOrder[Enum.AccessoryType.Jacket]
-- SetAccessories expects a table of accessory entries:
local accessories = {}
accessories[1] = lcAccessoryData
-- Load the player with the new accessories
game.Players.PlayerAdded:Connect(function(player)
-- Get the HumanoidDescription from the UserId and clone
local currentHumanoidDescription = game.Players:GetHumanoidDescriptionFromUserId(player.UserId)
local newHumanoidDescription = currentHumanoidDescription:Clone()
-- Apply the new description to the humanoid:
newHumanoidDescription:SetAccessories(accessories, --[[includeRigidAccessories = ]] false)
player:LoadCharacterWithHumanoidDescription(newHumanoidDescription)
end)
Note: HumanoidDescription also supports rigid accessories. Use HumanoidDescription.GetAccessories(true) and HumanoidDescription.SetAccessories(Accessory Table, true) parameters to include rigid accessories.
HumanoidDescription can also be applied to NPCs with a HumanoidDescription using Players:CreateHumanoidModelFromDescription()
.