This document is about: QUANTUM 2
SWITCH TO

Unityプラグイン


Available in the Gaming Circle and Industries Circle
Circle

開始方法

Unityプラグインをインストールする

Unityパッケージをダウンロードしてインストールします(SDKへのアクセス権が与えられると、ダウンロードリンクが表示されます)。
Assets/Import package/Custom Packageで通常どおりにパッケージをインポートします。

これには、ゲームクライアント内でトーナメントを実行するために必要なdllが含まれます。

新しいゲームを作成してgameIdをセットアップする

すべてのファイルをゲーム/プロジェクトにインポートしたら、ゲームID を作成する必要があります。
これを行うには、トーナメントダッシュボードにログインし、add new gameボタンをクリックし、新しいゲームを作成するまでウィザードの手順に従います。

Add game image

Then open Game settings/General where you can find your game id.
次にGame settings/Generalを開き、自分のゲームIDを見つけます。

Get gameid image

次に、Unityプロジェクトで、以下の名前のインポート済みファイルを見つけます。
Plugins/Gimmebreak.Backbone/Resources/フォルダーにある BackboneClientSetting.asset
以下に示すように、ファイルを開き、自分の ゲームIDにコピーします。

Set gameid image

SDKクライアントを初期化する

BackboneManagerスクリプトをシーンオブジェクトに追加します。
Unityの Start() が呼び出されたときにクライアントを初期化する場合は、 Initialize on startと書かれたボックスにチェックマークを付けます。

Add backbone manager image
Set backbone manager image

クライアントを手動で初期化する場合(例:インターネット接続を確認した後)には、後から明示的な呼び出しでおこなうことができます。

C#

public class MyMonoBehaviour : MonoBehaviour
{
    //EXAMPLE 1, using callback
    public void ExplicitInitializeCall()
    {
        //initializing Backbone (TournamentSDK) client
        BackboneManager.Initialize()
            .ResultCallback((result) => {
                if(result)
                {
                    //success
                }
                else
                {
                    //fail
                }
            })
            .Run(this);
    }

    //EXAMPLE 2, using Unity coroutine
    public IEnumerator ExplicitInitializeCallCoroutine()
    {
        //some other code initialization
        //...
        //waiting for internet connectivity
        //...
        //initializing Backbone (TournamentSDK) client
        AsyncOperation<bool> asyncOperation = BackboneManager.Initialize();
        //wait until initialization is done
        yield return asyncOperation;
        //check result
        if(asyncOperation.ReturnValue)        
        {
            //success
        }
        else
        {
            //fail
        }
    }
}

BackboneManager.IsInitializedを使用して、クライアントが初期化されているかどうかを確認できます。

ログインユーザー

ダッシュボードでログインプロバイダーを有効にする

トーナメントダッシュボードを開き、Game Settings/Authentication providersに移動します。
ゲームに関連するプロバイダーを有効にします。
有効な各プロバイダーに必要な設定を入力して保存します。

Login providers image

ログインユーザー

ログインプロバイダーがセットアップされている場合は、ユーザーのログインに進むことができます
クライアントの初期化後、ユーザーがログインしているかどうかを確認できます。
そうでない場合は、ログイン操作を続行できます。

この例では、Steam認証を使用しています。

C#

private IEnumerator Start()
{
    //wait until backbone client is initialized
    while (!BackboneManager.IsInitialized)
    {
        yield return null;
    }
    //check if user is logged in
    if (!BackboneManager.IsUserLoggedIn)
    {
        //Obtain steam user name, auth session ticket, steam id from prefered steam
        //api library
        //...
        //login user using steam authentication provider
        var steamLogin = LoginProvider.Steam(true, userName, steamAuthCode, steamUserId);
        yield return BackboneManager.Client.Login(steamLogin);
    }
}

これにより、Steamログインプロバイダーを使用してユーザーがログインします。
ユーザーが正常にログインした後、クライアントAPIとインタラクトできます。

基本的なトーナメント操作

トーナメントのリストを取得する

すべてのトーナメントのリストが以下の場所に格納されています:

C#

var allTournaments = BackboneManager.Client.Tournaments.TournamentList;

リストを読み込むまたは更新するには(ログイン後に空にすることができます)、 BackboneManager.Client.LoadTournamentList()操作を呼び出す必要があります。

C#

 //load/refresh tournament list
 BackboneManager.Client.LoadTournamentList()
     //set finish callback
     .FinishCallback(() =>
     {
         //bind data after operation finishes
         BindData();
     })
     //run async operation on this MonoBehaviour
     .Run(this);

注: この操作は、リストが正常に更新されたかどうかを示すbool結果を返します。
この操作が頻繁に呼び出されると、falseを返します。
現在の「許可された更新制限」は1分に設定されています。
登録することで操作結果を取得できます。

ResultCallback((result) => {}) は以下のようになります:

C#

 //load/refresh tournament list
 BackboneManager.Client.LoadTournamentList()
     //set finish callback
     .FinishCallback(() =>
     {
         //bind data after operation finishes
         BindData();
     })
     .ResultCallback((result) => {
         if(result)
         {
             //successful refresh/load
         }
         else
         {
             //not refreshed/loaded
         }
     })
     //run async operation on this MonoBehaviour
     .Run(this);

トーナメントリストが読み込まれた後、トーナメントクラスのすべてのプロパティが設定されるわけではありません。
すべてのトーナメントデータを読み込むには、 BackboneManager.Client.LoadTournament(tournamentId)を呼び出す必要があります。
トーナメントクラスにはフラグが含まれています:HasAllDataLoadedで、すべてのデータが読み込まれたかどうかを確認できます。

トーナメントを取得する

すべてのトーナメントデータを読み込む/更新するには、 BackboneManager.Client.LoadTournament(tournament)を呼び出します。
この操作は、トーナメントが正常に読み込まれた/リフレッシュされたかどうかを示すboolを返します。
また、トーナメントクラスには、tournament.HasAllDataLoadedというプロパティがあり、すべてのデータが既に読み込まれているかどうかを示します。

C#

//get first tournament in the list
var tournament = BackboneManager.Client.Tournaments.TournamentList[0];
//load/refresh all tournament data
BackboneManager.Client.LoadTournament(tournament)
    //set finish callback
    .FinishCallback(() =>
    {
        if(tournament.HasAllDataLoaded)
        {
            //all data has been loaded/refreshed
        }
    })
    //run async operation on this MonoBehaviour
    .Run(this);

トーナメントにサインアップする

ユーザーが既にサインアップしているかどうかを確認するには、トーナメントプロパティ: tournament.Inviteを確認してください。
招待がnullの場合、ユーザーには招待がなく、確認もされていません。
招待が利用可能かどうかを確認するには、ユーザーのトーナメントの招待ステータスを保持するtournament.Invite.Statusを確認します。

C#

//get tournament
var tournament = BackboneManager.Client.Tournaments.GetTournamentById(tournamentId);
//check if user is signed up
if (tournament.Invite == null ||
    tournament.Invite.Status != TournamentUserStatus.Confirmed)
{
    //user is not signed up for tournament
}

トーナメントにサインアップするには以下を呼びます: SignupForTournament(tournamentId)

C#

//sign up user for tournament
BackboneManager.Client.SignupForTournament(tournamentId)
    //set result callback
    .ResultCallback((result) =>
    {
        //check sign up result
        if (result.ProcessStatus != TournamentSignUpStatus.Ok)
        {
            LobbyAlertDialog.Show("Sign up process failed with status: " + result.ProcessStatus.ToString());
        }
    })
    //run async operation on this MonoBehaviour
    .Run(this);

この操作は、サインアップ結果に関する情報を含むInviteResultオブジェクトを返します。
サインアッププロセスの外部サーバーがダッシュボードで設定されている場合(例:通貨、アイテムなどを差し引くため)、inviteResult.IsExternalSignupErrorはこの操作中に問題があったかどうかを示します。
また、カスタムサーバーによってスローされたエラーメッセージはすべて、inviteResult.ErrorMessageで参照できます。

トーナメントハブ

トーナメントハブの初期化

トーナメントハブは、トーナメントのカスタムロビーとして機能します。
接続すると、マッチに関する情報とトーナメントの進行状況/ステータスが提供されます。
トーナメントハブコールバックを受信するには、 ITournamentHubCallbackHandlerインターフェースを実装します。

C#

public void OnInitialized(ITournamentHubController controller)
{
    //tournament hub was initialized and provides controller
}

public void OnHubStatusChanged(TournamentHubStatus newStatus)
{
    //tournament hub status has changed
}

public void OnTournamentUpdate()
{
    //tournament data has been updated
}

public void OnHubMatchStatusChanged(TournamentHubMatchStatus newStatus)
{
    //joined tournament match status has changed
}

public void OnHubMatchUpdate()
{
    //joined tournament match data has been updated
}

Tournament Hubを初期化するには: ConnectTournamentHub(callbackHandler, tournament);を呼び出します。コールバックハンドラーはITournamentHubCallbackHandlerを実装するオブジェクトです。

C#

var tournament = BackboneManager.Client.Tournaments.GetTournamentById(tournamentId);
BackboneManager.Client.ConnectTournamentHub(this, tournament);

トーナメントハブが初期化されると、OnInitialized(ITournamentHubController controller)を呼び出し、ユーザーの観点から特定のトーナメントフローを制御するために使用されるコントローラーを返します(例:ユーザーが次のマッチの準備ができていることを示す)。

トーナメントハブのステータス

OnHubStatusChanged(TournamentHubStatus newStatus)は、ユーザーの観点からトーナメントの現在のステータスを示します。 UIは、あらゆる変更に対応する必要があります。

C#

public void OnHubStatusChanged(TournamentHubStatus newStatus)
{        
    switch (newStatus)
    {
        case TournamentHubStatus.RegistrationClosed:
            //Registration is closed and has not been open yet. You can check
            //open time in tournament property 'RegistrationOpenTime'.
            break;
        case TournamentHubStatus.RegistrationOpening:
            //Registration is opening as 'RegistrationOpenTime' was reached but
            //confirmation from server is awaited.
            break;
        case TournamentHubStatus.RegistrationOpened:
            //Registration is opened and users can sign up for tournament.
            break;
        case TournamentHubStatus.RegistrationClosing:
            //Registration/Inivitation is closing as 'InvitationCloseTime' was reached
            //but confirmation from server is awaited.
            break;
        case TournamentHubStatus.WaitingForTournamentStart:
            //Registration is closed and tournament start confirmation from
            //server is awaited.
            break;
        case TournamentHubStatus.Starting:
            //Tournament is starting as tournament 'Time' was reached but
            //confirmation from server is awaited.
            break;
        case TournamentHubStatus.Started:
            //Tournament has started. Get current phase from
            //'tournament.GetCurrentTournamentPhase()' containing user standings.
            break;
        case TournamentHubStatus.MatchInProgress:
            //User has match in progress he should be part of.
            //Get all match metadata from 'tournament.UserActiveMatch'.
            break;
        case TournamentHubStatus.ResolvingPartiallyFilledMatch:
            //User active match was not filled in time. Awaiting confirmation from
            //server if match should be played.
            break;
        case TournamentHubStatus.ClosingOverdueMatch:
            //User active match reached a deadline and its due for closure.
            //Awaiting confirmation from server.
            break;
        case TournamentHubStatus.WaitingForUserReadyConfirmation:
            //User can proceed to next round of the tournament. Explicit confirmation
            //is requested by calling 'tournamentHubController.SetUserReady()'.
            break;
        case TournamentHubStatus.WaitingForNextPhase:
            //Tournament current phase is about to finish. Waiting for next phase to
            //start.
            break;
        case TournamentHubStatus.WaitingForTournamentToFinish:
            //User has finished all rounds in current phase or was already knocked
            //out of the tournament and waiting for tournament to finish.
            break;
        case TournamentHubStatus.Finishing:
            //Last round of last phase has reached deadline and all matches should
            //be finilized. Awaiting confirmation from server.
            break;
        case TournamentHubStatus.Finished:
            //Tournament has finished. Found out who won by looking at
            //'tournament.Winner.Users'
            break;
    }
}

ユーザーのアクティブなマッチ

トーナメントの実行中にユーザーがサインアップすると、すべてのメタデータとステータスを含む有効なマッチが自動的に与えられます。
ユーザーの有効なマッチには、以下のトーナメントハブからアクセスできます: tournamentHub.Tournament.UserActiveMatch

UserActiveMatch.Secretは、ネットワークルーム/ロビーのパスワードまたは名前として使用できます。これは、特定のマッチへの参加が許可されているユーザーにのみ配布されます。

UserActiveMatch.Statusを使用して、ユーザーが他のユーザー/対戦相手を待っているか、ゲームの進行中に特定のルーム/ロビーに接続する必要があるか、ユーザーが別の試合に進む必要があるかを判断します。

C#

switch (tournamentHubController.Tournament.UserActiveMatch.Status)
{
    case TournamentMatchStatus.Created:
        //Match was successfuly created.
        break;
    case TournamentMatchStatus.WaitingForOpponent:
        //Match is not filled and opponents are still awaited to join.
        break;
    case TournamentMatchStatus.GameReady:
        //Match game is ready to be played. Proceed to create game session that will
        //change status to 'GameInProgress'.
                //NB: users might still be checking in and connecting to room/lobby.
             //Client should wait until all parties are successfully connected and ready.
             //Only then procced to create game session.
        break;
    case TournamentMatchStatus.GameInProgress:
        //Match game is in progress, game session was created and it's in progress.
        //NB: user should be able to reconnect to ongoing game session.
        break;
    case TournamentMatchStatus.GameFinished:
        //Match game has finished as results were reported. If match requires more games
        //to be played per series (e.g. best of 3) proceed to create another game session
        //that will change status to 'GameInProgress' again.
        break;
    case TournamentMatchStatus.MatchFinished:
        //Match has finished as all games has been played (or deadline was reached).
        //It will be closed soon, user can proceed to another match.
        break;
    case TournamentMatchStatus.Closed:
        //Match was finalized and closed by server.
        break;
}

UserActiveMatch.Users[i].IsCheckedInを確認することで、対戦相手の準備ができているかどうかを判断できます。
以下を呼び出すことで、UserActiveMatchデータをリフレッシュできます:tournamentHubController.RefreshActiveMatch()
ユーザーがロビー/ルームに参加するたびにこれを呼び出すことをお勧めします。

UserActiveMatchはnullまたは終了済みステータスの可能性があることに留意してください。他のマッチをリクエスト してトーナメントに進むには、ユーザーは明示的にtournamentHubController.SetUserReady()を呼び出す必要があります。
ユーザーは、トーナメントハブがTournamentHubStatus.WaitingForUserReadyConfirmationステートに入ったらこれを行うようにしてください。このアクションはUI(例:次のマッチへ準備)で示したり、ユーザーインタラクションで先導することなくトーナメントハブがそのステートに入ったら即時で次のマッチへ 自動実行 させたりすることができます。

マッチ参加インターフェース

ゲームにプライベートゲーム/ロビー作成のメソッドが定義されている場合、マッチインターフェースを実装すると、ユーザーの参加とトーナメントマッチの開始を管理しやすくなります。

ロビースクリプトにITournamentMatchCallbackHandlerインターフェイスを実装するか、これを実装する新しいスクリプトを作成します。
ロビーの状態をトーナメントハブに伝えるための簡単なメソッドのセットが提供されます。

C#

public void OnJoinTournamentMatch(Tournament tournament, TournamentMatch match, ITournamentMatchController controller)
{
    //Callback from tournament hub passing tournament, match and controller object.
    //Use match data to join correct lobby/room.
    //User controller to inform tournament hub about changes in your lobby/room.
}

public bool IsConnectedToGameServerNetwork()
{
    //Check if client is successfully connected to your networking backend.
    //Return true if user is connected and ready to join lobby/room.
}

public bool IsUserConnectedToMatch(long userId)
{
    //Check if specific user is already connected to lobby/room.
    //Return true if user is connected.
}

public bool IsUserReadyForMatch(long userId)
{
    //Check if specific user is ready (e.g. moved to correct slot)
    //Return true if user is ready to start.
        //NB: local user that is not checked in for the match yet, will be checked in
    //only after returning true
}

public bool IsGameSessionInProgress()
{
    //Check if game session is already in progress for given tournament match.
    //Return true if game session is in progress.
}

public void OnLeaveTournamentMatch()
{
    //Callback from tournament hub informing user should leave joined lobby/room.
}

public void StartGameSession(IEnumerable<TournamentMatch.User> checkedInUsers)
{
    //Callback from tournament hub requesting game session to start immediately. Also
    //passing users that successfully checked in for current match.
    //Create tournament game session, and start your game.
    //This might be called multiple times until IsGameSessionInProgress returns true.
}

このインターフェイスを実装するオブジェクトは、特定のマッチに参加するときにトーナメントハブコントローラーメソッドに渡すことができます: tournamentHubController.JoinTournamentMatch()

コードフローの例:

C#

//Initialize tournament hub
BackboneManager.Client.ConnectTournamentHub(hubCallbackHandler, tournament);
//...
//Get hub controller
public void OnInitialized(ITournamentHubController controller)
{
    hubController = controller
}
//...
//Check tournament hub is in "MatchInProgress" status
public void OnHubStatusChanged(TournamentHubStatus newStatus)
{        
    switch (newStatus)
    {
        case TournamentHubStatus.MatchInProgress:
        case TournamentHubStatus.ResolvingPartiallyFilledMatch:
            //...
            //Join users active match
            var match = hubController.Tournament.UserActiveMatch;
            hubController.JoinTournamentMatch(match, matchCallbackHandler);
            //...
            break;        
    }
}

注: OnJoinTournamentMatchにパスされたtournamentMatchControllerレポートメソッド を使用することも重要です。
接続済みのとび―・ルームで特定のイベントが発生したらコントローラメソッドを呼び出します。
トーナメントハブはこれらを使用してメタデータを更新するタイミングを決定しています。
これを怠ると、不一致となりマッチできるクライアントとそうでないクライアントが出てきてしまいます。(例:他のクライアントにはユーザーがチェックインをしていないように見えます)

レポートをtournamentMatchControllerに変更するPhotonのルームコールバックの使用例

C#

//Photon callback when new player joined room
public void OnPlayerEnteredRoom(Player newPlayer)
{
    long userId;
    //extract user id from player custom properties
    if (this.tournamentMatchController != null &&
        TryGetPlayerBackboneUserId(newPlayer, out userId))
    {
        //report user who joined room
        this.tournamentMatchController.ReportJoinedUser(userId);
    }
}
//Photon callback when player disconnected from room
public void OnPlayerLeftRoom(Player otherPlayer)
{
    long userId;
    //extract user id from player custom properties
    if (this.tournamentMatchController != null &&
        TryGetPlayerBackboneUserId(otherPlayer, out userId))
    {
        //report user who disconnected from room
        this.tournamentMatchController.ReportDisconnectedUser(userId);
    }
}
//Photon callback when room properties are updated
public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
{
    if (this.tournamentMatchController != null)
    {
        //reporting status change will refresh match metadata
        this.tournamentMatchController.ReportStatusChange();
    }
}
//Photon callback when player properties are updated
public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
{
    if (this.tournamentMatchController != null)
    {
        //reporting status change will refresh match metadata
        this.tournamentMatchController.ReportStatusChange();
    }
}

トーナメントゲームセッションと結果提出

トーナメント設定に基づいて、マッチには複数のゲームセッションを含めることができます。
たとえば、1対1のマッチが「ベストオブ3」シリーズとして設定されている場合、少なくとも2つのゲームセッションをプレイする必要があります。
「ゲームセッション」は、試合シリーズのうちの1つのゲームを表します。

ゲームセッションを作成

ゲームセッションを作成するには、 CreateGameSession(users, userActiveMatchId, sessionType)を呼び出します。
返されたゲームセッションIDは、他のクライアントに配布できます。
後続されて別の呼び出しが行われた場合、同じゲームセッションIDが返されます。

C#

//create game session only for checked in users
var checkedInUsers = userActiveMatch.Users.Where(user => user.IsCheckedIn);
//game session type can be used to identify specific game modes
//e.g. 0-default, 1-4player mode, 2-8player mode
var sessionType = 0;
//create game session
BackboneManager.Client.CreateGameSession(checkedInUsers, userActiveMatch.Id, sessionType)
    //set result callback
    .ResultCallback((gameSession) =>
    {
        //get game session id and distribute it to other clients
        //NB: this is up to developer, e.g. use custom room/lobby properties
        //or broadcast message
        var gameSessionId = gameSession.Id;
    })
    //run async operation on this MonoBehaviour
    .Run(this);

結果を送信

ゲームセッションが終了したら、マッチの締め切りに達する前に結果を報告する必要があります。
マッチが複数のゲームセッション(例:3シリーズのうちのベスト)を持つように設定されている場合、 GetMatchNextGameDeadline(match)を使用して現在のゲームセッションの理想的な期限を決定し、後続のゲームセッションをプレイする時間があるかを判断します。

C#

//get user active match
var userActiveMatch = tournament.UserActiveMatch;
//get ideal deadline for next game session
var deadline = tournament.GetMatchNextGameDeadline(userActiveMatch);

ゲームセッションの結果を送信するには、 SubmitGameSession(gameSession)呼び出しを使用します。
ゲームセッションオブジェクトは、 CreateGameSession呼び出しから返された分散ゲームセッションIDを使用して、すべてのクライアントで作成する必要があります。
特定のゲームセッションのポイント分布を決定するユーザーの場所を設定することが重要です。

C#

//create game session only for checked in users
var matchUsers = userActiveMatch.Users.Where(user => user.IsCheckedIn).ToList();
//sort users based on your game session results, e.g. kills, deaths etc.
matchUsers.Sort((user1, user2) =>{
    //sort users from best to worst based on specific game rules
});
//create list for game session users
List<GameSession.User> gameSessionUsers = new List<GameSession.User>();
//loop through sorted users from best to worst
for(var i = 0; i < matchUsers.Count; i++)
{
    var userId = matchUsers[i].UserId;
    var teamId = matchUsers[i].TeamId;
    //add game session user with set final place in game session (more users
    //can have same placement if required)
    gameSessionUsers.Add(new GameSession.User(userId, teamId) { Place = (i + 1) });
}
//get user active match id
var matchId = userActiveMatch.Id;
//create game session using id that was obtained from 'CreateGameSession' call as
//well as passing tournament match id
GameSession gameSession = new GameSession(gameSessionId, 0, gameSessionUsers, matchId);
//set played date and game session duration
gameSession.PlayDate = DateTime.UtcNow;
gameSession.PlayTime = gameTime;
//submit game session to server
BackboneManager.Client.SubmitGameSession(gameSession)
    .ResultCallback((result) => {
        if (result)            
        {
            //game session was successfuly submitted
        }
    })
    .Run(this);

その他

クライアント言語の設定

クライアントは使用する言語を設定できます。
トーナメントが複数の言語で行われる場合、クライアントには設定した言語で表示されます。
設定した言語で行われない場合は、デフォルトとして英語が適用されます。

ユーザー言語を設定するには、UserLanguage プロパティに ISO639‑1 文字列を割り当ててください。

C#

BackboneManager.Client.User.UserLanguage = "en";
BackboneManager.Client.User.SetDataAsDirty();
BackboneManager.Client.SynchUser();

トーナメントリストのキャッシュと日付範囲

Api呼び出しの LoadTournamentList() は、デフォルトで15分に設定されたキャッシュあります。
これは、 TournamentData.tournamentListUpdateLimitを設定することで変更できます。
同様に、日付範囲も TournamentData.tournamentListSinceOffsetTournamentData.tournamentListUntilOffsetで設定できます。

C#

// refresh tournament list cache every 5 minutes
TournamentData.tournamentListUpdateLimit = 5;
// load tournaments from 3 days ago
TournamentData.tournamentListSinceOffset = System.TimeSpan.FromDays(-3);
// load tournaments for next 14 days
TournamentData.tournamentListUntilOffset = System.TimeSpan.FromDays(14);

備考: LoadTournaments() または LoadTournamentsAll()を呼び出す場合は、キャッシュは適用されません。

Back to top