Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Unity Multiplayer Problem interacting with Unity using threads

Discussion in 'Multiplayer' started by maozao, Jan 29, 2019.

  1. maozao

    maozao

    Joined:
    Jan 20, 2016
    Posts:
    12
    Hello.

    I'm having problems to interact with Unity (objects, Scenes, etc) inside a thread, since looks like Unity doesn't allow modifications on its thread from a different one.

    I kinda found a way to work with that, but I really don't like the way I'm using, so I want to know if someone of you guys have some better idea to deal with it.

    Current situation, I'm starting a new Thread to read/write the TCP packets from/to the server, since I can not use anything from Unity inside of it, I'm adding the packets I'm receiving into a Queue list and reading the list from a Cooroutine.

    This is my current code:

    Code (CSharp):
    1. private Queue<object> packetsToProcess = new Queue<object>();
    2. void Awake() {
    3.     StartCoroutine("ProcessPacketsCoroutine");
    4.  
    5.     Thread t = new Thread(new ThreadStart(AuthenticateUser));
    6.     t.IsBackground = true;
    7.     t.Start();
    8. }
    9.  
    10. private void AuthenticateUser() {
    11.     // Code to open connection and get the stream data, etc
    12.     if (packetType == AuthFailed)
    13.                     {
    14.                         AuthFailed p = new AuthFailed();
    15.                         packetsToProcess.Enqueue(p);
    16.                         break;
    17.                     }
    18.     else if (packetType == AuthSuccess) {
    19.         // SceneManager.LoadScene(1, LoadSceneMode.Single); // Can not do this here, Unity crash
    20.         packetsToProcess.Enqueue(new AuthSuccess());
    21.     }
    22. }
    23.  
    24. private IEnumerator ProcessPacketsCoroutine()
    25.     {
    26.         while(true)
    27.         {
    28.            
    29.             if(packetsToProcess.Count == 0)
    30.                 yield return new WaitForSeconds(0.5f);
    31.  
    32.             var packet = packetsToProcess.Dequeue();
    33.             if(packet is AuthFailed)
    34.             {
    35.                 ErrorText = "Wrong Auth!";
    36.             }
    37.             else if (packet is AuthSuccess) {
    38.                 SceneManager.LoadScene(1, LoadSceneMode.Single); // Here it works, since it's a CoRoutine
    39.             }
    40. }
    Of course it's a totally simplified code, the point is to show the problem with the SceneManager.LoadScene (in this case) and the workaround I found to proccess the packets.

    Any ideas what could be done?
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,824
    I don't believe a Queue is thread safe. I use ConcurrentQueue for this. Requires .net 4.x.
     
  3. maozao

    maozao

    Joined:
    Jan 20, 2016
    Posts:
    12
    Well, I had no problems using Queue, but I'm gonna take a look in the ConcurrentQueue, but that's not really the problem described, the Queue was just a workaround since I can not call for example, SceneManager.LoadScene(), inside the new Thread.
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,824
    I actually think it is the typical solution rather than a work around. Alternatively Unity added the new Jobs system partly due to problems of the Unity API not being thread safe, but I don't think the Jobs system is appropriate for a TCP client/server thread replacement.
     
  5. maozao

    maozao

    Joined:
    Jan 20, 2016
    Posts:
    12
    Well, yeah, it is a solution, I just didn't like it that much, so not sure if there is a better way to handle that hehehehe

    By the way, I've checked the Job Sytem, and for sure it's not to be used in cases like this, seems just a way to process multiple things at same time (parallel) in different threads (low life threads), like rendering trees, walls, etc.
     
    Joe-Censored likes this.
  6. maozao

    maozao

    Joined:
    Jan 20, 2016
    Posts:
    12
    Any improvements in Unity about these kind of scenarios?
     
  7. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,300
    Unity's GameObject world is not thread safe, you are supposed to access it only from the main thread.
    Unity's new DOTS/ECS can be threaded, but it's probably still too early to use.

    You can still use regular C# threads with GameObjects though. Just need to not access Unity API from the threads.
    For example, copy your data, push it into the thread with a ConcurrentQueue or similar, process in the thread, then push it back to main thread.

    Often the copy + queue overhead isn't worth putting it into a thread though.