浏览代码

Merge branch 'master' into fod_generator_randomization_changes

/fod_generator_randomization_changes
Steven Borkman 4 年前
当前提交
b45e3ea8
共有 248 个文件被更改,包括 4786 次插入4500 次删除
  1. 1
      .gitignore
  2. 5
      .yamato/upm-ci-full.yml
  3. 7
      README.md
  4. 2
      TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset
  5. 64
      TestProjects/PerceptionHDRP/Assets/Scenes/SampleScene.unity
  6. 64
      TestProjects/PerceptionHDRP/Assets/Scenes/SampleSceneLensDistortion.unity
  7. 4
      TestProjects/PerceptionHDRP/Packages/manifest.json
  8. 20
      TestProjects/PerceptionHDRP/Packages/packages-lock.json
  9. 3
      TestProjects/PerceptionHDRP/ProjectSettings/ProjectSettings.asset
  10. 4
      TestProjects/PerceptionHDRP/ProjectSettings/ProjectVersion.txt
  11. 2
      TestProjects/PerceptionURP/Assets/IdLabelConfig.asset
  12. 18
      TestProjects/PerceptionURP/Packages/packages-lock.json
  13. 1
      TestProjects/PerceptionURP/ProjectSettings/ProjectSettings.asset
  14. 4
      TestProjects/PerceptionURP/ProjectSettings/ProjectVersion.txt
  15. 2
      TestProjects/PerceptionURP/ProjectSettings/QualitySettings.asset
  16. 88
      com.unity.perception/CHANGELOG.md
  17. 108
      com.unity.perception/Documentation~/Randomization/Scenarios.md
  18. 17
      com.unity.perception/Documentation~/Schema/Synthetic_Dataset_Schema.md
  19. 999
      com.unity.perception/Documentation~/Tutorial/Images/all_back_rands.png
  20. 501
      com.unity.perception/Documentation~/Tutorial/Images/background_randomizer.png
  21. 590
      com.unity.perception/Documentation~/Tutorial/Images/fixedscenarioempty.png
  22. 244
      com.unity.perception/Documentation~/Tutorial/Images/light_rand_1.png
  23. 807
      com.unity.perception/Documentation~/Tutorial/Images/light_rand_2.png
  24. 999
      com.unity.perception/Documentation~/Tutorial/Images/pc_labelers_added.png
  25. 999
      com.unity.perception/Documentation~/Tutorial/Images/pclabelconfigsadded.png
  26. 429
      com.unity.perception/Documentation~/Tutorial/Images/perc_comp.png
  27. 999
      com.unity.perception/Documentation~/Tutorial/Images/randomizers_all.png
  28. 41
      com.unity.perception/Documentation~/Tutorial/Phase1.md
  29. 32
      com.unity.perception/Documentation~/Tutorial/Phase2.md
  30. 21
      com.unity.perception/Documentation~/Tutorial/Phase3.md
  31. 5
      com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs
  32. 1
      com.unity.perception/Editor/Randomization/Editors/PerceptionEditorAnalytics.cs
  33. 25
      com.unity.perception/Editor/Randomization/Editors/RandomizerTagEditor.cs
  34. 280
      com.unity.perception/Editor/Randomization/Editors/RunInUnitySimulationWindow.cs
  35. 57
      com.unity.perception/Editor/Randomization/Editors/ScenarioBaseEditor.cs
  36. 8
      com.unity.perception/Editor/Randomization/Uss/Styles.uss
  37. 26
      com.unity.perception/Editor/Randomization/Utilities/StaticData.cs
  38. 27
      com.unity.perception/Editor/Randomization/Utilities/UIElementsEditorUtilities.cs
  39. 48
      com.unity.perception/Editor/Randomization/Uxml/RunInUnitySimulationWindow.uxml
  40. 7
      com.unity.perception/Editor/Randomization/Uxml/ScenarioBaseElement.uxml
  41. 6
      com.unity.perception/Editor/Randomization/VisualElements/Parameter/CategoricalOptionElement.cs
  42. 49
      com.unity.perception/Editor/Randomization/VisualElements/Parameter/ParameterElement.cs
  43. 5
      com.unity.perception/Editor/Randomization/VisualElements/Randomizer/AddRandomizerMenu.cs
  44. 8
      com.unity.perception/Editor/Randomization/VisualElements/Randomizer/RandomizerElement.cs
  45. 21
      com.unity.perception/Editor/Randomization/VisualElements/Randomizer/RandomizerList.cs
  46. 1
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBox3DLabeler.cs
  47. 5
      com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs
  48. 2
      com.unity.perception/Runtime/GroundTruth/Labelers/CocoKeypointTemplate.asset
  49. 9
      com.unity.perception/Runtime/GroundTruth/Labelers/InstanceSegmentationLabeler.cs
  50. 7
      com.unity.perception/Runtime/GroundTruth/Labelers/JointLabel.cs
  51. 1
      com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs
  52. 76
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
  53. 9
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs
  54. 2
      com.unity.perception/Runtime/Randomization/Parameters/CategoricalParameter.cs
  55. 2
      com.unity.perception/Runtime/Randomization/Parameters/CategoricalParameterBase.cs
  56. 2
      com.unity.perception/Runtime/Randomization/Parameters/NumericParameter.cs
  57. 2
      com.unity.perception/Runtime/Randomization/Parameters/Parameter.cs
  58. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/AnimationClipParameter.cs
  59. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/GameObjectParameter.cs
  60. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/MaterialParameter.cs
  61. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/StringParameter.cs
  62. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/Texture2DParameter.cs
  63. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/BooleanParameter.cs
  64. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsva.cs
  65. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsvaCategoricalParameter.cs
  66. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsvaParameter.cs
  67. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorRgbCategoricalParameter.cs
  68. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorRgbParameter.cs
  69. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/FloatParameter.cs
  70. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/IntegerParameter.cs
  71. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector2Parameter.cs
  72. 3
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector3Parameter.cs
  73. 2
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector4Parameter.cs
  74. 2
      com.unity.perception/Runtime/Randomization/Randomizers/AddRandomizerMenuAttribute.cs
  75. 109
      com.unity.perception/Runtime/Randomization/Randomizers/Randomizer.cs
  76. 2
      com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Randomizers/BackgroundObjectPlacementRandomizer.cs
  77. 2
      com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Randomizers/ForegroundObjectPlacementRandomizer.cs
  78. 66
      com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Utilities/GameObjectOneWayCache.cs
  79. 1
      com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Utilities/PoissonDiskSampling.cs
  80. 28
      com.unity.perception/Runtime/Randomization/Randomizers/RandomizerTag.cs
  81. 8
      com.unity.perception/Runtime/Randomization/Randomizers/RandomizerTagManager.cs
  82. 2
      com.unity.perception/Runtime/Randomization/Samplers/FloatRange.cs
  83. 2
      com.unity.perception/Runtime/Randomization/Samplers/ISampler.cs
  84. 2
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs
  85. 2
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/ConstantSampler.cs
  86. 2
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/NormalSampler.cs
  87. 2
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/UniformSampler.cs
  88. 6
      com.unity.perception/Runtime/Randomization/Scenarios/FixedLengthScenario.cs
  89. 206
      com.unity.perception/Runtime/Randomization/Scenarios/Scenario.cs
  90. 506
      com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs
  91. 2
      com.unity.perception/Runtime/Randomization/Scenarios/ScenarioConstants.cs
  92. 45
      com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenario.cs
  93. 2
      com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenarioConstants.cs
  94. 30
      com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs
  95. 4
      com.unity.perception/Tests/Editor/RandomizerEditorTests.cs
  96. 9
      com.unity.perception/Tests/Runtime/GroundTruthTests/GroundTruthTestBase.cs
  97. 29
      com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs
  98. 7
      com.unity.perception/Tests/Runtime/GroundTruthTests/VisualizationTests.cs
  99. 409
      com.unity.perception/Tests/Runtime/GroundTruthTests/KeypointGroundTruthTests.cs
  100. 2
      com.unity.perception/Tests/Runtime/Randomization/RandomizerTests/ExampleTransformRandomizer.cs

1
.gitignore


**/Build/**
**/Builds/**
/utr
*.user

5
.yamato/upm-ci-full.yml


{% endfor %}
{% endfor %}
{% endfor %}
{% for editor in coverage_editors %}
- .yamato/upm-ci-testprojects.yml#codecoverage_windows_editmode_{{editor.version}}
{% endfor %}
{% for editor in per_commit_editors %}
{% for project in projects %}
- .yamato/upm-ci-testprojects.yml#{{project.name}}_windows_standalone_{{editor.version}}

7
README.md


> com.unity.perception is in active development. Its features and API are subject to significant change as development progresses.
# Perception Package (Unity Computer Vision)
# Perception Package ([Unity Computer Vision](https://unity.com/computer-vision))
Visit the [Unity Computer Vision](https://unity.com/computer-vision) page for more information on our tools and offerings!
## Getting Started

**[Perception Tutorial](com.unity.perception/Documentation~/Tutorial/TUTORIAL.md)**
Detailed instructions covering all the important steps from installing Unity Editor, to creating your first computer vision data generation project, building a randomized Scene, and generating large-scale synthetic datasets by leveraging the power of Unity Simulation. No prior Unity experience required.
**[Human Pose Labeling and Randomization Tutorial](com.unity.perception/Documentation~/HPTutorial/TUTORIAL.md)**
Step by step instructions for using the keypoint, pose, and animation randomization tools included in the Perception package. It is recommended that you finish Phase 1 of the Perception Tutorial above before starting this tutorial.
## Documentation
In-depth documentation on individual components of the package.

2
TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset


id: 3
- label: Terrain
id: 4
- label: Character
id: 5
autoAssignIds: 1
startingLabelId: 1

64
TestProjects/PerceptionHDRP/Assets/Scenes/SampleScene.unity


m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 12

debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &117484506
GameObject:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 117484508}
- component: {fileID: 117484507}
m_Layer: 0
m_Name: StaticLightingSky
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &117484507
MonoBehaviour:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 117484506}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 441482e8936e35048a1dffac814e3ef8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Profile: {fileID: 0}
m_StaticLightingSkyUniqueID: 0
m_SkySettings: {fileID: 0}
m_SkySettingsFromProfile: {fileID: 0}
--- !u!4 &117484508
Transform:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 117484506}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &411238276
GameObject:
m_ObjectHideFlags: 0

m_EditorClassIdentifier:
labels:
- Crate
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!65 &411238278
BoxCollider:
m_ObjectHideFlags: 0

m_EditorClassIdentifier:
labels:
- Cube
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!65 &934158984
BoxCollider:
m_ObjectHideFlags: 0

m_Name:
m_EditorClassIdentifier:
description: The main camera
period: 0.0166
startTime: 0
firstCaptureFrame: 0
captureTriggerMode: 0
manualSensorAffectSimulationTiming: 0
simulationDeltaTime: 0.0166
framesBetweenCaptures: 0
m_Labelers:
- id: 0
- id: 1

m_EditorClassIdentifier:
labels:
- Terrain
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!1 &1640252278
GameObject:
m_ObjectHideFlags: 0

m_EditorClassIdentifier:
labels:
- Box
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!65 &1640252280
BoxCollider:
m_ObjectHideFlags: 0

64
TestProjects/PerceptionHDRP/Assets/Scenes/SampleSceneLensDistortion.unity


m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 12

m_EditorClassIdentifier:
labels:
- Crate
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!65 &411238278
BoxCollider:
m_ObjectHideFlags: 0

m_EditorClassIdentifier:
labels:
- Cube
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!65 &464025706
BoxCollider:
m_ObjectHideFlags: 0

showAdditionalSettings: 0
m_AreaLightEmissiveMeshShadowCastingMode: 0
m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0
--- !u!1 &746670481
GameObject:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 746670483}
- component: {fileID: 746670482}
m_Layer: 0
m_Name: StaticLightingSky
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &746670482
MonoBehaviour:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 746670481}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 441482e8936e35048a1dffac814e3ef8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Profile: {fileID: 0}
m_StaticLightingSkyUniqueID: 0
m_SkySettings: {fileID: 0}
m_SkySettingsFromProfile: {fileID: 0}
--- !u!4 &746670483
Transform:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 746670481}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &963194225
GameObject:
m_ObjectHideFlags: 0

m_Name:
m_EditorClassIdentifier:
description: The main camera
period: 0.0166
startTime: 0
firstCaptureFrame: 0
captureTriggerMode: 0
manualSensorAffectSimulationTiming: 0
simulationDeltaTime: 0.0166
framesBetweenCaptures: 0
m_Labelers:
- id: 0
- id: 1

priority: 0
blendDistance: 0
weight: 1
sharedProfile: {fileID: 11400000, guid: 6886180e6c51dac4f9ea4d9bcdaa6e13, type: 2}
sharedProfile: {fileID: 0}
--- !u!4 &1562495300
Transform:
m_ObjectHideFlags: 0

m_EditorClassIdentifier:
labels:
- Box
useAutoLabeling: 0
autoLabelingSchemeType:
--- !u!65 &1640252280
BoxCollider:
m_ObjectHideFlags: 0

4
TestProjects/PerceptionHDRP/Packages/manifest.json


{
"dependencies": {
"com.unity.collab-proxy": "1.2.16",
"com.unity.ext.nunit": "1.0.5",
"com.unity.ext.nunit": "1.0.6",
"com.unity.ide.rider": "1.1.4",
"com.unity.ide.vscode": "1.2.3",
"com.unity.package-validation-suite": "0.9.1-preview",

"com.unity.simulation.capture": "0.0.10-preview.16",
"com.unity.simulation.core": "0.0.10-preview.21",
"com.unity.test-framework": "1.1.19",
"com.unity.test-framework": "1.1.20",
"com.unity.testtools.codecoverage": "0.2.2-preview",
"com.unity.textmeshpro": "2.0.1",
"com.unity.ugui": "1.0.0",

20
TestProjects/PerceptionHDRP/Packages/packages-lock.json


"url": "https://packages.unity.com"
},
"com.unity.ext.nunit": {
"version": "1.0.5",
"version": "1.0.6",
"depth": 0,
"source": "registry",
"dependencies": {},

"com.unity.burst": "1.3.9",
"com.unity.entities": "0.8.0-preview.8",
"com.unity.simulation.client": "0.0.10-preview.10",
"com.unity.simulation.capture": "0.0.10-preview.16",
"com.unity.simulation.core": "0.0.10-preview.21"
"com.unity.simulation.capture": "0.0.10-preview.19",
"com.unity.simulation.core": "0.0.10-preview.22"
}
},
"com.unity.platforms": {

"url": "https://packages.unity.com"
},
"com.unity.simulation.capture": {
"version": "0.0.10-preview.16",
"depth": 0,
"version": "0.0.10-preview.19",
"depth": 1,
"com.unity.simulation.core": "0.0.10-preview.21"
"com.unity.simulation.core": "0.0.10-preview.22"
},
"url": "https://packages.unity.com"
},

"url": "https://packages.unity.com"
},
"com.unity.simulation.core": {
"version": "0.0.10-preview.21",
"depth": 0,
"version": "0.0.10-preview.22",
"depth": 1,
"version": "1.1.19",
"version": "1.1.20",
"com.unity.ext.nunit": "1.0.5",
"com.unity.ext.nunit": "1.0.6",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
},

3
TestProjects/PerceptionHDRP/ProjectSettings/ProjectSettings.asset


metalEditorSupport: 1
metalAPIValidation: 1
iOSRenderExtraFrameOnPause: 0
iosCopyPluginsCodeInsteadOfSymlink: 0
appleDeveloperTeamID:
iOSManualSigningProvisioningProfileID:
tvOSManualSigningProvisioningProfileID:

additionalIl2CppArgs:
scriptingRuntimeVersion: 1
gcIncremental: 0
assemblyVersionValidation: 1
gcWBarrierValidation: 0
apiCompatibilityLevelPerPlatform:
Standalone: 6

XboxOneCapability: []
XboxOneGameRating: {}
XboxOneIsContentPackage: 0
XboxOneEnhancedXboxCompatibilityMode: 0
XboxOneEnableGPUVariability: 1
XboxOneSockets: {}
XboxOneSplashScreen: {fileID: 0}

4
TestProjects/PerceptionHDRP/ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2019.4.16f1
m_EditorVersionWithRevision: 2019.4.16f1 (e05b6e02d63e)
m_EditorVersion: 2019.4.19f1
m_EditorVersionWithRevision: 2019.4.19f1 (ca5b14067cec)

2
TestProjects/PerceptionURP/Assets/IdLabelConfig.asset


id: 3
- label: Terrain
id: 4
- label: Character
id: 5
autoAssignIds: 1
startingLabelId: 1

18
TestProjects/PerceptionURP/Packages/packages-lock.json


"url": "https://packages.unity.com"
},
"com.unity.ext.nunit": {
"version": "1.0.5",
"depth": 1,
"version": "1.0.6",
"depth": 2,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"

"com.unity.burst": "1.3.9",
"com.unity.entities": "0.8.0-preview.8",
"com.unity.simulation.client": "0.0.10-preview.10",
"com.unity.simulation.capture": "0.0.10-preview.16",
"com.unity.simulation.core": "0.0.10-preview.21"
"com.unity.simulation.capture": "0.0.10-preview.19",
"com.unity.simulation.core": "0.0.10-preview.22"
}
},
"com.unity.platforms": {

"url": "https://packages.unity.com"
},
"com.unity.simulation.capture": {
"version": "0.0.10-preview.16",
"depth": 0,
"version": "0.0.10-preview.19",
"depth": 1,
"com.unity.simulation.core": "0.0.10-preview.21"
"com.unity.simulation.core": "0.0.10-preview.22"
},
"url": "https://packages.unity.com"
},

"url": "https://packages.unity.com"
},
"com.unity.simulation.core": {
"version": "0.0.10-preview.21",
"depth": 0,
"version": "0.0.10-preview.22",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"

1
TestProjects/PerceptionURP/ProjectSettings/ProjectSettings.asset


additionalIl2CppArgs:
scriptingRuntimeVersion: 1
gcIncremental: 0
assemblyVersionValidation: 1
gcWBarrierValidation: 0
apiCompatibilityLevelPerPlatform: {}
m_RenderingPath: 1

4
TestProjects/PerceptionURP/ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2019.4.16f1
m_EditorVersionWithRevision: 2019.4.16f1 (e05b6e02d63e)
m_EditorVersion: 2019.4.19f1
m_EditorVersionWithRevision: 2019.4.19f1 (ca5b14067cec)

2
TestProjects/PerceptionURP/ProjectSettings/QualitySettings.asset


skinWeights: 2
textureQuality: 0
anisotropicTextures: 1
antiAliasing: 0
antiAliasing: 2
softParticles: 0
softVegetation: 1
realtimeReflectionProbes: 1

88
com.unity.perception/CHANGELOG.md


### Upgrade Notes
All appearances of the term `KeyPoint` have been renamed to `Keypoint`. Therefore, after upgrading to this version, if you have code that relies on any renamed types or names, make sure to alter your code to reflect the new names.
Added error message when missing Randomizer scripts are detected
Scenario serialization has been updated to include scalar values on randomizers and parameters.
Added new ScenarioBase virtual lifecycle hooks: OnAwake, OnStart, OnComplete, and OnIdle.
Keypoint occlusion has been added, no keypoint information will be recorded for a labeled asset completely out of the camera's frustum.
New keypoint tests have been added to test keypoint state.
The color of keypoints and connections are now reported in the annotation definition json file for keypoint templates.
The PerceptionScenario abstract class has been added to abstract perception data capture specific functionality from the vanilla scenario lifecycle.
Renamed all appearances of the term `KeyPoint` within types and names to `Keypoint`.
ScenarioBase's Awake, Start, and Update methods are now private. The newly added virtual lifecycle hooks are to be used as replacements.
Improved Run Unity Simulation window UI.
The Run Unity Simulation window now accepts option scenario JSON configurations to override existing scenario editor settings.
ScenarioBase's Get and Create randomizer methods have been augmented or replaced with more generic list index style accessors.
The scenario inspector buttons serialize and deserialize have been refactored to open a file explorer generate and import JSON configurations.
Randomizer tags now use OnEnable and OnDisable to manage lifecycle. This allows the user to toggle them on and off in the editor.
The randomizer methods OnCreate(), OnStartRunning(), and OnStopRunning() are now deprecated and have been replaced with OnAwake(), OnEnable() and OnDisable() respectively to better reflect the existing MonoBehaviour lifecycle methods.
### Deprecated
### Removed

Fixed a null reference error that appeared when adding options to categorical parameters.
Fixed ground truth not properly produced when there are other disabled PerceptionCameras present. Note: this does not yet add support for multiple enabled PerceptionCameras.
Fixed exception when rendering inspector for randomizers with private serialized fields
Fixed an issue preventing a user from adding more options to a Categorical Parameter's list of options with the 'Add Folder' button. 'Add Folder' now correctly appends the contents of the new folder on the list.
Fixed a bug where uniform probabilities were not properly reset upon adding or removing options from a Categorical Parameter's list of options.
Fixed keypoints being reporeted in wrong locations on the first frame an object is visible.
## [0.7.0-preview.2] - 2021-02-08
### Upgrade Notes
### Known Issues
### Added
Added Register() and Unregister() methods to the RandomizerTag API so users can implement RandomizerTag compatible GameObject caching
### Changed
Switched accessibility of scenario MonoBehaviour lifecycle functions (Awake, Start, Update) from private to protected to enable users to define their own overrides when deriving the Scenario class.
The GameObjectOneWayCache has been made public for users to cache GameObjects within their own custom Randomizers.
### Deprecated
### Removed
### Fixed
Fixed the math offsetting the iteration index of each Unity Simulation instance directly after they deserialize their app-params.
The RandomizerTagManager now uses a LinkedHashSet data structure to register tags to preserve insertion order determinism in Unity Simulation.
GameObjectOneWayCache now correctly registers and unregisters RandomizerTags on cached GameObjects.
#### Randomization Namespace Change
The Randomization toolset has been moved out of the Experimental namespace. After upgrading to this version of the Perception package, please follow these steps:
* Replace all references to `UnityEngine.Experimental.Perception.Randomization` with `UnityEngine.Perception.Randomization` in your C# code.
* Open your Unity Scene file in a text editor and replace all mentions of `UnityEngine.Experimental.Perception.Randomization` with `UnityEngine.Perception.Randomization`, and save the file.
#### Random Seed Generation
Replace usages of `ScenarioBase.GenerateRandomSeed()` with `SamplerState.NextRandomState()` in your custom Randomizer code.
#### Sampler Ranges
#### Tag Querying
The `RandomizerTagManager.Query<T>` function now returns the tag object itself instead of the GameObject it is attached to. You will need to slightly modify your custom Randomizers to accommodate this change. Please refer to the included sample Randomizers as examples.
### Known Issues

Semantic Segmentation Labeler now places data in folders with randomized filenames.
The uniform toggle on Categorical Parameters will now reset the Parameter's probability weights to be uniform.
Reorganized Perception MonoBehaviour paths within the AddComponentMenu.
Upgraded the Unity Simulation Capture package dependency to 0.0.10-preview.18 and Unity Simulation Core to 0.0.10-preview.22
### Deprecated

108
com.unity.perception/Documentation~/Randomization/Scenarios.md


Scenarios have three responsibilities:
1. Controlling the execution flow of your simulation
2. Defining a list of Randomizers
3. Defining constants that can be configured externally from a built Unity player
2. Organizing a list of Randomizers
3. Defining settings that can be configured externally from a built Unity player
## Scenario Lifecycle Hooks
Scenarios have a number of lifecycle hooks that are called during execution. Below is a diagram visualizing the sequence of operations run by a typical scenario:
<p align="center">
<img src="Images/scenario-lifecycle-diagram.png" width="600"/>
</p>
## JSON Configuration
Scenarios can be serialized to JSON, modified, and imported at runtime to configure simulation behavior even after a Unity player has been built. The following scenario settings can be serialized by default using the "Generate JSON Config" button on the scenario inspector:
1. Scenario constants
2. String, numeric, and boolean fields on Randomizers and Parameters
3. Constant, Uniform, and Normal sampler configurations
Here is an example of how to load a Scenario JSON configuration into a Windows Unity player using the `--scenario-config-file` flag:
`.\PerceptionTutorial.exe --scenario-config-file scenarioConfiguration.json`
NOTE: To execute a Scenario using the Run in Unity Simulation window, the Scenario class must implement the UnitySimulationScenario class.
4. **Main Scene** - The Unity scene to execute
5. **Scenario** - The Scenario to execute
6. **Sys-Param** - The system parameters or the hardware configuration of Unity Simulation worker instances to execute the Scenario with. Determines per instance specifications such as the number of CPU cores, amount of memory, and presence of a GPU for accelerated execution.
4. **Sys-Param** - The system parameters or the hardware configuration of Unity Simulation worker instances to execute the Scenario with. Determines per instance specifications such as the number of CPU cores, amount of memory, and presence of a GPU for accelerated execution.
5. **Json Configuration** - This field is optional. You can select a json scenario configuration within your project to configure your Unity Simulation run instead of using the Scenario settings presently configured in the Editor.
NOTE: To execute a Scenario using the Run in Unity Simulation window, the Scenario class must implement the UnitySimulationScenario class.
## Custom Scenarios
## Implementing Custom Scenarios
1. **isIterationComplete** - determines the conditions that cause the end of a Scenario Iteration
2. **isScenarioComplete** - determines the conditions that cause the end of a Scenario
1. **isScenarioReadyToStart** - defines the conditions that determine when a Scenario can begin iterating
1. **isIterationComplete** - defines the conditions that determine the end of a Scenario iteration
2. **isScenarioComplete** - defines the conditions that determine the a Scenario to stop iterating
## JSON Configuration
Scenarios can be serialized to JSON, modified, and reimported at runtime to configure simulation behavior even after a Unity player has been built. Constants and Randomizer Sampler settings are the two primary sections generated when serializing a Scenario. Note that currently, only numerical samplers are serialized. Below is the contents of a JSON configuration file created when serializing the Scenario used in Phase 1 of the [Perception Tutorial](../Tutorial/TUTORIAL.md):
```
{
"constants": {
"framesPerIteration": 1,
"totalIterations": 100,
"instanceCount": 1,
"instanceIndex": 0,
"randomSeed": 123456789
},
"randomizers": {
"HueOffsetRandomizer": {
"hueOffset": {
"value": {
"range": {
"minimum": -180.0,
"maximum": 180.0
}
}
}
},
"RotationRandomizer": {
"rotation": {
"x": {
"range": {
"minimum": 0.0,
"maximum": 360.0
}
},
"y": {
"range": {
"minimum": 0.0,
"maximum": 360.0
}
},
"z": {
"range": {
"minimum": 0.0,
"maximum": 360.0
}
}
}
}
}
}
```
### Abstract Scenario Classes
There are a few abstract scenario classes to choose from depending on your requirements when deriving a custom scenario. Below is a list of these options and when it is appropriate to derive them for your use case:
1. **Scenario<T>** - This is the most basic scenario class to derive if only the basic scenario lifecycle coordination tooling is necessary
2. **PerceptionScenario<T>** - The perception scenario abstract class introduces some useful functionality for Scenarios that intend to utilize the Perception package's data capture tooling to generate datasets.
3. **UnitySimulationScenario<T>** - This abstract Scenario class is useful for implementing custom perception Scenarios that are compatible with the "Run in Unity Simulation Window." The FixedLengthScenario class is an example of a Scenario deriving from the UnitySimulationScenario class.
### Constants
Constants can include properties such as starting Iteration value or total Iteration count, and you can always add your own custom constants. Below is an example of the Constants class used in the `FixedLengthScenario` class:
### Scenario Constants
Constants include properties such as starting iteration value or total iteration count that configure the lifecycle settings of the scenario. By deriving your own constants class you can add your own custom Scenario settings for configuring different scenario properties. Below is an example of the Constants class used in the `FixedLengthScenario` class:
```
[Serializable]
public class Constants : UnitySimulationScenarioConstants

```
There are a few key things to note here:
1. The Constants class will need to inherit from `UnitySimulationScenarioConstants` to be compatible with the Run in Unity Simulation window. Deriving from `UnitySimulationScenarioConstants` will add a few key properties to the Constants class that are needed to coordinate a Unity Simulation run.
2. Make sure to include the `[Serializable]` attribute on a constant class. This will ensure that the Constants can be manipulated from the Unity inspector.
1. The Constants class will need to inherit from `UnitySimulationScenarioConstants` to be compatible with the Run in Unity Simulation window. Deriving from `UnitySimulationScenarioConstants` will add a few key properties to the Constants class that are needed to coordinate a Unity Simulation run. If running in Unity Simulation is not a requirement, a new scenario constants class can derive from the base ScenarioConstants class instead.
2. Make sure to include the `[Serializable]` attribute on a constant class. This will ensure that the Constants can be properly configured from the Unity inspector.
Follow the instructions below to generate a Scenario configuration file to modify your Scenario Constants and Randomizers in a built player:
1. Click the _**Serialize Constants**_ button in the Scenario's inspector window. This will generate a `scenario_configuration.json` file and place it in the project's Assets/StreamingAssets folder.
2. Build your player. The new player will have a [ProjectName]_Data/StreamingAssets folder. A copy of the `scenario_configuration.json` file previously constructed in the editor will be found in this folder.
3. Change the contents of the `scenario_configuration.json` file. Any running player thereafter will utilize the newly authored values.

17
com.unity.perception/Documentation~/Schema/Synthetic_Dataset_Schema.md


Keypoint data, commonly used for human pose estimation. A keypoint capture is associated to a template that defines the keypoints (see annotation.definition file).
Each keypoint record maps a tuple of (instance, label) to template, pose, and an array of keypoints. A keypoint will exist in this record for each keypoint defined in the template file.
If a given keypoint doesn't exist in the labeled gameobject, then that keypoint will have a state value of 0; if it does exist then it will have a keypoint value of 2.
If a given keypoint doesn't exist in the labeled gameobject, then that keypoint will have a state value of 0; if it exists but is not visible, it will have a state value of 1,
if it exists and is visible it will have a state value of 2.
```
keypoints {
label_id: <int> -- Integer identifier of the label

index: <int> -- Index of keypoint in template
x: <float> -- X pixel coordinate of keypoint
y: <float> -- Y pixel coordinate of keypoint
state: <int> -- 0: keypoint does not exist, 2 keypoint exists
state: <int> -- 0: keypoint does not exist, 1 keypoint exists but is not visible, 2 keypoint exists and is visible
}, ...
]
}

{
label: <str> -- The label of the joint
index: <int> -- The index of the joint
color { -- [Optional] The color to use for the visualization of the keypoint
r: <float> -- Value from 0 to 1 for the red channel
g: <float> -- Value from 0 to 1 for the green channel
b: <float> -- Value from 0 to 1 for the blue channel
a: <float> -- Value from 0 to 1 for the alpha channel
}
}, ...
]
skeleton [ -- Array of skeletal connections (which joints have connections between one another) defined in this template

color { -- [Optional] The color to use for the visualization of the bone
r: <float> -- Value from 0 to 1 for the red channel
g: <float> -- Value from 0 to 1 for the green channel
b: <float> -- Value from 0 to 1 for the blue channel
a: <float> -- Value from 0 to 1 for the alpha channel
}
}, ...
]
}

999
com.unity.perception/Documentation~/Tutorial/Images/all_back_rands.png
文件差异内容过多而无法显示
查看文件

501
com.unity.perception/Documentation~/Tutorial/Images/background_randomizer.png

之前 之后
宽度: 824  |  高度: 510  |  大小: 88 KiB

590
com.unity.perception/Documentation~/Tutorial/Images/fixedscenarioempty.png

之前 之后
宽度: 864  |  高度: 1022  |  大小: 116 KiB

244
com.unity.perception/Documentation~/Tutorial/Images/light_rand_1.png

之前 之后
宽度: 846  |  高度: 178  |  大小: 35 KiB

807
com.unity.perception/Documentation~/Tutorial/Images/light_rand_2.png

之前 之后
宽度: 826  |  高度: 566  |  大小: 75 KiB

999
com.unity.perception/Documentation~/Tutorial/Images/pc_labelers_added.png
文件差异内容过多而无法显示
查看文件

999
com.unity.perception/Documentation~/Tutorial/Images/pclabelconfigsadded.png
文件差异内容过多而无法显示
查看文件

429
com.unity.perception/Documentation~/Tutorial/Images/perc_comp.png

之前 之后
宽度: 866  |  高度: 628  |  大小: 86 KiB

999
com.unity.perception/Documentation~/Tutorial/Images/randomizers_all.png
文件差异内容过多而无法显示
查看文件

41
com.unity.perception/Documentation~/Tutorial/Phase1.md


In this phase of the Perception tutorial, you will start from downloading and installing Unity Editor and the Perception package. You will then use our sample assets and provided components to easily generate a synthetic dataset for training an object-detection model.
Through-out the tutorial, lines starting with bullet points followed by **":green_circle: Action:"** denote the individual actions you will need to perform in order to progress through the tutorial. This is while non-bulleted lines will provide additional context and explanation around the actions. If in a hurry, you can just follow the actions!
Through-out the tutorial, lines starting with bullet points followed by **":green_circle: Action:"** denote the individual actions you will need to perform in order to progress through the tutorial. This is while the rest of the text will provide additional context and explanation around the actions. If in a hurry, you can just follow the actions!
Steps included this phase of the tutorial:
- [Step 1: Download Unity Editor and Create a New Project](#step-1)
- [Step 2: Download the Perception Package and Import Samples](#step-2)
- [Step 3: Setup a Scene for Your Perception Simulation](#step-3)
- [Step 4: Specify Ground-Truth and Set Up Object Labels](#step-4)
- [Step 5: Set Up Background Randomizers](#step-5)
- [Step 6: Set Up Foreground Randomizers](#step-6)
- [Step 7: Inspect Generated Synthetic Data](#step-7)
- [Step 8: Verify Data Using Dataset Insights](#step-8)
Steps included in this phase of the tutorial:
* [Step 1: Download Unity Editor and Create a New Project](#step-1)
* [Step 2: Download the Perception Package and Import Samples](#step-2)
* [Step 3: Setup a Scene for Your Perception Simulation](#step-3)
* [Step 4: Specify Ground-Truth and Set Up Object Labels](#step-4)
* [Step 5: Set Up Background Randomizers](#step-5)
* [Step 6: Set Up Foreground Randomizers](#step-6)
* [Step 7: Inspect Generated Synthetic Data](#step-7)
* [Step 8: Verify Data Using Dataset Insights](#step-8)
### <a name="step-1">Step 1: Download Unity Editor and Create a New Project</a>
* **:green_circle: Action**: Navigate to [this](https://unity3d.com/get-unity/download/archive) page to download and install the latest version of **Unity Editor 2019.4.x**. (The tutorial has not yet been fully tested on newer versions.)

* **:green_circle: Action**: **(For URP projects only)** The _**Project**_ tab contains a search bar; use it to find the file named `ForwardRenderer.asset`, as shown below:
<p align="center">
<img src="Images/forward_renderer.png"/>
<img src="Images/forward_renderer.png" width="800"/>
</p>
* **:green_circle: Action**: **(For URP projects only)** Click on the found file to select it. Then, from the _**Inspector**_ tab of the editor, click on the _**Add Renderer Feature**_ button, and select _**Ground Truth Renderer Feature**_ from the dropdown menu:

* **:green_circle: Action**: Click on `Main Camera` and in the _**Inspector**_ tab, modify the camera's `Position`, `Rotation`, `Projection` and `Size` to match the screenshot below. (Note that `Size` only becomes available once you set `Projection` to `Orthographic`)
<p align="center">
<img src="Images/camera_prep.png"/>
<img src="Images/camera_prep.png" width = "900"/>
</p>

<img src="Images/perc_comp.png" width="400"/>
</p>
If you hover your mouse pointer over each of the fields shown (e.g. `Capture Interval`), you will see a tooltip popup with an explanation on what the item controls. You may see a warning at the bottom of this UI regarding asynchronous shader compilation. If so, follow the instructions in the warning message to disable this functionality and remove the warning.
If you hover your mouse pointer over each of the fields shown (e.g. `Simulation Delta Time`), you will see a tooltip popup with an explanation on what the item controls.
As seen in the UI for `Perception Camera`, the list of `Camera Labelers` is currently empty. For each type of ground-truth you wish to generate along-side your captured frames (e.g. 2D bounding boxes around objects), you will need to add a corresponding `Camera Labeler` to this list.

When you open the Prefab asset, you will see the object shown in the Scene tab and its components shown on the right side of the editor, in the _**Inspector**_ tab:
<p align="center">
<img src="Images/exampleprefab.png"/>
<img src="Images/exampleprefab.png" width="900"/>
</p>
The Prefab contains a number of components, including a `Transform`, a `Mesh Filter`, a `Mesh Renderer` and a `Labeling` component (highlighted in the image above). While the first three of these are common Unity components, the fourth one is specific to the Perception package, and is used for assigning labels to objects. You can see here that the Prefab has one label already added, displayed in the list of `Added Labels`. The UI here provides a multitude of ways for you to assign labels to the object. You can either choose to have the asset automatically labeled (by enabling `Use Automatic Labeling`), or add labels manually. In case of automatic labeling, you can choose from a number of labeling schemes, e.g. the asset's name or folder name. If you go the manual route, you can type in labels, add labels from any of the label configurations included in the project, or add from lists of suggested labels based on the Prefab's name and path.

### <a name="step-7">Step 7: Inspect Generated Synthetic Data</a>
Once the run is complete, you will see a message in the _**Console**_ tab of the editor, with information on where the generated data has been saved. An example is shown below (Mac OS):
* **:green_circle: Action** Select `Main Camera` again to bring up its _**Inspector**_ view. You will now see a new section added to the `Perception Camera` component, with buttons for showing the latest dataset output folder and copying its path to clipboard. An example is shown below (Mac OS):
<img src="Images/dataset_written.png"/>
<img src="Images/output_path.png" width = "600"/>
* **:green_circle: Action**: Navigate to the dataset path addressed in the _**Console**_.
* **:green_circle: Action**: Click _**Show Folder**_ to show and highlight the folder in your operating system's file explorer. Enter this folder.
In this folder, you will find a few types of data, depending on your `Perception Camera` settings. These can include:
- Logs

* **:green_circle: Action**: Download and install [Docker Desktop](https://www.docker.com/products/docker-desktop)
* **:green_circle: Action**: Open a command line interface (Command Prompt on Windows, Terminal on Mac OS, etc.) and type the following command to run the Dataset Insights Docker image:
`docker run -p 8888:8888 -v "<path to synthetic data>:/data" -t unitytechnologies/datasetinsights:latest`, where the path to data is what we earlier found in Unity's console messages.
`docker run -p 8888:8888 -v "<path to synthetic data>:/data" -t unitytechnologies/datasetinsights:latest`, where the path to data is what we looked at earlier. You can copy the path using the _**Copy Path**_ button in the `Perception Camera` UI.
This will download a Docker image from Unity. If you get an error regarding the path to your dataset, make sure you have not included the enclosing `<` and `>` in the path and that the spaces are properly escaped.

<img src="Images/jupyter1.png"/>
<img src="Images/jupyter1.png" width="800"/>
</p>
* **:green_circle: Action**: To make sure your data is properly mounted, navigate to the `data` folder. If you see the dataset's folders there, we are good to go.

<p align="center">
<img src="Images/jupyter2.png"/>
<img src="Images/jupyter2.png" width="800"/>
</p>
This notebook contains a variety of functions for generating plots, tables, and bounding box images that help you analyze your generated dataset. Certain parts of this notebook are currently not of use to us, such as the code meant for downloading data generated through Unity Simulation (coming later in this tutorial).

32
com.unity.perception/Documentation~/Tutorial/Phase2.md


In Phase 1 of the tutorial, we learned how to use the Randomizers that are bundled with the Perception package to spawn background and foreground objects, and randomize their position, rotation, texture, and hue offset (color). In this phase, we will build a custom light Randomizer for the `Directional Light` object, affecting the light's intensity and color on each Iteration of the Scenario. We will also learn how to include certain data or logic inside a randomized object (such as the light) in order to more explicitly define and restrict its randomization behaviors.
Steps included this phase of the tutorial:
Steps included in this phase of the tutorial:
- [Step 1: Build a Lighting Randomizer](#step-1)
- [Step 2: Bundle Data and Logic Inside RandomizerTags](#step-2)

</p>
* **:green_circle: Action**: In the UI snippet for `MyLightRandomzier`, set the minimum and maximum for range to 0.5 and 3.
* **:green_circle: Action**: In the UI snippet for `MyLightRandomzier`, set the minimum and maximum for range to **0.5** and **3**.
The `OnIterationStart()` function is used for telling the Randomizer what actions to perform at the start of each Iteration of the Scenario. As seen in the code block, at the start of each Iteration, this class queries the `tagManager` object for all objects that carry the `MyLightRandomizerTag` component. Then, for each object inside the queried list, it first retrieves the `Light` component, and then sets its intensity to a new random float sampled from `lightIntensityParameter`.
The `OnIterationStart()` function is used for telling the Randomizer what actions to perform at the start of each Iteration of the Scenario. As seen in the code block, at the start of each Iteration, this class queries the `tagManager` object for all RandomizerTag components of type `MyLightRandomizerTag` that are currently present on active objects in the Scene. Then, for each tag inside the queried list, it first retrieves the `Light` component of the GameObject the tag is attached to, and then sets the light's intensity to a new random float sampled from `lightIntensityParameter`.
* **:green_circle: Action**: Open `MyLightRandomizerTag.cs` and replace its contents with the code below:

Yes, a RandomizerTag can be this simple if you just need it for helping Randomizers query for target objects. Later, you will learn how to add code here to encapsulate more data and logic within the randomized objects.
Notice there is a `RequireComponent(typeof(Light))` line at the top. This line makes it so that you can only add the `MyLightRandomizerTag` component to an object that already has a `Light` component attached. This way, the Randomizers that query for this tag can be confident that the found objects have a `Light` component and can thus be Randomized.
Notice there is a `RequireComponent(typeof(Light))` line at the top. This line makes it so that you can only add the `MyLightRandomizerTag` component to an object that already has a `Light` component attached. This way, the Randomizers that query for this tag can be confident that the found tags are attached to GameObjects that also have a `Light` component, and can thus be Randomized.
* **:green_circle: Action**: Select `Directional Light` in the Scene's _**Hierarchy**_, and in the _**Inspector**_ tab, add a `My Light Randomizer Tag` component.
* **:green_circle: Action**: Run the simulation again and inspect how `Directional Light` now switches between different intensities. You can pause the simulation and then use the step button (to the right of the pause button) to move the simulation one frame forward and clearly see the varying light intensity

}
```
If you now check the UI snippet for `MyLightRandomizer`, you will notice that `Color Parameter` is added. This Parameter includes four separate randomized values for `Red`, `Green`, `Blue` and `Alpha`. Note that the meaningful range for all of these values is 0-1 (and not 0-255). You can see that the sampling range for red, green, and blue is currently also set to 0-1, which means the Parameter covers a full range of colors. A color with (0,0,0) RGB components essentially emits no light. So, let's increase the minimum a bit to avoid such a scenario.
If you now check the UI snippet for `MyLightRandomizer`, you will notice that `Color Parameter` is added. This Parameter includes four separate randomized values for `Red`, `Green`, `Blue` and `Alpha`. Note that the meaningful range for all of these values is 0-1 (and not 0-255). You can see that the sampling range for red, green, and blue is currently set to 0-1, which means the Parameter covers a full range of colors. A color with (0,0,0) RGB components essentially emits no light. So, let's increase the minimum a bit to avoid such a scenario.
* **:green_circle: Action**: Increase the minimum value for red, green, and blue components to 0.4 (this is an arbitrary number that typically produces good-looking results).
* **:green_circle: Action**: Increase the minimum value for red, green, and blue components to **0.4** (this is an arbitrary number that typically produces good-looking results).
The UI for `My Light Randomizer` should now look like this:

* **:green_circle: Action**: Run the simulation for a few frames to observe the lighting color changing on each Iteration of the Scenario.
* **:green_circle: Action**: Run the simulation for a few frames to observe the light color changing on each Iteration of the Scenario.
You may sometimes need to bundle certain randomization-related data or logic within an object that are inherent to the object itself. For instance, you may have multiple lights in the Scene but would like each of them to have their own unique range of intensities. It would be quite tedious to add a new Parameter to your light Randomizer for each of your lights. Furthermore, this would make your light Randomizer excessively tailored to one use-case, limiting the Randomizer's reusability.
You may sometimes need to bundle certain randomization-related data or logic within an object that are inherent to the object itself. For instance, you may have multiple lights in the Scene but would like each of them to have their own unique range of intensities. It would be quite tedious to add a new Parameter to your light Randomizer for each of your lights just to achieve this. Furthermore, this would make your light Randomizer excessively tailored to one use-case, limiting the Randomizer's reusability.
There are also cases where you may need to include certain logic within your object in order to make the Randomizer code more reusable and easier to maintain. For instance, you may want to build an office chair Prefab to use in various simulations. This chair is likely to support a range of customizations for its various parts (back angle, seat angle, seat height, etc.). Instead of directly mapping a Rotation Parameter from a Randomizer to the rotation of the back angle object within the chair, it might be more convenient to have the chair expose the range of possible angles in the form of a simple float between 0 and 1. With this approach, the Randomizer would only need to sample a float Parameter and assign it to the chair. The chair would in turn have a script attached that knows how to map this single float to a certain plausible back angle. You could even map this float to a more complex state of the chair. Your Randomizer would still only need one float Parameter.

* **:green_circle: Action**: Change the Y rotation of `Directional Light (1)` to 60, as shown below:
* **:green_circle: Action**: Change the Y rotation of `Directional Light (1)` to **60**, as shown below:
* **:green_circle: Action**: Change the Y rotation of `Directional Light` to -60.
* **:green_circle: Action**: Change the Y rotation of the original `Directional Light` to **-60**.
This makes the two lights illuminate the scene from opposing angles, each having a 30-degree angle with the background and foreground planes. Note that the position of Directional Lights in Unity does not affect how they illuminate the scene, so you do not need to use the same position as the screenshot above.

}
```
In the above code, we have created a new `SetIntensity` function that first scales the incoming intensity (assumed to be between 0 and 1) to our desired range and then assigns it to the light's intensity. The `Light` component is now fetched from the GameObject that this Randomizer tag is attached to. This works because both this tag component and the `Light` component are attached to the same object in the Scene (which is one of the lights).
In the above code, we have created a new `SetIntensity` function that first scales the incoming intensity (assumed to be between 0 and 1) to our desired range and then assigns it to the light's intensity. The `Light` component is now fetched from the GameObject that this Randomizer tag is attached to. This works because both this tag component and the `Light` component are attached to the same object in the Scene (which is one of the directional lights we created).
* **:green_circle: Action**: Select `Directional Light` and from the **Inspector** UI for the `MyLightRandomizerTag` component, set `Min Intensity` to 0.5 and `Max Intensity` to 3.
* **:green_circle: Action**: Repeat the above step for `Directional Light (1)` and set `Min Intensity` to 0 and `Max Intensity` to 0.4.
* **:green_circle: Action**: Select `Directional Light` and from the **Inspector** UI for the `MyLightRandomizerTag` component, set `Min Intensity` to **0.5** and `Max Intensity` to **3**.
* **:green_circle: Action**: Repeat the above step for `Directional Light (1)` and set `Min Intensity` to **0** and `Max Intensity` to **0.4**.
Note that with this change, we fully transfer the responsibility for the light's intensity range to `MyLightRandomizerTag.cs` and assume the intensity value coming from `My Light Randomizer` is always between 0 and 1. Therefore, we now need to change the range for the corresponding Parameter in `My Light Randomizer` to (0,1).
Note that with this change, we fully transfer the responsibility for the light's intensity range to `MyLightRandomizerTag.cs` and assume that the intensity value coming from `My Light Randomizer` is always between 0 and 1. Therefore, we now need to change the range for the corresponding Parameter in `My Light Randomizer` to (0,1).
* **:green_circle: Action**: Select `SimulationScenario` and from the UI snippet for `My Light Randomizer`, change the range for `Light Intensity Parameter` from (0.5,3.5) to (0,1).
* **:green_circle: Action**: Select `SimulationScenario` and from the UI snippet for `My Light Randomizer`, change the range for `Light Intensity Parameter` from (0.5,3.5) to **(0,1)**.
We also need to make a minor change to `MyLightRandomizer.cs` in order to make it compatible with this new approach.

}
```
Notice how we now fetch the `MyLightRandomizerTag` component from the tagged object and use its `SetIntensity` function instead of directly setting the intensity of the `Light` component.
Notice how we now utilize the `SetIntensity` fucntion of `MyLightRandomizerTag` components of the tagged objects, instead of directly setting the intensity of the `Light` components.
* **:green_circle: Action**: Run your simulation, then pause it. Go to the _**Scene**_ view and inspect the color and intensity of each of the lights. Try turning each on and off to see how they affect the current frame.

21
com.unity.perception/Documentation~/Tutorial/Phase3.md


In this phase of the tutorial, we will learn how to run our Scene on _**Unity Simulation**_ and analyze the generated dataset using _**Dataset Insights**_. Unity Simulation will allow us to generate a much larger dataset than what is typically plausible on a workstation computer.
Steps included this phase of the tutorial:
- [Step 1: Setup Unity Account, Unity Simulation, and Cloud Project](#step-1)
- [Step 2: Run Project on Unity Simulation](#step-2)
- [Step 3: Keep Track of Your Runs Using the Unity Simulation Command-Line Interface](#step-3)
- [Step 4: Analyze the Dataset using Dataset Insights](#step-4)
Steps included in this phase of the tutorial:
* [Step 1: Setup Unity Account, Unity Simulation, and Cloud Project](#step-1)
* [Step 2: Run Project on Unity Simulation](#step-2)
* [Step 3: Keep Track of Your Runs Using the Unity Simulation Command-Line Interface](#step-3)
* [Step 4: Analyze the Dataset using Dataset Insights](#step-4)
### <a name="step-1">Step 1: Setup Unity Account, Unity Simulation, and Cloud Project</a>

* **:green_circle: Action**: In the window that opens, navigate to the _**Player**_ tab, find the _**Scripting Backend**_ setting (under _**Other Settings**_), and change it to _**Mono**_:
<p align="center">
<img src="Images/mono.png"/>
<img src="Images/mono.png" width="800"/>
</p>
* **:green_circle: Action**: Change _**Fullscreen Mode**_ to _**Windowed**_ and set a width and height of 800 by 600.

* **:green_circle: Action**: In the `data_root = /data/<GUID>` line, the `<GUID>` part will be the location inside your `<download path>` where the data will be downloaded. Therefore, you can just remove it so as to have data downloaded directly to the path you previously specified:
<p align="center">
<img src="Images/di_usim_1.png"/>
<img src="Images/di_usim_1.png" width="900"/>
</p>
The next few lines of code pertain to setting up your notebook for downloading data from Unity Simulation.

Once you have entered all the information, the block of code should look like the screenshot below (the actual values you input will be different):
<p align="center">
<img src="Images/di_usim_2.png"/>
<img src="Images/di_usim_2.png" width="800"/>
</p>

<p align="center">
<img src="Images/di_usim_3.png"/>
<img src="Images/di_usim_3.png" width="800"/>
</p>

<p align="center">
<img src="Images/di_usim_4.png"/>
<img src="Images/di_usim_4.png" width="800"/>
</p>
Follow the rest of the steps inside the notebook to generate a variety of plots and stats. Keep in mind that this notebook is provided just as an example, and you can modify and extend it according to your own needs using the tools provided by the [Dataset Insights framework](https://datasetinsights.readthedocs.io/en/latest/).

5
com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs


{
foreach (var prop in m_LabelerUserProperties)
{
EditorGUI.PropertyField(rect, prop);
rect.y += Styles.defaultLineSpace;
EditorGUI.PropertyField(rect, prop, true);
var height = EditorGUI.GetPropertyHeight(prop) + EditorGUIUtility.standardVerticalSpacing;
rect.y += height;
}
}

1
com.unity.perception/Editor/Randomization/Editors/PerceptionEditorAnalytics.cs


using System;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Analytics;
namespace UnityEditor.Perception.Randomization

25
com.unity.perception/Editor/Randomization/Editors/RandomizerTagEditor.cs


using UnityEditor;
using UnityEditor.Perception.Randomization;
using UnityEditor.UIElements;
using UnityEngine.Perception.Randomization.Randomizers;
using UnityEngine.UIElements;

[CustomEditor(typeof(RandomizerTag), true)]
public class RandomizerTagEditor : UnityEditor.Editor
{
public override VisualElement CreateInspectorGUI()
{
var rootElement = new VisualElement();
CreatePropertyFields(rootElement);
return rootElement;
}
void CreatePropertyFields(VisualElement rootElement)
{
var iterator = serializedObject.GetIterator();
iterator.NextVisible(true);
do
{
if (iterator.name == "m_Script")
continue;
var propertyField = new PropertyField(iterator.Copy());
propertyField.Bind(serializedObject);
rootElement.Add(propertyField);
} while (iterator.NextVisible(false));
}
}
class RandomizerTagEditor : ParameterUIElementsEditor { }
}

280
com.unity.perception/Editor/Randomization/Editors/RunInUnitySimulationWindow.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;

class RunInUnitySimulationWindow : EditorWindow
{
string m_BuildDirectory;
SysParamDefinition[] m_SysParamDefinitions;
ObjectField m_MainSceneField;
Button m_RunButton;
ObjectField m_ScenarioField;
SysParamDefinition m_SysParam;
ToolbarMenu m_SysParamMenu;
int m_SysParamIndex;
ObjectField m_ScenarioConfigField;
Button m_RunButton;
Label m_PrevRunNameLabel;
Label m_ProjectIdLabel;
Label m_PrevExecutionIdLabel;
RunParameters m_RunParameters;
[MenuItem("Window/Run in Unity Simulation")]
static void ShowWindow()

}
}
/// <summary>
/// Enables a visual element to remember values between editor sessions
/// </summary>
/// <param name="element">The visual element to enable view data for</param>
static void SetViewDataKey(VisualElement element)
{
element.viewDataKey = $"RunInUnitySimulation_{element.name}";
}
void CreateRunInUnitySimulationUI()
{
var root = rootVisualElement;

m_RunNameField = root.Q<TextField>("run-name");
SetViewDataKey(m_RunNameField);
SetViewDataKey(m_TotalIterationsField);
SetViewDataKey(m_InstanceCountField);
m_MainSceneField = root.Q<ObjectField>("main-scene");
m_MainSceneField.objectType = typeof(SceneAsset);
if (SceneManager.sceneCount > 0)
m_SysParamDefinitions = API.GetSysParams();
m_SysParamMenu = root.Q<ToolbarMenu>("sys-param");
for (var i = 0; i < m_SysParamDefinitions.Length; i++)
var path = SceneManager.GetSceneAt(0).path;
var asset = AssetDatabase.LoadAssetAtPath<SceneAsset>(path);
m_MainSceneField.value = asset;
}
m_ScenarioField = root.Q<ObjectField>("scenario");
m_ScenarioField.objectType = typeof(ScenarioBase);
m_ScenarioField.value = FindObjectOfType<ScenarioBase>();
var sysParamDefinitions = API.GetSysParams();
var sysParamMenu = root.Q<ToolbarMenu>("sys-param");
foreach (var definition in sysParamDefinitions)
sysParamMenu.menu.AppendAction(
definition.description,
var index = i;
var param = m_SysParamDefinitions[i];
m_SysParamMenu.menu.AppendAction(
param.description,
m_SysParam = definition;
sysParamMenu.text = definition.description;
m_SysParamIndex = index;
m_SysParamMenu.text = param.description;
}
sysParamMenu.text = sysParamDefinitions[0].description;
m_SysParam = sysParamDefinitions[0];
m_ScenarioConfigField = root.Q<ObjectField>("scenario-config");
m_ScenarioConfigField.objectType = typeof(TextAsset);
var configPath = PlayerPrefs.GetString("SimWindow/scenarioConfig");
if (configPath != string.Empty)
m_ScenarioConfigField.value = AssetDatabase.LoadAssetAtPath<TextAsset>(configPath);
m_PrevRunNameLabel = root.Q<Label>("prev-run-name");
m_ProjectIdLabel = root.Q<Label>("project-id");
m_PrevExecutionIdLabel = root.Q<Label>("execution-id");
var copyExecutionIdButton = root.Q<Button>("copy-execution-id");
copyExecutionIdButton.clicked += () =>
EditorGUIUtility.systemCopyBuffer = PlayerPrefs.GetString("SimWindow/prevExecutionId");
var copyProjectIdButton = root.Q<Button>("copy-project-id");
copyProjectIdButton.clicked += () =>
EditorGUIUtility.systemCopyBuffer = CloudProjectSettings.projectId;
SetFieldsFromPlayerPreferences();
}
void SetFieldsFromPlayerPreferences()
{
m_RunNameField.value = IncrementRunName(PlayerPrefs.GetString("SimWindow/runName"));
m_TotalIterationsField.value = PlayerPrefs.GetInt("SimWindow/totalIterations");
m_InstanceCountField.value = PlayerPrefs.GetInt("SimWindow/instanceCount");
m_SysParamIndex = PlayerPrefs.GetInt("SimWindow/sysParamIndex");
m_SysParamMenu.text = m_SysParamDefinitions[m_SysParamIndex].description;
m_PrevRunNameLabel.text = $"Run Name: {PlayerPrefs.GetString("SimWindow/runName")}";
m_ProjectIdLabel.text = $"Project ID: {CloudProjectSettings.projectId}";
m_PrevExecutionIdLabel.text = $"Execution ID: {PlayerPrefs.GetString("SimWindow/prevExecutionId")}";
}
static string IncrementRunName(string runName)
{
if (string.IsNullOrEmpty(runName))
return "Run0";
var stack = new Stack<char>();
var i = runName.Length - 1;
for (; i >= 0; i--)
{
if (!char.IsNumber(runName[i]))
break;
stack.Push(runName[i]);
}
if (stack.Count == 0)
return runName + "1";
var numericString = string.Concat(stack.ToArray());
var runVersion = int.Parse(numericString) + 1;
return runName.Substring(0, i + 1) + runVersion;
m_RunParameters = new RunParameters
{
runName = m_RunNameField.value,
totalIterations = m_TotalIterationsField.value,
instanceCount = m_InstanceCountField.value,
sysParamIndex = m_SysParamIndex,
scenarioConfig = (TextAsset)m_ScenarioConfigField.value,
currentOpenScenePath = SceneManager.GetSceneAt(0).path,
currentScenario = FindObjectOfType<ScenarioBase>()
};
m_TotalIterationsField.value,
m_InstanceCountField.value,
m_RunParameters.totalIterations,
m_RunParameters.instanceCount,
null);
try
{

void ValidateSettings()
{
if (string.IsNullOrEmpty(m_RunNameField.value))
if (string.IsNullOrEmpty(m_RunParameters.runName))
if (m_MainSceneField.value == null)
throw new MissingFieldException("Main scene unselected");
if (m_ScenarioField.value == null)
throw new MissingFieldException("Scenario unselected");
var scenario = (ScenarioBase)m_ScenarioField.value;
if (!StaticData.IsSubclassOfRawGeneric(typeof(UnitySimulationScenario<>), scenario.GetType()))
if (m_RunParameters.instanceCount <= 0)
throw new NotSupportedException("Invalid instance count specified");
if (m_RunParameters.totalIterations <= 0)
throw new NotSupportedException("Invalid total iteration count specified");
if (string.IsNullOrEmpty(m_RunParameters.currentOpenScenePath))
throw new MissingFieldException("Invalid scene path");
if (m_RunParameters.currentScenario == null)
throw new MissingFieldException(
"There is not a Unity Simulation compatible scenario present in the scene");
if (!StaticData.IsSubclassOfRawGeneric(
typeof(UnitySimulationScenario<>), m_RunParameters.currentScenario.GetType()))
if (m_RunParameters.scenarioConfig != null &&
Path.GetExtension(m_RunParameters.scenarioConfigAssetPath) != ".json")
throw new NotSupportedException(
"Scenario configuration must be a JSON text asset");
// Create build directory
var projectBuildDirectory = $"{m_BuildDirectory}/{m_RunNameField.value}";
var projectBuildDirectory = $"{m_BuildDirectory}/{m_RunParameters.runName}";
// Create Linux build
Debug.Log("Creating Linux build...");
scenes = new[] { AssetDatabase.GetAssetPath(m_MainSceneField.value) },
locationPathName = Path.Combine(projectBuildDirectory, $"{m_RunNameField.value}.x86_64"),
scenes = new[] { m_RunParameters.currentOpenScenePath },
locationPathName = Path.Combine(projectBuildDirectory, $"{m_RunParameters.runName}.x86_64"),
throw new Exception($"Build did not succeed: status = {summary.result}");
Debug.Log("Created Linux build");
throw new Exception($"The Linux build did not succeed: status = {summary.result}");
// Zip the build
Debug.Log("Starting to zip...");
Zip.DirectoryContents(projectBuildDirectory, m_RunNameField.value);
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Zipping Linux build...", 0f);
Zip.DirectoryContents(projectBuildDirectory, m_RunParameters.runName);
Debug.Log("Created build zip");
List<AppParam> GenerateAppParamIds(CancellationToken token, float progressStart, float progressEnd)
List<AppParam> UploadAppParam()
var scenario = (ScenarioBase)m_ScenarioField.value;
var configuration = JObject.Parse(scenario.SerializeToJson());
var constants = configuration["constants"];
constants["totalIterations"] = m_TotalIterationsField.value;
constants["instanceCount"] = m_InstanceCountField.value;
var configuration = JObject.Parse(m_RunParameters.scenarioConfig != null
? File.ReadAllText(m_RunParameters.scenarioConfigAssetPath)
: m_RunParameters.currentScenario.SerializeToJson());
var progressIncrement = (progressEnd - progressStart) / m_InstanceCountField.value;
var constants = configuration["constants"];
constants["totalIterations"] = m_RunParameters.totalIterations;
constants["instanceCount"] = m_RunParameters.instanceCount;
for (var i = 0; i < m_InstanceCountField.value; i++)
var appParamName = $"{m_RunParameters.runName}";
var appParamsString = JsonConvert.SerializeObject(configuration, Formatting.Indented);
var appParamId = API.UploadAppParam(appParamName, appParamsString);
appParamIds.Add(new AppParam
if (token.IsCancellationRequested)
return null;
var appParamName = $"{m_RunNameField.value}_{i}";
constants["instanceIndex"] = i;
var appParamsString = JsonConvert.SerializeObject(configuration, Formatting.Indented);
var appParamId = API.UploadAppParam(appParamName, appParamsString);
appParamIds.Add(new AppParam
{
id = appParamId,
name = appParamName,
num_instances = 1
});
EditorUtility.DisplayProgressBar(
"Unity Simulation Run",
$"Uploading app-param-ids for instances: {i + 1}/{m_InstanceCountField.value}",
progressStart + progressIncrement * i);
}
id = appParamId,
name = appParamName,
num_instances = m_RunParameters.instanceCount
});
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Uploading build...", 0.1f);
m_RunButton.SetEnabled(false);
m_RunButton.SetEnabled(false);
// Upload build
Debug.Log("Uploading build...");
m_RunNameField.value,
m_RunParameters.runName,
cancellationTokenSource: cancellationTokenSource);
Debug.Log($"Build upload complete: build id {buildId}");
var appParams = GenerateAppParamIds(token, 0.1f, 0.9f);
null, null,
cancellationTokenSource,
progress =>
{
EditorUtility.DisplayProgressBar(
"Unity Simulation Run", "Uploading build...", progress * 0.90f);
});
Debug.Log("Run cancelled");
Debug.Log("The build upload process has been cancelled. Aborting Unity Simulation launch.");
Debug.Log($"Generated app-param ids: {appParams.Count}");
// Generate and upload app-params
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Uploading app-params...", 0.90f);
var appParams = UploadAppParam();
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Uploading run definition...", 0.9f);
// Upload run definition
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Uploading run definition...", 0.95f);
name = m_RunNameField.value,
sys_param_id = m_SysParam.id,
name = m_RunParameters.runName,
sys_param_id = m_SysParamDefinitions[m_RunParameters.sysParamIndex].id,
Debug.Log($"Run definition upload complete: run definition id {runDefinitionId}");
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Executing run...", 0.95f);
// Execute run
EditorUtility.DisplayProgressBar("Unity Simulation Run", "Executing run...", 1f);
cancellationTokenSource.Dispose();
Debug.Log($"Executing run: {run.executionId}");
// Cleanup
EditorUtility.ClearProgressBar();
PerceptionEditorAnalytics.ReportRunInUnitySimulationSucceeded(runGuid, run.executionId);
EditorUtility.ClearProgressBar();
// Set new Player Preferences
PlayerPrefs.SetString("SimWindow/runName", m_RunParameters.runName);
PlayerPrefs.SetString("SimWindow/prevExecutionId", run.executionId);
PlayerPrefs.SetInt("SimWindow/totalIterations", m_RunParameters.totalIterations);
PlayerPrefs.SetInt("SimWindow/instanceCount", m_RunParameters.instanceCount);
PlayerPrefs.SetInt("SimWindow/sysParamIndex", m_RunParameters.sysParamIndex);
PlayerPrefs.SetString("SimWindow/scenarioConfig",
m_RunParameters.scenarioConfig != null ? m_RunParameters.scenarioConfigAssetPath : string.Empty);
SetFieldsFromPlayerPreferences();
}
struct RunParameters
{
public string runName;
public int totalIterations;
public int instanceCount;
public int sysParamIndex;
public TextAsset scenarioConfig;
public string currentOpenScenePath;
public ScenarioBase currentScenario;
PerceptionEditorAnalytics.ReportRunInUnitySimulationSucceeded(runGuid, run.executionId);
public string scenarioConfigAssetPath => AssetDatabase.GetAssetPath(scenarioConfig);
}
}
}

57
com.unity.perception/Editor/Randomization/Editors/ScenarioBaseEditor.cs


using System;
using System.IO;
using UnityEngine;
using Button = UnityEngine.UIElements.Button;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace UnityEditor.Perception.Randomization

VisualElement m_Root;
ScenarioBase m_Scenario;
SerializedObject m_SerializedObject;
const string k_ConfigFilePlayerPrefKey = "ScenarioBaseEditor/configFilePath";
public override VisualElement CreateInspectorGUI()
{

m_Scenario.genericConstants.randomSeed = (uint)Random.Range(int.MinValue, int.MaxValue);
};
var serializeConstantsButton = m_Root.Q<Button>("serialize");
serializeConstantsButton.clicked += () =>
var generateConfigButton = m_Root.Q<Button>("generate-json-config");
generateConfigButton.clicked += () =>
m_Scenario.SerializeToFile();
var filePath = GetSaveFilePath(
"Generate Scenario JSON Configuration", Application.dataPath,
"scenarioConfiguration", "json", k_ConfigFilePlayerPrefKey);
if (string.IsNullOrEmpty(filePath))
return;
m_Scenario.SerializeToFile(filePath);
var newConfigFileAsset = AssetDatabase.LoadAssetAtPath<Object>(m_Scenario.defaultConfigFileAssetPath);
EditorGUIUtility.PingObject(newConfigFileAsset);
EditorUtility.RevealInFinder(filePath);
PlayerPrefs.SetString(k_ConfigFilePlayerPrefKey, filePath);
var deserializeConstantsButton = m_Root.Q<Button>("deserialize");
var deserializeConstantsButton = m_Root.Q<Button>("import-json-config");
var filePath = GetOpenFilePath(
"Import Scenario JSON Configuration", Application.dataPath, "json", k_ConfigFilePlayerPrefKey);
if (string.IsNullOrEmpty(filePath))
return;
m_Scenario.DeserializeFromFile(m_Scenario.defaultConfigFilePath);
m_Scenario.DeserializeFromFile(filePath);
Debug.Log($"Deserialized scenario configuration from {Path.GetFullPath(filePath)}. " +
"Using undo in the editor will revert these changes to your scenario.");
PlayerPrefs.SetString(k_ConfigFilePlayerPrefKey, filePath);
};
return m_Root;

m_InspectorPropertiesContainer.style.marginBottom = 0;
m_ConstantsListVisualContainer.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
}
}
static string GetSaveFilePath(
string title, string defaultDirectory, string defaultFileName, string fileExtension, string playerPrefKey)
{
var prevFilePath = PlayerPrefs.GetString(playerPrefKey);
var prevDirectory = defaultDirectory;
var prevFileName = defaultFileName;
if (File.Exists(prevFilePath))
{
prevDirectory = Path.GetDirectoryName(prevFilePath);
prevFileName = Path.GetFileNameWithoutExtension(prevFilePath);
}
return EditorUtility.SaveFilePanel(
title, prevDirectory, prevFileName, fileExtension);
}
static string GetOpenFilePath(string title, string defaultDirectory, string fileExtension, string playerPrefKey)
{
var prevFilePath = PlayerPrefs.GetString(playerPrefKey);
var prevDirectory = defaultDirectory;
if (File.Exists(prevFilePath))
prevDirectory = Path.GetDirectoryName(prevFilePath);
return EditorUtility.OpenFilePanel(title, prevDirectory, fileExtension);
}
}
}

8
com.unity.perception/Editor/Randomization/Uss/Styles.uss


margin: 3px 3px 3px 3px;
}
.scenario__error-box {
color: #FF4040;
}
.scenario__dark-viewport {
border-radius: 5px;
background-color: #191919;

width: 0;
flex-grow: 1;
flex-shrink: 0;
}
.parameter__categorical-option-property-field Label.unity-property-field__label {
display: none;
}
.parameter__categorical-options-list-button {

26
com.unity.perception/Editor/Randomization/Utilities/StaticData.cs


object obj = prop.serializedObject.targetObject;
var elements = path.Split('.');
if (parent)
elements = elements.Take(elements.Count() - 1).ToArray();
elements = elements.Take(elements.Length - 1).ToArray();
foreach (var element in elements)
if (element.Contains("["))

if (source == null)
return null;
var type = source.GetType();
var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (f == null)
var field = GetField(type, name);
if (field == null)
var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
return p == null ? null : p.GetValue(source, null);
var property = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
return property == null ? null : property.GetValue(source, null);
return f.GetValue(source);
return field.GetValue(source);
}
static object GetArrayValue(object source, string name, int index)

while (index-- >= 0)
enumerator.MoveNext();
return enumerator.Current;
}
public static FieldInfo GetField(Type type, string fieldName)
{
if (type == null)
return null;
const BindingFlags flags =
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance |BindingFlags.DeclaredOnly;
var fields = type.GetFields(flags);
foreach (var field in fields)
if (field.Name == fieldName)
return field;
return GetField(type.BaseType, fieldName);
}
public static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)

27
com.unity.perception/Editor/Randomization/Utilities/UIElementsEditorUtilities.cs


using System;
using System.Linq;
using System.Reflection;
using UnityEngine.Perception.Randomization.Randomizers.SampleRandomizers;
using UnityEngine.UIElements;
namespace UnityEditor.Perception.Randomization

/// </summary>
public static class UIElementsEditorUtilities
static class UIElementsEditorUtilities
{
/// <summary>
/// Creates a list of PropertyFields from the class fields of the given SerializedObject

var fieldType = serializedObj.targetObject.GetType();
var iterator = serializedObj.GetIterator();
iterator.NextVisible(true);
iterator.NextVisible(false);
do
if (iterator.NextVisible(false))
var propertyField = CreatePropertyField(iterator, fieldType);
containerElement.Add(propertyField);
} while (iterator.NextVisible(false));
do
{
var propertyField = CreatePropertyField(iterator, fieldType);
containerElement.Add(propertyField);
} while (iterator.NextVisible(false));
}
}
/// <summary>

/// <param name="containerElement">The element to place the created PropertyFields in</param>
public static void CreatePropertyFields(SerializedProperty property, VisualElement containerElement)
{
var fieldType = StaticData.GetManagedReferenceValue(property).GetType();
var obj = StaticData.GetManagedReferenceValue(property);
if (obj == null)
return;
var fieldType = obj.GetType();
{
do
{
if (SerializedProperty.EqualContents(iterator, nextSiblingProperty))

} while (iterator.NextVisible(false));
}
}
/// <summary>

{
var propertyField = new PropertyField(iterator.Copy());
propertyField.Bind(iterator.serializedObject);
var originalField = parentPropertyType.GetField(iterator.name);
var originalField = parentPropertyType.GetField(iterator.name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );
var tooltipAttribute = originalField.GetCustomAttributes(true)
.ToList().Find(att => att.GetType() == typeof(TooltipAttribute));
if (tooltipAttribute != null)

48
com.unity.perception/Editor/Randomization/Uxml/RunInUnitySimulationWindow.uxml


<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements">
<TextField name="run-name" label="Run Name"/>
<editor:IntegerField name="total-iterations" label="Total Iterations"/>
<editor:IntegerField name="instance-count" label="Instance Count" max-value="10000"/>
<editor:ObjectField name="main-scene" label="Main Scene" allow-scene-objects="false"/>
<editor:ObjectField name="scenario" label="Scenario"/>
<VisualElement class="unity-base-field">
<Label text="Sys-Param" class="unity-base-field__label"/>
<editor:ToolbarMenu name="sys-param" class="unity-base-field__input" style="border-width: 1px;"/>
</VisualElement>
<VisualElement style="align-items: center;">
<Button name="run-button" text="Build and Run" style="margin: 10px; padding: 2 20; font-size: 13px;"/>
<VisualElement style="margin: 2 4 2 4;">
<Style src="../Uss/RunInUnitySimulationWindowStyles.uss"/>
<VisualElement class="sim-window__container-outer">
<Label text="Simulation Parameters" class="sim-window__header-1"/>
<TextField name="run-name" label="Run Name"/>
<editor:IntegerField name="total-iterations" label="Total Iterations"
tooltip="The number of scenario iterations to execute"/>
<editor:IntegerField name="instance-count" label="Instance Count" max-value="10000"
tooltip="The number of instances to distribute the work load across"/>
<VisualElement class="unity-base-field"
tooltip="The compute resources configuration to execute the simulation with">
<Label text="Sys-Param" class="unity-base-field__label"/>
<editor:ToolbarMenu name="sys-param" class="unity-base-field__input" style="border-width: 1px;"/>
</VisualElement>
<Label text="Optional Configuration" class="sim-window__header-1" style="margin-top: 18px;"/>
<editor:ObjectField name="scenario-config" label="Scenario JSON Config" allow-scene-object="false"
tooltip="Selects a scenario JSON configuration to load during the run.
You can leave this option blank to use the scenario settings currently configured in the editor."/>
<VisualElement style="align-items: center; margin-top: 8px;">
<Button name="run-button" text="Build and Run" style="margin: 10px; padding: 2 20; font-size: 13px;"/>
</VisualElement>
</VisualElement>
<VisualElement class="sim-window__container-outer">
<Label text="Previous Run Information" class="sim-window__header-1"/>
<Label name="prev-run-name" text="Run Name: " class="sim-window__label-prev-result"/>
<Label name="project-id" text="Project ID: " class="sim-window__label-prev-result"/>
<Label name="execution-id" text="Execution ID: " class="sim-window__label-prev-result"/>
<VisualElement style="flex-direction: row; margin-top: 2px;">
<Button name="copy-execution-id" text="Copy Execution ID" style="flex-grow: 1; flex-shrink: 0;"/>
<Button name="copy-project-id" text="Copy Project ID" style="flex-grow: 1; flex-shrink: 0;"/>
</VisualElement>
</VisualElement>
</VisualElement>
</UXML>

7
com.unity.perception/Editor/Randomization/Uxml/ScenarioBaseElement.uxml


<TextElement
class="scenario__info-box"
text="Scenarios control the execution flow of your simulation by applying randomization parameters. Make sure to always have only one scenario active within your scene."/>
<Toggle label="Quit On Complete" tooltip="Quit the application when the scenario completes" binding-path="quitOnComplete" style="margin-top:5px"/>
<VisualElement name="constants-container">
<Foldout style="padding-left: 16px" text="Constants" name="constants-list" tooltip="A list of parameters for this scenario that will be JSON serialized in the configuration file."/>
<editor:PropertyField name="configuration-file-name" label="Constants File Name" binding-path="serializedConstantsFileName"/>

<Button name="serialize" text="Serialize To Config File" style="flex-grow: 1;"
<Button name="generate-json-config" text="Generate JSON Config" style="flex-grow: 1;"
<Button name="deserialize" text="Deserialize From Config File" style="flex-grow: 1;"
tooltip="Deserializes scenario constants and randomizer settings from a scenario_configuration.json file located in the Assets/StreamingAssets project folder"/>
<Button name="import-json-config" text="Import JSON Config" style="flex-grow: 1;"
tooltip="Imports scenario constants and randomizer settings from a selected JSON file"/>
</VisualElement>
</VisualElement>
</VisualElement>

6
com.unity.perception/Editor/Randomization/VisualElements/Parameter/CategoricalOptionElement.cs


{
class CategoricalOptionElement : VisualElement
{
SerializedProperty m_CategoryProperty;
SerializedProperty m_CategoryProperty;
SerializedProperty m_ProbabilitiesProperty;
internal CategoricalOptionElement(

var optionProperty = m_CategoryProperty.GetArrayElementAtIndex(i);
var option = this.Q<PropertyField>("option");
option.BindProperty(optionProperty);
// Remove the redundant element label to save space
var label = option.Q<Label>();
label.parent.Remove(label);
var probabilityProperty = m_ProbabilitiesProperty.GetArrayElementAtIndex(i);
var probability = this.Q<FloatField>("probability");

49
com.unity.perception/Editor/Randomization/VisualElements/Parameter/ParameterElement.cs


listView.style.flexGrow = 1.0f;
listView.style.height = new StyleLength(listView.itemHeight * 4);
var uniformToggle = template.Q<Toggle>("uniform");
VisualElement MakeItem()
{
return new CategoricalOptionElement(

// First delete sets option to null, second delete removes option
var numOptions = optionsProperty.arraySize;
optionsProperty.DeleteArrayElementAtIndex(i);
{
}
void ResetProbabilities()
{
var uniformProbability = probabilitiesProperty.arraySize > 0 ? 1f / probabilitiesProperty.arraySize : 0;
for (var i = 0; i < probabilitiesProperty.arraySize; i++)
{
probabilitiesProperty.GetArrayElementAtIndex(i).floatValue = uniformProbability;
}
}
listView.bindItem = BindItem;
var addOptionButton = template.Q<Button>("add-option");

break;
}
// New items probability will be 0, unless uniform toggle is true
probabilitiesProperty.GetArrayElementAtIndex(probabilitiesProperty.arraySize - 1).floatValue = 0;
if (uniformToggle.value)
ResetProbabilities();
m_SerializedProperty.serializedObject.ApplyModifiedProperties();
listView.itemsSource = categoricalParameter.probabilities;
listView.Refresh();

return;
var categories = LoadAssetsFromFolder(folderPath, categoricalParameter.sampleType);
var probabilityIndex = probabilitiesProperty.arraySize;
probabilitiesProperty.arraySize += categories.Count;
var uniformProbability = 1f / categories.Count;
probabilitiesProperty.arraySize += categories.Count;
var probabilityProperty = probabilitiesProperty.GetArrayElementAtIndex(probabilityIndex + i);
probabilityProperty.floatValue = uniformProbability;
probabilitiesProperty.GetArrayElementAtIndex(i).floatValue = 0;
if (uniformToggle.value)
ResetProbabilities();
m_SerializedProperty.serializedObject.ApplyModifiedProperties();
listView.itemsSource = categoricalParameter.probabilities;

evt.StopImmediatePropagation();
});
var uniformToggle = template.Q<Toggle>("uniform");
if (uniformToggle.value)
listView.AddToClassList("collapsed");
else
listView.RemoveFromClassList("collapsed");
void ToggleUniform()
{
if (uniformToggle.value)
listView.AddToClassList("collapsed");
else
listView.RemoveFromClassList("collapsed");
}
ToggleUniform();
if (Application.isPlaying)
uniformToggle.SetEnabled(false);

listView.ToggleInClassList("collapsed");
ToggleUniform();
if (!evt.newValue)
return;
var numOptions = optionsProperty.arraySize;

5
com.unity.perception/Editor/Randomization/VisualElements/Randomizer/AddRandomizerMenu.cs


m_MenuItemsMap.Add(string.Empty, rootList);
var randomizerTypeSet = new HashSet<Type>();
foreach (var randomizer in m_RandomizerList.scenario.m_Randomizers)
foreach (var randomizer in m_RandomizerList.scenario.randomizers)
randomizerTypeSet.Add(randomizer.GetType());
foreach (var randomizerType in StaticData.randomizerTypes)

var menuAttribute = (AddRandomizerMenuAttribute)Attribute.GetCustomAttribute(randomizerType, typeof(AddRandomizerMenuAttribute));
var menuAttribute = (AddRandomizerMenuAttribute)Attribute.GetCustomAttribute(
randomizerType, typeof(AddRandomizerMenuAttribute));
if (menuAttribute != null)
{
var pathItems = menuAttribute.menuPath.Split('/');

8
com.unity.perception/Editor/Randomization/VisualElements/Randomizer/RandomizerElement.cs


{
m_Property = property;
this.randomizerList = randomizerList;
m_Collapsed = property.FindPropertyRelative("collapsed");
collapsed = m_Collapsed.boolValue;

collapseToggle.RegisterCallback<MouseUpEvent>(evt => collapsed = !collapsed);
var enabledToggle = this.Q<Toggle>("enabled");
enabledToggle.BindProperty(property.FindPropertyRelative("<enabled>k__BackingField"));
enabledToggle.BindProperty(property.FindPropertyRelative("m_Enabled"));
var removeButton = this.Q<Button>("remove");
removeButton.clicked += () => randomizerList.RemoveRandomizer(this);

public bool collapsed
{
get => m_Collapsed.boolValue;
get => m_Collapsed?.boolValue ?? true;
if (m_Collapsed == null)
return;
m_Collapsed.boolValue = value;
m_Property.serializedObject.ApplyModifiedPropertiesWithoutUndo();
if (value)

21
com.unity.perception/Editor/Randomization/VisualElements/Randomizer/RandomizerList.cs


void RefreshList()
{
m_Container.Clear();
if (m_Property.arraySize > 0 &&
string.IsNullOrEmpty(m_Property.GetArrayElementAtIndex(0).managedReferenceFullTypename))
{
var textElement = new TextElement()
{
text = "One or more randomizers have missing scripts. See console for more info."
};
textElement.AddToClassList("scenario__info-box");
textElement.AddToClassList("scenario__error-box");
m_Container.Add(textElement);
return;
}
for (var i = 0; i < m_Property.arraySize; i++)
m_Container.Add(new RandomizerElement(m_Property.GetArrayElementAtIndex(i), this));
}

public void RemoveRandomizer(RandomizerElement element)
{
Undo.RegisterCompleteObjectUndo(m_Property.serializedObject.targetObject, "Remove Randomizer");
scenario.RemoveRandomizer(element.randomizerType);
scenario.RemoveRandomizerAt(element.parent.IndexOf(element));
m_Property.serializedObject.Update();
RefreshList();
}

if (currentIndex == nextIndex)
return;
if (nextIndex > currentIndex)
nextIndex--;
scenario.ReorderRandomizer(currentIndex, nextIndex);
var randomizer = scenario.GetRandomizer(currentIndex);
scenario.RemoveRandomizerAt(currentIndex);
scenario.InsertRandomizer(nextIndex, randomizer);
m_Property.serializedObject.Update();
RefreshList();
}

1
com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBox3DLabeler.cs


return VisualizationHelper.ConvertToScreenSpace(cam, worldPoint);
}
/// <inheritdoc/>
protected override void OnVisualize()
{
if (m_ToReport == null) return;

5
com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs


/// </summary>
protected virtual void OnBeginRendering() {}
/// <summary>
/// Called just after the camera renders each frame the the labeler is enabled and <see cref="SensorHandle.ShouldCaptureThisFrame"/> is true.
/// </summary>
protected virtual void OnEndRendering() {}
/// <summary>
/// Labeling pass to display labeler's visualization components, if applicable. Important note, all labeler's visualizations need
/// to use Unity's Immediate Mode GUI (IMGUI) <see cref="https://docs.unity3d.com/Manual/GUIScriptingGuide.html"/> system.
/// This called is triggered from <see cref="perceptionCamera.OnGUI"/> call. This call happens immediately before <see cref="OnVisualizeAdditionalUI"/>

}
internal void InternalOnUpdate() => OnUpdate();
internal void InternalOnBeginRendering() => OnBeginRendering();
internal void InternalOnEndRendering() => OnEndRendering();
internal void InternalCleanup() => Cleanup();
internal void InternalVisualize() => OnVisualize();

2
com.unity.perception/Runtime/GroundTruth/Labelers/CocoKeypointTemplate.asset


templateName: Coco
jointTexture: {fileID: 2800000, guid: e381cbaaf29614168bafc8f7ec5dbfe9, type: 3}
skeletonTexture: {fileID: 2800000, guid: e381cbaaf29614168bafc8f7ec5dbfe9, type: 3}
keyPoints:
keypoints:
- label: nose
associateToRig: 0
rigLabel: 0

9
com.unity.perception/Runtime/GroundTruth/Labelers/InstanceSegmentationLabeler.cs


}
}
void OnImageCaptured(int frame, NativeArray<Color32> data, RenderTexture renderTexture)
void OnImageCaptured(int frameCount, NativeArray<Color32> data, RenderTexture renderTexture)
if (!m_AsyncAnnotations.ContainsKey(frameCount))
return;
m_InstancePath = $"{k_Directory}/{k_FilePrefix}{frame}.png";
var localPath = $"{Manager.Instance.GetDirectoryFor(k_Directory)}/{k_FilePrefix}{frame}.png";
m_InstancePath = $"{k_Directory}/{k_FilePrefix}{frameCount}.png";
var localPath = $"{Manager.Instance.GetDirectoryFor(k_Directory)}/{k_FilePrefix}{frameCount}.png";
var colors = new NativeArray<Color32>(data, Allocator.TempJob);

7
com.unity.perception/Runtime/GroundTruth/Labelers/JointLabel.cs


/// Label to designate a custom joint/keypoint. These are needed to add body
/// parts to a humanoid model that are not contained in its <see cref="Animator"/> <see cref="Avatar"/>
/// </summary>
[AddComponentMenu("Perception/Labeling/Joint Label")]
/// Maps this joint to a joint in a <see cref="KeyPointTemplate"/>
/// Maps this joint to a joint in a <see cref="KeypointTemplate"/>
/// The <see cref="KeyPointTemplate"/> that defines this joint.
/// The <see cref="KeypointTemplate"/> that defines this joint.
public KeyPointTemplate template;
public KeypointTemplate template;
/// <summary>
/// The name of the joint.
/// </summary>

1
com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs


/// <summary>
/// Defines a set of labels associated with the object and its descendants. A Labeling component will override any Labeling components on the object's ancestors.
/// </summary>
[AddComponentMenu("Perception/Labeling/Labeling")]
public class Labeling : MonoBehaviour
{
/// <summary>

76
com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs


public partial class PerceptionCamera : MonoBehaviour
{
//TODO: Remove the Guid path when we have proper dataset merging in Unity Simulation and Thea
internal static string RgbDirectory { get; } = $"RGB{Guid.NewGuid()}";
internal string rgbDirectory { get; } = $"RGB{Guid.NewGuid()}";
static string s_RgbFilePrefix = "rgb_";
/// <summary>

Dictionary<string, object> m_PersistentSensorData = new Dictionary<string, object>();
int m_LastFrameCaptured = -1;
int m_LastFrameEndRendering = -1;
#pragma warning disable 414
//only used to confirm that GroundTruthRendererFeature is present in URP

return m_PersistentSensorData.Remove(key);
}
// Start is called before the first frame update
void Awake()
void Start()
{
AsyncRequest.maxJobSystemParallelism = 0; // Jobs are not chained to one another in any way, maximizing parallelism
AsyncRequest.maxAsyncRequestFrameAge = 4; // Ensure that readbacks happen before Allocator.TempJob allocations get stale

void OnEnable()
{
RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
RenderPipelineManager.endCameraRendering += CheckForRendererFeature;
}

void CaptureRgbData(Camera cam)
{
Profiler.BeginSample("CaptureDataFromLastFrame");
Profiler.BeginSample("CaptureDataFromLastFrame");
var captureFilename = $"{Manager.Instance.GetDirectoryFor(RgbDirectory)}/{s_RgbFilePrefix}{Time.frameCount}.png";
var dxRootPath = $"{RgbDirectory}/{s_RgbFilePrefix}{Time.frameCount}.png";
var captureFilename = $"{Manager.Instance.GetDirectoryFor(rgbDirectory)}/{s_RgbFilePrefix}{Time.frameCount}.png";
var dxRootPath = $"{rgbDirectory}/{s_RgbFilePrefix}{Time.frameCount}.png";
var flipY = ShouldFlipY(cam);
colorFunctor = r =>
{

Profiler.EndSample();
}
// ReSharper disable once ParameterHidesMember
bool ShouldFlipY(Camera camera)
{
#if HDRP_PRESENT
var hdAdditionalCameraData = GetComponent<HDAdditionalCameraData>();
//Based on logic in HDRenderPipeline.PrepareFinalBlitParameters
return hdAdditionalCameraData.flipYMode == HDAdditionalCameraData.FlipYMode.ForceFlipY || (camera.targetTexture == null && camera.cameraType == CameraType.Game);
#elif URP_PRESENT
return (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11 || SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal) &&
(camera.targetTexture == null && camera.cameraType == CameraType.Game);
#else
return false;
#endif
}
void OnSimulationEnding()
{
CleanUpInstanceSegmentation();

void OnBeginCameraRendering(ScriptableRenderContext _, Camera cam)
{
if (cam != m_AttachedCamera)
return;
if (!SensorHandle.ShouldCaptureThisFrame)
return;
//there are cases when OnBeginCameraRendering is called multiple times in the same frame. Ignore the subsequent calls.
if (m_LastFrameCaptured == Time.frameCount)
if (!ShouldCallLabelers(cam, m_LastFrameCaptured))
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPaused)
CaptureRgbData(cam);
CallOnLabelers(l => l.InternalOnBeginRendering());
}
void OnEndCameraRendering(ScriptableRenderContext _, Camera cam)
{
if (!ShouldCallLabelers(cam, m_LastFrameEndRendering))
#endif
CaptureRgbData(cam);
m_LastFrameEndRendering = Time.frameCount;
CallOnLabelers(l => l.InternalOnEndRendering());
}
private void CallOnLabelers(Action<CameraLabeler> action)
{
foreach (var labeler in m_Labelers)
{
if (!labeler.enabled)

labeler.Init(this);
labeler.InternalOnBeginRendering();
action(labeler);
private bool ShouldCallLabelers(Camera cam, int lastFrameCalledThisCallback)
{
if (cam != m_AttachedCamera)
return false;
if (!SensorHandle.ShouldCaptureThisFrame)
return false;
//there are cases when OnBeginCameraRendering is called multiple times in the same frame. Ignore the subsequent calls.
if (lastFrameCalledThisCallback == Time.frameCount)
return false;
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPaused)
return false;
#endif
return true;
}
RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;
RenderPipelineManager.endCameraRendering -= CheckForRendererFeature;
}

9
com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs


internal bool m_fLensDistortionEnabled = false;
#if HDRP_PRESENT || URP_PRESENT
private float? m_LensDistortionIntensityOverride;
#if HDRP_PRESENT
InstanceSegmentationPass m_InstanceSegmentationPass;
LensDistortionPass m_LensDistortionPass;

internal void OverrideLensDistortionIntensity(float? intensity)
{
m_LensDistortionPass.m_LensDistortionCrossPipelinePass.lensDistortionOverride = intensity;
m_LensDistortionIntensityOverride = intensity;
if (m_LensDistortionPass != null)
m_LensDistortionPass.m_LensDistortionCrossPipelinePass.lensDistortionOverride = intensity;
}
#endif

m_RenderedObjectInfoGenerator = new RenderedObjectInfoGenerator();
#if HDRP_PRESENT || URP_PRESENT
#if HDRP_PRESENT
var customPassVolume = this.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>();
customPassVolume.injectionPoint = CustomPassInjectionPoint.BeforeRendering;

AddScriptableRenderPass(m_LensDistortionPass);
m_fLensDistortionEnabled = true;
#endif
m_LensDistortionPass.m_LensDistortionCrossPipelinePass.lensDistortionOverride =
m_LensDistortionIntensityOverride;
#endif
m_InstanceSegmentationReader = new RenderTextureReader<Color32>(m_InstanceSegmentationTexture, myCamera, (frameCount, data, tex) =>

2
com.unity.perception/Runtime/Randomization/Parameters/CategoricalParameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

/// <typeparam name="T">The sample type of the categorical parameter</typeparam>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public abstract class CategoricalParameter<T> : CategoricalParameterBase
{
[SerializeField] internal bool uniform = true;

2
com.unity.perception/Runtime/Randomization/Parameters/CategoricalParameterBase.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public abstract class CategoricalParameterBase : Parameter
{
[SerializeField] internal List<float> probabilities = new List<float>();

2
com.unity.perception/Runtime/Randomization/Parameters/NumericParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

/// <typeparam name="T">The sample type of the parameter</typeparam>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public abstract class NumericParameter<T> : Parameter where T : struct
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/Parameter.cs


using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

/// </summary>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public abstract class Parameter
{
[HideInInspector, SerializeField] internal bool collapsed;

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/AnimationClipParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class AnimationClipParameter : CategoricalParameter<AnimationClip> { }
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/GameObjectParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class GameObjectParameter : CategoricalParameter<GameObject> { }
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/MaterialParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class MaterialParameter : CategoricalParameter<Material> {}
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/StringParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class StringParameter : CategoricalParameter<string> {}
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/CategorialParameters/Texture2DParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class Texture2DParameter : CategoricalParameter<Texture2D> { }
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/BooleanParameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class BooleanParameter : NumericParameter<bool>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsva.cs


using System;
using Unity.Mathematics;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public struct ColorHsva
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsvaCategoricalParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class ColorHsvaCategoricalParameter : CategoricalParameter<ColorHsva> { }
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsvaParameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class ColorHsvaParameter : NumericParameter<Color>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorRgbCategoricalParameter.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class ColorRgbCategoricalParameter : CategoricalParameter<Color> { }
}

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorRgbParameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class ColorRgbParameter : NumericParameter<Color>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/FloatParameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class FloatParameter : NumericParameter<float>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/IntegerParameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class IntegerParameter : NumericParameter<int>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector2Parameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class Vector2Parameter : NumericParameter<Vector2>
{
/// <summary>

3
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector3Parameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{
/// <summary>

[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class Vector3Parameter : NumericParameter<Vector3>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector4Parameter.cs


using System;
using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Parameters
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Parameters")]
public class Vector4Parameter : NumericParameter<Vector4>
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Randomizers/AddRandomizerMenuAttribute.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Randomizers
{

[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Randomizers")]
public class AddRandomizerMenuAttribute : Attribute
{
/// <summary>

109
com.unity.perception/Runtime/Randomization/Randomizers/Randomizer.cs


using System;
using System.Collections.Generic;
using Unity.Entities;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Randomizers
{

/// https://issuetracker.unity3d.com/issues/serializereference-non-serialized-initialized-fields-lose-their-values-when-entering-play-mode
/// </remark>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Randomizers")]
bool m_PreviouslyEnabled;
[HideInInspector, SerializeField] internal bool collapsed;
[SerializeField, HideInInspector] bool m_Enabled = true;
[SerializeField, HideInInspector] internal bool collapsed;
[field: SerializeField, HideInInspector] public bool enabled { get; set; } = true;
public bool enabled
{
get => m_Enabled;
set
{
m_Enabled = value;
if (value)
OnEnable();
else
OnDisable();
}
}
/// <summary>
/// Returns the scenario containing this Randomizer

/// <summary>
/// OnCreate is called when the Randomizer is added or loaded to a scenario
/// </summary>
protected virtual void OnCreate() { }
[Obsolete("Method OnCreate has been deprecated. Use OnAwake instead (UnityUpgradable)", true)]
protected virtual void OnCreate() =>
throw new NotSupportedException("OnCreate method has been deprecated");
/// <summary>
/// OnAwake is called when the Randomizer is added or loaded to a scenario
/// </summary>
protected virtual void OnAwake() { }
/// OnIterationStart is called at the start of a new scenario iteration
/// OnEnabled is called when the Randomizer becomes enabled and active
protected virtual void OnIterationStart() { }
protected virtual void OnEnable() { }
/// OnIterationEnd is called the after a scenario iteration has completed
/// OnDisable is called when the Randomizer becomes disabled
protected virtual void OnIterationEnd() { }
protected virtual void OnDisable() { }
/// <summary>
/// OnScenarioStart is called on the frame the scenario begins iterating
/// </summary>
protected virtual void OnScenarioStart() { }
/// OnScenarioComplete is called the after the entire scenario has completed
/// OnScenarioComplete is called the after the entire Scenario has completed
/// <summary>
/// OnIterationStart is called at the start of a new Scenario iteration
/// </summary>
protected virtual void OnIterationStart() { }
/// <summary>
/// OnIterationEnd is called the after a Scenario iteration has completed
/// </summary>
protected virtual void OnIterationEnd() { }
protected virtual void OnStartRunning() { }
[Obsolete("Method OnStartRunning has been deprecated. Use OnEnabled instead (UnityUpgradable)", true)]
protected virtual void OnStartRunning() =>
throw new NotSupportedException("OnStartRunning method has been deprecated");
protected virtual void OnStopRunning() { }
[Obsolete("Method OnStopRunning has been deprecated. Use OnDisable instead (UnityUpgradable)", true)]
protected virtual void OnStopRunning() =>
throw new NotSupportedException("OnStopRunning method has been deprecated");
/// <summary>
/// OnUpdate is executed every frame for enabled Randomizers

public virtual void OnDrawGizmos() { }
#region InternalScenarioMethods
internal void Awake() => OnAwake();
internal virtual void Create()
{
OnCreate();
}
internal void ScenarioStart() => OnScenarioStart();
internal virtual void IterationStart()
{
OnIterationStart();
}
internal void ScenarioComplete() => OnScenarioComplete();
internal virtual void IterationEnd()
{
OnIterationEnd();
}
internal virtual void ScenarioStart()
{
OnScenarioStart();
}
internal void IterationStart() => OnIterationStart();
internal virtual void ScenarioComplete()
{
OnScenarioComplete();
}
internal void IterationEnd() => OnIterationEnd();
internal void Update()
{
if (enabled)
{
if (!m_PreviouslyEnabled)
{
m_PreviouslyEnabled = true;
OnStartRunning();
}
OnUpdate();
}
else if (m_PreviouslyEnabled)
{
m_PreviouslyEnabled = false;
OnStopRunning();
}
}
internal void Update() => OnUpdate();
#endregion
}
}

2
com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Randomizers/BackgroundObjectPlacementRandomizer.cs


GameObjectOneWayCache m_GameObjectOneWayCache;
/// <inheritdoc/>
protected override void OnCreate()
protected override void OnAwake()
{
m_Container = new GameObject("BackgroundContainer");
m_Container.transform.parent = scenario.transform;

2
com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Randomizers/ForegroundObjectPlacementRandomizer.cs


GameObjectOneWayCache m_GameObjectOneWayCache;
/// <inheritdoc/>
protected override void OnCreate()
protected override void OnAwake()
{
m_Container = new GameObject("Foreground Objects");
m_Container.transform.parent = scenario.transform;

66
com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Utilities/GameObjectOneWayCache.cs


/// Facilitates object pooling for a pre-specified collection of prefabs with the caveat that objects can be fetched
/// from the cache but not returned. Every frame, the cache needs to be reset, which will return all objects to the pool
/// </summary>
class GameObjectOneWayCache
public class GameObjectOneWayCache
// Objects will reset to this origin when not being used
List<GameObject>[] m_InstantiatedObjects;
List<CachedObjectData>[] m_InstantiatedObjects;
/// <summary>
/// The number of active cache objects in the scene
/// </summary>
/// <summary>
/// Creates a new GameObjectOneWayCache
/// </summary>
/// <param name="parent">The parent object all cached instances will be parented under</param>
/// <param name="prefabs">The prefabs to cache</param>
m_InstantiatedObjects = new List<GameObject>[prefabs.Length];
m_InstantiatedObjects = new List<CachedObjectData>[prefabs.Length];
m_NumObjectsActive = new int[prefabs.Length];
var index = 0;

m_InstanceIdToIndex.Add(instanceId, index);
m_InstantiatedObjects[index] = new List<GameObject>();
m_InstantiatedObjects[index] = new List<CachedObjectData>();
/// <summary>
/// Retrieves an existing instance of the given prefab from the cache if available.
/// Otherwise, instantiate a new instance of the given prefab.
/// </summary>
/// <param name="prefab"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
{
}
++NumObjectsActive;
if (m_NumObjectsActive[index] < m_InstantiatedObjects[index].Count)

return nextInCache;
}
else
{
++NumObjectsInCache;
var newObject = Object.Instantiate(prefab, m_CacheParent);
++m_NumObjectsActive[index];
m_InstantiatedObjects[index].Add(newObject);
return newObject;
foreach (var tag in nextInCache.randomizerTags)
tag.Register();
return nextInCache.instance;
++NumObjectsInCache;
var newObject = Object.Instantiate(prefab, m_CacheParent);
++m_NumObjectsActive[index];
m_InstantiatedObjects[index].Add(new CachedObjectData(newObject));
return newObject;
/// <summary>
/// Return all active cache objects back to an inactive state
/// </summary>
public void ResetAllObjects()
{
using (s_ResetAllObjectsMarker.Auto())

{
m_NumObjectsActive[i] = 0;
foreach (var obj in m_InstantiatedObjects[i])
foreach (var cachedObjectData in m_InstantiatedObjects[i])
obj.transform.localPosition = new Vector3(10000, 0, 0);
cachedObjectData.instance.transform.localPosition = new Vector3(10000, 0, 0);
foreach (var tag in cachedObjectData.randomizerTags)
tag.Unregister();
}
}
struct CachedObjectData
{
public GameObject instance;
public RandomizerTag[] randomizerTags;
public CachedObjectData(GameObject instance)
{
this.instance = instance;
randomizerTags = instance.GetComponents<RandomizerTag>();
}
}
}

1
com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Utilities/PoissonDiskSampling.cs


/// <summary>
/// Utility for generating lists of poisson disk sampled points
/// </summary>
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Randomizers.SampleRandomizers")]
public static class PoissonDiskSampling
{
const int k_DefaultSamplingResolution = 30;

28
com.unity.perception/Runtime/Randomization/Randomizers/RandomizerTag.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Randomizers
{

/// </summary>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Randomizers")]
void OnDestroy()
/// <summary>
/// OnEnable is called when this RandomizerTag is enabled, either created, instantiated, or enabled via
/// the Unity Editor
/// </summary>
protected void OnEnable()
tagManager.RemoveTag(this);
Register();
protected virtual void OnEnable()
/// <summary>
/// OnDisable is called when this RandomizerTag is disabled
/// </summary>
protected virtual void OnDisable()
{
Unregister();
}
/// <summary>
/// Registers this tag with the tagManager
/// </summary>
public void Register()
protected virtual void OnDisable()
/// <summary>
/// Unregisters this tag with the tagManager
/// </summary>
public void Unregister()
{
tagManager.RemoveTag(this);
}

8
com.unity.perception/Runtime/Randomization/Randomizers/RandomizerTagManager.cs


using System;
using System.Collections.Generic;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Randomizers
{

[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Randomizers")]
public class RandomizerTagManager
{
/// <summary>

Dictionary<Type, HashSet<Type>> m_TypeTree = new Dictionary<Type, HashSet<Type>>();
Dictionary<Type, HashSet<RandomizerTag>> m_TagMap = new Dictionary<Type, HashSet<RandomizerTag>>();
Dictionary<Type, LinkedHashSet<RandomizerTag>> m_TagMap = new Dictionary<Type, LinkedHashSet<RandomizerTag>>();
/// <summary>
/// Enumerates over all RandomizerTags of the given type present in the scene

if (m_TypeTree.ContainsKey(tagType))
return;
m_TagMap.Add(tagType, new HashSet<RandomizerTag>());
m_TagMap.Add(tagType, new LinkedHashSet<RandomizerTag>());
m_TypeTree.Add(tagType, new HashSet<Type>());
var baseType = tagType.BaseType;

{
m_TagMap.Add(baseType, new HashSet<RandomizerTag>());
m_TagMap.Add(baseType, new LinkedHashSet<RandomizerTag>());
m_TypeTree[baseType] = new HashSet<Type> { tagType };
}
else

2
com.unity.perception/Runtime/Randomization/Samplers/FloatRange.cs


using System;
using UnityEngine.Scripting.APIUpdating;
using Assert = UnityEngine.Assertions.Assert;
namespace UnityEngine.Perception.Randomization.Samplers

/// </summary>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Samplers")]
public struct FloatRange
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Samplers/ISampler.cs


using System;
using UnityEngine;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Samplers
{

[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Samplers")]
public interface ISampler
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Samplers
{

/// The Y values cannot however be negative.
/// </summary>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Samplers")]
public class AnimationCurveSampler : ISampler
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/ConstantSampler.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Samplers
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Samplers")]
public class ConstantSampler : ISampler
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/NormalSampler.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Samplers
{

/// </summary>
[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Samplers")]
public class NormalSampler : ISampler
{
/// <summary>

2
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/UniformSampler.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Samplers
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Samplers")]
public class UniformSampler : ISampler
{
/// <summary>

6
com.unity.perception/Runtime/Randomization/Scenarios/FixedLengthScenario.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Scenarios
{

[AddComponentMenu("Perception/Randomization/Scenarios/Fixed Length Scenario")]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Scenarios")]
[AddComponentMenu("Perception/Scenarios/Fixed Length Scenario")]
public class FixedLengthScenario: UnitySimulationScenario<FixedLengthScenario.Constants>
{
/// <summary>

/// <summary>
/// Returns whether the current scenario iteration has completed
/// </summary>
public override bool isIterationComplete => currentIterationFrame >= constants.framesPerIteration;
protected override bool isIterationComplete => currentIterationFrame >= constants.framesPerIteration;
}
}

206
com.unity.perception/Runtime/Randomization/Scenarios/Scenario.cs


using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine.Perception.Randomization.Parameters;
using UnityEngine.Perception.Randomization.Randomizers;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Scenarios
{

/// <typeparam name="T">The type of scenario constants to serialize</typeparam>
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Scenarios")]
public abstract class Scenario<T> : ScenarioBase where T : ScenarioConstants, new()
{
/// <summary>

/// <inheritdoc/>
public override ScenarioConstants genericConstants => constants;
/// <inheritdoc/>
public override string SerializeToJson()
{
var configObj = new JObject
{
["constants"] = SerializeConstants(),
["randomizers"] = SerializeRandomizers()
};
return JsonConvert.SerializeObject(configObj, Formatting.Indented);
}
JObject SerializeConstants()
{
var constantsObj = new JObject();
var constantsFields = constants.GetType().GetFields();
foreach (var constantsField in constantsFields)
constantsObj.Add(new JProperty(constantsField.Name, constantsField.GetValue(constants)));
return constantsObj;
}
JObject SerializeRandomizers()
{
var randomizersObj = new JObject();
foreach (var randomizer in m_Randomizers)
{
var randomizerObj = SerializeRandomizer(randomizer);
if (randomizerObj.Count > 0)
randomizersObj.Add(new JProperty(randomizer.GetType().Name, randomizerObj));
}
return randomizersObj;
}
static JObject SerializeRandomizer(Randomizer randomizer)
{
var randomizerObj = new JObject();
var parameterFields = randomizer.GetType().GetFields();
foreach (var parameterField in parameterFields)
{
if (!IsSubclassOfRawGeneric(typeof(NumericParameter<>), parameterField.FieldType))
continue;
var parameter = (Parameter)parameterField.GetValue(randomizer);
var parameterObj = SerializeParameter(parameter);
if (parameterObj.Count > 0)
randomizerObj.Add(new JProperty(parameterField.Name, parameterObj));
}
return randomizerObj;
}
static JObject SerializeParameter(Parameter parameter)
{
var parameterObj = new JObject();
var samplerFields = parameter.GetType().GetFields();
foreach (var samplerField in samplerFields)
{
if (samplerField.FieldType != typeof(ISampler))
continue;
var sampler = (ISampler)samplerField.GetValue(parameter);
var samplerObj = SerializeSampler(sampler);
parameterObj.Add(new JProperty(samplerField.Name, samplerObj));
}
return parameterObj;
}
static JObject SerializeSampler(ISampler sampler)
{
var samplerObj = new JObject();
var fields = sampler.GetType().GetFields();
foreach (var field in fields)
{
samplerObj.Add(new JProperty(field.Name, JToken.FromObject(field.GetValue(sampler))));
}
if (sampler.GetType() != typeof(ConstantSampler))
{
var rangeProperty = sampler.GetType().GetProperty("range");
if (rangeProperty != null)
{
var range = (FloatRange)rangeProperty.GetValue(sampler);
var rangeObj = new JObject
{
new JProperty("minimum", range.minimum),
new JProperty("maximum", range.maximum)
};
samplerObj.Add(new JProperty("range", rangeObj));
}
}
return samplerObj;
}
/// <inheritdoc/>
public override void DeserializeFromFile(string configFilePath)
{
if (string.IsNullOrEmpty(configFilePath))
throw new ArgumentNullException();
if (!File.Exists(configFilePath))
throw new FileNotFoundException($"A scenario configuration file does not exist at path {configFilePath}");
#if UNITY_EDITOR
Debug.Log($"Deserialized scenario configuration from <a href=\"file:///${configFilePath}\">{configFilePath}</a>. " +
"Using undo in the editor will revert these changes to your scenario.");
#else
Debug.Log($"Deserialized scenario configuration from <a href=\"file:///${configFilePath}\">{configFilePath}</a>");
#endif
var jsonText = File.ReadAllText(configFilePath);
DeserializeFromJson(jsonText);
}
/// <inheritdoc/>
public override void DeserializeFromJson(string json)
{
var jsonObj = JObject.Parse(json);
var constantsObj = (JObject)jsonObj["constants"];
DeserializeConstants(constantsObj);
var randomizersObj = (JObject)jsonObj["randomizers"];
DeserializeRandomizers(randomizersObj);
}
void DeserializeConstants(JObject constantsObj)
{
constants = constantsObj.ToObject<T>();
}
void DeserializeRandomizers(JObject randomizersObj)
{
var randomizerTypeMap = new Dictionary<string, Randomizer>();
foreach (var randomizer in randomizers)
randomizerTypeMap.Add(randomizer.GetType().Name, randomizer);
foreach (var randomizerPair in randomizersObj)
{
if (!randomizerTypeMap.ContainsKey(randomizerPair.Key))
continue;
var randomizer = randomizerTypeMap[randomizerPair.Key];
var randomizerObj = (JObject)randomizerPair.Value;
DeserializeRandomizer(randomizer, randomizerObj);
}
}
static void DeserializeRandomizer(Randomizer randomizer, JObject randomizerObj)
{
foreach (var parameterPair in randomizerObj)
{
var parameterField = randomizer.GetType().GetField(parameterPair.Key);
if (parameterField == null)
continue;
var parameter = (Parameter)parameterField.GetValue(randomizer);
var parameterObj = (JObject)parameterPair.Value;
DeserializeParameter(parameter, parameterObj);
}
}
static void DeserializeParameter(Parameter parameter, JObject parameterObj)
{
foreach (var samplerPair in parameterObj)
{
var samplerField = parameter.GetType().GetField(samplerPair.Key);
if (samplerField == null)
continue;
var sampler = (ISampler)samplerField.GetValue(parameter);
var samplerObj = (JObject)samplerPair.Value;
DeserializeSampler(sampler, samplerObj);
}
}
static void DeserializeSampler(ISampler sampler, JObject samplerObj)
{
foreach (var samplerFieldPair in samplerObj)
{
if (samplerFieldPair.Key == "range")
{
var rangeObj = (JObject)samplerFieldPair.Value;
var field = sampler.GetType().GetField(samplerFieldPair.Key);
var range = new FloatRange(rangeObj["minimum"].ToObject<float>(), rangeObj["maximum"].ToObject<float>());
field.SetValue(sampler, range);
}
else
{
var field = sampler.GetType().GetField(samplerFieldPair.Key);
if (field != null)
{
field.SetValue(sampler, JsonConvert.DeserializeObject(samplerFieldPair.Value.ToString(), field.FieldType));
}
}
}
}
static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
while (toCheck != null && toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
}
}

506
com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs


using System;
using System.Collections.Generic;
using System.IO;
using Unity.Simulation;
using UnityEditor;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.Scripting.APIUpdating;
using UnityEngine.Perception.Randomization.Scenarios.Serialization;
namespace UnityEngine.Perception.Randomization.Scenarios
{

[DefaultExecutionOrder(-1)]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Scenarios")]
const string k_ScenarioIterationMetricDefinitionId = "DB1B258E-D1D0-41B6-8751-16F601A2E230";
bool m_SkipFrame = true;
bool m_FirstScenarioFrame = true;
bool m_WaitingForFinalUploads;
MetricDefinition m_IterationMetricDefinition;
IEnumerable<Randomizer> activeRandomizers
/// <summary>
/// Returns the active parameter scenario in the scene
/// </summary>
public static ScenarioBase activeScenario
get
get => s_ActiveScenario;
private set
foreach (var randomizer in m_Randomizers)
if (randomizer.enabled)
yield return randomizer;
if (value != null && s_ActiveScenario != null && value != s_ActiveScenario)
throw new ScenarioException("There cannot be more than one active Scenario");
s_ActiveScenario = value;
// ReSharper disable once InconsistentNaming
[SerializeReference] internal List<Randomizer> m_Randomizers = new List<Randomizer>();
/// Return the list of randomizers attached to this scenario
/// </summary>
public IReadOnlyList<Randomizer> randomizers => m_Randomizers.AsReadOnly();
/// <summary>
/// If true, this scenario will quit the Unity application when it's finished executing
/// The current activity state of the scenario
[HideInInspector] public bool quitOnComplete = true;
public State state { get; private set; } = State.Initializing;
/// The name of the Json file this scenario's constants are serialized to/from.
/// The list of randomizers managed by this scenario
public virtual string configFileName => "scenario_configuration";
[SerializeReference] List<Randomizer> m_Randomizers = new List<Randomizer>();
/// Returns the active parameter scenario in the scene
/// Enumerates over all enabled randomizers
public static ScenarioBase activeScenario
public IEnumerable<Randomizer> activeRandomizers
#if UNITY_EDITOR
// This compiler define is required to allow samplers to
// iterate the scenario's random state in edit-mode
if (s_ActiveScenario == null)
s_ActiveScenario = FindObjectOfType<ScenarioBase>();
#endif
return s_ActiveScenario;
}
private set
{
if (value != null && s_ActiveScenario != null && value != s_ActiveScenario)
throw new ScenarioException("There cannot be more than one active Scenario");
s_ActiveScenario = value;
foreach (var randomizer in m_Randomizers)
if (randomizer.enabled)
yield return randomizer;
/// Returns the asset location of the JSON serialized configuration.
/// This API is used for finding the config file using the AssetDatabase API.
/// Return the list of randomizers attached to this scenario
public string defaultConfigFileAssetPath =>
"Assets/StreamingAssets/" + configFileName + ".json";
/// <summary>
/// Returns the absolute file path of the JSON serialized configuration
/// </summary>
public string defaultConfigFilePath =>
Application.dataPath + "/StreamingAssets/" + configFileName + ".json";
public IReadOnlyList<Randomizer> randomizers => m_Randomizers.AsReadOnly();
/// <summary>
/// Returns this scenario's non-typed serialized constants

/// The current iteration index of the scenario
/// </summary>
public int currentIteration { get; protected set; }
/// <summary>
/// The scenario will begin on the frame this property first returns true
/// </summary>
/// <returns>Whether the scenario should start this frame</returns>
protected abstract bool isScenarioReadyToStart { get; }
public abstract bool isIterationComplete { get; }
protected abstract bool isIterationComplete { get; }
/// Returns whether the entire scenario has completed
/// Returns whether the scenario has completed
public abstract bool isScenarioComplete { get; }
protected abstract bool isScenarioComplete { get; }
/// Progresses the current scenario iteration
/// This method selects what the next iteration index will be. By default, the scenario will simply progress to
/// the next iteration, but this behaviour can be overriden.
/// </summary>
protected virtual void IncrementIteration()
{

/// Serializes the scenario's constants and randomizer settings to a JSON string
/// </summary>
/// <returns>The scenario configuration as a JSON string</returns>
public abstract string SerializeToJson();
public virtual string SerializeToJson()
{
return ScenarioSerializer.SerializeToJsonString(this);
}
public void SerializeToFile()
/// <param name="filePath">The file path to serialize the scenario to</param>
public virtual void SerializeToFile(string filePath)
Directory.CreateDirectory(Application.dataPath + "/StreamingAssets/");
using (var writer = new StreamWriter(defaultConfigFilePath, false))
writer.Write(SerializeToJson());
ScenarioSerializer.SerializeToFile(this, filePath);
}
/// <summary>

public abstract void DeserializeFromJson(string json);
public virtual void DeserializeFromJson(string json)
{
ScenarioSerializer.Deserialize(this, json);
}
/// <summary>
/// Overwrites this scenario's randomizer settings and scenario constants using a configuration file located at

public abstract void DeserializeFromFile(string configFilePath);
public virtual void DeserializeFromFile(string configFilePath)
{
if (string.IsNullOrEmpty(configFilePath))
throw new ArgumentException($"{nameof(configFilePath)} is null or empty");
if (!File.Exists(configFilePath))
throw new ArgumentException($"No configuration file found at {configFilePath}");
var jsonText = File.ReadAllText(configFilePath);
DeserializeFromJson(jsonText);
#if !UNITY_EDITOR
Debug.Log($"Deserialized scenario configuration from {Path.GetFullPath(configFilePath)}");
#endif
}
/// <summary>
/// Deserialize scenario settings from a file passed through a command line argument
/// </summary>
/// <param name="commandLineArg">The command line argument to look for</param>
protected virtual void DeserializeFromCommandLine(string commandLineArg="--scenario-config-file")
{
var args = Environment.GetCommandLineArgs();
var filePath = string.Empty;
for (var i = 0; i < args.Length - 1; i++)
{
if (args[i] != "--scenario-config-file")
continue;
filePath = args[i + 1];
break;
}
if (string.IsNullOrEmpty(filePath))
{
Debug.Log("No --scenario-config-file command line arg specified. " +
"Proceeding with editor assigned scenario configuration values.");
return;
}
try { DeserializeFromFile(filePath); }
catch (Exception exception)
{
Debug.LogException(exception);
Debug.LogError("An exception was caught while attempting to parse a " +
$"scenario configuration file at {filePath}. Cleaning up and exiting simulation.");
}
}
/// Overwrites this scenario's randomizer settings and scenario constants using a configuration file located at
/// this scenario's defaultConfigFilePath
/// Resets SamplerState.randomState with a new seed value generated by hashing this Scenario's randomSeed
/// with its currentIteration
public void DeserializeFromFile()
protected virtual void ResetRandomStateOnIteration()
DeserializeFromFile(defaultConfigFilePath);
SamplerState.randomState = SamplerUtility.IterateSeed((uint)currentIteration, genericConstants.randomSeed);
#region LifecycleHooks
/// This method executed directly after this scenario has been registered and initialized
/// OnAwake is called when this scenario MonoBehaviour is created or instantiated
void Awake()
/// <summary>
/// OnConfigurationImport is called before OnStart in the same frame. This method by default loads a scenario
/// settings from a file before the scenario begins.
/// </summary>
protected virtual void OnConfigurationImport()
activeScenario = this;
OnAwake();
foreach (var randomizer in m_Randomizers)
randomizer.Create();
ValidateParameters();
#if !UNITY_EDITOR
DeserializeFromCommandLine();
#endif
}
// Don't skip the first frame if executing on Unity Simulation
if (Configuration.Instance.IsSimulationRunningInCloud())
m_SkipFrame = false;
/// <summary>
/// OnStart is called when the scenario first begins playing
/// </summary>
protected virtual void OnStart() { }
m_IterationMetricDefinition = DatasetCapture.RegisterMetricDefinition("scenario_iteration", "Iteration information for dataset sequences",
Guid.Parse(k_ScenarioIterationMetricDefinitionId));
}
/// <summary>
/// OnIterationStart is called before a new iteration begins
/// </summary>
protected virtual void OnIterationStart() { }
void OnEnable()
/// <summary>
/// OnIterationStart is called after each iteration has completed
/// </summary>
protected virtual void OnIterationEnd() { }
/// <summary>
/// OnUpdate is called every frame while the scenario is playing
/// </summary>
protected virtual void OnUpdate() { }
/// <summary>
/// OnComplete is called when this scenario's isScenarioComplete property
/// returns true during its main update loop
/// </summary>
protected virtual void OnComplete() { }
/// <summary>
/// OnIdle is called each frame after the scenario has completed
/// </summary>
protected virtual void OnIdle() { }
/// <summary>
/// Restart the scenario
/// </summary>
public void Restart()
activeScenario = this;
if (state != State.Idle)
throw new ScenarioException(
"A Scenario cannot be restarted until it is finished and has entered the Idle state");
currentIteration = 0;
currentIterationFrame = 0;
framesSinceInitialization = 0;
state = State.Initializing;
void OnDisable()
/// <summary>
/// Exit to playmode if in the Editor or quit the application if in a built player
/// </summary>
protected void Quit()
activeScenario = null;
#if UNITY_EDITOR
EditorApplication.ExitPlaymode();
#else
Application.Quit();
#endif
#endregion
void Start()
#region MonoBehaviourMethods
void Awake()
currentIteration = (int)genericConstants.startFrame;
var randomSeedMetricDefinition = DatasetCapture.RegisterMetricDefinition(
"random-seed",
"The random seed used to initialize the random state of the simulation. Only triggered once per simulation.",
Guid.Parse("14adb394-46c0-47e8-a3f0-99e754483b76"));
DatasetCapture.ReportMetric(randomSeedMetricDefinition, new[] { genericConstants.randomSeed });
#if !UNITY_EDITOR
if (File.Exists(defaultConfigFilePath))
DeserializeFromFile();
else
Debug.Log($"No configuration file found at {defaultConfigFilePath}. " +
"Proceeding with built in scenario constants and randomizer settings.");
#endif
activeScenario = this;
OnAwake();
foreach (var randomizer in m_Randomizers)
randomizer.Awake();
ValidateParameters();
}
foreach (var randomizer in activeRandomizers)
randomizer.ScenarioStart();
/// <summary>
/// OnEnable is called when this scenario is enabled
/// </summary>
protected virtual void OnEnable()
{
activeScenario = this;
struct IterationMetricData
/// <summary>
/// OnEnable is called when this scenario is disabled
/// </summary>
protected virtual void OnDisable()
public int iteration;
activeScenario = null;
// TODO: remove this check when the perception camera can capture the first frame of output
if (m_SkipFrame)
switch (state)
m_SkipFrame = false;
return;
}
case State.Initializing:
if (isScenarioReadyToStart)
{
OnConfigurationImport();
state = State.Playing;
OnStart();
foreach (var randomizer in m_Randomizers)
randomizer.ScenarioStart();
IterationLoop();
}
break;
// Wait for any final uploads before exiting quitting
if (m_WaitingForFinalUploads && quitOnComplete)
{
Manager.Instance.Shutdown();
if (!Manager.FinalUploadsDone)
return;
#if UNITY_EDITOR
UnityEditor.EditorApplication.ExitPlaymode();
#else
Application.Quit();
#endif
return;
case State.Playing:
IterationLoop();
break;
case State.Idle:
OnIdle();
break;
default:
throw new ArgumentOutOfRangeException(
$"Invalid state {state} encountered while updating scenario");
}
#endregion
// Iterate Scenario
if (m_FirstScenarioFrame)
{
m_FirstScenarioFrame = false;
}
else
void IterationLoop()
{
// Increment iteration and cleanup last iteration
if (isIterationComplete)
currentIterationFrame++;
framesSinceInitialization++;
if (isIterationComplete)
{
IncrementIteration();
currentIterationFrame = 0;
foreach (var randomizer in activeRandomizers)
randomizer.IterationEnd();
}
IncrementIteration();
currentIterationFrame = 0;
foreach (var randomizer in activeRandomizers)
randomizer.IterationEnd();
OnIterationEnd();
}
// Quit if scenario is complete

randomizer.ScenarioComplete();
DatasetCapture.ResetSimulation();
m_WaitingForFinalUploads = true;
OnComplete();
state = State.Idle;
OnIdle();
return;
}

DatasetCapture.StartNewSequence();
SamplerState.randomState = SamplerUtility.IterateSeed((uint)currentIteration, genericConstants.randomSeed);
DatasetCapture.ReportMetric(m_IterationMetricDefinition, new[]
{
new IterationMetricData()
{
iteration = currentIteration
}
});
ResetRandomStateOnIteration();
OnIterationStart();
OnUpdate();
// Iterate scenario frame count
currentIterationFrame++;
framesSinceInitialization++;
}
void OnDrawGizmos()

}
/// <summary>
/// Finds and returns a randomizer attached to this scenario of the specified Randomizer type
/// Called by the "Add Randomizer" button in the scenario Inspector
/// <typeparam name="T">The type of randomizer to find</typeparam>
/// <returns>A randomizer of the specified type</returns>
/// <param name="randomizerType">The type of randomizer to create</param>
/// <returns>The newly created randomizer</returns>
public T GetRandomizer<T>() where T : Randomizer
internal Randomizer CreateRandomizer(Type randomizerType)
foreach (var randomizer in m_Randomizers)
if (randomizer is T typedRandomizer)
return typedRandomizer;
throw new ScenarioException($"A Randomizer of type {typeof(T).Name} was not added to this scenario");
if (!randomizerType.IsSubclassOf(typeof(Randomizer)))
throw new ScenarioException(
$"Cannot add non-randomizer type {randomizerType.Name} to randomizer list");
var newRandomizer = (Randomizer)Activator.CreateInstance(randomizerType);
AddRandomizer(newRandomizer);
return newRandomizer;
/// Creates a new randomizer and adds it to this scenario
/// Append a randomizer to the end of the randomizer list
/// <typeparam name="T">The type of randomizer to create</typeparam>
/// <returns>The newly created randomizer</returns>
public T CreateRandomizer<T>() where T : Randomizer, new()
/// <param name="newRandomizer">The Randomizer to add to the Scenario</param>
public void AddRandomizer(Randomizer newRandomizer)
return (T)CreateRandomizer(typeof(T));
InsertRandomizer(m_Randomizers.Count, newRandomizer);
internal Randomizer CreateRandomizer(Type randomizerType)
/// <summary>
/// Insert a randomizer at a given index within the randomizer list
/// </summary>
/// <param name="index">The index to place the randomizer</param>
/// <param name="newRandomizer">The randomizer to add to the list</param>
/// <exception cref="ScenarioException"></exception>
public void InsertRandomizer(int index, Randomizer newRandomizer)
if (!randomizerType.IsSubclassOf(typeof(Randomizer)))
throw new ScenarioException(
$"Cannot add non-randomizer type {randomizerType.Name} to randomizer list");
if (state != State.Initializing)
throw new ScenarioException("Randomizers cannot be added to the scenario after it has started");
if (randomizer.GetType() == randomizerType)
if (randomizer.GetType() == newRandomizer.GetType())
$"Two Randomizers of the same type ({randomizerType.Name}) cannot both be active simultaneously");
var newRandomizer = (Randomizer)Activator.CreateInstance(randomizerType);
m_Randomizers.Add(newRandomizer);
$"Cannot add another randomizer of type ${newRandomizer.GetType()} when " +
$"a scenario of this type is already present in the scenario");
m_Randomizers.Insert(index, newRandomizer);
newRandomizer.Create();
newRandomizer.Awake();
newRandomizer.Create();
newRandomizer.Awake();
return newRandomizer;
/// Removes a randomizer of the specified type from this scenario
/// Remove the randomizer present at the given index
/// <typeparam name="T">The type of scenario to remove</typeparam>
public void RemoveRandomizer<T>() where T : Randomizer, new()
{
RemoveRandomizer(typeof(T));
}
internal void RemoveRandomizer(Type randomizerType)
/// <param name="index">The index of the randomizer to remove</param>
public void RemoveRandomizerAt(int index)
if (!randomizerType.IsSubclassOf(typeof(Randomizer)))
throw new ScenarioException(
$"Cannot remove non-randomizer type {randomizerType.Name} from randomizer list");
var removed = false;
for (var i = 0; i < m_Randomizers.Count; i++)
{
if (m_Randomizers[i].GetType() == randomizerType)
{
m_Randomizers.RemoveAt(i);
removed = true;
break;
}
}
if (!removed)
throw new ScenarioException(
$"No active Randomizer of type {randomizerType.Name} could be removed");
if (state != State.Initializing)
throw new ScenarioException("Randomizers cannot be added to the scenario after it has started");
m_Randomizers.RemoveAt(index);
/// Returns the execution order index of a randomizer of the given type
/// Returns the randomizer present at the given index
/// <typeparam name="T">The type of randomizer to index</typeparam>
/// <returns>The randomizer index</returns>
/// <exception cref="ScenarioException"></exception>
public int GetRandomizerIndex<T>() where T : Randomizer, new()
/// <param name="index">The lookup index</param>
/// <returns>The randomizer present at the given index</returns>
public Randomizer GetRandomizer(int index)
for (var i = 0; i < m_Randomizers.Count; i++)
{
var randomizer = m_Randomizers[i];
if (randomizer is T)
return i;
}
throw new ScenarioException($"A Randomizer of type {typeof(T).Name} was not added to this scenario");
return m_Randomizers[index];
/// Moves a randomizer from one index to another
/// Finds and returns a randomizer attached to this scenario of the specified Randomizer type
/// <param name="currentIndex">The index of the randomizer to move</param>
/// <param name="nextIndex">The index to move the randomizer to</param>
public void ReorderRandomizer(int currentIndex, int nextIndex)
/// <typeparam name="T">The type of randomizer to find</typeparam>
/// <returns>A randomizer of the specified type</returns>
/// <exception cref="ScenarioException"></exception>
public T GetRandomizer<T>() where T : Randomizer
if (currentIndex == nextIndex)
return;
if (nextIndex > currentIndex)
nextIndex--;
var randomizer = m_Randomizers[currentIndex];
m_Randomizers.RemoveAt(currentIndex);
m_Randomizers.Insert(nextIndex, randomizer);
foreach (var randomizer in m_Randomizers)
if (randomizer is T typedRandomizer)
return typedRandomizer;
throw new ScenarioException($"A Randomizer of type {typeof(T).Name} was not added to this scenario");
}
void ValidateParameters()

{
try
{
parameter.Validate();
}
catch (ParameterValidationException exception)
{
Debug.LogException(exception, this);
}
try { parameter.Validate(); }
catch (ParameterValidationException exception) { Debug.LogException(exception, this); }
}
/// <summary>
/// Enum used to track the lifecycle of a Scenario
/// </summary>
public enum State
{
Initializing,
Playing,
Idle
}
}
}

2
com.unity.perception/Runtime/Randomization/Scenarios/ScenarioConstants.cs


using System;
using UnityEngine.Perception.Randomization.Samplers;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Scenarios
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Scenarios")]
public class ScenarioConstants
{
/// <summary>

45
com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenario.cs


using System;
using Unity.Simulation;
using UnityEngine.Scripting.APIUpdating;
/// Defines a scenario that is compatible with the Run in Unity Simulation window
/// A scenario must derive from this class to be compatible with the Run in
/// Unity Simulation window. The iterations of this scenario will be executed in parallel across a user specified
/// number of worker instances when run in Unity Simulation.
/// <typeparam name="T">The type of constants to serialize</typeparam>
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Scenarios")]
public abstract class UnitySimulationScenario<T> : Scenario<T> where T : UnitySimulationScenarioConstants, new()
/// <typeparam name="T">The type of scenario constants to serialize</typeparam>
public abstract class UnitySimulationScenario<T> : PerceptionScenario<T>
where T : UnitySimulationScenarioConstants, new()
public sealed override bool isScenarioComplete => currentIteration >= constants.totalIterations;
protected override bool isScenarioReadyToStart
{
get
{
if (!Configuration.Instance.IsSimulationRunningInCloud() && !m_SkippedFirstFrame)
{
m_SkippedFirstFrame = true;
return false;
}
return true;
}
}
protected sealed override void IncrementIteration()
protected sealed override bool isScenarioComplete => currentIteration >= constants.totalIterations;
/// <inheritdoc/>
protected override void OnConfigurationImport()
currentIteration += constants.instanceCount;
if (Configuration.Instance.IsSimulationRunningInCloud())
{
DeserializeFromFile(new Uri(Configuration.Instance.SimulationConfig.app_param_uri).LocalPath);
constants.instanceIndex = int.Parse(Configuration.Instance.GetInstanceId()) - 1;
}
else
base.OnConfigurationImport();
currentIteration = constants.instanceIndex;
public sealed override void DeserializeFromFile(string configFilePath)
protected sealed override void IncrementIteration()
base.DeserializeFromFile(Configuration.Instance.IsSimulationRunningInCloud()
? new Uri(Configuration.Instance.SimulationConfig.app_param_uri).LocalPath
: configFilePath);
currentIteration = constants.instanceIndex;
currentIteration += constants.instanceCount;
}
}
}

2
com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenarioConstants.cs


using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Perception.Randomization.Scenarios
{

[Serializable]
[MovedFrom("UnityEngine.Experimental.Perception.Randomization.Scenarios")]
public class UnitySimulationScenarioConstants : ScenarioConstants
{
/// <summary>

30
com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs


public IEnumerator EditorPause_DoesNotLogErrors()
{
ResetScene();
SetupCamera(p =>
var cameraObject = SetupCamera(p =>
{
var idLabelConfig = ScriptableObject.CreateInstance<IdLabelConfig>();
p.captureRgbImages = true;

cameraObject.name = "Camera";
yield return new EnterPlayMode();
var expectedFirstFrame = Time.frameCount;
yield return null;

var capturesJson = File.ReadAllText(capturesPath);
for (int iFrameCount = expectedFirstFrame; iFrameCount <= expectedLastFrame; iFrameCount++)
{
var imagePath = $"{PerceptionCamera.RgbDirectory}/rgb_{iFrameCount}";
var imagePath = $"{GameObject.Find("Camera").GetComponent<PerceptionCamera>().rgbDirectory}/rgb_{iFrameCount}";
StringAssert.Contains(imagePath, capturesJson);
}

yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator Labeler_ShouldSetupAndUpdateAndOnBeginRenderingInFirstFrame()
public IEnumerator Labeler_ShouldRunCallbacksInFirstFrame()
{
ResetScene();
yield return new EnterPlayMode();

yield return null;
mockLabeler.Protected().Verify("OnEndRendering", Times.Once());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator Labeler_ShouldNotRunCallbacksWhenCameraDisabled()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
var camera = SetupCamera(null);
var perceptionCamera = camera.GetComponent<PerceptionCamera>();
perceptionCamera.AddLabeler(mockLabeler.Object);
yield return null;
perceptionCamera.enabled = false;
yield return null;
mockLabeler.Protected().Verify("Setup", Times.Once());
mockLabeler.Protected().Verify("OnUpdate", Times.Once());
mockLabeler.Protected().Verify("OnBeginRendering", Times.Once());
mockLabeler.Protected().Verify("OnEndRendering", Times.Once());
yield return new ExitPlayMode();
}
[UnityTest]

mockLabeler.Protected().Verify("Setup", Times.Never());
mockLabeler.Protected().Verify("OnUpdate", Times.Never());
mockLabeler.Protected().Verify("OnBeginRendering", Times.Never());
mockLabeler.Protected().Verify("OnEndRendering", Times.Never());
mockLabeler.Protected().Verify("Cleanup", Times.Never());
yield return new ExitPlayMode();
}

mockLabeler.Protected().Verify("Setup", Times.Once());
mockLabeler.Protected().Verify("OnUpdate", Times.Never());
mockLabeler.Protected().Verify("OnBeginRendering", Times.Never());
mockLabeler.Protected().Verify("OnEndRendering", Times.Never());
Assert.IsFalse(labeler.enabled);
yield return new ExitPlayMode();
}

4
com.unity.perception/Tests/Editor/RandomizerEditorTests.cs


// if ScenarioBase.CreateRandomizer<>() was coded correctly
Assert.DoesNotThrow(() =>
{
m_Scenario.CreateRandomizer<ErrorsOnCreateTestRandomizer>();
m_Scenario.AddRandomizer(new ErrorsOnCreateTestRandomizer());
});
}
}

{
public GameObject testGameObject;
protected override void OnCreate()
protected override void OnAwake()
{
// This line should throw a NullReferenceException
testGameObject.transform.position = Vector3.zero;

9
com.unity.perception/Tests/Runtime/GroundTruthTests/GroundTruthTestBase.cs


using NUnit.Framework;
using UnityEngine;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
namespace GroundTruthTests

List<Object> m_ObjectsToDestroy = new List<Object>();
List<string> m_ScenesToUnload = new List<string>();
[TearDown]
public void TearDown()
{

m_ObjectsToDestroy.Clear();
foreach (var s in m_ScenesToUnload)
SceneManager.UnloadSceneAsync(s);
m_ScenesToUnload.Clear();
DatasetCapture.ResetSimulation();
Time.timeScale = 1;
if (Directory.Exists(DatasetCapture.OutputDirectory))

public void AddTestObjectForCleanup(Object @object) => m_ObjectsToDestroy.Add(@object);
public void AddSceneForCleanup(string sceneName) => m_ScenesToUnload.Add(sceneName);
public void DestroyTestObject(Object @object)
{

29
com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs


public class SegmentationPassTests : GroundTruthTestBase
{
static readonly Color32 k_SemanticPixelValue = new Color32(10, 20, 30, Byte.MaxValue);
private static readonly Color32 k_InstanceSegmentationPixelValue = new Color32(255,0,0, 255);
public enum SegmentationKind
{

{
case SegmentationKind.Instance:
//expectedPixelValue = new Color32(0, 74, 255, 255);
expectedPixelValue = new Color32(255,0,0, 255);
expectedPixelValue = k_InstanceSegmentationPixelValue;
cameraObject = SetupCameraInstanceSegmentation(OnSegmentationImageReceived);
break;
case SegmentationKind.Semantic:

Assert.AreEqual(2, timesSegmentationImageReceived);
}
[UnityTest]
public IEnumerator InstanceSegmentationPass_WithSeparateDisabledPerceptionCamera_ProducesCorrectValues()
{
int timesSegmentationImageReceived = 0;
void OnSegmentationImageReceived(NativeArray<Color32> data)
{
CollectionAssert.AreEqual(Enumerable.Repeat(k_InstanceSegmentationPixelValue, data.Length), data);
timesSegmentationImageReceived++;
}
var cameraObject = SetupCameraInstanceSegmentation((frame, data, renderTexture) => OnSegmentationImageReceived(data));
var cameraObject2 = SetupCameraInstanceSegmentation(null);
cameraObject2.SetActive(false);
var plane = TestHelper.CreateLabeledPlane();
AddTestObjectForCleanup(plane);
yield return null;
//destroy the object to force all pending segmented image readbacks to finish and events to be fired.
DestroyTestObject(cameraObject);
DestroyTestObject(cameraObject2);
Assert.AreEqual(1, timesSegmentationImageReceived);
}
[UnityTest]
public IEnumerator SegmentationPassProducesCorrectValuesEachFrame(
[Values(SegmentationKind.Instance, SegmentationKind.Semantic)] SegmentationKind segmentationKind)

SetupCameraSemanticSegmentation((a) => OnSegmentationImageReceived<Color32>(a.frameCount, a.data, a.sourceTexture), false);
//object expectedPixelValue = segmentationKind == SegmentationKind.Instance ? (object) new Color32(0, 74, 255, 255) : k_SemanticPixelValue;
object expectedPixelValue = segmentationKind == SegmentationKind.Instance ? (object) new Color32(255, 0, 0, 255) : k_SemanticPixelValue;
object expectedPixelValue = segmentationKind == SegmentationKind.Instance ? (object) k_InstanceSegmentationPixelValue : k_SemanticPixelValue;
expectedLabelAtFrame = new Dictionary<int, object>
{

7
com.unity.perception/Tests/Runtime/GroundTruthTests/VisualizationTests.cs


Assert.IsNotNull(GameObject.Find("overlay_canvas"));
}
[Test]
public void TwoCamerasVisualizing_CausesWarningAndDisablesVisualization()
[UnityTest]
public IEnumerator TwoCamerasVisualizing_CausesWarningAndDisablesVisualization()
{
var object1 = new GameObject();
object1.name = nameof(TwoCamerasVisualizing_CausesWarningAndDisablesVisualization);

AddTestObjectForCleanup(object2);
object1.SetActive(true);
yield return null;
LogAssert.ignoreFailingMessages = true;
yield return null;
}
[UnityTest]
public IEnumerator DestroyCamera_RemovesVisualization()

409
com.unity.perception/Tests/Runtime/GroundTruthTests/KeypointGroundTruthTests.cs


using NUnit.Framework;
using UnityEngine;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.SceneManagement;
public class KeyPointGroundTruthTests : GroundTruthTestBase
public class KeyPointGroundTruthTests : GroundTruthTestBase, IPrebuildSetup, IPostBuildCleanup
static GameObject SetupCamera(IdLabelConfig config, KeyPointTemplate template, Action<List<KeyPointLabeler.KeyPointEntry>> computeListener)
private const string kAnimatedCubeScenePath = "Packages/com.unity.perception/Tests/Runtime/TestAssets/AnimatedCubeScene.unity";
public void Setup()
{
#if UNITY_EDITOR
var scenes = UnityEditor.EditorBuildSettings.scenes.ToList();
scenes.Add(new UnityEditor.EditorBuildSettingsScene(kAnimatedCubeScenePath, true));
UnityEditor.EditorBuildSettings.scenes = scenes.ToArray();
#endif
}
public void Cleanup()
{
#if UNITY_EDITOR
var scenes = UnityEditor.EditorBuildSettings.scenes;
scenes = scenes.Where(s => s.path != kAnimatedCubeScenePath).ToArray();
UnityEditor.EditorBuildSettings.scenes = scenes;
#endif
}
static GameObject SetupCamera(IdLabelConfig config, KeypointTemplate template, Action<int, List<KeypointLabeler.KeypointEntry>> computeListener, RenderTexture renderTexture = null)
{
var cameraObject = new GameObject();
cameraObject.SetActive(false);

camera.transform.position = new Vector3(0, 0, -10);
if (renderTexture)
{
camera.targetTexture = renderTexture;
}
var keyPointLabeler = new KeyPointLabeler(config, template);
var keyPointLabeler = new KeypointLabeler(config, template);
keyPointLabeler.KeyPointsComputed += computeListener;
keyPointLabeler.KeypointsComputed += computeListener;
perceptionCamera.AddLabeler(keyPointLabeler);

static KeyPointTemplate CreateTestTemplate(Guid guid, string label)
static KeypointTemplate CreateTestTemplate(Guid guid, string label)
var keyPoints = new[]
var keypoints = new[]
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
new KeyPointDefinition
new KeypointDefinition
{
label = "Center",
associateToRig = false,

},
};
var template = ScriptableObject.CreateInstance<KeyPointTemplate>();
var template = ScriptableObject.CreateInstance<KeypointTemplate>();
template.keyPoints = keyPoints;
template.keypoints = keypoints;
template.skeleton = skeleton;
return template;

Assert.AreEqual(template.templateName, label);
Assert.IsNull(template.jointTexture);
Assert.IsNull(template.skeletonTexture);
Assert.IsNotNull(template.keyPoints);
Assert.IsNotNull(template.keypoints);
Assert.AreEqual(template.keyPoints.Length, 9);
Assert.AreEqual(template.keypoints.Length, 9);
var k0 = template.keyPoints[0];
var k0 = template.keypoints[0];
Assert.NotNull(k0);
Assert.AreEqual(k0.label, "FrontLowerLeft");
Assert.False(k0.associateToRig);

return cfg;
}
static void SetupCubeJoint(GameObject cube, KeyPointTemplate template, string label, float x, float y, float z)
static void SetupCubeJoint(GameObject cube, KeypointTemplate template, string label, float x, float y, float z)
{
var joint = new GameObject();
joint.transform.parent = cube.transform;

jointLabel.templateInformation.Add(templateData);
}
static void SetupCubeJoints(GameObject cube, KeyPointTemplate template)
static void SetupCubeJoints(GameObject cube, KeypointTemplate template)
SetupCubeJoint(cube, template, "FrontLowerLeft", -0.5f, -0.5f, -0.5f);
SetupCubeJoint(cube, template, "FrontUpperLeft", -0.5f, 0.5f, -0.5f);
SetupCubeJoint(cube, template, "FrontUpperRight", 0.5f, 0.5f, -0.5f);
SetupCubeJoint(cube, template, "FrontLowerRight", 0.5f, -0.5f, -0.5f);
SetupCubeJoint(cube, template, "BackLowerLeft", -0.5f, -0.5f, 0.5f);
SetupCubeJoint(cube, template, "BackUpperLeft", -0.5f, 0.5f, 0.5f);
SetupCubeJoint(cube, template, "BackUpperRight", 0.5f, 0.5f, 0.5f);
SetupCubeJoint(cube, template, "BackLowerRight", 0.5f, -0.5f, 0.5f);
SetupCubeJoint(cube, template, "FrontLowerLeft", -0.495f, -0.495f, -0.495f);
SetupCubeJoint(cube, template, "FrontUpperLeft", -0.495f, 0.495f, -0.495f);
SetupCubeJoint(cube, template, "FrontUpperRight", 0.495f, 0.495f, -0.495f);
SetupCubeJoint(cube, template, "FrontLowerRight", 0.495f, -0.495f, -0.495f);
SetupCubeJoint(cube, template, "BackLowerLeft", -0.495f, -0.495f, 0.495f);
SetupCubeJoint(cube, template, "BackUpperLeft", -0.495f, 0.495f, 0.495f);
SetupCubeJoint(cube, template, "BackUpperRight", 0.495f, 0.495f, 0.495f);
SetupCubeJoint(cube, template, "BackLowerRight", 0.495f, -0.495f, 0.495f);
var incoming = new List<List<KeyPointLabeler.KeyPointEntry>>();
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var template = CreateTestTemplate(Guid.NewGuid(), "TestTemplate");
var texture = new RenderTexture(1024, 768, 16);
texture.Create();
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
}, texture);
var cube = TestHelper.CreateLabeledCube(scale: 6, z: 8);
SetupCubeJoints(cube, template);
cube.SetActive(true);
cam.SetActive(true);
AddTestObjectForCleanup(cam);
AddTestObjectForCleanup(cube);
yield return null;
//force all async readbacks to complete
DestroyTestObject(cam);
texture.Release();
var testCase = incoming.Last();
Assert.AreEqual(1, testCase.Count);
var t = testCase.First();
Assert.NotNull(t);
Assert.AreEqual(1, t.instance_id);
Assert.AreEqual(1, t.label_id);
Assert.AreEqual(template.templateID.ToString(), t.template_guid);
Assert.AreEqual(9, t.keypoints.Length);
Assert.AreEqual(t.keypoints[0].x, t.keypoints[1].x);
Assert.AreEqual(t.keypoints[2].x, t.keypoints[3].x);
Assert.AreEqual(t.keypoints[4].x, t.keypoints[5].x);
Assert.AreEqual(t.keypoints[6].x, t.keypoints[7].x);
Assert.AreEqual(t.keypoints[0].y, t.keypoints[3].y);
Assert.AreEqual(t.keypoints[1].y, t.keypoints[2].y);
Assert.AreEqual(t.keypoints[4].y, t.keypoints[7].y);
Assert.AreEqual(t.keypoints[5].y, t.keypoints[6].y);
for (var i = 0; i < 9; i++) Assert.AreEqual(i, t.keypoints[i].index);
for (var i = 0; i < 8; i++) Assert.AreEqual(2, t.keypoints[i].state);
Assert.Zero(t.keypoints[8].state);
Assert.Zero(t.keypoints[8].x);
Assert.Zero(t.keypoints[8].y);
}
[UnityTest]
public IEnumerator Keypoint_TestAllOffScreen()
{
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var cam = SetupCamera(SetUpLabelConfig(), template, (data) =>
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
});

cube.transform.position = new Vector3(-1000, -1000, 0);
cube.SetActive(true);
cam.SetActive(true);

yield return null;
//force all async readbacks to complete
DestroyTestObject(cam);
foreach (var i in incoming)
{
Assert.Zero(i.Count);
}
}
[UnityTest]
public IEnumerator Keypoint_TestPartialOffScreen([Values(1,5)] int framesToRunBeforeAsserting)
{
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var template = CreateTestTemplate(Guid.NewGuid(), "TestTemplate");
var texture = new RenderTexture(1024, 768, 16);
texture.Create();
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
}, texture);
var cube = TestHelper.CreateLabeledCube(scale: 6, z: 8);
SetupCubeJoints(cube, template);
cube.transform.position += Vector3.right * 13.5f;
cube.SetActive(true);
cam.SetActive(true);
AddTestObjectForCleanup(cam);
AddTestObjectForCleanup(cube);
for (var i = 0; i < framesToRunBeforeAsserting; i++)
yield return null;
//force all async readbacks to complete
DestroyTestObject(cam);
if (texture != null) texture.Release();
var testCase = incoming.Last();
Assert.AreEqual(1, testCase.Count);
var t = testCase.First();
Assert.NotNull(t);
Assert.AreEqual(1, t.instance_id);
Assert.AreEqual(1, t.label_id);
Assert.AreEqual(template.templateID.ToString(), t.template_guid);
Assert.AreEqual(9, t.keypoints.Length);
Assert.NotZero(t.keypoints[0].state);
Assert.NotZero(t.keypoints[1].state);
Assert.NotZero(t.keypoints[4].state);
Assert.NotZero(t.keypoints[5].state);
Assert.Zero(t.keypoints[2].state);
Assert.Zero(t.keypoints[3].state);
Assert.Zero(t.keypoints[6].state);
Assert.Zero(t.keypoints[7].state);
for (var i = 0; i < 9; i++) Assert.AreEqual(i, t.keypoints[i].index);
Assert.Zero(t.keypoints[8].state);
Assert.Zero(t.keypoints[8].x);
Assert.Zero(t.keypoints[8].y);
}
[UnityTest]
public IEnumerator Keypoint_TestAllOnScreen()
{
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var template = CreateTestTemplate(Guid.NewGuid(), "TestTemplate");
var texture = new RenderTexture(1024, 768, 16);
texture.Create();
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
}, texture);
var cube = TestHelper.CreateLabeledCube(scale: 6, z: 8);
SetupCubeJoints(cube, template);
cube.SetActive(true);
cam.SetActive(true);
AddTestObjectForCleanup(cam);
AddTestObjectForCleanup(cube);
//force all async readbacks to complete
DestroyTestObject(cam);
if (texture != null) texture.Release();
var testCase = incoming.Last();
Assert.AreEqual(1, testCase.Count);
var t = testCase.First();

Assert.AreEqual(t.keypoints[5].y, t.keypoints[6].y);
for (var i = 0; i < 9; i++) Assert.AreEqual(i, t.keypoints[i].index);
for (var i = 0; i < 8; i++) Assert.AreEqual(1, t.keypoints[i].state);
for (var i = 0; i < 8; i++) Assert.AreEqual(2, t.keypoints[i].state);
}
[UnityTest]
public IEnumerator Keypoint_TestAllBlockedByOther()
{
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var template = CreateTestTemplate(Guid.NewGuid(), "TestTemplate");
var texture = new RenderTexture(1024, 768, 16);
texture.Create();
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
}, texture);
var cube = TestHelper.CreateLabeledCube(scale: 6, z: 8);
SetupCubeJoints(cube, template);
var blocker = GameObject.CreatePrimitive(PrimitiveType.Cube);
blocker.transform.position = new Vector3(0, 0, 5);
blocker.transform.localScale = new Vector3(7, 7, 7);
cube.SetActive(true);
cam.SetActive(true);
AddTestObjectForCleanup(cam);
AddTestObjectForCleanup(cube);
AddTestObjectForCleanup(blocker);
yield return null;
//force all async readbacks to complete
DestroyTestObject(cam);
if (texture != null) texture.Release();
var testCase = incoming.Last();
Assert.AreEqual(1, testCase.Count);
var t = testCase.First();
Assert.NotNull(t);
Assert.AreEqual(1, t.instance_id);
Assert.AreEqual(1, t.label_id);
Assert.AreEqual(template.templateID.ToString(), t.template_guid);
Assert.AreEqual(9, t.keypoints.Length);
for (var i = 0; i < 8; i++)
Assert.AreEqual(1, t.keypoints[i].state);
for (var i = 0; i < 9; i++) Assert.AreEqual(i, t.keypoints[i].index);
Assert.Zero(t.keypoints[8].state);
Assert.Zero(t.keypoints[8].x);
Assert.Zero(t.keypoints[8].y);
}
[UnityTest]
public IEnumerator Keypoint_TestPartiallyBlockedByOther()
{
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var template = CreateTestTemplate(Guid.NewGuid(), "TestTemplate");
var texture = new RenderTexture(1024, 768, 16);
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
}, texture);
var cube = TestHelper.CreateLabeledCube(scale: 6, z: 8);
SetupCubeJoints(cube, template);
var blocker = GameObject.CreatePrimitive(PrimitiveType.Cube);
blocker.transform.position = new Vector3(3, 0, 5);
blocker.transform.localScale = new Vector3(7, 7, 7);
cube.SetActive(true);
cam.SetActive(true);
AddTestObjectForCleanup(cam);
AddTestObjectForCleanup(cube);
AddTestObjectForCleanup(blocker);
yield return null;
//force all async readbacks to complete
DestroyTestObject(cam);
texture.Release();
var testCase = incoming.Last();
Assert.AreEqual(1, testCase.Count);
var t = testCase.First();
Assert.NotNull(t);
Assert.AreEqual(1, t.instance_id);
Assert.AreEqual(1, t.label_id);
Assert.AreEqual(template.templateID.ToString(), t.template_guid);
Assert.AreEqual(9, t.keypoints.Length);
Assert.AreEqual(2, t.keypoints[0].state);
Assert.AreEqual(2, t.keypoints[1].state);
Assert.AreEqual(2, t.keypoints[4].state);
Assert.AreEqual(2, t.keypoints[5].state);
Assert.AreEqual(1, t.keypoints[2].state);
Assert.AreEqual(1, t.keypoints[3].state);
Assert.AreEqual(1, t.keypoints[6].state);
Assert.AreEqual(1, t.keypoints[7].state);
for (var i = 0; i < 9; i++) Assert.AreEqual(i, t.keypoints[i].index);
Assert.Zero(t.keypoints[8].state);
Assert.Zero(t.keypoints[8].x);
Assert.Zero(t.keypoints[8].y);
}
[UnityTest]
public IEnumerator Keypoint_AnimatedCube_PositionsCaptured()
{
var incoming = new List<List<KeypointLabeler.KeypointEntry>>();
var template = CreateTestTemplate(Guid.NewGuid(), "TestTemplate");
var texture = new RenderTexture(1024, 768, 16);
texture.Create();
var cam = SetupCamera(SetUpLabelConfig(), template, (frame, data) =>
{
incoming.Add(data);
}, texture);
var cameraComponent = cam.GetComponent<Camera>();
cameraComponent.orthographic = true;
cameraComponent.orthographicSize = 2;
var screenPointCenterExpected = cameraComponent.WorldToScreenPoint(
new Vector3(-1.0f, -1.0f * -1 /*flip y for image-space*/, -1.0f));
cam.transform.position = new Vector3(0, 0, -10);
// ReSharper disable once Unity.LoadSceneUnknownSceneName
SceneManager.LoadScene("AnimatedCubeScene", LoadSceneMode.Additive);
AddSceneForCleanup("AnimatedCubeScene");
//scenes are loaded at the end of the frame
yield return null;
var cube = GameObject.Find("AnimatedCube");
cube.SetActive(false);
var labeling = cube.AddComponent<Labeling>();
labeling.labels.Add("label");
SetupCubeJoint(cube, template, "Center",0f, 0f, 0f);
cube.SetActive(true);
cam.SetActive(true);
AddTestObjectForCleanup(cam);
AddTestObjectForCleanup(cube);
yield return null;
//force all async readbacks to complete
DestroyTestObject(cam);
if (texture != null) texture.Release();
var testCase = incoming.Last();
Assert.AreEqual(1, testCase.Count);
var t = testCase.First();
Assert.NotNull(t);
Assert.AreEqual(1, t.instance_id);
Assert.AreEqual(1, t.label_id);
Assert.AreEqual(template.templateID.ToString(), t.template_guid);
Assert.AreEqual(9, t.keypoints.Length);
//large delta because the animation will already have taken it some distance from the starting location
Assert.AreEqual(screenPointCenterExpected.x, t.keypoints[8].x, Screen.width * .1);
Assert.AreEqual(screenPointCenterExpected.y, t.keypoints[8].y, Screen.height * .1);
Assert.AreEqual(8, t.keypoints[8].index);
Assert.AreEqual(2, t.keypoints[8].state);
}
}
}

2
com.unity.perception/Tests/Runtime/Randomization/RandomizerTests/ExampleTransformRandomizer.cs


public Transform transform;
protected override void OnCreate()
protected override void OnAwake()
{
transform = scenario.transform;
}

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存