การสร้างสรรค์

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

คุณสามารถเผยแพร่ประสบการณ์ที่ช่วยให้ผู้เล่นสามารถสร้าง ปรับแต่ง และซื้อร่างกายอวาตาร์ได้ในเวลาจริงเมื่อซื้อแล้ว ร่างกายที่กำหนดเองเหล่านี้จะบันทึกโดยตรงในคลังสินค้า Roblox ของผู้เล่น ทำให้ผู้เล่นสามารถติดตั้งและสวมใส่อวตารที่กำหนดเองในประสบการณ์อื่นได้

เจ้าของประสบการณ์ที่ใช้การสร้างอวตารในประสบการณ์ได้รับประโยชน์จาก ค่าธรรมเนียมตลาด ทั้งในฐานะผู้สร้างอวตารและเจ้าของประสบการณ์หากสินทรัพย์ที่สร้างในประสบการณ์ถูกตรวจสอบ รายการจะให้ลิงก์ไปยังประสบการณ์เดิมที่สร้างขึ้น

คุณสามารถทดสอบการสร้างในประสบการณ์ในการสาธิตของ Roblox's Avatar Creator

การสร้างสรรค์

ใช้คำแนะนำและรหัสอ้างอิงต่อไปนี้เพื่อสร้างโครงการสร้างอวาตาร์ประสบการณ์แรกของคุณคำแนะนำต่อไปนี้ใช้ร่างกายหลัก Model ที่ผู้เล่นสามารถแก้ไขและปรับแต่งก่อนเผยแพร่

ก่อนที่จะเริ่มต้น กำลังติดตาม:

  • รูปแบบตัวละคร — การดำเนินการต่อไปต้องนำเข้าร่างกายพื้นฐานที่ตรงกับข้อกำหนดส่วน 15 ของ Robloxนี้ Model ให้บริการเป็นฐานสำหรับการปรับแต่งและการแก้ไขผู้ใช้เพิ่มเติม
    • ร่างกายฐานต้องปฏิบัติตามคำแนะนำด้านร่างกายของ Roblox Avatar body guidelines รวมถึงจํานวน FACS ขั้นต่ําสําหรับการปรับแต่งใบหน้า
  • โทเค็นการสร้างอวตาร — ประสบการณ์ที่ใช้สร้างอวตารต้องมีโทเค็นการสร้างอย่างน้อยหนึ่งโทเค็นโทเค็นเหล่านี้ต้องใช้ Robux ในการซื้อและอนุญาตให้คุณตั้งราคาและการตั้งค่าการขายอื่นๆ สำหรับการซื้อที่ทำในประสบการณ์
  • คลาส API
    • AvatarCreationService — จัดการการสร้างอวตารที่ระบุและยืนยันการตรวจสอบ
    • EditableImage — จัดการการสร้างและการปรับแต่งเทกเจอร์ในระหว่างการทำงาน
    • EditableMesh — จัดการการปรับแต่งระหว่างการทำงานของเมทริกซ์ภูมิทัศน์
    • WrapDeformer — จัดการการปรับแต่งเวลาของภาชนะที่มองไม่เห็นที่ช่วยให้ตัวละครอวาตาร์สามารถสวมใส่เสื้อผ้า 3D ได้ 3D

นำเข้าร่างกายฐาน

ร่างกายหลักทำหน้าที่เป็นพื้นฐานเริ่มต้นที่ผู้ใช้สามารถปรับแต่งและแก้ไขได้คุณสามารถใช้ของคุณเอง Model หรือนำเข้าสินทรัพย์ที่กําหนดเองด้วย ผู้นําเข้า 3D และติดตั้งผ่าน การตั้งค่าอวาตาร์

ร่างกายฐานต้องปฏิบัติตามข้อกำหนดของอวตารของ Roblox และต้องรวมส่วนประกอบเช่น 15 ตัวอย่างที่ประกอบขึ้นเป็น 6 ส่วนของร่างกาย: หัว, ลําตัว, แขนซ้าย, ขาซ้าย, แขนขวา, และขาขวา รวมถึงส่วนประกอบอวตารอื่น ๆ อีกด้วย

สำหรับการอ้างอิงและตัวอย่างของร่างกายอวาตาร์ที่กำหนดค่าอย่างถูกต้อง ดู การอ้างอิงอวาตาร์

ใช้งาน API การแก้ไข

เพื่อพัฒนาระบบที่ผู้ใช้สามารถแก้ไขตัวอย่าง MeshPart การสร้างสรรค์ใช้ EditableImage สำหรับการแก้ไขเทกเจอร์ EditableMesh สำหรับการแก้ไขเมช และ WrapDeformer สำหรับการรักษาข้อมูลผิวหนังและ FACS ในระหว่างการแก้ไขเมช

  1. หลังจากนำเข้าร่างกายหลักแล้วใช้สคริปต์ต่อไปนี้เพื่อตั้งค่า EditableImages , EditableMeshes และ WrapDeformers ของคุณ


    local AssetService = game:GetService("AssetService")
    local function setupBodyPart(meshPart, wrapTarget)
    -- สร้างและแนบ WrapDeformer ไปยัง MeshPart
    local wrapDeformer = Instance.new("WrapDeformer")
    wrapDeformer.Parent = meshPart
    -- สร้างเมชที่แก้ไขได้สำหรับเมชของกรงเป้าหมายห่อ
    local cageEditableMesh: EditableMesh =
    AssetService:CreateEditableMeshAsync(Content.fromUri(wrapTarget.CageMeshId), {
    FixedSize = true,
    })
    -- กำหนดเมทช์กรงให้กับ WrapDeformer
    wrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))
    end
    local function setupRigidMesh(meshPart)
    -- สร้างเมชที่แก้ไขได้จาก MeshPart เดิม
    local editableMesh = AssetService:CreateEditableMeshAsync(Content.fromUri(meshPart.MeshId), {
    FixedSize = true,
    })
    -- สร้าง MeshPart ใหม่จากเมชที่แก้ไขได้
    local newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh))
    -- คัดลอกขนาด ตําแหน่ง และเทกเจอร์จาก MeshPart เดิม
    newMeshPart.Size = meshPart.Size
    newMeshPart.CFrame = meshPart.CFrame
    newMeshPart.TextureContent = meshPart.TextureContent
    -- นำ MeshPart ใหม่กลับไปที่ต้นฉบับ
    meshPart:ApplyMesh(newMeshPart)
    end
    local function setupMeshTexture(meshPart, textureIdToEditableImageMap)
    -- หาก EditableImage มีอยู่แล้วสำหรับ TextureID นี้ให้ใช้ซ้ำแทนที่จะสร้างใหม่
    if textureIdToEditableImageMap[meshPart.TextureID] then
    meshPart.TextureContent =
    Content.fromObject(textureIdToEditableImageMap[meshPart.TextureID])
    return
    end
    -- สร้างภาพที่แก้ไขได้ใหม่และใช้เป็นเนื้อหาของเทกเจอร์
    local editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(meshPart.TextureID))
    textureIdToEditableImageMap[meshPart.TextureID] = editableImage
    meshPart.TextureContent = Content.fromObject(editableImage)
    end
    local function setupModel(model)
    -- แผนที่สำหรับการใช้ซ้ำตัวอย่าง EditableImage โดยรหัสเทกเจอร์
    local textureIdToEditableImageMap = {}
    for _, descendant in model:GetDescendants() do
    if not descendant:IsA("MeshPart") then
    continue
    end
    -- กำหนดค่า MeshPart ตามการปรากฏตัวของ WrapTarget
    -- หาก WrapTarget ปรากฏขึ้น เพิ่มลูก WrapDeformer ด้วย EditableMesh
    -- มิฉะนั้นใช้ EditableMesh กับ MeshPart โดยตรง
    local wrapTarget = descendant:FindFirstChildOfClass("WrapTarget")
    if wrapTarget then
    setupBodyPart(descendant, wrapTarget)
    else
    setupRigidMesh(descendant)
    end
    -- กำหนดค่าภาพที่แก้ไขได้สำหรับชิ้นส่วน Mesh
    setupMeshTexture(descendant, textureIdToEditableImageMap)
    end
    end
  2. สร้างเครื่องมือ EditableImage ที่ช่วยให้ผู้เล่นสามารถเปลี่ยนสี วาด หรือเพิ่มสติกเกอร์ลงบนร่างกายหลักของคุณคุณสามารถใช้ประโยชน์จาก API ในเช่น DrawImage() , DrawRectangle() , WritePixelsBuffer() .

    • สำหรับการเปลี่ยนแปลงขั้นสูง DrawImageTransformed() ช่วยให้คุณสามารถระบุตำแหน่ง การหมุน และขนาดเมื่อวาดภาพที่แก้ไขได้หนึ่งภาพไปยังอีกภาพหนึ่งเช่นเดียวกัน DrawImageProjected() ทำงานคล้ายกับ DrawImage() แต่โครงการภาพวาดที่วาดได้อย่างถูกต้องหากตัวอย่าง EditableImage ถูกใช้ด้วย 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. โดยใช้ WrapDeformer และ EditableMesh สร้างเครื่องมือสำหรับแก้ไขการเปลี่ยนรูปเมชในร่างกายของคุณ

    1. WrapDeformer จัดการการเปลี่ยนรูปแบบสดของรูปทรงที่เรนเดอร์ได้รับ MeshPart ในขณะที่รักษาข้อมูลสกินและข้อมูล FACS พื้นฐานไว้

    2. EditableMesh ช่วยให้คุณสามารถปรับแต่งตาข่ายกรงที่ WrapDeformer ตอบสนองได้

      1. ใช้ WrapDeformer:SetCageMeshContent() เพื่อใช้ตัวอย่าง EditableMesh ที่แทนที่ตาข่ายกรงที่เกี่ยวข้องกับ WrapDeformer
      2. ใช้ EditableMesh , เช่น SetPosition() , เพื่อทำลายเหลี่ยมและแก้ไขรูปร่างของ 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

สร้างคําขอสร้าง

หลังจากตั้งค่าร่างกายหลักและแก้ไข API แล้ว สร้างคำเตือนสำหรับผู้ใช้เพื่อสร้างและซื้อจากประสบการณ์โดยใช้ AvatarCreationService:PromptCreateAvatarAsync()


export type BodyPartInfo = {
bodyPart: Enum.BodyPart,
instance: Instance --โฟลเดอร์ที่มีชิ้นส่วนเมชที่สร้างขึ้น
}
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() ใช้พารามิเตอร์ HumanoidDescription การสร้างสรรค์HumanoidDescription จะต้องรวมทรัพยากรใหม่ที่จะสร้างสำหรับแต่ละส่วนของร่างกาย 6 ส่วน ( Head , Torso , RightLeg , LeftLeg , RightArm , LeftArm )ไอเท็มเสริมHair ได้

เพื่อสนับสนุนสิ่งนี้ HumanoidDescription ควรรวมเด็ก 6 BodyPartDescription คนแต่ละคุณสมบัติ BodyPartDescription.Instance อ้างอิงถึง Folder ซึ่งรวมถึงทุกตัวอย่าง MeshPart ที่ทำให้เกิดส่วนของร่างกายตัวอย่างเช่น โฟลเดอร์ LeftArm มี LeftHand , LeftUpperArm และ LeftLowerArm``Class.MeshPart|MeshPartsคุณสมบัติ BodyPartDescription.BodyPart ควรตั้งเป็น Enum.BodyPart ที่เกี่ยวข้องด้วย

แต่ละส่วนของร่างกาย 15 MeshPart ต้องรวมถึง:

รหัสสินทรัพย์ที่ให้มา HumanoidDescription ไม่ควรรวมรหัสสินทรัพย์ที่มีอยู่แล้วล่วงหน้าเพื่อแทนที่ส่วนหรืออุปกรณ์เสริมในการสร้างที่ตั้งใจไว้ในทางกลับกัน HumanoidDescription อาจรวมถึงเครื่องชั่งมนุษย์ของ BodyTypeScale , HeadScale , HeightScale , WidthScale และ ProportionScaleโปรดใส่ใจกับเครื่องชั่งที่ร่างฐานถูกนำมาใช้เพื่อให้ตรงกับเครื่องชั่งที่ให้ไว้กับ HumanoidDescription

รวมอุปกรณ์เสริม

หากรวมอุปกรณ์เสริม เช่น ผม ตัว HumanoidDescription ควรรวมเด็ก AccessoryDescription โดยมี:

สร้างโทเค็นการสร้างอวตาร

AvatarCreationService:PromptCreateAvatarAsync() ใช้พารามิเตอร์ ID การสร้างอวตาร โทเค็นนี้เป็นกุญแจสําคัญสําหรับการสร้างจากจักรวาลของคุณและเป็นสิ่งที่คุณสามารถใช้เพื่อตั้งราคาการสร้างอวาตาร์จากประสบการณ์ของคุณสำหรับคําแนะนําและรายละเอียดเพิ่มเติมเกี่ยวกับการสร้างโทเค็นดูที่ โทเค็นการสร้างอวตาร

หลังจากซื้อและสร้างโทเค็นแล้ว คุณสามารถตรวจสอบโทเค็นใน Creator Hub เพื่อค้นหารหัสที่คุณสามารถใช้สำหรับ API AvatarCreationService:PromptCreateAvatarAsync() ได้

ตอบสนองต่อผู้เล่นที่เข้าร่วมโดยการโยนความคิดเห็น

แพ็คเกจตัวละครที่สร้างขึ้นในประสบการณ์รวมถึงลิงก์การอ้างอิงไปยังประสบการณ์เดิมที่ตัวละครถูกสร้างขึ้นหากอวตารถูกตรวจสอบโดยผู้เล่นคนอื่น จะมีการแสดงคำเตือนพร้อมตัวเลือกในการเยี่ยมชมประสบการณ์ที่อวตารถูกสร้างขึ้น

เพื่อจัดการผู้เล่นที่เข้าร่วมประสบการณ์ของคุณโดยใช้ลิงก์การโยบายนี้, ใช้ Player:GetJoinData() และแยกตารางที่ส่งคืนสำหรับ GameJoinContext

GameJoinContext รวมถึงมูลค่าตารางต่อไปนี้:

  • JoinSourceEnum.JoinSource
    • การเชื่อมโยงประสบการณ์ของคุณจากลิงก์การจัดสรรนี้จะมี เพื่อระบุการเข้าถึงจากไอเทมที่สร้างขึ้น
  • ItemType — ตัวเลือก Enum.AvatarItemType
  • AssetId — ตัวเลือก string
  • OutfitId — ตัวเลือก string
  • AssetType — ตัวเลือก Enum.AssetType