diff --git a/rigify/generate.py b/rigify/generate.py
index e1fd29b8f51762ea2ff405331a1f10a549af70c8..475c57feb2a1828c1b1b3a95ef63140c29bd2f78 100644
--- a/rigify/generate.py
+++ b/rigify/generate.py
@@ -112,35 +112,47 @@ class Generator(base_generate.BaseGenerator):
         return obj
 
 
-    def __create_widget_group(self, new_group_name):
-        context = self.context
-        scene = self.scene
-        id_store = self.id_store
+    def __create_widget_group(self):
+        new_group_name = "WGTS_" + self.obj.name
+        wgts_group_name = "WGTS_" + (self.rig_old_name or self.obj.name)
 
-        # Create/find widge collection
-        self.widget_collection = ensure_widget_collection(context)
+        # Find the old widgets collection
+        old_collection = bpy.data.collections.get(wgts_group_name)
 
-        # Remove wgts if force update is set
-        wgts_group_name = "WGTS_" + (self.rig_old_name or self.obj.name)
-        if wgts_group_name in scene.objects and self.metarig.data.rigify_force_widget_update:
-            bpy.ops.object.mode_set(mode='OBJECT')
-            bpy.ops.object.select_all(action='DESELECT')
-            for wgt in bpy.data.objects[wgts_group_name].children:
-                wgt.select_set(True)
-            bpy.ops.object.delete(use_global=False)
+        if not old_collection:
+            # Update the old 'Widgets' collection
+            legacy_collection = bpy.data.collections.get('Widgets')
+
+            if legacy_collection and wgts_group_name in legacy_collection.objects:
+                legacy_collection.name = wgts_group_name
+                old_collection = legacy_collection
+
+        if old_collection:
+            # Remove widgets if force update is set
+            if self.metarig.data.rigify_force_widget_update:
+                for obj in list(old_collection.objects):
+                    bpy.data.objects.remove(obj)
+
+            # Rename widgets and collection if renaming
             if self.rig_old_name:
-                bpy.data.objects[wgts_group_name].name = new_group_name
+                old_prefix = WGT_PREFIX + self.rig_old_name + "_"
+                new_prefix = WGT_PREFIX + self.obj.name + "_"
 
-        # Create Group widget
-        wgts_group_name = new_group_name
-        if wgts_group_name not in scene.objects:
-            if wgts_group_name in bpy.data.objects:
-                bpy.data.objects[wgts_group_name].user_clear()
-                bpy.data.objects.remove(bpy.data.objects[wgts_group_name])
-            mesh = bpy.data.meshes.new(wgts_group_name)
-            wgts_obj = bpy.data.objects.new(wgts_group_name, mesh)
-            self.widget_collection.objects.link(wgts_obj)
+                for obj in list(old_collection.objects):
+                    if obj.name.startswith(old_prefix):
+                        new_name = new_prefix + obj.name[len(old_prefix):]
+                    elif obj.name == wgts_group_name:
+                        new_name = new_group_name
+                    else:
+                        continue
+
+                    obj.data.name = new_name
+                    obj.name = new_name
+
+                old_collection.name = new_group_name
 
+        # Create/find widget collection
+        self.widget_collection = ensure_widget_collection(self.context, new_group_name)
         self.wgts_group_name = new_group_name
 
 
@@ -351,7 +363,7 @@ class Generator(base_generate.BaseGenerator):
 
         #------------------------------------------
         # Create Group widget
-        self.__create_widget_group("WGTS_" + obj.name)
+        self.__create_widget_group()
 
         t.tick("Create main WGTS: ")
 
diff --git a/rigify/utils/collections.py b/rigify/utils/collections.py
index 5682ec64528ba857bf8c58c02fb85bb2febce7b7..a172b9849f4c9b83d26b9e3eea7f4acab45ba7f2 100644
--- a/rigify/utils/collections.py
+++ b/rigify/utils/collections.py
@@ -65,9 +65,7 @@ def filter_layer_collections_by_object(layer_collections, obj):
     return [lc for lc in layer_collections if obj in lc.collection.objects.values()]
 
 
-def ensure_widget_collection(context):
-    wgts_collection_name = "Widgets"
-
+def ensure_widget_collection(context, wgts_collection_name):
     view_layer = context.view_layer
     layer_collection = bpy.context.layer_collection
     collection = layer_collection.collection
@@ -89,6 +87,8 @@ def ensure_widget_collection(context):
         collection.children.link(widget_collection)
         widget_layer_collection = [c for c in layer_collection.children if c.collection == widget_collection][0]
 
+        widget_layer_collection.exclude = True
+
     # Make the widget the active collection for the upcoming added (widget) objects
     view_layer.active_layer_collection = widget_layer_collection
     return widget_collection
diff --git a/rigify/utils/widgets.py b/rigify/utils/widgets.py
index 04e176c6e3c56f2b262cae916341b7df4491aedc..f198afdaca03c3fb5a3dd45bbde1a46ba641052e 100644
--- a/rigify/utils/widgets.py
+++ b/rigify/utils/widgets.py
@@ -54,7 +54,7 @@ def obj_to_bone(obj, rig, bone_name, bone_transform_name=None):
     obj.matrix_basis = rig.matrix_world @ bone.bone.matrix_local @ Matrix.Scale(scale, 4)
 
 
-def create_widget(rig, bone_name, bone_transform_name=None):
+def create_widget(rig, bone_name, bone_transform_name=None, *, widget_name=None, widget_force_new=False):
     """ Creates an empty widget object for a bone, and returns the object.
     """
     assert rig.mode != 'EDIT'
@@ -64,37 +64,34 @@ def create_widget(rig, bone_name, bone_transform_name=None):
     if bone.custom_shape:
         return None
 
-    obj_name = WGT_PREFIX + rig.name + '_' + bone_name
+    obj_name = widget_name or WGT_PREFIX + rig.name + '_' + bone_name
     scene = bpy.context.scene
-    collection = ensure_widget_collection(bpy.context)
+    collection = ensure_widget_collection(bpy.context, 'WGTS_' + rig.name)
 
     # Check if it already exists in the scene
-    if obj_name in scene.objects:
-        # Move object to bone position, in case it changed
-        obj = scene.objects[obj_name]
-        obj_to_bone(obj, rig, bone_name, bone_transform_name)
+    if not widget_force_new:
+        if obj_name in scene.objects:
+            # Move object to bone position, in case it changed
+            obj = scene.objects[obj_name]
+            obj_to_bone(obj, rig, bone_name, bone_transform_name)
+
+            return None
 
-        return None
-    else:
         # Delete object if it exists in blend data but not scene data.
         # This is necessary so we can then create the object without
         # name conflicts.
         if obj_name in bpy.data.objects:
-            bpy.data.objects[obj_name].user_clear()
             bpy.data.objects.remove(bpy.data.objects[obj_name])
 
-        # Create mesh object
-        mesh = bpy.data.meshes.new(obj_name)
-        obj = bpy.data.objects.new(obj_name, mesh)
-        collection.objects.link(obj)
+    # Create mesh object
+    mesh = bpy.data.meshes.new(obj_name)
+    obj = bpy.data.objects.new(obj_name, mesh)
+    collection.objects.link(obj)
 
-        # Move object to bone position and set layers
-        obj_to_bone(obj, rig, bone_name, bone_transform_name)
-        wgts_group_name = 'WGTS_' + rig.name
-        if wgts_group_name in bpy.data.objects.keys():
-            obj.parent = bpy.data.objects[wgts_group_name]
+    # Move object to bone position and set layers
+    obj_to_bone(obj, rig, bone_name, bone_transform_name)
 
-        return obj
+    return obj
 
 
 def create_circle_polygon(number_verts, axis, radius=1.0, head_tail=0.0):