Tạo Avatar trong kinh sản phẩm

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Bạn có thể xuất bản một trải nghiệm cho phép người chơi tạo, tùy chỉnh và mua các cơ thể avatar trong thời gian thực.Khi mua, các cơ thể tùy chỉnh này lưu trực tiếp vào kho Roblox của người chơi, cho phép người chơi trang bị và mặc các avatar tùy chỉnh trong các trải nghiệm khác.

Các chủ sở hữu kinh nghiệm thực hiện sáng tạo avatar trong kinh nghiệm được hưởng lợi từ phí thị trường cả về vai trò người tạo của vật phẩm avatar và chủ sở hữu kinh nghiệm .Nếu một tài sản được tạo trong trải nghiệm được kiểm tra, mục cung cấp một liên kết đến trải nghiệm ban đầu nó được tạo.

Bạn có thể thử nghiệm sáng tạo trong kinh nghiệm trong demo Người sáng tạo Avatar của Roblox.

Cách thực hiện sản phẩmtrong kinh nghiệm

Sử dụng các hướng dẫn và tham chiếu mã sau để tạo dự án tạo avatar đầu tiên trong trải nghiệm của bạn.Các hướng dẫn sau đây sử dụng một cơ thể cơ bản Model mà người chơi có thể chỉnh sửa và tùy chỉnh trước khi xuất bản.

Trước khi bắt đầu, hãy quen thuộc với những điều theo dõi:

  • Mô hình avatar — Thực hiện tiếp theo yêu cầu nhập một cơ thể cơ bản đáp ứng các thông số phần 15 của Roblox.Cái này Model phục vụ như một cơ sở để tùy chỉnh và thay đổi người dùng bổ sung.
    • Cơ thể cơ bản phải đáp ứng các hướng dẫn cơ thể Avatar của Roblox, bao gồm số lượng tối thiểu của điều khiển FACS cho căng cứng khuôn mặt.
  • Token tạo avatar — Các trải nghiệm triển khai tạo avatar cần ít nhất một token tạo.Các token này yêu cầu Robux để mua và cho phép bạn đặt giá và các cài đặt bán hàng khác cho các giao dịch được thực hiện trong kinh nghiệm.
  • Lớp API
    • AvatarCreationService — Xử lý lời nhắc và xác minh tạo avatar.
    • EditableImage — Xử lý tạo thời gian chạy và thao tác với kết cấu.
    • EditableMesh — Xử lý thời gian chạy thao tác biến hình của khối lưới.
    • WrapDeformer — Xử lý thời gian chạy của địa hình lồng bên ngoài vô hình cho phép các nhân vật avatar trang bị quần áo 3D .

Nhập một cơ thể cơ thân

Cơ thể cơ bản hoạt động như nền tảng ban đầu mà người dùng có thể tùy chỉnh và chỉnh sửa.Bạn có thể sử dụng Model, hoặc nhập một tài sản tùy chỉnh với Nhập khẩu 3D và thiết lập thông qua Cài đặt Avatar.

Các cơ thể cơ bản phải tuân thủ các đặc tính avatar của Roblox, và phải bao gồm các thành phần như 15 ví dụ các thành phần cơ thể 6: đầu, thân, tay trái, chân trái, tay phải và chân phải, cũng như các thành phần avatar khác .

Đối với các tham chiếu và ví dụ về các cơ thể avatar được cấu hình đúng, xem Tham chiếu avatar.

Thực hiện chỉnh sửa API

Để phát triển một hệ thống mà người dùng có thể chỉnh sửa các MeshPart trên một avatar trong trải nghiệm của bạn để sản phẩm, sử dụng EditableImage để chỉnh sửa kết cấu, EditableMesh để chỉnh sửa khối lượng lưới, và WrapDeformer để duy trì dữ liệu skinning và FACS trong quá trình chỉnh sửa lưới.

  1. Sau khi nhập cơ thâncơ bản của bạn, sử dụng kịch bản sau để thiết lập EditableImages , EditableMeshesWrapDeformers của bạn.


    local AssetService = game:GetService("AssetService")
    local function setupBodyPart(meshPart, wrapTarget)
    -- Tạo và gắn một WrapDeformer vào MeshPart
    local wrapDeformer = Instance.new("WrapDeformer")
    wrapDeformer.Parent = meshPart
    -- Tạo một lưới có thể chỉnh sửa cho lưới lồng của mục tiêu bọc
    local cageEditableMesh: EditableMesh =
    AssetService:CreateEditableMeshAsync(Content.fromUri(wrapTarget.CageMeshId), {
    FixedSize = true,
    })
    -- Gán khối lưới lồng vào WrapDeformer
    wrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))
    end
    local function setupRigidMesh(meshPart)
    -- Tạo một khối lượng có thể chỉnh sửa từ MeshPart ban đầu
    local editableMesh = AssetService:CreateEditableMeshAsync(Content.fromUri(meshPart.MeshId), {
    FixedSize = true,
    })
    -- Tạo một MeshPart mới từ lưới có thể chỉnh sửa
    local newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh))
    -- Sao chép kích thước, vị trí và kết cấu từ MeshPart gốc
    newMeshPart.Size = meshPart.Size
    newMeshPart.CFrame = meshPart.CFrame
    newMeshPart.TextureContent = meshPart.TextureContent
    -- Áp dụng MeshPart mới trở lại nguyên bản
    meshPart:ApplyMesh(newMeshPart)
    end
    local function setupMeshTexture(meshPart, textureIdToEditableImageMap)
    -- Nếu EditableImage hiện tồn tại cho TextureID này, hãy sử dụng lại nó thay vì tạo một cái mới
    if textureIdToEditableImageMap[meshPart.TextureID] then
    meshPart.TextureContent =
    Content.fromObject(textureIdToEditableImageMap[meshPart.TextureID])
    return
    end
    -- Tạo một hình ảnh có thể chỉnh sửa mới và áp dụng nó như nội dung kết cấu
    local editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(meshPart.TextureID))
    textureIdToEditableImageMap[meshPart.TextureID] = editableImage
    meshPart.TextureContent = Content.fromObject(editableImage)
    end
    local function setupModel(model)
    -- Bản đồ cho việc tái sử dụng các ví dụ EditableImage bằng ID kết cấu
    local textureIdToEditableImageMap = {}
    for _, descendant in model:GetDescendants() do
    if not descendant:IsA("MeshPart") then
    continue
    end
    -- Tùy chỉnh MeshPart dựa trên sự hiện diện của WrapTarget
    -- Nếu WrapTarget có mặt, thêm một đứa con WrapDeformer với một EditableMesh
    -- Nếu không, áp dụng EditableMesh cho MeshPart trực tiếp
    local wrapTarget = descendant:FindFirstChildOfClass("WrapTarget")
    if wrapTarget then
    setupBodyPart(descendant, wrapTarget)
    else
    setupRigidMesh(descendant)
    end
    -- Tùy chỉnh hình ảnh có thể chỉnh sửa cho MeshPart
    setupMeshTexture(descendant, textureIdToEditableImageMap)
    end
    end
  2. Tạo công cụ EditableImage cho phép người chơi thay đổi màu, vẽ hoặc thêm nhãn dán vào cơ thể thâncủa bạn.Bạn có thể tận dụng API trong giống như DrawImage() , DrawRectangle() , WritePixelsBuffer() .

    • Đối với biến dạng nâng cao, DrawImageTransformed() cho phép bạn xác định vị trí, xoay và thước đo khi vẽ một Hình ảnh có thể chỉnh sửa lên một khác.Tương tự, DrawImageProjected() hoạt động giống như DrawImage() nhưng dự án hình ảnh được vẽ đúng nếu EditableImage instance được sử dụng với một 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. Sử dụng WrapDeformerEditableMesh, tạo công cụ để chỉnh sửa biến dạng lưới trên cơ thâncủa bạn.

    1. WrapDeformer xử lý các biến dạng trực tiếp của định dạng được render MeshPart trong khi duy trì dữ liệu skinning và FACS cơ bản.

    2. EditableMesh cho phép bạn thay đổi lưới lồng mà WrapDeformer đáp ứng.

      1. Sử dụng WrapDeformer:SetCageMeshContent() để áp dụng EditableMesh ví dụ instance đại diện cho lưới lồng liên quan vào WrapDeformer .
      2. Sử dụng EditableMesh , chẳng hạn như SetPosition() , để biến dạng các đỉnh và chỉnh sửa hình dạng của 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

Tạo lời nhắc tạo

Sau khi thiết lập cơ thể cơ bản và chỉnh sửa API, tạo một lời nhắc cho người dùng tạo và mua từ trải nghiệm bằng AvatarCreationService:PromptCreateAvatarAsync() .


export type BodyPartInfo = {
bodyPart: Enum.BodyPart,
instance: Instance --Thư mục với MeshParts được tạo
}
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() nhận một tham số HumanoidDescription để đại diện cho avatar dự định mua hoặc sản phẩm.Đối với việc sản phẩmavatar, nhân vật của HumanoidDescription phải bao gồm các tài sản mới được tạo cho mỗi phần cơ thể 6 ( Head , Torso , RightLeg , LeftLeg , RightArm , LeftArm ).Tùy chọn, nó cũng có thể bao gồm một phụ kiện mới Hair.

Để hỗ trợ điều này, HumanoidDescription nên bao gồm 6 đứa con BodyPartDescription .Mỗi BodyPartDescription.Instance tài sản tham chiếu một Folder bao gồm tất cả các MeshPart ví dụ mà tạo nên phần thân.Ví dụ, thư mục LeftArm chứa LeftHand , LeftUpperArm , và LeftLowerArm``Class.MeshPart|MeshParts .Thuộc tính BodyPartDescription.BodyPart cũng nên được đặt thành Enum.BodyPart liên quan.

Mỗi trong số 15 MeshPart phần cơ thể phải bao gồm:

ID tài sản được cung cấp HumanoidDescription không nên bao gồm bất kỳ ID tài sản hiện có nào để đại diện cho các bộ phận cơ thể hoặc phụ kiện trong quá trình sản phẩmdự kiến.Mặt khác, HumanoidDescription có thể bao gồm các thước đo hình người của BodyTypeScale , HeadScale , HeightScale , WidthScaleProportionScale .Hãy lưu ý đến các thước đo mà một cơ thể cơ bản được nhập với nhằm chúng phù hợp với các thước đo được cung cấp cho HumanoidDescription .

Bao gồm phụ kiện

Nếu bao gồm một phụ kiện, chẳng hạn như tóc, HumanoidDescription nên bao gồm một đứa con AccessoryDescription nơi:

Tạo một token tạo avatar

AvatarCreationService:PromptCreateAvatarAsync() nhận một tham số ID Tạo Avatar .Token này là chìa khóa cho các sáng tạo từ vũ trụ của bạn, và nó là những gì bạn có thể sử dụng để đặt giá cho việc tạo avatar từ trải nghiệm của bạn.Đối với hướng dẫn và chi tiết bổ sung về việc tạo token, xem Mã tạo Avatar.

Sau khi mua và tạo token của bạn, bạn có thể kiểm tra token trong Trung tâm Nhà sáng tạo để tìm ID mà bạn có thể sử dụng cho API AvatarCreationService:PromptCreateAvatarAsync() .

Trả lời người chơi tham gia bằng cách gán cho

Các gói avatar được tạo ra trong kinh nghiệm bao gồm một liên kết đóng góp đến trải nghiệm ban đầu mà avatar được tạo ra.Nếu avatar được kiểm tra bởi người chơi khác, một thông báo hiển thị cung cấp một lựa chọn để truy cập trải nghiệm mà avatar được tạo ra.

Để xử lý người chơi tham gia trải nghiệm của bạn bằng liên kết phân bổ này, hãy sử dụng Player:GetJoinData() và phân tích bảng trả về cho GameJoinContext .

GameJoinContext bao gồm các giá trị bảng sau: