Le transazioni all'interno dell'isola ti consentono di promuovere oggetti, offerte e offerte bundle nella tua isola utilizzando Verse.
In questa guida imparerai a configurare i tuoi oggetti, le tue offerte e le offerte bundle. Utilizzando il modulo Marketplace nell'API Verse, potrai gestire la vendita degli oggetti in gioco.
Oggetti
Gli oggetti sono definiti in Verse come diritti e si suddividono in due categorie: oggetti consumabili, che vengono rimossi dall'inventario del giocatore dopo l'uso, e oggetti durevoli, che il giocatore può continuare a utilizzare senza che vengano rimossi dall'inventario.
Ogni diritto Verse presenta le seguenti proprietà:
Nome: il nome del diritto, fino a 50 caratteri
Descrizione: la descrizione estesa visualizzata con il diritto, fino a 500 caratteri.
ShortDescription: una descrizione breve che riassume il diritto in una finestra di dialogo più piccola, fino a 100 caratteri.
Icona: un'immagine del diritto.
Se il diritto corrisponde a un oggetto casuale a pagamento, devi indicare nella descrizione le probabilità numeriche esatte di ciò che il giocatore può ricevere. Per ulteriori informazioni, vedi Oggetti casuali a pagamento.
Un diritto Verse può includere inoltre le seguenti proprietà facoltative:
MaxCount: il numero massimo di quel diritto che il giocatore può possedere contemporaneamente.
Consumabile: se impostato su true, il diritto può essere consumato, riducendo il numero totale di utilizzi. Se false, il diritto è un oggetto permanente e non viene consumato all'uso
PaidArea: se impostato su true, il diritto garantisce l'accesso a un'area protetta da paywall.
PaidRandomItem: se impostato su true, questi diritti vengono acquistati o riscattati tramite contenuti per ottenere una ricompensa casuale.
ConsequentialToGameplay: se impostato su vero, l'oggetto offre un vantaggio significativo nella tua isola. Per maggiori dettagli vediConsequenziale al gameplay.
Se hai oggetti attivi che non sono in uso e non confermi gli acquisti in-app sul questionario IARC, la moderazione della tua isola non andrà a buon fine.
Per ovviare a questo problema, puoi commentare i tuoi diritti in Verse fino a quando non sei pronto a utilizzarli in una partita live. Una volta che i diritti sono stati commentati, non devi richiedere gli acquisti in-app nel questionario IARC.
Creazione di un diritto consumabile in Verse
I diritti sono definiti in Verse, inoltre sono derivati dalla classe basedei diritti. Il seguente snippet mostra come creare un oggetto consumabile. In questo esempio, creerai dei semi di mais come oggetto consumabile. Un'icona dei semi è fornita qui sotto per l'utilizzo.
# The base entitlement you should define for ALL of your entitlements in your experience.
my_island_entitlement := class<abstract><castable>(entitlement){}
CornSeedPacket<public> := module:
Name<public><localizes> : message = "Corn seed pack"
Description<public><localizes> : message = "A pack of corn seeds. Opening a pack yields 10 corn seeds for planting."
ShortDescription<public><localizes> : message = "Contains 10 corn seeds for planting."
cornseedpacket<public> := class<concrete>(my_island_entitlement):
var Name<override>:message = CornSeedPacket.Name
Quando crei un diritto, devi includere il percorso di una texture icona valida affinché il codice Verse venga compilato correttamente. Puoi utilizzare gratuitamente il pacchetto di semi di mais e le altre icone incluse in questa guida!
Assicurati che le icone dei tuoi diritti utilizzino una texture quadrata con dimensioni in potenze di due per ottenere immagini della migliore qualità nella tua vetrina. Per informazioni sull'importazione delle texture in UEFN da utilizzare come icone, consulta Importazione di asset. Per informazioni su come rendere disponibili asset come le texture in Verse, consulta Esposizione degli asset.
Creazione di diritti durevoli in Verse
I diritti durevoli in Verse seguono lo stesso formato dei diritti consumabili, con una differenza principale: Consumabile è impostato su false e non su true. I diritti durevoli possono essere acquistati una sola volta dai giocatori, inoltre i giocatori possono possedere soltanto un diritto durevole per ogni categoria.
In questo esempio, potrai creare una pala come diritto durevole. Un'icona per la texture della pala è fornita dopo lo snippet riportato qui sotto.
Shovel<public> := module:
Name<public><localizes>: message = "Shovel"
Description<public><localizes>: message = "An unbreakable shovel used to dig holes for planting."
ShortDescription<public><localizes>: message = "Digs holes."
shovel<public> := class<concrete>(my_island_entitlement):
var Name<override>:message = Shovel.Name
var Description<override>:message = Shovel.Description
var ShortDescription<override>:message = Shovel.ShortDescription
var Icon<override>:texture = # path to your texture here
Per impostazione predefinita, gli oggetti non sono Consumable e hanno MaxCount = 1. Se l'oggetto è un'area a pagamento, un oggetto casuale a pagamento oppure offre un vantaggio significativo che è consequenziale al gameplay, i relativi campi dovranno essere definiti nel tuo codice.
Regole di convalida dei diritti
Un diritto valido in Verse deve rispettare le seguenti linee guida. Gli acquisti di un diritto che non le rispetta non andranno a buon fine.
Le regole che definiscono un diritto valido sono le seguenti:
Name (nome) ha un limite di 50 caratteri.
Description (descrizione) ha un limite di 500 caratteri.
ShortDescription (descrizione breve) ha un limite di 100 caratteri.
MaxCount (conteggio massimo) deve essere 1 quando Consumable = false.
MaxCount (conteggio massimo) può avere un valore massimo di 10.000.000.
Impostare MaxCount <1 non è vietato ma causerà un errore, poiché non è possibile concedere meno di un singolo oggetto a un giocatore.
Il Catalogo diritti
Puoi utilizzare il Catalogo diritti per visualizzare tutti i diritti che offri ai giocatori.
Puoi visualizzare un report con l'elenco dei tuoi diritti in UEFN selezionando Strumenti > Catalogo diritti oppure direttamente dal catalogo nel Portale creatori della tua isola.
Offerte
Un'offerta specifica un prezzo in V-buck per un oggetto o un asset. Ogni offerta ha un proprio nome, una descrizione e un'icona, separati dalle specifiche dei diritti. Un'offerta è definita in Verse.
Ogni offerta presenta le seguenti proprietà:
Name (nome): il nome dell'offerta.
Description (descrizione): la descrizione estesa visualizzata accanto all'offerta.
ShortDescription (descrizione breve): una descrizione breve che riassume l'offerta in finestre di dialogo più piccole.
Icon (icona): un'immagine dell’offerta.
EntitlementType: una dichiarazione del diritto incluso nell'offerta.
Price (prezzo): un prezzo espresso in V-buck. Non deve essere inferiore a 50 V-buck e non deve essere superiore a 5.000 V-buck. Il prezzo deve essere impostato in multipli di 50.
Creazione di un'offerta semplice
Questo snippet definisce un'offerta di base, l'offerta semplice pacchetto di semi di mais. Puoi utilizzare nuovamente l'icona dei semi di mais dell'esempio di diritto come icona per questa offerta.
CornSeedPacket<public> := module:
Name<public><localizes> : message = "Corn seed pack"
Description<public><localizes> : message = "A pack of corn seeds. Opening a pack yields 10 corn seeds for planting."
ShortDescription<public><localizes> : message = "Contains 10 corn seeds for planting."
corn_seed_pack<public> := class(entitlement_offer):
var Name<override> : message = CornSeedPacket.Name
var Description<override> : message = CornSeedPacket.Description
var ShortDescription<override> : message = CornSeedPacket.ShortDescription
Il prezzo in V-buck deve essere un multiplo di 50 e compreso tra 50 e 5.000 V-buck.
Devi assicurarti che i giocatori possano visualizzare le probabilità numeriche esatte di ottenere ciascun oggetto casuale a pagamento prima dell'acquisto. La mancata indicazione sarà considerata una violazione del Regolamento per sviluppatori Fortnite e potrà comportare sanzioni per te e per la tua isola.
Per ulteriori informazioni, consulta Limitazioni sulle Transazioni all'interno dell'isola.
Creazione e modifica di offerte fisse e alternative
Puoi fare offerte alternative per lo stesso diritto allo scopo di offrire prezzi speciali per le vacanze, bonus introduttivi e variare il prezzo per area. Puoi anche usarlo per testare il diritto creando un'offerta identica, ma usando un'icona diversa per vedere quale attira di più i giocatori. Utilizziamo questa icona come esempio.
CornSeedPacketAlternate<public> := module:
Name<public><localizes> : message = "Corn seed pack"
Description<public><localizes> : message = "Special price! Only today!"
ShortDescription<public><localizes> : message = "Special offer half price!"
corn_seed_pack_alternate<public> := class(entitlement_offer):
var Name<override> : message = CornSeedPacketAlternate.Name
var Description<override> : message = CornSeedPacketAlternate.Description
var ShortDescription<override> : message = CornSeedPacketAlternate.ShortDescription
var Icon<override> : texture = # Your texture here
Offerte bundle
I bundle sono definiti in Verse e possono contenere una combinazione di offerte diverse, più istanze della stessa offerta o un mix delle due. Come avviene per le offerte semplici, anche le offerte bundle specificano un prezzo, un nome e una descrizione propri, inoltre presentano un'icona distinta da quella di diritti e offerte. Puoi anche annidare le offerte includendo bundle all'interno di un'altra offerta bundle. Un esempio può essere un bundle a tempo limitato che include una pala e un bundle di pacchetti di semi di mais. Ciò permette di utilizzare piccoli bundle come elementi costitutivi per bundle più grandi e combinati.
I tipi di bundle standard sono:
Bundle impilato: un bundle che contiene più offerte dello stesso diritto, solitamente a prezzo scontato.
Bundle multi-offerta: un bundle che combina offerte per più diritti può includere anche una combinazione di offerte impilate e offerte singole.
La profondità delle offerte annidate non può superare 5, altrimenti la transazione fallirà. Limita l'annidamento delle offerte ove possibile.
Creazione di un bundle impilato
Questo snippet definisce un bundle impilato di semi di mais. Un bundle contiene un array di tuple di offerte, che include l'offerta definita e un int che indica il numero di offerte. In questo caso, il bundle comprende due offerte corn_seed_pack (pacchetto di semi di mais). Per questo esempio è fornita un'icona.
CornSeedPacketBundle<public> := module:
Name<public><localizes> : message = "Corn seed pack bundle"
Description<public><localizes> : message = "Two packs of corn seeds. Opening a pack yields 10 corn seeds for planting."
ShortDescription<public><localizes> : message = "Two packs of corn seeds containing 10 corn seeds for planting."
corn_seed_pack_bundle<public> := class(bundle_offer):
var Name<override> : message = CornSeedPacketBundle.Name
var Description<override> : message = CornSeedPacketBundle.Description
var ShortDescription<override> : message = CornSeedPacketBundle.ShortDescription
var Icon<override> : texture = # your texture here
Creazione di bundle multi-offerta
I giocatori potrebbero voler evitare la scelta di più transazioni, per questo motivo puoi creare un bundle che includa più offerte con diritti diversi. Questo snippet crea un bundle multi-offerta che fornisce al giocatore il numero massimo di pacchetti di semi di mais e una pala.
StarterBundle<public> := module:
Name<public><localizes> : message = "Starter bundle"
Description<public><localizes> : message = "Everything a new player needs. Get fully stocked to start quickly! A shovel that digs holes, and ten packs of corn seeds each containing 10 corn seeds for planting."
ShortDescription<public><localizes> : message = "A shovel that digs holes, and ten packs of corn seeds each containing 10 corn seeds for planting."
starter_bundle<public> := class(bundle_offer):
var Name<override> : message = StarterBundle.Name
var Description<override> : message = StarterBundle.Description
var ShortDescription<override> : message = StarterBundle.ShortDescription
var Icon<override> : texture = # your texture here
In Verse, i bundle non contengono direttamente i diritti. Includono invece offerte che a loro volta comprendono le definizioni di diritto.
Offerte create dinamicamente
Un'offerta creata dinamicamente è un'offerta o un'offerta bundle generata in fase di runtime in Verse. I casi d'uso più comuni per le offerte dinamiche possono essere:
Un'offerta per la quantità massima di legno che un giocatore può possedere in un gioco di creazione.
Un bundle per ottenere il massimo numero di pozioni di salute e mana all'ingresso di un dungeon in un dungeon crawler.
Per semplicità, collega l'offerta a un elemento semplice come un pulsante o un'insegna. Nel codice Verse, il flusso segue la sequenza: On Interaction > chiama BuyOffer.
Questo snippet mostra come vendere un bundle di pacchetti di semi di mais fino al numero massimo consentito per un giocatore. Se l'acquisto non riesce, viene visualizzato un messaggio di errore.
TryBuyOffer(Player : player)<suspends>:void =
Purchases := GetPurchasedEntitlements(Player, Entitlements.corn_seed_pack)
var NumPlayerCornSeedPacks : int = 0
if (Purchase := Purchases[0]):
set NumPlayerCornSeedPacks = Purchase(1)
# Limit to at least 1 packet.
# If the player has the maximum amount, the offer displays with a disabled purchase button.
NumCornSeedPacks := Max(1, Entitlements.corn_seed_pack{}.MaxCount - NumPlayerCornSeedPacks)
Regole di convalida dell'offerta
Un'offerta o un'offerta bundle valida deve rispettare le seguenti linee guida. Le offerte che non le rispettano non supereranno la moderazione. Le regole che definiscono un'offerta valida sono:
La profondità delle offerte annidate non può superare 5.
Il numero totale di identificatori di diritto non può superare la soglia di 100 per ogni offerta. Ciò significa che il numero totale di diritti diversi venduti contemporaneamente corrisponde al massimo a 100.
Il prezzo dell'offerta deve essere compreso tra 50 e 5.000 V-buck, e può essere impostato solo in multipli di 50.
Il testo predefinito del campo
Namedi un'offerta non può superare 50 caratteri.Il testo predefinito del campo
Descriptiondi un'offerta non può superare 500 caratteri.Il testo predefinito del campo
ShortDescriptiondi un'offerta non può superare 100 caratteri.Un'offerta deve contenere almeno 1 oggetto.
Un'offerta non può includere una quantità di diritto superiore al
MaxCountdel diritto.Un'offerta non può includere un diritto durevole con
MaxCount> 1.
Puoi decidere di applicare restrizioni su dove vengono visualizzate le offerte e su chi può vederle. Per ulteriori informazioni, consulta Limitazioni sulle Transazioni all'interno dell'isola.
Creazione di una vetrina
Ora che hai configurato i tuoi diritti, le offerte e i bundle, ti serve un luogo in cui venderli!
Interfaccia utente predefinita
L'interfaccia della vetrina predefinita si apre con un elenco di tutti i diritti e le offerte che hai aggiunto. Il primo diritto nell'elenco appare evidenziato e mostra una panoramica del diritto in una finestra accanto all'elenco.
Le vetrine possono includere più pagine.
È possibile scorrere gli elenchi con più di cinque oggetti.
Un giocatore avvia il flusso di acquisto richiamando il metodo BuyOffer oppure utilizzando la vetrina predefinita con il metodo ShowOffersDialog. Di seguito, alcuni esempi di dispositivi che puoi usare per integrare il flusso di acquisto della vetrina nel design del tuo gioco:
Dispositivo Volume
Dispositivo Timer Scene Graph
PNG
Dispositivo di conversazione
È buona prassi, nella progettazione di una vetrina, richiedere un'azione esplicita del giocatore per aprire il flusso di acquisto. Ignorare questa scelta e forzare l'apertura del flusso di acquisto riduce l'autonomia del giocatore e rischia di causare un'esperienza negativa.
Tutte le offerte presentano i pulsanti Acquista ed Esamina, che aprono le finestre del marketplace per acquistare un oggetto o visualizzare il contenuto dell'offerta. Solo i bundle dispongono del pulsante Esamina bundle.
Selezionando il pulsante Chiudi si chiude il marketplace.
L'esperienza della vetrina è completamente gestita dallo sviluppatore:
Decidi quali oggetti o proprietà di gameplay offrire ai tuoi giocatori.
Imposti il prezzo per ogni offerta o offerta bundle.
Puoi presentare una tua vetrina personalizzata oppure utilizzare l'interfaccia della vetrina Fortnite preconfigurata.
UI della vetrina
Questo snippet definisce una callback generica che apre l'interfaccia della vetrina predefinita di Fortnite. Il callback può essere richiamato da un'iscrizione, un pulsante, un evento di conversazione e così via.
OnEvent(Agent:agent):void=
if(Player:= player[Agent]):
spawn{ShowOffersDialog(Player, array{
ExampleOffers.shovel{},
ExampleOffers.cornseedpacket{}
})}
Gestione degli acquisti
Questo snippet mostra un esempio generico di acquisto di un'offerta. Se l'acquisto non riesce, viene visualizzato un messaggio di errore.
TryBuyOffer(Player:player, Offer : offer)<suspends>:void =
Result := BuyOffer(Player, Offer)
if (not Result?):
Print("Failed to buy the {offer.name} offer.")Per agevolare il debug in caso di acquisti non riusciti, includi un modo per identificare quale acquisto è fallito nel messaggio di errore, ad esempio includendo il nome dell'offerta.
Funzioni aggiuntive
Oggetti casuali a pagamento
Esistono due modi per offrire oggetti casuali a pagamento nella tua isola:
Puoi offrirli direttamente in acquisto con i V-buck.
Puoi offrirli indirettamente consentendo ai giocatori di acquistare diritti con V-buck che possono poi essere riscattati per una ricompensa casuale, o influenzare la probabilità di ricevere una ricompensa casuale.
Quando crei un oggetto che concede una ricompensa casuale, devi impostare PaidRandomItem su true.
Se offri contenuti che possono essere utilizzati per riscattare una ricompensa casuale, devi usare la funzione RestrictPaidRandomItems per impedire ai giocatori non autorizzati di ottenerla.
OnEvent(Agent:agent):void=
if (Player := player[Agent]):
if (RestrictPaidRandomItems[Player]):
Print("Player is not allowed to purchase PaidRandomItems.")
else:
Print("Player is allowed to purchase PaidRandomItems.")
Prompt diretti all'acquisto
Se la tua isola include prompt di acquisto diretti, devi utilizzare la funzione RestrictDirectPromptsToPurchase per determinare se il giocatore è idoneo a riceverli.
OnEvent(Agent:agent):void=
if (Player:= player[Agent]):
if (RestrictDirectPromptsToPurchase[Player]):
Print("Player is not allowed to receive direct purchase prompts.")
else:
Print("Player is allowed to receive direct purchase prompts.")
Consequenziale al gameplay
Se l'oggetto che stai vendendo offre ai giocatori un vantaggio significativo nella tua isola, devi impostare ConsequentialToGameplay su vero.
Gli oggetti che sono consequenziali al gameplay includono qualsiasi oggetto che, se acquistato, fornisce ai giocatori un vantaggio significativo nel gioco. Ciò può essere diretto (ad esempio, un oggetto che aumenta la velocità di progressione nel gioco, la potenza o le capacità del giocatore) o indiretto (ad esempio, un oggetto che garantisce l'accesso a un altro oggetto che influisce in modo significativo sulla velocità di progressione nel gioco o sulle probabilità di vittoria del giocatore).
Se esiste un'alternativa all'oggetto che stai vendendo, liberamente disponibile a tutti i giocatori nello stesso momento in cui l'offerta viene presentata e che offre lo stesso vantaggio, allora non è necessario impostare ConsequentialToGameplay su vero. Se un oggetto di gioco ha un impatto casuale ma irrilevante per il gameplay, come nel caso di combinazioni di colori diversi degli abiti che hanno visibilità leggermente diverse in ambienti diversi, o di emote diverse che producono movimenti del corpo diversi, non è considerato consequenziale.
# The base entitlement you should define for ALL of your entitlements in your experience.
my_island_entitlement := class<abstract><castable>(entitlement){}
CornSeedPacket<public> := module:
Name<public><localizes> : message = "Corn seed pack"
Description<public><localizes> : message = "A pack of corn seeds. Opening a pack yields 10 corn seeds for planting."
ShortDescription<public><localizes> : message = "Contains 10 corn seeds for planting."
cornseedpacket<public> := class<concrete>(my_island_entitlement):
var Name<override>:message = CornSeedPacket.Name