Search Unity

How to execute something outside of Update everytime it is called?

Discussion in 'Scripting' started by LimePencil, Jul 29, 2021.

  1. LimePencil

    LimePencil

    Joined:
    Jun 24, 2021
    Posts:
    2
    I am currently using another thread for data transmission, and I want to call the movement function outside of Update() function. The problem is that when I call

    playerObj.transform.position = new Vector3(0,0,27f,0)


    inside of the other thread, it causes this error

    UnityException: get_transform can only be called from the main thread.
    Constructors and field initializers will be executed from the loading thread when loading a scene.

    How do I solve this so that I can properly call the function in another thread?


    Please help me. I been struggling so long
     
    Last edited: Jul 29, 2021
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,747
    You need a delegate queue, then the other thread locks and adds to that queue, while Update locks and removes from it.

    Then you would package up that little snippet of code above and pass it out for execution on the main thread via Update():

    Something as simple as:

    Code (csharp):
    1. private     Queue<System.Action> TODO = new Queue<System.Action>();
    and then to fill it:

    Code (csharp):
    1.         lock(TODO)
    2.         {
    3.             TODO.Enqueue( () => {
    4.                 // your code here
    5.                 playerObj.transform.position = new Vector3(0,0,27f);
    6.             });
    7.         }

    and then in your Update():

    Code (csharp):
    1. lock(TODO)
    2. {
    3.         // Warning: this is an ultra simple concept-only demo.
    4.         // This code will fail if any delegate executed in here
    5.         // causes a fresh attempt to enqueue something, which
    6.         // would then spin-lock against the locked queue.
    7.         //
    8.         // A proper professional solution requires you to:
    9.         // - copy all delegates out
    10.         // - release the queue lock
    11.         // - execute those copied out delegates.
    12.         //
    13.         while( TODO.Count > 0)
    14.         {
    15.             // NOT A TYPO: first paren pair is "get the action," second is "invoke it"
    16.             TODO.Dequeue()();
    17.         }
    18. }
    The dequeue could be snazzier and copy ALL items out of the queue at once, THEN execute them, especially to avoid spinlock situations where a dequeued item could in turn invoke code that would add to the queue, which it couldn't do because it was locked. :)

    There's also this handy-dandy asset store package that might prove helpful:

    https://assetstore.unity.com/packages/tools/thread-ninja-multithread-coroutine-15717
     
    Last edited: Nov 22, 2021
    tonemcbride, _geo__ and LimePencil like this.
  3. LimePencil

    LimePencil

    Joined:
    Jun 24, 2021
    Posts:
    2
    Thanks! I read about this somewhere but you explained clearly!
     
    Kurt-Dekker likes this.