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.
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 MeshPartlocal wrapDeformer = Instance.new("WrapDeformer")wrapDeformer.Parent = meshPart-- Buat mesh yang dapat diedit untuk mesh kandang target bungkuslocal cageEditableMesh: EditableMesh =AssetService:CreateEditableMeshAsync(Content.fromUri(wrapTarget.CageMeshId), {FixedSize = true,})-- Ambil kandang meshes ke WrapDeformerwrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))endlocal function setupRigidMesh(meshPart)-- Buat mesh yang dapat diedit dari MeshPart aslilocal editableMesh = AssetService:CreateEditableMeshAsync(Content.fromUri(meshPart.MeshId), {FixedSize = true,})-- Hasilkan MeshPart baru dari mesh yang dapat dieditlocal newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh))-- Salin ukuran, posisi, dan tekstur dari MeshPart aslinewMeshPart.Size = meshPart.SizenewMeshPart.CFrame = meshPart.CFramenewMeshPart.TextureContent = meshPart.TextureContent-- Terapkan MeshPart baru kembali ke aslimeshPart:ApplyMesh(newMeshPart)endlocal function setupMeshTexture(meshPart, textureIdToEditableImageMap)-- Jika EditableImage sudah ada untuk TextureID ini, gunakan kembali daripada membuat yang baruif textureIdToEditableImageMap[meshPart.TextureID] thenmeshPart.TextureContent =Content.fromObject(textureIdToEditableImageMap[meshPart.TextureID])returnend-- Buat gambar yang dapat diedit baru dan terapkan sebagai konten teksurlocal editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(meshPart.TextureID))textureIdToEditableImageMap[meshPart.TextureID] = editableImagemeshPart.TextureContent = Content.fromObject(editableImage)endlocal function setupModel(model)-- Peta untuk menggunakan kembali instansi EditableImage oleh ID teksturlocal textureIdToEditableImageMap = {}for _, descendant in model:GetDescendants() doif not descendant:IsA("MeshPart") thencontinueend-- Konfigurasi MeshPart berdasarkan kehadiran WrapTarget-- Jika WrapTarget hadir, tambahkan anak WrapDeformer dengan EditableMesh-- Jika tidak, terapkan EditableMesh ke MeshPart secara langsunglocal wrapTarget = descendant:FindFirstChildOfClass("WrapTarget")if wrapTarget thensetupBodyPart(descendant, wrapTarget)elsesetupRigidMesh(descendant)end-- Konfigurasi Gambar yang Dapat Diubah untuk MeshPartsetupMeshTexture(descendant, textureIdToEditableImageMap)endendBuat 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)endlocal 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)endlocal 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).Unitlocal 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
Menggunakan WrapDeformer dan EditableMesh , buat alat untuk mengedit deformasi mesh di tubuh Anda.
WrapDeformer menangani deformasi hidup dari geometri yang drender MeshPart sambil menjaga kulit dasar dan data FACS.
EditableMesh memungkinkan anda untuk memodifikasi meshes kandang yang direspons oleh WrapDeformer .
- Gunakan WrapDeformer:SetCageMeshContent() untuk menerapkan instansi EditableMesh yang mewakili meshes kandang yang relevan ke WrapDeformer.
- 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.CageMeshIdlocal wrapDeformer = Instance.new("WrapDeformer")wrapDeformer.Parent = meshPartlocal cageEditableMesh = AssetService:CreateEditableMeshAsync(cageMeshId)local verticesWithinSphere =cageEditableMesh:FindVerticesWithinSphere(controlPointCenter, controlPointRadius)for _, vertexId in verticesWithinSphere dolocal vertexPosition = cageEditableMesh:GetPosition(vertexId)cageEditableMesh:SetPosition(vertexId, vertexPosition + controlPointDeformation)endwrapDeformer: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:
- An EditableImage .
- Sebuah WrapDeformer dengan EditableMesh.
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:
- Properti AccessoryDescription.Instance merujuk pada instansi Accessory.
- Properti AccessoryDescription.AccessoryType diatur ke Enum.AccessoryType yang relevan.
- Dalam kasus termasuk Enum.AccessoryType.Hair dalam kreasi Anda, MeshPart harus termasuk EditableImage .Namun, seharusnya tidak termasuk anak WrapDeformer tetapi harus termasuk set EditableMesh pada MeshPart langsung.
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:
- JoinSource — Enum.JoinSource
- Sebuah Player bergabung dengan pengalaman Anda dari tautan atribusi ini akan memiliki Enum.JoinSource.CreatedItemAttribution untuk menunjukkan entri dari item yang dibuat.
- ItemType — opsional Enum.AvatarItemType
- AssetId — opsional string
- OutfitId — opsional string
- AssetType — opsional Enum.AssetType