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:

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. Das log -Objekt macht die folgenden Methoden verfügbar: info, debugund error. 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 ExecuteCloudScriptRequesterstellen und die ActionId -Eigenschaft auf den Namen der CloudScript-Funktion festlegen, die Sie ausführen möchten (in diesem Fall wäre helloWorldes ), 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 Fall helloWorldist .

  • ExecuteCloudScriptRequest.FunctionParameter kann ein beliebiges Objekt sein, das in JSON serialisiert werden kann. Er wird zum ersten args-Parameter in der helloWorld 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 titleIdenthä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.FunctionParameterund 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.

  1. 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.

Game Manager – PlayStream – Ereignisaktionen

  1. 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.

    Game Manager – PlayStream – Aktion speichern

  2. 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 InfoMethoden , Debugund 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.

    Game Manager – PlayStream – Debugger

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.

    Game Manager – PlayStream – JSON-Ereignisprotokoll

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.