How to loop duplicate one object and translate the copy origin on top of the origin of all selected objects (origin position in the belonging objects unchanged) one by one with a python script?

Edit 10-19-23 [mm-dd-yy] 15:13 CEST)):

How to loop duplicate one source object (source/active) and translate the copy on top of all other selected objects; with a python script?

Edit (10-19-23 16:16 CEST):

Your typical particle wood

This former objects (redwood trees) scattered via a particle system. Since been converted into mesh. Each tree has a belonging simple/low-poly collision mesh (typical need for game assets) I was hoping the collision mesh would be applied too, the way I setup the particle system. But unfortunately something went wrong in the process!

I start manually:

  • Cursor to Selected mesh [Shift]+[S]
  • Select collision-mesh (it's always the same) by simply clicking it in the bottom outliner panel (no [Ctrl] selection, so the current tree mesh remains active)
  • Duplicate [shift]+[D]
  • Selection to Cursor (Keep Offset) [Shift]+[S] => [7]
  • Select a new tree mesh by clicking it in the upper outliner panel
  • Repete

I already did this as ridiculously far as 348 objects/trees (See image bottom outliner panel to become a true believer). When I realised I'd newer reach the end of it without automation/Python script.

  • $\begingroup$ Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. $\endgroup$
    – Community Bot
    Commented Oct 19, 2023 at 6:30
  • $\begingroup$ Just the origin? You want geometry remaining at the same position? $\endgroup$ Commented Oct 19, 2023 at 6:46
  • $\begingroup$ "one by one with a Python script" So... All at once with a loop in a Python script or one by one? It's unclear, what you want. $\endgroup$ Commented Oct 19, 2023 at 6:50
  • 1
    $\begingroup$ Hello, Mijeka, welcome to BSE. Even though you might be seeking a general answer, I think the question is best posed with a specific example, including any code you have written so far, so we can copy, paste, adjust. $\endgroup$
    – Robin Betts
    Commented Oct 19, 2023 at 8:56
  • 1
    $\begingroup$ Yes, @RobinBetts. Back from town. I will clarify with images, descriptions and the solution python script for Blender, if chat-gpt is my friend! Might take me a while (I'm not too fast at it ;-). $\endgroup$
    – Mijeka
    Commented Oct 19, 2023 at 13:31

1 Answer 1


Select all the objects with the one to duplicate last so it is the active object and run this:

import bpy

C = bpy.context
active = C.object
selected = C.selected_objects
for o in selected:
    if o is C.object: #skip active itself
    obj_copy = active.copy()
    obj_copy.location = o.location

This keeps the data of the original object attached to all the copies. If you want to make a copy of data as well, you could add obj_copy.data = obj_copy.data.copy() in the loop.

Edit: OK, so I actually need to do this often myself, because I usually need to distribute light objects to a lot of modelled light fixtures in my scene(that I don't place manually one by one) and I usually just write this in Python Console every single time which is ridiculous. An add-on will be way more convenient. Here it is in an add-on (copy-paste to Blender's text editor, save with .py extension, install as add-on):

bl_info = {
    "name": "Place Active Copies on Selected",
    "author": "Martynas Žiemys",
    "version": (1, 0),
    "blender": (3, 6, 4),
    "location": "View3D > Object > Link\Transfer Data(Ctrl+L)",
    "description": "Place active copies on selected",
    "warning": "",
    "doc_url": "",
    "category": "Object",

import bpy
from bpy.types import Operator
from bpy.props import FloatVectorProperty
from bpy.props import StringProperty

class OBJECT_OT_copy_to_selected(Operator):
    """Place active object copies on selected"""
    bl_idname = "object.copies_to_selected"
    bl_label = "Place Active Copies on Selected"
    bl_options = {'REGISTER', 'UNDO'}

    offset: FloatVectorProperty(
        default=(0.0, 0.0, 0.0),
    name: StringProperty(
        description="Name of copies",

    def execute(self, context):
        active = C.object
        selected = C.selected_objects
        for o in selected:
            if o is active: #skip active itself
            obj_copy = active.copy()
            obj_copy.location = o.location + self.offset
            obj_copy.name = self.name
        return {'FINISHED'}
    def invoke(self, context, event):
        self.name = context.object.name
        return self.execute(context)

def copy_to_selected_button(self, context):
    self.layout.operator(OBJECT_OT_copy_to_selected.bl_idname, icon='PLUGIN')

def register():

def unregister():

if __name__ == "__main__":
  • $\begingroup$ Thank you for the answer. It works as expected. I like the naming convention for the duplikates better than the one from the chat-gpt suggestion ;-). I will upvote as soon as I can, in two days! $\endgroup$
    – Mijeka
    Commented Oct 19, 2023 at 14:44
  • $\begingroup$ GPT ignores that the active object is also selected and makes a duplicate on top anyway... $\endgroup$ Commented Oct 19, 2023 at 14:49
  • $\begingroup$ Thank you @DuarteFarrajotaRamos for clarifying the invality of using AI (chat-gpt in this case) in this type of forum (Stack Exchange in explicity). I hope it's ok I atempt entirely removing my answer! Also apologies for my ways of expression (English isn't my strongest)! $\endgroup$
    – Mijeka
    Commented Oct 20, 2023 at 1:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .