5
$\begingroup$

I have a script that chooses from about 100 models and changes the selected object's location using constraints. I need some help getting this to happen on keyframe.

Does anyone have anything that could help me?

$\endgroup$
1
  • $\begingroup$ Could you attach the script you have already written? $\endgroup$ Jul 4 at 23:13

2 Answers 2

3
$\begingroup$

There are two parts to this. First you need to create or set the constraints. Second you need to do the keyframing.

Part 1: How to create and set constraints

You need to locate the object, find (or create) the copy location constraint, and change the constraint's target to the object you are copying from. You may also want to change other settings of the constraint.

Here's an example that creates a "COPY_LOCATION" constraint on every selected object but the active object. All constraints use the active object as a target. The spaces are changed just to give an example of setting other parameters.

You can find the names of the parameters by enabling Python Tool Tips in Preferences → Interface → Display. Once you've done that, you can hover over an input in the constraint and it will display the name of the setting.

import bpy

# Adding a constraint to selected objects
# This is an example of adding copy location constraints to objects
# It adds a constraint to every selected objects except the active
# setting the target to the active object.

src_obj = bpy.context.active_object

def get_constraint(obj, name, type):
    """ return the first constraint with name name for obj
        if there isn't one add one of type type and return it
    """
    try:
        con = obj.constraints[name]
    except KeyError:
        con = obj.constraints.new('COPY_LOCATION')
    return con

for dst_obj in bpy.context.selected_objects:
    if dst_obj is src_obj:
        continue
    print(dst_obj.name)
    con = get_constraint(dst_obj, 'Copy Location', 'COPY_LOCATION')
    con.target = src_obj
    con.target_space = 'LOCAL'
    con.owner_space = 'LOCAL'

You'll need to figure out what objects you want the constraint on, the target of the constraint, and any other constraint properties you want to change.

Part 2: How to keyframe

You can't keyframe the constraint's target. Instead you need to do one of two things, depending on whether you are transferring control, or just enabling and disabling the constraint. Transferring control requires two constraints, one for each of the objects you want to control the location of the constrained object. Enabling and disabling only requires one. I'll describe it first.

The property you want to key frame is the constraint's influence value. To enable the constraint, set the value to 1 and keyframe it. To disable the constraint, set the value to 0 and keyframe it.

Here's an example of having zero influence on frames 1-9 and switching suddenly to full influence on frame 10:

obj.constraints["Copy Location"].influence = 0
obj.keyframe_insert('constraints["Copy Location"].influence', frame = 1)
obj.keyframe_insert('constraints["Copy Location"].influence', frame = 9)
obj.constraints["Copy Location"].influence = 0
obj.keyframe_insert('constraints["Copy Location"].influence', frame = 10)

Zero influence is keyframed twice to keep the influence constant throughout the frame range. If you want to let blender slowly switch influnce, remove the second keyframe_insert.

To transfer, use the same technique, but give the two objects opposite influence values.

$\endgroup$
4
  • $\begingroup$ You sure there isn't a way to keyframe the target of the constraint. Halfway through the animation it needs to change target objects. Any way to do that? $\endgroup$
    – Aidan
    Jul 5 at 17:34
  • 1
    $\begingroup$ Positive. The way to do that is to have two constraints. In my example, at frame 1, set the influence on the active target constraint to 1 and the target of the passive target constraint to 0 and keyframe both. At frame 9, duplicate both keyframes. At frame 10 set the old active target's influence to 0, the old passive target's constraint to 1 and keyframe that. This is a fairly common technique and is use for a lot of constraints, especially child-of. $\endgroup$ Jul 5 at 17:46
  • $\begingroup$ so I think i could make that work, I do have one more question. It sounds like I'll have to make six copy location constraints for this to work as I want it to go to one box then another depending on if it was selected as character 1, 2, 3, 4 or 5. Is there any way to simplify this or is this the best solution available? $\endgroup$
    – Aidan
    Jul 5 at 18:12
  • $\begingroup$ To be clear, 'character 1 - 5' are the target objects and 'it' is the object you want to apply the constraint to, or is it the other way around? In the first case, you do need 5 constraints, one for each target object. I don't know of any way to make it simpler. $\endgroup$ Jul 5 at 19:34
2
$\begingroup$

This script will check if any selected objects have a constraint of type Copy Location.
If the constraint is found, their target attribute is set to a stated scene object.

import bpy

TARGET = bpy.data.objects["Torus"]

for o in bpy.context.selected_objects:
    for c in o.constraints:
        if c.type == "COPY_LOCATION":
            c.target = TARGET

As for activating this script on keyframe, you'll need to setup a operator class to run the script when it's triggered by a certain keyframe condition. I'm not sure what keyframe condition you'd want, so for now I'll wait to edit my post until you've stated what kind of keyframe condition you're looking for to avoid over complicating things.

$\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.