Open6

PlayFabでEntityを使ったプレイヤーのデータ管理をする

TakaseTakase

Entityの初期化(IDとTypeの取得)

  • 基本的にEntityIdとEntityTypeを使ってEntityAPIのメソッドを呼び出す
  • ログイン時のTypeはtitle_player_accountが返る
// 例としてCustomIDでログイン
void Login()
{
    var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
    {
        CustomId = SystemInfo.deviceUniqueIdentifier,
        CreateAccount = true,
    };
    PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
}

// LoginResultがEntityIDとTypeを持ってる
void OnLogin(PlayFab.ClientModels.LoginResult result)
{
    entityId = result.EntityToken.Entity.Id;
    // The expected entity type is title_player_account.
    entityType = result.EntityToken.Entity.Type;
}
  • GetEntityTokenでいつでも取得できる
PlayFabAuthenticationAPI.GetEntityToken(new GetEntityTokenRequest(),
(entityResult) =>
{
    var entityId = entityResult.Entity.Id;
    var entityType = entityResult.Entity.Type;
}, OnPlayFabError); // Define your own OnPlayFabError function to report errors
TakaseTakase

オブジェクトのSet・Get

  • オブジェクト:Entityに紐づいているデータ

SetObjects

  • SetObject型のオブジェクトの中にデータを入れる(data)
    • データはDictionaryで格納?
  • SetObject型の配列を作ってそこにSetObjectを入れる(dataList)
  • EntityIDとEntityTypeを指定してSetObjectsする
var data = new Dictionary<string, object>()
{
    {"Health", 100},
    {"Mana", 10000}
};
var dataList = new List<SetObject>()
{
    new SetObject()
    {
        ObjectName = "PlayerData",
        DataObject = data
    }
};

PlayFabDataAPI.SetObjects(new SetObjectsRequest()
{
    Entity = new EntityKey {Id = entityId, Type = entityType},
    Objects = dataList,
}, (setResult) => {
    Debug.Log(setResult.ProfileVersion);
}, OnPlayFabError);

こんな感じで保存される

GetObject

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

ファイルの添付

Entityに任意の形式でファイルを添付できる
同時に同じファイルを操作しないように、ファイル操作中にロックする機構を作る(ここではGlobalFileLockを使ってる)

ファイルの取得

 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 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 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
}
TakaseTakase

タイトルデータとパブリッシャーデータは後で触る
タイトルデータ:タイトルごとのグローバルなデータ
パブリッシャーデータ:複数のタイトルにまたがるデータ

TakaseTakase

タイトルデータとは

  • キーと値のペア
  • タイトル全体の設定データなどの変数を管理するのに使える

タイトルデータの取得

ドキュメントより、クライアントから取得するコード

public void ClientGetTitleData() {
    PlayFabClientAPI.GetTitleData(new GetTitleDataRequest(),
        result => {
            if(result.Data == null || !result.Data.ContainsKey("MonsterName")) Debug.Log("No MonsterName");
            else Debug.Log("MonsterName: "+result.Data["MonsterName"]);
        },
        error => {
            Debug.Log("Got error getting titleData:");
            Debug.Log(error.GenerateErrorReport());
        }
    );
}
TakaseTakase

そもそもタイトルデータを使うんじゃなくて、Entityで実装したほうがいいのでは?