Strange error during test with Unity 2.6

Hello,

Found another error with Unity 2.6.

I’m making my game inside Unity + SFS. So far so good with last version of Unity.

When I test with 2.6, this errors occurs:

!Thread::EqualsCurrentThreadID(m_MainThreadID)

!Thread::EqualsCurrentThreadID(GetPersistentManager().GetMainThreadID())  mode != kCreateObjectDontRegisterInstanceID

m_ThreadCheck  !Thread::EqualsCurrentThreadID(m_ThreadID)

It shows every second…
In the bottom part of editor, for the first error, it says:

Assert in file: .. \ .. \ Runtime\ Serialize\ PersistentManager.cpp at line: 694

Second error:

Assert in file: .. \ .. \ Runtime\ BaseClasses\ BaseObject.cpp at line: 505

And third one:

Assert in file: .. \ .. \ Runtime\ Utilities\ MemoryPool.cpp at line: 117

Somebody knows what is it? :lol:
The errors starts when other player enters in the same scene as my player (but it was already in the same room)… the pauses when this happens, sometimes I can unpause and continue, sometimes it crashs UNity and I need to CTRL+DEL :lol:

Is there any particular action in the player script that reacts when another player is present? (Just trying to narrow it down…)

Not in player script… I have a “master script” that checkes connections and who enters the room (the room is controlled via Unity+SFS). But everything works…

The only thing that reacts is when player attacks, then it trigger an event in remote player (prefab in my scene). But I dont think this has anything to do with the error.

I tested other way now…
If I enter the room the other player created, the error does not happen, but if he goes out (exit room), it happens again… the built version works good… the error occurs only during edit mode

yep. I have this error too. :?
But no crushes. :slight_smile:

Guys,

Unity is not thread safe. This means that only one thread can call into Unity API functions. In your scripts you can start other threads. These threads may not call Unity functions. We added an assert into 2.6 when the player is running inside the Editor to report when a calling thread was not the thread that started Unity script. The message you have is basically saying “the code calling into Unity is not the thread that Unity is expecting. The behaviour of Unity may become unpredictable.” (The problem is really when two threads call into Unity functions at the same time.)

When Unity spits out these type of messages the intention is that it gives you a clue about something wrong about to happen. In the best case make sure your game runs without any asserts/warnings/errors from Unity.

Thanks,
Graham

Yes, I always try to keep the game without errors…
I will try to get where, in my script, the error occurs… I still dont know where or where to start from, because in 2.5 no message was given to me and I already have lots of line of code.

Thanks for the reply.

I’m working with the Sun Game Server / Darkstar Server. I got the exact same list of errors as the original poster. It almost got me to stay with 2.5.1 to be honest. However the lure of the performance profiler proved strong enough to send me seeking a solution.

And so, this is my fix. There may be a million more better fixes out there, but this one is mine.

In essence, one must build a buffer of all incoming messages from servers that use threading communications API’s.

I separated the listener class and code from all other classes, and added a static List to it, along with a static method that returns the string at zero position in the list and deletes that string. All incoming messages from the server are added to that list of messages instead of being acted on directly. This includes special messages such as login confirmations which may actually appear to be separate functions in the communications interface.

I have one such object handling session communication (Only one instance per client) and a dictionary of them in a separate class handling channel communications (multiple channels per client).

Various monobehaviours now access the message lists according to their needs.

Eg: The update class for my login manager monobehaviour script starts with

    void Update()
    {
        if (CityOSSession.msgList != null  CityOSSession.msgList.Count > 0)
        {
            String receivedDataString = CityOSSession.msgList[0];
            CityOSSession.msgList.RemoveAt(0);
            String[] cmds = receivedDataString.Split(receivedDataString.ToCharArray()[0]);
            if (cmds[1].Equals("UploadCharacter"))
            {
                MasterManager.characterManager.UploadedCharacter(cmds);
            }
            else if (cmds[1].Equals("LoggedIn"))
            {
                LoggedIn();
            }
            else if (cmds[1].Equals("CharacterList")) 
            {
             ...
             ....
(etc)

The incoming messages from the server are stuffed into the message lists quite simply.

class CityOSSession : SimpleClientListener
{
    public static List<String> msgList;
    public static byte[] reconnectKey;
    private System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

...

    public CityOSSession(String loginName, String loginPass, String server, int port)
    {
        msgList = new List<string>();
        msgList.Add("~msg~Logging in!");
        this.loginName = loginName;
        this.loginPass = loginPass;
        client = new SimpleClient(this);
        try { client.login(server, port); }
        catch (Exception e) { msgList.Add("client.login error [" + e.ToString()+"]"); }
    }

...
    public void LoggedIn(byte[] reconnectKey)
    {
        CityOSSession.reconnectKey = reconnectKey;
        msgList.Add("~LoggedIn");
        client.SessionSend(encode("~CharacterList"));
        client.SessionSend(encode("~RaceList"));
        client.SessionSend(encode("~ClassList"));
    }
...
    public void ReceivedMessage(byte[] message)
    {
        if (msgList == null) { msgList = new List<string>(); }
        String receivedDataString = Encoding.UTF8.GetString(message);
        msgList.Add(receivedDataString);
    }
...

The actual access of the static lists is moved off to nice secure static functions on the session classes, but here is shown in the Update that uses it for clarity.

The methods that can be called by the server should not make any calls on any Unity methods, or even on any code that can call unity methods, (save only the Debug.Log apparently).

For clarity in my code I do not include a “Using UnityEngine;” in any classes that implement server communication.

There is concern at the back of my mind regarding the possibility of unity side code trying to read a string from the list before the server driven method has finished writing it. I’d like to assume that List.Add() is atomic, but it’d be a big assumption.

Hope this helps out any other folks who find their server communications being slapped with “Bad Thread! Bad!” errors.

Hey, Emfinnfz, thanks for the tip, I will take a look.

In fact, the version 2.6 is really bad for me too. I’m almost changing back to 2.5.
Several errors appears now that was not happening before. And in my built game, when I’m testing with my users, the game simply crash all the time and I still dont know why. And I did not change much in code…

I really hope UT can make a bug fix soon… otherwise, I will need to get back to 2.5.1

:roll: :cry:

Guys,

By all means change back to 2.5 or 2.5.1. All that will happen is the assert will not be triggered. Your code is just as likely to not work. What I mean is, to help people know that their code is using threads in a dangerous way we have added some code to check what thread is calling into Unity and give this assert if it is not the correct one.

Old code:

someUnityAPIFunction()
{
// do something useful
}

New code:

someUnityAPIFunction()
{
// check if calling thread is not the expected one and give assert
// do something useful
}

@xandeck

There is no Unity bug here. There is nothing for us to fix. Please ignore the assert if it bothers you, but it is there to tell you your code is calling Unity in an unsafe way. Unity is saying “don’t play with scissors”. We are not stopping you from playing with scissors, but when you hurt yourself (and your game exhibits random bugs) please remember our warning.

I have not studied Emfinnfz’s code, but his description of how to use async sockets safely is stop on.

Thanks,
Graham

We are checking the code again.
This is not hapenning with another project, so we already realized that is something what we did, or any project conversion error.

I only wanted to know if it was some Unity error or bug.
Yes, maybe I’m playing with scissors, but I wanted to know how to operate the scissor… I only got the answer in the last post.

Just found out, this also happens when trying to release a Unity object (a mesh, for example) from within a class destructor. My guess is that the garbage collector is running in a different thread and when the destructor is called, the assert fails (obviously). I know it’s not good practice to use class constructors and destructors with Unity, but I was just testing to see what I could and couldn’t do. :wink:

I don’t know really, it seems like there’s something fishy here. I go to great lenghts to keep my threaded (tcp server) code safe and always use locked buffers for information exchange.

However, when I’m using Application.LoadLevelAsync(), I get these error messages about threads. If I use the regular LoadLevel(), I don’t get any errors. How come?

Exactly how much work does the LoadLevelAsync do? Does it call Awake() and such on stuff, before handing the loaded scene over to the main Unity thread?

It’s a bit troublesome that the error message doesn’t provide a proper stacktrace.

Also… something interesting… I don’t get the thread warning messages in OSX - only in Windows.

I have the exact same problem with Application.LoadLevelAsync().

So i do also have to use LoadLevel() instead to make the error disappear and it do also give me a better proformance.

Just for the record, this is an extremely confusing and unhelpful “helpful warning”. :shock: No stack trace, and from reading it, I assumed I was accessing an object in a dead thread somehow. This was scary since I didn’t even realize I was using multiple threads! (The callbacks from SmartFoxServer come in from different threads, but that wasn’t documented anywhere.) Could you make this assertion message clearer?

Also, how hard would it be for you guys (Unity) to make SendMessage() thread-safe? From folks who have adopted the sample code from SmartFoxServer, this function is likely the cause of the problems.

More importantly, in most systems (such as Windows messaging or most Java message structures), “SendMessage” is thread-safe, so it not being so is pretty unintuitive.

I’m getting these errors with LoadLevelASync too. Is this a Unity bug or what? I’m not using any external code, nor am I starting any threads of my own. In fact, I pretty much don’t do anything except check ASyncOperation.IsDone until it’s loaded. Yet I’m still getting these threading errors. As mentioned above, there’s no stacktrace or anything, so there’s nothing I can do to debug it. It would be very annoying not to be able to use Asynchronous loading, but I can’t very well release a game which is throwing serious errors like this either.

I dont get these errors anymore… I dont know about these commands with the error too… try to report for the bug report, I think they can have a look :wink:

Are you using 2.6 or 2.6.1? I haven’t upgraded to 2.6.1 as I’m in the middle of a project, but upgrading when the project is complete is always an option.

I was using 2.6.1 when I got the error.

I’m getting these too - and I’m pretty sure that the code running is thread safe “workaround” as also explained by someone in an earlier post.

SFS BTW has a “queue mode” for this exact reason - so use that. Its already build in.

The error is totally useless really for debugging anything. You just get the error on the console without any extra info to help you. Please make it more informative.

/Thomas