浏览代码

Merge branch 'main' into ai-hw-2021

/ai-hw-2021
Ruo-Ping Dong 4 年前
当前提交
deeea398
共有 74 个文件被更改,包括 870 次插入686 次删除
  1. 100
      .yamato/com.unity.ml-agents-optional-dep-tests.yml
  2. 263
      .yamato/com.unity.ml-agents-test.yml
  3. 6
      Project/Assets/ML-Agents/Examples/Basic/Scripts/BasicSensorComponent.cs
  4. 8
      Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/SensorBase.cs
  5. 4
      Project/Assets/ML-Agents/TestScenes/TestCompressedTexture/TestTextureSensor.cs
  6. 16
      Project/Assets/ML-Agents/TestScenes/TestCompressedTexture/TestTextureSensorComponent.cs
  7. 14
      com.unity.ml-agents.extensions/Runtime/Match3/Match3Sensor.cs
  8. 14
      com.unity.ml-agents.extensions/Runtime/Match3/Match3SensorComponent.cs
  9. 20
      com.unity.ml-agents.extensions/Runtime/Sensors/ArticulationBodySensorComponent.cs
  10. 11
      com.unity.ml-agents.extensions/Runtime/Sensors/GridSensor.cs
  11. 10
      com.unity.ml-agents.extensions/Runtime/Sensors/PhysicsBodySensor.cs
  12. 20
      com.unity.ml-agents.extensions/Runtime/Sensors/RigidBodySensorComponent.cs
  13. 43
      com.unity.ml-agents.extensions/Tests/Editor/Match3/Match3SensorTests.cs
  14. 19
      com.unity.ml-agents.extensions/Tests/Editor/Sensors/ChannelHotShapeTests.cs
  15. 15
      com.unity.ml-agents.extensions/Tests/Editor/Sensors/ChannelShapeTests.cs
  16. 27
      com.unity.ml-agents.extensions/Tests/Editor/Sensors/GridSensorTestUtils.cs
  17. 6
      com.unity.ml-agents.extensions/Tests/Runtime/Sensors/ArticulationBodySensorTests.cs
  18. 6
      com.unity.ml-agents.extensions/Tests/Runtime/Sensors/RigidBodySensorTests.cs
  19. 3
      com.unity.ml-agents.extensions/package.json
  20. 8
      com.unity.ml-agents/CHANGELOG.md
  21. 16
      com.unity.ml-agents/Editor/RayPerceptionSensorComponentBaseEditor.cs
  22. 14
      com.unity.ml-agents/Editor/Unity.ML-Agents.Editor.asmdef
  23. 14
      com.unity.ml-agents/Runtime/Agent.cs
  24. 2
      com.unity.ml-agents/Runtime/Analytics/Events.cs
  25. 18
      com.unity.ml-agents/Runtime/Analytics/InferenceAnalytics.cs
  26. 29
      com.unity.ml-agents/Runtime/Analytics/TrainingAnalytics.cs
  27. 44
      com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs
  28. 20
      com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs
  29. 4
      com.unity.ml-agents/Runtime/Policies/HeuristicPolicy.cs
  30. 14
      com.unity.ml-agents/Runtime/Policies/RemotePolicy.cs
  31. 6
      com.unity.ml-agents/Runtime/Sensors/BufferSensor.cs
  32. 6
      com.unity.ml-agents/Runtime/Sensors/BufferSensorComponent.cs
  33. 5
      com.unity.ml-agents/Runtime/Sensors/CameraSensor.cs
  34. 15
      com.unity.ml-agents/Runtime/Sensors/CameraSensorComponent.cs
  35. 24
      com.unity.ml-agents/Runtime/Sensors/ISensor.cs
  36. 14
      com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensor.cs
  37. 2
      com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensorComponent2D.cs
  38. 18
      com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensorComponentBase.cs
  39. 5
      com.unity.ml-agents/Runtime/Sensors/Reflection/ReflectionSensorBase.cs
  40. 5
      com.unity.ml-agents/Runtime/Sensors/RenderTextureSensor.cs
  41. 16
      com.unity.ml-agents/Runtime/Sensors/RenderTextureSensorComponent.cs
  42. 7
      com.unity.ml-agents/Runtime/Sensors/SensorComponent.cs
  43. 27
      com.unity.ml-agents/Runtime/Sensors/StackingSensor.cs
  44. 6
      com.unity.ml-agents/Runtime/Sensors/VectorSensor.cs
  45. 10
      com.unity.ml-agents/Runtime/Unity.ML-Agents.asmdef
  46. 7
      com.unity.ml-agents/Runtime/Utilities.cs
  47. 12
      com.unity.ml-agents/Tests/Editor/Analytics/TrainingAnalyticsTest.cs
  48. 137
      com.unity.ml-agents/Tests/Editor/Communicator/GrpcExtensionsTests.cs
  49. 11
      com.unity.ml-agents/Tests/Editor/Inference/ParameterLoaderTest.cs
  50. 40
      com.unity.ml-agents/Tests/Editor/MLAgentsEditModeTest.cs
  51. 2
      com.unity.ml-agents/Tests/Editor/PublicAPI/PublicApiValidation.cs
  52. 10
      com.unity.ml-agents/Tests/Editor/Unity.ML-Agents.Editor.Tests.asmdef
  53. 24
      com.unity.ml-agents/Tests/Runtime/RuntimeAPITest.cs
  54. 4
      com.unity.ml-agents/Tests/Runtime/Sensor/BufferSensorTest.cs
  55. 7
      com.unity.ml-agents/Tests/Runtime/Sensor/CameraSensorComponentTest.cs
  56. 4
      com.unity.ml-agents/Tests/Runtime/Sensor/FloatVisualSensorTests.cs
  57. 16
      com.unity.ml-agents/Tests/Runtime/Sensor/RayPerceptionSensorTests.cs
  58. 5
      com.unity.ml-agents/Tests/Runtime/Sensor/RenderTextureSensorComponentTests.cs
  59. 6
      com.unity.ml-agents/Tests/Runtime/Sensor/SensorShapeValidatorTests.cs
  60. 20
      com.unity.ml-agents/Tests/Runtime/Sensor/StackingSensorTests.cs
  61. 12
      com.unity.ml-agents/Tests/Runtime/Sensor/Unity.ML-Agents.Runtime.Sensor.Tests.asmdef
  62. 12
      com.unity.ml-agents/Tests/Runtime/Unity.ML-Agents.Runtime.Tests.asmdef
  63. 5
      com.unity.ml-agents/Tests/Runtime/Utils/TestClasses.cs
  64. 4
      com.unity.ml-agents/package.json
  65. 27
      docs/Migrating.md
  66. 4
      markdown-link-check.full.json
  67. 40
      .yamato/com.unity.ml-agents-coverage.yml
  68. 17
      .yamato/coverage_tests.metafile
  69. 109
      com.unity.ml-agents/Runtime/Sensors/CompressionSpec.cs
  70. 3
      com.unity.ml-agents/Runtime/Sensors/CompressionSpec.cs.meta
  71. 30
      com.unity.ml-agents/Tests/Runtime/Sensor/CompressionSpecTests.cs
  72. 3
      com.unity.ml-agents/Tests/Runtime/Sensor/CompressionSpecTests.cs.meta
  73. 20
      com.unity.ml-agents/Runtime/Sensors/ISparseChannelSensor.cs
  74. 11
      com.unity.ml-agents/Runtime/Sensors/ISparseChannelSensor.cs.meta

100
.yamato/com.unity.ml-agents-optional-dep-tests.yml


OptionalDependencyTestsLinux:
name : LinuxOptionalDependenciesTests
agent:
type: Unity::VM
image: package-ci/ubuntu:stable
flavor: b1.medium
commands:
- |
curl -L https://artifactory.prd.it.unity3d.com/artifactory/api/gpg/key/public | sudo apt-key add -
sudo sh -c "echo 'deb https://artifactory.prd.it.unity3d.com/artifactory/unity-apt-local bionic main' > /etc/apt/sources.list.d/unity.list"
sudo apt update
sudo apt install -y unity-config
npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
unity-config settings editor-path ./.Editor
unity-config project create opt-deps-test
unity-config project add dependency com.unity.ml-agents/
unity-config project add testable com.unity.ml-agents
unity-config project add dependency com.unity.modules.imageconversion@1.0.0
unity-config project add dependency com.unity.modules.jsonserialize@1.0.0
unity-config project add dependency com.unity.modules.physics@1.0.0
unity-config project add dependency com.unity.modules.physics2d@1.0.0
upm-ci project test -u 2019.4 --type project-tests --project-path opt-deps-test --package-filter com.unity.ml-agents
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/com.unity.ml-agents-pack.yml#pack
triggers:
cancel_old_ci: true
expression: |
(pull_request.target eq "main" OR
pull_request.target match "release.+") AND
NOT pull_request.draft AND
(pull_request.changes.any match "com.unity.ml-agents/**" OR
pull_request.changes.any match ".yamato/com.unity.ml-agents-test.yml")
optional_deps:
- name: Analytics
project: "OptionalDepedencyTests/NoAnalyticsModule"
version: 2020.2
- name: Physics
project: OptionalDepedencyTests/NoPhysicsModule
version: 2020.2
- name: Physics2D
project: OptionalDepedencyTests/NoPhysics2DModule
version: 2020.2
---
{% for optional_dep in optional_deps %}
OptionalDependencyTests_{{ optional_dep.name }}:
name : Test Optional Package Dependencies {{ optional_dep.name }}
agent:
type: Unity::VM
image: package-ci/ubuntu:stable
flavor: b1.medium
commands:
- |
curl -L https://artifactory.prd.it.unity3d.com/artifactory/api/gpg/key/public | sudo apt-key add -
sudo sh -c "echo 'deb https://artifactory.prd.it.unity3d.com/artifactory/unity-apt-local bionic main' > /etc/apt/sources.list.d/unity.list"
sudo apt update
sudo apt install -y unity-config
npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
unity-config settings editor-path ./.Editor
unity-config project create opt-deps-test
unity-config project add dependency com.unity.ml-agents/
unity-config project add testable com.unity.ml-agents
unity-config project add dependency com.unity.modules.imageconversion@1.0.0
unity-config project add dependency com.unity.modules.jsonserialize@1.0.0
{% unless optional_dep.name == "Physics" %}
unity-config project add dependency com.unity.modules.physics@1.0.0
{% endunless %}
{% unless optional_dep.name == "Physics2D" %}
unity-config project add dependency com.unity.modules.physics2d@1.0.0
{% endunless %}
{% unless optional_dep.name == "Analytics" %}
unity-config project add dependency com.unity.modules.unityanalytics@1.0.0
{% endunless %}
upm-ci project test -u {{ optional_dep.version }} --type project-tests --project-path opt-deps-test --package-filter com.unity.ml-agents
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/com.unity.ml-agents-pack.yml#pack
{% for coverage_editor in coverage_test_editors %}
{% for coverage_plathform in coverage_test_platforms %}
{% for coverage_package in coverage_test_packages %}
- .yamato/com.unity.ml-agents-coverage.yml#test_coverage_{{ coverage_package.name }}_{{ coverage_platform.name }}_{{ coverage_editor.version }}
{% endfor %}
{% endfor %}
{% endfor %}
triggers:
cancel_old_ci: true
expression: |
(pull_request.target eq "main" OR
pull_request.target match "release.+") AND
NOT pull_request.draft AND
(pull_request.changes.any match "com.unity.ml-agents/**" OR
pull_request.changes.any match ".yamato/com.unity.ml-agents-test.yml")
{% endfor %}

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


{% metadata_file .yamato/coverage_tests.metafile %}
- version: 2019.4
enableCodeCoverage: !!bool true
# We want some scene tests to run in the DevProject, but packages there only support 2020+
testProject: Project
enableNoDefaultPackages: !!bool true
- version: 2020.2
enableCodeCoverage: !!bool true
testProject: DevProject
enableNoDefaultPackages: !!bool true
- version: 2021.1
enableCodeCoverage: !!bool true
testProject: DevProject
enableNoDefaultPackages: !!bool true
- version: 2019.4
enableCodeCoverage: !!bool true
# We want some scene tests to run in the DevProject, but packages there only support 2020+
testProject: Project
enableNoDefaultPackages: !!bool true
- version: 2020.2
enableCodeCoverage: !!bool true
testProject: DevProject
enableNoDefaultPackages: !!bool true
- version: 2021.1
enableCodeCoverage: !!bool true
testProject: DevProject
enableNoDefaultPackages: !!bool true
- version: trunk
# Workaround for MLA-1596 - need to make sure we load the right results.
enableCodeCoverage: !!bool false
testProject: DevProject
- version: trunk
# Workaround for MLA-1596 - need to make sure we load the right results.
enableCodeCoverage: !!bool false
testProject: DevProject
- name: win
type: Unity::VM
image: package-ci/win10:stable
flavor: b1.large
- name: mac
type: Unity::VM::osx
image: package-ci/mac:stable
flavor: b1.small
- name: linux
type: Unity::VM
image: package-ci/ubuntu:stable
flavor: b1.medium
- name: win
type: Unity::VM
image: package-ci/win10:stable
flavor: b1.large
- name: mac
type: Unity::VM::osx
image: package-ci/mac:stable
flavor: b1.small
- name: linux
type: Unity::VM
image: package-ci/ubuntu:stable
flavor: b1.medium
- name: com.unity.ml-agents
assembly: Unity.ML-Agents
minCoveragePct: 72
- name: com.unity.ml-agents.extensions
assembly: Unity.ML-Agents.Extensions*
minCoveragePct: 75
- name: com.unity.ml-agents
assembly: Unity.ML-Agents
minCoveragePct: 72
- name: com.unity.ml-agents.extensions
assembly: Unity.ML-Agents.Extensions*
minCoveragePct: 75
name: Run All Combinations of Editors/Platforms Tests
dependencies:
{% for editor in test_editors %}
{% for platform in test_platforms %}
- .yamato/com.unity.ml-agents-test.yml#test_com.unity.ml-agents_{{ platform.name }}_{{ editor.version }}
{% endfor %}
{% endfor %}
{% for editor in trunk_editor %}
{% for platform in test_platforms %}
- .yamato/com.unity.ml-agents-test.yml#test_com.unity.ml-agents_{{ platform.name }}_{{ editor.version }}
{% endfor %}
{% endfor %}
triggers:
cancel_old_ci: true
recurring:
- branch: main
frequency: daily
name: Run All Combinations of Editors/Platforms Tests
dependencies:
{% for coverage_editor in coverage_test_editors %}
{% for coverage_plathform in coverage_test_platforms %}
{% for coverage_package in coverage_test_packages %}
- .yamato/com.unity.ml-agents-coverage.yml#test_coverage_{{ coverage_package.name }}_{{ coverage_platform.name }}_{{ coverage_editor.version }}
{% endfor %}
{% endfor %}
{% endfor %}
{% for editor in test_editors %}
{% for platform in test_platforms %}
- .yamato/com.unity.ml-agents-test.yml#test_com.unity.ml-agents_{{ platform.name }}_{{ editor.version }}
{% endfor %}
{% endfor %}
{% for editor in trunk_editor %}
{% for platform in test_platforms %}
- .yamato/com.unity.ml-agents-test.yml#test_com.unity.ml-agents_{{ platform.name }}_{{ editor.version }}
{% endfor %}
{% endfor %}
triggers:
cancel_old_ci: true
recurring:
- branch: main
frequency: daily
{% for package in packages %}
{% for package in packages %}
{% for platform in test_platforms %}
{% for platform in test_platforms %}
{% if editor.enableCodeCoverage %}
{% capture coverageOptions %} --enable-code-coverage --code-coverage-options 'generateHtmlReport;assemblyFilters:+{{ package.assembly }}'{% endcapture %}
{% else %}
{% assign coverageOptions = "" %}
{% endif %}
{% if editor.enableNoDefaultPackages %}
{% if editor.enableNoDefaultPackages %}
{% else %}
{% else %}
{% endif %}
{% endif %}
name : {{ package.name }} test {{ editor.version }} on {{ platform.name }}
agent:
type: {{ platform.type }}
image: {{ platform.image }}
flavor: {{ platform.flavor}}
commands:
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- upm-ci project test -u {{ editor.version }} --project-path {{ editor.testProject }} --package-filter {{ package.name }} {{ coverageOptions }} {{ noDefaultPackagesOptions }} --extra-utr-arg "reruncount=2"
{% if editor.enableCodeCoverage %}
- python3 ml-agents/tests/yamato/check_coverage_percent.py upm-ci~/test-results/ {{ package.minCoveragePct }}
{% endif %}
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/com.unity.ml-agents-pack.yml#pack
triggers:
cancel_old_ci: true
{% if platform.name == "linux" %}
expression: |
(pull_request.target eq "main" OR
pull_request.target match "release.+") AND
NOT pull_request.draft AND
(pull_request.changes.any match "com.unity.ml-agents/**" OR
pull_request.changes.any match " {{ editor.testProject }}/**" OR
{% if package.name == "com.unity.ml-agents.extensions" %}
pull_request.changes.any match "com.unity.ml-agents.extensions/**" OR
name : {{ package.name }} test {{ editor.version }} on {{ platform.name }}
agent:
type: {{ platform.type }}
image: {{ platform.image }}
flavor: {{ platform.flavor}}
commands:
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- upm-ci project test -u {{ editor.version }} --project-path {{ editor.testProject }} --package-filter {{ package.name }} {{ noDefaultPackagesOptions }} --extra-utr-arg "reruncount=2"
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/com.unity.ml-agents-pack.yml#pack
{% for coverage_editor in coverage_test_editors %}
{% for coverage_plathform in coverage_test_platforms %}
{% for coverage_package in coverage_test_packages %}
- .yamato/com.unity.ml-agents-coverage.yml#test_coverage_{{ coverage_package.name }}_{{ coverage_platform.name }}_{{ coverage_editor.version }}
{% endfor %}
{% endfor %}
{% endfor %}
triggers:
cancel_old_ci: true
{% if platform.name == "linux" %}
expression: |
(pull_request.target eq "main" OR
pull_request.target match "release.+") AND
NOT pull_request.draft AND
(pull_request.changes.any match "com.unity.ml-agents/**" OR
pull_request.changes.any match " {{ editor.testProject }}/**" OR
{% if package.name == "com.unity.ml-agents.extensions" %}
pull_request.changes.any match "com.unity.ml-agents.extensions/**" OR
{% endif %}
pull_request.changes.any match ".yamato/com.unity.ml-agents-test.yml")
pull_request.changes.any match ".yamato/com.unity.ml-agents-test.yml")
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
{% for package in packages %}
{% for package in packages %}
{% for platform in test_platforms %}
{% for platform in test_platforms %}
{% if editor.enableCodeCoverage %}
{% if editor.enableCodeCoverage %}
{% else %}
{% assign coverageOptions = "" %}
{% endif %}
{% else %}
{% assign coverageOptions = "" %}
{% endif %}
name : {{ package.name }} test {{ editor.version }} on {{ platform.name }}
agent:
type: {{ platform.type }}
image: {{ platform.image }}
flavor: {{ platform.flavor}}
commands:
- python3 -m pip install unity-downloader-cli --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
- unity-downloader-cli -u trunk -c editor --wait --fast
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- upm-ci project test -u {{ editor.version }} --project-path {{ editor.testProject }} --package-filter {{ package.name }} {{ coverageOptions }} --extra-create-project-arg="-upmNoDefaultPackages" --extra-utr-arg "reruncount=2"
{% if editor.enableCodeCoverage %}
- python3 ml-agents/tests/yamato/check_coverage_percent.py upm-ci~/test-results/ {{ package.minCoveragePct }}
{% endif %}
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/com.unity.ml-agents-pack.yml#pack
triggers:
cancel_old_ci: true
{% endfor %}
name : {{ package.name }} test {{ editor.version }} on {{ platform.name }}
agent:
type: {{ platform.type }}
image: {{ platform.image }}
flavor: {{ platform.flavor}}
commands:
- python3 -m pip install unity-downloader-cli --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
- unity-downloader-cli -u trunk -c editor --wait --fast
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- upm-ci project test -u {{ editor.version }} --project-path {{ editor.testProject }} --package-filter {{ package.name }} {{ coverageOptions }} --extra-create-project-arg="-upmNoDefaultPackages" --extra-utr-arg "reruncount=2"
{% if editor.enableCodeCoverage %}
- python3 ml-agents/tests/yamato/check_coverage_percent.py upm-ci~/test-results/ {{ package.minCoveragePct }}
{% endif %}
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/com.unity.ml-agents-pack.yml#pack
{% for coverage_editor in coverage_test_editors %}
{% for coverage_plathform in coverage_test_platforms %}
{% for coverage_package in coverage_test_packages %}
- .yamato/com.unity.ml-agents-coverage.yml#test_coverage_{{ coverage_package.name }}_{{ coverage_platform.name }}_{{ coverage_editor.version }}
{% endfor %}
{% endfor %}
{% endfor %}
triggers:
cancel_old_ci: true
{% endfor %}
{% endfor %}
{% endfor %}

6
Project/Assets/ML-Agents/Examples/Basic/Scripts/BasicSensorComponent.cs


{
return new BasicSensor(basicController);
}
/// <inheritdoc/>
public override int[] GetObservationShape()
{
return new[] { BasicController.k_Extents };
}
}
/// <summary>

8
Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/SensorBase.cs


{
/// <summary>
/// Write the observations to the output buffer. This size of the buffer will be product
/// of the sizes returned by <see cref="GetObservationShape"/>.
/// of the Shape array values returned by <see cref="ObservationSpec"/>.
/// </summary>
/// <param name="output"></param>
public abstract void WriteObservation(float[] output);

/// <returns>The number of elements written.</returns>
public virtual int Write(ObservationWriter writer)
{
// TODO reuse buffer for similar agents, don't call GetObservationShape()
// TODO reuse buffer for similar agents
var numFloats = this.ObservationSize();
float[] buffer = new float[numFloats];
WriteObservation(buffer);

}
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
public virtual CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
}
}

4
Project/Assets/ML-Agents/TestScenes/TestCompressedTexture/TestTextureSensor.cs


public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return m_CompressionType;
return CompressionSpec.Default();
}
}

16
Project/Assets/ML-Agents/TestScenes/TestCompressedTexture/TestTextureSensorComponent.cs


}
return m_Sensor;
}
/// <inheritdoc/>
public override int[] GetObservationShape()
{
var width = TestTexture.width;
var height = TestTexture.height;
var observationShape = new[] { height, width, 3 };
var stacks = ObservationStacks > 1 ? ObservationStacks : 1;
if (stacks > 1)
{
observationShape[2] *= stacks;
}
return observationShape;
}
}

14
com.unity.ml-agents.extensions/Runtime/Match3/Match3Sensor.cs


/// or uncompressed visual observations. Uses AbstractBoard.GetCellType()
/// and AbstractBoard.GetSpecialType() to determine the observation values.
/// </summary>
public class Match3Sensor : ISparseChannelSensor, IBuiltInSensor
public class Match3Sensor : ISensor, IBuiltInSensor
{
private Match3ObservationType m_ObservationType;
private AbstractBoard m_Board;

private int m_Columns;
private int m_NumCellTypes;
private int m_NumSpecialTypes;
private ISparseChannelSensor sparseChannelSensorImplementation;
private int SpecialTypeSize
{

{
}
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
internal SensorCompressionType GetCompressionType()
{
return m_ObservationType == Match3ObservationType.CompressedVisual ?
SensorCompressionType.PNG :

/// <inheritdoc/>
public string GetName()
public CompressionSpec GetCompressionSpec()
return m_Name;
return new CompressionSpec(GetCompressionType(), m_SparseChannelMapping);
public int[] GetCompressedChannelMapping()
public string GetName()
return m_SparseChannelMapping;
return m_Name;
}
/// <inheritdoc/>

14
com.unity.ml-agents.extensions/Runtime/Match3/Match3SensorComponent.cs


return new Match3Sensor(board, ObservationType, SensorName);
}
/// <inheritdoc/>
public override int[] GetObservationShape()
{
var board = GetComponent<AbstractBoard>();
if (board == null)
{
return System.Array.Empty<int>();
}
var specialSize = board.NumSpecialTypes == 0 ? 0 : board.NumSpecialTypes + 1;
return ObservationType == Match3ObservationType.Vector ?
new[] { board.Rows * board.Columns * (board.NumCellTypes + specialSize) } :
new[] { board.Rows, board.Columns, board.NumCellTypes + specialSize };
}
}
}

20
com.unity.ml-agents.extensions/Runtime/Sensors/ArticulationBodySensorComponent.cs


return new PhysicsBodySensor(RootBody, Settings, sensorName);
}
/// <inheritdoc/>
public override int[] GetObservationShape()
{
if (RootBody == null)
{
return new[] { 0 };
}
// TODO static method in PhysicsBodySensor?
// TODO only update PoseExtractor when body changes?
var poseExtractor = new ArticulationBodyPoseExtractor(RootBody);
var numPoseObservations = poseExtractor.GetNumPoseObservations(Settings);
var numJointObservations = 0;
foreach(var articBody in poseExtractor.GetEnabledArticulationBodies())
{
numJointObservations += ArticulationBodyJointExtractor.NumObservations(articBody, Settings);
}
return new[] { numPoseObservations + numJointObservations };
}
}
}

11
com.unity.ml-agents.extensions/Runtime/Sensors/GridSensor.cs


}
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
public virtual CompressionSpec GetCompressionSpec()
return CompressionType;
return new CompressionSpec(CompressionType);
}
/// <inheritdoc/>

m_ObservationSpec = ObservationSpec.Visual(GridNumSideX, GridNumSideZ, ObservationPerCell);
}
return m_ObservationSpec;
}
/// <inheritdoc/>
public override int[] GetObservationShape()
{
var shape = m_ObservationSpec.Shape;
return new int[] { shape[0], shape[1], shape[2] };
}
/// <inheritdoc/>

10
com.unity.ml-agents.extensions/Runtime/Sensors/PhysicsBodySensor.cs


}
#if UNITY_2020_1_OR_NEWER
public PhysicsBodySensor(ArticulationBody rootBody, PhysicsSensorSettings settings, string sensorName=null)
public PhysicsBodySensor(ArticulationBody rootBody, PhysicsSensorSettings settings, string sensorName = null)
{
var poseExtractor = new ArticulationBodyPoseExtractor(rootBody);
m_PoseExtractor = poseExtractor;

var numJointExtractorObservations = 0;
m_JointExtractors = new List<IJointExtractor>(poseExtractor.NumEnabledPoses);
foreach(var articBody in poseExtractor.GetEnabledArticulationBodies())
foreach (var articBody in poseExtractor.GetEnabledArticulationBodies())
{
var jointExtractor = new ArticulationBodyJointExtractor(articBody);
numJointExtractorObservations += jointExtractor.NumObservations(settings);

var numTransformObservations = m_PoseExtractor.GetNumPoseObservations(settings);
m_ObservationSpec = ObservationSpec.Vector(numTransformObservations + numJointExtractorObservations);
}
#endif
/// <inheritdoc/>

public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
/// <inheritdoc/>

{
return BuiltInSensorType.PhysicsBodySensor;
}
}
}

20
com.unity.ml-agents.extensions/Runtime/Sensors/RigidBodySensorComponent.cs


return new PhysicsBodySensor(GetPoseExtractor(), Settings, _sensorName);
}
/// <inheritdoc/>
public override int[] GetObservationShape()
{
if (RootBody == null)
{
return new[] { 0 };
}
var poseExtractor = GetPoseExtractor();
var numPoseObservations = poseExtractor.GetNumPoseObservations(Settings);
var numJointObservations = 0;
foreach (var rb in poseExtractor.GetEnabledRigidbodies())
{
var joint = rb.GetComponent<Joint>();
numJointObservations += RigidBodyJointExtractor.NumObservations(rb, joint, Settings);
}
return new[] { numPoseObservations + numJointObservations };
}
/// <summary>
/// Get the DisplayNodes of the hierarchy.
/// </summary>

43
com.unity.ml-agents.extensions/Tests/Editor/Match3/Match3SensorTests.cs


sensorComponent.ObservationType = Match3ObservationType.Vector;
var sensor = sensorComponent.CreateSensor();
var expectedShape = new[] { 3 * 3 * 2 };
Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
var expectedShape = new InplaceArray<int>(3 * 3 * 2);
Assert.AreEqual(expectedShape, sensor.GetObservationSpec().Shape);
var expectedObs = new float[]
{

sensorComponent.ObservationType = Match3ObservationType.Vector;
var sensor = sensorComponent.CreateSensor();
var expectedShape = new[] { 3 * 3 * (2 + 3) };
Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
var expectedShape = new InplaceArray<int>(3 * 3 * (2 + 3));
Assert.AreEqual(expectedShape, sensor.GetObservationSpec().Shape);
var expectedObs = new float[]
{

};
SensorTestHelper.CompareObservation(sensor, expectedObs);
}
[Test]
public void TestVisualObservations()

sensorComponent.ObservationType = Match3ObservationType.UncompressedVisual;
var sensor = sensorComponent.CreateSensor();
var expectedShape = new[] { 3, 3, 2 };
Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
var expectedShape = new InplaceArray<int>(3, 3, 2);
Assert.AreEqual(expectedShape, sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionSpec().SensorCompressionType);
var expectedObs = new float[]
{

sensorComponent.ObservationType = Match3ObservationType.UncompressedVisual;
var sensor = sensorComponent.CreateSensor();
var expectedShape = new[] { 3, 3, 2 + 3 };
Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
var expectedShape = new InplaceArray<int>(3, 3, 2 + 3);
Assert.AreEqual(expectedShape, sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionSpec().SensorCompressionType);
var expectedObs = new float[]
{

sensorComponent.ObservationType = Match3ObservationType.CompressedVisual;
var sensor = sensorComponent.CreateSensor();
var expectedShape = new[] { 3, 3, 2 };
Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
var expectedShape = new InplaceArray<int>(3, 3, 2);
Assert.AreEqual(expectedShape, sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionSpec().SensorCompressionType);
var pngData = sensor.GetCompressedObservation();
if (WritePNGDataToFile)

Assert.AreEqual(expectedPng, pngData);
}
[Test]
public void TestCompressedVisualObservationsSpecial()
{

sensorComponent.ObservationType = Match3ObservationType.CompressedVisual;
var sensor = sensorComponent.CreateSensor();
var expectedShape = new[] { 3, 3, 2 + 3 };
Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
var expectedShape = new InplaceArray<int>(3, 3, 2 + 3);
Assert.AreEqual(expectedShape, sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionSpec().SensorCompressionType);
var concatenatedPngData = sensor.GetCompressedObservation();
var pathPrefix = "match3obs_special";

}
var expectedPng = LoadPNGs(pathPrefix, 2);
Assert.AreEqual(expectedPng, concatenatedPngData);
}
/// <summary>

}
return bytesOut.ToArray();
}
}
}

19
com.unity.ml-agents.extensions/Tests/Editor/Sensors/ChannelHotShapeTests.cs


1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 1 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 1);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}

1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 2 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 2);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}
[Test]

1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 3 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 3);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}

1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 6 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 6);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}
}

15
com.unity.ml-agents.extensions/Tests/Editor/Sensors/ChannelShapeTests.cs


1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 1 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 1);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}
[Test]

1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 2 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 2);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}
[Test]

1f, 1f, 10, 10, LayerMask.GetMask("Default"), false, colors);
gridSensor.Start();
int[] expectedShape = { 10, 10, 7 };
GridObsTestUtils.AssertArraysAreEqual(expectedShape, gridSensor.GetObservationShape());
var expectedShape = new InplaceArray<int>(10, 10, 7);
Assert.AreEqual(expectedShape, gridSensor.GetObservationSpec().Shape);
}
}
}

27
com.unity.ml-agents.extensions/Tests/Editor/Sensors/GridSensorTestUtils.cs


return duplicated;
}
/// <summary>
/// Asserts that 2 int arrays are the same
/// </summary>
/// <param name="expected">The expected array</param>
/// <param name="actual">The actual array</param>
public static void AssertArraysAreEqual(int[] expected, int[] actual)
{
Assert.AreEqual(expected.Length, actual.Length, "Lengths are not the same");
for (int i = 0; i < actual.Length; i++)
{
Assert.AreEqual(expected[i], actual[i], "Got " + Array2Str(actual) + ", expected " + Array2Str(expected));
}
}
/// <summary>
/// Asserts that 2 float arrays are the same
/// </summary>
/// <param name="expected">The expected array</param>
/// <param name="actual">The actual array</param>
public static void AssertArraysAreEqual(float[] expected, float[] actual)
{
Assert.AreEqual(expected.Length, actual.Length, "Lengths are not the same");
for (int i = 0; i < actual.Length; i++)
{
Assert.AreEqual(expected[i], actual[i], "Got " + Array2Str(actual) + ", expected " + Array2Str(expected));
}
}
/// <summary>
/// Asserts that the sub-arrays of the total array are equal to specific subarrays at specific subarray indicies and equal to a default everywhere else.

6
com.unity.ml-agents.extensions/Tests/Runtime/Sensors/ArticulationBodySensorTests.cs


0f, 0f, 0f, 1f // LocalSpaceRotations
};
SensorTestHelper.CompareObservation(sensor, expected);
Assert.AreEqual(expected.Length, sensorComponent.GetObservationShape()[0]);
Assert.AreEqual(expected.Length, sensorComponent.CreateSensor().GetObservationSpec().Shape[0]);
}
[Test]

#endif
};
SensorTestHelper.CompareObservation(sensor, expected);
Assert.AreEqual(expected.Length, sensorComponent.GetObservationShape()[0]);
Assert.AreEqual(expected.Length, sensorComponent.CreateSensor().GetObservationSpec().Shape[0]);
// Update the settings to only process joint observations
sensorComponent.Settings = new PhysicsSensorSettings

0f, // joint2.force
};
SensorTestHelper.CompareObservation(sensor, expected);
Assert.AreEqual(expected.Length, sensorComponent.GetObservationShape()[0]);
Assert.AreEqual(expected.Length, sensorComponent.CreateSensor().GetObservationSpec().Shape[0]);
}
}
}

6
com.unity.ml-agents.extensions/Tests/Runtime/Sensors/RigidBodySensorTests.cs


// The root body is ignored since it always generates identity values
// and there are no other bodies to generate observations.
var expected = new float[0];
Assert.AreEqual(expected.Length, sensorComponent.GetObservationShape()[0]);
Assert.AreEqual(expected.Length, sensorComponent.CreateSensor().GetObservationSpec().Shape[0]);
SensorTestHelper.CompareObservation(sensor, expected);
}

-1f, 1f, 0f, // Attached vel
0f, -1f, 1f // Leaf vel
};
Assert.AreEqual(expected.Length, sensorComponent.GetObservationShape()[0]);
Assert.AreEqual(expected.Length, sensorComponent.CreateSensor().GetObservationSpec().Shape[0]);
SensorTestHelper.CompareObservation(sensor, expected);
// Update the settings to only process joint observations

0f, 0f, 0f, // joint2.torque
};
SensorTestHelper.CompareObservation(sensor, expected);
Assert.AreEqual(expected.Length, sensorComponent.GetObservationShape()[0]);
Assert.AreEqual(expected.Length, sensorComponent.CreateSensor().GetObservationSpec().Shape[0]);
}
}

3
com.unity.ml-agents.extensions/package.json


"unity": "2019.4",
"description": "A source-only package for new features based on ML-Agents",
"dependencies": {
"com.unity.ml-agents": "2.0.0-exp.1"
"com.unity.ml-agents": "2.0.0-exp.1",
"com.unity.modules.physics": "1.0.0"
}
}

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


`WriteMask(int branch, IEnumerable<int> actionIndices)` was replaced with
`SetActionEnabled(int branch, int actionIndex, bool isEnabled)`. (#5060)
- IActuator now implements IHeuristicProvider. (#5110)
- `ISensor.GetObservationShape()` was removed, and `GetObservationSpec()` was added. (#5127)
- `ISensor.GetObservationShape()` was removed, and `GetObservationSpec()` was added. The `ITypedSensor`
and `IDimensionPropertiesSensor` interfaces were removed. (#5127)
- `ISensor.GetCompressionType()` was removed, and `GetCompressionSpec()` was added. The `ISparseChannelSensor`
interface was removed. (#5164)
- The abstract method `SensorComponent.GetObservationShape()` was no longer being called, so it has been removed. (#5172)
#### ml-agents / ml-agents-envs / gym-unity (Python)

- The `.onnx` models discrete action output now contains the discrete actions values and not the logits. Models created with this version will not be usable with previous versions of the package (#5080)
- Added ML-Agents package settings. (#5027)
- Make com.unity.modules.unityanalytics an optional dependency. (#5109)
- Make com.unity.modules.physics and com.unity.modules.physics2d optional dependencies. (#5112)
#### ml-agents / ml-agents-envs / gym-unity (Python)
### Bug Fixes

16
com.unity.ml-agents/Editor/RayPerceptionSensorComponentBaseEditor.cs


protected void OnRayPerceptionInspectorGUI(bool is3d)
{
#if !MLA_UNITY_PHYSICS_MODULE
if (is3d)
{
EditorGUILayout.HelpBox("The Physics Module is not currently present. " +
"Please add it to your project in order to use the Ray Perception APIs in the " +
$"{nameof(RayPerceptionSensorComponent3D)}", MessageType.Warning);
}
#endif
#if !MLA_UNITY_PHYSICS2D_MODULE
if (!is3d)
{
EditorGUILayout.HelpBox("The Physics2D Module is not currently present. " +
"Please add it to your project in order to use the Ray Perception APIs in the " +
$"{nameof(RayPerceptionSensorComponent3D)}", MessageType.Warning);
}
#endif
var so = serializedObject;
so.Update();

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


"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.modules.physics",
"expression": "1.0.0",
"define": "MLA_UNITY_PHYSICS_MODULE"
},
{
"name": "com.unity.modules.physics2d",
"expression": "1.0.0",
"define": "MLA_UNITY_PHYSICS2D_MODULE"
}
]
}

14
com.unity.ml-agents/Runtime/Agent.cs


internal class AgentVectorActuator : VectorActuator
{
public AgentVectorActuator(IActionReceiver actionReceiver,
IHeuristicProvider heuristicProvider,
ActionSpec actionSpec,
string name = "VectorActuator"
IHeuristicProvider heuristicProvider,
ActionSpec actionSpec,
string name = "VectorActuator"
) : base(actionReceiver, heuristicProvider, actionSpec, name)
{ }

/// <param name="reward">The new value of the reward.</param>
public void SetReward(float reward)
{
#if DEBUG
#endif
m_CumulativeReward += (reward - m_Reward);
m_Reward = reward;
}

/// <param name="increment">Incremental reward value.</param>
public void AddReward(float increment)
{
#if DEBUG
#endif
m_Reward += increment;
m_CumulativeReward += increment;
}

#if DEBUG
#endif
#if DEBUG
#endif
m_GroupReward += increment;
}

2
com.unity.ml-agents/Runtime/Analytics/Events.cs


return new EventObservationSpec
{
SensorName = sensor.GetName(),
CompressionType = sensor.GetCompressionType().ToString(),
CompressionType = sensor.GetCompressionSpec().SensorCompressionType.ToString(),
BuiltInSensorType = (int)builtInSensorType,
DimensionInfos = dimInfos,
};

18
com.unity.ml-agents/Runtime/Analytics/InferenceAnalytics.cs


const int k_MaxNumberOfElements = 1000;
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
#endif
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
#elif MLA_UNITY_ANALYTICS_MODULE
AnalyticsResult result = AnalyticsResult.UnsupportedPlatform;
if (result == AnalyticsResult.Ok)
{
s_EventRegistered = true;
}
#endif
#else // no editor, no analytics
s_EventRegistered = false;
#endif
return s_EventRegistered;
}

IList<IActuator> actuators
)
{
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
// The event shouldn't be able to report if this is disabled but if we know we're not going to report
// Lets early out and not waste time gathering all the data
if (!IsAnalyticsEnabled())

var data = GetEventForModel(nnModel, behaviorName, inferenceDevice, sensors, actionSpec, actuators);
// Note - to debug, use JsonUtility.ToJson on the event.
// Debug.Log(JsonUtility.ToJson(data, true));
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
#else
return;
#endif
}

29
com.unity.ml-agents/Runtime/Analytics/TrainingAnalytics.cs


namespace Unity.MLAgents.Analytics
{
internal class TrainingAnalytics
internal static class TrainingAnalytics
{
const string k_VendorKey = "unity.ml-agents";
const string k_TrainingEnvironmentInitializedEventName = "ml_agents_training_environment_initialized";

};
/// <summary>
/// Whether or not we've registered this particular event yet
/// </summary>
static bool s_EventsRegistered = false;
/// <summary>
/// Hourly limit for this event name
/// </summary>
const int k_MaxEventsPerHour = 1000;

const int k_MaxNumberOfElements = 1000;
private static bool s_SentEnvironmentInitialized;
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
/// <summary>
/// Whether or not we've registered this particular event yet
/// </summary>
static bool s_EventsRegistered = false;
#endif
private static Guid s_TrainingSessionGuid;

static bool EnableAnalytics()
internal static bool EnableAnalytics()
#if MLA_UNITY_ANALYTICS_MODULE
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
if (s_EventsRegistered)
{
return true;

#if UNITY_EDITOR
#else
return false;
#endif // UNITY_EDITOR
}
s_EventsRegistered = true;

IList<IActuator> actuators
)
{
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
if (!IsAnalyticsEnabled())
return;

// Debug.Log(
// $"Would send event {k_RemotePolicyInitializedEventName} with body {JsonUtility.ToJson(data, true)}"
// );
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
if (AnalyticsUtils.s_SendEditorAnalytics)
{
EditorAnalytics.SendEventWithLimit(k_RemotePolicyInitializedEventName, data);

[Conditional("MLA_UNITY_ANALYTICS_MODULE")]
public static void TrainingBehaviorInitialized(TrainingBehaviorInitializedEvent tbiEvent)
{
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
if (!IsAnalyticsEnabled())
return;

// Debug.Log(
// $"Would send event {k_TrainingBehaviorInitializedEventName} with body {JsonUtility.ToJson(tbiEvent, true)}"
// );
#if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE
#else
return;
#endif
}

44
com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs


var obsSpec = sensor.GetObservationSpec();
var shape = obsSpec.Shape;
ObservationProto observationProto = null;
var compressionType = sensor.GetCompressionType();
var compressionSpec = sensor.GetCompressionSpec();
var compressionType = compressionSpec.SensorCompressionType;
// Check capabilities if we need to concatenate PNGs
if (compressionType == SensorCompressionType.PNG && shape.Length == 3 && shape[2] > 3)
{

if (compressionType != SensorCompressionType.None && shape.Length == 3 && shape[2] > 3)
{
var trainerCanHandleMapping = Academy.Instance.TrainerCapabilities == null || Academy.Instance.TrainerCapabilities.CompressedChannelMapping;
var isTrivialMapping = IsTrivialMapping(sensor);
var isTrivialMapping = compressionSpec.IsTrivialMapping();
if (!trainerCanHandleMapping && !isTrivialMapping)
{
if (!s_HaveWarnedTrainerCapabilitiesMapping)

throw new UnityAgentsException(
$"GetCompressedObservation() returned null data for sensor named {sensor.GetName()}. " +
"You must return a byte[]. If you don't want to use compressed observations, " +
"return SensorCompressionType.None from GetCompressionType()."
"return CompressionSpec.Default() from GetCompressionSpec()."
CompressionType = (CompressionTypeProto)sensor.GetCompressionType(),
CompressionType = (CompressionTypeProto)sensor.GetCompressionSpec().SensorCompressionType,
var compressibleSensor = sensor as ISparseChannelSensor;
if (compressibleSensor != null)
if (compressionSpec.CompressedChannelMapping != null)
observationProto.CompressedChannelMapping.AddRange(compressibleSensor.GetCompressedChannelMapping());
observationProto.CompressedChannelMapping.AddRange(compressionSpec.CompressedChannelMapping);
}
}

};
}
internal static bool IsTrivialMapping(ISensor sensor)
{
var compressibleSensor = sensor as ISparseChannelSensor;
if (compressibleSensor is null)
{
return true;
}
var mapping = compressibleSensor.GetCompressedChannelMapping();
if (mapping == null)
{
return true;
}
// check if mapping equals zero mapping
if (mapping.Length == 3 && mapping.All(m => m == 0))
{
return true;
}
// check if mapping equals identity mapping
for (var i = 0; i < mapping.Length; i++)
{
if (mapping[i] != i)
{
return false;
}
}
return true;
}
#region Analytics
internal static TrainingEnvironmentInitializedEvent ToTrainingEnvironmentInitializedEvent(
this TrainingEnvironmentInitialized inputProto)

NumNetworkHiddenUnits = inputProto.NumNetworkHiddenUnits,
};
}
#endregion
#endregion
}
}

20
com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs


using Unity.Barracuda;
using System.Collections.Generic;
using System.Diagnostics;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Inference;
using Unity.MLAgents.Sensors;

/// </summary>
private bool m_AnalyticsSent;
/// <inheritdoc />
/// <summary>
/// Instantiate a BarracudaPolicy with the necessary objects for it to run.
/// </summary>
/// <param name="actionSpec">The action spec of the behavior.</param>
/// <param name="actuators">The actuators used for this behavior.</param>
/// <param name="model">The Neural Network to use.</param>
/// <param name="inferenceDevice">Which device Barracuda will run on.</param>
/// <param name="behaviorName">The name of the behavior.</param>
public BarracudaPolicy(
ActionSpec actionSpec,
IList<IActuator> actuators,

/// <inheritdoc />
public void RequestDecision(AgentInfo info, List<ISensor> sensors)
{
SendAnalytics(sensors);
m_AgentId = info.episodeId;
m_ModelRunner?.PutObservations(info, sensors);
}
[Conditional("MLA_UNITY_ANALYTICS_MODULE")]
void SendAnalytics(IList<ISensor> sensors)
{
if (!m_AnalyticsSent)
{
m_AnalyticsSent = true;

m_Actuators
);
}
m_AgentId = info.episodeId;
m_ModelRunner?.PutObservations(info, sensors);
}
/// <inheritdoc />

4
com.unity.ml-agents/Runtime/Policies/HeuristicPolicy.cs


/// Trivial implementation of the IList interface that does nothing.
/// This is only used for "writing" observations that we will discard.
/// </summary>
class NullList : IList<float>
internal class NullList : IList<float>
{
public IEnumerator<float> GetEnumerator()
{

{
foreach (var sensor in sensors)
{
if (sensor.GetCompressionType() == SensorCompressionType.None)
if (sensor.GetCompressionSpec().SensorCompressionType == SensorCompressionType.None)
{
m_ObservationWriter.SetTarget(m_NullList, sensor.GetObservationSpec(), 0);
sensor.Write(m_ObservationWriter);

14
com.unity.ml-agents/Runtime/Policies/RemotePolicy.cs


using System.Diagnostics;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Analytics;

string m_FullyQualifiedBehaviorName;
ActionSpec m_ActionSpec;
ActionBuffers m_LastActionBuffer;
private bool m_AnalyticsSent = false;
bool m_AnalyticsSent;
internal ICommunicator m_Communicator;

/// <inheritdoc />
public void RequestDecision(AgentInfo info, List<ISensor> sensors)
{
SendAnalytics(sensors);
m_AgentId = info.episodeId;
m_Communicator?.PutObservations(m_FullyQualifiedBehaviorNam