{"record":{"id":"883d5c160bbec83f","repo":"Unity-Technologies/ml-agents","slug":"the-gym-wrapper-does-not-provide-explicit-support","errorCode":null,"errorMessage":"The gym wrapper does not provide explicit support for both discrete and continuous actions.","messagePattern":"The gym wrapper does not provide explicit support for both discrete and continuous actions\\.","errorType":"exception","errorClass":"UnityGymException","httpStatus":null,"severity":"error","filePath":"ml-agents-envs/mlagents_envs/envs/unity_gym_env.py","lineNumber":129,"sourceCode":"            else:\n                if flatten_branched:\n                    self._flattener = ActionFlattener(branches)\n                    self._action_space = self._flattener.action_space\n                else:\n                    self._action_space = spaces.MultiDiscrete(branches)\n\n        elif self.group_spec.action_spec.is_continuous():\n            if flatten_branched:\n                logger.warning(\n                    \"The environment has a non-discrete action space. It will \"\n                    \"not be flattened.\"\n                )\n\n            self.action_size = self.group_spec.action_spec.continuous_size\n            high = np.array([1] * self.group_spec.action_spec.continuous_size)\n            self._action_space = spaces.Box(-high, high, dtype=np.float32)\n        else:\n            raise UnityGymException(\n                \"The gym wrapper does not provide explicit support for both discrete \"\n                \"and continuous actions.\"\n            )\n\n        if action_space_seed is not None:\n            self._action_space.seed(action_space_seed)\n\n        # Set observations space\n        list_spaces: List[gym.Space] = []\n        shapes = self._get_vis_obs_shape()\n        for shape in shapes:\n            if uint8_visual:\n                list_spaces.append(spaces.Box(0, 255, dtype=np.uint8, shape=shape))\n            else:\n                list_spaces.append(spaces.Box(0, 1, dtype=np.float32, shape=shape))\n        if self._get_vec_obs_size() > 0:\n            # vector observation is last\n            high = np.array([np.inf] * self._get_vec_obs_size())","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/Unity-Technologies/ml-agents/blob/3ecb446f75d1e7400eb404c562dc005d3164cffc/ml-agents-envs/mlagents_envs/envs/unity_gym_env.py#L111-L147","documentation":"UnityGymException thrown by UnityGymEnv.__init__ when the wrapped behavior's action_spec has both nonzero continuous_size and nonzero discrete branches. The gym wrapper only supports one action modality at a time, so it refuses hybrid (discrete+continuous) action spaces.","triggerScenarios":"Wrapping an environment whose Behavior Parameters in Unity enable both a continuous action vector and discrete action branches (Continuous Actions > 0 AND Discrete Actions branches defined).","commonSituations":"ML-Agents project configured with hybrid actions for research; recently edited Behavior Parameters adding discrete branches to a previously continuous controller; trying to wrap ML-Agents 1.0+ hybrid-action environments in gym.","solutions":["In Unity Behavior Parameters, set one modality to zero: either Continuous Actions = 0 or remove all discrete branches, then rebuild.","Set flatten_branches/use_discrete handling consistent with the spec — only discrete-only or continuous-only environments can be wrapped.","Use the raw UnityEnvironment API (behavior_specs action_spec gives continuous and discrete parts) for hybrid control.","Report/extend the wrapper if hybrid gym support is required; upstream gym wrapper doesn't support it."],"exampleFix":"// before\n# Unity Behavior Parameters: Continuous Actions = 3, Discrete branches = [2,2]\nenv = UnityGymEx(UnityEnvironment(file_name='hybrid_app'))\n// after\n# Unity Behavior Parameters: Continuous Actions = 0, Discrete branches = [2,2]\nenv = UnityGymEnv(UnityEnvironment(file_name='discrete_app'))","handlingStrategy":"validation","validationCode":"spec = unity_env.behavior_specs[behavior_name]\naspec = spec.action_spec\nif aspec.continuous_size > 0 and len(aspec.discrete_branches) > 0:\n    raise ValueError(\"Hybrid actions not supported by the gym wrapper\")","typeGuard":"def is_single_modality(action_spec) -> bool:\n    return (action_spec.continuous_size > 0) != (len(action_spec.discrete_branches) > 0)","tryCatchPattern":"try:\n    env = UnityGymEnv(unity_env)\nexcept UnityGymException:\n    logger.error(\"Hybrid action space; set exactly one of continuous/discrete in Behavior Parameters\")","preventionTips":["Keep Behavior Parameters single-modality when targeting gym","Check action_spec.continuous_size and discrete_branches before wrapping","Use raw UnityEnvironment for hybrid action research setups"],"tags":["gym","action-space","unity-environment"],"backgroundTag":"hybrid-action-space-unsupported","analyzedSha":"3ecb446f75d1e7400eb404c562dc005d3164cffc","analyzedAt":"2026-09-02T16:33:12.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}