def __init__(self, init_observations):
        """
        The real init is happened in self.init(), in which super().__init__() will be called
        """
        # for getting {agent_id: BaseObject}, use agent_manager.active_agents
        self._active_objects = {}  # {object.id: BaseObject}

        # fake init. before creating engine, it is necessary when all objects re-created in runtime
        self.observations = copy.copy(init_observations)  # its value is map<agent_id, obs> before init() is called
        self._init_observations = init_observations  # map <agent_id, observation>

        # init spaces before initializing env.engine
        observation_space = {
            agent_id: single_obs.observation_space
            for agent_id, single_obs in init_observations.items()
        }
        init_action_space = self._get_action_space()
        assert isinstance(init_action_space, dict)
        assert isinstance(observation_space, dict)
        self._init_observation_spaces = observation_space
        self._init_action_spaces = init_action_space
        self.observation_spaces = copy.copy(observation_space)
        self.action_spaces = copy.copy(init_action_space)
        self.episode_created_agents = None

        # this map will be override when the env.init() is first called and objects are made
        self._agent_to_object = {k: k for k in self.observations.keys()}  # no target objects created, fake init
        self._object_to_agent = {k: k for k in self.observations.keys()}  # no target objects created, fake init

        self._debug = None

        The real init is happened in self.init(), in which super().__init__() will be called
        
metadrive/manager/base_manager.py