浏览代码

Merge branch 'master' into soccer-fives

/soccer-fives
Andrew Cohen 5 年前
当前提交
de73baa9
共有 74 个文件被更改,包括 1404 次插入374 次删除
  1. 50
      .circleci/config.yml
  2. 8
      .github/PULL_REQUEST_TEMPLATE.md
  3. 4
      .pre-commit-config.yaml
  4. 1
      .yamato/com.unity.ml-agents-test.yml
  5. 9
      Project/Assets/ML-Agents/Examples/WallJump/Scripts/WallJumpAgent.cs
  6. 3
      com.unity.ml-agents/CHANGELOG.md
  7. 4
      com.unity.ml-agents/Editor/BrainParametersDrawer.cs
  8. 10
      com.unity.ml-agents/Editor/Unity.ML-Agents.Editor.asmdef
  9. 12
      com.unity.ml-agents/Runtime/Academy.cs
  10. 13
      com.unity.ml-agents/Runtime/ActionMasker.cs
  11. 29
      com.unity.ml-agents/Runtime/DecisionRequester.cs
  12. 20
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs
  13. 16
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs
  14. 4
      com.unity.ml-agents/Runtime/InferenceBrain/BarracudaModelParamLoader.cs
  15. 12
      com.unity.ml-agents/Runtime/InferenceBrain/TensorGenerator.cs
  16. 4
      com.unity.ml-agents/Runtime/InferenceBrain/Utils/RandomNormal.cs
  17. 12
      com.unity.ml-agents/Runtime/Policy/BarracudaPolicy.cs
  18. 21
      com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs
  19. 34
      com.unity.ml-agents/Runtime/Policy/BrainParameters.cs
  20. 54
      com.unity.ml-agents/Runtime/Sensor/CameraSensor.cs
  21. 37
      com.unity.ml-agents/Runtime/Sensor/CameraSensorComponent.cs
  22. 63
      com.unity.ml-agents/Runtime/Sensor/ISensor.cs
  23. 2
      com.unity.ml-agents/Runtime/Sensor/Observation.cs
  24. 44
      com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensor.cs
  25. 7
      com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponent2D.cs
  26. 37
      com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponent3D.cs
  27. 279
      com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponentBase.cs
  28. 21
      com.unity.ml-agents/Runtime/Sensor/RenderTextureSensor.cs
  29. 22
      com.unity.ml-agents/Runtime/Sensor/RenderTextureSensorComponent.cs
  30. 19
      com.unity.ml-agents/Runtime/Sensor/SensorBase.cs
  31. 17
      com.unity.ml-agents/Runtime/Sensor/SensorComponent.cs
  32. 4
      com.unity.ml-agents/Runtime/Sensor/StackingSensor.cs
  33. 23
      com.unity.ml-agents/Runtime/Sensor/VectorSensor.cs
  34. 8
      com.unity.ml-agents/Runtime/Sensor/WriteAdapter.cs
  35. 8
      com.unity.ml-agents/Runtime/SideChannel/EngineConfigurationChannel.cs
  36. 16
      com.unity.ml-agents/Runtime/SideChannel/FloatPropertiesChannel.cs
  37. 5
      com.unity.ml-agents/Runtime/SideChannel/RawBytesChannel.cs
  38. 7
      com.unity.ml-agents/Runtime/SideChannel/SideChannel.cs
  39. 18
      com.unity.ml-agents/Runtime/Timer.cs
  40. 5
      com.unity.ml-agents/Runtime/Unity.ML-Agents.asmdef
  41. 9
      com.unity.ml-agents/Runtime/UnityAgentsException.cs
  42. 82
      com.unity.ml-agents/Runtime/Utilities.cs
  43. 4
      com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs
  44. 5
      com.unity.ml-agents/Tests/Editor/Unity.ML-Agents.Editor.Tests.asmdef
  45. 15
      gym-unity/gym_unity/envs/__init__.py
  46. 9
      ml-agents/mlagents/trainers/common/nn_policy.py
  47. 4
      ml-agents/mlagents/trainers/components/reward_signals/curiosity/signal.py
  48. 4
      ml-agents/mlagents/trainers/components/reward_signals/gail/signal.py
  49. 6
      ml-agents/mlagents/trainers/ppo/optimizer.py
  50. 8
      ml-agents/mlagents/trainers/sac/network.py
  51. 7
      ml-agents/mlagents/trainers/sac/optimizer.py
  52. 4
      ml-agents/mlagents/trainers/tests/test_meta_curriculum.py
  53. 9
      ml-agents/mlagents/trainers/tests/test_simple_rl.py
  54. 1
      ml-agents/mlagents/trainers/tf_policy.py
  55. 34
      notebooks/getting-started-gym.ipynb
  56. 27
      notebooks/getting-started.ipynb
  57. 8
      com.unity.ml-agents/Runtime/Communicator/ICommunicator.cs
  58. 40
      .yamato/protobuf-generation-test.yml
  59. 94
      com.unity.ml-agents/Editor/RayPerceptionSensorComponentBaseEditor.cs
  60. 11
      com.unity.ml-agents/Editor/RayPerceptionSensorComponentBaseEditor.cs.meta
  61. 8
      com.unity.ml-agents/Runtime/Communicator.meta
  62. 5
      com.unity.ml-agents/Runtime/Grpc/AssemblyInfo.cs
  63. 11
      com.unity.ml-agents/Runtime/Grpc/AssemblyInfo.cs.meta
  64. 16
      com.unity.ml-agents/Runtime/Grpc/Unity.ML-Agents.CommunicatorObjects.asmdef
  65. 7
      com.unity.ml-agents/Runtime/Grpc/Unity.ML-Agents.CommunicatorObjects.asmdef.meta
  66. 381
      com.unity.ml-agents/Third Party Notices.md
  67. 7
      com.unity.ml-agents/Third Party Notices.md.meta
  68. 0
      /com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs.meta
  69. 0
      /com.unity.ml-agents/Runtime/Communicator/RpcCommunicator.cs.meta
  70. 0
      /com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs
  71. 0
      /com.unity.ml-agents/Runtime/Communicator/RpcCommunicator.cs
  72. 0
      /com.unity.ml-agents/Runtime/Communicator/ICommunicator.cs.meta
  73. 0
      /com.unity.ml-agents/Runtime/Communicator/ICommunicator.cs

50
.circleci/config.yml


. venv/bin/activate
pre-commit run --hook-stage manual << parameters.precommit_command >> --all-files
protobuf_generation_check:
docker:
- image: circleci/python:3.7.3
working_directory: ~/repo/
steps:
- checkout
- run:
name: Combine proto files for caching
command: cat protobuf-definitions/proto/mlagents_envs/communicator_objects/*.proto > /tmp/proto_deps.txt
- restore_cache:
keys:
- v1-protobuf-gen-dependencies-{{ checksum "/tmp/proto_deps.txt" }}
- v1-protobuf-gen-dependencies-
- run:
name: Install Dependencies
command: |
sudo apt-get install nuget
nuget install Grpc.Tools -Version 1.14.1 -OutputDirectory protobuf-definitions/
python3 -m venv venv
. venv/bin/activate
pip install --upgrade pip
pip install grpcio-tools==1.13.0 --progress-bar=off
pip install mypy-protobuf==1.16.0 --progress-bar=off
- save_cache:
paths:
- ./venv
key: v1-protobuf-gen-dependencies-{{ checksum "/tmp/proto_deps.txt" }}
- run:
name: Generate protobufs
command: |
. venv/bin/activate
cd protobuf-definitions
chmod +x Grpc.Tools.1.14.1/tools/linux_x64/protoc
chmod +x Grpc.Tools.1.14.1/tools/linux_x64/grpc_csharp_plugin
COMPILER=Grpc.Tools.1.14.1/tools/linux_x64 ./make.sh
CS_PROTO_PATH=com.unity.ml-agents/Runtime/Grpc/CommunicatorObjects
git diff --exit-code --quiet -- :/ ":(exclude,top)$CS_PROTO_PATH/*.meta" \
|| { GIT_ERR=$?; echo "protobufs need to be regenerated, apply the patch uploaded to artifacts."; \
echo "Apply the patch with the command: git apply proto.patch"; \
git diff -- :/ ":(exclude,top)$CS_PROTO_PATH/*.meta" > /tmp/proto.patch; \
exit $GIT_ERR; }
- store_artifacts:
path: /tmp/proto.patch
destination: proto.patch
deploy:
parameters:
directory:

# Test python 3.7 with the newest supported versions
pip_constraints: test_constraints_max_tf2_version.txt
- markdown_link_check
- protobuf_generation_check
- pre-commit
- deploy:
name: deploy ml-agents-envs

8
.github/PULL_REQUEST_TEMPLATE.md


- [ ] Other (please describe)
### Checklist
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] I have added updated the changelog (if applicable)
- [ ] I have added necessary documentation (if applicable)
- [ ] I have updated the migration guide (if applicable)
- [ ] Added tests that prove my fix is effective or that my feature works
- [ ] Updated the [changelog](https://github.com/Unity-Technologies/ml-agents/blob/master/com.unity.ml-agents/CHANGELOG.md) (if applicable)
- [ ] Updated the [documentation](https://github.com/Unity-Technologies/ml-agents/tree/master/docs) (if applicable)
- [ ] Updated the [migration guide](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Migrating.md) (if applicable)
### Other comments

4
.pre-commit-config.yaml


# markdown-link-check doesn't support multiple files on the commandline, so this hacks around that.
# Note that you must install the package separately via npm. For example:
# brew install npm; npm install -g markdown-link-check
entry: bash -xc 'echo "$@" | xargs -n1 -t markdown-link-check -c markdown-link-check.fast.json' --
entry: bash -c 'for i in "$@"; do markdown-link-check -c markdown-link-check.fast.json "$i"; done' --
language: system
types: [markdown]
# Don't check localized files since their target might not be localized.

- id: markdown-link-check-full
name: markdown-link-check-full
entry: bash -xc 'echo "$@" | xargs -n1 -t markdown-link-check -c markdown-link-check.full.json' --
entry: bash -c 'for i in "$@"; do markdown-link-check -c markdown-link-check.full.json "$i"; done' --
language: system
types: [markdown]
exclude: ".*localized.*"

1
.yamato/com.unity.ml-agents-test.yml


test_editors:
- version: 2018.4
- version: 2019.3
- version: 2020.1
test_platforms:
- name: win
type: Unity::VM

9
Project/Assets/ML-Agents/Examples/WallJump/Scripts/WallJumpAgent.cs


}
/// <summary>
/// Chenges the color of the ground for a moment
/// Changes the color of the ground for a moment.
/// <returns>The Enumerator to be used in a Coroutine</returns>
/// <param name="mat">The material to be swaped.</param>
/// <returns>The Enumerator to be used in a Coroutine.</returns>
/// <param name="mat">The material to be swapped.</param>
/// <param name="time">The time the material will remain.</param>
IEnumerator GoalScoredSwapGroundMaterial(Material mat, float time)
{

/// <param name="config">Config.
/// If 0 : No wall and noWallBrain.
/// If 1: Small wall and smallWallBrain.
/// Other : Tall wall and BigWallBrain. </param>
/// Other : Tall wall and BigWallBrain.
/// </param>
void ConfigureAgent(int config)
{
var localScale = wall.transform.localScale;

3
com.unity.ml-agents/CHANGELOG.md


- `DemonstrationRecorder` now has an optional path for the demonstrations. This will default to `Application.dataPath` if not set.
- `DemonstrationStore` was changed to accept a `Stream` for its constructor, and was renamed to `DemonstrationWriter`
- The method `GetStepCount()` on the Agent class has been replaced with the property getter `StepCount`
- `RayPerceptionSensorComponent` and related classes now display the debug gizmos whenever the Agent is selected (not just Play mode).
- Most fields on `RayPerceptionSensorComponent` can now be changed while the editor is in Play mode. The exceptions to this are fields that affect the number of observations.
- Unused static methods from the `Utilities` class (ShiftLeft, ReplaceRange, AddRangeNoAlloc, and GetSensorFloatObservationSize) were removed.
### Bugfixes
- Fixed an issue which caused self-play training sessions to consume a lot of memory. (#3451)

4
com.unity.ml-agents/Editor/BrainParametersDrawer.cs


}
/// <summary>
/// The Height required to draw the Vector Action parameters
/// The Height required to draw the Vector Action parameters.
/// <returns>The height of the drawer of the Vector Action </returns>
/// <returns>The height of the drawer of the Vector Action.</returns>
static float GetHeightDrawVectorAction(SerializedProperty property)
{
var actionSize = 2 + property.FindPropertyRelative(k_ActionSizePropName).arraySize;

10
com.unity.ml-agents/Editor/Unity.ML-Agents.Editor.asmdef


"name": "Unity.ML-Agents.Editor",
"references": [
"Unity.ML-Agents",
"Barracuda"
"Barracuda",
"Unity.ML-Agents.CommunicatorObjects"
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],

"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
"defineConstraints": []
}

12
com.unity.ml-agents/Runtime/Academy.cs


/// Creates or retrieves an existing ModelRunner that uses the same
/// NNModel and the InferenceDevice as provided.
/// </summary>
/// <param name="model"> The NNModel the ModelRunner must use </param>
/// <param name="brainParameters"> The brainParameters used to create
/// the ModelRunner </param>
/// <param name="inferenceDevice"> The inference device (CPU or GPU)
/// the ModelRunner will use </param>
/// <returns> The ModelRunner compatible with the input settings</returns>
/// <param name="model">The NNModel the ModelRunner must use.</param>
/// <param name="brainParameters">The brainParameters used to create the ModelRunner.</param>
/// <param name="inferenceDevice">
/// The inference device (CPU or GPU) the ModelRunner will use.
/// </param>
/// <returns> The ModelRunner compatible with the input settings.</returns>
internal ModelRunner GetOrCreateModelRunner(
NNModel model, BrainParameters brainParameters, InferenceDevice inferenceDevice)
{

13
com.unity.ml-agents/Runtime/ActionMasker.cs


namespace MLAgents
{
/// <summary>
/// Agents that take discrete actions can explicitly indicate that specific actions
/// are not allowed at a point in time. This enables the agent to indicate that some actions
/// may be illegal (e.g. the King in Chess taking a move to the left if it is already in the
/// left side of the board). This class represents the set of masked actions and provides
/// the utilities for setting and retrieving them.
/// </summary>
public class ActionMasker
{
/// When using discrete control, is the starting indices of the actions

/// The actionIndices correspond to the actions the agent will be unable to perform
/// on the branch 0.
/// </summary>
/// <param name="actionIndices">The indices of the masked actions on branch 0</param>
/// <param name="actionIndices">The indices of the masked actions on branch 0.</param>
public void SetActionMask(IEnumerable<int> actionIndices)
{
SetActionMask(0, actionIndices);

/// action branch. The actionIndex correspond to the action the agent will be unable
/// to perform.
/// </summary>
/// <param name="branch">The branch for which the actions will be masked</param>
/// <param name="actionIndex">The index of the masked action</param>
/// <param name="branch">The branch for which the actions will be masked.</param>
/// <param name="actionIndex">The index of the masked action.</param>
public void SetActionMask(int branch, int actionIndex)
{
SetActionMask(branch, new[] { actionIndex });

29
com.unity.ml-agents/Runtime/DecisionRequester.cs


using System;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace MLAgents

[AddComponentMenu("ML Agents/Decision Requester", (int)MenuGroup.Default)]
public class DecisionRequester : MonoBehaviour
{
/// <summary>
/// The frequency with which the agent requests a decision. A DecisionPeriod of 5 means
/// that the Agent will request a decision every 5 Academy steps.
/// </summary>
[Tooltip("The agent will automatically request a decision every X Academy steps.")]
[Tooltip("The frequency with which the agent requests a decision. A DecisionPeriod " +
"of 5 means that the Agent will request a decision every 5 Academy steps.")]
[Tooltip("Whether or not AgentAction will be called on Academy steps that decisions aren't requested. Has no effect if DecisionPeriod is 1.")]
/// <summary>
/// Indicates whether or not the agent will take an action during the Academy steps where
/// it does not request a decision. Has no effect when DecisionPeriod is set to 1.
/// </summary>
[Tooltip("Indicates whether or not the agent will take an action during the Academy " +
"steps where it does not request a decision. Has no effect when DecisionPeriod " +
"is set to 1.")]
[Tooltip("Whether or not Agent decisions should start at a random offset.")]
/// <summary>
/// Whether or not the Agent decisions should start at an offset (different for each agent).
/// This does not affect <see cref="DecisionPeriod"/>. Turning this on will distribute
/// the decision-making computations for all the agents across multiple Academy steps.
/// This can be valuable in scenarios where you have many agents in the scene, particularly
/// during the inference phase.
/// </summary>
[Tooltip("Whether or not Agent decisions should start at an offset.")]
public void Awake()
internal void Awake()
{
m_Offset = offsetStep ? gameObject.GetInstanceID() : 0;
m_Agent = gameObject.GetComponent<Agent>();

20
com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs


[AddComponentMenu("ML Agents/Demonstration Recorder", (int)MenuGroup.Default)]
public class DemonstrationRecorder : MonoBehaviour
{
/// <summary>
/// Whether or not to record demonstrations.
/// </summary>
[Tooltip("Base demonstration file name. Will have numbers appended to make unique.")]
/// <summary>
/// Base demonstration file name. If multiple files are saved, the additional filenames
/// will have a sequence of unique numbers appended.
/// </summary>
[Tooltip("Base demonstration file name. If multiple files are saved, the additional " +
"filenames will have a unique number appended.")]
[Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")]
/// <summary>
/// Directory to save the demo files. Will default to a "Demonstrations/" folder in the
/// Application data path if not specified.
/// </summary>
[Tooltip("Directory to save the demo files. Will default to " +
"{Application.dataPath}/Demonstrations if not specified.")]
public string demonstrationDirectory;
DemonstrationWriter m_DemoWriter;

const string k_DefaultDirectoryName = "Demonstrations";
IFileSystem m_FileSystem;
Agent m_Agent;

}
if (string.IsNullOrEmpty(demonstrationDirectory))
{
demonstrationDirectory = Path.Combine(Application.dataPath, "Demonstrations");
demonstrationDirectory = Path.Combine(Application.dataPath, k_DefaultDirectoryName);
}
demonstrationName = SanitizeName(demonstrationName, MaxNameLength);

16
com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs


namespace MLAgents
{
/// <summary>
/// Responsible for writing demonstration data to stream (usually a file stream).
/// Responsible for writing demonstration data to stream (typically a file stream).
public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file.
/// <summary>
/// Number of bytes reserved for the Demonstration metadata at the start of the demo file.
/// </summary>
internal const int MetaDataBytes = 32;
DemonstrationMetaData m_MetaData;
Stream m_Writer;

/// <summary>
/// Writes the initial data to the stream.
/// </summary>
/// <param name="demonstrationName">Base name of the demonstration file(s).</param>
/// <param name="brainName">The name of the Brain the agent is attached to.</param>
/// <param name="brainParameters">The parameters of the Brain the agent is attached to.</param>
public void Initialize(
string demonstrationName, BrainParameters brainParameters, string brainName)
{

/// <summary>
/// Writes brain parameters to file.
/// </summary>
/// <param name="brainName">The name of the Brain the agent is attached to.</param>
/// <param name="brainParameters">The parameters of the Brain the agent is attached to.</param>
void WriteBrainParameters(string brainName, BrainParameters brainParameters)
{
if (m_Writer == null)

/// <summary>
/// Write AgentInfo experience to file.
/// </summary>
/// <param name="info"> <see cref="AgentInfo"/> for the agent being recorded.</param>
/// <param name="sensors">List of sensors to record for the agent.</param>
internal void Record(AgentInfo info, List<ISensor> sensors)
{
if (m_Writer == null)

/// <summary>
/// Performs all clean-up necessary
/// Performs all clean-up necessary.
/// </summary>
public void Close()
{

4
com.unity.ml-agents/Runtime/InferenceBrain/BarracudaModelParamLoader.cs


/// Generates the Tensor inputs that are expected to be present in the Model.
/// </summary>
/// <param name="model">
/// The Barracuda engine model for loading static parameters
/// The Barracuda engine model for loading static parameters.
/// <returns>TensorProxy IEnumerable with the expected Tensor inputs</returns>
/// <returns>TensorProxy IEnumerable with the expected Tensor inputs.</returns>
public static IReadOnlyList<TensorProxy> GetInputTensors(Model model)
{
var tensors = new List<TensorProxy>();

12
com.unity.ml-agents/Runtime/InferenceBrain/TensorGenerator.cs


/// Modifies the data inside a Tensor according to the information contained in the
/// AgentInfos contained in the current batch.
/// </summary>
/// <param name="tensorProxy"> The tensor the data and shape will be modified</param>
/// <param name="batchSize"> The number of agents present in the current batch</param>
/// <param name="infos"> List of AgentInfos containing the
/// information that will be used to populate the tensor's data</param>
/// <param name="tensorProxy"> The tensor the data and shape will be modified.</param>
/// <param name="batchSize"> The number of agents present in the current batch.</param>
/// <param name="infos">
/// List of AgentInfos containing the information that will be used to populate
/// the tensor's data.
/// </param>
void Generate(
TensorProxy tensorProxy, int batchSize, IEnumerable<AgentInfoSensorsPair> infos);
}

/// Returns a new TensorGenerators object.
/// </summary>
/// <param name="seed"> The seed the Generators will be initialized with.</param>
/// <param name="allocator"> Tensor allocator</param>
/// <param name="allocator"> Tensor allocator.</param>
/// <param name="memories">Dictionary of AgentInfo.id to memory for use in the inference model.</param>
/// <param name="barracudaModel"></param>
public TensorGenerator(

4
com.unity.ml-agents/Runtime/InferenceBrain/Utils/RandomNormal.cs


double m_SpareUnscaled;
/// <summary>
/// Return the next random double number
/// Return the next random double number.
/// <returns>Next random double number</returns>
/// <returns>Next random double number.</returns>
public double NextDouble()
{
if (m_HasSpare)

12
com.unity.ml-agents/Runtime/Policy/BarracudaPolicy.cs


namespace MLAgents
{
/// <summary>
/// Where to perform inference.
/// </summary>
/// <summary>
/// CPU inference
/// </summary>
/// <summary>
/// GPU inference
/// </summary>
/// every step. It uses a ModelRunner that is shared accross all
/// every step. It uses a ModelRunner that is shared across all
/// Barracuda Policies that use the same model and inference devices.
/// </summary>
internal class BarracudaPolicy : IPolicy

21
com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs


/// <summary>
/// The Factory to generate policies.
/// </summary>
///
[AddComponentMenu("ML Agents/Behavior Parameters", (int)MenuGroup.Default)]
public class BehaviorParameters : MonoBehaviour
{

[HideInInspector]
[SerializeField]
string m_BehaviorName = "My Behavior";
/// <summary>
/// The team ID for this behavior.
/// </summary>
[HideInInspector]
[SerializeField]
public int m_TeamID;

[Tooltip("Use all Sensor components attached to child GameObjects of this Agent.")]
bool m_UseChildSensors = true;
/// <summary>
/// The associated <see cref="BrainParameters"/> for this behavior.
/// </summary>
/// <summary>
/// Whether or not to use all the sensor components attached to child GameObjects of the agent.
/// </summary>
/// <summary>
/// The name of this behavior, which is used as a base name. See
/// <see cref="fullyQualifiedBehaviorName"/> for the full name.
/// </summary>
public string behaviorName
{
get { return m_BehaviorName; }

}
}
/// <summary>
/// Updates the model and related details for this behavior.
/// </summary>
/// <param name="newBehaviorName">New name for the behavior.</param>
/// <param name="model">New neural network model for this behavior.</param>
/// <param name="inferenceDevice">New inference device for this behavior.</param>
public void GiveModel(
string newBehaviorName,
NNModel model,

34
com.unity.ml-agents/Runtime/Policy/BrainParameters.cs


namespace MLAgents
{
/// <summary>
/// Whether the action space is discrete or continuous.
/// </summary>
/// <summary>
/// Discrete action space: a fixed number of options are available.
/// </summary>
/// <summary>
/// Continuous action space: each action can take on a float value.
/// </summary>
Continuous
}

public class BrainParameters
{
/// <summary>
/// If continuous : The length of the float vector that represents
/// the state
/// If discrete : The number of possible values the state can take
/// If continuous : The length of the float vector that represents the state.
/// If discrete : The number of possible values the state can take.
/// <summary>
/// Stacking refers to concatenating the observations across multiple frames. This field
/// indicates the number of frames to concatenate across.
/// </summary>
/// If continuous : The length of the float vector that represents
/// the action
/// If discrete : The number of possible values the action can take*/
/// If continuous : The length of the float vector that represents the action.
/// If discrete : The number of possible values the action can take.
/// <summary></summary>The list of strings describing what the actions correpond to */
/// <summary>
/// The list of strings describing what the actions correspond to.
/// </summary>
/// <summary>Defines if the action is discrete or continuous</summary>
/// <summary>
/// Defines if the action is discrete or continuous.
/// </summary>
/// Deep clones the BrainParameter object
/// Deep clones the BrainParameter object.
/// </summary>
/// <returns> A new BrainParameter object with the same values as the original.</returns>
public BrainParameters Clone()

54
com.unity.ml-agents/Runtime/Sensor/CameraSensor.cs


using System;
/// <summary>
/// A sensor that wraps a Camera object to generate visual observations for an agent.
/// </summary>
public class CameraSensor : ISensor
{
Camera m_Camera;

int[] m_Shape;
SensorCompressionType m_CompressionType;
public CameraSensor(Camera camera, int width, int height, bool grayscale, string name,
SensorCompressionType compression)
/// <summary>
/// Creates and returns the camera sensor.
/// </summary>
/// <param name="camera">Camera object to capture images from.</param>
/// <param name="width">The width of the generated visual observation.</param>
/// <param name="height">The height of the generated visual observation.</param>
/// <param name="grayscale">Whether to convert the generated image to grayscale or keep color.</param>
/// <param name="name">The name of the camera sensor.</param>
/// <param name="compression">The compression to apply to the generated image.</param>
public CameraSensor(
Camera camera, int width, int height, bool grayscale, string name, SensorCompressionType compression)
{
m_Camera = camera;
m_Width = width;

m_Shape = new[] { height, width, grayscale ? 1 : 3 };
m_Shape = GenerateShape(width, height, grayscale);
/// <summary>
/// Accessor for the name of the sensor.
/// </summary>
/// <returns>Sensor name.</returns>
/// <summary>
/// Accessor for the size of the sensor data. Will be h x w x 1 for grayscale and
/// h x w x 3 for color.
/// </summary>
/// <returns>Size of each of the three dimensions.</returns>
/// <summary>
/// Generates a compressed image. This can be valuable in speeding-up training.
/// </summary>
/// <returns>Compressed image.</returns>
public byte[] GetCompressedObservation()
{
using (TimerStack.Instance.Scoped("CameraSensor.GetCompressedObservation"))

}
}
/// <summary>
/// Writes out the generated, uncompressed image to the provided <see cref="WriteAdapter"/>.
/// </summary>
/// <param name="adapter">Where the observation is written to.</param>
/// <returns></returns>
public int Write(WriteAdapter adapter)
{
using (TimerStack.Instance.Scoped("CameraSensor.WriteToTensor"))

}
}
/// <inheritdoc/>
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
{
return m_CompressionType;

/// Converts a m_Camera and corresponding resolution to a 2D texture.
/// Renders a Camera instance to a 2D texture at the corresponding resolution.
/// </summary>
/// <returns>The 2D texture.</returns>
/// <param name="obsCamera">Camera.</param>

RenderTexture.active = prevActiveRt;
RenderTexture.ReleaseTemporary(tempRt);
return texture2D;
}
/// <summary>
/// Computes the observation shape for a camera sensor based on the height, width
/// and grayscale flag.
/// </summary>
/// <param name="width">Width of the image captures from the camera.</param>
/// <param name="height">Height of the image captures from the camera.</param>
/// <param name="grayscale">Whether or not to convert the image to grayscale.</param>
/// <returns>The observation shape.</returns>
internal static int[] GenerateShape(int width, int height, bool grayscale)
{
return new[] { height, width, grayscale ? 1 : 3 };
}
}
}

37
com.unity.ml-agents/Runtime/Sensor/CameraSensorComponent.cs


using System;
/// <summary>
/// A SensorComponent that creates a <see cref="CameraSensor"/>.
/// </summary>
/// <summary>
/// Camera object that provides the data to the sensor.
/// </summary>
/// <summary>
/// Name of the generated <see cref="CameraSensor"/> object.
/// </summary>
/// <summary>
/// Width of the generated image.
/// </summary>
/// <summary>
/// Height of the generated image.
/// </summary>
/// <summary>
/// Whether to generate grayscale images or color.
/// </summary>
/// <summary>
/// The compression type to use for the sensor.
/// </summary>
/// <summary>
/// Creates the <see cref="CameraSensor"/>
/// </summary>
/// <returns>The created <see cref="CameraSensor"/> object for this component.</returns>
/// <summary>
/// Computes the observation shape of the sensor.
/// </summary>
/// <returns>The observation shape of the associated <see cref="CameraSensor"/> object.</returns>
return new[] { height, width, grayscale ? 1 : 3 };
return CameraSensor.GenerateShape(width, height, grayscale);
}
}
}

63
com.unity.ml-agents/Runtime/Sensor/ISensor.cs


namespace MLAgents
{
/// <summary>
/// The compression setting for visual/camera observations.
/// </summary>
/// <summary>
/// No compression. Data is preserved as float arrays.
/// </summary>
/// <summary>
/// PNG format. Data will be stored in binary format.
/// </summary>
/// For custom implementations, it is recommended to SensorBase instead.
/// For custom implementations, it is recommended to <see cref="SensorBase"/> instead.
/// For example, a sensor that observes the velocity of a rigid body (in 3D) would return new {3}.
/// A sensor that returns an RGB image would return new [] {Width, Height, 3}
/// For example, a sensor that observes the velocity of a rigid body (in 3D) would return
/// new {3}. A sensor that returns an RGB image would return new [] {Height, Width, 3}
/// <returns></returns>
/// <returns>Size of the observations that will be generated.</returns>
/// Write the observation data directly to the WriteAdapter.
/// This is considered an advanced interface; for a simpler approach, use SensorBase and override WriteFloats instead.
/// Note that this (and GetCompressedObservation) may be called multiple times per agent step, so should not
/// mutate any internal state.
/// Write the observation data directly to the <see cref="WriteAdapter"/>.
/// This is considered an advanced interface; for a simpler approach, use
/// <see cref="SensorBase"/> and override <see cref="SensorBase.WriteObservation"/> instead.
/// Note that this (and <see cref="GetCompressedObservation"/>) may
/// be called multiple times per agent step, so should not mutate any internal state.
/// <param name="adapter"></param>
/// <returns>The number of elements written</returns>
/// <param name="adapter">Where the observations will be written to.</param>
/// <returns>The number of elements written.</returns>
/// Return a compressed representation of the observation. For small observations, this should generally not be
/// implemented. However, compressing large observations (such as visual results) can significantly improve
/// model training time.
/// Return a compressed representation of the observation. For small observations,
/// this should generally not be implemented. However, compressing large observations
/// (such as visual results) can significantly improve model training time.
/// <returns></returns>
/// <returns>Compressed observation.</returns>
byte[] GetCompressedObservation();
/// <summary>

/// <summary>
/// Return the compression type being used. If no compression is used, return SensorCompressionType.None
/// Return the compression type being used. If no compression is used, return
/// <see cref="SensorCompressionType.None"/>.
/// <returns></returns>
/// <returns>Compression type used by the sensor.</returns>
/// Get the name of the sensor. This is used to ensure deterministic sorting of the sensors on an Agent,
/// so the naming must be consistent across all sensors and agents.
/// Get the name of the sensor. This is used to ensure deterministic sorting of the sensors
/// on an Agent, so the naming must be consistent across all sensors and agents.
/// <returns>The name of the sensor</returns>
/// <returns>The name of the sensor.</returns>
/// <summary>
/// Helper methods to be shared by all classes that implement <see cref="ISensor"/>.
/// </summary>
/// Get the total number of elements in the ISensor's observation (i.e. the product of the shape elements).
/// Get the total number of elements in the ISensor's observation (i.e. the product of the
/// shape elements).
/// </summary>
/// <param name="sensor"></param>
/// <returns></returns>

int count = 1;
for (var i = 0; i < shape.Length; i++)
var count = 1;
foreach (var dim in shape)
count *= shape[i];
count *= dim;
}
return count;

2
com.unity.ml-agents/Runtime/Sensor/Observation.cs


/// <summary>
/// The uncompressed dimensions of the data.
/// E.g. for RGB visual observations, this will be {Width, Height, 3}
/// E.g. for RGB visual observations, this will be {Height, Width, 3}
/// </summary>
public int[] Shape;
}

44
com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensor.cs


/// </summary>
public enum RayPerceptionCastType
{
/// <summary>
/// </summary>
/// <summary>
/// </summary>
/// <summary>
/// Contains the elements that define a ray perception sensor.
/// </summary>
public struct RayPerceptionInput
{
/// <summary>

}
}
/// <summary>
/// Contains the data generated/produced from a ray perception sensor.
/// </summary>
/// <summary>
/// Contains the data generated from a single ray of a ray perception sensor.
/// </summary>
public struct RayOutput
{
/// <summary>

int m_Frame;
}
/// <summary>
/// A sensor implementation that supports ray cast-based observations.
/// </summary>
public class RayPerceptionSensor : ISensor
{
float[] m_Observations;

get { return m_DebugDisplayInfo; }
}
/// <summary>
/// Creates the RayPerceptionSensor.
/// </summary>
/// <param name="name">The name of the sensor.</param>
/// <param name="rayInput">The inputs for the sensor.</param>
public RayPerceptionSensor(string name, RayPerceptionInput rayInput)
{
var numObservations = rayInput.OutputSize();

}
}
internal void SetRayPerceptionInput(RayPerceptionInput input)
{
// TODO make sure that number of rays and tags don't change
m_RayPerceptionInput = input;
}
/// <summary>
/// Computes the ray perception observations and saves them to the provided
/// <see cref="WriteAdapter"/>.
/// </summary>
/// <param name="adapter">Where the ray perception observations are written to.</param>
/// <returns></returns>
public int Write(WriteAdapter adapter)
{
using (TimerStack.Instance.Scoped("RayPerceptionSensor.Perceive"))

return m_Observations.Length;
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
{
return SensorCompressionType.None;

/// Evaluates the raycasts to be used as part of an observation of an agent.
/// </summary>
/// <param name="input">Input defining the rays that will be cast.</param>
/// <param name="output">Output class that will be written to with raycast results.</param>
///
/// <returns>Output struct containing the raycast results.</returns>
public static RayPerceptionOutput PerceiveStatic(RayPerceptionInput input)
{
RayPerceptionOutput output = new RayPerceptionOutput();

/// <param name="rayIndex"></param>
/// <param name="debugRayOut"></param>
/// <returns></returns>
static RayPerceptionOutput.RayOutput PerceiveSingleRay(
internal static RayPerceptionOutput.RayOutput PerceiveSingleRay(
RayPerceptionInput input,
int rayIndex,
out DebugDisplayInfo.RayInfo debugRayOut

debugRayOut.castRadius = scaledCastRadius;
return rayOutput;
}
}
}

7
com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponent2D.cs


namespace MLAgents
{
/// <summary>
/// A component for 2D Ray Perception.
/// </summary>
/// <summary>
/// Initializes the raycast sensor component.
/// </summary>
public RayPerceptionSensorComponent2D()
{
// Set to the 2D defaults (just in case they ever diverge).

/// <inheritdoc/>
public override RayPerceptionCastType GetCastType()
{
return RayPerceptionCastType.Cast2D;

37
com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponent3D.cs


using System;
using UnityEngine.Serialization;
/// <summary>
/// A component for 3D Ray Perception.
/// </summary>
[Header("3D Properties", order = 100)]
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("startVerticalOffset")]
public float startVerticalOffset;
float m_StartVerticalOffset;
/// <summary>
/// Ray start is offset up or down by this amount.
/// </summary>
public float startVerticalOffset
{
get => m_StartVerticalOffset;
set { m_StartVerticalOffset = value; UpdateSensor(); }
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("endVerticalOffset")]
public float endVerticalOffset;
float m_EndVerticalOffset;
/// <summary>
/// Ray end is offset up or down by this amount.
/// </summary>
public float endVerticalOffset
{
get => m_EndVerticalOffset;
set { m_EndVerticalOffset = value; UpdateSensor(); }
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public override float GetEndVerticalOffset()
{
return endVerticalOffset;

279
com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponentBase.cs


using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
/// <summary>
/// A base class to support sensor components for raycast-based sensors.
/// </summary>
public string sensorName = "RayPerceptionSensor";
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("sensorName")]
string m_SensorName = "RayPerceptionSensor";
/// <summary>
/// The name of the Sensor that this component wraps.
/// </summary>
public string sensorName
{
get => m_SensorName;
// Restrict the access on the name, since changing it a runtime doesn't re-sort the Agent sensors.
internal set => m_SensorName = value;
}
[SerializeField]
[FormerlySerializedAs("detectableTags")]
public List<string> detectableTags;
List<string> m_DetectableTags;
/// <summary>
/// List of tags in the scene to compare against.
/// </summary>
public List<string> detectableTags
{
get => m_DetectableTags;
// Note: can't change at runtime
internal set => m_DetectableTags = value;
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("raysPerDirection")]
public int raysPerDirection = 3;
int m_RaysPerDirection = 3;
/// <summary>
/// Number of rays to the left and right of center.
/// </summary>
public int raysPerDirection
{
get => m_RaysPerDirection;
// Note: can't change at runtime
internal set => m_RaysPerDirection = value;
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("maxRayDegrees")]
[Tooltip("Cone size for rays. Using 90 degrees will cast rays to the left and right. Greater than 90 degrees will go backwards.")]
public float maxRayDegrees = 70;
[Tooltip("Cone size for rays. Using 90 degrees will cast rays to the left and right. " +
"Greater than 90 degrees will go backwards.")]
float m_MaxRayDegrees = 70;
/// <summary>
/// Cone size for rays. Using 90 degrees will cast rays to the left and right.
/// Greater than 90 degrees will go backwards.
/// </summary>
public float maxRayDegrees
{
get => m_MaxRayDegrees;
set { m_MaxRayDegrees = value; UpdateSensor(); }
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("sphereCastRadius")]
public float sphereCastRadius = 0.5f;
float m_SphereCastRadius = 0.5f;
/// <summary>
/// Radius of sphere to cast. Set to zero for raycasts.
/// </summary>
public float sphereCastRadius
{
get => m_SphereCastRadius;
set { m_SphereCastRadius = value; UpdateSensor(); }
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("rayLength")]
public float rayLength = 20f;
float m_RayLength = 20f;
/// <summary>
/// Length of the rays to cast.
/// </summary>
public float rayLength
{
get => m_RayLength;
set { m_RayLength = value; UpdateSensor(); }
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("rayLayerMask")]
public LayerMask rayLayerMask = Physics.DefaultRaycastLayers;
LayerMask m_RayLayerMask = Physics.DefaultRaycastLayers;
/// <summary>
/// Controls which layers the rays can hit.
/// </summary>
public LayerMask rayLayerMask
{
get => m_RayLayerMask;
set { m_RayLayerMask = value; UpdateSensor();}
}
[HideInInspector]
[SerializeField]
[FormerlySerializedAs("observationStacks")]
public int observationStacks = 1;
int m_ObservationStacks = 1;
/// <summary>
/// Whether to stack previous observations. Using 1 means no previous observations.
/// </summary>
internal int observationStacks
{
get => m_ObservationStacks;
set => m_ObservationStacks = value; // Note: can't change at runtime
}
/// <summary>
/// Color to code a ray that hits another object.
/// </summary>
[HideInInspector]
[SerializeField]
public Color rayHitColor = Color.red;
public Color rayMissColor = Color.white;
internal Color rayHitColor = Color.red;
/// <summary>
/// Color to code a ray that avoid or misses all other objects.
/// </summary>
[HideInInspector]
[SerializeField]
internal Color rayMissColor = Color.white;
/// <summary>
/// Returns the <see cref="RayPerceptionCastType"/> for the associated raycast sensor.
/// </summary>
/// <returns></returns>
/// <summary>
/// Returns the amount that the ray start is offset up or down by.
/// </summary>
/// <returns></returns>
/// <summary>
/// Returns the amount that the ray end is offset up or down by.
/// </summary>
/// <returns></returns>
/// <summary>
/// Returns an initialized raycast sensor.
/// </summary>
/// <returns></returns>
var rayAngles = GetRayAngles(raysPerDirection, maxRayDegrees);
var rayPerceptionInput = GetRayPerceptionInput();
var rayPerceptionInput = new RayPerceptionInput();
rayPerceptionInput.rayLength = rayLength;
rayPerceptionInput.detectableTags = detectableTags;
rayPerceptionInput.angles = rayAngles;
rayPerceptionInput.startOffset = GetStartVerticalOffset();
rayPerceptionInput.endOffset = GetEndVerticalOffset();
rayPerceptionInput.castRadius = sphereCastRadius;
rayPerceptionInput.transform = transform;
rayPerceptionInput.castType = GetCastType();
rayPerceptionInput.layerMask = rayLayerMask;
m_RaySensor = new RayPerceptionSensor(sensorName, rayPerceptionInput);
m_RaySensor = new RayPerceptionSensor(m_SensorName, rayPerceptionInput);
if (observationStacks != 1)
{

return m_RaySensor;
}
/// <summary>
/// Returns the specific ray angles given the number of rays per direction and the
/// cone size for the rays.
/// </summary>
/// <param name="raysPerDirection">Number of rays to the left and right of center.</param>
/// <param name="maxRayDegrees">
/// Cone size for rays. Using 90 degrees will cast rays to the left and right.
/// Greater than 90 degrees will go backwards.
/// </param>
/// <returns></returns>
public static float[] GetRayAngles(int raysPerDirection, float maxRayDegrees)
{
// Example:

return anglesOut;
}
/// <summary>
/// Returns the observation shape for this raycast sensor which depends on the number
/// of tags for detected objects and the number of rays.
/// </summary>
/// <returns></returns>
var numTags = detectableTags?.Count ?? 0;
var numTags = m_DetectableTags?.Count ?? 0;
/// <summary>
/// Draw the debug information from the sensor (if available).
/// </summary>
public void OnDrawGizmos()
RayPerceptionInput GetRayPerceptionInput()
{
var rayAngles = GetRayAngles(raysPerDirection, maxRayDegrees);
var rayPerceptionInput = new RayPerceptionInput();
rayPerceptionInput.rayLength = rayLength;
rayPerceptionInput.detectableTags = detectableTags;
rayPerceptionInput.angles = rayAngles;
rayPerceptionInput.startOffset = GetStartVerticalOffset();
rayPerceptionInput.endOffset = GetEndVerticalOffset();
rayPerceptionInput.castRadius = sphereCastRadius;
rayPerceptionInput.transform = transform;
rayPerceptionInput.castType = GetCastType();
rayPerceptionInput.layerMask = rayLayerMask;
return rayPerceptionInput;
}
internal void UpdateSensor()
if (m_RaySensor?.debugDisplayInfo?.rayInfos == null)
if (m_RaySensor != null)
return;
var rayInput = GetRayPerceptionInput();
m_RaySensor.SetRayPerceptionInput(rayInput);
var debugInfo = m_RaySensor.debugDisplayInfo;
}
// Draw "old" observations in a lighter color.
// Since the agent may not step every frame, this helps de-emphasize "stale" hit information.
var alpha = Mathf.Pow(.5f, debugInfo.age);
void OnDrawGizmosSelected()
{
if (m_RaySensor?.debugDisplayInfo?.rayInfos != null)
{
// If we have cached debug info from the sensor, draw that.
// Draw "old" observations in a lighter color.
// Since the agent may not step every frame, this helps de-emphasize "stale" hit information.
var alpha = Mathf.Pow(.5f, m_RaySensor.debugDisplayInfo.age);
foreach (var rayInfo in debugInfo.rayInfos)
foreach (var rayInfo in m_RaySensor.debugDisplayInfo.rayInfos)
{
DrawRaycastGizmos(rayInfo, alpha);
}
}
else
var startPositionWorld = rayInfo.worldStart;
var endPositionWorld = rayInfo.worldEnd;
var rayDirection = endPositionWorld - startPositionWorld;
rayDirection *= rayInfo.rayOutput.hitFraction;
var rayInput = GetRayPerceptionInput();
for (var rayIndex = 0; rayIndex < rayInput.angles.Count; rayIndex++)
{
DebugDisplayInfo.RayInfo debugRay;
RayPerceptionSensor.PerceiveSingleRay(rayInput, rayIndex, out debugRay);
DrawRaycastGizmos(debugRay);
}
}
}
/// <summary>
/// Draw the debug information from the sensor (if available).
/// </summary>
void DrawRaycastGizmos(DebugDisplayInfo.RayInfo rayInfo, float alpha=1.0f)
{
var startPositionWorld = rayInfo.worldStart;
var endPositionWorld = rayInfo.worldEnd;
var rayDirection = endPositionWorld - startPositionWorld;
rayDirection *= rayInfo.rayOutput.hitFraction;
// hit fraction ^2 will shift "far" hits closer to the hit color
var lerpT = rayInfo.rayOutput.hitFraction * rayInfo.rayOutput.hitFraction;
var color = Color.Lerp(rayHitColor, rayMissColor, lerpT);
color.a *= alpha;
Gizmos.color = color;
Gizmos.DrawRay(startPositionWorld, rayDirection);
// hit fraction ^2 will shift "far" hits closer to the hit color
var lerpT = rayInfo.rayOutput.hitFraction * rayInfo.rayOutput.hitFraction;
var color = Color.Lerp(rayHitColor, rayMissColor, lerpT);
color.a *= alpha;
Gizmos.color = color;
Gizmos.DrawRay(startPositionWorld, rayDirection);
// Draw the hit point as a sphere. If using rays to cast (0 radius), use a small sphere.
if (rayInfo.rayOutput.hasHit)
{
var hitRadius = Mathf.Max(rayInfo.castRadius, .05f);
Gizmos.DrawWireSphere(startPositionWorld + rayDirection, hitRadius);
}
// Draw the hit point as a sphere. If using rays to cast (0 radius), use a small sphere.
if (rayInfo.rayOutput.hasHit)
{
var hitRadius = Mathf.Max(rayInfo.castRadius, .05f);
Gizmos.DrawWireSphere(startPositionWorld + rayDirection, hitRadius);
}
}
}

21
com.unity.ml-agents/Runtime/Sensor/RenderTextureSensor.cs


using System;
/// <summary>
/// Sensor class that wraps a <see cref="RenderTexture"/> instance.
/// </summary>
public class RenderTextureSensor : ISensor
{
RenderTexture m_RenderTexture;

SensorCompressionType m_CompressionType;
public RenderTextureSensor(RenderTexture renderTexture, bool grayscale, string name,
SensorCompressionType compressionType)
/// <summary>
/// Initializes the sensor.
/// </summary>
/// <param name="renderTexture">The <see cref="RenderTexture"/> instance to wrap.</param>
/// <param name="grayscale">Whether to convert it to grayscale or not.</param>
/// <param name="name">Name of the sensor.</param>
/// <param name="compressionType">Compression method for the render texture.</param>
public RenderTextureSensor(
RenderTexture renderTexture, bool grayscale, string name, SensorCompressionType compressionType)
{
m_RenderTexture = renderTexture;
var width = renderTexture != null ? renderTexture.width : 0;

m_CompressionType = compressionType;
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public byte[] GetCompressedObservation()
{
using (TimerStack.Instance.Scoped("RenderTexSensor.GetCompressedObservation"))

}
}
/// <inheritdoc/>
public int Write(WriteAdapter adapter)
{
using (TimerStack.Instance.Scoped("RenderTexSensor.GetCompressedObservation"))

}
}
/// <inheritdoc/>
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
{
return m_CompressionType;

22
com.unity.ml-agents/Runtime/Sensor/RenderTextureSensorComponent.cs


using System;
/// <summary>
/// Component that wraps a <see cref="RenderTextureSensor"/>.
/// </summary>
/// <summary>
/// The <see cref="RenderTexture"/> instance that the associated
/// <see cref="RenderTextureSensor"/> wraps.
/// </summary>
/// <summary>
/// Name of the sensor.
/// </summary>
/// <summary>
/// Whether the RenderTexture observation should be converted to grayscale or not.
/// </summary>
/// <summary>
/// Compression type for the render texture observation.
/// </summary>
/// <inheritdoc/>
/// <inheritdoc/>
public override int[] GetObservationShape()
{
var width = renderTexture != null ? renderTexture.width : 0;

19
com.unity.ml-agents/Runtime/Sensor/SensorBase.cs


using UnityEngine;
/// <summary>
/// A base sensor that provides a number default implementations.
/// </summary>
/// Write the observations to the output buffer. This size of the buffer will be product of the sizes returned
/// by GetObservationShape().
/// Write the observations to the output buffer. This size of the buffer will be product
/// of the sizes returned by <see cref="GetObservationShape"/>.
/// <inheritdoc/>
/// <inheritdoc/>
/// Default implementation of Write interface. This creates a temporary array, calls WriteObservation,
/// and then writes the results to the WriteAdapter.
/// Default implementation of Write interface. This creates a temporary array,
/// calls WriteObservation, and then writes the results to the WriteAdapter.
/// <returns>The number of elements written.</returns>
public virtual int Write(WriteAdapter adapter)
{
// TODO reuse buffer for similar agents, don't call GetObservationShape()

return numFloats;
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
{
return SensorCompressionType.None;

17
com.unity.ml-agents/Runtime/Sensor/SensorComponent.cs


using System;
/// Editor components for creating Sensors. Generally an ISensor implementation should have a corresponding
/// SensorComponent to create it.
/// Editor components for creating Sensors. Generally an ISensor implementation should have a
/// corresponding SensorComponent to create it.
/// </summary>
public abstract class SensorComponent : MonoBehaviour
{

/// <returns></returns>
/// <returns>Created ISensor object.</returns>
/// <returns></returns>
/// <returns>Shape of the sensor observation.</returns>
/// <summary>
/// Whether the observation is visual or not.
/// </summary>
/// <returns>True if the observation is visual, false otherwise.</returns>
public virtual bool IsVisual()
{
var shape = GetObservationShape();

/// <summary>
/// Whether the observation is vector or not.
/// </summary>
/// <returns>True if the observation is vector, false otherwise.</returns>
public virtual bool IsVector()
{
var shape = GetObservationShape();

4
com.unity.ml-agents/Runtime/Sensor/StackingSensor.cs


/// <summary>
///
/// </summary>
/// <param name="wrapped">The wrapped sensor</param>
/// <param name="numStackedObservations">Number of stacked observations to keep</param>
/// <param name="wrapped">The wrapped sensor.</param>
/// <param name="numStackedObservations">Number of stacked observations to keep.</param>
public StackingSensor(ISensor wrapped, int numStackedObservations)
{
// TODO ensure numStackedObservations > 1

23
com.unity.ml-agents/Runtime/Sensor/VectorSensor.cs


namespace MLAgents
{
/// <summary>
/// A sensor implementation for vector observations.
/// </summary>
// TOOD allow setting float[]
// TODO allow setting float[]
/// <summary>
/// Initializes the sensor.
/// </summary>
/// <param name="observationSize">Number of vector observations.</param>
/// <param name="name">Name of the sensor.</param>
public VectorSensor(int observationSize, string name = null)
{
if (name == null)

m_Shape = new[] { observationSize };
}
/// <inheritdoc/>
public int Write(WriteAdapter adapter)
{
var expectedObservations = m_Shape[0];

return expectedObservations;
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
{
return SensorCompressionType.None;

/// <summary>
/// Adds a boolean observation to the vector observation of the agent.
/// </summary>
/// <param name="observation"></param>
/// <param name="observation">Observation.</param>
/// <summary>
/// Adds a one-hot encoding observation.
/// </summary>
/// <param name="observation">The index of this observation.</param>
/// <param name="range">The max index for any observation.</param>
public void AddOneHotObservation(int observation, int range)
{
for (var i = 0; i < range; i++)

8
com.unity.ml-agents/Runtime/Sensor/WriteAdapter.cs


/// <summary>
/// Set the adapter to write to a TensorProxy at the given batch and channel offset.
/// </summary>
/// <param name="tensorProxy">Tensor proxy that will be writtent to.</param>
/// <param name="batchIndex">Batch index in the tensor proxy (i.e. the index of the Agent)</param>
/// <param name="tensorProxy">Tensor proxy that will be written to.</param>
/// <param name="batchIndex">Batch index in the tensor proxy (i.e. the index of the Agent).</param>
/// <param name="channelOffset">Offset from the start of the channel to write to.</param>
internal void SetTarget(TensorProxy tensorProxy, int batchIndex, int channelOffset)
{

/// <summary>
/// 1D write access at a specified index. Use AddRange if possible instead.
/// </summary>
/// <param name="index">Index to write to</param>
/// <param name="index">Index to write to.</param>
public float this[int index]
{