Unity and Python Reinforcement and Imitation Learning with Gymnasium and PettingZoo API.
Project description
Gymize - Gym Reinforcement Learning with Unity 3D
Unity and Python Reinforcement and Imitation Learning with Gymnasium and PettingZoo API.
Installations
Installation for Python 3
pip install gymize
If you want to render videos, please install ffmpeg additionally.
You can also install ffmpeg with Anaconda:
conda install -c conda-forge ffmpeg
Installation for Unity
Go to Window -> Package Manager -> Add package from git URL...
Then paste the following git URL:
https://github.com/timcsy/gymize.git?path=/unity
If git hasn't been installed, then you can download gymize first and install it from disk, specify the path to /unity/package.json, or you can install from tarball, downloaded from Releases.
Usages
Usage for Python 3
- Assign the
env_name, which should be same as in the Unity. For example,kart. file_nameis the path to the built Unity game, or leaveNoneif using Unity Editor.- Define the observation space in the format of Gym Spaces.
- Define the action space in the format of Gym Spaces.
- Assign
render_mode='video'if you want to record video from Unity, otherwise omitrender_mode. - Assign
views=['', ...]if you want to record video from Unity, which given a list of view names, the empty string will be the default view, otherwise omitviews. - Make the Gymnasium or PettingZoo environment by the following commands:
Single-Agent with Gymnasium API:
import gymnasium as gym
import gymize
env = gym.make(
'gymize/Unity-v0',
env_name='<your env name>',
file_name=file_name,
observation_space=observation_space,
action_space=action_space,
render_mode='<render_mode>',
views=['', ...]
)
Multi-Agents with PettingZoo AEC API:
from gymize.envs import UnityAECEnv
env = UnityAECEnv(
env_name='<your env name>',
file_name=file_name,
observation_spaces=observation_spaces,
action_spaces=action_spaces,
render_mode='<render_mode>',
views=['', ...]
)
Multi-Agents with PettingZoo Parallel API:
from gymize.envs import UnityParallelEnv
env = UnityParallelEnv(
env_name='<your env name>',
file_name=file_name,
observation_spaces=observation_spaces,
action_spaces=action_spaces,
render_mode='<render_mode>',
views=['', ...]
)
Well done! Now you can use the environment as the gym environment!
The environment env will have some additional methods other than Gymnasium or PettingZoo:
env.unwrapped.send_info(info, agent=None)- At anytime, you can send information through
infoparameter in the form of Gymize Instance (see below) to Unity side. - The
agentparameter is the agent name that will receive info (byGymize.Agent.OnInfo()method in the Unity side), orNonefor the environment to receive info (byGymize.GymEnv.OnInfo += (info) => {}listener in the Unity side).
- At anytime, you can send information through
env.unwrapped.begin_render(screen_width=-1, screen_height=-1, fullscreen=False)- Begin to record video in the Unity.
screen_widthandscreen_heightis to set the width and height of the window, leave-1if you want the default window size.fullscreenis to set whether Unity is fullscreen.
env.unwrapped.end_render()- Stop to record video in the Unity.
env.unwrapped.render_all(video_paths={})- Render the videos which name and path are given by key value pairs in
video_path. - Using
Noneas path for binary video object.
- Render the videos which name and path are given by key value pairs in
env.unwrapped.render()orenv.render()- Only render the default video, and return a binary video object.
If you want to open the signaling service only, you can run gymize-signaling at the command line.
Usage for Unity
- Create Gym Manager Component
- Add a game object in the scene.
- Add a
Gym ManagerComponent to the game object. - Fill in the
Env Nameproperty with the name of the environment, which should be same as in the Python. For example,kart.
- Implement a class that inherit the
Agentclass:class MyAgent : Agent {}- Note that the
Agentclass is inheritted fromMonoBehaviourclass.- Override these listeners
public override void OnReset() {}public override void OnAction(object obj) {}public override void OnInfo(object obj) {}- Add
Terminate(),Truncate()at the proper place. - For example:
public class MyAgent : Agent { [Obs] private float pi = 3.14159f; private int m_Count; private float m_Speed; private string m_NickName; public override void OnReset() { // Reload the Unity scene when getting the reset signal from Python SceneManager.LoadScene(SceneManager.GetActiveScene().name, LoadSceneMode.Single); } public override void OnAction(object action) { Dictionary<string, object> actions = action as Dictionary<string, object>; List<object> arr = actions["arr"] as List<object>; Debug.Log((long)arr[0]); // arr[0] is Discrete value m_Count = Convert.ToInt32(arr[0]); // arr[0] is Discrete value m_Speed = Convert.ToSingle(actions["speed"]); // actions["speed"] is float value } public override void OnInfo(object info) { m_NickName = (string)info; } void Update() { // Terminate the game if collision occurred if (m_Collision) { // This method will tell the Python side to terminate the env Terminate(); } } }
- Add this Agent Component to the game object, and fill in the
Nameproperty with the name of the agent, usingagentfor single agent.
- Note that the
- Add Observers
- Refer below to learn more about the concept of "Locator".
- Using Attributes in the Agent class, assign the Locator or use the default Locator, for example:
[Obs] // Using the default Locator ".UsedTime", which is same as the field name. private float UsedTime; [Obs(".Progress")] private float m_Progress; [Box] private float Distance; [Box(".Height=$")] private float m_Height; - You can use
Obsto use the default Gym space type depending on the source variable, or you can useBox(for Tensor, including MultiBinrary and MultiDiscrete),Discrete,Text,Dict,List,Graphattributes, see more details in the Reflection folder, check out TestAgentInstance.cs for more examples. - Add Sensor Component in the scene.
- Inheritted from
SensorComponentclass.CameraSensoris an example of a sensor component. - Make sure that the
public override IInstance GetObservation() {}method is implemented in the Sensor Component. - Assign proper Locator in the Unity Editor.
- Inheritted from
- Add Gym Render Recorder Component to the scene if needed
- The
Nameproperty can be empty or the name of the view. - At the Python side, set
render_mode='video'if you want to render videos.
- The
- You can disable the
Gym Managercomponent in the Unity Editor to develop the game without Python connection and play the game manually, it is useful for debugging.
!!! Remember to close the channel in MonoBehaviour.OnApplicationQuit !!!
Gymize Instance
The instance generated from the action, observation space or info is called "Gymize Instance".
Gymize Instance is defined in the space.proto, which describes how the Gymize exchange data between Unity and Python, using Protocol Buffers 3. Most of which originates from the Gym Spaces.
In Unity, check out GymInstance.cs for more information about how to convert the object into a meaningful type. In Python, you can treat the instance as usual object.
Fundamental Instance
Tensor: numpy array, with dtype and shape- Corresponding to the Gym Spaces as
Box,MultiBinrary,MultiDiscrete
- Corresponding to the Gym Spaces as
Discrete: int64- Corresponding to the Gym Spaces as
Discrete
- Corresponding to the Gym Spaces as
Text: string- Corresponding to the Gym Spaces as
Text
- Corresponding to the Gym Spaces as
Composite Instance
Dict:key,valuepairs mapping. Type ofkeyis string,valueis Gymize Instance- Corresponding to the Gym Spaces as
Dict
- Corresponding to the Gym Spaces as
List: array of Gymize Instance- Corresponding to the Gym Spaces as
Tuple,Sequence
- Corresponding to the Gym Spaces as
Graph: including three tensor objects, which arenodes,edgesandedge_linksnodes: the numeric information of nodesedges: the numeric information of edgesedge_links: the list of edges represent by node pairs (the node index begins with 0)- Corresponding to the Gym Spaces as
Graph
Additional Instance (Not defined in Gym Spaces)
Raw: binary dataImage: image data, include format (PNG, JPG, ...), binary data, dtype, shape, axis permutationFloat: double precision floating numberBoolean: boolean value (true/false)JSON: JSON after stringifying
Locator
"Locator" maps the observations collected from the Unity side to the specified location of Python side observation data, which is transferred by Gymize Instance.
The followings are valid examples:
example 1:
.UsedTime = $
example 2:
.Progress
example 3:
@.Rays
example 4:
agent1@agent2@.key.0[12]["camera"]['front'][right][87](2)
example 5:
@@agent3@agent4@["camera"](1:10:2) = $(24:29) & @[11]=$[0] & @.key = $(3:8)
For more examples, check out TestLocator.cs and TestAgentInstance.cs.
Structure of Locator
- A
Locatoris a sequence ofMappings. - A
Mappingconsists ofAgent,Destination, andSource.Agenthas four kinds: "all agents", "list agents", "root agent", and "omitted".DestinationandSourceare in the form ofSelector.
- A
Selectorcan act on the following types:Dict,Tuple,Sequence,Tensor.- "key" selector is for
Dict. - "index" or "slices" selector is for
Tuple,Sequence,Tensor.
- "key" selector is for
- A
Sliceis Python-like or Numpy-like, which has "start", "stop", and "step".- Usually we write
start:stop:step, e.g.1:10:2. - There are some special cases: "index", "ellipsis", and "new axis".
- Usually we write
Syntax for Locator
- Syntax for
Locator- Using
&to connect differentMappings. - e.g.
.field1 & .field2=$ & @.field3=$["key"]
- Using
- Syntax of
Mapping- {
Agent}Selectors(Destination){=$Selectors(Source)}- { } means can be omitted.
- If you omit
Agent, then the Locator will become relative w.r.t Agent. - If you omit
=$Selectors(Source), it is same as=$. =means mapping or assignment. It will map the source (right hand side) to the destination (left hand side).$means the Unity side observation (variable or sensor data).
- {
- Syntax for
Agent- Using
agent@to assign the agent name. - Using
agent1@agent2@to assign the agent names. - Using
@@means for all agents. - Using
@@agent3@agent4@means for all agents, exceptagent3andagent4. - Using
@to represent the root agent itself. - You can omit the
Agentto use relative location.
- Using
- Syntax for
Selector- For
Dict:.key,['key'],["key"], or[key] - For
Tuple:[index]or[slice] - For
Sequence:[], means append - For
Tensor:(Slice)or(Slice1, Slice2, ..., SliceN)- The several
Tensorselectors have to put at the end of the selector sequence.
- The several
- For
- Syntax for
Slice- Same syntax as Python or numpy.
start:stop:step, e.g.1:10:2.- omitted "step", it becomes
1:10. - omitted "stop", it becomes
1:. - omitted "start", it becomes
:.
- omitted "step", it becomes
- You can just use an integer to represent the index (negative integer means counting from the end).
- You can use
...to represent ellipsis. - You can use
newaxisornp.newaxisto represent new axis.
See locator.bnf for more information about the syntax.
Known issues
- Gymize get the observation space type information by generating a sample instance, so it may not get the type information of
Sequenceif it samples a empty array. - On the Python side, it may cause some problems if you edit the observation data directly, because it is not a copy, it is a reference object.
- Dict source with different keys but with same destination Locator may not merged correctly, check out
space.pyfor more details. - If you run the built Unity Application and it fails after first OnReset, try:
- It may be this issue:
ArgumentNullException: Value cannot be null. Parameter name: shader. - Go to: Edit -> ProjectSettings -> Graphics
- Change the size of Always Included Shaders, and add the
Runtime/Space/Grayscale.shaderinto it.
- It may be this issue:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gymize-0.0.3.tar.gz.
File metadata
- Download URL: gymize-0.0.3.tar.gz
- Upload date:
- Size: 32.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0379f3c4b4d1eca8a56ec0ee6a1d423ecfa01574104435ff6ef3fe24491aabd
|
|
| MD5 |
31a8c1560aef6c84413a28419686b4af
|
|
| BLAKE2b-256 |
967cc4bc610529c2a5ccded48ff8be151258e14ef8009eb522ecc119ef4d4465
|
File details
Details for the file gymize-0.0.3-py3-none-any.whl.
File metadata
- Download URL: gymize-0.0.3-py3-none-any.whl
- Upload date:
- Size: 35.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa894c98b3f66688c2e8f99bba090db2cfcf3cc007313df777cc41dc7c51da2f
|
|
| MD5 |
7807e59829a054c303a11650634f0931
|
|
| BLAKE2b-256 |
3a044d8debf2e2e0fb077fc66d5fed71e71f48cefc3040db0e29a58177564290
|