6
$\begingroup$

I have a driver on a keyshape which is controlled by an object moving in the scene. I would like to add a 5 frame delay so the keyshape changes are delayed by X frames.

I am using scripted expression currently it has (var+2.73)*.1

so if its possible to add what ever is required to make a delay.

cheers Shaun

$\endgroup$

2 Answers 2

12
$\begingroup$

Similar to this answer, we can use a driver function to capture the relevant details - but instead of using the values to calculate the velocity and/or acceleration, we can simply store the previous data value into a queue and retrieve the value after the specified number of frames.

Here's the code you'll need - paste it into a Text Editor window named something like 'delay.py'. Tick the 'Register' checkbox to ensure it's run automatically whenever the .blend is loaded - or just run it manually using the 'Run Script' button.

import bpy

attributes = {}

def drv_delay(frame, attr, delay, value):
# Used to delay the value by a specified number of frames.

    # Determine whether we already have a value for this attribute
    if attr in attributes:
        attribute = attributes[attr]
    else:
        # Not found - create a new record for it and store it
        attribute = {'frame':frame, 'dataqueue': []}
        attributes[attr] = attribute

    if frame <= 1:
        del(attribute['dataqueue'][:])

    # Only store the value on change of frame (to guard against being called multiple times per frame)
    if frame != attribute['frame']:

        # Store this value in the queue
        attribute['dataqueue'].append(value)

        # Discard any elements that are more than the delay period
        while len(attribute['dataqueue']) > (delay+1):
            del(attribute['dataqueue'][0])  #remove one from head of the list

    # Store frame
    attributes[attr]['frame'] = frame

    #return the value at the head of the list
    if len(attribute['dataqueue']) == 0:
        return value
    else:
        return attribute['dataqueue'][0]

if 'drv_delay' in bpy.app.driver_namespace:
    del bpy.app.driver_namespace['drv_delay']
bpy.app.driver_namespace['drv_delay'] = drv_delay

The script defines a driver function and registers it in the driver namespace to make it available to use in driver scripted expressions. This means that we can use a new function in the driver expression as follows :

drv_delay(<frame>, <attribute>, <delay>, <value>)

Where frame is the current frame (so we can detect frame change for handling the delay), attribute is a name for this 'delay queue' - each property will need to be given a unique name so that blender knows which one we are referring to), delay is how many frames the 'queue' should buffer, value is the actual value that we want to delay.

To use it, set up the driver Scripted Expression as something like :

drv_delay(frame,"cube_y",10, var)

This sets up a delay queue named 'cube_y' (for the y-coordinate of the cube) with a delay of 10 frames. var is the value being delayed. The function will essentially return the var value passed in 10 frames ago.

To demonstrate, here's an example with an Empty moving in the scene, with a Cube delayed by 10 frames and a Sphere delayed by 15 frames. The queues are automatically reset at frame 1 so the motion can restart afresh.

animated delay location

Blend file included

$\endgroup$
6
  • $\begingroup$ Thankyou for your answer, I am giving you the tick for the answer and level of detail, thanks heaps for this. :) I will have a play with this to see what needs to happen and toy around with your blend file. $\endgroup$ Commented May 16, 2018 at 6:36
  • $\begingroup$ for some reason blender keeps discarding my drivers as soon as I reload the file. $\endgroup$ Commented Feb 2, 2021 at 20:29
  • $\begingroup$ I would upvote this twice if I could. Thank you for this! $\endgroup$
    – ofekp
    Commented Feb 25, 2023 at 16:24
  • $\begingroup$ Would this be possible with Geometry Nodes ? $\endgroup$
    – gordie
    Commented Oct 11, 2023 at 6:55
  • $\begingroup$ I honestly don't know @gordie. I suppose it all depends on when the drivers are evaluated in relating to geometry nodes.... best thing is to try it. Note that geometry nodes now includes 'Simulation' which can update per frame so you do have the ability to do similar but in different ways. $\endgroup$ Commented Oct 12, 2023 at 9:45
1
$\begingroup$

Maybe you can use an Empty, parented to your moving object, with "slow parent" activated (in Object/relation Extra) and an offset of 5 frames. Then drive the empty instead of the moving object.

$\endgroup$
1
  • $\begingroup$ Thankyou Kindly for an answer, I will try this. I wanted to give you the tick, but this other answer deserves it due to the details and effort they put into it. Cheers. $\endgroup$ Commented May 16, 2018 at 6:28

You must log in to answer this question.

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