全てのメンバーの準備が整うまで待つ方法

オーナーがゲームを開始するタイミングを選択できるようにするには、オーナーを含む全てのメンバーの準備ができるのを待つ必要があります。

ルームメンバーのステータスはルームメンバーオブジェクトに保存できます(詳細については、ロビーの作り方を参照してください)。

全てのメンバーの状態を確認するには、次のコードを使用できます。

public static bool CheckAllRoomMembersState(int desiredState) {
    foreach (var roomMember in StrixNetwork.instance.roomMembers) {
        if (!roomMember.Value.GetProperties().TryGetValue("state",
            out object value)) {
            return false;
        }

        if ((int) value != desiredState) {
            return false;
        }
    }

    Debug.Log("CheckAllRoomMembersState OK");
    return true;
}

ここでStrixNetwork.instance.roomMembersは、ルーム内の全てのメンバーのインスタンスを格納したコンテナーです。この関数は、全てのメンバーの状態がdesiredState引数と等しいかどうかを確認します。

CheckAllRoomMembersState()は、2つの方法で呼び出すことができます。

まず、WaitUntilクラスを使用してコルーチン内で呼び出すことができます。次のコードは、このアプローチを示しています。

// 全てのメンバーを待ってゲームを開始します
void Start() {
    StartCoroutine(WaitStartGame());
}

private IEnumerator WaitStartGame() {
    yield return new WaitUntil(() => CheckAllRoomMembersState(1));
}

別のアプローチは、RoomSetMemberNotificationを使用することです。そのためには、RoomSetMemberNotifiedイベントハンドラーを登録する必要があります。次のコードは、このアプローチを示しています。

public static void AddRoomSetMemberHandler() {
    StrixNetwork.instance.roomSession.roomClient.RoomSetMemberNotified +=
        RoomSetMemberNotifiedHandler;
}

private static void RoomSetMemberNotifiedHandler(
    NotificationEventArgs<RoomSetMemberNotification<CustomizableMatchRoomMember>> notification) {
    if (CheckAllRoomMembersState(1) {
        // 全てのメンバーの準備が整い、ゲームを開始します
        StartGame();
    }
}

注釈

StrixNetwork.instance.roomMembersの内容は、他のクライアントから要求された変更を反映するように自動的に更新されます。この際、新メンバーが追加されたり退出したメンバーが削除されたりするのみではなく、同じメンバーに対するCustomizableMatchRoomMemberオブジェクトが、ネットワーク処理の進行に応じて適時再作成されることもあります。

この結果、`roomMembers`から得たオブジェクトを、将来のフレームで使用するためにキャッシュしておくことはできません。上記の例のCheckAllRoomMembersStateのように、毎フレーム(または通知が届くたびに)roomMembersから最新のオブジェクトを取得するようにしてください。