【Roblox】開発者製品の購入について
はじめに
今回は開発者製品の購入のプログラムについて紹介します。
Robloxバージョン:0.638.1.6380615
参考にした記事・サイト
購入ダイアログを出す
MarketplaceService:PromptProductPurchase(localPlayer, assetId)
MarketplaceServiceのPromptProductPurchase
を呼ぶことで開発者製品の購入ダイアログを作成できます。
引数
localPlayer:ダイアログを出したいPlayer
assetId:購入させたいアセットのId
購入ダイアログ
上記ダイアログにある値段や名前、アイコンなどはRobloxのダッシュボードで設定したものが表示されます。
プログラム上で変更や編集はできないので注意が必要です。
※編集はダッシュボードでできます。
購入ダイアログを閉じた
-- 購入ダイアログを閉じた際に呼ばれる
local function onPromptProductPurchaseFinished(userId:number, productId:number, isPurchased:boolean)
local player = game:GetService("Players"):GetPlayerByUserId(userId)
if isPurchased then
-- 購入に成功した場合
print("Success to purchase", player, productId)
else
-- 購入に失敗した場合
error("Failure to purchase", player, productId)
end
end
MarketplaceService.PromptProductPurchaseFinished:Connect(onPromptProductPurchaseFinished)
MarketplaceServiceのPromptProductPurchaseFinished
は購入ダイアログを閉じた際に呼ばれる関数を設定できるイベントです。
登録したメソッドの引数
userId:購入ダイアログを閉じたPlayerのユーザーId
productId:開発者製品のアセットId
isPurchased:購入されたかどうか(キャンセルでダイアログを閉じた場合はfalse)
注意点はダイアログが閉じた際に開発者製品の効果を付与するのは遅いということです。
このタイミングでDataStoreに課金情報を保存する場合、ダイアログを閉じずにゲームから退出したユーザーには効果が付与されない可能性があります。
購入後の効果の付与は次の項目で説明します。
購入後の結果の付与
-- 開発者製品の購入確認処理
local function processReceipt(receiptInfo)
return Enum.ProductPurchaseDecision.PurchaseGranted
end
-- 開発者製品 購入時に呼ばれる。
MarketplaceService.ProcessReceipt = processReceipt
MarketplaceServiceのProcessReceipt
コールバックに関数を設定することで開発者製品が購入された後すぐにこのメソッドが呼ばれます。
購入後の効果の反映はここで行います。(コインの追加や攻撃力の追加など)
引数
receiptInfo:
このコールバックに渡されるreceiptInfoテーブルには、次のデータが含まれます。
PurchaseId — 特定の購入の一意の識別子。(ランダムに割り振られた商品ごとの固有のId)
PlayerId — 購入したプレイヤーのユーザー ID。
ProductId — 購入した製品の ID。(アセットId)
PlaceIdWherePurchased — 購入が行われた場所の ID。必ずしも現在の場所の ID と同じではありません。
CurrencySpent — トランザクションで費やされた通貨の金額。
CurrencyType — 購入に使用された通貨の種類。常にEnum.CurrencyType.Robux です。
注意点
設定したメソッドはEnum.ProductPurchaseDecision
を返す必要があります。
これが返されることで購入が完了or失敗したとみなされるためです。
MarketplaceService.ProcessReceipt
はイベントではないため、1つしか設定できません。
ほかのScriptからも設定すると予期せぬ挙動になるようです。
開発者製品はパスと違い、ユーザーが購入したかどうかを自分(製作者)が管理しないといけません。
また、このコールバックはユーザーが未解決の購入があった場合に、再度サーバーに入った時に呼ばれる場合があります。
⇒ DataStoreを用いてユーザーに対して効果を付与済みかどうかを保存する必要があります。
-- 開発者製品を保存する用のデータストア
local DataStoreService = game:GetService("DataStoreService")
local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")
-- 開発者製品の購入確認処理
local function processReceipt(receiptInfo)
-- すでに購入済みかどうかをDataStoreから確認
local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
local purchased = false
local success, errorMessage
success, errorMessage = pcall(function()
purchased = purchaseHistoryStore:GetAsync(playerProductKey)
end)
if success and purchased then
-- すでに効果付与済み
return Enum.ProductPurchaseDecision.PurchaseGranted
elseif not success then
-- DataStoreでエラーが出た
error("Data store error:" .. errorMessage)
end
-- DataStoreに効果付与の状況を保存する
local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
local success, isPurchaseRecorded = pcall(function()
return purchaseHistoryStore:UpdateAsync(playerProductKey, function(alreadyPurchased)
if alreadyPurchased then
-- すでに効果付与済み
return true
end
if not player then
-- このサーバーにプレイヤーがいない
return nil
end
-- 任意の効果付与の関数を実行する
local handler = productPurchaseHandler
local success, result = pcall(handler, receiptInfo.PlayerId, receiptInfo.ProductId, true)
if not success or not result then
-- 効果付与失敗
warn("Failed to process a product purchase for ProductId: " .. tostring(receiptInfo.ProductId) .. " Player: " .. tostring(player) .. " Error: " .. tostring(result))
return nil
end
-- データストアに記録する
return true
end)
end)
-- 効果付与が完了した場合のみ、購入完了とみなす。
if not success then
warn("Failed to process receipt due to data store error.")
return Enum.ProductPurchaseDecision.NotProcessedYet
elseif isPurchaseRecorded == nil then
return Enum.ProductPurchaseDecision.NotProcessedYet
else
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
-- 開発者製品 購入時に呼ばれる。
MarketplaceService.ProcessReceipt = processReceipt
DataStoreに付与済みか確認、Playerがサーバーにいれば効果を付与、結果を保存、購入完了という流れです。
もし細かく開発者製品の購入情報を詳しく保持したければ、DataStoreに保存する内容を増やすことも可能です。
また、こういったユーザーのデータに直接かかわる処理はサーバー側で行ってください。クライアント側で行うと悪用される可能性があります。
まとめ
- 購入のダイアログを出す処理とダイアログを閉じた時に呼ばれる処理はゲームパスと関数名が違うだけでほぼ同じ処理。
- 開発者製品の購入効果の反映は
MarketplaceService.ProcessReceipt
コールバックを使用する。 -
MarketplaceService.ProcessReceipt
の結果はDataStoreに保存する。
公式フォーラムでは、開発者製品の処理は開発者によって自由に作成できるという意見もあります。
自分が作成した処理は一例なのでゲームに沿ったよりよい処理を作成しましょう。
ぜひMarketplaceServiceを使いこなしましょう!!
当社ではRobloxを活用したゲームの開発、 また企業の商品やサービスの認知度拡大に寄与する3Dワールドの制作など、 Robloxにおける様々な活用支援を行っております。 Robloxのコンテンツ開発をご検討されている企業様は、お気軽にご相談ください。 landho.co.jp/
Discussion