メイクアップのための体験内作成

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

プレイヤーがリアルタイムでメイクアップアセットを作成、カスタマイズ、購入できる体験を公開できます。これは、体験内アバターのボディ作成に加えて行えます。購入されたメイクアップアセットは、プレイヤーの Roblox インベントリに直接保存されます。

体験の所有者が体験内メイク作成を実装すると、メイクアップアセットの発行者としてマーケットプレイスの手数料の恩恵を受ける一方で、アセットを作成したプレイヤーはそのアセットのクリエイターとなります。

体験内メイク作成の実装方法

以下の手順とコードリファレンスを使用して、プレイヤーにアバターの頭にメイクアップアセットをペイント、組み立て、購入するよう促します。

始める前に、以下の内容に目を通してください。

  • アバター作成トークン — メイク作成を実装する体験には、作成するメイクアップアセットのタイプに一致する少なくとも1つの作成トークンが必要です。
  • API クラス
    • AvatarCreationService — アバターアセットの作成を促す処理と検証を行います。
    • EditableImage — テクスチャのランタイム作成と操作を行います。
    • EditableMesh — メッシュジオメトリのランタイム操作を行います。
    • WrapDeformer — アバターキャラクターが3D 衣服やアクセサリーを装備できるようにするための、見えない外部ケージジオメトリのランタイム操作を行います。これには、レイヤー状の眉毛やまつげメッシュが含まれます。
    • WrapTarget — ケージメッシュとターゲットメッシュの間のバインディングを表し、両者間のテクスチャ空間変換を公開します。
    • WrapTextureTransfer — メイクアップデカールを含むデカールが、親メッシュの WrapTarget に基づいてラッピングされるのを容易にします。

単一アセットまたは複数アセットのフローを選択

メイク作成は、1つのメイクアップアセットを作成するか、複数のレイヤーを1つのアウトフィットに合成するかによって、2つのプロンプトをサポートします。

  • AvatarCreationService:PromptCreateAvatarAssetAsync() — 単一の個別に作成されたメイクアップアセットを作成します。5つのサポートされている Enum.AvatarAssetType 値のいずれかを渡します:FaceMakeup、LipMakeup、または EyeMakeup(ペイントされたテクスチャ用)、または EyebrowAccessory または EyelashAccessory(レイヤー状のメッシュアクセサリー用)。トークンの作成タイプは、渡す assetType と一致する必要があります。
  • AvatarCreationService:PromptCreateMakeupAsync() — 2つ以上のメイクレイヤーを1つの購入可能なアウトフィットに合成します。各レイヤーは独自の作成トークンと Enum.AvatarAssetType を提供し、合成のためのソート順を指定し、全体のアウトフィットは1つのヘッドカラーを共有します。1つのメイクアップアセットを作成するだけの場合は、代わりに PromptCreateAvatarAssetAsync() を使用してください。PromptCreateMakeupAsync() は、少なくとも2つのエントリが必要です。

PromptCreateMakeupAsync() は、メイクアップアセットエントリのリストを受け取ります。各エントリには以下が含まれます:

  • そのレイヤーの作成トークン ID。
  • アセットを作成するためのインスタンス。
  • レイヤーの AvatarAssetType(Enum.AvatarAssetType として)。
  • 複数のレイヤーが重なるときの合成を制御するソート順。

全体のアウトフィットに対して Enum.PromptCreateMakeupResult を返します(Success、PartialSuccess、CreationFailure、PermissionDenied、Timeout、NoUserInput、または UnknownFailure)、さらに個々のアセットの結果も返すため、全体の結果が PartialSuccess のときにどのレイヤーが成功したかを知ることができます。

アバター作成トークンを生成する

各メイクアップアセットタイプには、PromptCreateAvatarAssetAsync() に渡す Enum.AvatarAssetType と一致する作成タイプを持つ独自のアバター作成トークンが必要です。また、PromptCreateMakeupAsync() を使用する場合は、各レイヤーのアセットタイプと一致する必要があります。提出エントリを構築する前に必要なトークンを生成し、サーバー側のプロンプト用に各トークン ID をコピーします。

トークンタイプのドロップダウンがアイメイクに設定されており、トークンのコンテキストメニューが開いてコピー トークン ID オプションが表示されています。

以下の手順では、プレイヤーの頭に投影ペイントを使用することを主な経路とします。代わりに、オーサリングヘッドや他の体験所有のメッシュをそのネイティブ UV スペースでペイントする場合は、ケージスペースとターゲットスペース間でテクスチャを移動するに従い、その後デカールを作成して作成のために提出するでメインパスに再接続します。

プレイヤーの頭にメイクアップテクスチャをペイントする

新しいアセットにペイントするのとは異なり、一般的にローカルプレイヤーの頭から EditableMesh を直接読み取ってペイントすることはできません。ヘッドメッシュは他のプレイヤー所有のインスタンスと同じ権限モデルの対象です。例外は、体験がヘッドメッシュを所有している場合(たとえば、体験所有の NPC や体験自体が作成したボディ)で、その場合は EditableMesh を直接使用できます。これは、アバターのボディ作成と同じ方法です。それ以外の場合は、WrapTextureTransfer を準備し、描画時の投影ターゲットとして使用します:

  1. WrapTextureTransfer:PrepareProjectionMeshDataAsync() を呼び出して、プレイヤーの頭の投影メッシュデータを準備してキャッシュします。これは、転送に対して投影描画またはサンプル呼び出しを行う前に完了する必要があります。基になるヘッドメッシュが変更された場合は、ペイントを続ける前に WrapTextureTransfer を再準備してください。
  2. 準備した WrapTextureTransfer を投影ソースとして DrawImageProjected() または SampleImageProjected() に渡します。これらのメソッドは、EditableMesh の代わりに WrapTextureTransfer を受け入れ、プレイヤーの実際の頭の形状に対して直接ペイントできるようにします。
local AssetService = game:GetService("AssetService")
-- プレイヤーの頭のためにすでに作成した WrapTextureTransfer を渡します。
local function paintMakeupLayer(textureTransfer: WrapTextureTransfer, brushConfig, projectionParams)
local success, err = pcall(function()
textureTransfer:PrepareProjectionMeshDataAsync()
end)
if not success then
warn("投影メッシュデータの準備に失敗しました:", err)
return
end
local makeupTexture = AssetService:CreateEditableImage()
if not makeupTexture then
warn("メイクアップテクスチャを作成するための編集可能なメモリが不足しています")
return
end
makeupTexture:DrawImageProjected(textureTransfer, projectionParams, brushConfig)
return makeupTexture
end

ケージスペースとターゲットスペース間でテクスチャを移動する

準備された WrapTextureTransfer を介してプレイヤー所有の頭に直接ペイントすることは、プレイヤーの頭にメイクアップテクスチャをペイントするで説明したように、ヘッドメッシュのターゲット UV スペースでは始まりません。投影パスは、全体を通して共有ケージ UV レイアウトで機能するため、結果はすでに提出の準備が整ったケージスペーステクスチャです。

ケージ/ターゲット変換は、オーサリングヘッドや、そのネイティブターゲット UV スペースで直接ペイントできる体験所有のメッシュを扱う場合に重要です:

CreateTextureInTargetSpaceAsync() を使用して、再利用可能なケージスペースメイクアップテクスチャをそのメッシュのターゲットスペースに持ち込み、編集後に CreateTextureInCageSpaceAsync() を使用して、編集結果をケージスペースに戻してメイクアップアセットとして提出します。

メイクアップの場合、ケージスペース変換をメイクアップ領域に制限し、全体のケージではなくメイクアップ領域を使用します。AvatarCreationService:GetValidationRules() を呼び出し、MakeupRules.WrapTextureTransferUVBounds を読み取ります。これにより、MinBound と MaxBound が Vector2 値として提供されます。これらを CreateTextureInCageSpaceAsync() に MinUVBounds と MaxUVBounds として渡します。これらのオプションがない場合、メソッドは全体のケージから境界を導出します。各境界は有限でなければならず、最大値は両軸で最小値より大きくなければなりません。

local AvatarCreationService = game:GetService("AvatarCreationService")
local validationRules = AvatarCreationService:GetValidationRules()
local makeupBounds = validationRules.MakeupRules.WrapTextureTransferUVBounds
local cageSpaceTexture = wrapTarget:CreateTextureInCageSpaceAsync(targetSpaceTexture, {
MinUVBounds = makeupBounds.MinBound,
MaxUVBounds = makeupBounds.MaxBound,
})

デカールを作成して作成のために提出する

顔、唇、目のメイクアップはペイントされたテクスチャであり、眉毛やまつげは、他の3D 衣服やアクセサリーと同様に、個別に作成されたレイヤー状のメッシュアクセサリーです。各レイヤーの提出エントリをそれに応じて構築します:

得られたインスタンスを、アバター作成トークンを生成するからの一致するトークン ID、そのアセットタイプ、およびレイヤー順序と組み合わせます。以下のサンプルは、いずれかの種類のエントリを受け取り、単一エントリの場合は AvatarCreationService:PromptCreateAvatarAssetAsync() を自動的に選択し、2つ以上のレイヤーを1つのアウトフィットに合成する場合は AvatarCreationService:PromptCreateMakeupAsync() を選択します。

両方のプロンプトは、アセットを作成およびモデレーションのために提出する前に、プレイヤーに最終確認画面を表示します。

local AssetService = game:GetService("AssetService")
local AvatarCreationService = game:GetService("AvatarCreationService")
type MakeupEntry = {
tokenId: string,
instance: Instance,
assetType: Enum.AvatarAssetType,
sortOrder: number,
}
-- 顔、唇、目のメイクアップ:完成したテクスチャをデカールにラップし、
-- ペイントに使用した WrapTextureTransfer をデカールの唯一の子として親子関係を持たせます。
local function createMakeupTextureEntry(
tokenId: string,
texture: EditableImage,
textureTransfer: WrapTextureTransfer,
assetType: Enum.AvatarAssetType,
sortOrder: number
): MakeupEntry
local decal = AssetService:CreateDecalAsync({
TextureContent = Content.fromObject(texture),
})
decal.Face = Enum.NormalId.Front
textureTransfer.Parent = decal
return {
tokenId = tokenId,
instance = decal,
assetType = assetType,
sortOrder = sortOrder,
}
end
-- 眉毛やまつげ:作成されたレイヤー状のメッシュアクセサリーを直接渡します。
local function createMakeupAccessoryEntry(
tokenId: string,
accessory: Accessory,
assetType: Enum.AvatarAssetType,
sortOrder: number
): MakeupEntry
return {
tokenId = tokenId,
instance = accessory,
assetType = assetType,
sortOrder = sortOrder,
}
end
local function submitMakeupEntries(entries: {MakeupEntry}, player: Player, headColor: Color3?)
local assetEntries = {}
for _, entry in entries do
table.insert(assetEntries, {
TokenId = entry.tokenId,
Instance = entry.instance,
AvatarAssetType = entry.assetType,
SortOrder = entry.sortOrder,
})
end
if #assetEntries == 1 then
local entry = assetEntries[1]
local success, result, assetIdOrErrorMessage = pcall(function()
return AvatarCreationService:PromptCreateAvatarAssetAsync(
entry.TokenId,
player,
entry.Instance,
entry.AvatarAssetType
)
end)
if success and result == Enum.PromptCreateAssetResult.Success then
print("AssetId で正常にアップロードされました:", assetIdOrErrorMessage)
else
print("メイクアップアセットの作成に失敗しました:", assetIdOrErrorMessage)
end
else
local success, result, perAssetResults = pcall(function()
return AvatarCreationService:PromptCreateMakeupAsync(player, assetEntries, headColor)
end)
if success and result == Enum.PromptCreateMakeupResult.Success then
print("メイクアップアウトフィットが正常に作成されました")
else
print("メイクアップアウトフィットの作成結果:", result, perAssetResults)
end
end
end

モデレーションの処理

メイクアップアセットが作成された後、それは体験内で使用するのに安全であることを確認するためにモデレーションを経ます。

  • AvatarAssetModerationCompleted をリッスンして、PromptCreateAvatarAssetAsync() で作成された個々のメイクアップアセットのモデレーションが完了したときに知ることができます。
  • PromptCreateMakeupAsync() で作成されたマルチレイヤーのアウトフィットの場合、AvatarAssetModerationCompleted はアウトフィット内の各個別のメイクアップアセットに対して1回発火し、さらに AvatarOutfitModerationCompleted がアウトフィット全体に対して1回発火します。両方をリッスンしてください:特定のレイヤーのモデレーション結果を知る必要がある場合は個別のイベントを使用し、全体のルックが体験内で使用するのに安全であることを知るにはアウトフィットレベルのイベントを使用します。
©2026 Roblox Corporation。Roblox(ロブロックス)、RobloxロゴおよびPowering Imaginationは、米国並びにその他の国における登録商標および非登録商標です。