Penciptaan avatar dalam kreasi

*Konten ini diterjemahkan menggunakan AI (Beta) dan mungkin mengandung kesalahan. Untuk melihat halaman ini dalam bahasa Inggris, klik di sini.

Anda dapat mempublikasikan pengalaman yang memungkinkan pemain untuk membuat, menyesuaikan, dan membeli tubuh avatar dalam waktu nyata.Saat dibeli, tubuh khusus ini disimpan langsung ke inventaris Roblox pemain, memungkinkan pemain untuk melengkapi dan memakai avatar khusus di pengalaman lain.

Pemilik pengalaman yang menerapkan penciptaan avatar dalam pengalaman mendapat manfaat dari komisi pasar sebagai kedua pencipta dari item avatar dan pemilik pengalaman .Jika aset yang dibuat dalam pengalaman diperiksa, item memberikan tautan ke pengalaman asli yang dibuat.

Anda dapat menguji penciptaan dalam pengalaman di demo Pencipta Avatar Roblox.

Cara menerapkan penciptaan dalam kreasi

Gunakan instruksi dan referensi kode berikut untuk membuat proyek penciptaan avatar pertama Anda dalam pengalaman.Instruksi berikut menggunakan tubuh dasar Model yang dapat dimodifikasi dan disesuaikan sebelum dipublikasikan.

Sebelum mulai, kenali diri Anda dengan hal mengikuti:

  • Model avatar — Penerapan berikut memerlukan impor tubuh dasar yang memenuhi spesifikasi bagian 15 Roblox.Ini Model melayani sebagai dasar untuk kustomisasi dan modifikasi pengguna tambahan.
    • Tubuh dasar harus memenuhi panduan tubuh Roblox Avatar, termasuk jumlah minimum kontrol FACS untuk pengeringan wajah.
  • Token pembuatan avatar — Pengalaman menerapkan pembuatan avatar memerlukan setidaknya satu token pembuatan.Token ini memerlukan Robux untuk dibeli dan memungkinkan Anda untuk menetapkan harga dan pengaturan penjualan lainnya untuk pembelian yang dilakukan dalam pengalaman virtual.
  • Kelas API
    • AvatarCreationService — Menangani pembuatan avatar yang meminta dan memverifikasi validasi.
    • EditableImage — Menangani pembuatan waktu eksekusi dan manipulasi tekstur.
    • EditableMesh — Menangani manipulasi runtime geometri mesh.
    • WrapDeformer — Menangani manipulasi waktu eksekusi geometri kandang luar tak terlihat yang memungkinkan karakter avatar untuk melengkapi pakaian 3D.

Impor tubuh dasar

Tubuh dasar bertindak sebagai dasar awal yang dapat disesuaikan dan diedit oleh pengguna.Anda dapat menggunakan Model, atau mengimpor aset khusus dengan Importer 3-D dan mengatur melalui Pengaturan Avatar.

Tubuh dasar harus mematuhi spesifikasi avatar Roblox, dan harus memasukkan komponen seperti 15 instansi yang membentuk 6 bagian tubuh: kepala, torso, lengan kiri, kaki kiri, lengan kanan, dan lengan kanan, serta komponen avatar lainnya .

Untuk referensi dan sampel tubuh avatar yang dikonfigurasi dengan benar, lihat Referensi avatar.

Implementasikan API pengeditan

Untuk mengembangkan sistem di mana pengguna dapat mengedit instansi MeshPart pada avatar dalam pengalaman Anda untuk kreasi, gunakan EditableImage untuk pengeditan tekstur, EditableMesh untuk pengeditan meshes, dan WrapDeformer untuk menjaga data skin dan FACS selama pengeditan meshes.

  1. Setelah mengekspor tubuh dasar Anda, gunakan skrip berikut untuk mengatur EditableImages , EditableMeshes , dan WrapDeformers .


    local AssetService = game:GetService("AssetService")
    local function setupBodyPart(meshPart, wrapTarget)
    -- Buat dan lampirkan WrapDeformer ke MeshPart
    local wrapDeformer = Instance.new("WrapDeformer")
    wrapDeformer.Parent = meshPart
    -- Buat mesh yang dapat diedit untuk mesh kandang target bungkus
    local cageEditableMesh: EditableMesh =
    AssetService:CreateEditableMeshAsync(Content.fromUri(wrapTarget.CageMeshId), {
    FixedSize = true,
    })
    -- Ambil kandang meshes ke WrapDeformer
    wrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))
    end
    local function setupRigidMesh(meshPart)
    -- Buat mesh yang dapat diedit dari MeshPart asli
    local editableMesh = AssetService:CreateEditableMeshAsync(Content.fromUri(meshPart.MeshId), {
    FixedSize = true,
    })
    -- Hasilkan MeshPart baru dari mesh yang dapat diedit
    local newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh))
    -- Salin ukuran, posisi, dan tekstur dari MeshPart asli
    newMeshPart.Size = meshPart.Size
    newMeshPart.CFrame = meshPart.CFrame
    newMeshPart.TextureContent = meshPart.TextureContent
    -- Terapkan MeshPart baru kembali ke asli
    meshPart:ApplyMesh(newMeshPart)
    end
    local function setupMeshTexture(meshPart, textureIdToEditableImageMap)
    -- Jika EditableImage sudah ada untuk TextureID ini, gunakan kembali daripada membuat yang baru
    if textureIdToEditableImageMap[meshPart.TextureID] then
    meshPart.TextureContent =
    Content.fromObject(textureIdToEditableImageMap[meshPart.TextureID])
    return
    end
    -- Buat gambar yang dapat diedit baru dan terapkan sebagai konten teksur
    local editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(meshPart.TextureID))
    textureIdToEditableImageMap[meshPart.TextureID] = editableImage
    meshPart.TextureContent = Content.fromObject(editableImage)
    end
    local function setupModel(model)
    -- Peta untuk menggunakan kembali instansi EditableImage oleh ID tekstur
    local textureIdToEditableImageMap = {}
    for _, descendant in model:GetDescendants() do
    if not descendant:IsA("MeshPart") then
    continue
    end
    -- Konfigurasi MeshPart berdasarkan kehadiran WrapTarget
    -- Jika WrapTarget hadir, tambahkan anak WrapDeformer dengan EditableMesh
    -- Jika tidak, terapkan EditableMesh ke MeshPart secara langsung
    local wrapTarget = descendant:FindFirstChildOfClass("WrapTarget")
    if wrapTarget then
    setupBodyPart(descendant, wrapTarget)
    else
    setupRigidMesh(descendant)
    end
    -- Konfigurasi Gambar yang Dapat Diubah untuk MeshPart
    setupMeshTexture(descendant, textureIdToEditableImageMap)
    end
    end
  2. Buat alat EditableImage yang memungkinkan pemain untuk mengubah warna, menarik, atau menambahkan stiker ke tubuh dasar Anda.Anda dapat memanfaatkan API di seperti DrawImage() , DrawRectangle() , WritePixelsBuffer() .

    • Untuk transformasi lanjutan, DrawImageTransformed() memungkinkan Anda untuk menentukan posisi, rotasi, dan skala saat menggambar satu EditableImage ke yang lain.Demikian pula, DrawImageProjected() bekerja seperti DrawImage() tetapi menampilkan gambar yang ditarik dengan benar jika instansi EditableImage digunakan dengan 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 = (game.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. Menggunakan WrapDeformer dan EditableMesh , buat alat untuk mengedit deformasi mesh di tubuh Anda.

    1. WrapDeformer menangani deformasi hidup dari geometri yang drender MeshPart sambil menjaga kulit dasar dan data FACS.

    2. EditableMesh memungkinkan anda untuk memodifikasi meshes kandang yang direspons oleh WrapDeformer .

      1. Gunakan WrapDeformer:SetCageMeshContent() untuk menerapkan instansi EditableMesh yang mewakili meshes kandang yang relevan ke WrapDeformer.
      2. Gunakan EditableMesh , seperti SetPosition() , untuk melengkungkan vertiks dan mengedit bentuk MeshPart .

      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

Buat prompt penciptaan

Setelah menyiapkan tubuh dasar dan mengedit API, buat perintah untuk pengguna untuk membuat dan membeli dari pengalaman menggunakan AvatarCreationService:PromptCreateAvatarAsync() .


export type BodyPartInfo = {
bodyPart: Enum.BodyPart,
instance: Instance --Folder dengan MeshParts yang Dibuat
}
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("Successfully uploaded with BundleId: ", bundleIdOrErrorMessage)
print("Successfully uploaded with OutfitId: ", outfitId)
else
print("Unsuccessfully uploaded with error message:", bundleIdOrErrorMessage)
end
else
print("Avatar creation unsuccessful")
end
end

AvatarCreationService:PromptCreateAvatarAsync() mengambil parameter HumanoidDescription untuk mewakili avatar yang dimaksudkan untuk dibeli atau kreasi.Untuk kreasiavatar, karakter HumanoidDescription harus mencakup aset baru yang akan dibuat untuk masing-masing dari 6 bagian tubuh ( Head , Torso , RightLeg , LeftLeg , RightArm , LeftArm ).Opsi, ini juga dapat termasuk aksesori baru Hair .

Untuk mendukung ini, HumanoidDescription harus termasuk 6 BodyPartDescription anak.Setiap BodyPartDescription.Instance properti merujuk pada Folder yang mencakup semua instansi MeshPart yang membentuk bagian tubuh.Sebagai contoh, folder LeftArm berisi LeftHand , LeftUpperArm , dan LeftLowerArm``Class.MeshPart|MeshParts .Properti BodyPartDescription.BodyPart juga harus ditetapkan ke Enum.BodyPart yang relevan.

Masing-masing dari 15 bagian tubuh MeshPart harus termasuk:

Yang disediakan HumanoidDescription tidak boleh mencakup ID aset pramat yang ada untuk mewakili bagian tubuh atau aksesori pada kreasi yang dimaksud.Di sisi lain, HumanoidDescription mungkin termasuk skala humanoid dari BodyTypeScale , HeadScale , HeightScale , WidthScale , dan ProportionScale .Perhatikan skala yang diimpor dengan tubuh dasar sehingga mereka cocok dengan skala yang disediakan ke HumanoidDescription .

Tambahkan aksesori

Jika termasuk aksesori, seperti rambut, HumanoidDescription harus termasuk anak AccessoryDescription di mana:

Hasilkan token pembuatan avatar

AvatarCreationService:PromptCreateAvatarAsync() mengambil parameter ID Penciptaan Avatar .Token ini adalah kunci untuk kreasi dari alam semesta Anda, dan itu adalah apa yang dapat Anda gunakan untuk menetapkan harga pembuatan avatar dari pengalaman Anda.Untuk instruksi dan detail tambahan tentang menghasilkan token, lihat Token Pembuatan Avatar.

Setelah membeli dan menghasilkan token Anda, Anda dapat memeriksa token di Hub Pencipta untuk menemukan ID yang kemudian dapat Anda gunakan untuk API AvatarCreationService:PromptCreateAvatarAsync().

Balas pemain yang bergabung dengan atribusi

Paket avatar yang dibuat dalam pengalaman termasuk tautan atribusi ke pengalaman asli di mana avatar dibuat.Jika avatar diperiksa oleh pemain lain, popup akan ditampilkan yang menyediakan opsi untuk mengunjungi pengalaman di mana avatar dibuat.

Untuk menangani pemain yang bergabung dengan pengalaman Anda menggunakan tautkanatribusi ini, gunakan Player:GetJoinData() dan memproses tabel yang dikembalikan untuk GameJoinContext .

GameJoinContext termasuk nilai tabel berikut: