我正在开发一个类似于unity个智力竞赛游戏的应用程序,其中包括一些matchmakingmultiplayer功能.我的问题是,我已经设置了Firebase身份验证,然后我已经设置了Firebase实时数据库,让点击开始按钮的玩家,之后他会看到搜索游戏标签来匹配其他玩家,我现在正在使用不同的设备进行测试,所以当玩家1点击开始按钮,然后玩家2点击开始按钮时,他们两个都应该进入游戏场景,但在我的情况下,只有玩家2可以进入游戏场景,而玩家1停留在同一场景.我想知道这里有什么问题,这是我第一次做在线应用程序/游戏,所以我还没有

using UnityEngine;
using UnityEngine.SceneManagement;
using Firebase;
using Firebase.Database;
using Firebase.Auth;
using System;
using System.Collections.Generic;

public class MatchmakingManager : MonoBehaviour
{
    private DatabaseReference databaseReference;
    private FirebaseAuth auth;
    private FirebaseUser currentUser;
    private bool isMatchmaking = false;
    private bool sceneTransitioned = false;

    void Start()
    {
        // Initialize Firebase components
        databaseReference = FirebaseDatabase.DefaultInstance.RootReference;
        auth = FirebaseAuth.DefaultInstance;
        currentUser = auth.CurrentUser;

        if (currentUser != null)
        {
            // Check if the current user is already in matchmaking
            CheckMatchmakingStatus();
        }
        else
        {
            Debug.LogError("User is not logged in.");
        }
    }

    private void CheckMatchmakingStatus()
    {
        // Check if the current user is already in matchmaking
        databaseReference.Child("matchmaking").Child(currentUser.UserId).GetValueAsync().ContinueWith(task =>
        {
            if (task.IsCompleted && !task.IsFaulted && !task.IsCanceled)
            {
                DataSnapshot snapshot = task.Result;
                if (snapshot != null && snapshot.Exists)
                {
                    // User is already in matchmaking
                    isMatchmaking = true;
                }
                else
                {
                    // User is not in matchmaking
                    isMatchmaking = false;
                }
            }
            else
            {
                Debug.LogError("Failed to check matchmaking status: " + task.Exception);
            }
        });
    }

    public void StartMatchmaking()
    {
        if (!isMatchmaking)
        {
            // Add the current user to matchmaking
            databaseReference.Child("matchmaking").Child(currentUser.UserId).SetValueAsync(true).ContinueWith(task =>
            {
                if (task.IsCompleted && !task.IsFaulted && !task.IsCanceled)
                {
                    // Successfully added to matchmaking
                    isMatchmaking = true;

                    // Check for available matches
                    FindMatch();
                }
                else
                {
                    Debug.LogError("Failed to start matchmaking: " + task.Exception);
                }
            });
        }
        else
        {
            Debug.LogWarning("User is already in matchmaking.");
        }
    }

    public void CancelMatchmaking()
    {
        // Remove the player from the matchmaking pool
        string playerId = auth.CurrentUser.UserId;
        databaseReference.Child("matchmaking").Child(playerId).RemoveValueAsync().ContinueWith(task =>
        {
            if (task.IsCompleted && !task.IsFaulted && !task.IsCanceled)
            {
                // Successfully removed from matchmaking
                isMatchmaking = false;
            }
            else
            {
                Debug.LogError("Failed to cancel matchmaking: " + task.Exception);
            }
        });
    }

    private void FindMatch()
    {
        // Query the database for game rooms with two players
        databaseReference.Child("matchmaking").OrderByKey().LimitToFirst(2).GetValueAsync().ContinueWith(task =>
        {
            if (task.IsCompleted && !task.IsFaulted && !task.IsCanceled)
            {
                DataSnapshot snapshot = task.Result;
                if (snapshot != null && snapshot.HasChildren && snapshot.ChildrenCount == 2)
                {
                    // Found two players, remove them from matchmaking
                    List<string> playerIds = new List<string>();
                    foreach (DataSnapshot playerSnapshot in snapshot.Children)
                    {
                        string playerId = playerSnapshot.Key;
                        playerIds.Add(playerId);
                    }

                    // Create a game room for the matched players
                    CreateGameRoom(playerIds[0], playerIds[1]);
                }
                else
                {
                    // No available matches yet or insufficient players in the queue
                    Debug.Log("No available matches yet or insufficient players in the queue, continuing waiting...");
                }
            }
            else
            {
                Debug.LogError("Failed to find a match: " + task.Exception);
            }
        });
    }

    private void CreateGameRoom(string player1Id, string player2Id)
    {
        // Generate a unique ID for the game room
        string roomId = databaseReference.Child("gameRooms").Push().Key;

        // Create a data structure representing the game room
        Dictionary<string, object> roomData = new Dictionary<string, object>();
        roomData["player1Id"] = player1Id;
        roomData["player2Id"] = player2Id;
        roomData["status"] = "active"; // You can set initial status to "active" or "waiting" or any other status you prefer

        // Set the data in the database under the generated room ID
        databaseReference.Child("gameRooms").Child(roomId).SetValueAsync(roomData)
            .ContinueWith(task =>
            {
                if (task.IsCompleted && !task.IsFaulted && !task.IsCanceled)
                {
                    Debug.Log("Game room created successfully!");

                    // Transition the matched players to the gameplay scene only if it hasn't been done before
                    if (!sceneTransitioned)
                    {
                        sceneTransitioned = true;
                        SceneManager.LoadScene("GamePlay");
                    }
                }
                else if (task.IsFaulted)
                {
                    // Handle the error
                    foreach (Exception exception in task.Exception.InnerExceptions)
                    {
                        Debug.LogError("Failed to create game room: " + exception.Message);
                    }
                }
                else if (task.IsCanceled)
                {
                    Debug.LogWarning("Creating game room task was canceled.");
                }
                else
                {
                    Debug.LogError("Unknown error occurred while creating game room.");
                }
            });
    }
}

以前有过什么经历吗.

我希望两个玩家都go 游戏现场,然后我需要处理其他功能,如分数,玩家姓名等.

推荐答案

井.当第一个玩家进入游戏时,他没有找到任何其他玩家,并被添加到等待名单中.

当第二个玩家进入时,他看到了第一个玩家,并创建了一个房间--然后go 了"游戏现场"--而第一个玩家并不知道这一点.

解决方案: 第一个玩家-如果他找不到任何可用的房间-应该创建一个房间-并听取其中的变化.当第二个玩家进入时,他会找到这个房间,加入并聆听这个 node -当双方都加入并且更新已经到来时,开始游戏场景.

而且,如果不调试我也无法判断,但看起来你的玩家同时创建了两个ID不同的房间.

string roomId = databaseReference.Child("gameRooms").Push().Key;
    //two rooms will be created
    // you must have a common room id for two players.
    // For example String(player1Id+player2Id)

你也可以用databaseReference.Child("matchmaking").Child(currentUser.UserId).GetValueAsync()

适用于一次性取数:

您可以使用GetValueAsync方法读取 在给定路径上的内容一次.任务结果将包含快照 包含该位置的所有数据,包括子数据.如果有 没有数据,则返回的快照为空.

你需要听这changes

在任何情况下,这都是一种误解--你可以通过这种方式获得两个随机的玩家,而不是发起创建房间的那个.

databaseReference.Child("matchmaking").OrderByKey().LimitToFirst(2)

Csharp相关问答推荐

使用GeneratedComInterfaceProperty的.NET 8 COM类对于VB 6/SYS或ALEViewer不可见

如何使嵌套for-loop更高效?

如何在Visual Studio中为C# spread操作符设置格式规则?

在C#中使用in修饰符

在静态模式下实例化配置

JSON空引用异常仅在调试器中忽略try-Catch块,但在其他上下文中捕获得很好

显示文档的ECDsa签名PDF在Adobe Reader中签名后已被更改或损坏

使用Entity Framework6在对象中填充列表会导致列表大多为空

在DoubleClick上交换DataGridViewImageColumn的图像和工具提示

WPF DataGrid文件名列,允许直接输入文本或通过对话框按键浏览

WPF动态设置弹出窗口水平偏移

如何强制新设置在Unity中工作?

如何使用IHostedService添加数据种子方法

如何将 colored颜色 转换为KnownColor名称?

Xamarin中出错.表单:应用程序的分部声明不能指定不同的基类

SignalR跨域

如何在更新数据库实体时忽略特定字段?

为什么Visual Studio 2022建议IDE0251将我的方法设置为只读?

同时通过多个IEumable<;T&>枚举

使用';UnityEngineering.Random.Range()';的IF语句仅适用于极高的最大值