يمكنك نشر تجربة تسمح للاعبين بإنشاء وتخصيص وشراء أجساد الصور الرمزية في الوقت الفعلي. عند الشراء، يتم حفظ هذه الأجساد المخصصة مباشرة في مخزون اللاعب على Roblox، مما يسمح للاعبين بارتداء واستخدام الصور الرمزية المخصصة في تجارب أخرى.
يستفيد مالكو التجارب الذين ينفذون إنشاء الصور الرمزية داخل التجربة من عمولات السوق بصفة كل من مبدع العنصر الرمزي ومالك التجربة. إذا تم فحص عنصر تم إنشاؤه داخل التجربة، فإن العنصر يوفر رابطاً للتجربة الأصلية التي تم إنشاؤه فيها.
يمكنك اختبار إنشاء التجربة داخل تجربة منشئ الصور الرمزية في Roblox.
كيفية تنفيذ إنشاء داخل التجربة
استخدم التعليمات والمراجع البرمجية التالية لإنشاء مشروعك الأول لإنشاء الصور الرمزية داخل التجربة. تستخدم التعليمات التالية جسماً أساسيًا من Model يمكن للاعبين تعديله وتخصيصه قبل النشر.
قبل البدء، تأكد من معرفتك بالأمور التالية:
- نماذج الصور الرمزية — تتطلب هذه التنفيذات استيراد جسم أساسي يفي بمواصفات Roblox المكونة من 15 جزءًا. هذا Model يعمل كأساس لتخصيص المستخدم الإضافي.
- يجب أن يتوافق الجسم الأساسي مع إرشادات جسم الصورة الرمزية الخاصة بـ Roblox، بما في ذلك الحد الأدنى لعدد عناصر التحكم FACS للتصور الوجهي.
- رموز إنشاء الصور الرمزية — تتطلب التجارب التي تنفذ إنشاء الصور الرمزية على الأقل رمز إنشاء واحد. تتطلب هذه الرموز Robux للشراء وتسمح لك بتحديد الأسعار وغيرها من إعدادات البيع للعمليات التي تمت داخل التجربة.
- فئات واجهة برمجة التطبيقات
- AvatarCreationService — يتعامل مع دعوات إنشاء الصور الرمزية والتحقق منها.
- EditableImage — يتعامل مع إنشاء وتعديل الأنسجة في وقت التشغيل.
- EditableMesh — يتعامل مع تعديل هندسة الشبكة في وقت التشغيل.
- WrapDeformer — يتعامل مع تعديل هندسة السلك الخارجي غير المرئي الذي يسمح لشخصيات الصور الرمزية بارتداء ملابس ثلاثية الأبعاد.
استيراد جسم أساسي
يعمل الجسم الأساسي كأساس أولي يمكن للمستخدمين تخصيصه وتعديله. يمكنك استخدام Model الخاص بك، أو استيراد أصل مخصص باستخدام المستورد وإعداده من خلال إعداد الصور الرمزية.
يجب أن تلتزم الأجسام الأساسية بمواصفات الصورة الرمزية الخاصة بـ Roblox، ويجب أن تتضمن مكونات مثل 15 عنصر MeshPart التي تتكون من 6 أجزاء للجسم: الرأس، الجذع، الذراع اليسرى، الساق اليسرى، الذراع اليمنى، والساق اليمنى، بالإضافة إلى مكونات الصورة الرمزية الأخرى.
للاطلاع على المراجع والعينات من الأجسام الرمزية المُعدّة بشكل صحيح، راجع مراجع الصور الرمزية.
تنفيذ واجهات برمجة التطبيقات للتعديل
لتطوير نظام يمكن للمستخدمين من خلاله تعديل عناصر MeshPart على صورة رمزية في تجربتك من أجل الإنشاء، استخدم EditableImage لتحرير الأنسجة، وEditableMesh لتحرير الشبكات، وWrapDeformer للحفاظ على بيانات الجلد وFACS أثناء تعديل الشبكة.
بعد استيراد جسمك الأساسي، استخدم البرنامج النصي التالي لإعداد EditableImages، وEditableMeshes، وWrapDeformers.
local AssetService = game:GetService("AssetService")local function setupBodyPart(meshPart, wrapTarget)-- إنشاء وإرفاق WrapDeformer إلى MeshPartlocal wrapDeformer = Instance.new("WrapDeformer")wrapDeformer.Parent = meshPart-- إنشاء شبكة قابلة للتعديل لهيكل الشبكة الهدفlocal cageEditableMesh: EditableMesh =AssetService:CreateEditableMeshAsync(Content.fromUri(wrapTarget.CageMeshId), {FixedSize = true,})-- تعيين شبكة الهيكل إلى WrapDeformerwrapDeformer:SetCageMeshContent(Content.fromObject(cageEditableMesh))endlocal 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.SizenewMeshPart.CFrame = meshPart.CFramenewMeshPart.TextureContent = meshPart.TextureContent-- تطبيق MeshPart الجديد مرة أخرى على الأصليmeshPart:ApplyMesh(newMeshPart)endlocal function setupMeshTexture(meshPart, textureIdToEditableImageMap)-- إذا كانت EditableImage موجودة بالفعل لهذا TextureID، استخدمها بدلاً من إنشاء واحدة جديدةif textureIdToEditableImageMap[meshPart.TextureID] thenmeshPart.TextureContent =Content.fromObject(textureIdToEditableImageMap[meshPart.TextureID])returnend-- إنشاء EditableImage جديدة وتطبيقها كمحتوى للأنسجةlocal editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(meshPart.TextureID))textureIdToEditableImageMap[meshPart.TextureID] = editableImagemeshPart.TextureContent = Content.fromObject(editableImage)endlocal function setupModel(model)-- خريطة لإعادة استخدام مثيلات EditableImage حسب معرف الأنسجةlocal textureIdToEditableImageMap = {}for _, descendant in model:GetDescendants() doif not descendant:IsA("MeshPart") thencontinueend-- تكوين MeshPart بناءً على وجود WrapTarget-- إذا كان WrapTarget موجودًا، أضف WrapDeformer كطفل مع EditableMesh-- خلاف ذلك، قم بتطبيق EditableMesh على MeshPart مباشرةlocal wrapTarget = descendant:FindFirstChildOfClass("WrapTarget")if wrapTarget thensetupBodyPart(descendant, wrapTarget)elsesetupRigidMesh(descendant)end-- تكوين EditableImage لـ MeshPartsetupMeshTexture(descendant, textureIdToEditableImageMap)endendأنشئ أدوات EditableImage التي تسمح للاعبين بتغيير الألوان أو الرسم أو إضافة ملصقات إلى جسمك الأساسي. يمكنك استخدام واجهات برمجة التطبيقات مثل DrawImage()، وDrawRectangle()، وWritePixelsBuffer().
للتحويلات المتقدمة، DrawImageTransformed() يتيح لك تحديد الموقع والدوران والنطاق عند رسم EditableImage ضمن EditableImage آخر. بالمثل، 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)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 = (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
باستخدام WrapDeformer وEditableMesh، أنشئ أدوات لتعديل تشوهات الشبكة على جسمك.
WrapDeformer يتعامل مع التشوهات الحية لهندسة MeshPart المعروض مع الحفاظ على بيانات الجلد وFACS الأساسية.
EditableMesh يسمح لك بتعديل الشبكة الهيكلية التي تستجيب لها WrapDeformer.
- استخدم WrapDeformer:SetCageMeshContent() لتطبيق مثيل EditableMesh الذي يمثل الشبكة الهيكلية ذات الصلة إلى WrapDeformer.
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
إنشاء دعوة الإنشاء
بعد إعداد جسمك الأساسي وواجهات برمجة التطبيقات للتعديل، أنشئ دعوة للمستخدمين لإنشاء وشراء من التجربة باستخدام AvatarCreationService:PromptCreateAvatarAsync().
export type BodyPartInfo = {
bodyPart: Enum.BodyPart,
instance: Instance --Folder with Created 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("تم التحميل بنجاح بمعرف Bundle: ", bundleIdOrErrorMessage)
print("تم التحميل بنجاح بمعرف Outfit: ", outfitId)
else
print("فشل التحميل مع رسالة الخطأ:", bundleIdOrErrorMessage)
end
else
print("فشل إنشاء الصورة الرمزية")
end
endAvatarCreationService:PromptCreateAvatarAsync() يأخذ معلمة HumanoidDescription لتمثيل الصورة الرمزية المراد شراؤها أو إنشاؤها. لإنشاء صورة رمزية، يجب أن تشمل HumanoidDescription للشخصية الأصول الجديدة التي سيتم إنشاؤها لكل من 6 أجزاء الجسم (Head، Torso، RightLeg، LeftLeg، RightArm، LeftArm). اختيارياً، يمكن أن تتضمن أيضاً اكسسوار جديد من نوع Hair.
لدعم ذلك، يجب أن تتضمن HumanoidDescription 6 أطفال من نوع BodyPartDescription. كل خاصية BodyPartDescription.Instance تشير إلى Folder التي تحتوي على جميع مثيلات MeshPart المكونة للجزء الجسم. على سبيل المثال، تحتوي مجلد LeftArm على LeftHand وLeftUpperArm وLeftLowerArm من نوع MeshParts. يجب أيضاً تعيين خاصية BodyPartDescription.BodyPart إلى Enum.BodyPart ذي الصلة.
يجب أن تحتوي كل من الأجزاء الـ15 من MeshPart على:
يجب ألا تتضمن HumanoidDescription المقدمة أي معرفات أصول موجودة مسبقًا لتمثيل أجزاء الجسم أو الاكسسوارات ذات الصلة بالإنشاء المقصود. من ناحية أخرى، يمكن أن تتضمن HumanoidDescription مقاييس البشر لـ BodyTypeScale، HeadScale، HeightScale، WidthScale، و ProportionScale. كن حذرًا بشأن المقاييس التي تم استيراد جسم أساسي بها لضمان تطابقها مع المقاييس المقدمة إلى HumanoidDescription.

تضمين الاكسسوارات
إذا كنت تتضمن اكسسوارًا، مثل الشعر، يجب أن تتضمن HumanoidDescription طفلًا من AccessoryDescription حيث:
- تشير خاصية AccessoryDescription.Instance إلى مثيل Accessory.
- يتم تعيين خاصية AccessoryDescription.AccessoryType إلى Enum.AccessoryType ذي الصلة.
- في حالة تضمين Enum.AccessoryType.Hair في إنشائك، يجب أن تتضمن MeshPart صورة قابلة للتعديل EditableImage. ومع ذلك، يجب ألا تتضمن طفل WrapDeformer ولكن يجب أن تتضمن EditableMesh معين على MeshPart مباشرة.
إنشاء رمز إنشاء الصورة الرمزية
تأخذ AvatarCreationService:PromptCreateAvatarAsync() معلمة معرف رمز إنشاء الصورة الرمزية. هذا الرمز هو المفتاح لإنشاءات من الكون الخاص بك، ويمكن استخدامه لتحديد سعر إنشاء الصورة الرمزية من تجربتك. للحصول على التعليمات والتفاصيل الإضافية حول توليد الرموز، راجع رموز إنشاء الصور الرمزية.
بعد شراء وتوليد الرمز الخاص بك، يمكنك فحص الرمز في مركز المبدعين للعثور على المعرف الذي يمكنك استخدامه بعد ذلك API AvatarCreationService:PromptCreateAvatarAsync().

الرد على انضمام اللاعبين من خلال النسبة
تشمل حزم الصور الرمزية التي تم إنشاؤها داخل التجربة رابط نسبة إلى التجربة الأصلية التي تم فيها إنشاء الصورة الرمزية. إذا تم فحص الصورة الرمزية من قبل لاعب آخر، فإن دعوة تظهر لتوفير خيار زيارة التجربة التي تم إنشاء الصورة الرمزية فيها.

للتعامل مع اللاعبين الذين ينضمون إلى تجربتك باستخدام رابط النسبة، استخدم Player:GetJoinData() وقم بتحليل الجدول المُرجع من أجل GameJoinContext.
يتضمن GameJoinContext القيم الجدول التالية:
- JoinSource — Enum.JoinSource
- سيكون منضم Player إلى تجربتك من خلال هذا الرابط النسبوي لديه Enum.JoinSource.CreatedItemAttribution للإشارة إلى الدخول من عنصر تم إنشاؤه.
- ItemType — Enum.AvatarItemType اختياري
- AssetId — string اختياري
- OutfitId — string اختياري
- AssetType — Enum.AssetType اختياري