I have a character with eyes.

enter image description here

I have a blink shapekey. and I am using this expression as a driver to randomly blink on certain frames

noise.random() > 0.97

enter image description here

But the blinking is a bit abrupt. I wish I could do it over three frames instead of one. Is there some way to get random blinking in this manner?


1 Answer 1


You can add custom functions instead of simple expressions in your driver. There you can realise more complex behaviours.

Head to the Scripting tab and run this script (see docs):

import bpy
from mathutils import noise

def blink_longer():

    # still blinking
    if blink_longer.time > 0:
        blink_longer.time -= 1
        return True
    # new blink?
    elif noise.random() > 0.97:
        blink_longer.time = 3 # max blink time
        return True
    # not blinking
        return False

blink_longer.time = 0  # avoid a global to track blinking

# add blink function to the driver namespace
bpy.app.driver_namespace['blink_longer'] = blink_longer

Side note: I added an attribute to the function to avoid a global, but globals will work too.

Now in your driver expression, just call the function blink_longer() et voila, longer blinking.

Edit: Based on @HarryMcKenzie's comment, some notes about usage: because driver functions drive something (i.e. values) they must return the driven value. In the screenshot i added a custom function

def func():

to the driver namespace by running the script (note that this action works as func itself is valid python). But using this function in a driver results in ERROR: Invalid Python expression which my be confusing. By checking the error with Window > Toggle System Console one can see that "func" is correctly printed (thus func has been called) and after that a type error occures. The driven weight value of the shape key is a number but func returns implicitly None, hence the error. func needs to return something number compatible in this case. The blink_longer function returns True/False which is ok as True/False are coerced to $1/0$ respectively. After fixing errors, run the namespace script again to override the old function definition and then refresh the driver expression.

enter image description here

  • $\begingroup$ +1 very good to know with the namespace thing to prevent global namespace pollution. but can you post a screenshot to be more specific on the usage? because i tried it and i get error snipboard.io/h67y8n.jpg I already ran the script but still not detected. $\endgroup$ Aug 10, 2023 at 2:59
  • $\begingroup$ @HarryMcKenzie When you check the console, you will see TypeError: must be real number, not NoneType because your myfunc doesn't return anything (thus None). Returning True/False as in my example is ok as its get coerced to $0/1$. I'll update my answer. $\endgroup$
    – taiyo
    Aug 10, 2023 at 6:52
  • 1
    $\begingroup$ yes very good especially for beginners. btw it's True=1, False=0, which is different from return Success=0 and return Fail>0 :D $\endgroup$ Aug 10, 2023 at 7:56
  • 1
    $\begingroup$ Darn, you got me. Haha nice catch^^ $\endgroup$
    – taiyo
    Aug 10, 2023 at 8:00
  • 1
    $\begingroup$ Thanks! I dunno why i didn't get a notification for your answer. I didn't know we could call custom python functions like this! Lemme double check that this works when I get home tomorrow and then I'll get you the green check mark. $\endgroup$
    – TheJeran
    Aug 12, 2023 at 16:26

You must log in to answer this question.

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