Schnellstart für Entitäten

In dieser Schnellstartanleitung für Entitäten wird veranschaulicht, wie Sie mit Entitätsobjekten und Entitätsdateien arbeiten.

Informationen zum Migrieren von Legacykonten und Datensystemen zu PlayFab-Entitäten finden Sie unter Informationen zur Entitätsmigration.

Voraussetzungen

  • Ein PlayFab-Entwicklerkonto.
  • Eine installierte Kopie des Unity-Editors. Informationen zum Installieren des Unity-Editors finden Sie unter Installieren von Unity in der Unity-Dokumentation. Sie können eine Version von Unity auch mithilfe des Visual Studio-Featureinstallationsprogramms installieren.

    Notiz

    Das PlayFab Unity3D SDK unterstützt Unity Editor Version 5.3 und höher.

  • Ein Unity-Projekt. Informationen zum Erstellen eines Unity-Projekts finden Sie im Schnellstarthandbuch.

    Notiz

    Wenn Sie mit Unity nicht vertraut sind, bieten Ihnen aktuelle Installationspakete die Möglichkeit, exemplarische Vorgehensweisen für die Spieleerstellung zu installieren. Sie können eine der exemplarischen Vorgehensweisen verwenden, um ein Beispielspiel zu erstellen, das in der folgenden Schnellstartanleitung verwendet wird.

  • Das PlayFab Unity3D SDK.

Die C#-Beispiele in diesem Artikel wurden für das Unity SDK geschrieben. Das Unity SDK verwendet ein ereignisgesteuertes Modell, um nicht synchrone Aufgaben zu verarbeiten. Um den Beispielcode mit den Standard-C#- oder Xamarin C#-SDKs auszuführen, müssen Sie den Code so ändern, dass er ein asynchrones Aufgabenmodell verwendet. Methoden, die geändert werden müssen, weisen Async an den Methodennamen in der Signatur an. Beispielsweise wird SetObject im Unity SDK im Standard-C#-SDK zu SetObjectAsync. Weitere Informationen finden Sie unter Asynchrone Programmierung mit async und await.

Terminologie

Entitäten sind beliebige PlayFab-Konzepte, die Daten enthalten können. Die integrierten Entitätstypen sind:

  • title : Ein Titel enthält globale Informationen, die allen Spielern zur Verfügung stehen. Dies ähnelt TitleData. Sie wird durch die Titel-ID (TitleId) des Spiels/der Anwendung identifiziert.
  • master_player_account : Mit diesem Entitätstyp können Sie Informationen zu einem Spieler in mehreren Spielen innerhalb eines Namespace freigeben. Es wird durch die Spieler-ID (PlayFabId) des Spielers identifiziert, die als Teil einer Anmeldung oder eines Aufrufs zum Abrufen von Kontoinformationen für das Spielerkonto (z. B. die PlayFab-Client-API GetAccountInfo) zurückgegeben wird.
  • title_player_account : Identifiziert ein Spielerkonto, das einige Informationen zum aktuellen Titel enthält. Dies wird durch die Entitäts-ID (EntityKey.Id) identifiziert, die Sie im EntityKey-Objekt bei jeder Anmeldung erhalten.
  • character : Identifiziert ein Zeichen, das der Spieler besitzt, der Informationen enthält, die Sie abrufen können. Sie wird durch die Zeichen-ID (CharacterId) des Zeichens identifiziert.

Weitere Informationen zu den integrierten Entitätstypen finden Sie unter Verfügbare integrierte Entitätstypen.

Entitätsinitialisierung

Um die Entitäts-API aufzurufen, müssen Sie die Entität ID und die Entität Typeabrufen. Sie verwenden und IDType , um Aufrufe an andere Entitäts-API-Methoden zu senden. Dies sind Elemente eines EntityKey-Objekts .

Dazu rufen Sie eine der Anmeldemethoden auf, z LoginWithCustomID. B. .

    void Login()
    {
        var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
        {
            CustomId = SystemInfo.deviceUniqueIdentifier,
            CreateAccount = true,
        };
        PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
    }

    void OnLogin(PlayFab.ClientModels.LoginResult result)
    {
        entityId = result.EntityToken.Entity.Id;
        // The expected entity type is title_player_account.
        entityType = result.EntityToken.Entity.Type;
    }

Sie können die Entität ID und Entität Type auch durch Aufrufen der GetEntityToken-Methode abrufen.

PlayFabAuthenticationAPI.GetEntityToken(new GetEntityTokenRequest(),
(entityResult) =>
{
    var entityId = entityResult.Entity.Id;
    var entityType = entityResult.Entity.Type;
}, OnPlayFabError); // Define your own OnPlayFabError function to report errors

Beim Aufruf vom Client stellt dies in der Regel den angemeldeten Player dar. Wenn sie von Spielservern aufgerufen wird, stellt dies Ihren Titel dar.

Entitätsobjekte

Mit Entitätsobjekten können Sie kleine JSON-serialisierbare Objekte lesen und schreiben, die an eine Entität angefügt sind. Alle Entitätstypen unterstützen die GetObjects Methoden und SetObjects .

Die folgenden Codeausschnitte zeigen, wie Sie eine Object für eine title_player_account Entität festlegen und lesen.

Verwenden Sie die SetObjects-Methode, um Entitätsobjekte auf einem Player oder einem Titel festzulegen.

var data = new Dictionary<string, object>()
{
    {"Health", 100},
    {"Mana", 10000}
};
var dataList = new List<SetObject>()
{
    new SetObject()
    {
        ObjectName = "PlayerData",
        DataObject = data
    },
    // A free-tier customer may store up to 3 objects on each entity
};

PlayFabDataAPI.SetObjects(new SetObjectsRequest()
{
    Entity = new EntityKey {Id = entityId, Type = entityType}, // Saved from GetEntityToken, or a specified key created from a titlePlayerId, CharacterId, etc
    Objects = dataList,
}, (setResult) => {
    Debug.Log(setResult.ProfileVersion);
}, OnPlayFabError);

Verwenden Sie die GetObjects-Methode, um Entitätsobjekte für einen Player oder einen Titel abzurufen.

var getRequest = new GetObjectsRequest {Entity = new EntityKey {Id = entityId, Type = entityType}};
PlayFabDataAPI.GetObjects(getRequest,
    result => { var objs = result.Objects; },
    OnPlayFabError
);

Entitätsdateien

Mit Entitätsdateien können Sie Dateien lesen und schreiben, die an eine Entität angefügt sind, in jedem Format.

Verwenden Sie die GetFiles-Methode, um Entitätsdateien abzurufen.

    void LoadAllFiles()
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");

        GlobalFileLock += 1; // Start GetFiles
        var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType } };
        PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
    }

Verwenden Sie die initiatefileuploads-Methode , um einen Dateiupload in das Profil einer Entität zu initiieren.

    void UploadFile(string fileName)
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");

        ActiveUploadFileName = fileName;

        GlobalFileLock += 1; // Start InitiateFileUploads
        var request = new PlayFab.DataModels.InitiateFileUploadsRequest
        {
            Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
            FileNames = new List<string> { ActiveUploadFileName },
        };
        PlayFabDataAPI.InitiateFileUploads(request, OnInitFileUpload, OnInitFailed);
    }

Verwenden Sie die AbortFileUploads-Methode , um einen ausstehenden Dateiupload in das Profil einer Entität abzubrechen.

    void OnInitFailed(PlayFabError error)
    {
        if (error.Error == PlayFabErrorCode.EntityFileOperationPending)
        {
            // This is an error you should handle when calling InitiateFileUploads, but your resolution path may vary
            GlobalFileLock += 1; // Start AbortFileUploads
            var request = new PlayFab.DataModels.AbortFileUploadsRequest
            {
                Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
                FileNames = new List<string> { ActiveUploadFileName },
            };
            PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1; UploadFile(ActiveUploadFileName); }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads
            GlobalFileLock -= 1; // Failed InitiateFileUploads
        }
        else
            OnSharedFailure(error);
    }

Verwenden Sie die FinalizeFileUploads-Methode , um Dateiuploads in das Profil einer Entität abzuschließen. Das Entitätssystem betrachtet den Dateiupload nicht als abgeschlossen und spiegelt auch keine Änderungen an anderen Aufrufern wider, bis der atomische Uploadvorgang erfolgreich abgeschlossen wurde.

    void FinalizeUpload(byte[] data)
    {
        GlobalFileLock += 1; // Start FinalizeFileUploads
        var request = new PlayFab.DataModels.FinalizeFileUploadsRequest
        {
            Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
            FileNames = new List<string> { ActiveUploadFileName },
        };
        PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure);
        GlobalFileLock -= 1; // Finish SimplePutCall
    }

Das folgende Beispiel zeigt eine vollständige Entitätsdateischleife, von der Anmeldung über das Laden einer Datei bis hin zum Hochladen einer neuen Datei.

Hierfür sind die folgenden Schritte erforderlich:

  • melden Sie sich an, und rufen Sie die Entität ID und die Entität Typeab.
  • Initialisieren Sie den atomischen Uploadvorgang.
  • Laden Sie alle Dateien hoch.
  • Schließen Sie den atomischen Uploadvorgang ab.

Der Einfachheit halber speichert dieses Beispiel jeweils eine Datei, aber Dateien können atomar in Sätzen hochgeladen werden.

In diesem Beispiel wird davon ausgegangen, dass Sie mit der Verwendung der Unity 3D-Engine vertraut sind.

#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API

using PlayFab;
using PlayFab.Internal;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class EntityFileExample : MonoBehaviour
{
    public string entityId; // Id representing the logged in player
    public string entityType; // entityType representing the logged in player
    private readonly Dictionary<string, string> _entityFileJson = new Dictionary<string, string>();
    private readonly Dictionary<string, string> _tempUpdates = new Dictionary<string, string>();
    public string ActiveUploadFileName;
    public string NewFileName;
    // GlobalFileLock provides is a simplistic way to avoid file collisions, specifically designed for this example.
    public int GlobalFileLock = 0; 

    void OnSharedFailure(PlayFabError error)
    {
        Debug.LogError(error.GenerateErrorReport());
        GlobalFileLock -= 1;
    }

    // OnGUI provides a way to build a Unity GUI entirely within script.
  - // Your GUI will be game-specific.
    void OnGUI()
    {
        if (!PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "Login"))
            Login();
        if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "LogOut"))
            PlayFabClientAPI.ForgetAllCredentials();

        if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(100, 0, 100, 30), "(re)Load Files"))
            LoadAllFiles();

        if (PlayFabClientAPI.IsClientLoggedIn())
        {
            // Display existing files
            _tempUpdates.Clear();
            var index = 0;
            foreach (var each in _entityFileJson)
            {
                GUI.Label(new Rect(100 * index, 60, 100, 30), each.Key);
                var tempInput = _entityFileJson[each.Key];
                var tempOutput = GUI.TextField(new Rect(100 * index, 90, 100, 30), tempInput);
                if (tempInput != tempOutput)
                    _tempUpdates[each.Key] = tempOutput;
                if (GUI.Button(new Rect(100 * index, 120, 100, 30), "Save " + each.Key))
                    UploadFile(each.Key);
                index++;
            }
            // Apply any changes
            foreach (var each in _tempUpdates)
                _entityFileJson[each.Key] = each.Value;

            // Add a new file
            NewFileName = GUI.TextField(new Rect(100 * index, 60, 100, 30), NewFileName);
            if (GUI.Button(new Rect(100 * index, 90, 100, 60), "Create " + NewFileName))
                UploadFile(NewFileName);
        }
    }

    void Login()
    {
        var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
        {
            CustomId = SystemInfo.deviceUniqueIdentifier,
            CreateAccount = true,
        };
        PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
    }

    void OnLogin(PlayFab.ClientModels.LoginResult result)
    {
        entityId = result.EntityToken.Entity.Id;
        entityType = result.EntityToken.Entity.Type;
    }

    void LoadAllFiles()
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");

        GlobalFileLock += 1; // Start GetFiles
        var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType } };
        PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
    }

    void OnGetFileMeta(PlayFab.DataModels.GetFilesResponse result)
    {
        Debug.Log("Loading " + result.Metadata.Count + " files");

        _entityFileJson.Clear();
        foreach (var eachFilePair in result.Metadata)
        {
            _entityFileJson.Add(eachFilePair.Key, null);
            GetActualFile(eachFilePair.Value);
        }
        GlobalFileLock -= 1; // Finish GetFiles
    }

    void GetActualFile(PlayFab.DataModels.GetFileMetadata fileData)
    {
        GlobalFileLock += 1; // Start Each SimpleGetCall
        PlayFabHttp.SimpleGetCall(fileData.DownloadUrl,
            result => { _entityFileJson[fileData.FileName] = Encoding.UTF8.GetString(result); GlobalFileLock -= 1; }, // Finish Each SimpleGetCall
            error => { Debug.Log(error); }
        );
    }

    void UploadFile(string fileName)
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");

        ActiveUploadFileName = fileName;

        GlobalFileLock += 1; // Start InitiateFileUploads
        var request = new PlayFab.DataModels.InitiateFileUploadsRequest
        {
            Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
            FileNames = new List<string> { ActiveUploadFileName },
        };
        PlayFabDataAPI.InitiateFileUploads(request, OnInitFileUpload, OnInitFailed);
    }

    void OnInitFailed(PlayFabError error)
    {
        if (error.Error == PlayFabErrorCode.EntityFileOperationPending)
        {
            // This is an error you should handle when calling InitiateFileUploads, but your resolution path may vary
            GlobalFileLock += 1; // Start AbortFileUploads
            var request = new PlayFab.DataModels.AbortFileUploadsRequest
            {
                Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
                FileNames = new List<string> { ActiveUploadFileName },
            };
            PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1; UploadFile(ActiveUploadFileName); }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads
            GlobalFileLock -= 1; // Failed InitiateFileUploads
        }
        else
            OnSharedFailure(error);
    }

    void OnInitFileUpload(PlayFab.DataModels.InitiateFileUploadsResponse response)
    {
        string payloadStr;
        if (!_entityFileJson.TryGetValue(ActiveUploadFileName, out payloadStr))
            payloadStr = "{}";
        var payload = Encoding.UTF8.GetBytes(payloadStr);

        GlobalFileLock += 1; // Start SimplePutCall
        PlayFabHttp.SimplePutCall(response.UploadDetails[0].UploadUrl,
            payload,
            FinalizeUpload,
            error => { Debug.Log(error); }
        );
        GlobalFileLock -= 1; // Finish InitiateFileUploads
    }

    void FinalizeUpload(byte[] data)
    {
        GlobalFileLock += 1; // Start FinalizeFileUploads
        var request = new PlayFab.DataModels.FinalizeFileUploadsRequest
        {
            Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
            FileNames = new List<string> { ActiveUploadFileName },
        };
        PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure);
        GlobalFileLock -= 1; // Finish SimplePutCall
    }
    void OnUploadSuccess(PlayFab.DataModels.FinalizeFileUploadsResponse result)
    {
        Debug.Log("File upload success: " + ActiveUploadFileName);
        GlobalFileLock -= 1; // Finish FinalizeFileUploads
    }
}
#endif

Notiz

Jede Dateiaktion erfordert viele Schritte und mehrere API-Aufrufe. Versuchen Sie daher nicht, gleichzeitig auf dieselbe Datei zuzugreifen. Wenn Sie sehr vorsichtig sind, benötigen Sie möglicherweise keinen Sperrmechanismus. Wenn Sie etwas Kompliziertes ausführen möchten, ist Ihr Sperrmechanismus möglicherweise viel komplexer.

Game Manager und Entitäten

Mit dem Game Manager können Sie Objekte und Dateien für Spieler bearbeiten. In der Spielerübersicht werden sowohl die Informationen zum Titelspieler als auch master Spielerkonto angezeigt.

Game Manager – Entitäten – Spielerübersicht

Darüber hinaus verfügen Dateien und Objekte jetzt über eigene Abschnitte auf der Registerkarte Spieler .

Game Manager – Entitäten – Playerdateien und -objekte

Weitere Informationen

Einführung in Entitäten, Objekte und Dateien im PlayFab-Blog.