GS2-Realtime

GS2 SDK for Unity を利用して リアルタイム通信機能を実装します。

GS2-Matchmaking の説明でマッチメイキングが成立した際に Gs2.Matchmaking.Gathering が得られる例を示しました。

GS2-Realtime はこの Gathering インスタンスを受け取って通信処理を開始します。

独自のマッチメイキングを利用して、リアルタイム通信機能を利用したい場合は Gs2.Matchmaking.Gathering インスタンスを作成してIPアドレスやポートの情報を設定して GS2-Realtime のクライアントに渡してください。

リアルタイム通信を実装する

ゲームサーバセッションを作成する

Gs2.Realtime.RealtimeSession rsession = gs2.Realtime.CreateSession (
    session,
    gathering,
    new RealtimeEventHandler ());

gs2.Realtime.CreateSession() でゲームサーバへ接続するゲームセッションを作成します。

session には GS2のログインセッションを、gathering には接続するゲームサーバの情報を渡します。

この関数を呼び出した段階ではゲームサーバへの接続は行われず、後述の Dispatch() で実際の接続処理が実行されます。

ゲームサーバと通信する

rsession.Dispatch (
    events => {

    });

Gs2.Realtime.RealtimeSession.Dispatch() でゲームサーバとの通信処理を行います。

この処理はコルーチンで呼び出すことでブロックせずに処理を実行することが出来ます。

実装サンプル

GS2-Realtime も GS2-Matchmaking 同様 イベントハンドラ方式とコールバック方式の2種類のアプローチで実装することができるよう設計されています。

イベントハンドラ方式

public class GameLogic : MonoBehaviour {

    private const string CLIENT_ID = "your client id";
    private const string CLIENT_SECRET = "your client secret";

    private const string MATCHMAKING_NAME = "matchmaking-0001";

    Gs2.Client gs2;
    Gs2.GameSession session;
    bool started;
    Gs2.Matchmaking.Gathering gathering;
    Gs2.Realtime.RealtimeSession rsession;
    DateTime lastSendTime;

    void Start () {
        // GS2 Client を初期化
        gs2 = new Gs2.Client (new Gs2.Profile ()
            .WithClientId (CLIENT_ID)
            .WithClientSecret (CLIENT_SECRET));
        lastSendTime = DateTime.Now;

        StartCoroutine (Login ());
    }

    IEnumerator Login() {
        // GS2-Account を利用して認証します
        string GAME_NAME = "game-0001";
        string KEY_NAME = "account";
        string USER_ID = "user";
        string PASSWORD = "password";
        string authenticationToken = null;
        yield return gs2.Account.Authentication (
            result => {
                if(result.Error != null) throw result.Error;
                authenticationToken = result.Result;
            },
            GAME_NAME,
            KEY_NAME,
            USER_ID,
            PASSWORD);

        // GS2-Account の認証情報を利用して GS2 にログインします
        yield return gs2.Auth.Login (
            result => {
                if(result.Error != null) throw result.Error;
                session = result.Result;
            },
            USER_ID,
            KEY_NAME,
            authenticationToken);

        StartCoroutine (StartMatchmaking ());
    }

    IEnumerator StartMatchmaking() {
        // マッチメイキングを開始する
        Gs2.Matchmaking.AnybodyMatchmakingConfig config =
            new Gs2.Matchmaking.AnybodyMatchmakingConfig ()
                .MatchmakingName (MATCHMAKING_NAME)        // GS2-Matchmaking に作成したマッチメイキング名
                .Handler (new EventHandler());            // イベントハンドラ
        gs2.Matchmaking.Anybody.Start (session, config);
        started = true;
    }

    void Update () {
        if (started && gathering == null) {
            // マッチメイキングを開始しており、マッチメイキングが完了していない間呼び出す
            StartCoroutine (DoMatchmaking ());
        }
        if (gathering != null) {
            // マッチメイキングが完了している場合に呼び出す
            StartCoroutine (DoRealtime ());
        }
    }

    IEnumerator DoMatchmaking() {
        // マッチメイキング処理を実行する
        yield return gs2.Matchmaking.Anybody.Dispatch (
            result => {
                if(result.Error != null) throw result.Error;
                Gs2.Matchmaking.Event mmEvent = result.Result;
                if(mmEvent != null) {
                    switch(mmEvent.Type) {
                    case Gs2.Matchmaking.EventType.COMPLETE:
                        // マッチメイキングが成立したときに返ります
                        this.gathering = mmEvent.Gathering;
                        break;
                    }
                }
            },
            session);
        if (this.gathering != null) {
            // マッチメイキングが成立した場合は GS2-Realtime の初期化を行う
            StartCoroutine (CreateRealtimeSession ());
        }
    }

    IEnumerator CreateRealtimeSession() {
        // GS2-Realtime のゲームサーバに接続する
        rsession = gs2.Realtime.CreateSession (
            session,
            gathering,
            new RealtimeEventHandler ());
    }

    IEnumerator DoRealtime() {
        // リアルタイム通信を開始します
        yield return rsession.Dispatch (
            events => {
                // イベントハンドラ方式では、ここのコールバックには処理を記述する必要はありません
            });

        // 5秒に1回対戦相手にメッセージを送信する
        lock (this) {
            if (DateTime.Now - lastSendTime >= TimeSpan.FromSeconds (5)) {
                lastSendTime = DateTime.Now;
                rsession.Send ("hello");
            }
        }
    }
}

public class RealtimeEventHandler : Gs2.Realtime.RealtimeEventHandler
{
    public void Connect ()
    {
        // ゲームサーバとの接続に成功したときに呼び出されます
    }

    public void Join (string userId)
    {
        // 新しくプレイヤーが参加したときに呼び出されます
    }

    public void Leave (string userId)
    {
        // 参加していたプレイヤーが離脱したときに呼び出されます
    }

    public void Complete ()
    {
        // 参加予定のプレイヤーが全員揃ったときに呼び出されます
    }

    public void Recive (string text, string fromUserId)
    {
        // メッセージを受信したときに呼び出されます
        Debug.Log ("メッセージ: " + text);
        Debug.Log ("送信元ユーザID: " + fromUserId);
    }

    public void Disconnect()
    {
        // 自分がサーバから切断されたときに呼び出されます
    }
}

コールバック方式

public class GameLogic : MonoBehaviour {

    private const string CLIENT_ID = "your client id";
    private const string CLIENT_SECRET = "your client secret";

    private const string MATCHMAKING_NAME = "matchmaking-0001";

    Gs2.Client gs2;
    Gs2.GameSession session;
    bool started;
    Gs2.Matchmaking.Gathering gathering;
    Gs2.Realtime.RealtimeSession rsession;
    DateTime lastSendTime;

    void Start () {
        // GS2 Client を初期化
        gs2 = new Gs2.Client (new Gs2.Profile ()
            .WithClientId (CLIENT_ID)
            .WithClientSecret (CLIENT_SECRET));
        lastSendTime = DateTime.Now;

        StartCoroutine (Login ());
    }

    IEnumerator Login() {
        // GS2-Account を利用して認証します
        string GAME_NAME = "game-0001";
        string KEY_NAME = "account";
        string USER_ID = "user";
        string PASSWORD = "password";
        string authenticationToken = null;
        yield return gs2.Account.Authentication (
            result => {
                if(result.Error != null) throw result.Error;
                authenticationToken = result.Result;
            },
            GAME_NAME,
            KEY_NAME,
            USER_ID,
            PASSWORD);

        // GS2-Account の認証情報を利用して GS2 にログインします
        yield return gs2.Auth.Login (
            result => {
                if(result.Error != null) throw result.Error;
                session = result.Result;
            },
            USER_ID,
            KEY_NAME,
            authenticationToken);

        StartCoroutine (StartMatchmaking ());
    }

    IEnumerator StartMatchmaking() {
        // マッチメイキングを開始する
        Gs2.Matchmaking.AnybodyMatchmakingConfig config =
            new Gs2.Matchmaking.AnybodyMatchmakingConfig ()
                .MatchmakingName (MATCHMAKING_NAME)        // GS2-Matchmaking に作成したマッチメイキング名
                .Handler (new EventHandler());            // イベントハンドラ
        gs2.Matchmaking.Anybody.Start (session, config);
        started = true;
    }

    void Update () {
        if (started && gathering == null) {
            // マッチメイキングを開始しており、マッチメイキングが完了していない間呼び出す
            StartCoroutine (DoMatchmaking ());
        }
        if (gathering != null) {
            // マッチメイキングが完了している場合に呼び出す
            StartCoroutine (DoRealtime ());
        }
    }

    IEnumerator DoMatchmaking() {
        // マッチメイキング処理を実行する
        yield return gs2.Matchmaking.Anybody.Dispatch (
            result => {
                if(result.Error != null) throw result.Error;
                Gs2.Matchmaking.Event mmEvent = result.Result;
                if(mmEvent != null) {
                    switch(mmEvent.Type) {
                    case Gs2.Matchmaking.EventType.COMPLETE:
                        // マッチメイキングが成立したときに返ります
                        this.gathering = mmEvent.Gathering;
                        break;
                    }
                }
            },
            session);
        if (this.gathering != null) {
            // マッチメイキングが成立した場合は GS2-Realtime の初期化を行う
            StartCoroutine (CreateRealtimeSession ());
        }
    }

    IEnumerator CreateRealtimeSession() {
        // GS2-Realtime のゲームサーバに接続する
        rsession = gs2.Realtime.CreateSession (
            session,
            gathering);
    }

    IEnumerator DoRealtime() {
        // リアルタイム通信を開始します
        yield return rsession.Dispatch (
            events => {
                // イベントハンドラ方式と異なり、このコールバックで発生したイベントをハンドリングします
                foreach(Gs2.Realtime.Event rtEvent in events) {
                    switch (rtEvent.Type) {
                    case Gs2.Realtime.EventType.CONNECT:
                        // ゲームサーバとの接続に成功したときに返ります
                        break;
                    case Gs2.Realtime.EventType.JOIN:
                        // 新しくプレイヤーが参加したときに返ります
                        break;
                    case Gs2.Realtime.EventType.LEAVE:
                        // 参加していたプレイヤーが離脱したときに返ります
                        break;
                    case Gs2.Realtime.EventType.COMPLETE:
                        // 参加予定のプレイヤーが全員揃ったときに返ります
                        break;
                    case Gs2.Realtime.EventType.MESSAGE:
                        // メッセージを受信したときに返ります
                        Debug.Log ("メッセージ: " + rtEvent.Message.Text);
                        Debug.Log ("送信元ユーザID: " + rtEvent.Message.FromUserId);
                        break;
                    case Gs2.Realtime.EventType.DISCONNECT:
                        // 自分がサーバから切断されたときに返ります
                        break;
                    }
                }
            });

        // 5秒に1回対戦相手にメッセージを送信する
        lock (this) {
            if (DateTime.Now - lastSendTime >= TimeSpan.FromSeconds (5)) {
                lastSendTime = DateTime.Now;
                rsession.Send ("hello");
            }
        }
    }
}

どちらの方式を採用しても リアルタイム通信を実装することが出来ます。