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.
Blend file included