Метод зависает при попытке присвоить значение в функции события - PullRequest
0 голосов
/ 10 марта 2020

Я создаю многопользовательскую игру, которая должна взаимодействовать с сервером. Для связи я создал ClientObject, который постоянно ожидает сообщения от сервера. Когда сообщение получено, оно расшифровывает его и отправляет событие с сообщением. В функции, которая срабатывает, когда событие транслируется, я пытаюсь присвоить часть сообщения PlayerObject. Например, имя других игроков. Моя проблема в том, что когда он достигает Players [i] .Name = name [i], программа зависает. Отладка показывает, что имя [i] является ожидаемым значением. Player [i] .Name имеет значение null в точке назначения, но является доступной переменной String, поэтому строка должна работать.

Объект клиента:

public class ClientObject
{
    public Socket clientSocket;
    public void Connect()
    {
        IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("192.168.56.1"), 3000);

        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        clientSocket.Connect(serverAddress);
        Thread thread = new Thread(new ThreadStart(ReceiveMessage));
        thread.Start();
    }

    public void ReceiveMessage() {
        try
        {
            while (true)
            {

                byte[] rcvLenBytes = new byte[4];
                clientSocket.Receive(rcvLenBytes);
                int rcvLen = System.BitConverter.ToInt32(rcvLenBytes, 0);
                byte[] rcvBytes = new byte[rcvLen];
                clientSocket.Receive(rcvBytes);
                String rcv = System.Text.Encoding.ASCII.GetString(rcvBytes);



                MessageReceivedEventArgs args = new MessageReceivedEventArgs();
                args.Message = rcv;

                if (TestMessageRecevied != null)
                {
                    TestMessageRecevied(this, args);
                }
            }
        }
        catch
        {

        }
    }


    public delegate void MessageHandler(object sender, MessageReceivedEventArgs e);
    public event MessageHandler TestMessageRecevied;
}
    public class MessageReceivedEventArgs : EventArgs
{
    public string Message { get; set; }

}

Объект игрока:

public class PlayerObject
{

    public string Name 
    {
        get;
        set;
    }

    public bool ReadyState
    {
        get;
        set;
    }

    public int DiceLeft
    {
        get;
        set;
    }

}

Готовое меню:

В этом случае я назначаю переменную PlayerObject.Name, но она также зависает, если я пытаюсь изменить спрайт изображений или значение текстового объекта в пользовательском интерфейсе. Так что, похоже, проблема с назначением, но не может тренироваться, что. Если я выполняю назначение в методе Start (), он отлично работает.

public class ReadyMenu : MonoBehaviour
{

    ClientObject client;

    public GameObject backgroundPanel;
    public Sprite tick;
    public Sprite cross;

    Text pName;
    Image imgCheck;

    PlayerObject[] players;

    // Start is called before the first frame update
    void Start()
    {
        pName = GameObject.Find("PlayerPanel1/Name").GetComponent<Text>();

        players = new PlayerObject[6];
        client = new ClientObject();
        client.TestMessageRecevied += Client_MessagedReceived;
        client.Connect();
        SendClientMessage(PlayerPrefs.GetString("name"));

    }

    private void Client_MessagedReceived(object sender, MessageReceivedEventArgs e)
    {
        Debug.Log("In C_MR: " + e.Message);
        string message = e.Message;

        if (message.Contains("READY"))
        {
            //NOT IMPLEMENTED YET

            return;
        }
        if (message.Contains("PLAYERS"))
        {
            //Message before split
            Debug.Log(message);
            message = message.Substring(7);

            //Cut PLAYERS from the string
            Debug.Log("substring: "+message);

            //Seperate names
            char[] sep = { ' ' };
            String[] names = message.Split(sep,StringSplitOptions.RemoveEmptyEntries);

            Debug.Log("after name split");
            Debug.Log("names length is: "+names.Length);
            Debug.Log("names 0 is: "+names[0]);

            for (int i = 0; i < names.Length; i++) 
            {

                Debug.Log("in loop, i = "+i);

                Debug.Log("in loop, setting playerobject name");
                players[i] = new PlayerObject();
                players[i].Name = names[i];
                Debug.Log("in loop, after setting playerobject name");

                //GameObject panel = GameObject.Find("PlayerPanel" + (i + 1));
                //Debug.Log("in loop, activate apnel");
                //panel.SetActive(true);
            }
            Debug.Log("finsihed");
        }

    }

Вывод с проверяемым именем

В C_MR: PLAYERStest

PLAYERtest

Подстрока: test

после разделения

длина имен равна: 1

длина имен 0: test

в l oop, i = 0

в l oop, установка имени игрока

1 Ответ

0 голосов
/ 10 марта 2020

РЕДАКТИРОВАТЬ - Похоже, что ОП отредактировал свой ответ, включив в него оператор players[i] = new PlayerObject(), тем самым лишив законной силы этот ответ


Ваша проблема связана с тем, что вы на самом деле не заполнили свой players массив с PlayerObject с. Делая только PlayerObject[] players = new PlayerObject[6], вы просто создаете массив из шести нулевых объектов.

Следовательно, когда вы пытаетесь получить доступ к свойству player.Name, вы пытаетесь сделать это для нулевого объекта. Это должно вывести NullReferenceException, однако вы маскируете любые исключения, используя try-catch в функции ReceiveMessage без фактического перехвата и регистрации исключения.

Поэтому вам просто нужно заполнить ваш players массив с PlayerObject с, и вы должны быть хороши до go. Вы можете сделать это непосредственно перед тем, как задать имя (например, players[i] = new PlayerObject()), если изменение имени произойдет только один раз за время существования приложения, или сделать это при создании массива players.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...