Avatar in-experience creatie

*Deze inhoud is vertaald met behulp van AI (bèta) en kan fouten bevatten. Klik hier om deze pagina in het Engels te bekijken.

Je kunt een ervaring publiceren die spelers in staat stelt om avatars in realtime te maken, aan te passen en aan te schaffen, naast in-experience make-up creatie. Wanneer deze aangepaste items worden aangeschaft, worden ze direct opgeslagen in de Roblox-inventaris van de speler, waardoor spelers ze kunnen uitrusten en dragen in andere ervaringen.

Ervaringseigenaren die in-experience avatarcreatie implementeren, profiteren van Marketplace commissies als de uitgever van het avataritem, terwijl de speler die het maakt de maker van het item is. Als een asset die in-experience is gemaakt, wordt geïnspecteerd, biedt het item een link naar de oorspronkelijke ervaring waarin het is gemaakt.

Je kunt in-experience creatie testen in de Avatar Creator demo van Roblox.

Hoe in-experience creatie te implementeren

Gebruik de volgende instructies en codeverwijzingen om je eerste in-experience avatarcreatieproject te maken. De volgende instructies gebruiken een basislichaam Model dat spelers kunnen aanpassen en wijzigen voordat ze het publiceren.

Voordat je begint, maak jezelf vertrouwd met het volgende:

  • Avatar modellen — De volgende implementatie vereist het importeren van een basislichaam dat voldoet aan de 15-deel specificaties van Roblox. Dit Model dient als basis voor aanvullende gebruikersaanpassing en -wijziging.
    • Het basislichaam moet voldoen aan de Avatar lichaamsrichtlijnen van Roblox, inclusief het minimum aantal FACS-controles voor gezichtsrigging.
  • Avatar creatietokens — Ervaringen die avatarcreatie implementeren, vereisen ten minste één creatietoken. Deze tokens vereisen Robux om aan te schaffen en stellen je in staat om prijzen en andere verkoopinstellingen voor aankopen in-experience in te stellen.
  • API-klassen
    • AvatarCreationService — Behandelt het vragen om avatarcreatie en validatie.
    • EditableImage — Behandelt runtime creatie en manipulatie van texturen.
    • EditableMesh — Behandelt runtime manipulatie van mesh-geometrie.
    • WrapDeformer — Behandelt runtime manipulatie van onzichtbare buitenste kooi-geometrie die avatarpersonages in staat stelt om 3D-kleding te dragen.

Importeer een basislichaam

Het basislichaam fungeert als de initiële basis die gebruikers kunnen aanpassen en bewerken. Je kunt je eigen Model gebruiken of een aangepast asset importeren met de Importer en instellen via Avatar Setup.

Basislichamen moeten voldoen aan de avatar specificaties van Roblox en moeten componenten bevatten zoals de 15 MeshPart instanties die 6 lichaamsdelen vormen: hoofd, torso, linkerarm, linkerbeen, rechterarm en rechterbeen, evenals andere avatarcomponenten.

Voor referenties en voorbeelden van goed geconfigureerde avatarlichamen, zie Avatar referenties.

Implementeer bewerkings-API's

Om een systeem te ontwikkelen waarin gebruikers de MeshPart instanties op een avatar in jouw ervaring kunnen bewerken voor creatie, gebruik EditableImage voor textuurbewerking, EditableMesh voor mesh-bewerking, en WrapDeformer voor het behouden van skinning en FACS-gegevens tijdens mesh-bewerkingen.

  1. Nadat je je basislichaam hebt geïmporteerd, gebruik je het volgende script om je EditableImages, EditableMeshes, en WrapDeformers in te stellen.

    local AssetService = game:GetService("AssetService")
    local function setupBodyPart(meshPart, wrapTarget)
    -- Maak en koppel een WrapDeformer aan de MeshPart
    local wrapDeformer = Instance.new("WrapDeformer")
    wrapDeformer.Parent = meshPart
    -- Maak een bewerkbare mesh voor de kooi-mesh van het wrapdoel
    local cageEditableMesh: EditableMesh =
    AssetService:CreateEditableMeshAsync(Content.fromUri(wrapTarget.CageMeshId), {
    FixedSize = true,
    })
    -- Wijs de kooi-mesh toe aan de WrapDeformer
    wrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))
    end
    local function setupRigidMesh(meshPart)
    -- Maak een bewerkbare mesh van de originele MeshPart
    local editableMesh = AssetService:CreateEditableMeshAsync(Content.fromUri(meshPart.MeshId), {
    FixedSize = true,
    })
    -- Genereer een nieuwe MeshPart van de bewerkbare mesh
    local newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh))
    -- Kopieer grootte, positie en textuur van de originele MeshPart
    newMeshPart.Size = meshPart.Size
    newMeshPart.CFrame = meshPart.CFrame
    newMeshPart.TextureContent = meshPart.TextureContent
    -- Pas de nieuwe MeshPart toe op de originele
    meshPart:ApplyMesh(newMeshPart)
    end
    local function setupMeshTexture(meshPart, textureIdToEditableImageMap)
    -- Als EditableImage al bestaat voor deze TextureID, hergebruik deze in plaats van een nieuwe te maken
    if textureIdToEditableImageMap[meshPart.TextureID] then
    meshPart.TextureContent =
    Content.fromObject(textureIdToEditableImageMap[meshPart.TextureID])
    return
    end
    -- Maak een nieuwe EditableImage en pas deze toe als de textuurinhoud
    local editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(meshPart.TextureID))
    textureIdToEditableImageMap[meshPart.TextureID] = editableImage
    meshPart.TextureContent = Content.fromObject(editableImage)
    end
    local function setupModel(model)
    -- Kaart voor het hergebruiken van EditableImage-instanties op basis van textuur-ID
    local textureIdToEditableImageMap = {}
    for _, descendant in model:GetDescendants() do
    if not descendant:IsA("MeshPart") then
    continue
    end
    -- Configureer MeshPart op basis van de aanwezigheid van WrapTarget
    -- Als WrapTarget aanwezig is, voeg een WrapDeformer-kind toe met een EditableMesh
    -- Anders, pas EditableMesh direct toe op de MeshPart
    local wrapTarget = descendant:FindFirstChildOfClass("WrapTarget")
    if wrapTarget then
    setupBodyPart(descendant, wrapTarget)
    else
    setupRigidMesh(descendant)
    end
    -- Configureer de EditableImage voor de MeshPart
    setupMeshTexture(descendant, textureIdToEditableImageMap)
    end
    end
  2. Maak EditableImage tools waarmee spelers de kleur kunnen wijzigen, tekenen of stickers aan je basislichaam kunnen toevoegen. Je kunt API's gebruiken zoals DrawImage(), DrawRectangle(), WritePixelsBuffer().

    • Voor geavanceerde transformaties, stelt DrawImageTransformed() je in staat om positie, rotatie en schaal op te geven bij het tekenen van de ene EditableImage op de andere. Evenzo werkt DrawImageProjected() veel zoals DrawImage(), maar projecteert de getekende afbeelding correct als de EditableImage instantie wordt gebruikt met een MeshPart.

      local function recolorTexture(
      meshPart: MeshPart,
      color: Color3
      )
      local bodyPartTexture = AssetService:CreateEditableImageAsync(meshPart.TextureID)
      meshPart.TextureContent = Content.fromObject(bodyPartTexture)
      bodyPartTexture:DrawRectangle(
      Vector2.new(0, 0),
      bodyPartTexture.Size,
      color,
      0,
      Enum.ImageCombineType.Overwrite
      )
      end
      local function applySticker(
      meshPart: MeshPart,
      textureCoordinate: Vector2,
      stickerId: TextureId
      )
      local bodyPartTexture = AssetService:CreateEditableImageAsync(meshPart.TextureID)
      meshPart.TextureContent = Content.fromObject(bodyPartTexture)
      local stickerTexture = AssetService:CreateEditableImageAsync(stickerId)
      bodyPartTexture:DrawImage(textureCoordinate, stickerTexture, Enum.ImageCombineType.BlendSourceOver)
      end
      local function applyStickerProjected(
      meshPart: MeshPart,
      targetMesh: EditableMesh,
      stickerId: TextureId,
      raycastHitPos: Vector3
      )
      local bodyPartTexture = AssetService:CreateEditableImageAsync(meshPart.TextureID)
      local relativePos = meshPart.CFrame:PointToWorldSpace(raycastHitPos)
      local direction = (workspace.CurrentCamera.CFrame.Position - relativePos).Unit
      local projectionParams: ProjectionParams = {
      Direction = meshPart.CFrame:VectorToObjectSpace(direction),
      Position = meshPart.CFrame:PointToObjectSpace(relativePos),
      Size = Vector3.new(1, 1, 1),
      Up = meshPart.CFrame:VectorToObjectSpace(Vector3.new(0, 1, 0)),
      }
      local stickerTexture = AssetService:CreateEditableImageAsync(stickerId)
      local localBrushConfig: BrushConfig = {
      Decal = stickerTexture,
      ColorBlendType = Enum.ImageCombineType.BlendSourceOver,
      AlphaBlendType = Enum.ImageAlphaType.Default,
      BlendIntensity = 1,
      FadeAngle = 90.0
      }
      bodyPartTexture:DrawImageProjected(targetMesh, projectionParams, localBrushConfig)
      end
  3. Gebruik WrapDeformer en EditableMesh om tools te maken voor het bewerken van mesh-deformaties op je lichaam.

    1. WrapDeformer behandelt de live deformaties van de weergegeven MeshPart geometrie terwijl de onderliggende skinning en FACS-gegevens behouden blijven.

    2. EditableMesh stelt je in staat om de kooi-mesh te wijzigen waar de WrapDeformer op reageert.

      1. Gebruik WrapDeformer:SetCageMeshContent() om de EditableMesh instantie die de relevante kooi-mesh vertegenwoordigt toe te passen op de WrapDeformer.
      2. Gebruik EditableMesh, zoals SetPosition(), om de vertices te vervormen en de vorm van de MeshPart te bewerken.
      local function deformBodyPart(
      meshPart: MeshPart,
      controlPointCenter: Vector3,
      controlPointRadius: number,
      controlPointDeformation: Vector3
      )
      local wrapTarget = meshPart:FindFirstChildWhichIsA("WrapTarget")
      local cageMeshId = wrapTarget.CageMeshId
      local wrapDeformer = Instance.new("WrapDeformer")
      wrapDeformer.Parent = meshPart
      local cageEditableMesh = AssetService:CreateEditableMeshAsync(cageMeshId)
      local verticesWithinSphere =
      cageEditableMesh:FindVerticesWithinSphere(controlPointCenter, controlPointRadius)
      for _, vertexId in verticesWithinSphere do
      local vertexPosition = cageEditableMesh:GetPosition(vertexId)
      cageEditableMesh:SetPosition(vertexId, vertexPosition + controlPointDeformation)
      end
      wrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))
      end

Maak een creatieprompt

Nadat je je basislichaam en bewerkings-API's hebt ingesteld, maak je een prompt voor gebruikers om te creëren en aan te schaffen vanuit de ervaring met AvatarCreationService:PromptCreateAvatarAsync().

export type BodyPartInfo = {
bodyPart: Enum.BodyPart,
instance: Instance --Folder met gemaakte MeshParts
}
export type BodyPartList = {BodyPartInfo}
local function publishAvatar(bodyPartInstances: BodyPartList, player: Player, tokenId: string)
local humanoidDescription = Instance.new("HumanoidDescription")
for _, bodyPartInfo in bodyPartInstances do
local bodyPartDescription = Instance.new("BodyPartDescription")
bodyPartDescription.Instance = bodyPartInfo.instance
bodyPartDescription.BodyPart = bodyPartInfo.bodyPart
bodyPartDescription.Parent = humanoidDescription
end
local success, result, bundleIdOrErrorMessage, outfitId = pcall(function()
return AvatarCreationService:PromptCreateAvatarAsync(tokenId, player, humanoidDescription)
end)
if success then
if result == Enum.PromptCreateAvatarResult.Success then
print("Succesvol geüpload met BundleId: ", bundleIdOrErrorMessage)
print("Succesvol geüpload met OutfitId: ", outfitId)
else
print("Onsuccesvol geüpload met foutmelding:", bundleIdOrErrorMessage)
end
else
print("Avatarcreatie niet succesvol")
end
end

AvatarCreationService:PromptCreateAvatarAsync() neemt een HumanoidDescription parameter om de avatar voor aankoop of creatie weer te geven. Voor avatarcreatie moet de HumanoidDescription van het personage nieuwe assets bevatten die voor elk van de 6 lichaamsdelen moeten worden gemaakt (Head, Torso, RightLeg, LeftLeg, RightArm, LeftArm). Optioneel kan het ook een nieuwe Hair accessoire bevatten.

Om dit te ondersteunen, moet de HumanoidDescription 6 BodyPartDescription kinderen bevatten. Elke BodyPartDescription.Instance eigenschap verwijst naar een Folder die alle MeshPart instanties bevat die het lichaamsdeel vormen. Bijvoorbeeld, de LeftArm map bevat LeftHand, LeftUpperArm, en LeftLowerArm MeshParts. De BodyPartDescription.BodyPart eigenschap moet ook worden ingesteld op de relevante Enum.BodyPart.

Elk van de 15 MeshPart lichaamsdelen moet bevatten:

De geleverde HumanoidDescription mag geen bestaande asset-ID's bevatten om lichaamsdelen of accessoires op de bedoelde creatie weer te geven. Aan de andere kant kan de HumanoidDescription de humanoïde schalen van BodyTypeScale, HeadScale, HeightScale, WidthScale, en ProportionScale bevatten. Wees je bewust van de schalen waarmee een basislichaam is geïmporteerd, zodat ze overeenkomen met de schalen die aan de HumanoidDescription zijn verstrekt.

Inclusief accessoires

Als je een accessoire, zoals haar, wilt opnemen, moet de HumanoidDescription een kind AccessoryDescription bevatten waar:

Genereer een avatar creatietoken

AvatarCreationService:PromptCreateAvatarAsync() neemt een Avatar Creatie Token ID parameter. Dit token is de sleutel voor creaties uit jouw universum, en het is wat je kunt gebruiken om de prijs van avatarcreatie vanuit jouw ervaring in te stellen. Voor instructies en aanvullende details over het genereren van tokens, zie Avatar Creatie Tokens.

Na het kopen en genereren van je token, kun je het token inspecteren in de Creator Hub om de ID te vinden die je vervolgens kunt gebruiken voor de AvatarCreationService:PromptCreateAvatarAsync() API.

Reageer op spelers die zich aanmelden via attributie

Avatarbundels die in-experience zijn gemaakt, bevatten een attributielink naar de oorspronkelijke ervaring waarin de avatar is gemaakt. Als de avatar door een andere speler wordt geïnspecteerd, verschijnt er een prompt met de optie om de ervaring te bezoeken waar de avatar is gemaakt.

Om spelers die zich aanmelden bij jouw ervaring via deze attributielink te verwerken, gebruik je Player:GetJoinData() en parse je de geretourneerde tabel voor GameJoinContext.

GameJoinContext bevat de volgende tabelwaarden:

©2026 Roblox Corporation. Roblox, het Roblox-logo en Powering Imagination behoren tot onze geregistreerde en niet-geregistreerde handelsmerken in de VS en andere landen.