class_docstr: A MultiAgentEnv representing a single Unity3D game instance.
  
  For an example on how to use this Env with a running Unity3D editor
  or with a compiled game, see:
  `rllib/examples/unity3d_env_local.py`
  For an example on how to use it inside a Unity game client, which
  connects to an RLlib Policy server, see:
  `rllib/examples/serving/unity3d_[client|server].py`
  
  Supports all Unity3D (MLAgents) examples, multi- or single-agent and
  gets converted automatically into an ExternalMultiAgentEnv, when used
  inside an RLlib PolicyClient for cloud/distributed training of Unity games.
class_docstr_tok: ["A","MultiAgentEnv","representing","a","single","Unity3D","game","instance",".","For","an","example","on","how","to","use","this","Env","with","a","running","Unity3D","editor","or","with","a","compiled","game",",","see",":","`","rllib\/examples\/unity3d_env_local.py","`","For","an","example","on","how","to","use","it","inside","a","Unity","game","client",",","which","connects","to","an","RLlib","Policy","server",",","see",":","`","rllib\/examples\/serving\/unity3d_","[","client|server","]",".py","`","Supports","all","Unity3D","(","MLAgents",")","examples",",","multi-","or","single-agent","and","gets","converted","automatically","into","an","ExternalMultiAgentEnv",",","when","used","inside","an","RLlib","PolicyClient","for","cloud\/distributed","training","of","Unity","games","."]
docstr: Collects those agents' obs/rewards that have to act in next `step`.
  
  Returns:
      Tuple:
          obs: Multi-agent observation dict.
              Only those observations for which to get new actions are
              returned.
          rewards: Rewards dict matching `obs`.
          dones: Done dict with only an __all__ multi-agent entry in it.
              __all__=True, if episode is done for all agents.
          infos: An (empty) info dict.
docstr_tok: ["Collects","those","agents","'","obs\/rewards","that","have","to","act","in","next","`","step","`",".","Returns",":","Tuple",":","obs",":","Multi-agent","observation","dict",".","Only","those","observations","for","which","to","get","new","actions","are","returned",".","rewards",":","Rewards","dict","matching","`","obs","`",".","dones",":","Done","dict","with","only","an","__all__","multi-agent","entry","in","it",".","__all__=True",",","if","episode","is","done","for","all","agents",".","infos",":","An","(","empty",")","info","dict","."]
code: def _get_step_results(self):
      """Collects those agents' obs/rewards that have to act in next `step`.
  
      Returns:
          Tuple:
              obs: Multi-agent observation dict.
                  Only those observations for which to get new actions are
                  returned.
              rewards: Rewards dict matching `obs`.
              dones: Done dict with only an __all__ multi-agent entry in it.
                  __all__=True, if episode is done for all agents.
              infos: An (empty) info dict.
      """
      obs = {}
      rewards = {}
      infos = {}
      for behavior_name in self.unity_env.behavior_specs:
          decision_steps, terminal_steps = self.unity_env.get_steps(
              behavior_name
          )
          # Important: Only update those sub-envs that are currently
          # available within _env_state.
          # Loop through all envs ("agents") and fill in, whatever
          # information we have.
          for agent_id, idx in decision_steps.agent_id_to_index.items():
              key = behavior_name + "_{}".format(agent_id)
              os = tuple(o[idx] for o in decision_steps.obs)
              os = os[0] if len(os) == 1 else os
              obs[key] = os
              rewards[key] = (
                  decision_steps.reward[idx]
                  + decision_steps.group_reward[idx]
              )
          for agent_id, idx in terminal_steps.agent_id_to_index.items():
              key = behavior_name + "_{}".format(agent_id)
              # Only overwrite rewards (last reward in episode), b/c obs
              # here is the last obs (which doesn't matter anyways).
              # Unless key does not exist in obs.
              if key not in obs:
                  os = tuple(o[idx] for o in terminal_steps.obs)
                  obs[key] = os = os[0] if len(os) == 1 else os
              rewards[key] = (
                  terminal_steps.reward[idx]
                  + terminal_steps.group_reward[idx]
              )
  
      # Only use dones if all agents are done, then we should do a reset.
      return obs, rewards, {"__all__": False}, {"__all__": False}, infos
  
file_path: ray/python/ray/rllib/env/wrappers/unity3d_env.py
imports: from gymnasium.spaces import Box, MultiDiscrete, Tuple
  import logging
  import numpy
  import random
  import time
  from typing import Callable, Optional, Tuple
  from ray.rllib.env.multi_agent_env import MultiAgentEnv
  from ray.rllib.policy.policy import PolicySpec
  from ray.rllib.utils.annotations import PublicAPI
  from ray.rllib.utils.typing import MultiAgentDict, PolicyID, AgentID
label_desc: Use image node_id 4 for calling the Unity3DEnv obj's underlying member method code with example usage: obj._get_step_results() and returns: obs,  rewards,  dict,  dict,  infos