Results 1 to 10 of 10
  1. #1

    Threading in game engine? [SOLVED]

    I'm experimenting with threads in game engine (blender 2.55). I need an udp-client and some data fetching over the net.

    What concerns me is the fact that threads are not stopped when game engine is stopped. Instead they keep running until they are finished or forever if there is a loop. This may cause problems when game engine is stopped and started several times.

    So, is it generally a bad idea to use threads in game engine? Any experiences?
    Last edited by Ubuntuist; 28-Dec-10 at 14:38.
    /\\\\ Message void if penguin violated
    _\\_V Don\'t mess with the penguin

  2. #2
    The general consensus is that the BGE doesn't support threading. However, given enough experimentation, something might be feasible. One thing to keep in mind is that due to Python's GIL (you can Google it if you want more info) Python scripts do not gain a whole lot from threading. Instead, you might want to look into something like the multiprocessing module, which has a similar interface to the threading module but it uses multiple processes instead of multiple threads. Also, a word of caution: Python doesn't exit when you stop a game when using the embedded player. This sometimes allows for garbage (especially from threads) to build up. Maybe some sort of on exit script can fix this.

    Good luck,

  3. #3
    Thanks for the reply!

    The general consensus is that the BGE doesn't support threading.
    This was my fear also.

    The main reason I want to use threads is that I want to separate my net traffic from game ticks (that are related to FPS, I believe?). Now the udp client triggered by always sensor is slowing down the whole application. Increasing the frequency of always sensor makes things better but it just doesn't seem to be a good solution.

    I will experiment with multiprocessing module.
    /\\\\ Message void if penguin violated
    _\\_V Don\'t mess with the penguin

  4. #4
    Okay, this maybe the ugliest solution ever but it seems to work:

    from threading import Thread
    import time
    class MyThread ( Thread ):
        def run ( self ):
                print("You called my start method")
                    import bge
    bge module only exists when game engine is running. So we test that in thread and if it is not found then we return. As I said, this may break all the rules but it works
    Last edited by Ubuntuist; 17-Dec-10 at 08:30. Reason: typo
    /\\\\ Message void if penguin violated
    _\\_V Don\'t mess with the penguin

  5. #5

  6. #6
    Moderator Monster's Avatar
    Join Date
    Jan 2006
    Or you let the game send an echo message to the thread every X milliseconds. If there is not new message end end the thread. It is ugly too .

  7. #7
    I would make use of a separate process if you truly wanted to separate your networking from the rest of your logic. You can also try making wrapper class around a thread:

    import bge
    class thread_ptr:
        __init__(self, thread):
            self.thread = thread
            self.thread.terminate() # not in Threads
    # Assuming MyThread is the thread you want to use and extends Thread by adding some sort of terminating ability
    bge.logic.thread = thread_ptr(MyThread)
    Now, when thread_ptr gets grabbed by the garbage collector, it should kill MyThread. You can do some Googling around for figuring out how to actually get the thread to terminate. Also, I didn't test any of this.


  8. #8
    Thanks for suggestions!

    I've been playing around with different approaches. I sort of got multiprocessing working but I didn't manage to terminate them properly. No big problem since threads are enough in this case.

    Using only threads things worked ok except updating textures with videotexture. It seems that I *cannot* use videotexture from a thread. Here is a back trace from one attempt:
    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0xb06b0b70 (LWP 2437)]
    0x002e4368 in ?? () from /usr/lib/
    (gdb) bt
    #0  0x002e4368 in ?? () from /usr/lib/
    #1  0x002ea9fc in gluScaleImage () from /usr/lib/
    #2  0x08e05731 in Texture_refresh(Texture*, _object*) ()
    #3  0x092486f0 in PyEval_EvalFrameEx ()
    #4  0x0924933d in PyEval_EvalFrameEx ()
    #5  0x0924933d in PyEval_EvalFrameEx ()
    #6  0x0924933d in PyEval_EvalFrameEx ()
    #7  0x09249ea1 in PyEval_EvalCodeEx ()
    #8  0x091f86ba in ?? ()
    #9  0x091e08bd in PyObject_Call ()
    #10 0x091ece4f in ?? ()
    #11 0x091e08bd in PyObject_Call ()
    #12 0x09242932 in PyEval_CallObjectWithKeywords ()
    #13 0x0927e92f in ?? ()
    #14 0x0077396e in start_thread () from /lib/tls/i686/cmov/
    #15 0x006b7a4e in clone () from /lib/tls/i686/cmov/
    The idea was to download an image and change it in the thread, so that game engine wouldn't have to wait. This may not be possible?

    If nothing else helps, then I'll make a preload script that collects all the data to files on engine start.
    /\\\\ Message void if penguin violated
    _\\_V Don\'t mess with the penguin

  9. #9
    Moderator Monster's Avatar
    Join Date
    Jan 2006
    My suggestion:

    just download the image by your thread as you described.
    Set a property at an KX_GameObject, to notify there is a new image.
    The KX_GameObject senses the property and deals with the VideoTexture as usual.

    I think this provides a good modular solution (thread deals with network, KX_GameObject deals with videotexture, interface = property)

  10. #10
    @Monster: Thanks, I'll try that.

    Meanwhile, here is a sample script of using threads in bge. Like Moguri suggested, I created class that terminates thread on exit. Not tested very well but this seems to work.

    import bge
    # example script of using threads in Blender 2.55 game engine
    # thread(!) in ba:
    # Example of terminating thread is from here:
    import threading
    # class that is responsible for stopping thread (thanks to [email protected])
    class thread_ptr():
        def __init__(self,t):
            print("creating thread_ptr")
            self.thread = t
        def __del__(self):
            print("deleting thread_ptr")
            #self.thread.terminate() # not in Threads
    class TestThread(threading.Thread):
        A sample thread class
        def __init__(self):
            Constructor, setting initial variables
            print("Creating thread")
            self._stopevent = threading.Event()
            self._sleepperiod = 1.0
            threading.Thread.__init__(self, name="TestThread")
        def run(self):
            overload of
            main control loop
            print("starts ", self.getName())
            count = 0
            while not self._stopevent.isSet():
                count += 1
                print ("loop " ,count)
                # do some heavy lifting
                for i in range(100000):
                    n = i
            print ("ends ",self.getName())
        def join(self,timeout=None):
            Stop the thread
            print("Terminating thread")
            threading.Thread.join(self, timeout)
    # run this script only once
    ob = bge.logic.getCurrentController().owner
    if ob['init'] == 0:
        ob['init'] = 1
        thread = TestThread()
        bge.logic.thread = thread_ptr(thread)
        print("GOING ON")
    Thanks for the help everyone!
    Last edited by Ubuntuist; 21-Dec-10 at 05:26.
    /\\\\ Message void if penguin violated
    _\\_V Don\'t mess with the penguin

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts