The easiest way to hide and show rendering objects is to assign animation keys to them. To do this, move the cursor over the eye icon (visibility in the viewport) or camera (visibility when rendering) in the Outliner window, press the “i” key and then manage the created condition in the Graph Editor like the ordinary animation keys.
But this method is not always available. For example, we cannot assign visibility animation keys for collections, Blender will generate errors like:
“hide_viewport” property cannot be animated
or
“hide_render” property can not be animated
However, using the Blender Python API, we can control the visibility of such objects.
Let’s create a simple scene with three objects in their own collection. In practice, there can be lots of meshes in one collection, which allows managing the visibility of all them through the single collection.
Let’s open the Text Editor, internal or external as you like, and create a script that will manage the visibility of the three created collections – “cube”, “monkey” and “sphere”.
At first, define three lists to specify the frames on which we need to change the collection visibility.
1 2 3 4 5 |
import bpy bpy.data.collections['cube']['toggle_visibility_frame'] = [2, 22, 42, 62, 82] bpy.data.collections['monkey']['toggle_visibility_frame'] = [10, 70] bpy.data.collections['sphere']['toggle_visibility_frame'] = [25, 45, 66, 75] |
We added a new attribute “toggle_visibility_frame” to each collection and assigned it with a list of frame numbers. Through this list, we can conveniently assign frames to change the visibility of the desired collection.
Define the list with the collections to which we assigned the visibility change attribute.
1 |
collections_list = [collection for collection in bpy.data.collections if 'toggle_visibility_frame' in collection] |
Next, define the function that will compare the current timeline frame number with the list of numbers from the “toggle_visibility_frame” attributes and if the number of the current frame matches the number specified in the list, change the visibility of the collection by hiding or showing it.
1 2 3 4 5 |
def on_frame_change(scene): for collection in collections_list: if bpy.context.scene.frame_current in collection['toggle_visibility_frame']: collection.hide_render = not collection.hide_render collection.hide_viewport = not collection.hide_viewport |
Now we need to call this function every time a frame is changed in the timeline. Let’s bind the call of our function to the frame change event through the “frame_change_pre” handler, which calls every time before changing the next frame in the scene.
1 2 3 4 |
from bpy.app import handlers if on_frame_change not in handlers.frame_change_pre: handlers.frame_change_pre.append(on_frame_change) |
That’s all.
Full text of our script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import bpy from bpy.app import handlers bpy.data.collections['cube']['toggle_visibility_frame'] = [2, 22, 42, 62, 82] bpy.data.collections['monkey']['toggle_visibility_frame'] = [10, 70] bpy.data.collections['sphere']['toggle_visibility_frame'] = [25, 45, 66, 75] collections_list = [collection for collection in bpy.data.collections if 'toggle_visibility_frame' in collection] def on_frame_change(scene): for collection in collections_list: if bpy.context.scene.frame_current in collection['toggle_visibility_frame']: collection.hide_render = not collection.hide_render collection.hide_viewport = not collection.hide_viewport if on_frame_change not in handlers.frame_change_pre: handlers.frame_change_pre.append(on_frame_change) |
Execute the script by clicking the “Run Script” button and start the animation.
As a result, the collections are shown and hidden in accordance with the assigned frames.