I have a bit of a weird problem that I simply cannot seem to get around. I want to run 2 timers, each set to a different interval.

The problem that I'm having is that both classes receive each others 'TIMER' event! I think that this is really weird, as one would expect the timer event to be constrained within the class it's created in.

After hours of DuckDuckGoing, I found this forum post: https://blenderartists.org/t/how-to-distinguish-timers-when-running-multiple-modal-operators/601432/7

But it didn't help much, basically stating that it's impossible, + it's from 4 years ago, maybe something has changed.

Am I looking at this the wrong way? Maybe I don't really understand Blender's paradigm here, anything that can help me get on the right track would be really appreciated, thanks!

I created a demo blender file showing my problem: https://keybase.pub/peterwilli/StackExchange_Files/TimerProblem.blend

Just open with Blender and look at the console (open blender from the console in Linux) and run timer1.py and timer2.py, what you see is that both timers run each 1 second, but if you run both, both of them run practically twice as fast, taking each other's event.

  • 1
    $\begingroup$ The only way is using threads. Did you test that? $\endgroup$
    – yhoyo
    Dec 6, 2018 at 11:28
  • $\begingroup$ @yhoyo how would that work using threads? Would I still be able to redraw the 3D view? (I'm using timers to draw a HUD in the Blender editor) $\endgroup$
    – user125756
    Dec 6, 2018 at 12:17

1 Answer 1


Application Timers

Blender 2.8 has a new API to run functions in specific time intervals.

Run a Function every x Seconds

import bpy

def every_2_seconds():
    print("Hello World")
    return 2.0


Move an object every second

import bpy
import functools

def move_obj(ob):
    ob.location.x += 0.1
    return 1

bpy.app.timers.register(functools.partial(move_obj, bpy.context.object), first_interval=1)

Similar but passing object time axis and disp

import bpy
import functools

def move_obj(ob, axis, dist, sec):
    print(ob, axis, dist)
    ob.location["xyz".index(axis)] += dist
    return sec

bpy.app.timers.register(functools.partial(move_obj, bpy.context.object, "x", 0.1, 1), first_interval=1)

bpy.app.timers.register(functools.partial(move_obj, bpy.context.object, "y", 2, 10), first_interval=1)

bpy.app.timers.register(functools.partial(move_obj, bpy.context.object, "z", -0.1, 2), first_interval=1)

On a few quick tests it appears that the context, if passed to the timer like above is restricted, has no "object" attribute for example.

  • $\begingroup$ A friend just told me the same thing, I just downloaded Blender 2.8, too bad that the templates are still using the old version, I'll try to port a tiny bit and mark as valid answer if it works. $\endgroup$
    – user125756
    Dec 6, 2018 at 13:25
  • $\begingroup$ Thanks! It worked, I thought it was going to be an ordeal to port the whole script to Blender 2.8 but it wasn't so bad after all. I never saw the new GUI it looks and works really well. $\endgroup$
    – user125756
    Dec 6, 2018 at 16:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .