def clear_objects(self, filter: Optional[Union[Callable, List]], force_destroy=False, record=True):
        """
        Destroy all self-generated objects or objects satisfying the filter condition
        Since we don't expect a iterator, and the number of objects is not so large, we don't use built-in filter()
        If force_destroy=True, we will destroy this element instead of storing them for next time using

        filter: A list of object ids or a function returning a list of object id
        """
        """
        In addition, we need to remove a color mapping whenever an object is destructed.
        
        """
        force_destroy_this_obj = True if force_destroy or self.global_config["force_destroy"] else False

        if isinstance(filter, (list, tuple)):
            exclude_objects = {obj_id: self._spawned_objects[obj_id] for obj_id in filter}
        elif callable(filter):
            exclude_objects = dict()
            for id, obj in self._spawned_objects.items():
                if filter(obj):
                    exclude_objects[id] = obj
        else:
            raise ValueError("filter should be a list or a function")
        for id, obj in exclude_objects.items():
            self._clean_color(id)
            self._spawned_objects.pop(id)
            if id in self._object_tasks:
                self._object_tasks.pop(id)
            if id in self._object_policies:
                policy = self._object_policies.pop(id)
                policy.destroy()
            if force_destroy_this_obj:
                #self._clean_color(obj.id)
                obj.destroy()
            else:
                obj.detach_from_world(self.physics_world)

                # We might want to remove some episode-relevant information when recycling some objects
                if hasattr(obj, "before_reset"):
                    obj.before_reset()

                if obj.class_name not in self._dying_objects:
                    self._dying_objects[obj.class_name] = []
                # We have a limit for buffering objects
                if len(self._dying_objects[obj.class_name]) < self.global_config["num_buffering_objects"]:
                    self._dying_objects[obj.class_name].append(obj)
                else:
                    #self._clean_color(obj.id)
                    obj.destroy()
            if self.global_config["record_episode"] and not self.replay_episode and record:
                self.record_manager.add_clear_info(obj)
        return exclude_objects.keys()

        Destroy all self-generated objects or objects satisfying the filter condition
        Since we don't expect a iterator, and the number of objects is not so large, we don't use built-in filter()
        If force_destroy=True, we will destroy this element instead of storing them for next time using

        filter: A list of object ids or a function returning a list of object id
        
metadrive/engine/base_engine.py