В Unity (C#) мое время l oop останавливается намного раньше, чем должно - почему и как мне его переписать? - PullRequest
0 голосов
/ 21 апреля 2020

Сценарий: я делаю многопользовательскую игру с 5-ди git кодами комнат (также называемыми «игровыми кодами» или «именами комнат») для идентификации лобби. Чтобы создать комнату:

  1. Текущий регистр комнат загружается из Firebase (и переносится в список)
  2. Создается случайный 5-значный git код
  3. Этот код проверяется для каждого члена списка на наличие конфликта.
  4. . Если возникает конфликт, шаги 2 и 3 повторяются до тех пор, пока не будет достигнут произвольный «предел попыток»

Я использовал некоторое время l oop, чтобы попытаться достичь этого. Теперь, чтобы проверить надежность этого кода, я подумал: «Что произойдет, если сгенерированный код будет конфликтовать с регистром каждый раз? Будет ли достигнут предел попыток?» И ответ «нет»: l oop выходит намного раньше, чем должен в случайной точке (меняется каждый раз, когда я его запускаю), и условия разрыва достоверно не выполняются. Я подозреваю, что он молча терпит крах, потому что ни один из последующих методов не вызывается. Почему это происходит и как я могу реструктурировать этот код, чтобы сделать то, что я хочу?

Вот выдержка из моего кода (метод, который принимает запрос Firebase), а под ним журнал отладки:

void GenerateValidCode(IEnumerable<DataSnapshot> roomsList)
    {
        // This just transfers the room names from the DataSnapshot to a string list, this fixed a problem in the Java version
        List<string> roomNamesList = new List<string>();
        if (roomsList != null)
        {
            foreach(DataSnapshot room in roomsList)
            {
                Debug.Log("ROOM NAME ADDED TO LIST: " + room.Key);
                roomNamesList.Add(room.Key);
            }
        }

        // Game Code generation objects
        string gameCode = "";
        string abc = "ABCDEFGHIJKLMNOPQRSTUVXYZ";
        string num = "0123456789";
        System.Random rand = new System.Random();

        // While loop break conditions
        bool codeGot = false;
        int attemptsLeft = ATTEMPTS_ALLOWED; // ATTEMPTS_ALLOWED is a field set to 100

        // WHILE LOOP BEGINS
        while(!codeGot && attemptsLeft > 0)
        {
            // Generates a 5 digit code
            gameCode = "";
            gameCode = gameCode + abc[(int)(rand.NextDouble() * 26)];
            gameCode = gameCode + abc[(int)(rand.NextDouble() * 26)];
            gameCode = gameCode + abc[(int)(rand.NextDouble() * 26)];
            gameCode = gameCode + num[(int)(rand.NextDouble() * 10)];
            gameCode = gameCode + num[(int)(rand.NextDouble() * 10)];

            // DEBUG PURPOSES ONLY - Forces code to be equal to the only existing code on database
            gameCode = "DRU41";

            Debug.Log("THIS CODE: " + gameCode);

            // If no rooms, then there's no possibility of conflict so we just continue...
            if (roomNamesList.Count == 0)
            {
                codeGot = true;
            }
            else // If there are rooms registered, we must look for a conflict...
            {
                bool conflictFound = false;

                foreach (string roomName in roomNamesList)
                {
                    Debug.Log("ROOM BEING TESTED FOR MATCH: "+roomName);

                    // If there exists any room with the code generated, conflict found set to true
                    if (string.Equals(roomName, gameCode)) conflictFound = true;

                    Debug.Log("CONFLICTFOUND?: " + conflictFound.ToString()); // This will be true every time
                }

                // If no conflict was found, we've got our code
                if (!conflictFound) codeGot = true;
            }

            attemptsLeft--;

            Debug.Log("ATTEMPTS LEFT: "+attemptsLeft.ToString()+",CODEGOT?: "+codeGot.ToString());
        }
        // end of while loop

        if(codeGot)
        {
            main.GameCreationUpdate("Creating room " + gameCode); // This method prints to console as well, but is never called
            CreateRoom(gameCode);
        }
        else
        {
            failureMessage = "Failed to generate unique game code. Try again later.";
            main.OnGameCreationComplete(this, false); // This method also prints to console, but is never called
        }



    }

Выдержка из журнала отладки:

ROOM NAME ADDED TO LIST: DRU41
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:73)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

THIS CODE: DRU41
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:102)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

ROOM BEING TESTED FOR MATCH: DRU41
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:115)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

CONFLICTFOUND?: True
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:120)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

ATTEMPTS LEFT: 99,CODEGOT?: False
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:129)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

Вышеизложенное повторяется, когда попытки попытки возврата влево снижаются, а затем резко заканчивается (здесь 61, иногда 98):

ATTEMPTS LEFT: 61,CODEGOT?: False
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:129)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

Я адаптирую этот проект из проекта, который я уже сделал в Android Studio, и код Java, который делает это в этом проекте, работает нормально (и в основном то же самое).

...