diff --git a/add_advanced_objects_menu/arrange_on_curve.py b/add_advanced_objects_menu/arrange_on_curve.py
index c292e341da92293accb13d16d49513aad7da6dc2..bfed37a75d3fa37f3cb9536a5a26e3ee0f92bee7 100644
--- a/add_advanced_objects_menu/arrange_on_curve.py
+++ b/add_advanced_objects_menu/arrange_on_curve.py
@@ -59,7 +59,7 @@ class PanelDupliCurve(Panel):
             elif adv_obj.arrange_c_select_type == 'G':
                 layout.column(align=True).prop_search(
                               adv_obj, "arrange_c_obj_arranjar",
-                              bpy.data, "groups"
+                              bpy.data, "collections"
                               )
         if context.object.type == 'CURVE':
             layout.operator("object.arranjar_numa_curva", text="Arrange Objects")
@@ -238,7 +238,7 @@ class DupliCurve(Operator):
         elif adv_obj.arrange_c_select_type == 'O':
             G_Objeto = bpy.data.objects[adv_obj.arrange_c_obj_arranjar],
         elif adv_obj.arrange_c_select_type == 'G':
-            G_Objeto = bpy.data.groups[adv_obj.arrange_c_obj_arranjar].objects
+            G_Objeto = bpy.data.collections[adv_obj.arrange_c_obj_arranjar].objects
 
         yawMatrix = mathutils.Matrix.Rotation(self.Yaw, 4, 'X')
         pitchMatrix = mathutils.Matrix.Rotation(self.Pitch, 4, 'Y')
diff --git a/add_advanced_objects_menu/pixelate_3d.py b/add_advanced_objects_menu/pixelate_3d.py
index 3a9fc88634f55336baaeac19098ad661ca470945..567e882ab5dfcb9e5b45d53d56605f50f2f916fe 100644
--- a/add_advanced_objects_menu/pixelate_3d.py
+++ b/add_advanced_objects_menu/pixelate_3d.py
@@ -28,7 +28,7 @@ def pix(self, obj):
     mes.transform(obj.matrix_world)
     dup = bpy.data.objects.new('dup', mes)
     sce.objects.link(dup)
-    dup.dupli_type = 'VERTS'
+    dup.instance_type = 'VERTS'
     sce.objects.active = dup
     bpy.ops.object.mode_set()
     ver = mes.vertices
diff --git a/add_advanced_objects_menu/random_box_structure.py b/add_advanced_objects_menu/random_box_structure.py
index fa4b6497f6c8f059e5ffd2c3ff87032d8a9d2d12..ead19bd1f2100bcaa07818f368412751c452a055 100644
--- a/add_advanced_objects_menu/random_box_structure.py
+++ b/add_advanced_objects_menu/random_box_structure.py
@@ -94,8 +94,8 @@ class makestructure(Operator):
         rsdchange = self.rsd
         oblst = []
         uvyes = 0
-        bpy.ops.group.create(name='Cubagrouper')
-        bpy.ops.group.objects_remove()
+        bpy.ops.collection.create(name='Cubagrouper')
+        bpy.ops.collection.objects_remove()
 
         for ob in bpy.context.selected_objects:
             oblst.append(ob)
@@ -107,7 +107,7 @@ class makestructure(Operator):
                 uvyes = 1
             else:
                 uvyes = 0
-            bpy.ops.object.group_link(group='Cubagrouper')
+            bpy.ops.object.collection_link(group='Cubagrouper')
             dim = obj.dimensions
             rot = obj.rotation_euler
             if self.uf is True:
@@ -155,7 +155,7 @@ class makestructure(Operator):
                     )
                 bpy.ops.object.mode_set(mode='OBJECT')
                 select = bpy.context.object  # This is used to keep something selected for poll()
-                bpy.ops.object.group_link(group='Cubagrouper')
+                bpy.ops.object.collection_link(group='Cubagrouper')
                 rsdchange += 3
             bpy.ops.object.select_grouped(type='GROUP')
             bpy.ops.transform.rotate(
@@ -180,7 +180,7 @@ class makestructure(Operator):
             if uvyes == 1:
                 bpy.ops.object.join_uvs()
 
-            bpy.ops.group.objects_remove()
+            bpy.ops.collection.objects_remove()
             bpy.context.scene.objects.active = select
 
             if self.dc is True:
diff --git a/add_advanced_objects_panels/drop_to_ground.py b/add_advanced_objects_panels/drop_to_ground.py
index e6facbcf7208636b0685e33005c7749d75c9ee70..8c66fb46ce4038b543e532663470faec0219bfc2 100644
--- a/add_advanced_objects_panels/drop_to_ground.py
+++ b/add_advanced_objects_panels/drop_to_ground.py
@@ -87,13 +87,13 @@ def get_lowest_world_co(context, ob, mat_parent=None):
     if ob.type == 'MESH':
         return get_lowest_world_co_from_mesh(ob)
 
-    elif ob.type == 'EMPTY' and ob.dupli_type == 'GROUP':
-        if not ob.dupli_group:
+    elif ob.type == 'EMPTY' and ob.instance_type == 'COLLECTION':
+        if not ob.instance_collection:
             return None
 
         else:
             lowest_co = None
-            for ob_l in ob.dupli_group.objects:
+            for ob_l in ob.instance_collection.objects:
                 if ob_l.type == 'MESH':
                     lowest_ob_l = get_lowest_world_co_from_mesh(ob_l, ob.matrix_world)
                     if not lowest_co:
diff --git a/add_curve_sapling/utils.py b/add_curve_sapling/utils.py
index 7f6a45b718660891377fc3a1f7319a6e2daf2f09..fb1fc7d39c0890ad1433edb45a26870681bac430 100644
--- a/add_curve_sapling/utils.py
+++ b/add_curve_sapling/utils.py
@@ -1797,17 +1797,17 @@ def addTree(props):
 
         # enable duplication
         if leafShape == 'dFace':
-            leafObj.dupli_type = "FACES"
-            leafObj.use_dupli_faces_scale = True
-            leafObj.dupli_faces_scale = 10.0
+            leafObj.instance_type = "FACES"
+            leafObj.use_instance_faces_scale = True
+            leafObj.instance_faces_scale = 10.0
             try:
                 if leafDupliObj not in "NONE":
                     bpy.data.objects[leafDupliObj].parent = leafObj
             except KeyError:
                 pass
         elif leafShape == 'dVert':
-            leafObj.dupli_type = "VERTS"
-            leafObj.use_dupli_vertices_rotation = True
+            leafObj.instance_type = "VERTS"
+            leafObj.use_instance_vertices_rotation = True
             try:
                 if leafDupliObj not in "NONE":
                     bpy.data.objects[leafDupliObj].parent = leafObj
diff --git a/add_mesh_extra_objects/add_empty_as_parent.py b/add_mesh_extra_objects/add_empty_as_parent.py
index 32d0d16796aad899f8577b9d86a3cba13904fafe..a6ae69e6cafef2e34a0f2d9020aa2ea14225464c 100644
--- a/add_mesh_extra_objects/add_empty_as_parent.py
+++ b/add_mesh_extra_objects/add_empty_as_parent.py
@@ -81,15 +81,15 @@ class P2E(Operator):
         context.object.show_in_front = True
 
         if self.grupo:
-            bpy.ops.group.create(name=self.nombre)
-            bpy.ops.group.objects_add_active()
+            bpy.ops.collection.create(name=self.nombre)
+            bpy.ops.collection.objects_add_active()
 
         for o in objs:
             o.select = True
             if not o.parent:
                 bpy.ops.object.parent_set(type='OBJECT')
             if self.grupo:
-                bpy.ops.group.objects_add_active()
+                bpy.ops.collection.objects_add_active()
             o.select = False
         for o in objs:
             if self.renom:
diff --git a/btrace/bTrace.py b/btrace/bTrace.py
index 82d93f9dc76966f977047c1fdf16ec37c0f33ae6..8df064754908aa1fd12b498eb7a2cf87dae13729 100644
--- a/btrace/bTrace.py
+++ b/btrace/bTrace.py
@@ -115,9 +115,9 @@ class OBJECT_OT_objectconnect(Operator):
             if curve_handle == 'AUTOMATIC':  # hackish because of naming conflict in api
                 curve_handle = 'AUTO'
             # Check if Btrace group exists, if not create
-            bgroup = bpy.data.groups.keys()
+            bgroup = bpy.data.collections.keys()
             if 'Btrace' not in bgroup:
-                bpy.ops.group.create(name="Btrace")
+                bpy.ops.collections.create(name="Btrace")
             #  check if noise
             if Btrace.connect_noise:
                 bpy.ops.object.btfcnoise()
@@ -181,7 +181,7 @@ class OBJECT_OT_objectconnect(Operator):
             if Btrace.animate:   # Add Curve Grow it?
                 bpy.ops.curve.btgrow()
 
-            bpy.ops.object.group_link(group="Btrace")  # add to Btrace group
+            bpy.ops.object.collection_link(group="Btrace")  # add to Btrace group
             if Btrace.animate:
                 bpy.ops.curve.btgrow()  # Add grow curve
 
@@ -245,9 +245,9 @@ class OBJECT_OT_particletrace(Operator):
                 curve_handle = 'FREE'
 
             # Check if Btrace group exists, if not create
-            bgroup = bpy.data.groups.keys()
+            bgroup = bpy.data.collections.keys()
             if 'Btrace' not in bgroup:
-                bpy.ops.group.create(name="Btrace")
+                bpy.ops.collection.create(name="Btrace")
 
             if Btrace.curve_join:
                 tracer = curvetracer('Tracer', 'Splines')
@@ -271,7 +271,7 @@ class OBJECT_OT_particletrace(Operator):
             for curveobject in curvelist:
                 curveobject.select = True
                 bpy.context.scene.objects.active = curveobject
-                bpy.ops.object.group_link(group="Btrace")
+                bpy.ops.object.collection_link(group="Btrace")
                 # Materials
                 trace_mats = addtracemat(curveobject.data)
                 if not trace_mats and check_materials is True:
@@ -721,9 +721,9 @@ class OBJECT_OT_meshfollow(Operator):
 
             # Run methods
             # Check if Btrace group exists, if not create
-            bgroup = bpy.data.groups.keys()
+            bgroup = bpy.data.collections.keys()
             if 'Btrace' not in bgroup:
-                bpy.ops.group.create(name="Btrace")
+                bpy.ops.collection.create(name="Btrace")
 
             Btrace = bpy.context.window_manager.curve_tracer
             sel = getsel_option()  # Get selection
@@ -743,7 +743,7 @@ class OBJECT_OT_meshfollow(Operator):
                 if curveobject.type == 'CURVE':
                     curveobject.select = True
                     context.scene.objects.active = curveobject
-                    bpy.ops.object.group_link(group="Btrace")
+                    bpy.ops.object.collection_link(group="Btrace")
                     # Materials
                     trace_mats = addtracemat(curveobject.data)
                     if not trace_mats and check_materials is True:
diff --git a/io_blend_utils/blend/blendfile_path_walker.py b/io_blend_utils/blend/blendfile_path_walker.py
index df07235eab2770299b1ab0d7e43fe98e86c9d658..ef49960427cb1170b019fe913e2cf9b2a4444cf5 100644
--- a/io_blend_utils/blend/blendfile_path_walker.py
+++ b/io_blend_utils/blend/blendfile_path_walker.py
@@ -726,7 +726,7 @@ class ExpandID:
             del dup_group
 
         yield block.get_pointer(b'proxy')
-        yield block.get_pointer(b'proxy_group')
+        yield block.get_pointer(b'proxy_collection')
 
         if USE_ALEMBIC_BRANCH:
             if has_dup_group:
diff --git a/io_blend_utils/blender_bam-unpacked.whl/bam/blend/blendfile_path_walker.py b/io_blend_utils/blender_bam-unpacked.whl/bam/blend/blendfile_path_walker.py
index df07235eab2770299b1ab0d7e43fe98e86c9d658..ef49960427cb1170b019fe913e2cf9b2a4444cf5 100644
--- a/io_blend_utils/blender_bam-unpacked.whl/bam/blend/blendfile_path_walker.py
+++ b/io_blend_utils/blender_bam-unpacked.whl/bam/blend/blendfile_path_walker.py
@@ -726,7 +726,7 @@ class ExpandID:
             del dup_group
 
         yield block.get_pointer(b'proxy')
-        yield block.get_pointer(b'proxy_group')
+        yield block.get_pointer(b'proxy_collection')
 
         if USE_ALEMBIC_BRANCH:
             if has_dup_group:
diff --git a/io_import_dxf/dxfimport/do.py b/io_import_dxf/dxfimport/do.py
index be79908c2fa3cac7adbaf17998e4a7a56fe9ebc2..8db6b854b42a1b2295d13e703ea915fbf54bad01 100644
--- a/io_import_dxf/dxfimport/do.py
+++ b/io_import_dxf/dxfimport/do.py
@@ -989,13 +989,13 @@ class Do:
             bbox = self._object_bbox(objects + inserts, block_scene, name, True)
 
             for i in inserts:
-                sub_group = i.dupli_group
+                sub_group = i.instance_collection
                 block_scene.objects.unlink(i)
                 block_group.objects.unlink(i)
                 i_empty = bpy.data.objects.new(i.name, None)
                 i_empty.matrix_basis = i.matrix_basis
-                i_empty.dupli_type = "GROUP"
-                i_empty.dupli_group = sub_group
+                i_empty.instance_type = "COLLECTION"
+                i_empty.instance_collection = sub_group
                 block_group.objects.link(i_empty)
                 block_scene.objects.link(i_empty)
 
@@ -1006,8 +1006,8 @@ class Do:
         bpy.context.screen.scene = scene
         o = bbox.copy()
         # o.empty_display_size = 0.3
-        o.dupli_type = "GROUP"
-        o.dupli_group = block_group
+        o.instance_type = "COLLECTION"
+        o.instance_collection = block_group
         group.objects.link(o)
         if invisible is not None:
             o.hide = invisible
@@ -1021,7 +1021,7 @@ class Do:
         """
         entity: DXF entity
         name: String; not used but required to be consistent with the methods being called from _call_type()
-        group: Blender group of type (bpy_types.group) being set if called from block()
+        group: Blender group of type (bpy_types.Collection) being set if called from block()
         invisible: boolean to control visibility; being set if called from block()
         """
         aunits = self.dwg.header.get('$AUNITS', 0)
@@ -1066,7 +1066,7 @@ class Do:
                                               entity.col_count, entity.row_count)
                 o = bpy.data.objects.new(entity.name, dm)
                 instance.parent = o
-                o.dupli_type = "VERTS"
+                o.instance_type = "VERTS"
 
         # insert transformations
         rot = radians(entity.rotation) if aunits == 0 else entity.rotation
@@ -1342,11 +1342,11 @@ class Do:
         name: name of group (String)
         Finds group by name or creates it if it does not exist.
         """
-        groups = bpy.data.groups
+        groups = bpy.data.collections
         if name in groups.keys():
             group = groups[name]
         else:
-            group = bpy.data.groups.new(name)
+            group = bpy.data.collections.new(name)
         return group
 
     def _call_object_types(self, TYPE, entities, group, name, scene, separated=False):
@@ -1466,9 +1466,9 @@ class Do:
         scene.objects.link(o)
 
         self._nest_block(o, blockname, blgroup, scene)
-        o.dupli_type = "FACES"
-        o.use_dupli_faces_scale = True
-        o.dupli_faces_scale = f
+        o.instance_type = "FACES"
+        o.use_instance_faces_scale = True
+        o.instance_faces_scale = f
 
     def _nest_block(self, parent, name, blgroup, scene):
         b = self.dwg.blocks[name]
diff --git a/io_mesh_pdb/import_pdb.py b/io_mesh_pdb/import_pdb.py
index 8256d10865e034ae4b6057dd320fa8940883cddf..bf2438992e6067f46ede866f345f62fce6374fce 100644
--- a/io_mesh_pdb/import_pdb.py
+++ b/io_mesh_pdb/import_pdb.py
@@ -685,7 +685,7 @@ def draw_atoms_one_type(draw_all_atoms_type,
         ball.name = "Ball_"+atom[0]
     ball.active_material = atom[1]
     ball.parent = new_atom_mesh
-    new_atom_mesh.dupli_type = 'VERTS'
+    new_atom_mesh.instance_type = 'VERTS'
     # The object is back translated to 'object_center_vec'.
     new_atom_mesh.location = object_center_vec
 
@@ -858,7 +858,7 @@ def draw_sticks_dupliverts(all_atoms,
         # Parenting the mesh to the cylinder.
         stick_cylinder.parent = new_mesh
         stick_cups.parent = new_mesh
-        new_mesh.dupli_type = 'FACES'
+        new_mesh.instance_type = 'FACES'
         new_mesh.location = center
         atom_object_list.append(new_mesh)
 
diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index 3c970dcd81ec89392d4e7e3acf573253f055ea49..94d94376f6ba63b70ead63629b17bb5632df82c6 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -2050,9 +2050,9 @@ def fbx_animations(scene_data):
                 'tag', 'track_axis', 'up_axis', 'active_material', 'active_material_index',
                 'matrix_parent_inverse', 'empty_display_type', 'empty_display_size', 'empty_image_offset', 'pass_index',
                 'color', 'hide_viewport', 'hide_select', 'hide_render', 'use_slow_parent', 'slow_parent_offset',
-                'dupli_type', 'use_dupli_frames_speed',
-                'use_dupli_vertices_rotation', 'use_dupli_faces_scale', 'dupli_faces_scale',
-                'dupli_frames_start', 'dupli_frames_end', 'dupli_frames_on', 'dupli_frames_off',
+                'instance_type', 'use_instance_frames_speed',
+                'use_instance_vertices_rotation', 'use_instance_faces_scale', 'instance_faces_scale',
+                'instance_frames_start', 'instance_frames_end', 'instance_frames_on', 'instance_frames_off',
                 'display_type', 'show_bounds', 'display_bounds_type', 'show_name', 'show_axis', 'show_texture_space',
                 'show_wire', 'show_all_edges', 'show_transparent', 'show_in_front',
                 'show_only_shape_key', 'use_shape_key_edit_mode', 'active_shape_key_index',
diff --git a/io_scene_fbx/fbx_utils.py b/io_scene_fbx/fbx_utils.py
index 7b3b9d0fffdcbdc75f2b159cfab38244dd6380f6..19f3280029ce1d1bcac5af25d03293abd79e79d3 100644
--- a/io_scene_fbx/fbx_utils.py
+++ b/io_scene_fbx/fbx_utils.py
@@ -1192,7 +1192,7 @@ class ObjectWrapper(metaclass=MetaObjectWrapper):
 
     # #### Duplis...
     def dupli_list_gen(self, depsgraph):
-        if self._tag == 'OB' and self.bdata.is_duplicator:
+        if self._tag == 'OB' and self.bdata.is_instancer:
             return (ObjectWrapper(dup) for dup in depsgraph.object_instances
                                        if dup.parent and ObjectWrapper(dup.parent.original) == self)
         return ()
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py
index e8da100d335e9c50a6c8e29732993c14917e0424..061410fe5ce04aa6a4c519d3724a67033e4dea3d 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py
@@ -57,7 +57,7 @@ def __filter_node(blender_object, export_settings):
         return False
     if not export_settings[gltf2_blender_export_keys.LAYERS] and not blender_object.layers[0]:
         return False
-    if blender_object.dupli_group is not None and not blender_object.dupli_group.layers[0]:
+    if blender_object.instance_collection is not None and not blender_object.instance_collection.layers[0]:
         return False
 
     return True
@@ -75,8 +75,8 @@ def __gather_children(blender_object, export_settings):
         if node is not None:
             children.append(node)
     # blender dupli objects
-    if blender_object.dupli_type == 'GROUP' and blender_object.dupli_group:
-        for dupli_object in blender_object.dupli_group.objects:
+    if blender_object.instance_type == 'COLLECTION' and blender_object.instance_collection:
+        for dupli_object in blender_object.instance_collection.objects:
             node = gather_node(dupli_object, export_settings)
             if node is not None:
                 children.append(node)
@@ -140,16 +140,16 @@ def __gather_mesh(blender_object, export_settings):
 
 
 def __gather_name(blender_object, export_settings):
-    if blender_object.dupli_type == 'GROUP' and blender_object.dupli_group:
+    if blender_object.instance_type == 'COLLECTION' and blender_object.instance_collection:
         return "Duplication_Offset_" + blender_object.name
     return blender_object.name
 
 
 def __gather_trans_rot_scale(blender_object, export_settings):
     trans, rot, sca = gltf2_blender_extract.decompose_transition(blender_object.matrix_local, 'NODE', export_settings)
-    if blender_object.dupli_type == 'GROUP' and blender_object.dupli_group:
+    if blender_object.instance_type == 'COLLECTION' and blender_object.instance_collection:
         trans = -gltf2_blender_extract.convert_swizzle_location(
-            blender_object.dupli_group.dupli_offset, export_settings)
+            blender_object.instance_collection.instance_offset, export_settings)
     translation, rotation, scale = (None, None, None)
     if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
         translation = [trans[0], trans[1], trans[2]]
diff --git a/io_scene_ms3d/ms3d_import.py b/io_scene_ms3d/ms3d_import.py
index 9a6fb42f8c02cee47fa82640de81e613912bd845..5a2397a54d059d8be531183a8c57d228f4e0e7e4 100644
--- a/io_scene_ms3d/ms3d_import.py
+++ b/io_scene_ms3d/ms3d_import.py
@@ -234,7 +234,7 @@ class Ms3dImporter():
 
         blender_scene = blender_context.scene
 
-        blender_group = blender_context.blend_data.groups.new(
+        blender_group = blender_context.blend_data.collections.new(
                 FORMAT_GROUP.format(ms3d_model.name))
         blender_empty_object = blender_context.blend_data.objects.new(
                 FORMAT_EMPTY_OBJECT.format(ms3d_model.name), None)
diff --git a/io_scene_obj/export_obj.py b/io_scene_obj/export_obj.py
index 0fe7fbccc9f95fe29dd13e660b4ce6d9e30422f6..0e905141bc0d2c717aa80025bf82e14a61ac0f49 100644
--- a/io_scene_obj/export_obj.py
+++ b/io_scene_obj/export_obj.py
@@ -324,13 +324,13 @@ def write_file(filepath, objects, depsgraph, scene,
             subprogress1.enter_substeps(len(objects))
             for i, ob_main in enumerate(objects):
                 # ignore dupli children
-                if ob_main.parent and ob_main.parent.dupli_type in {'VERTS', 'FACES'}:
+                if ob_main.parent and ob_main.parent.instance_type in {'VERTS', 'FACES'}:
                     # XXX
                     subprogress1.step("Ignoring %s, dupli child..." % ob_main.name)
                     continue
 
                 obs = [(ob_main, ob_main.matrix_world)]
-                if ob_main.dupli_type != 'NONE':
+                if ob_main.instance_type != 'NONE':
                     # XXX
                     print('creating dupli_list on', ob_main.name)
                     ob_main.dupli_list_create(scene)
@@ -644,7 +644,7 @@ def write_file(filepath, objects, depsgraph, scene,
                         # clean up
                         bpy.data.meshes.remove(me)
 
-                if ob_main.dupli_type != 'NONE':
+                if ob_main.instance_type != 'NONE':
                     ob_main.dupli_list_clear()
 
                 subprogress1.leave_substeps("Finished writing geometry of '%s'." % ob_main.name)
diff --git a/mesh_carver.py b/mesh_carver.py
index cf720fdbb9ea0a94988ba29261e5506261b9208e..7d453ad822590c48585b8aa8b54a06e5983ec89f 100644
--- a/mesh_carver.py
+++ b/mesh_carver.py
@@ -1707,7 +1707,7 @@ def Picking(context, event):
             if obj.type == 'MESH':
                 yield (obj, obj.matrix_world.copy())
 
-            if obj.dupli_type != 'NONE':
+            if obj.instance_type != 'NONE':
                 obj.dupli_list_create(scene)
                 for dob in obj.dupli_list:
                     obj_dupli = dob.object
diff --git a/modules/rna_manual_reference.py b/modules/rna_manual_reference.py
index 0f72ad87d43bc39d73ba80cb4e8046381e9ba640..1ba5501a0e1495df53c0929baf87025e4775c535 100644
--- a/modules/rna_manual_reference.py
+++ b/modules/rna_manual_reference.py
@@ -352,7 +352,7 @@ url_manual_mapping = (
 	("bpy.types.movietrackingtrack*", "editors/movie_clip_editor/tracking/clip/properties/introduction.html#bpy-types-movietrackingtrack"),
 	("bpy.types.nodeoutputfileslot*", "compositing/types/output/file.html#bpy-types-nodeoutputfileslot"),
 	("bpy.types.normaleditmodifier*", "modeling/modifiers/modify/normal_edit.html#bpy-types-normaleditmodifier"),
-	("bpy.types.object.dupli_group*", "editors/3dview/object/properties/duplication/dupligroup.html#bpy-types-object-dupli-group"),
+	("bpy.types.object.instance_collection*", "editors/3dview/object/properties/duplication/dupligroup.html#bpy-types-object-dupli-group"),
 	("bpy.types.scene.audio_volume*", "data_system/scenes/properties.html#bpy-types-scene-audio-volume"),
 	("bpy.types.shadernodebsdfhair*", "render/cycles/nodes/types/shaders/hair.html#bpy-types-shadernodebsdfhair"),
 	("bpy.types.shadernodebsdftoon*", "render/cycles/nodes/types/shaders/toon.html#bpy-types-shadernodebsdftoon"),
@@ -394,7 +394,7 @@ url_manual_mapping = (
 	("bpy.types.meshcachemodifier*", "modeling/modifiers/modify/mesh_cache.html#bpy-types-meshcachemodifier"),
 	("bpy.types.movieclipsequence*", "editors/vse/sequencer/strips/clip_mask.html#bpy-types-movieclipsequence"),
 	("bpy.types.object.dimensions*", "editors/3dview/object/properties/transforms.html#bpy-types-object-dimensions"),
-	("bpy.types.object.dupli_type*", "editors/3dview/object/properties/duplication/index.html#bpy-types-object-dupli-type"),
+	("bpy.types.object.instance_type*", "editors/3dview/object/properties/duplication/index.html#bpy-types-object-dupli-type"),
 	("bpy.types.object.track_axis*", "editors/3dview/object/properties/relations/extras.html#bpy-types-object-track-axis"),
 	("bpy.types.scene.active_clip*", "data_system/scenes/properties.html#bpy-types-scene-active-clip"),
 	("bpy.types.shadernodecombine*", "render/cycles/nodes/types/converter/combine_separate.html#bpy-types-shadernodecombine"),
@@ -727,7 +727,7 @@ url_manual_mapping = (
 	("bpy.types.addon*", "preferences/addons.html#bpy-types-addon"),
 	("bpy.types.brush*", "sculpt_paint/brush.html#bpy-types-brush"),
 	("bpy.types.curve*", "modeling/curves/index.html#bpy-types-curve"),
-	("bpy.types.group*", "editors/3dview/object/properties/relations/groups.html#bpy-types-group"),
+	("bpy.types.collection*", "editors/3dview/object/properties/relations/groups.html#bpy-types-group"),
 	("bpy.types.image*", "data_system/files/media/image_formats.html#bpy-types-image"),
 	("bpy.types.nodes*", "editors/node_editor/nodes/index.html#bpy-types-nodes"),
 	("bpy.types.panel*", "interface/window_system/tabs_panels.html#bpy-types-panel"),
@@ -765,7 +765,7 @@ url_manual_mapping = (
 	("bpy.ops.curve*", "modeling/curves/index.html#bpy-ops-curve"),
 	("bpy.ops.fluid*", "physics/fluid/index.html#bpy-ops-fluid"),
 	("bpy.ops.graph*", "editors/graph_editor/index.html#bpy-ops-graph"),
-	("bpy.ops.group*", "editors/3dview/object/properties/relations/groups.html#bpy-ops-group"),
+	("bpy.ops.collection*", "editors/3dview/object/properties/relations/groups.html#bpy-ops-group"),
 	("bpy.ops.image*", "data_system/files/media/image_formats.html#bpy-ops-image"),
 	("bpy.ops.mball*", "modeling/metas/index.html#bpy-ops-mball"),
 	("bpy.ops.paint*", "sculpt_paint/index.html#bpy-ops-paint"),
diff --git a/object_boolean_tools.py b/object_boolean_tools.py
index a97280690fddb27e326ef1f7a4560d5437a8e5fb..702fbb8e855b4e3b777a6012a15595becea7c52f 100644
--- a/object_boolean_tools.py
+++ b/object_boolean_tools.py
@@ -169,7 +169,7 @@ def Operation(context, _operation):
             cyclesVis.shadow = False
             cyclesVis.transmission = False
             if _operation == "SLICE":
-                # copies dupli_group property(empty), but group property is empty (users_group = None)
+                # copies instance_collection property(empty), but group property is empty (users_group = None)
                 clone = context.active_object.copy()
                 # clone.select = True
                 context.scene.objects.link(clone)
diff --git a/object_edit_linked.py b/object_edit_linked.py
index 85359a5105b020053e70fdf09de0f8580d72a5de..28a500965dd77e88ecb71ab9483e281373eae5f4 100644
--- a/object_edit_linked.py
+++ b/object_edit_linked.py
@@ -76,8 +76,8 @@ class EditLinked(bpy.types.Operator):
     @classmethod
     def poll(cls, context):
         return settings["original_file"] == "" and context.active_object is not None and (
-                (context.active_object.dupli_group and
-                 context.active_object.dupli_group.library is not None) or
+                (context.active_object.instance_collection and
+                 context.active_object.instance_collection.library is not None) or
                 (context.active_object.proxy and
                  context.active_object.proxy.library is not None) or
                  context.active_object.library is not None)
@@ -87,9 +87,9 @@ class EditLinked(bpy.types.Operator):
         #print(bpy.context.active_object.library)
         target = context.active_object
 
-        if target.dupli_group and target.dupli_group.library:
-            targetpath = target.dupli_group.library.filepath
-            settings["linked_objects"].extend({ob.name for ob in target.dupli_group.objects})
+        if target.instance_collection and target.instance_collection.library:
+            targetpath = target.instance_collection.library.filepath
+            settings["linked_objects"].extend({ob.name for ob in target.instance_collection.objects})
         elif target.library:
             targetpath = target.library.filepath
             settings["linked_objects"].append(target.name)
@@ -180,7 +180,7 @@ class PanelLinkedEdit(bpy.types.Panel):
         if context.active_object.proxy:
             target = context.active_object.proxy
         else:
-            target = context.active_object.dupli_group
+            target = context.active_object.instance_collection
 
         if settings["original_file"] == "" and (
                 (target and
@@ -219,7 +219,7 @@ class PanelLinkedEdit(bpy.types.Panel):
                 #  when launching a new Blender instance. Nested links don't
                 #  currently work when using a single instance of Blender.
                 props = layout.operator("object.edit_linked",
-                                        text="Edit Library: %s" % context.active_object.dupli_group.name,
+                                        text="Edit Library: %s" % context.active_object.instance_collection.name,
                                         icon="LINK_BLEND")
                 props.use_autosave = scene.use_autosave
                 props.use_instance = scene.use_instance
@@ -227,7 +227,7 @@ class PanelLinkedEdit(bpy.types.Panel):
                 layout.prop(scene, "use_instance")
 
                 layout.label(text="Path: %s" %
-                             context.active_object.dupli_group.library.filepath)
+                             context.active_object.instance_collection.library.filepath)
 
             else:
                 props = layout.operator("wm.return_to_original", icon="LOOP_BACK")
diff --git a/object_fracture/fracture_ops.py b/object_fracture/fracture_ops.py
index f5687e3af31fb8c1459a932c0458519b888dfcd5..d2f88159d9b0b23053fc9a1948d77c41e1ab7025 100644
--- a/object_fracture/fracture_ops.py
+++ b/object_fracture/fracture_ops.py
@@ -317,7 +317,7 @@ def fracture_group(context, group):
             and (len(ob.users_group) == 0 or ob.users_group[0].name != group)):
             tobesplit.append(ob)
 
-    cutters = bpy.data.groups[group].objects
+    cutters = bpy.data.collections[group].objects
 
     # @todo This can be optimized.
     # Avoid booleans on obs where bbox doesn't intersect.
@@ -407,7 +407,7 @@ class FractureGroup(bpy.types.Operator):
                            description="Specify the group used for fracturing")
 
 #    e = []
-#    for i, g in enumerate(bpy.data.groups):
+#    for i, g in enumerate(bpy.data.collections):
 #        e.append((g.name, g.name, ''))
 #    group = EnumProperty(name='Group (hit F8 to refresh list)',
 #                         items=e,
@@ -431,7 +431,7 @@ class FractureGroup(bpy.types.Operator):
     def draw(self, context):
         layout = self.layout
         layout.prop(self, "exe")
-        layout.prop_search(self, "group", bpy.data, "groups")
+        layout.prop_search(self, "group", bpy.data, "collections")
 
 #####################################################################
 # Import Functions
diff --git a/object_fracture_cell/__init__.py b/object_fracture_cell/__init__.py
index 891027f21c7cc031dfcfb3009032bb3b0e156c71..f845ccf12fd186b32f4cb823109b283e9e3f1116 100644
--- a/object_fracture_cell/__init__.py
+++ b/object_fracture_cell/__init__.py
@@ -163,9 +163,9 @@ def main_object(scene, obj, level, **kw):
 
     # group
     if group_name:
-        group = bpy.data.groups.get(group_name)
+        group = bpy.data.collections.get(group_name)
         if group is None:
-            group = bpy.data.groups.new(group_name)
+            group = bpy.data.collections.new(group_name)
         group_objects = group.objects[:]
         for obj_cell in objects:
             if obj_cell not in group_objects:
diff --git a/object_scatter/operator.py b/object_scatter/operator.py
index 69c2d6e4e798cb12580b1b30ec02b77614874fe1..1c0c133a9840b5e07981c8a2b8886bdbe762371d 100644
--- a/object_scatter/operator.py
+++ b/object_scatter/operator.py
@@ -204,11 +204,11 @@ def make_duplicator(target_collection, source_object, matrices):
     triangle_scale = 0.1
 
     duplicator = triangle_object_from_matrices(source_object.name + " Duplicator", matrices, triangle_scale)
-    duplicator.dupli_type = 'FACES'
-    duplicator.use_dupli_faces_scale = True
-    duplicator.show_duplicator_for_viewport = True
-    duplicator.show_duplicator_for_render = False
-    duplicator.dupli_faces_scale = 1 / triangle_scale
+    duplicator.instance_type = 'FACES'
+    duplicator.use_instance_faces_scale = True
+    duplicator.show_instancer_for_viewport = True
+    duplicator.show_instancer_for_render = False
+    duplicator.instance_faces_scale = 1 / triangle_scale
 
     copy_obj = source_object.copy()
     copy_obj.name = source_object.name + " - copy"
diff --git a/oscurart_tools/__init__.py b/oscurart_tools/__init__.py
index 420a4990c64390d01c90879060d285eda710dc98..4b7b5cf7eff0012e7e8d00a78ae01abee3c9c3fc 100644
--- a/oscurart_tools/__init__.py
+++ b/oscurart_tools/__init__.py
@@ -208,7 +208,7 @@ class OscPanelMesh(Panel):
         colrow.operator("lattice.mirror_selected", icon="LATTICE_DATA")
         colrow = col.row(align=1)
         colrow.label(text="Edit Multimesh")
-        colrow.prop_search(scene, "multimeshedit", bpy.data, "groups", text="")
+        colrow.prop_search(scene, "multimeshedit", bpy.data, "collections", text="")
         colrow = col.row(align=1)
         colrow.operator("mesh.create_edit_multimesh", icon="IMPORT", text= "StartEdit")
         colrow.operator("mesh.apply_edit_multimesh", icon="EXPORT", text="FinishEdit")
diff --git a/oscurart_tools/oscurart_files.py b/oscurart_tools/oscurart_files.py
index 65c248ebc46862e8fd819408d47a7b604de8c020..6c2f371ded539c0840090af5e59006c300782041 100644
--- a/oscurart_tools/oscurart_files.py
+++ b/oscurart_tools/oscurart_files.py
@@ -97,10 +97,10 @@ class reFreshMissingGroups(Operator):
     bl_options = {"REGISTER", "UNDO"}
 
     def execute(self, context):
-        for group in bpy.data.groups:
+        for group in bpy.data.collections:
             if group.library is not None:
                 with bpy.data.libraries.load(group.library.filepath, link=True) as (linked, local):
-                    local.groups = linked.groups
+                    local.collections = linked.collections
         return {'FINISHED'}
 
 
diff --git a/oscurart_tools/oscurart_meshes.py b/oscurart_tools/oscurart_meshes.py
index a601aa53faf09948baa6403f9525e8568ec5ddee..392575423aedda2ff2d80eaa41cfb4655429f5fd 100644
--- a/oscurart_tools/oscurart_meshes.py
+++ b/oscurart_tools/oscurart_meshes.py
@@ -659,7 +659,7 @@ class createEditMultimesh(Operator):
         global relvert
         global me
         global ob
-        temp = [[ob , [vert.co for vert in ob.data.vertices]]for ob in bpy.data.groups[bpy.context.scene.multimeshedit].objects]
+        temp = [[ob , [vert.co for vert in ob.data.vertices]]for ob in bpy.data.collections[bpy.context.scene.multimeshedit].objects]
         vi = 0
         pi = 0
         relvert = {}
diff --git a/oscurart_tools/oscurart_objects.py b/oscurart_tools/oscurart_objects.py
index dd3d46247d8a426a8b8af1daf3df048e71dbecb8..b3773b7a8cf8f1119f07fa1b79af67c38fc54e44 100644
--- a/oscurart_tools/oscurart_objects.py
+++ b/oscurart_tools/oscurart_objects.py
@@ -198,7 +198,7 @@ def CopyObjectGroupsAndLayers(self):
                     scene.object_bases[OBJECT.name].layers[:] = list(GLOBALLAYERS)
 
             # REMUEVO DE TODO GRUPO
-            for GROUP in bpy.data.groups[:]:
+            for GROUP in bpy.data.collections[:]:
                 if GROUP in OBJECT.users_group[:]:
                     GROUP.objects.unlink(OBJECT)
 
@@ -342,17 +342,17 @@ class SetLayersToOtherScenes (Operator):
 
 def DefRenderOnlyInCamera():
     # crea grupos
-    if "INCAMERA" not in bpy.data.groups:
-        bpy.data.groups.new("INCAMERA")
-    if "NOTINCAMERA" not in bpy.data.groups:
-        bpy.data.groups.new("NOTINCAMERA")
+    if "INCAMERA" not in bpy.data.collections:
+        bpy.data.collections.new("INCAMERA")
+    if "NOTINCAMERA" not in bpy.data.collections:
+        bpy.data.collections.new("NOTINCAMERA")
 
     # limpio grupos
     for ob in bpy.data.objects:
-        if ob.name in bpy.data.groups["INCAMERA"].objects:
-            bpy.data.groups["INCAMERA"].objects.unlink(ob)
-        if ob.name in bpy.data.groups["NOTINCAMERA"].objects:
-            bpy.data.groups["NOTINCAMERA"].objects.unlink(ob)
+        if ob.name in bpy.data.collections["INCAMERA"].objects:
+            bpy.data.collections["INCAMERA"].objects.unlink(ob)
+        if ob.name in bpy.data.collections["NOTINCAMERA"].objects:
+            bpy.data.collections["NOTINCAMERA"].objects.unlink(ob)
 
     # ordeno grupos
     for ob in bpy.data.objects:
@@ -370,9 +370,9 @@ def DefRenderOnlyInCamera():
         else:
             obs = True
         if obs:
-            bpy.data.groups["INCAMERA"].objects.link(ob)
+            bpy.data.collections["INCAMERA"].objects.link(ob)
         else:
-            bpy.data.groups["NOTINCAMERA"].objects.link(ob)
+            bpy.data.collections["NOTINCAMERA"].objects.link(ob)
 
 
 class RenderOnlyInCamera (Operator):
@@ -528,15 +528,15 @@ class oscDuplicateSymmetricalOp (Operator):
 def DefObjectToGroups():
     try:
         "%s_MSH" % (os.path.basename(bpy.data.filepath).replace(".blend", ""))
-        scgr = bpy.data.groups["%s_MSH" % (os.path.basename(bpy.data.filepath).replace(".blend", ""))]
+        scgr = bpy.data.collections["%s_MSH" % (os.path.basename(bpy.data.filepath).replace(".blend", ""))]
     except:
-        scgr = bpy.data.groups.new(
+        scgr = bpy.data.collections.new(
             "%s_MSH" %
             (os.path.basename(bpy.data.filepath).replace(".blend", "")))
     for ob in bpy.data.objects:
         if ob.select:
             if ob.type == "MESH":
-                gr = bpy.data.groups.new(ob.name)
+                gr = bpy.data.collections.new(ob.name)
                 gr.objects.link(ob)
                 scgr.objects.link(ob)
 
diff --git a/oscurart_tools/oscurart_overrides.py b/oscurart_tools/oscurart_overrides.py
index 5709c5b5c7ee6e29d13cd1ad60f74fe57488677c..9924fda5386ccd0d0aebedf83983779c4ea86f77 100644
--- a/oscurart_tools/oscurart_overrides.py
+++ b/oscurart_tools/oscurart_overrides.py
@@ -39,7 +39,7 @@ def DefOscApplyOverrides(self):
     scene = bpy.context.scene
     proptolist = list(eval(scene.oscurart.overrides))
     for group, material in proptolist:
-        for object in bpy.data.groups[group].objects:
+        for object in bpy.data.collections[group].objects:
             lenslots = len(object.material_slots)
             if object.type in types:
                 if len(object.data.materials):
@@ -133,7 +133,7 @@ class OscCheckOverrides(Operator):
                 MATLIST.append(MATERIAL.name)
 
             GROUPLIST = []
-            for GROUP in bpy.data.groups[:]:
+            for GROUP in bpy.data.collections[:]:
                 if GROUP.users > 0:
                     GROUPLIST.append(GROUP.name)
 
@@ -194,7 +194,7 @@ class OscOverridesGUI(Panel):
 
         for i, m in enumerate(bpy.context.scene.ovlist):
             colrow = col.row(align=1)
-            colrow.prop_search(m, "grooverride", bpy.data, "groups", text="")
+            colrow.prop_search(m, "grooverride", bpy.data, "collections", text="")
             colrow.prop_search(
                 m,
                 "matoverride",
diff --git a/oscurart_tools/oscurart_render.py b/oscurart_tools/oscurart_render.py
index f6e083e91392c25a34aa8880b8266bc0209cc902..67dacfb22092e83a3ca715efdea2ea85a3930360 100644
--- a/oscurart_tools/oscurart_render.py
+++ b/oscurart_tools/oscurart_render.py
@@ -55,7 +55,7 @@ def defRenderAll(frametype, scenes):
             scene.frame_start = FC
 
         for group, material in proptolist:
-            for object in bpy.data.groups[group].objects:
+            for object in bpy.data.collections[group].objects:
                 lenslots = len(object.material_slots)
                 if object.type in types:
                     if len(object.data.materials):
diff --git a/render_povray/render.py b/render_povray/render.py
index 227a588c737a777f6bcd12c7e5e74717f7924969..1e27beab57be7dd2d909c1c8f3c53db0519edfd4 100644
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -2266,10 +2266,10 @@ def write_pov(filename, scene=None, info_callback=None):
                 if ob.data:
                     name_orig = "OB" + ob.name
                     dataname_orig = "DATA" + ob.data.name
-                elif ob.is_duplicator:
-                    if ob.dupli_type == 'GROUP':
+                elif ob.is_instancer:
+                    if ob.instance_type == 'COLLECTION':
                         name_orig = "OB" + ob.name
-                        dataname_orig = "DATA" + ob.dupli_group.name
+                        dataname_orig = "DATA" + ob.instance_collection.name
                     else:
                         #hoping only dupligroups have several source datablocks
                         ob.dupli_list_create(scene)
@@ -2671,7 +2671,7 @@ def write_pov(filename, scene=None, info_callback=None):
 
 
 ############################################else try to export mesh
-                elif ob.is_duplicator == False: #except duplis which should be instances groups for now but all duplis later
+                elif ob.is_instancer == False: #except duplis which should be instances groups for now but all duplis later
                     if ob.type == 'EMPTY':
                         tabWrite("\n//dummy sphere to represent Empty location\n")
                         tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
@@ -3216,7 +3216,7 @@ def write_pov(filename, scene=None, info_callback=None):
             duplidata_ref = []
             for ob in sel:
                 #matrix = global_matrix * ob.matrix_world
-                if ob.is_duplicator:
+                if ob.is_instancer:
                     tabWrite("\n//--DupliObjects in %s--\n\n"% ob.name)
                     ob.dupli_list_create(scene)
                     dup = ""
@@ -3228,8 +3228,8 @@ def write_pov(filename, scene=None, info_callback=None):
                     for eachduplicate in ob.dupli_list:
                         duplidataname = "OB"+string_strip_hyphen(bpy.path.clean_name(bpy.data.objects[eachduplicate.object.name].data.name))
                         dup += ("\tobject {\n\t\tDATA%s\n\t\t%s\t}\n" %(string_strip_hyphen(bpy.path.clean_name(bpy.data.objects[eachduplicate.object.name].data.name)), MatrixAsPovString(ob.matrix_world.inverted() * eachduplicate.matrix)))
-                        #add object to a list so that it is not rendered for some dupli_types
-                        if ob.dupli_type not in {'GROUP'} and duplidataname not in duplidata_ref:
+                        #add object to a list so that it is not rendered for some instance_types
+                        if ob.instance_type not in {'COLLECTION'} and duplidataname not in duplidata_ref:
                             duplidata_ref.append(duplidataname) #older key [string_strip_hyphen(bpy.path.clean_name("OB"+ob.name))]
                     dup += "}\n"
                     ob.dupli_list_clear()
diff --git a/space_view3d_copy_attributes.py b/space_view3d_copy_attributes.py
index 9063bc89e33dcbd5d060713444dfb982aee1fd09..7037354c6943714d904baa5a7022d80edb74c051 100644
--- a/space_view3d_copy_attributes.py
+++ b/space_view3d_copy_attributes.py
@@ -434,7 +434,7 @@ def obMod(ob, active, context):
 
 
 def obGrp(ob, active, context):
-    for grp in bpy.data.groups:
+    for grp in bpy.data.collections:
         if active.name in grp.objects and ob.name not in grp.objects:
             grp.objects.link(ob)
     return('INFO', "Groups copied")
diff --git a/space_view3d_spacebar_menu.py b/space_view3d_spacebar_menu.py
index 463a92ebb83aa3f4acc46ec62f763888b473fe87..c6a8c93f1b83654380d88e6715d405ce85e01e6e 100644
--- a/space_view3d_spacebar_menu.py
+++ b/space_view3d_spacebar_menu.py
@@ -850,18 +850,18 @@ class VIEW3D_MT_AddMenu(Menu):
         layout.menu("VIEW3D_MT_object_quick_effects", text="Quick Effects", icon='PARTICLES')
         UseSeparator(self, context)
 
-        has_groups = (len(bpy.data.groups) > 0)
+        has_groups = (len(bpy.data.collections) > 0)
         col_group = layout.column()
         col_group.enabled = has_groups
 
-        if not has_groups or len(bpy.data.groups) > 10:
+        if not has_groups or len(bpy.data.collections) > 10:
             col_group.operator_context = 'INVOKE_REGION_WIN'
-            col_group.operator("object.group_instance_add",
-                                text="Group Instance..." if has_groups else "No Groups in Data",
+            col_group.operator("object.collection_instance_add",
+                                text="Collection Instance..." if has_groups else "No Groups in Data",
                                 icon='GROUP_VERTEX')
         else:
-            col_group.operator_menu_enum("object.group_instance_add", "group",
-                                text="Group Instance", icon='GROUP_VERTEX')
+            col_group.operator_menu_enum("object.collection_instance_add", "collection",
+                                text="Collection Instance", icon='GROUP_VERTEX')
 
 
 # ********** Object Manipulator **********
@@ -1178,12 +1178,12 @@ class VIEW3D_MT_GroupMenu(Menu):
 
     def draw(self, context):
         layout = self.layout
-        layout.operator("group.create")
-        layout.operator("group.objects_add_active")
+        layout.operator("collection.create")
+        layout.operator("collection.objects_add_active")
         UseSeparator(self, context)
-        layout.operator("group.objects_remove")
-        layout.operator("group.objects_remove_all")
-        layout.operator("group.objects_remove_active")
+        layout.operator("collection.objects_remove")
+        layout.operator("collection.objects_remove_all")
+        layout.operator("collection.objects_remove_active")
 
 
 # ********** Object Camera Options **********
diff --git a/uv_texture_atlas.py b/uv_texture_atlas.py
index debd44184447d42b16d71de8179ac9cbddc490bf..b3bc1ec61f48b915d4e68e15b2b3eb051aa1432e 100644
--- a/uv_texture_atlas.py
+++ b/uv_texture_atlas.py
@@ -51,7 +51,7 @@ def check_all_objects_visible(self, context):
     group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
     isAllObjectsVisible = True
     bpy.ops.object.select_all(action='DESELECT')
-    for thisObject in bpy.data.groups[group.name].objects:
+    for thisObject in bpy.data.collections[group.name].objects:
         isThisObjectVisible = False
         # scene.objects.active = thisObject
         for thisLayerNumb in range(20):
@@ -68,7 +68,7 @@ def check_group_exist(self, context, use_report=True):
     scene = context.scene
     group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
 
-    if group.name in bpy.data.groups:
+    if group.name in bpy.data.collections:
         return True
     else:
         if use_report:
@@ -162,7 +162,7 @@ class TexAtl_RunAuto(Operator):
         if bpy.ops.object.mode_set.poll():
             bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 
-        if group.bake is True and bpy.data.groups[group.name].objects:
+        if group.bake is True and bpy.data.collections[group.name].objects:
 
             # Check if objects are all on the visible Layers.
             isAllObjVisible = check_all_objects_visible(self, context)
@@ -209,7 +209,7 @@ class TexAtl_RunStart(Operator):
         if bpy.ops.object.mode_set.poll():
             bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 
-        if group.bake is True and bpy.data.groups[group.name].objects:
+        if group.bake is True and bpy.data.collections[group.name].objects:
 
             # Check if objects are all on the visible Layers.
             isAllObjVisible = check_all_objects_visible(self, context)
@@ -257,7 +257,7 @@ class TexAtl_RunFinish(Operator):
         if bpy.ops.object.mode_set.poll():
             bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 
-        if group.bake is True and bpy.data.groups[group.name].objects:
+        if group.bake is True and bpy.data.collections[group.name].objects:
 
             # Check if objects are all on the visible Layers.
             isAllObjVisible = check_all_objects_visible(self, context)
@@ -354,9 +354,9 @@ class TexAtl_AddSelectedToGroup(Operator):
             scene.ms_lightmap_groups_index].name
 
         # Create a New Group if it was deleted.
-        obj_group = bpy.data.groups.get(group_name)
+        obj_group = bpy.data.collections.get(group_name)
         if obj_group is None:
-            obj_group = bpy.data.groups.new(group_name)
+            obj_group = bpy.data.collections.new(group_name)
 
         # Add objects to  a group
         if bpy.ops.object.mode_set.poll():
@@ -387,7 +387,7 @@ class TexAtl_SelectGroup(Operator):
             bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 
         bpy.ops.object.select_all(action='DESELECT')
-        obj_group = bpy.data.groups[group_name]
+        obj_group = bpy.data.collections[group_name]
         for object in obj_group.objects:
             object.select = True
         return {'FINISHED'}
@@ -415,7 +415,7 @@ class TexAtl_RemoveFromGroup(Operator):
         for group in scene.ms_lightmap_groups:
             group_name = group.name
 
-            obj_group = bpy.data.groups[group_name]
+            obj_group = bpy.data.collections[group_name]
             for object in context.selected_objects:
                 scene.objects.active = object
 
@@ -451,7 +451,7 @@ class TexAtl_RemoveOtherUVs(Operator):
             bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
         # bpy.ops.object.select_all(action='DESELECT')
 
-        obj_group = bpy.data.groups[group_name]
+        obj_group = bpy.data.collections[group_name]
 
         # Remove other UVs of selected objects
         for object in context.selected_objects:
@@ -482,7 +482,7 @@ class TexAtl_AddLightmapGroup(Operator):
 
     def execute(self, context):
         scene = context.scene
-        obj_group = bpy.data.groups.new(self.name)
+        obj_group = bpy.data.collections.new(self.name)
 
         item = scene.ms_lightmap_groups.add()
         item.name = obj_group.name
@@ -513,7 +513,7 @@ class TexAtl_DelLightmapGroup(Operator):
             group_name = scene.ms_lightmap_groups[idx].name
 
             # Remove Group
-            group = bpy.data.groups.get(group_name)
+            group = bpy.data.collections.get(group_name)
             if group is not None:
 
                 # Unhide Objects if they are hidden
@@ -521,7 +521,7 @@ class TexAtl_DelLightmapGroup(Operator):
                     obj.hide_render = False
                     obj.hide = False
 
-                bpy.data.groups.remove(group, do_unlink=True)
+                bpy.data.collections.remove(group, do_unlink=True)
 
             # Remove Lightmap Group
             scene.ms_lightmap_groups.remove(scene.ms_lightmap_groups_index)
@@ -553,7 +553,7 @@ class TexAtl_CreateLightmap(Operator):
         image.generated_type = 'COLOR_GRID'
         image.generated_width = self.resolutionX
         image.generated_height = self.resolutionY
-        obj_group = bpy.data.groups[self.group_name]
+        obj_group = bpy.data.collections[self.group_name]
 
         # non MESH objects for removal list
         NON_MESH_LIST = []
@@ -623,7 +623,7 @@ class TexAtl_MergeObjects(Operator):
 
         # We do the MergeList because we will duplicate grouped objects
         mergeList = []
-        for object in bpy.data.groups[self.group_name].objects:
+        for object in bpy.data.collections[self.group_name].objects:
             mergeList.append(object)
 
         for object in mergeList:
@@ -746,7 +746,7 @@ class TexAtl_SeparateObjects(Operator):
             bpy.ops.object.select_all(action='DESELECT')
             ob_merged.hide = False
             ob_merged.select = True
-            groupSeparate = bpy.data.groups.new(ob_merged.name)
+            groupSeparate = bpy.data.collections.new(ob_merged.name)
             groupSeparate.objects.link(ob_merged)
             ob_merged.select = False