島内取引の Verse の仕掛けには、島内取引のテンプレートが含まれています。 これには、Verse API のマーケットプレイス モジュールの主要な要素の実装が全て含まれています。 これにはアイテム、オファー、バンドル オファー、そしてデフォルトのストアフロント UI を活用した購入の処理が含まれます。 このコードをガイドとして、ストアフロントを素早く設定しましょう。
以下の手順で仕掛けにアクセスします。
[Verse Explorer] に移動します。
プロジェクト名を右クリックします。
[Add new Verse file to project (新規 Verse ファイルをプロジェクトに追加)] を選択します。
島内取引の仕掛けを選択します。
アイテムを作成する
アイテムは Verse ではエンタイトルメントとして定義され、消耗アイテムと耐久アイテムの 2 つのカテゴリーに分類されます。消耗アイテムは使用するとプレイヤーのインベントリから削除され、耐久アイテムはインベントリから削除されずにプレイヤーが使い続けることができます。
EntitlementInfo モジュール
モジュールは、複数のファイルで使用するために再配布可能なコードの最小単位です。 モジュールは、すでにそのモジュールが使用されているファイル内の依存関係を損なうことなく、時間の経過とともに変更することが可能です。 エンタイトルメント定義のような長くて繰り返しの多いコード単位を別のファイルに分割し、using 文を使ってインポートすることができます。
EntitlementInfo モジュールは、テンプレート内のすべてのエンタイトルメントの名前、説明、簡潔な説明を収集します。 このモジュールは、同じ製品の名前やその他の変数を繰り返し再定義する必要なく、エンタイトルメントを定義する必要がある任意のファイルに含めることができます。これにより、エンタイトルメント情報の変更が容易になり、エンタイトルメントのデバッグの複雑さが軽減されます。
# Setup your entitlements and offers data, in this case that's your Names, Descriptions & Short Descriptions as well as any other data you want to be constant
EntitlementInfo<public> := module:
Potion<public> := module:
Name<public><localizes>:message = "Potion"
Description<public><localizes>:message = "Adds +10 health when used. Green so you know its healthy!"
エンタイトルメントを定義する
全ての Verse エンタイトルメントには次のプロパティがあります。
Name:最大 50 文字のエンタイトルメント名
Description:エンタイトルメントに表示される最大 500 文字の長い説明。
ShortDescription:エンタイトルメントを要約した最大 100 文字の短い説明。
Icon:エンタイトルメントの画像。
エンタイトルメントが有料ランダム アイテムである場合、プレイヤーが受け取る可能性のあるものの説明に正確な数値確率を含める必要があります。 詳細については、「有料ランダム アイテム」をご参照ください。
Verse のエンタイトルメントには次のオプション プロパティもあります。
MaxCount:プレイヤーが一度に所有できるそのエンタイトルメントの最大数。
消耗品:「true」に設定すると、エンタイトルメントは
ConsumeEntitlementで消費できます。これにより、Epic のシステムでユーザーが保持するエンタイトルメントの総数が減ります。mi 「false」に設定すると、エンタイトルメントは永久的なアイテムとなり、使用しても消費されません。PaidArea:「true」に設定すると、そのエンタイトルメントは有料エリアへのアクセスを提供します。
PaidRandomItem:「true」に設定すると、これらのエンタイトルメントはコンテンツの購入または引き換えによって取得され、ランダムな報酬を得ることができます。
ConsequentialToGameplay:これを「true」に設定した場合、このアイテムはあなたの島で大きな利点を持つようになります。 詳細は、「ゲームプレイに影響する」をご参照ください。
以下のスニペットでは、以前に定義された EntitlementInfo モジュールを使用してエンタイトルメントの定義を構築します。 消耗品のエンタイトルメントを定義するには、Consumable を「true」に設定する必要があります。
エンタイトルメントを定義する前に、エクスペリエンス内のエンタイトルメントで使用される基本的なエンタイトルメントクラスを作成する必要があります。
— この場合は、feature_example_entitlement です。
各エンタイトルメント定義のアイコンテクスチャへのファイルパスを定義する必要があります。定義しない場合、エンタイトルメント定義は検証に失敗します。
Entitlements<public> := module:
using {EntitlementInfo}
# The base entitlement you should define for ALL your entitlements in your experience
feature_example_entitlement<public> := class<abstract><castable>(entitlement){}
basic_sword<public> := class<concrete>(feature_example_entitlement):
var Name<override>:message = Sword.Name
デフォルトでは、アイテムは消耗品ではなく、MaxCount は 1 です。 アイテムが有料エリア、有料ランダム アイテム、またはゲームプレイに影響を与える重要な利点を提供する場合は、関連するフィールドをコードで定義する必要があります。
エンタイトルメント オファー
オファーは、アイテムまたはアセットの価格を V-Bucks で指定します。 各オファーには、エンタイトルメントの仕様とは別に、独自の名前、説明、アイコンがあります。 オファーは Verse で定義されます。
エンタイトルメントを販売するには、そのエンタイトルメントに対応するオファーが必要です。
全てのオファーには次のプロパティがあります。
Name:オファー名。
Description:オファーと共に表示される長い説明文。
ShortDescription:小さなダイアログ ボックス内のオファーの概要をまとめるための短い説明。
Icon:オファーの画像。
EntitlementType:オファーに含まれるエンタイトルメントの宣言。
価格:V-Bucks の価格。 50 V-Bucks 以上 5000 V-Bucks 以下である必要があります。 価格は 50 の倍数で設定する必要があります。
このスニペットは、エンタイトルメント オファーを定義する方法を示します。基本的なエンタイトルメント情報については、既存の EntitlementInfo モジュールを使用します。 同様に EntitlementType も定義する必要があります。
これは、オファーのエンタイトルメントと V-Bucks での価格を定義します。 オファーのオプションとして、固定値、国コード、プラットフォーム ファミリーによる制限、またはこれらの要素の組み合わせに応じて、最小購入年齢を定義することもできます。 この例のいくつかを以下のスニペットで示します。
サブディビジョン コードは現在サポートされていませんが、今後のリリースで利用可能になる予定です。
ExampleOffers<public> := module:
using {EntitlementInfo}
basic_sword<public> := class(entitlement_offer):
var Name<override>:message = EntitlementInfo.Sword.Name
var Description<override>:message = EntitlementInfo.Sword.Description
var ShortDescription<override>:message = EntitlementInfo.Sword.ShortDescription
V-Bucks の価格は 50 の倍数で、50~5000 V-Bucks の範囲で設定する必要があります。
有料ランダム アイテムについては、プレイヤーがオファーの詳細で各有料ランダム アイテムを入手する正確な数値の確率を確認できるようにしなければなりません。 そうしない場合はフォートナイト デベロッパー規約の違反とみなされ、該当するユーザーとその島は適切な制裁の対象となります。
詳しくは「島内の取引の制限」を参照してください。
バンドル オファー
バンドルは Verse で定義され、異なるオファーの組み合わせ、同じオファーのスタック、または両方の組み合わせを含めることができます。 単純なオファーと同様に、バンドル オファーは独自の価格、名前、説明を指定し、エンタイトルメントやオファーとは異なるアイコンが付いています。 バンドル オファー内にバンドルを含めることで、オファーをネストすることもできます。 一例としては、シャベルとトウモロコシの種の袋が含まれる期間限定バンドルなどがあります。 こうすることで、小さなバンドルをより大きな結合バンドルの構成要素として使用できるようになります。
標準のバンドル タイプは次のとおりです。
スタック バンドル:同じエンタイトルメントの複数のオファーを含むバンドルで、通常は割引価格で提供されます。
複数オファー バンドル:複数のエンタイトルメントに対するオファーを組み合わせたバンドルで、スタックされたオファーと通常のオファーの組み合わせも含まれます。
バンドルには、定義されたオファーとオファーの数を示す int を含むタプル配列のオファーが含まれています。
ネストされたオファーの深さは 5 を超えることはできず、超えた場合、試行されたトランザクションは失敗します。 可能な限り、オファーのネストを制限するようにしてください。
以下のスニペットは、ポーション パック バンドルの作成方法を示しています。 オファー情報は、PotionCount 変数を含む EntitlementInfo モジュール内で定義されます。
ExampleOffers<public> := module:
using {EntitlementInfo}
<# --- other offer definitions above --- #>
potion_pack<public> := class(bundle_offer) :
var Name<override>:message = EntitlementInfo.PotionPack.Name
購入制限
エンタイトルメントの購入を制限することで、限定のホリデー アイテムやプロモーション、季節限定オファーの作成を可能にし、地域特有のコンテンツを作成できます。
GetMinPurchaseAge
GetMinPurchaseAge を使用して、特定の entitlement_offer に対するカスタム購入制限を定義します。 これは購入検証の一部として自動的に呼び出されるため、定義するだけで十分です。 特定の整数値、国コード、またはプラットフォーム ファミリーを定義できます。
サブディビジョン コードは現在サポートされていませんが、今後のリリースで利用可能になる予定です。
以下は、GetMinPurchaseAge 関数の例です。
# Optional overrideable function you can use to inform Epic systems what the minimum age a player needs to be to purchase this offer
GetMinPurchaseAge<override>(CountryCode:string, SubdivisionCode:string, PlatformFamily:string)<decides><computes>:int =
# A Hypothetical example where you only want to sell swords to people who don't live in Antarctica
CountryCode <> CountryCodes.Antarctica
return 0
プレイヤーのエンタイトルメントを検証
プレイヤーのエンタイトルメントの検証は、プレイヤーが購入したエンタイトルメントがセッション間で持続するために必要な手順です。 エンタイトルメントの検証が正しく行われないと、エンタイトルメントの複製やエンタイトルメントの喪失などの問題が発生する可能性があります。
以前の購入を検証する
次のスニペットは、プレイヤーがセッションに参加する際に実行されるシンプルなエンタイトルメント検証を示しています。 まず、受信したプレイヤーが OnPurchasesChanged イベントにサブスクライブされているかどうかを確認します。 次に、まだサブスクライブされていない場合、プレイヤーがサブスクライブされます。 最後に、ValidatePreviousPurchases 関数を使用して、そのプレイヤーが購入した全てのエンタイトルメントに関する記録が取得されます。
この段階でプレイヤーのエンタイトルメントの検証チェックを実行し、エクスペリエンスに保存されたデータが、マーケットプレイス API によって所有されているとされるものとプレイヤーのインベントリが一致していることを確認することをお勧めします。
OnPlayerJoin(InPlayer:player):void =
Subscription := GetEntitlementsChangedEvent(InPlayer, Entitlements.feature_example_entitlement).Subscribe(OnPurchasesChanged)
if (set EntitlementChangeSubscription[InPlayer] = option{Subscription}):
Print("Adding entitlement Change Subscription player subscription")
# On players joining you are likely going to want to run some validation checks to make sure that any data you save
購入の処理
エンタイトルメントの購入を処理するために使用される主な関数には、BuyOffer および OnPurchasesChanged の 2 つがあります。 最初の機能は、プレイヤーにオファーを提示し、購入を検証するためのロジックを処理します。 2 つ目の関数は、取引の成功または返金に関するロジックを処理します。 以下のスニペットは、これら 2 つの関数を示しています。
# Base Implementation of how to present players with an offer to purchase in your experience
TryBuyOffer(Player:player, Offer:entitlement_offer)<suspends>:void =
Result := BuyOffer(Player, Offer)
if (Result?):
# do nothing it should respond in the purchase subscription, see OnPurchasesChanged for details
消耗品を処理する
消耗可能なエンタイトルメントを消費するには、マーケットプレイス Verse API の ConsumeEntitlement 関数を使用する必要があります。 消費が成功したら、消費後に生成された効果のロジックを処理する必要があります。 プレイヤーが所有するエンタイトルメントのカウントは、関数内で消費されたカウントだけ減少します。
以下のスニペットは、指定されたプレイヤーによって特定のエンタイトルメントが消費される方法を示しています。
# Base Implementation of how to flag a consumable in your experience as being consumed
TryConsumeEntitlement(Player:player, Entitlement:concrete_subtype(entitlement), NumberConsuming:int)<suspends>:void =
Result := ConsumeEntitlement(Player, Entitlement, ?Count := NumberConsuming)
if (Result?):
Print("Successfully consumed entitlement!")
永続的なエンタイトルメントは消費できません。 試みようとすると、ConsumeEntitlement は失敗します。
エンタイトルメントの付与
V-Bucks を必要とするエンタイトルメントの購入とは異なり、GrantEntitlement メソッドを使用してプレイヤーにエンタイトルメントを付与することもできます。
エンタイトルメントを付与するユースケースには、プロモーション アイテム、消耗品の無料サンプル、バグや不具合で失われたアイテムの復元などが含まれます。
このスニペットは、プレイヤーにエンタイトルメントを付与する方法を示しています。
# Base Implementation of how to give players a entitlement in your experience without them purchasing it
TryGrantEntitlement(Player:player, Entitlement:concrete_subtype(entitlement), NumberToGrant:int)<suspends>:void =
Result := GrantEntitlement(Player, Entitlement, ?Count := NumberToGrant)
if (Result?):
Print("Successfully granted a player your entitlement!")
エンタイトルメントの最大数を超えるか、永続的なエンタイトルメントを 1 つ以上付与しようとすると、エンタイトルメントの付与が失敗します。
プレイヤーにエンタイトルメントオファーを表示する
Marketplace moduleは、ShowOffersDialog 機能を使用し、島で使用するためのビルトインのストアフロント UI を提供します。 以下のスニペットは、特定のプレイヤー向けのオファーを表示するストアフロントの方法を示しています。
# Base Implementation of how to show an array of offers to the player that are available for purchase
ShowArrayOfOffers(Player:player)<suspends>:void =
ShowOffersDialog(Player, array{ExampleOffers.basic_sword{}, ExampleOffers.potion{}, ExampleOffers.potion_pack{}, ExampleOffers.potion_thanksgiving{}, ExampleOffers.potion_gib{}})完全なコード
using { /Fortnite.com/Devices }
using { /Fortnite.com/Marketplace }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Assets }
using { /Verse.org/Simulation }