Change parent only location via script

import bpy

ts = bpy.context.scene.tool_settings
ts.use_transform_skip_children = True
target_loc = bpy.data.objects["target"].location
bpy.context.selected_objects[0].location = target_loc


I'm trying to move only the parent to a new location taken from another object in Blender 2.93. The problem I'm having is that the children are moving along eventhough I'm enabling "Affect Only Parent" and I would like to keep the children in its original location.

GLOBAL vs LOCAL

Similarly to your new question, re rotation, the space is important

Does a child object inherit the matrix from the parent?

The values we see in UI are the objects matrix_basis and when parenting is involved can be somewhat arbitrary if taken on their own.

One way to look at this is an objects world matrix is like its GPS location, ie no matter where in the world it has one location. LOCAL however is somewhat arbitrary as we can set the matrix_parent_inverse such that any location is anywhere.

Hence perhaps the simplest way to do this is to copy the children's world matrix, move the parent, reset back. Often a goto case in blender is to work in global coordinates. Note, when changing matrices in script it can be the case they are not updated, in which case call a view layer update. (Was the old scene update pre 2.8)

Both examples below move the context object to scene camera's location, whilst leaving their children in place.

import bpy

context = bpy.context
scene = context.scene

cam = scene.camera # our target object for example sake

ob = bpy.context.object # Parent

before = [(o, o.matrix_world.copy()) for o in ob.children]
ob.matrix_world.translation = cam.matrix_world.translation
#context.view_layer.update()
for  o, mw in before:
o.matrix_world = mw


as described in link above, can also alter the local matrices of the children.

Example of moving context -> camera and setting childrens inverse parent matrix such that they remain stationary.

import bpy

context = bpy.context
scene = context.scene

cam = scene.camera # our target object for example sake

ob = bpy.context.object # Parent
mw = ob.matrix_world
global_loc = cam.matrix_world.translation
target_local_loc = mw.inverted() @ global_loc
ob.matrix_world.translation = global_loc

for c in ob.children:
c.matrix_parent_inverse.translation -= target_local_loc

• Thank you for the detailed explanation, really appreciated. Jul 13, 2021 at 11:46