How do I copy children of an object using copy() method, without messing up their positions? I am making a scene procedurally with python, and recently switched to the copy() method instead of duplicate_move(). With duplicate_move, all the children of the object reproduced faithfully and their positions relative to the parent were correct. However, with copy(), the children did not get included, so I had to make a series of nested loops going to the depth I needed for my model (four layers) and manually copy, assign parent, and link to scene with each child. This worked, with the exception that the positions of many of the children were wrong, they appeared to be offset vertically by some amount, but their transform data in the inspector panel appears to be the same.

Before we get into what I may have done wrong in my nested loops, is there any way to automatically do a deep copy of the entire hierarchy of an object using the copy() method?

EDIT: Sorry, forgot to include code. Here is the core of what I am currently doing.

actor_copy = actor.copy()
actor_copy.name = str(ID)
scene.objects.link(actor_copy)
if len(actor.particle_systems)&gt;0:
    ps = actor.particle_systems[0].settings.copy()
    actor_copy.particle_systems[0].settings = ps
for child in actor.children:        
    child_copy = child.copy()
    child_copy.parent = actor_copy
    scene.objects.link(child_copy)        
    if len(child.particle_systems)&gt;0:
        ps = child.particle_systems[0].settings.copy()
        child_copy.particle_systems[0].settings = ps
    for subchild in child.children:
        subchild_copy = subchild.copy()
        subchild_copy.parent = child_copy
        scene.objects.link(subchild_copy)
        if len(subchild.particle_systems)&gt;0:
            ps = subchild.particle_systems[0].settings.copy()
            subchild_copy.particle_systems[0].settings = ps
        for sub2child in subchild.children:
            sub2child_copy = sub2child.copy()
            sub2child_copy.parent = subchild_copy
            scene.objects.link(sub2child_copy)
            if len(sub2child.particle_systems)&gt;0:
                ps = sub2child.particle_systems[0].settings.copy()
                sub2child_copy.particle_systems[0].settings = ps
            for sub3child in sub2child.children:
                sub3child_copy = sub3child.copy()
                sub3child_copy.parent = sub2child_copy
                scene.objects.link(sub3child_copy)
                if len(sub3child.particle_systems)&gt;0:
                    ps = sub3child.particle_systems[0].settings.copy()
                    sub3child_copy.particle_systems[0].settings = ps


Apologies for the hack job, time was short and I'm still hoping this can all be thrown away in favor of the right pre-existing function call. But no, I did not know about matrix_parent_inverse, that sounds very promising, thank you!
Set the matrix_parent_inverse of the copy.
Thought I'd add a supplementary answer, using recursion to get all the children up to a certain level. Without it the code is going to get long and unwieldy for more levels.
import bpy

def copy_ob(ob, parent,  collection=bpy.context.collection):
    # copy ob
    copy = ob.copy()
    copy.parent = parent
    copy.matrix_parent_inverse = ob.matrix_parent_inverse.copy()
    # copy particle settings
    for ps in copy.particle_systems:
        ps.settings = ps.settings.copy()
    collection.objects.link(copy)
    return copy
    
def tree_copy(ob, parent, levels=3):
    def recurse(ob, parent, depth):
        if depth &gt; levels: 
            return
        copy = copy_ob(ob, parent)
        
        for child in ob.children:
            recurse(child, copy, depth + 1)
    recurse(ob, ob.parent, 0)
    
#test
tree_copy(bpy.context.object, None)