7
$\begingroup$

Is it possible to assign a specific action to multiple objects?

I have 13 000 objects and they all need to have their render visibility animated off. I was hoping to create an action for one of them and then somehow assign that action to each object.

I don't believe I can simply use the "make links" functionality, since each object has also another action, that must stay individual for each object (and making links would override that action).

$\endgroup$
  • $\begingroup$ Related: blender.stackexchange.com/questions/7335/… You can also consider to join them as a single object (if acceptable). $\endgroup$ – Leon Cheung Feb 23 '15 at 4:55
  • $\begingroup$ @LeonCheung I can't join them as single object, because each object has unique location keyframes. The answer in the link you provided doesn't go into any detail on how to assign the action to multiple objects. $\endgroup$ – Antti Feb 24 '15 at 23:25
  • 1
    $\begingroup$ @Antti Should each object appear/disappear at different times, or everyone at the same time? $\endgroup$ – Einar Feb 25 '15 at 0:08
  • $\begingroup$ Everyone at the same time. $\endgroup$ – Antti Feb 25 '15 at 15:07
3
+100
$\begingroup$

I've edited the code to hide all selected objects at frame 40.

If you want to hide the objects at a different frame, you only need to edit the value for hide_at_frame.

Note: I haven't put it any functionality for removing previous keyframing of visibility. So if you run this script 3 times, with different values, you're going to get 3 keyframes.

Code

import bpy

selected_objects = bpy.context.selected_objects
hide_at_frame = 40

for cube in selected_objects:
    #Hide from viewport
    cube.hide = False
    cube.keyframe_insert(data_path="hide", index=-1, frame=1) 

    cube.hide = True
    cube.keyframe_insert(data_path="hide", index=-1, frame=hide_at_frame)

    #Hide from render
    cube.hide_render = False
    cube.keyframe_insert(data_path="hide_render", index=-1, frame=1) 

    cube.hide_render = True
    cube.keyframe_insert(data_path="hide_render", index=-1, frame=hide_at_frame)
$\endgroup$
  • $\begingroup$ I would need two small modifications: 1.Only affect selected objects and 2.Animate all selected objects off at the same time (not incrementally) $\endgroup$ – Antti Feb 25 '15 at 15:19
  • $\begingroup$ @Antti I've updated the code to meet the new requirements =) $\endgroup$ – Einar Feb 25 '15 at 18:54
  • $\begingroup$ @Antti Updated code again. First code only hid objects from viewport. Now it hides from both viewport and from render. $\endgroup$ – Einar Feb 25 '15 at 19:10
  • 1
    $\begingroup$ Thank you, this seems like the simplest solution, so bounty for you! :) Edit: seems like I need to wait 2 more hours to award it. $\endgroup$ – Antti Feb 25 '15 at 21:08
3
$\begingroup$

There are still possible solutions by using some node-based animation addons like Animation nodes and MotionTool. It is hard to cover enough information here on how to use them, but you can learn them from many places, and they are not so hard to learn at all (I'll try cover the basic usage if really requested).

Now let's take a simple case. Assuming you want to render the object(s) during frame 1 to 10, not render during frame 11 to 15, then render again from frame 16, we can use them to do so:

Setup for Animation Nodes:

enter image description here

Setup for MotionTool:

enter image description here

enter image description here

P.S.: You can still insert keyframes for buttons and values on those nodes, which may further simplify the setups, but the animation data haven't been exposed to any editors, which makes it less convenient to control, and not currently recommended.

$\endgroup$
1
$\begingroup$

same as my answer here :

this code keeps a specific group of objects' visibility related to an object this is how it works :

  • add the selected objects to a group named 'linked objects'
  • rename the active object 'source object'
  • whenever the function is called it copies the render visibility from the 'source object' to the rest objects in the group
  • the function is appended to the frame_change_pre() handler to be called automatically before each frame change

Note :
- before you run the script make sure to select your objects and the active object is going to be the source object thus it will be renamed ( you can make a dummy object as the source to keep the names)
- you can add/remove other objects later to/from the group because the update is related to the group not specific objects

import bpy

bpy.context.active_object.name = 'source_object'
linked_objects = bpy.data.groups.new('Linked_objects')
selected_objects = [obj for obj in bpy.context.selected_objects 
                            if obj.type == bpy.context.active_object.type]
for obj in selected_objects:        
      linked_objects.objects.link(obj)


def link_visibility(context):

    linked_objects = bpy.data.groups['Linked_objects'].objects
    hide = bpy.context.scene.objects['source_object'].hide_render


    for obj in linked_objects:
        obj.hide_render = hide


bpy.app.handlers.frame_change_pre.append(link_visibility)  #update on frame change

#bpy.app.handlers.scene_update_pre.append(link_visibility) #this for instant update
  • you animate the render visibility on the source object and other object will have the same effect
$\endgroup$
0
$\begingroup$

Use animation nodes ;) enter image description here

Toggle between 0 and 1 in the "Integer Input" node.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.