Schreiben von benutzerdefiniertem CloudScript
CloudScript ist eines der vielseitigsten Features von PlayFab. Es ermöglicht Clientcode, die Ausführung jeder Art von benutzerdefinierter serverseitiger Funktionalität anzufordern, die Sie implementieren können, und sie kann mit praktisch allem verwendet werden. Zusätzlich zu expliziten Ausführungsanforderungen von Client- oder Servercode kann CloudScript als Reaktion auf PlayStream-Ereignisse (durch Erstellen einer Regel) oder als Teil einer geplanten Aufgabe ausgeführt werden.
Notiz
CloudScript mit Azure Functions verbessert, was CloudScript mit mehr unterstützten Sprachen und besseren Debugworkflows hervorragend gemacht hat.
In diesem Tutorial wird das Schreiben Ihres CloudScript-Codes behandelt. Hilfe zum Hochladen Ihrer CloudScript-Dateien in Ihren Titel finden Sie im CloudScript-Schnellstart .
Notiz
In diesem Tutorial werden Unity-Codebeispiele veranschaulicht, aber CloudScript funktioniert für alle SDKs ähnlich.
Voraussetzungen für dieses Tutorial:
-
Unity-Umgebung mit dem PlayFab Unity SDK eingerichtet
- Die Titel-ID wird im
PlayFabSharedSettings
-Objekt festgelegt. - Das Projekt kann sich erfolgreich bei einem Benutzer anmelden.
- Die Titel-ID wird im
Erste Schritte: helloWorld
Unser helloWorld
Beispiel funktioniert mit einem brandneuen Titel ohne Änderungen im Game Manager. Die CloudScript-Standarddatei für einen neuen Titel enthält einen Handler namens helloWorld
. Es werden einige grundlegende Features, Eingabeparameter, Protokollierung, currentPlayerId und Rückgabeparameter verwendet.
Das folgende Beispiel zeigt den Standardfunktionscode helloWorld
(minus Kommentare).
// CloudScript (JavaScript)
handlers.helloWorld = function (args, context) {
var message = "Hello " + currentPlayerId + "!";
log.info(message);
var inputValue = null;
if (args && args.hasOwnProperty("inputValue"))
inputValue = args.inputValue;
log.debug("helloWorld:", { input: inputValue });
return { messageValue: message };
}
Dekonstruieren des Codes
Das Handlerobjekt ist in der PlayFab CloudScript-Umgebung vordefiniert. Sie sollten eine Ihrer CloudScript-Funktionen zu diesem Objekt hinzufügen.
helloWorld
ist eine Funktion, die ihrem Titel und Ihren SDKs zur Verfügung gestellt wird, da sie im Handlerobjekt definiert ist.args
ist ein beliebiges Objekt, das vom Aufrufer stammt. Es wird aus JSON analysiert und kann beliebige Daten enthalten, die in beliebiger Weise formatiert sind.
Weitere Informationen finden Sie unter FunctionParameter im nächsten Abschnitt.
Warnung
Sie sollten dieses Objekt mit Zero Trust behandeln. Ein gehackter Client oder böswilliger Benutzer kann hier alle Informationen in jedem Format bereitstellen.
Context
ist ein erweiterter Parameter. In diesem Beispiel ist es NULL. Dieser Parameter ist servergesteuert und sicher.currentPlayerId
ist eine globale Variable, die auf die PlayFabId des Spielers festgelegt ist, der diesen Aufruf anfordert. Dieser Parameter ist servergesteuert und sicher. Hinweis: Bei Verwendung der ExecuteEntityCloudScript-API ist dieser Parameter NULL, es sei denn, die Entität hat eine MasterPlayerID in ihrer Entitätskette.log.info
:log
ist ein globales Objekt. Es wird hauptsächlich zum Debuggen Von CloudScript verwendet. Daslog
-Objekt macht die folgenden Methoden verfügbar:info
,debug
underror
. Weitere Informationen finden Sie weiter unten in diesem Tutorial.return
: Jedes zurückgegebene Objekt wird als JSON serialisiert und an den Aufrufer zurückgegeben. Sie können jedes JSON-serialisierfähige Objekt mit beliebigen Daten zurückgeben.
Warnung
Es liegt in Ihrer Verantwortung, wenn Ihr CloudScript geheime Daten an Ihre Clients zurückgibt. Ein gehackter Client oder ein böswilliger Benutzer kann die zurückgegebenen Daten untersuchen, auch wenn Sie sie dem Benutzer im regulären Spiel nicht anzeigen.
Ausführen von CloudScript-Funktionen über einen Unity-Spielclient
Das Aufrufen einer CloudScript-Funktion aus einem Client ist einfach. Sie müssen zuerst einen ExecuteCloudScriptRequest
erstellen und die ActionId
-Eigenschaft auf den Namen der CloudScript-Funktion festlegen, die Sie ausführen möchten (in diesem Fall wäre helloWorld
es ), und dann das Objekt über unsere API an PlayFab senden.
Notiz
Sie können nur CloudScript-Methoden aufrufen, die an das JavaScript-Objekt des Handlers angefügt sind.
Zum Ausführen von CloudScript-Methoden benötigen Sie die folgenden Codezeilen in Ihrem Client.
// Build the request object and access the API
private static void StartCloudHelloWorld()
{
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest()
{
FunctionName = "helloWorld", // Arbitrary function name (must exist in your uploaded cloud.js file)
FunctionParameter = new { inputValue = "YOUR NAME" }, // The parameter provided to your function
GeneratePlayStreamEvent = true, // Optional - Shows this event in PlayStream
}, OnCloudHelloWorld, OnErrorShared);
}
// OnCloudHelloWorld defined in the next code block
Dekonstruieren des Codes
ExecuteCloudScriptRequest ist der Anforderungstyp für jeden Aufruf von PlayFabClientAPI.ExecuteCloudScript.
ExecuteCloudScriptRequest.FunctionName
ist eine Zeichenfolge. Der Wert sollte mit dem Namen der in CloudScript definierten Funktion übereinstimmen. In diesem FallhelloWorld
ist .ExecuteCloudScriptRequest.FunctionParameter
kann ein beliebiges Objekt sein, das in JSON serialisiert werden kann. Er wird zum ersten args-Parameter in derhelloWorld
Funktion (siehe die Argumente im vorherigen Abschnitt).ExecuteCloudScriptRequest.GeneratePlayStreamEvent
ist optional. Wenn true, wird ein Ereignis in PlayStream gepostet, das Sie im Game Manager anzeigen oder für andere PlayStream-Trigger verwenden können.
Je nach Sprache besteht der letzte Teil der ExecuteCloudScript
Zeile darin, die Anforderung an den PlayFab-CloudScript-Server und den für die Sprache spezifischen Teil zur Behandlung von Ergebnissen und Fehlern zu stellen.
In Unity, JavaScript oder AS3 wird beispielsweise die Fehler- und Ergebnisbehandlung mithilfe von Rückruffunktionen bereitgestellt.
Es folgt ein Beispiel für Fehlerbehandlungsmethoden.
private static void OnCloudHelloWorld(ExecuteCloudScriptResult result) {
// CloudScript returns arbitrary results, so you have to evaluate them one step and one parameter at a time
Debug.Log(JsonWrapper.SerializeObject(result.FunctionResult));
JsonObject jsonResult = (JsonObject)result.FunctionResult;
object messageValue;
jsonResult.TryGetValue("messageValue", out messageValue); // note how "messageValue" directly corresponds to the JSON values set in CloudScript
Debug.Log((string)messageValue);
}
private static void OnErrorShared(PlayFabError error)
{
Debug.Log(error.GenerateErrorReport());
}
Zwischenübersicht: Globale Und erweiterte Argumente
CloudScript ist eine Reihe von JavaScript-Funktionen, die mit V8 kompiliert und auf playFab-Servern gehostet werden. Es hat Zugriff auf jede Server-API, die in der Referenzdokumentation zur PlayFab-API aufgeführt ist, sowie auf eine Protokollierung, die PlayFab-ID des Spielers, der die CloudScript-Anforderung stellt, und auf alle Informationen, die in der Anforderung enthalten sind, alles in Form von vordefinierten Objekten.
CloudScript-Funktionen selbst sind Eigenschaften eines globalen Handlerobjekts. Die folgende Tabelle enthält eine vollständige Liste dieser vordefinierten Variablen.
Name | Verwendung |
---|---|
Server | Hat Zugriff auf alle serverseitigen API-Aufrufe, die in der Referenzdokumentation zur PlayFab-API aufgeführt sind. Sie können (synchron) wie folgt aufgerufen werden: var result = server.AuthenticateUserTicket(request); |
http | Führt synchrone HTTP-Anforderungen wie folgt aus: http.request(url, method, content, contentType, headers, logRequestAndResponse) . Das headers -Objekt enthält Eigenschaften, die verschiedenen Headern und deren Werten entsprechen.
logRequestAndResponse ist ein boolescher Wert, der bestimmt, ob der Titel Fehler in der Anforderung als Teil der Antwort protokollieren soll. |
Protokoll | Erstellt Protokollanweisungen und fügt sie der Antwort hinzu. Protokolle verfügen über drei Ebenen: log.info() , log.debug() und log.error() . Alle drei Ebenen verwenden eine Nachrichtenzeichenfolge zusammen mit einem optionalen Objekt, das zusätzliche Daten enthält, die in das Protokoll eingeschlossen werden sollen. Beispiel: log.info('hello!', { time: new Date() }); . |
currentPlayerId | PlayFab-ID des Spielers, der den CloudScript-Aufruf ausgelöst hat. |
Handler | Globales Objekt, das alle CloudScript-Funktionen für Ihren Titel enthält. Funktionen können über dieses Objekt hinzugefügt oder aufgerufen werden. Beispiel: handlers.pop = function() {}; , handlers.pop(); . |
script | Globales Objekt, das und titleId enthältRevision .
Revision stellt die Revisionsnummer für das aktuell ausgeführte CloudScript dar und titleId stellt die ID für den aktuellen Titel dar. |
Darüber hinaus werden allen Handlerfunktionen zwei Parameter übergeben, die unten beschrieben werden.
Name | Verwendung |
---|---|
Args | Erster Parameter für eine Handlerfunktion. Eine Objektdarstellung des FunctionParameter Felds einer ExecuteCloudscript Anforderung. |
Kontext | Zweiter Parameter für eine Handlerfunktion. Zusätzliche Informationen zur Anforderung, wenn sie durch eine PlayStream-Ereignisaktion ausgelöst wird, einschließlich der Daten aus dem Ereignis , das die Aktion ausgelöst hat (context.playStreamEvent) und die Profildaten für den zugeordneten Player. (context.playerProfile) |
CloudScript-Funktionen können über die ExecuteCloudScript
API oder durch eine voreingestellte PlayStream-Ereignisaktion aufgerufen werden.
Ausführliche Informationen zur Antwort auf ExecuteCloudScript
finden Sie unter ExecuteCloudScriptResult.
Intermediate: FunctionParameter und args
Im vorherigen Abschnitt haben wir beschrieben, wie sie das -Element auffüllen request.FunctionParameter
und diese Informationen im args
-Parameter anzeigen. In der CloudScript-Schnellstartanleitung wird veranschaulicht, wie Sie neues CloudScript hochladen.
Wenn wir beides zusammensetzen, können wir ein weiteres Beispiel für die Übergabe von Argumenten vom Client an CloudScript bereitstellen. Nehmen Sie das vorherige Beispiel, und ändern Sie den CloudScript-Code und Ihren Clientcode wie unten gezeigt.
handlers.helloWorld = function (args) {
// ALWAYS validate args parameter passed in from clients (Better than we do here)
var message = "Hello " + args.name + "!"; // Utilize the name parameter sent from client
log.info(message);
return { messageValue: message };
}
// Build the request object and access the API
private static void StartCloudHelloWorld()
{
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest()
{
FunctionName = "helloWorld", // Arbitrary function name (must exist in your uploaded cloud.js file)
FunctionParameter = new { name = "YOUR NAME" }, // The parameter provided to your function
GeneratePlayStreamEvent = true, // Optional - Shows this event in PlayStream
}, OnCloudHelloWorld, OnErrorShared);
}
private static void OnCloudHelloWorld(ExecuteCloudScriptResult result) {
// CloudScript returns arbitrary results, so you have to evaluate them one step and one parameter at a time
Debug.Log(JsonWrapper.SerializeObject(result.FunctionResult));
JsonObject jsonResult = (JsonObject)result.FunctionResult;
object messageValue;
jsonResult.TryGetValue("messageValue", out messageValue); // note how "messageValue" directly corresponds to the JSON values set in CloudScript
Debug.Log((string)messageValue);
}
private static void OnErrorShared(PlayFabError error)
{
Debug.Log(error.GenerateErrorReport());
}
Nachdem Sie diese Änderungen vorgenommen haben, können Sie jetzt ganz einfach Daten zwischen CloudScript und Ihren Clients senden und empfangen.
Notiz
Es ist wichtig, darauf hinzuweisen, dass alle Daten, die von Ihren Kunden stammen, anfällig für Hacking und Ausbeutung sind.
Sie sollten immer Eingabeparameter überprüfen, bevor Sie Ihr Back-End aktualisieren. Der Prozess zum Überprüfen von Eingabeparametern variiert von Titel zu Titel, aber die grundlegendste Überprüfung überprüft, um sicherzustellen, dass Eingaben innerhalb akzeptabler Bereiche und Zeiträume liegen.
Zwischenstufe: Aufrufen der Server-APIs
Wie bereits erwähnt, haben Sie in CloudScript-Methoden Zugriff auf den vollständigen Satz von Server-API-Aufrufen. Dadurch kann Ihr Cloudcode als dedizierter Server fungieren.
Allgemeine Serveraufgaben:
- Aktualisieren Sie Spielerstatistiken und -daten.
- Elemente und Währung gewähren.
- Zufälliges Generieren von Spieldaten.
- Sicheres Berechnen von Kampfergebnissen und mehr...
Die erforderlichen Parameter und Objektstrukturen finden Sie in den Server-APIs, die in unserer Referenzdokumentation zur PlayFab-API aufgeführt sind.
Das folgende Beispiel stammt aus einem potenziellen CloudScript-Handler.
// CloudScript (JavaScript)
//See: JSON.parse, JSON.stringify, parseInt and other built-in javascript helper functions for manipulating data
var currentState; // here we are calculating the current player's game state
// here we are fetching the "SaveState" key from PlayFab,
var playerData = server.GetUserReadOnlyData({"PlayFabId" : currentPlayerId, "Keys" : ["SaveState"]});
var previousState = {}; //if we return a matching key-value pair, then we can proceed otherwise we will need to create a new record.
if(playerData.Data.hasOwnProperty("SaveState"))
{
previousState = playerData.Data["SaveState"];
}
var writeToServer = {};
writeToServer["SaveState"] = previousState + currentState; // pseudo Code showing that the previous state is updated to the current state
var result = server.UpdateUserReadOnlyData({"PlayFabId" : currentPlayerId, "Data" : writeToServer, "Permission":"Public" });
if(result)
{
log.info(result);
}
else
{
log.error(result);
}
Erweitert: PlayStream-Ereignisaktion
Eine CloudScript-Funktion kann so konfiguriert werden, dass sie als Reaktion auf ein PlayStream-Ereignis ausgeführt wird.
- In jedem Browser:
- Besuchen Sie den PlayFab Game Manager.
- Suchen Sie Ihren Titel.
- Wechseln Sie in der Randleiste unter Erstellen zur Registerkarte Automatisierung .
- Wechseln Sie zur Registerkarte Regeln .
Die Seite sieht wie im unten angegebenen Beispiel aus.
Verwenden Sie die Schaltfläche Neue Regel , um eine neue Regel zu erstellen.
- Geben Sie der neuen Regel einen Namen.
- Wählen Sie einen Ereignistyp aus, der als Trigger für eine Bedingung oder Aktion verwendet wird.
- Damit die Regel eine CloudScript-Funktion auslöst, fügen Sie eine Aktion mit der Schaltfläche in diesem Abschnitt hinzu.
- Wählen Sie dann die Option im Dropdownmenü Typ aus.
- Wählen Sie im Dropdownmenü cloud script function (Cloudskriptfunktion) die Funktion helloWorld aus.
- Wählen Sie die Schaltfläche Aktion Speichern aus.
Diese Regel ist jetzt so festgelegt, dass sie für jedes Ereignis des ausgewählten Typs ausgelöst wird. So testen Sie sie:
- Aktivieren Sie das Kontrollkästchen Ergebnisse als PlayStream-Ereignis veröffentlichen .
- Speichern Sie die Aktion.
- Lösen Sie dann ein Ereignis aus.
- Im PlayStream-Monitor sollte ein neues Ereignis vorhanden sein, das der CloudScript-Ausführung entspricht und die entsprechenden Informationen enthält.
- Weitere Informationen zum Überprüfen eines PlayStream-Ereignisses im Debugger finden Sie im folgenden Abschnitt Erweitert: Debuggen von CloudScript.
Notiz
Ereignisaktionen können nur die Liverevision verwenden, wenn CloudScript-Funktionen aufgerufen werden. Wenn Sie die HelloWorld-Funktion in der Dropdownliste nicht finden, ist dies der wahrscheinlichste Grund.
Erweitert: Debuggen von CloudScript
Notiz
Das Debuggen ist mit CloudScript mithilfe von Azure Functions viel einfacher. Erfahren Sie mehr über die Verwendung des lokalen Debuggens für CloudScript mit Azure Functions.
Protokollierung
Eines der wichtigsten Tools zum Debuggen von Code ist die Protokollierung. Unser CloudScript bietet ein Hilfsprogramm zum Ausführen der Funktion.
Dies hat die Form des log
-Objekts, das jede gewünschte Nachricht mit den Info
Methoden , Debug
und Error
protokollieren kann.
Darüber hinaus protokolliert das HTTP-Objekt alle Fehler, die beim Senden von Anforderungen auftreten, indem der logRequestAndResponse
Parameter festgelegt wird. Das Einrichten dieser Protokolle ist zwar einfach, der Zugriff auf sie erfordert jedoch etwas Feingefühl.
Hier sehen Sie ein Beispiel für eine CloudScript-Funktion, die alle vier Protokolltypen verwendet.
handlers.logTest = function(args, context) {
log.info("This is a log statement!");
log.debug("This is a debug statement.");
log.error("This is... an error statement?");
// the last parameter indicates we want logging on errors
http.request('https://httpbin.org/status/404', 'post', '', 'text/plain', null, true);
};
Um dieses Beispiel auszuführen, fügen Sie diese Funktion ihrer Liverevision hinzu, bevor Sie fortfahren.
Die logTest
Funktion kann mit aufgerufen werden, ExecuteCloudScript
wie unten gezeigt.
// Invoke this on start of your application
void Login() {
PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest {
CreateAccount = true,
CustomId = "Starter"
}, result => RunLogTest(), null);
}
void RunLogTest() {
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest {
FunctionName = "logTest",
// duplicates the response of the request to PlayStream
GeneratePlayStreamEvent = true
}, null, null);
}
// Logs evaluated in next code block
Die Einstellung GeneratePlayStreamEvent
bewirkt, dass der CloudScript-Funktionsaufruf ein PlayStream-Ereignis generiert, das den Inhalt der Antwort enthält. So suchen Sie den Inhalt eines PlayStream-Ereignisses:
Wechseln Sie entweder zur Startseite des Game Managers für Ihren Titel oder zur zugehörigen Registerkarte PlayStream .
Der PlayStream-Debugger zeigt Ereignisse an, sobald sie eingehen.
Wenn sie eintreffen, wählen Sie das kleine blaue Infosymbol in der oberen rechten Ecke des Ereignisses aus, wie unten gezeigt.
Wenn Sie diese Option auswählen, wird der unformatierte JSON-Code des Ereignisses angezeigt, der hier für jedes Ereignis beschrieben wird. Ein Beispiel für diesen JSON-Code finden Sie im folgenden Beispiel.
Wenn wir den
LogScript
MonoBehavior zur Szene hinzufügen, führt das Ausführen des Spiels dazu, dass dies in PlayStream erfolgt.
Das Ergebnis eines Aufrufs ExecuteCloudScript
enthält ein Feld namens Logs
, bei dem es sich um eine Liste von Protokollobjekten handelt, die von der CloudScript-Funktion generiert werden.
Sie können die drei Protokollaufrufe sowie das Protokoll aus der ungültigen HTTP-Anforderung sehen. Das HTTP-Anforderungsprotokoll Data
verwendet im Gegensatz zu den Protokollaufrufen auch das -Feld.
Dieses Feld ist ein JavaScript-Objekt, das mit allen informationen aufgefüllt werden kann, die für die Protokollanweisungen relevant sind. Aufrufe von Protokollen können auch dieses Feld verwenden, indem der zweite Parameter verwendet wird, wie unten angegeben.
handlers.logTest = function(args, context) {
log.info("This is a log statement!", { what: "Here on business." });
log.debug("This is a debug statement.", { who: "I am a doctor, sir" });
log.error("This is... an error statement?", { why: "I'm here to fix the plumbing. Probably.", errCode: 123 });
};
Diese Aufrufe füllen das Data
Feld im Ergebnis mit ihrem zweiten Parameter auf.
Da die Protokolle im Ergebnis enthalten sind, kann der clientseitige Code auf Protokollanweisungen reagieren. Der Fehler in der logTest
Funktion wird erzwungen, aber der Clientcode kann angepasst werden, um darauf zu reagieren.
void RunLogTest()
{
PlayFabClientAPI.ExecuteCloudScript(
new ExecuteCloudScriptRequest
{
FunctionName = "logTest",
// handy for logs because the response will be duplicated on PlayStream
GeneratePlayStreamEvent = true
},
result =>
{
var error123Present = false;
foreach (var log in result.Logs)
{
if (log.Level != "Error") continue;
var errData = (JsonObject) log.Data;
object errCode;
var errCodePresent = errData.TryGetValue("errCode", out errCode);
if (errCodePresent && (ulong) errCode == 123) error123Present = true;
}
if (error123Present)
Debug.Log("There was a bad, bad error!");
else
Debug.Log("Nice weather we're having.");
}, null);
}
Wenn dieser Code ausgeführt wird, sollte die Ausgabe das Vorhandensein des Fehlers angeben. Realistische Fehlerantworten können darin sein, den Fehler auf der Benutzeroberfläche anzuzeigen oder einen Wert in einer Protokolldatei zu speichern.
Erweitert: Fehler
In der Entwicklung werden CloudScript-Fehler häufig nicht manuell ausgelöst , wie im Fall von log.error
.
Glücklicherweise enthält die Antwort auf ExecuteCloudScript ein ExecuteCloudScriptResult,das ein ScriptExecutionError-Feld enthält. Wenn Wir das letzte Beispiel aus dem Protokollierungsabschnitt anpassen, können wir es wie unten gezeigt verwenden.
void RunLogTest() {
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest {
FunctionName = "logTest",
// handy for logs because the response will be duplicated on PlayStream
GeneratePlayStreamEvent = true
}, result => {
if(result.Error != null) {
Debug.Log(string.Format("There was error in the CloudScript function {0}:\n Error Code: {1}\n Message: {2}"
, result.FunctionName, result.Error.Error, result.Error.Message));
}
},
null);
}
Im Falle eines Fehlers wird dieser Code im Protokoll angezeigt.