1
$\begingroup$

I was handed an older file today to work on, and it features duplicate objects in multiple places which are interfering with the appearance of the renders. I've been able to locate some of those duplicates by manually searching through the 1,000+ objects in the scene, but I'm realizing that this is both slow and inefficient, and so I'm hoping that there's a quicker way to do this. To further complicate the issue that I'm having at this moment, some of the objects with duplicates are set up as reference objects, and so when I think I've found a duplicate, it turns out to be a reference and not the duplicate.

The file is much too large to share, and so if this needs further explanation/clarification, please let me know.

EDIT 1: I'm realizing now that I should mention this: I'm not having success with finding duplicates by just clicking on an object that I think might have duplicates, hiding/deleting them, and so forth until the duplicates are gone. If it were that simple, I would not be asking.

EDIT 2: It occurred to me that seeing the outliner structure might be helpful, so an image is included below now that hopefully does a better job of illustrating at least a part of the issue--basically, if I try to hide or delete one of those copies, it eliminates all of them from the scene.

Image of a Blender Outliner window which indicates that there are multiple copies/instances of one object

$\endgroup$
5
  • 3
    $\begingroup$ By referenced object I assume you mean they share the same mesh data? If so use Select - Select Linked - Object Data to find all the objects that share the active objects mesh data $\endgroup$
    – Psyonic
    Mar 17 at 23:40
  • $\begingroup$ This suggestion appears to be helping with some of the items. For others, though, I might be able to find each copy in the outliner, but when I hide or delete one of the copies, it deletes all of them--how can I hide or delete just one copy at a time without getting rid of all of them? $\endgroup$
    – NickJ_001
    Mar 20 at 14:09
  • $\begingroup$ I'm not sure if this is an instance where I would need to re-link the objects in question or potentially use something like Resync or Resync Enforce. I've also tried ID Data -- Make Single User, but it gives me a warning along the lines of "not yet implemented" (I'm on v 3.4.1, if that matters). I believe that this file was created either in an earlier version of v3 or a later version of v2. $\endgroup$
    – NickJ_001
    Mar 20 at 14:18
  • 1
    $\begingroup$ you commented: "but when I hide or delete one of the copies, it deletes all of them". You are still describing the behavior of an object whose data is linked to several collections. You need to select each object that you suspect is a copy, and so as @Psyonic suggests. You could automate this with a python script (for each object, find and remove any links). $\endgroup$
    – james_t
    Mar 20 at 16:00
  • 1
    $\begingroup$ All these occurrences are the exact same object, that is linked in a single collection. This collection is linked in both Archipack.011 and Collection 6.006 $\endgroup$
    – Gorgious
    Mar 20 at 16:33

1 Answer 1

2
$\begingroup$

Here is my scripted solution. Some important deficiencies

  1. you don't get to choose which Collection the object remains linked
  2. It will remove all multi-collection links for all objects

the script, simplified from @Gorgious comments below:

import bpy

for o in bpy.data.objects:
    # skip non-mesh objects
    if o.type != 'MESH':
        continue
    firstCollectionFound = False
    for c in o.users_collection[:]:
        if firstCollectionFound: 
                print( 'unlinking obj', o, 'from collection', c )
                c.objects.unlink(o)
        else:
            print( 'obj', o, 'in collection', c )
            firstCollectionFound = True

You can try it out:

console output:

obj <bpy_struct, Object("Cube") at 0x000001B627058F08> in collection <bpy_struct, Collection("Collection") at 0x000001B616324E88>
unlinking obj <bpy_struct, Object("Cube") at 0x000001B627058F08> from collection <bpy_struct, Collection("Collection 2") at 0x000001B629E03B88>
obj <bpy_struct, Object("Sphere") at 0x000001B629BFF908> in collection <bpy_struct, Collection("Collection") at 0x000001B616324E88>
unlinking obj <bpy_struct, Object("Sphere") at 0x000001B629BFF908> from collection <bpy_struct, Collection("Collection 2") at 0x000001B629E03B88>
$\endgroup$
5
  • 1
    $\begingroup$ Note you can get all collections the object is linked to with obj.users_collection (if that was your intent) $\endgroup$
    – Gorgious
    Mar 20 at 16:36
  • $\begingroup$ @Gorgious -- excellent! I've simplified the script in my solution based on this. $\endgroup$
    – james_t
    Mar 20 at 17:10
  • $\begingroup$ hehe just be aware it's not a good idea to modify a list while iterating over it. I would use for c in o.users_collection[:]: instead to operate on a copy of the list $\endgroup$
    – Gorgious
    Mar 20 at 17:32
  • $\begingroup$ @Gorgious - james good with Java. James ignorant of python and therefore dangerous while learning. James talks in third person when asking for forgiveness. $\endgroup$
    – james_t
    Mar 20 at 21:59
  • $\begingroup$ haha no problem happy blending and happy scripting ;) $\endgroup$
    – Gorgious
    Mar 21 at 7:10

You must log in to answer this question.

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