Search Unity

Thread issues when upgrading from 2.6 to 3.0

Discussion in 'Editor & General Support' started by thpetsen, Oct 3, 2010.

  1. thpetsen

    thpetsen

    Joined:
    Feb 25, 2010
    Posts:
    21
    HI, this weekend I started porting a fully functional 2.6 project to Unity 3.0, now that it is out of beta.
    I must say that Unity 3.0 is quite impressive, lots of useful improvements !
    This said, I soon ran into severe problems that I would like to share for comments, and perhaps even possible solutions.

    Background: We are creating a 'chess'-like game, i.e. we have a huge AI-part that we like to run in the background not interfering with the GUI thread (animations, &c.). We have a fully working 2.6 solution where we create a background thread (using System.Threading) to handle game logics, AI &c. Works perfectly (in Unity 2.6), as long as we don't manipulate any GUI related stuff. Thread switch is performed by letting Update() handle the GUI related part.

    Observations in Unity 3.0 (in order of apperance):
    1) thread can no longer call GameObject.Find() (never returns)
    2) thread can no longer call gameObject.GetComponent<>() (never returns)
    (ok these two can be delt with by caching the items)
    3) thread can no longer test if a component is null (like in if(thecomp != null) { ...})
    (this is strange, why (and how) is this implemented ? - a solution is to cast the component to object before testing).
    4) thread can not access (read) gameObject.name
    (strange !)
    5) thread can not access (read) gameObject.transform

    Ok. I finally get the picture:
    Starting from Unity 3.0, a background thread can no longer access *ANY* method or member of any GameObject.
    This is really turning into a showstopper for our plans of porting to Unity 3.0

    By "can no longer xxx" in the above I mean that the function never returns, not even when reading the member gameObject.name, thus effectively halting the thread.

    I can not see any reference to these changes in the documentation. The release notes mention better thread support, but it seems to be even worse than in Unity 2.6 now making it absolutely useless.

    In 2.6 I noticed assertions in the GUI functions that checked for correct thread (when I by mistake tried to do GUI manipulations from the wrong thread), I hope this is something similar that I see in Unity 3.0, and that Unity removes these assertion or at least sends a message to the console or an exception to the script.

    We would love to use Unity3.0 but this is really a showstopper.
     
  2. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    864
    I have the same problem. It's not only GameObject that can't be accessed though.

    "END" is never printed in the following code:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Threading;
    4.  
    5.  
    6. public class ThreadTest : MonoBehaviour
    7. {
    8.     bool threadEnded;
    9.    
    10.    
    11.     IEnumerator Start()
    12.     {
    13.         Debug.Log( "START" );
    14.         Thread someThread = new Thread( new ThreadStart( SomeThread ) );
    15.         someThread.Start();
    16.         while( !threadEnded ) yield return 0;
    17.         Debug.Log( "END" );
    18.     }
    19.    
    20.    
    21.     void SomeThread()
    22.     {
    23.         float something = Random.value;
    24.         threadEnded = true;
    25.     }
    26.    
    27. }
    If I uncomment Random.value then "END" is printed.

    Could someone from Unity please respond?

    Best
    ~ce
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    No Unity functions are thread-safe and none of them can be used in threads. You can only use thread-safe .NET functions (such as System.Random instead of UnityEngine.Random).

    --Eric
     
  4. cannon

    cannon

    Joined:
    Jun 5, 2009
    Posts:
    751
    Just to add, it only seems to work in 2.6, but it's actually unsafe code that's going to crash at odd times.
    3.0 just adds extra checks to keep users from doing things that look like they work but aren't safe.
     
  5. thpetsen

    thpetsen

    Joined:
    Feb 25, 2010
    Posts:
    21
    Why has this not been documented ? This is a big change since 2.6 !

    I had to revrite my thread code to use Coroutine yield instead, this dramatically changing the dynamics in the game, I have lost several weeks of development in that process...

    I hope there is some very good reasons for this, like System.Threads are not generally supported across platforms (Iphone, Android &c.), please give us some insight as to why thread support have been removed in Unity !

    @Cannon: It is not completely random, it works in 2.6 as long as you do not access GUI methods, but you can read transform.position etc. and do calculations in the background thread - updating the transform has to be done in the GUI thread (via Instantiate or Update()).
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's not a change from 2.6, except that it's enforced now. You never were supposed to use Unity functions in threads. If it ever worked it was just luck.

    Thread support hasn't been removed. You can still use all thread-safe .NET functions, same as before.

    --Eric
     
  7. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    864
    Ah! Well please document it then. It would be convenient if an attempt to use unity functions in a thread would throw a nasty error to the console.

    Thanks for the reply
    ~ce
     
  8. galent

    galent

    Joined:
    Jan 7, 2008
    Posts:
    1,078
    If I"m understanding correctly, that won't work, but it should if you change SomeThread() this way:

    void SomeThread()
    {
    lock(this) {
    float something = Random.value;
    threadEnded = true;
    }
    }

    That will make the method processing thread-safe, which should allow the code to operate as expected.

    Correct Eric?
     
  9. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Incorrect

    Not use means not use.
    Unity does not lock it on its side so nothing prevents it from still running into the wall.

    If you want a random in a thread, use System.Random as Eric mentioned
     
  10. galent

    galent

    Joined:
    Jan 7, 2008
    Posts:
    1,078
    Ok, so how is that implemented? Obviously Random.value is a Unity wrapper object, but how is the exclusion manifested? Is the new Thread outside the namespace? Does the same apply to child threads? It's not like we forked the process, just spun up a new thread to handle some extranous processing (ok, let's ignore all the cross-platform and threading implecations for the moment).

    First, why enforce a singleton processing model in the first place? (That's still and anti-pattern approach, however popular... yes I'm in that camp :) )

    Second, How are the Unity functions being excluded? If a method, or class, or whatever is thread-safe, then where in execution is this exclusion rule being applied? thinking aloud... I assume extending all classes from Monobehaviour is the base class with the Unity namespace, but I can build non-monobehaviour class structures and use them in Unity - as long as I don't define my own namespace... as I recall (correct me if I'm wrong). Even that restriction seems odd, within the context of the mono .Net runtime.

    Just trying to understand myself (for sanity's sake :) ),

    Cheers,

    Galen
     
  11. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537
    does thread here means use of other processors of PC (like 2nd core of core 2 duo)?
     
  12. galent

    galent

    Joined:
    Jan 7, 2008
    Posts:
    1,078
    that depends on the runtime (mono .net per platform in this case). I assume the Mono .Net is using native threads, so yes, load would be distributed across the processors via the OS thread scheduler, if it's green threads then thread processing is managed by the .Net VM and timesliced over whatever processors the VM is using.

    Cheers,

    Galen
     
  13. rahuxx

    rahuxx

    Joined:
    May 8, 2009
    Posts:
    537
    any example or code that simply distributes my unity project load to multiple cores/threads on this forum?