@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 8cbcc68bb8cc7e649b1f5bf601d24fec | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,27 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!114 &11400000 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 0 | |||
m_CorrespondingSourceObject: {fileID: 0} | |||
m_PrefabInstance: {fileID: 0} | |||
m_PrefabAsset: {fileID: 0} | |||
m_GameObject: {fileID: 0} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 8b23992c8eb17439887f5e944bf04a40, type: 3} | |||
m_Name: CozmoLearning | |||
m_EditorClassIdentifier: | |||
brainParameters: | |||
vectorObservationSize: 0 | |||
numStackedVectorObservations: 1 | |||
vectorActionSize: 01000000 | |||
cameraResolutions: | |||
- width: 84 | |||
height: 84 | |||
blackAndWhite: 1 | |||
vectorActionDescriptions: | |||
- | |||
vectorActionSpaceType: 0 | |||
model: {fileID: 0} | |||
inferenceDevice: 0 |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 94e62c225e4fe8148a7543c5fd1acfd4 | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 11400000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: c5dd104aa5d6bff4d972bb36ad0340ab | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 64f5b1a0bb6688d498ff44bbae7b57a5 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,30 @@ | |||
using UnityEngine; | |||
using System.Collections; | |||
public class CurvedLinePoint : MonoBehaviour | |||
{ | |||
[HideInInspector] public bool showGizmo = true; | |||
[HideInInspector] public float gizmoSize = 0.1f; | |||
[HideInInspector] public Color gizmoColor = new Color(1,0,0,0.5f); | |||
void OnDrawGizmos() | |||
{ | |||
if( showGizmo == true ) | |||
{ | |||
Gizmos.color = gizmoColor; | |||
Gizmos.DrawSphere( this.transform.position, gizmoSize ); | |||
} | |||
} | |||
//update parent line when this point moved | |||
void OnDrawGizmosSelected() | |||
{ | |||
CurvedLineRenderer curvedLine = this.transform.parent.GetComponent<CurvedLineRenderer>(); | |||
if( curvedLine != null ) | |||
{ | |||
curvedLine.Update(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 4efb4faa31cad924994c5bc6ba7329d7 | |||
timeCreated: 1457753586 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,94 @@ | |||
using UnityEngine; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
[RequireComponent( typeof(LineRenderer) )] | |||
public class CurvedLineRenderer : MonoBehaviour | |||
{ | |||
//PUBLIC | |||
public float lineSegmentSize = 0.15f; | |||
public float lineWidth = 0.1f; | |||
[Header("Gizmos")] | |||
public bool showGizmos = true; | |||
public float gizmoSize = 0.1f; | |||
public Color gizmoColor = new Color(1,0,0,0.5f); | |||
//PRIVATE | |||
private CurvedLinePoint[] linePoints = new CurvedLinePoint[0]; | |||
private Vector3[] linePositions = new Vector3[0]; | |||
private Vector3[] linePositionsOld = new Vector3[0]; | |||
// Update is called once per frame | |||
public void Update () | |||
{ | |||
GetPoints(); | |||
SetPointsToLine(); | |||
} | |||
void GetPoints() | |||
{ | |||
//find curved points in children | |||
linePoints = this.GetComponentsInChildren<CurvedLinePoint>(); | |||
//add positions | |||
linePositions = new Vector3[linePoints.Length]; | |||
for( int i = 0; i < linePoints.Length; i++ ) | |||
{ | |||
linePositions[i] = linePoints[i].transform.position; | |||
} | |||
} | |||
void SetPointsToLine() | |||
{ | |||
//create old positions if they dont match | |||
if( linePositionsOld.Length != linePositions.Length ) | |||
{ | |||
linePositionsOld = new Vector3[linePositions.Length]; | |||
} | |||
//check if line points have moved | |||
bool moved = false; | |||
for( int i = 0; i < linePositions.Length; i++ ) | |||
{ | |||
//compare | |||
if( linePositions[i] != linePositionsOld[i] ) | |||
{ | |||
moved = true; | |||
} | |||
} | |||
//update if moved | |||
if( moved == true ) | |||
{ | |||
LineRenderer line = this.GetComponent<LineRenderer>(); | |||
//get smoothed values | |||
Vector3[] smoothedPoints = LineSmoother.SmoothLine( linePositions, lineSegmentSize ); | |||
//set line settings | |||
line.SetVertexCount( smoothedPoints.Length ); | |||
line.SetPositions( smoothedPoints ); | |||
line.SetWidth( lineWidth, lineWidth ); | |||
} | |||
} | |||
void OnDrawGizmosSelected() | |||
{ | |||
Update(); | |||
} | |||
void OnDrawGizmos() | |||
{ | |||
if( linePoints.Length == 0 ) | |||
{ | |||
GetPoints(); | |||
} | |||
//settings for gizmos | |||
foreach( CurvedLinePoint linePoint in linePoints ) | |||
{ | |||
linePoint.showGizmo = showGizmos; | |||
linePoint.gizmoSize = gizmoSize; | |||
linePoint.gizmoColor = gizmoColor; | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: f886d860c5994de44bda0d51d3182bee | |||
timeCreated: 1457752249 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: ac901715280af9641bef97a88e0a3522 | |||
timeCreated: 1457750910 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: ba19bde9a20962f488a50be7f354bc2e | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 7910d69941406d04294f7eb428513ad0 | |||
timeCreated: 1457754790 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: c1b4e62fb04f0734d84710b9fbdd8c85 | |||
timeCreated: 1457756473 | |||
licenseType: Free | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 7dc1ce4b31c63e34da34775dd888c0dc | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 239a923e346c7564eab507004b9293df | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 48abdf8d850ee0b4890625559ec6f520 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,76 @@ | |||
fileFormatVersion: 2 | |||
guid: fbee1fddc738f410ea0b37fe6301d7c0 | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
externalObjects: {} | |||
serializedVersion: 4 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 1 | |||
sRGBTexture: 1 | |||
linearTexture: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapsPreserveCoverage: 0 | |||
alphaTestReferenceValue: 0.5 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: 0.25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 6 | |||
cubemapConvolution: 0 | |||
seamlessCubemap: 0 | |||
textureFormat: 1 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
serializedVersion: 2 | |||
filterMode: -1 | |||
aniso: -1 | |||
mipBias: -1 | |||
wrapU: -1 | |||
wrapV: -1 | |||
wrapW: -1 | |||
nPOTScale: 1 | |||
lightmap: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: 0.5, y: 0.5} | |||
spritePixelsToUnits: 100 | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spriteGenerateFallbackPhysicsShape: 1 | |||
alphaUsage: 1 | |||
alphaIsTransparency: 0 | |||
spriteTessellationDetail: -1 | |||
textureType: 0 | |||
textureShape: 1 | |||
maxTextureSizeSet: 0 | |||
compressionQualitySet: 0 | |||
textureFormatSet: 0 | |||
platformSettings: | |||
- buildTarget: DefaultTexturePlatform | |||
maxTextureSize: 2048 | |||
resizeAlgorithm: 0 | |||
textureFormat: -1 | |||
textureCompression: 1 | |||
compressionQuality: 50 | |||
crunchedCompression: 0 | |||
allowsAlphaSplitting: 0 | |||
overridden: 0 | |||
androidETC2FallbackOverride: 0 | |||
spriteSheet: | |||
serializedVersion: 2 | |||
sprites: [] | |||
outline: [] | |||
physicsShape: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,76 @@ | |||
fileFormatVersion: 2 | |||
guid: aff60a06d6c704801a2d09a8e72cbefc | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
externalObjects: {} | |||
serializedVersion: 4 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 1 | |||
sRGBTexture: 1 | |||
linearTexture: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapsPreserveCoverage: 0 | |||
alphaTestReferenceValue: 0.5 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: 0.25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 6 | |||
cubemapConvolution: 0 | |||
seamlessCubemap: 0 | |||
textureFormat: 1 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
serializedVersion: 2 | |||
filterMode: -1 | |||
aniso: -1 | |||
mipBias: -1 | |||
wrapU: -1 | |||
wrapV: -1 | |||
wrapW: -1 | |||
nPOTScale: 1 | |||
lightmap: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: 0.5, y: 0.5} | |||
spritePixelsToUnits: 100 | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spriteGenerateFallbackPhysicsShape: 1 | |||
alphaUsage: 1 | |||
alphaIsTransparency: 0 | |||
spriteTessellationDetail: -1 | |||
textureType: 0 | |||
textureShape: 1 | |||
maxTextureSizeSet: 0 | |||
compressionQualitySet: 0 | |||
textureFormatSet: 0 | |||
platformSettings: | |||
- buildTarget: DefaultTexturePlatform | |||
maxTextureSize: 2048 | |||
resizeAlgorithm: 0 | |||
textureFormat: -1 | |||
textureCompression: 1 | |||
compressionQuality: 50 | |||
crunchedCompression: 0 | |||
allowsAlphaSplitting: 0 | |||
overridden: 0 | |||
androidETC2FallbackOverride: 0 | |||
spriteSheet: | |||
serializedVersion: 2 | |||
sprites: [] | |||
outline: [] | |||
physicsShape: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,76 @@ | |||
fileFormatVersion: 2 | |||
guid: 224cd0666bb7b4477b0806fd29cf5966 | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
externalObjects: {} | |||
serializedVersion: 4 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 1 | |||
sRGBTexture: 1 | |||
linearTexture: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapsPreserveCoverage: 0 | |||
alphaTestReferenceValue: 0.5 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: 0.25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 6 | |||
cubemapConvolution: 0 | |||
seamlessCubemap: 0 | |||
textureFormat: 1 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
serializedVersion: 2 | |||
filterMode: -1 | |||
aniso: -1 | |||
mipBias: -1 | |||
wrapU: -1 | |||
wrapV: -1 | |||
wrapW: -1 | |||
nPOTScale: 1 | |||
lightmap: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: 0.5, y: 0.5} | |||
spritePixelsToUnits: 100 | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spriteGenerateFallbackPhysicsShape: 1 | |||
alphaUsage: 1 | |||
alphaIsTransparency: 0 | |||
spriteTessellationDetail: -1 | |||
textureType: 0 | |||
textureShape: 1 | |||
maxTextureSizeSet: 0 | |||
compressionQualitySet: 0 | |||
textureFormatSet: 0 | |||
platformSettings: | |||
- buildTarget: DefaultTexturePlatform | |||
maxTextureSize: 2048 | |||
resizeAlgorithm: 0 | |||
textureFormat: -1 | |||
textureCompression: 1 | |||
compressionQuality: 50 | |||
crunchedCompression: 0 | |||
allowsAlphaSplitting: 0 | |||
overridden: 0 | |||
androidETC2FallbackOverride: 0 | |||
spriteSheet: | |||
serializedVersion: 2 | |||
sprites: [] | |||
outline: [] | |||
physicsShape: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 11630fa83cc8b4194b94352e3e6cdb9d | |||
folderAsset: yes | |||
timeCreated: 1504127524 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 67b4fb0b937cc471eae742addf6bda86 | |||
folderAsset: yes | |||
timeCreated: 1503177274 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,86 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
namespace MLAgents | |||
{ | |||
/* | |||
This code is meant to modify the behavior of the inspector on Brain Components. | |||
Depending on the type of brain that is used, the available fields will be modified in the inspector accordingly. | |||
*/ | |||
[CustomEditor(typeof(Agent), true)] | |||
[CanEditMultipleObjects] | |||
public class AgentEditor : Editor | |||
{ | |||
public override void OnInspectorGUI() | |||
{ | |||
SerializedObject serializedAgent = serializedObject; | |||
serializedAgent.Update(); | |||
SerializedProperty brain = serializedAgent.FindProperty("brain"); | |||
SerializedProperty actionsPerDecision = serializedAgent.FindProperty( | |||
"agentParameters.numberOfActionsBetweenDecisions"); | |||
SerializedProperty maxSteps = serializedAgent.FindProperty( | |||
"agentParameters.maxStep"); | |||
SerializedProperty isResetOnDone = serializedAgent.FindProperty( | |||
"agentParameters.resetOnDone"); | |||
SerializedProperty isODD = serializedAgent.FindProperty( | |||
"agentParameters.onDemandDecision"); | |||
SerializedProperty cameras = serializedAgent.FindProperty( | |||
"agentParameters.agentCameras"); | |||
EditorGUILayout.PropertyField(brain); | |||
EditorGUILayout.LabelField("Agent Cameras"); | |||
for (int i = 0; i < cameras.arraySize; i++) | |||
{ | |||
EditorGUILayout.PropertyField( | |||
cameras.GetArrayElementAtIndex(i), | |||
new GUIContent("Camera " + (i + 1).ToString() + ": ")); | |||
} | |||
EditorGUILayout.BeginHorizontal(); | |||
if (GUILayout.Button("Add Camera", EditorStyles.miniButton)) | |||
{ | |||
cameras.arraySize++; | |||
} | |||
if (GUILayout.Button("Remove Camera", EditorStyles.miniButton)) | |||
{ | |||
cameras.arraySize--; | |||
} | |||
EditorGUILayout.EndHorizontal(); | |||
EditorGUILayout.PropertyField( | |||
maxSteps, | |||
new GUIContent( | |||
"Max Step", "The per-agent maximum number of steps.")); | |||
EditorGUILayout.PropertyField( | |||
isResetOnDone, | |||
new GUIContent( | |||
"Reset On Done", | |||
"If checked, the agent will reset on done. Else, AgentOnDone() will be called.")); | |||
EditorGUILayout.PropertyField( | |||
isODD, | |||
new GUIContent( | |||
"On Demand Decisions", | |||
"If checked, you must manually request decisions.")); | |||
if (!isODD.boolValue) | |||
{ | |||
EditorGUILayout.PropertyField( | |||
actionsPerDecision, | |||
new GUIContent( | |||
"Decision Interval", | |||
"The agent will automatically request a decision every X" + | |||
" steps and perform an action at every step.")); | |||
actionsPerDecision.intValue = Mathf.Max(1, actionsPerDecision.intValue); | |||
} | |||
serializedAgent.ApplyModifiedProperties(); | |||
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); | |||
base.OnInspectorGUI(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: c3b291e1cd0c64781861652b579d0ac1 | |||
timeCreated: 1503270350 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,36 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// CustomEditor for the Brain base class. Defines the default Inspector view for a Brain. | |||
/// Shows the BrainParameters of the Brain and expose a tool to deep copy BrainParameters | |||
/// between brains. | |||
/// </summary> | |||
[CustomEditor(typeof(Brain))] | |||
public class BrainEditor : Editor | |||
{ | |||
public override void OnInspectorGUI() | |||
{ | |||
var brain = (Brain) target; | |||
var brainToCopy = EditorGUILayout.ObjectField( | |||
"Copy Brain Parameters from : ", null, typeof(Brain), false) as Brain; | |||
if (brainToCopy != null) | |||
{ | |||
brain.brainParameters = brainToCopy.brainParameters.Clone(); | |||
EditorUtility.SetDirty(brain); | |||
AssetDatabase.SaveAssets(); | |||
return; | |||
} | |||
var serializedBrain = serializedObject; | |||
serializedBrain.Update(); | |||
EditorGUILayout.PropertyField(serializedBrain.FindProperty("brainParameters"), true); | |||
serializedBrain.ApplyModifiedProperties(); | |||
// Draws a horizontal thick line | |||
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: 7b07bebd03994ed08559c725da882b62 | |||
timeCreated: 1537834304 |
@@ -0,0 +1,369 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// PropertyDrawer for BrainParameters. Defines how BrainParameters are displayed in the | |||
/// Inspector. | |||
/// </summary> | |||
[CustomPropertyDrawer(typeof(BrainParameters))] | |||
public class BrainParametersDrawer : PropertyDrawer | |||
{ | |||
// The height of a line in the Unity Inspectors | |||
private const float LineHeight = 17f; | |||
private const int VecObsNumLine = 3; | |||
private const string CamResPropName = "cameraResolutions"; | |||
private const string ActionSizePropName = "vectorActionSize"; | |||
private const string ActionTypePropName = "vectorActionSpaceType"; | |||
private const string ActionDescriptionPropName = "vectorActionDescriptions"; | |||
private const string VecObsPropName = "vectorObservationSize"; | |||
private const string NumVecObsPropName ="numStackedVectorObservations"; | |||
private const string CamWidthPropName = "width"; | |||
private const string CamHeightPropName = "height"; | |||
private const string CamGrayPropName = "blackAndWhite"; | |||
private const int DefaultCameraWidth = 84; | |||
private const int DefaultCameraHeight = 84; | |||
private const bool DefaultCameraGray = false; | |||
/// <inheritdoc /> | |||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |||
{ | |||
if (property.isExpanded) | |||
{ | |||
return LineHeight + | |||
GetHeightDrawVectorObservation() + | |||
GetHeightDrawVisualObservation(property) + | |||
GetHeightDrawVectorAction(property) + | |||
GetHeightDrawVectorActionDescriptions(property); | |||
} | |||
return LineHeight; | |||
} | |||
/// <inheritdoc /> | |||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |||
{ | |||
var indent = EditorGUI.indentLevel; | |||
EditorGUI.indentLevel = 0; | |||
position.height = LineHeight; | |||
property.isExpanded = EditorGUI.Foldout(position, property.isExpanded, label); | |||
position.y += LineHeight; | |||
if (property.isExpanded) | |||
{ | |||
EditorGUI.BeginProperty(position, label, property); | |||
EditorGUI.indentLevel++; | |||
// Vector Observations | |||
DrawVectorObservation(position, property); | |||
position.y += GetHeightDrawVectorObservation(); | |||
//Visual Observations | |||
DrawVisualObservations(position, property); | |||
position.y += GetHeightDrawVisualObservation(property); | |||
// Vector Action | |||
DrawVectorAction(position, property); | |||
position.y += GetHeightDrawVectorAction(property); | |||
// Vector Action Descriptions | |||
DrawVectorActionDescriptions(position, property); | |||
position.y += GetHeightDrawVectorActionDescriptions(property); | |||
EditorGUI.EndProperty(); | |||
} | |||
EditorGUI.indentLevel = indent; | |||
} | |||
/// <summary> | |||
/// Draws the Vector Observations for the Brain Parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="property">The SerializedProperty of the BrainParameters | |||
/// to make the custom GUI for.</param> | |||
private static void DrawVectorObservation(Rect position, SerializedProperty property) | |||
{ | |||
EditorGUI.LabelField(position, "Vector Observation"); | |||
position.y += LineHeight; | |||
EditorGUI.indentLevel++; | |||
EditorGUI.PropertyField(position, | |||
property.FindPropertyRelative(VecObsPropName), | |||
new GUIContent("Space Size", | |||
"Length of state " + | |||
"vector for brain (In Continuous state space)." + | |||
"Or number of possible values (in Discrete state space).")); | |||
position.y += LineHeight; | |||
EditorGUI.PropertyField(position, | |||
property.FindPropertyRelative(NumVecObsPropName), | |||
new GUIContent("Stacked Vectors", | |||
"Number of states that will be stacked before " + | |||
"beeing fed to the neural network.")); | |||
position.y += LineHeight; | |||
EditorGUI.indentLevel--; | |||
} | |||
/// <summary> | |||
/// The Height required to draw the Vector Observations paramaters | |||
/// </summary> | |||
/// <returns>The height of the drawer of the Vector Observations </returns> | |||
private static float GetHeightDrawVectorObservation() | |||
{ | |||
return VecObsNumLine * LineHeight; | |||
} | |||
/// <summary> | |||
/// Draws the Visual Observations parameters for the Brain Parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="property">The SerializedProperty of the BrainParameters | |||
/// to make the custom GUI for.</param> | |||
private static void DrawVisualObservations(Rect position, SerializedProperty property) | |||
{ | |||
EditorGUI.LabelField(position, "Visual Observations"); | |||
position.y += LineHeight; | |||
var quarter = position.width / 4; | |||
var resolutions = property.FindPropertyRelative(CamResPropName); | |||
DrawVisualObsButtons(position, resolutions); | |||
position.y += LineHeight; | |||
// Display the labels for the columns : Index, Width, Height and Gray | |||
var indexRect = new Rect(position.x, position.y, quarter, position.height); | |||
var widthRect = new Rect(position.x + quarter, position.y, quarter, position.height); | |||
var heightRect = new Rect(position.x + 2*quarter, position.y, quarter, position.height); | |||
var bwRect = new Rect(position.x + 3*quarter, position.y, quarter, position.height); | |||
EditorGUI.indentLevel++; | |||
if (resolutions.arraySize > 0) | |||
{ | |||
EditorGUI.LabelField(indexRect, "Index"); | |||
indexRect.y += LineHeight; | |||
EditorGUI.LabelField(widthRect, "Width"); | |||
widthRect.y += LineHeight; | |||
EditorGUI.LabelField(heightRect, "Height"); | |||
heightRect.y += LineHeight; | |||
EditorGUI.LabelField(bwRect, "Gray"); | |||
bwRect.y += LineHeight; | |||
} | |||
// Iterate over the resolutions | |||
for (var i = 0; i < resolutions.arraySize; i++) | |||
{ | |||
EditorGUI.LabelField(indexRect, "Obs " + i); | |||
indexRect.y += LineHeight; | |||
var res = resolutions.GetArrayElementAtIndex(i); | |||
var w = res.FindPropertyRelative("width"); | |||
w.intValue = EditorGUI.IntField(widthRect, w.intValue); | |||
widthRect.y += LineHeight; | |||
var h = res.FindPropertyRelative("height"); | |||
h.intValue = EditorGUI.IntField(heightRect, h.intValue); | |||
heightRect.y += LineHeight; | |||
var bw = res.FindPropertyRelative("blackAndWhite"); | |||
bw.boolValue = EditorGUI.Toggle(bwRect, bw.boolValue); | |||
bwRect.y += LineHeight; | |||
} | |||
EditorGUI.indentLevel--; | |||
} | |||
/// <summary> | |||
/// Draws the buttons to add and remove the visual observations parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="resolutions">The SerializedProperty of the resolution array | |||
/// to make the custom GUI for.</param> | |||
private static void DrawVisualObsButtons(Rect position, SerializedProperty resolutions) | |||
{ | |||
var widthEighth = position.width / 8; | |||
var addButtonRect = new Rect(position.x + widthEighth, position.y, | |||
3 * widthEighth, position.height); | |||
var removeButtonRect = new Rect(position.x + 4 * widthEighth, position.y, | |||
3 * widthEighth, position.height); | |||
if (resolutions.arraySize == 0) | |||
{ | |||
addButtonRect.width *= 2; | |||
} | |||
// Display the buttons | |||
if (GUI.Button(addButtonRect, "Add New", EditorStyles.miniButton)) | |||
{ | |||
resolutions.arraySize += 1; | |||
var newRes = resolutions.GetArrayElementAtIndex(resolutions.arraySize - 1); | |||
newRes.FindPropertyRelative(CamWidthPropName).intValue = DefaultCameraWidth; | |||
newRes.FindPropertyRelative(CamHeightPropName).intValue = DefaultCameraHeight; | |||
newRes.FindPropertyRelative(CamGrayPropName).boolValue = DefaultCameraGray; | |||
} | |||
if (resolutions.arraySize > 0) | |||
{ | |||
if (GUI.Button(removeButtonRect, "Remove Last", EditorStyles.miniButton)) | |||
{ | |||
resolutions.arraySize -= 1; | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// The Height required to draw the Visual Observations parameters | |||
/// </summary> | |||
/// <returns>The height of the drawer of the Visual Observations </returns> | |||
private static float GetHeightDrawVisualObservation(SerializedProperty property) | |||
{ | |||
var visObsSize = property.FindPropertyRelative(CamResPropName).arraySize + 2; | |||
if (property.FindPropertyRelative(CamResPropName).arraySize > 0) | |||
{ | |||
visObsSize += 1; | |||
} | |||
return LineHeight * visObsSize; | |||
} | |||
/// <summary> | |||
/// Draws the Vector Actions parameters for the Brain Parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="property">The SerializedProperty of the BrainParameters | |||
/// to make the custom GUI for.</param> | |||
private static void DrawVectorAction(Rect position, SerializedProperty property) | |||
{ | |||
EditorGUI.LabelField(position, "Vector Action"); | |||
position.y += LineHeight; | |||
EditorGUI.indentLevel++; | |||
var bpVectorActionType = property.FindPropertyRelative(ActionTypePropName); | |||
EditorGUI.PropertyField( | |||
position, | |||
bpVectorActionType, | |||
new GUIContent("Space Type", | |||
"Corresponds to whether state vector contains a single integer (Discrete) " + | |||
"or a series of real-valued floats (Continuous).")); | |||
position.y += LineHeight; | |||
if (bpVectorActionType.enumValueIndex == 1) | |||
{ | |||
DrawContinuousVectorAction(position, property); | |||
} | |||
else | |||
{ | |||
DrawDiscreteVectorAction(position, property); | |||
} | |||
} | |||
/// <summary> | |||
/// Draws the Continuous Vector Actions parameters for the Brain Parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="property">The SerializedProperty of the BrainParameters | |||
/// to make the custom GUI for.</param> | |||
private static void DrawContinuousVectorAction(Rect position, SerializedProperty property) | |||
{ | |||
var vecActionSize = property.FindPropertyRelative(ActionSizePropName); | |||
vecActionSize.arraySize = 1; | |||
SerializedProperty continuousActionSize = | |||
vecActionSize.GetArrayElementAtIndex(0); | |||
EditorGUI.PropertyField( | |||
position, | |||
continuousActionSize, | |||
new GUIContent("Space Size", "Length of continuous action vector.")); | |||
} | |||
/// <summary> | |||
/// Draws the Discrete Vector Actions parameters for the Brain Parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="property">The SerializedProperty of the BrainParameters | |||
/// to make the custom GUI for.</param> | |||
private static void DrawDiscreteVectorAction(Rect position, SerializedProperty property) | |||
{ | |||
var vecActionSize = property.FindPropertyRelative(ActionSizePropName); | |||
vecActionSize.arraySize = EditorGUI.IntField( | |||
position, "Branches Size", vecActionSize.arraySize); | |||
position.y += LineHeight; | |||
position.x += 20; | |||
position.width -= 20; | |||
for (var branchIndex = 0; | |||
branchIndex < vecActionSize.arraySize; | |||
branchIndex++) | |||
{ | |||
SerializedProperty branchActionSize = | |||
vecActionSize.GetArrayElementAtIndex(branchIndex); | |||
EditorGUI.PropertyField( | |||
position, | |||
branchActionSize, | |||
new GUIContent("Branch " + branchIndex + " Size", | |||
"Number of possible actions for the branch number " + branchIndex + ".")); | |||
position.y += LineHeight; | |||
} | |||
} | |||
/// <summary> | |||
/// The Height required to draw the Vector Action parameters | |||
/// </summary> | |||
/// <returns>The height of the drawer of the Vector Action </returns> | |||
private static float GetHeightDrawVectorAction(SerializedProperty property) | |||
{ | |||
var actionSize = 2 + property.FindPropertyRelative(ActionSizePropName).arraySize; | |||
if (property.FindPropertyRelative(ActionTypePropName).enumValueIndex == 0) | |||
{ | |||
actionSize += 1; | |||
} | |||
return actionSize * LineHeight; | |||
} | |||
/// <summary> | |||
/// Draws the Vector Actions descriptions for the Brain Parameters | |||
/// </summary> | |||
/// <param name="position">Rectangle on the screen to use for the property GUI.</param> | |||
/// <param name="property">The SerializedProperty of the BrainParameters | |||
/// to make the custom GUI for.</param> | |||
private static void DrawVectorActionDescriptions(Rect position, SerializedProperty property) | |||
{ | |||
var bpVectorActionType = property.FindPropertyRelative(ActionTypePropName); | |||
var vecActionSize = property.FindPropertyRelative(ActionSizePropName); | |||
var numberOfDescriptions = 0; | |||
if (bpVectorActionType.enumValueIndex == 1) | |||
{ | |||
numberOfDescriptions = vecActionSize.GetArrayElementAtIndex(0).intValue; | |||
} | |||
else | |||
{ | |||
numberOfDescriptions = vecActionSize.arraySize; | |||
} | |||
EditorGUI.indentLevel++; | |||
var vecActionDescriptions = | |||
property.FindPropertyRelative(ActionDescriptionPropName); | |||
vecActionDescriptions.arraySize = numberOfDescriptions; | |||
if (bpVectorActionType.enumValueIndex == 1) | |||
{ | |||
//Continuous case : | |||
EditorGUI.PropertyField( | |||
position, | |||
vecActionDescriptions, | |||
new GUIContent("Action Descriptions", | |||
"A list of strings used to name the available actionsm for the Brain."), | |||
true); | |||
position.y += LineHeight; | |||
} | |||
else | |||
{ | |||
// Discrete case : | |||
EditorGUI.PropertyField( | |||
position, | |||
vecActionDescriptions, | |||
new GUIContent("Branch Descriptions", | |||
"A list of strings used to name the available branches for the Brain."), | |||
true); | |||
position.y += LineHeight; | |||
} | |||
} | |||
/// <summary> | |||
/// The Height required to draw the Action Descriptions | |||
/// </summary> | |||
/// <returns>The height of the drawer of the Action Descriptions </returns> | |||
private static float GetHeightDrawVectorActionDescriptions(SerializedProperty property) | |||
{ | |||
var descriptionSize = 1; | |||
if (property.FindPropertyRelative(ActionDescriptionPropName).isExpanded) | |||
{ | |||
var descriptions = property.FindPropertyRelative(ActionDescriptionPropName); | |||
descriptionSize += descriptions.arraySize + 1; | |||
} | |||
return descriptionSize * LineHeight; | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: b060ae8e687cf49bcae88b24db17bfa6 | |||
timeCreated: 1517291065 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,208 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System; | |||
using System.Linq; | |||
using UnityEditor.SceneManagement; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// PropertyDrawer for BroadcastHub. Used to display the BroadcastHub in the Inspector. | |||
/// </summary> | |||
[CustomPropertyDrawer(typeof(BroadcastHub))] | |||
public class BroadcastHubDrawer : PropertyDrawer | |||
{ | |||
private BroadcastHub _hub; | |||
// The height of a line in the Unity Inspectors | |||
private const float LineHeight = 17f; | |||
// The vertical space left below the BroadcastHub UI. | |||
private const float ExtraSpaceBelow = 10f; | |||
// The horizontal size of the Control checkbox | |||
private const int ControlSize = 80; | |||
/// <summary> | |||
/// Computes the height of the Drawer depending on the property it is showing | |||
/// </summary> | |||
/// <param name="property">The property that is being drawn.</param> | |||
/// <param name="label">The label of the property being drawn.</param> | |||
/// <returns>The vertical space needed to draw the property.</returns> | |||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |||
{ | |||
LazyInitializeHub(property, label); | |||
var numLines = _hub.Count + 2 + (_hub.Count > 0 ? 1 : 0); | |||
return (numLines) * LineHeight + ExtraSpaceBelow; | |||
} | |||
/// <inheritdoc /> | |||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |||
{ | |||
LazyInitializeHub(property, label); | |||
position.height = LineHeight; | |||
EditorGUI.LabelField(position, new GUIContent(label.text, | |||
"The Broadcast Hub helps you define which Brains you want to expose to " + | |||
"the external process")); | |||
position.y += LineHeight; | |||
EditorGUI.BeginProperty(position, label, property); | |||
EditorGUI.indentLevel++; | |||
DrawAddRemoveButtons(position); | |||
position.y += LineHeight; | |||
// This is the labels for each columns | |||
var brainWidth = position.width - ControlSize; | |||
var brainRect = new Rect( | |||
position.x, position.y, brainWidth, position.height); | |||
var controlRect = new Rect( | |||
position.x + brainWidth, position.y, ControlSize, position.height); | |||
if (_hub.Count > 0) | |||
{ | |||
EditorGUI.LabelField(brainRect, "Brains"); | |||
brainRect.y += LineHeight; | |||
EditorGUI.LabelField(controlRect, "Control"); | |||
controlRect.y += LineHeight; | |||
controlRect.x += 15; | |||
} | |||
DrawBrains(brainRect, controlRect); | |||
EditorGUI.indentLevel--; | |||
EditorGUI.EndProperty(); | |||
} | |||
/// <summary> | |||
/// Draws the Add and Remove buttons. | |||
/// </summary> | |||
/// <param name="position">The position at which to draw.</param> | |||
private void DrawAddRemoveButtons(Rect position) | |||
{ | |||
// This is the rectangle for the Add button | |||
var addButtonRect = position; | |||
addButtonRect.x += 20; | |||
if (_hub.Count > 0) | |||
{ | |||
addButtonRect.width /= 2; | |||
addButtonRect.width -= 24; | |||
var buttonContent = new GUIContent( | |||
"Add New", "Add a new Brain to the Broadcast Hub"); | |||
if (GUI.Button(addButtonRect, buttonContent, EditorStyles.miniButton)) | |||
{ | |||
MarkSceneAsDirty(); | |||
AddBrain(); | |||
} | |||
// This is the rectangle for the Remove button | |||
var removeButtonRect = position; | |||
removeButtonRect.x = position.width / 2 + 15; | |||
removeButtonRect.width = addButtonRect.width - 18; | |||
buttonContent = new GUIContent( | |||
"Remove Last", "Remove the last Brain from the Broadcast Hub"); | |||
if (GUI.Button(removeButtonRect, buttonContent, EditorStyles.miniButton)) | |||
{ | |||
MarkSceneAsDirty(); | |||
RemoveLastBrain(); | |||
} | |||
} | |||
else | |||
{ | |||
addButtonRect.width -= 50; | |||
var buttonContent = new GUIContent( | |||
"Add Brain to Broadcast Hub", "Add a new Brain to the Broadcast Hub"); | |||
if (GUI.Button(addButtonRect, buttonContent, EditorStyles.miniButton)) | |||
{ | |||
MarkSceneAsDirty(); | |||
AddBrain(); | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Draws the Brain and Control checkbox for the brains contained in the BroadCastHub. | |||
/// </summary> | |||
/// <param name="brainRect">The Rect to draw the Brains.</param> | |||
/// <param name="controlRect">The Rect to draw the control checkbox.</param> | |||
private void DrawBrains(Rect brainRect, Rect controlRect) | |||
{ | |||
for (var index = 0; index < _hub.Count; index++) | |||
{ | |||
var exposedBrains = _hub.broadcastingBrains; | |||
var brain = exposedBrains[index]; | |||
// This is the rectangle for the brain | |||
EditorGUI.BeginChangeCheck(); | |||
var newBrain = EditorGUI.ObjectField( | |||
brainRect, brain, typeof(Brain), true) as Brain; | |||
brainRect.y += LineHeight; | |||
if (EditorGUI.EndChangeCheck()) | |||
{ | |||
MarkSceneAsDirty(); | |||
_hub.broadcastingBrains.RemoveAt(index); | |||
var brainToInsert = exposedBrains.Contains(newBrain) ? null : newBrain; | |||
exposedBrains.Insert(index, brainToInsert); | |||
break; | |||
} | |||
// This is the Rectangle for the control checkbox | |||
EditorGUI.BeginChangeCheck(); | |||
if (brain is LearningBrain) | |||
{ | |||
var isTraining = _hub.IsControlled(brain); | |||
isTraining = EditorGUI.Toggle(controlRect, isTraining); | |||
_hub.SetControlled(brain, isTraining); | |||
} | |||
controlRect.y += LineHeight; | |||
if (EditorGUI.EndChangeCheck()) | |||
{ | |||
MarkSceneAsDirty(); | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Lazy initializes the Drawer with the property to be drawn. | |||
/// </summary> | |||
/// <param name="property">The SerializedProperty of the BroadcastHub | |||
/// to make the custom GUI for.</param> | |||
/// <param name="label">The label of this property.</param> | |||
private void LazyInitializeHub(SerializedProperty property, GUIContent label) | |||
{ | |||
if (_hub != null) | |||
{ | |||
return; | |||
} | |||
var target = property.serializedObject.targetObject; | |||
_hub = fieldInfo.GetValue(target) as BroadcastHub; | |||
if (_hub == null) | |||
{ | |||
_hub = new BroadcastHub(); | |||
fieldInfo.SetValue(target, _hub); | |||
} | |||
} | |||
/// <summary> | |||
/// Signals that the property has been modified and requires the scene to be saved for | |||
/// the changes to persist. Only works when the Editor is not playing. | |||
/// </summary> | |||
private static void MarkSceneAsDirty() | |||
{ | |||
if (!EditorApplication.isPlaying) | |||
{ | |||
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); | |||
} | |||
} | |||
/// <summary> | |||
/// Removes the last Brain from the BroadcastHub | |||
/// </summary> | |||
private void RemoveLastBrain() | |||
{ | |||
if (_hub.Count > 0) | |||
{ | |||
_hub.broadcastingBrains.RemoveAt(_hub.broadcastingBrains.Count - 1); | |||
} | |||
} | |||
/// <summary> | |||
/// Adds a new Brain to the BroadcastHub. The value of this brain will not be initialized. | |||
/// </summary> | |||
private void AddBrain() | |||
{ | |||
_hub.broadcastingBrains.Add(null); | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: aa1bef9e5833447ab7251fc6f7a3a609 | |||
timeCreated: 1536852419 |
@@ -0,0 +1,95 @@ | |||
using System.Text; | |||
using MLAgents; | |||
using UnityEditor; | |||
/// <summary> | |||
/// Renders a custom UI for Demonstration Scriptable Object. | |||
/// </summary> | |||
[CustomEditor(typeof(Demonstration))] | |||
[CanEditMultipleObjects] | |||
public class DemonstrationEditor : Editor | |||
{ | |||
SerializedProperty brainParameters; | |||
SerializedProperty demoMetaData; | |||
void OnEnable() | |||
{ | |||
brainParameters = serializedObject.FindProperty("brainParameters"); | |||
demoMetaData = serializedObject.FindProperty("metaData"); | |||
} | |||
/// <summary> | |||
/// Renders Inspector UI for Demonstration metadata. | |||
/// </summary> | |||
void MakeMetaDataProperty(SerializedProperty property) | |||
{ | |||
var nameProp = property.FindPropertyRelative("demonstrationName"); | |||
var expProp = property.FindPropertyRelative("numberExperiences"); | |||
var epiProp = property.FindPropertyRelative("numberEpisodes"); | |||
var rewProp = property.FindPropertyRelative("meanReward"); | |||
var nameLabel = nameProp.displayName + ": " + nameProp.stringValue; | |||
var expLabel = expProp.displayName + ": " + expProp.intValue; | |||
var epiLabel = epiProp.displayName + ": " + epiProp.intValue; | |||
var rewLabel = rewProp.displayName + ": " + rewProp.floatValue; | |||
EditorGUILayout.LabelField(nameLabel); | |||
EditorGUILayout.LabelField(expLabel); | |||
EditorGUILayout.LabelField(epiLabel); | |||
EditorGUILayout.LabelField(rewLabel); | |||
} | |||
/// <summary> | |||
/// Constructs label for action size array. | |||
/// </summary> | |||
static string BuildActionArrayLabel(SerializedProperty actionSizeProperty) | |||
{ | |||
var actionSize = actionSizeProperty.arraySize; | |||
StringBuilder actionLabel = new StringBuilder("[ "); | |||
for (int i = 0; i < actionSize; i++) | |||
{ | |||
actionLabel.Append(actionSizeProperty.GetArrayElementAtIndex(i).intValue); | |||
if (i < actionSize - 1) | |||
{ | |||
actionLabel.Append(", "); | |||
} | |||
} | |||
actionLabel.Append(" ]"); | |||
return actionLabel.ToString(); | |||
} | |||
/// <summary> | |||
/// Renders Inspector UI for Brain Parameters of Demonstration. | |||
/// </summary> | |||
void MakeBrainParametersProperty(SerializedProperty property) | |||
{ | |||
var vecObsSizeProp = property.FindPropertyRelative("vectorObservationSize"); | |||
var numStackedProp = property.FindPropertyRelative("numStackedVectorObservations"); | |||
var actSizeProperty = property.FindPropertyRelative("vectorActionSize"); | |||
var camResProp = property.FindPropertyRelative("cameraResolutions"); | |||
var actSpaceTypeProp = property.FindPropertyRelative("vectorActionSpaceType"); | |||
var vecObsSizeLabel = vecObsSizeProp.displayName + ": " + vecObsSizeProp.intValue; | |||
var numStackedLabel = numStackedProp.displayName + ": " + numStackedProp.intValue; | |||
var vecActSizeLabel = actSizeProperty.displayName + ": " + BuildActionArrayLabel(actSizeProperty); | |||
var camResLabel = camResProp.displayName + ": " + camResProp.arraySize; | |||
var actSpaceTypeLabel = actSpaceTypeProp.displayName + ": " + (SpaceType) actSpaceTypeProp.enumValueIndex; | |||
EditorGUILayout.LabelField(vecObsSizeLabel); | |||
EditorGUILayout.LabelField(numStackedLabel); | |||
EditorGUILayout.LabelField(vecActSizeLabel); | |||
EditorGUILayout.LabelField(camResLabel); | |||
EditorGUILayout.LabelField(actSpaceTypeLabel); | |||
} | |||
public override void OnInspectorGUI() | |||
{ | |||
serializedObject.Update(); | |||
EditorGUILayout.LabelField("Meta Data", EditorStyles.boldLabel); | |||
MakeMetaDataProperty(demoMetaData); | |||
EditorGUILayout.LabelField("Brain Parameters", EditorStyles.boldLabel); | |||
MakeBrainParametersProperty(brainParameters); | |||
serializedObject.ApplyModifiedProperties(); | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 84f9cd83f56c74790a51444a6cfe4945 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,60 @@ | |||
using System; | |||
using System.IO; | |||
using MLAgents.CommunicatorObjects; | |||
using UnityEditor; | |||
using UnityEngine; | |||
using UnityEditor.Experimental.AssetImporters; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// Asset Importer used to parse demonstration files. | |||
/// </summary> | |||
[ScriptedImporter(1, new[] {"demo"})] | |||
public class DemonstrationImporter : ScriptedImporter | |||
{ | |||
private const string IconPath = "Assets/ML-Agents/Resources/DemoIcon.png"; | |||
public override void OnImportAsset(AssetImportContext ctx) | |||
{ | |||
var inputType = Path.GetExtension(ctx.assetPath); | |||
if (inputType == null) | |||
{ | |||
throw new Exception("Demonstration import error."); | |||
} | |||
try | |||
{ | |||
// Read first two proto objects containing metadata and brain parameters. | |||
Stream reader = File.OpenRead(ctx.assetPath); | |||
var metaDataProto = DemonstrationMetaProto.Parser.ParseDelimitedFrom(reader); | |||
var metaData = new DemonstrationMetaData(metaDataProto); | |||
reader.Seek(DemonstrationStore.MetaDataBytes + 1, 0); | |||
var brainParamsProto = BrainParametersProto.Parser.ParseDelimitedFrom(reader); | |||
var brainParameters = new BrainParameters(brainParamsProto); | |||
reader.Close(); | |||
var demonstration = ScriptableObject.CreateInstance<Demonstration>(); | |||
demonstration.Initialize(brainParameters, metaData); | |||
userData = demonstration.ToString(); | |||
Texture2D texture = (Texture2D) | |||
AssetDatabase.LoadAssetAtPath(IconPath, typeof(Texture2D)); | |||
#if UNITY_2017_3_OR_NEWER | |||
ctx.AddObjectToAsset(ctx.assetPath, demonstration, texture); | |||
ctx.SetMainObject(demonstration); | |||
#else | |||
ctx.SetMainAsset(ctx.assetPath, model); | |||
#endif | |||
} | |||
catch | |||
{ | |||
return; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 7bd65ce151aaa4a41a45312543c56be1 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,56 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// CustomEditor for the Heuristic Brain class. Defines the default Inspector view for a | |||
/// HeuristicBrain. | |||
/// Shows the BrainParameters of the Brain and expose a tool to deep copy BrainParameters | |||
/// between brains. Provides a drag box for a Decision Monoscript that will be used by | |||
/// the Heuristic Brain. | |||
/// </summary> | |||
[CustomEditor(typeof(HeuristicBrain))] | |||
public class HeuristicBrainEditor : BrainEditor | |||
{ | |||
public override void OnInspectorGUI() | |||
{ | |||
EditorGUILayout.LabelField("Heuristic Brain", EditorStyles.boldLabel); | |||
var brain = (HeuristicBrain) target; | |||
base.OnInspectorGUI(); | |||
// Expose the Heuristic Brain's Monoscript for decision in a drag and drop box. | |||
brain.decisionScript = EditorGUILayout.ObjectField( | |||
"Decision Script", brain.decisionScript, typeof(MonoScript), true) as MonoScript; | |||
CheckIsDecision(brain); | |||
// Draw an error box if the Decision is not set. | |||
if (brain.decisionScript == null) | |||
{ | |||
EditorGUILayout.HelpBox("You need to add a 'Decision' component to this Object", | |||
MessageType.Error); | |||
} | |||
} | |||
/// <summary> | |||
/// Ensures tht the Monoscript for the decision of the HeuristicBrain is either null or | |||
/// an implementation of Decision. If the Monoscript is not an implementation of | |||
/// Decision, it will be set to null. | |||
/// </summary> | |||
/// <param name="brain">The HeuristicBrain with the decision script attached</param> | |||
private static void CheckIsDecision(HeuristicBrain brain) | |||
{ | |||
if (brain.decisionScript != null) | |||
{ | |||
var decisionInstance = (CreateInstance(brain.decisionScript.name) as Decision); | |||
if (decisionInstance == null) | |||
{ | |||
Debug.LogError( | |||
"Instance of " + brain.decisionScript.name + " couldn't be created. " + | |||
"The the script class needs to derive from Decision."); | |||
brain.decisionScript = null; | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: c3347a9ad704411896dd4898423c6515 | |||
timeCreated: 1536852553 |
@@ -0,0 +1,84 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// CustomEditor for the LearningBrain class. Defines the default Inspector view for a | |||
/// LearningBrain. | |||
/// Shows the BrainParameters of the Brain and expose a tool to deep copy BrainParameters | |||
/// between brains. Also exposes a drag box for the Model that will be used by the | |||
/// LearningBrain. | |||
/// </summary> | |||
[CustomEditor(typeof(LearningBrain))] | |||
public class LearningBrainEditor : BrainEditor | |||
{ | |||
private const string ModelPropName = "model"; | |||
private const string InferenceDevicePropName = "inferenceDevice"; | |||
private const float TimeBetweenModelReloads = 2f; | |||
// Time since the last reload of the model | |||
private float _timeSinceModelReload; | |||
// Whether or not the model needs to be reloaded | |||
private bool _requireReload; | |||
/// <summary> | |||
/// Called when the user opens the Inspector for the LearningBrain | |||
/// </summary> | |||
public void OnEnable() | |||
{ | |||
_requireReload = true; | |||
EditorApplication.update += IncreaseTimeSinceLastModelReload; | |||
} | |||
/// <summary> | |||
/// Called when the user leaves the Inspector for the LearningBrain | |||
/// </summary> | |||
public void OnDisable() | |||
{ | |||
EditorApplication.update -= IncreaseTimeSinceLastModelReload; | |||
} | |||
public override void OnInspectorGUI() | |||
{ | |||
EditorGUILayout.LabelField("Learning Brain", EditorStyles.boldLabel); | |||
var brain = (LearningBrain) target; | |||
var serializedBrain = serializedObject; | |||
EditorGUI.BeginChangeCheck(); | |||
base.OnInspectorGUI(); | |||
serializedBrain.Update(); | |||
var tfGraphModel = serializedBrain.FindProperty(ModelPropName); | |||
EditorGUILayout.ObjectField(tfGraphModel); | |||
var inferenceDevice = serializedBrain.FindProperty(InferenceDevicePropName); | |||
EditorGUILayout.PropertyField(inferenceDevice); | |||
serializedBrain.ApplyModifiedProperties(); | |||
if (EditorGUI.EndChangeCheck()) | |||
{ | |||
_requireReload = true; | |||
} | |||
if (_requireReload && _timeSinceModelReload > TimeBetweenModelReloads) | |||
{ | |||
brain.ReloadModel(); | |||
_requireReload = false; | |||
_timeSinceModelReload = 0; | |||
} | |||
// Display all failed checks | |||
var failedChecks = brain.GetModelFailedChecks(); | |||
foreach (var check in failedChecks) | |||
{ | |||
if (check != null) | |||
{ | |||
EditorGUILayout.HelpBox(check, MessageType.Warning); | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Increases the time since last model reload by the deltaTime since the last Update call | |||
/// from the UnityEditor | |||
/// </summary> | |||
private void IncreaseTimeSinceLastModelReload() | |||
{ | |||
_timeSinceModelReload += Time.deltaTime; | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: b538d92cc78b4a62a596822eca31423e | |||
timeCreated: 1536970736 |
@@ -0,0 +1,29 @@ | |||
using System.IO; | |||
using UnityEditor; | |||
using UnityEngine; | |||
using UnityEditor.Experimental.AssetImporters; | |||
using MLAgents.InferenceBrain; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// Asset Importer of barracuda models. | |||
/// </summary> | |||
[ScriptedImporter(1, new[] {"nn"})] | |||
public class NNModelImporter : ScriptedImporter { | |||
private const string IconPath = "Assets/ML-Agents/Resources/NNModelIcon.png"; | |||
public override void OnImportAsset(AssetImportContext ctx) | |||
{ | |||
var model = File.ReadAllBytes(ctx.assetPath); | |||
var asset = ScriptableObject.CreateInstance<NNModel>(); | |||
asset.Value = model; | |||
Texture2D texture = (Texture2D) | |||
AssetDatabase.LoadAssetAtPath(IconPath, typeof(Texture2D)); | |||
ctx.AddObjectToAsset(ctx.assetPath, asset, texture); | |||
ctx.SetMainObject(asset); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 83221ad3db87f4b3b91b041047cb2bc5 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,106 @@ | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System.Linq; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// CustomEditor for the PlayerBrain class. Defines the default Inspector view for a | |||
/// PlayerBrain. | |||
/// Shows the BrainParameters of the Brain and expose a tool to deep copy BrainParameters | |||
/// between brains. Also exposes the key mappings for either continuous or discrete control | |||
/// depending on the Vector Action Space Type of the Brain Parameter. These mappings are the | |||
/// ones that will be used by the PlayerBrain. | |||
/// </summary> | |||
[CustomEditor(typeof(PlayerBrain))] | |||
public class PlayerBrainEditor : BrainEditor | |||
{ | |||
private const string KeyContinuousPropName = "keyContinuousPlayerActions"; | |||
private const string KeyDiscretePropName = "discretePlayerActions"; | |||
private const string AxisContinuousPropName = "axisContinuousPlayerActions"; | |||
public override void OnInspectorGUI() | |||
{ | |||
EditorGUILayout.LabelField("Player Brain", EditorStyles.boldLabel); | |||
var brain = (PlayerBrain) target; | |||
var serializedBrain = serializedObject; | |||
base.OnInspectorGUI(); | |||
serializedBrain.Update(); | |||
if (brain.brainParameters.vectorActionSpaceType == SpaceType.continuous) | |||
{ | |||
DrawContinuousKeyMapping(serializedBrain, brain); | |||
} | |||
else | |||
{ | |||
DrawDiscreteKeyMapping(serializedBrain); | |||
} | |||
serializedBrain.ApplyModifiedProperties(); | |||
} | |||
/// <summary> | |||
/// Draws the UI for continuous control key mapping to actions. | |||
/// </summary> | |||
/// <param name="serializedBrain"> The SerializedObject corresponding to the brain. </param> | |||
/// <param name="brain"> The Brain of which properties are displayed. </param> | |||
private static void DrawContinuousKeyMapping( | |||
SerializedObject serializedBrain, PlayerBrain brain) | |||
{ | |||
GUILayout.Label("Edit the continuous inputs for your actions", EditorStyles.boldLabel); | |||
var keyActionsProp = serializedBrain.FindProperty(KeyContinuousPropName); | |||
var axisActionsProp = serializedBrain.FindProperty(AxisContinuousPropName); | |||
EditorGUILayout.PropertyField(keyActionsProp , true); | |||
EditorGUILayout.PropertyField(axisActionsProp, true); | |||
var keyContinuous = brain.keyContinuousPlayerActions; | |||
var axisContinuous = brain.axisContinuousPlayerActions; | |||
var brainParams = brain.brainParameters; | |||
if (keyContinuous == null) | |||
{ | |||
keyContinuous = new PlayerBrain.KeyContinuousPlayerAction[0]; | |||
} | |||
if (axisContinuous == null) | |||
{ | |||
axisContinuous = new PlayerBrain.AxisContinuousPlayerAction[0]; | |||
} | |||
foreach (var action in keyContinuous) | |||
{ | |||
if (action.index >= brainParams.vectorActionSize[0]) | |||
{ | |||
EditorGUILayout.HelpBox( | |||
$"Key {action.key.ToString()} is assigned to index " + | |||
$"{action.index.ToString()} but the action size is only of size " + | |||
$"{brainParams.vectorActionSize.ToString()}", | |||
MessageType.Error); | |||
} | |||
} | |||
foreach (var action in axisContinuous) | |||
{ | |||
if (action.index >= brainParams.vectorActionSize[0]) | |||
{ | |||
EditorGUILayout.HelpBox( | |||
$"Axis {action.axis} is assigned to index {action.index.ToString()} " + | |||
$"but the action size is only of size {brainParams.vectorActionSize}", | |||
MessageType.Error); | |||
} | |||
} | |||
GUILayout.Label("You can change axis settings from Edit->Project Settings->Input", | |||
EditorStyles.helpBox ); | |||
} | |||
/// <summary> | |||
/// Draws the UI for discrete control key mapping to actions. | |||
/// </summary> | |||
/// <param name="serializedBrain"> The SerializedObject corresponding to the brain. </param> | |||
private static void DrawDiscreteKeyMapping(SerializedObject serializedBrain) | |||
{ | |||
GUILayout.Label("Edit the discrete inputs for your actions", | |||
EditorStyles.boldLabel); | |||
var dhas = serializedBrain.FindProperty(KeyDiscretePropName); | |||
serializedBrain.Update(); | |||
EditorGUILayout.PropertyField(dhas, true); | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: 0d99e43f78e54b4f96a346219e2ca2d2 | |||
timeCreated: 1536851993 |
@@ -0,0 +1,179 @@ | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System; | |||
using System.Linq; | |||
using UnityEditor.SceneManagement; | |||
namespace MLAgents | |||
{ | |||
/// <summary> | |||
/// PropertyDrawer for ResetParameters. Defines how ResetParameters are displayed in the | |||
/// Inspector. | |||
/// </summary> | |||
[CustomPropertyDrawer(typeof(ResetParameters))] | |||
public class ResetParameterDrawer : PropertyDrawer | |||
{ | |||
private ResetParameters _parameters; | |||
// The height of a line in the Unity Inspectors | |||
private const float LineHeight = 17f; | |||
// This is the prefix for the key when you add a reset parameter | |||
private const string NewKeyPrefix = "Param-"; | |||
/// <summary> | |||
/// Computes the height of the Drawer depending on the property it is showing | |||
/// </summary> | |||
/// <param name="property">The property that is being drawn.</param> | |||
/// <param name="label">The label of the property being drawn.</param> | |||
/// <returns>The vertical space needed to draw the property.</returns> | |||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |||
{ | |||
LazyInitializeParameters(property, label); | |||
return (_parameters.Count + 2) * LineHeight; | |||
} | |||
/// <inheritdoc /> | |||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |||
{ | |||
LazyInitializeParameters(property, label); | |||
position.height = LineHeight; | |||
EditorGUI.LabelField(position, label); | |||
position.y += LineHeight; | |||
var width = position.width / 2 - 24; | |||
var keyRect = new Rect(position.x + 20, position.y, width, position.height); | |||
var valueRect = new Rect(position.x + width + 30, position.y, width, position.height); | |||
DrawAddRemoveButtons(keyRect, valueRect); | |||
EditorGUI.BeginProperty(position, label, property); | |||
foreach (var parameter in _parameters) | |||
{ | |||
var key = parameter.Key; | |||
var value = parameter.Value; | |||
keyRect.y += LineHeight; | |||
valueRect.y += LineHeight; | |||
EditorGUI.BeginChangeCheck(); | |||
var newKey = EditorGUI.TextField(keyRect, key); | |||
if (EditorGUI.EndChangeCheck()) | |||
{ | |||
MarkSceneAsDirty(); | |||
try | |||
{ | |||
_parameters.Remove(key); | |||
_parameters.Add(newKey, value); | |||
} | |||
catch (Exception e) | |||
{ | |||
Debug.Log(e.Message); | |||
} | |||
break; | |||
} | |||
EditorGUI.BeginChangeCheck(); | |||
value = EditorGUI.FloatField(valueRect, value); | |||
if (EditorGUI.EndChangeCheck()) | |||
{ | |||
MarkSceneAsDirty(); | |||
_parameters[key] = value; | |||
break; | |||
} | |||
} | |||
EditorGUI.EndProperty(); | |||
} | |||
/// <summary> | |||
/// Draws the Add and Remove buttons. | |||
/// </summary> | |||
/// <param name="addRect">The rectangle for the Add New button.</param> | |||
/// <param name="removeRect">The rectangle for the Remove Last button.</param> | |||
private void DrawAddRemoveButtons(Rect addRect, Rect removeRect) | |||
{ | |||
// This is the Add button | |||
if (_parameters.Count == 0) | |||
{ | |||
addRect.width *= 2; | |||
} | |||
if (GUI.Button(addRect, | |||
new GUIContent("Add New", "Add a new item to the default reset parameters"), | |||
EditorStyles.miniButton)) | |||
{ | |||
MarkSceneAsDirty(); | |||
AddParameter(); | |||
} | |||
// If there are no items in the ResetParameters, Hide the Remove button | |||
if (_parameters.Count == 0) | |||
{ | |||
return; | |||
} | |||
// This is the Remove button | |||
if (GUI.Button(removeRect, | |||
new GUIContent( | |||
"Remove Last", "Remove the last item from the default reset parameters"), | |||
EditorStyles.miniButton)) | |||
{ | |||
MarkSceneAsDirty(); | |||
RemoveLastParameter(); | |||
} | |||
} | |||
/// <summary> | |||
/// Signals that the property has been modified and requires the scene to be saved for | |||
/// the changes to persist. Only works when the Editor is not playing. | |||
/// </summary> | |||
private static void MarkSceneAsDirty() | |||
{ | |||
if (!EditorApplication.isPlaying) | |||
{ | |||
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); | |||
} | |||
} | |||
/// <summary> | |||
/// Ensures that the state of the Drawer is synchronized with the property. | |||
/// </summary> | |||
/// <param name="property">The SerializedProperty of the ResetParameters | |||
/// to make the custom GUI for.</param> | |||
/// <param name="label">The label of this property.</param> | |||
private void LazyInitializeParameters(SerializedProperty property, GUIContent label) | |||
{ | |||
if (_parameters != null) | |||
{ | |||
return; | |||
} | |||
var target = property.serializedObject.targetObject; | |||
_parameters = fieldInfo.GetValue(target) as ResetParameters; | |||
if (_parameters == null) | |||
{ | |||
_parameters = new ResetParameters(); | |||
fieldInfo.SetValue(target, _parameters); | |||
} | |||
} | |||
/// <summary> | |||
/// Removes the last ResetParameter from the ResetParameters | |||
/// </summary> | |||
private void RemoveLastParameter() | |||
{ | |||
if (_parameters.Count > 0) | |||
{ | |||
string key = _parameters.Keys.ToList()[_parameters.Count - 1]; | |||
_parameters.Remove(key); | |||
} | |||
} | |||
/// <summary> | |||
/// Adds a new ResetParameter to the ResetParameters with a default name. | |||
/// </summary> | |||
private void AddParameter() | |||
{ | |||
string key = NewKeyPrefix + _parameters.Count; | |||
var value = default(float); | |||
try | |||
{ | |||
_parameters.Add(key, value); | |||
} | |||
catch (Exception e) | |||
{ | |||
Debug.Log(e.Message); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 740b9a60fe38f476ab020dcf91f3f94a | |||
timeCreated: 1517291065 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 172fcc71d343247a9a91d5b54dd21cd6 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,66 @@ | |||
using System.Collections.Generic; | |||
using NUnit.Framework; | |||
using UnityEngine; | |||
using System.IO.Abstractions.TestingHelpers; | |||
namespace MLAgents.Tests | |||
{ | |||
public class DemonstrationTests : MonoBehaviour | |||
{ | |||
private const string DemoDirecory = "Assets/Demonstrations/"; | |||
private const string ExtensionType = ".demo"; | |||
private const string DemoName = "Test"; | |||
[Test] | |||
public void TestSanitization() | |||
{ | |||
const string dirtyString = "abc123&!@"; | |||
const string knownCleanString = "abc123"; | |||
var cleanString = DemonstrationRecorder.SanitizeName(dirtyString); | |||
Assert.AreNotEqual(dirtyString, cleanString); | |||
Assert.AreEqual(cleanString, knownCleanString); | |||
} | |||
[Test] | |||
public void TestStoreInitalize() | |||
{ | |||
var fileSystem = new MockFileSystem(); | |||
var demoStore = new DemonstrationStore(fileSystem); | |||
Assert.IsFalse(fileSystem.Directory.Exists(DemoDirecory)); | |||
var brainParameters = new BrainParameters | |||
{ | |||
vectorObservationSize = 3, | |||
numStackedVectorObservations = 2, | |||
cameraResolutions = new [] {new Resolution()}, | |||
vectorActionDescriptions = new [] {"TestActionA", "TestActionB"}, | |||
vectorActionSize = new [] {2, 2}, | |||
vectorActionSpaceType = SpaceType.discrete | |||
}; | |||
demoStore.Initialize(DemoName, brainParameters, "TestBrain"); | |||
Assert.IsTrue(fileSystem.Directory.Exists(DemoDirecory)); | |||
Assert.IsTrue(fileSystem.FileExists(DemoDirecory + DemoName + ExtensionType)); | |||
var agentInfo = new AgentInfo | |||
{ | |||
reward = 1f, | |||
visualObservations = new List<Texture2D>(), | |||
actionMasks = new []{false, true}, | |||
done = true, | |||
id = 5, | |||
maxStepReached = true, | |||
memories = new List<float>(), | |||
stackedVectorObservation = new List<float>() {1f, 1f, 1f}, | |||
storedTextActions = "TestAction", | |||
storedVectorActions = new [] {0f, 1f}, | |||
textObservation = "TestAction", | |||
}; | |||
demoStore.Record(agentInfo); | |||
demoStore.Close(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 4c5a970f5b6be4b57b3bd7a5f84c3623 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,139 @@ | |||
using NUnit.Framework; | |||
namespace MLAgents.Tests | |||
{ | |||
public class EditModeTestActionMasker | |||
{ | |||
[Test] | |||
public void Contruction() | |||
{ | |||
var bp = new BrainParameters(); | |||
var masker = new ActionMasker(bp); | |||
Assert.IsNotNull(masker); | |||
} | |||
[Test] | |||
public void FailsWithContinuous() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.continuous; | |||
bp.vectorActionSize = new int[1] {4}; | |||
var masker = new ActionMasker(bp); | |||
masker.SetActionMask(0, new int[1] {0}); | |||
Assert.Catch<UnityAgentsException>(() => masker.GetMask()); | |||
} | |||
[Test] | |||
public void NullMask() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.discrete; | |||
var masker = new ActionMasker(bp); | |||
var mask = masker.GetMask(); | |||
Assert.IsNull(mask); | |||
} | |||
[Test] | |||
public void FirstBranchMask() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.discrete; | |||
bp.vectorActionSize = new int[3] {4, 5, 6}; | |||
var masker = new ActionMasker(bp); | |||
var mask = masker.GetMask(); | |||
Assert.IsNull(mask); | |||
masker.SetActionMask(0, new int[]{1,2,3}); | |||
mask = masker.GetMask(); | |||
Assert.IsFalse(mask[0]); | |||
Assert.IsTrue(mask[1]); | |||
Assert.IsTrue(mask[2]); | |||
Assert.IsTrue(mask[3]); | |||
Assert.IsFalse(mask[4]); | |||
Assert.AreEqual(mask.Length, 15); | |||
} | |||
[Test] | |||
public void SecondBranchMask() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.discrete; | |||
bp.vectorActionSize = new int[3] {4, 5, 6}; | |||
var masker = new ActionMasker(bp); | |||
bool[] mask = masker.GetMask(); | |||
masker.SetActionMask(1, new int[]{1,2,3}); | |||
mask = masker.GetMask(); | |||
Assert.IsFalse(mask[0]); | |||
Assert.IsFalse(mask[4]); | |||
Assert.IsTrue(mask[5]); | |||
Assert.IsTrue(mask[6]); | |||
Assert.IsTrue(mask[7]); | |||
Assert.IsFalse(mask[8]); | |||
Assert.IsFalse(mask[9]); | |||
} | |||
[Test] | |||
public void MaskReset() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.discrete; | |||
bp.vectorActionSize = new int[3] {4, 5, 6}; | |||
var masker = new ActionMasker(bp); | |||
var mask = masker.GetMask(); | |||
masker.SetActionMask(1, new int[3]{1,2,3}); | |||
mask = masker.GetMask(); | |||
masker.ResetMask(); | |||
mask = masker.GetMask(); | |||
for (var i = 0; i < 15; i++) | |||
{ | |||
Assert.IsFalse(mask[i]); | |||
} | |||
} | |||
[Test] | |||
public void ThrowsError() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.discrete; | |||
bp.vectorActionSize = new int[3] {4, 5, 6}; | |||
var masker = new ActionMasker(bp); | |||
Assert.Catch<UnityAgentsException>( | |||
() => masker.SetActionMask(0, new int[1]{5})); | |||
Assert.Catch<UnityAgentsException>( | |||
() => masker.SetActionMask(1, new int[1]{5})); | |||
masker.SetActionMask(2, new int[1] {5}); | |||
Assert.Catch<UnityAgentsException>( | |||
() => masker.SetActionMask(3, new int[1]{1})); | |||
masker.GetMask(); | |||
masker.ResetMask(); | |||
masker.SetActionMask(0, new int[4] {0, 1, 2, 3}); | |||
Assert.Catch<UnityAgentsException>( | |||
() => masker.GetMask()); | |||
} | |||
[Test] | |||
public void MultipleMaskEdit() | |||
{ | |||
var bp = new BrainParameters(); | |||
bp.vectorActionSpaceType = SpaceType.discrete; | |||
bp.vectorActionSize = new int[3] {4, 5, 6}; | |||
var masker = new ActionMasker(bp); | |||
masker.SetActionMask(0, new int[2] {0, 1}); | |||
masker.SetActionMask(0, new int[1] {3}); | |||
masker.SetActionMask(2, new int[1] {1}); | |||
var mask = masker.GetMask(); | |||
for (var i = 0; i < 15; i++) | |||
{ | |||
if ((i == 0) || (i == 1) || (i == 3)|| (i == 10)) | |||
{ | |||
Assert.IsTrue(mask[i]); | |||
} | |||
else | |||
{ | |||
Assert.IsFalse(mask[i]); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 2e2810ee6c8c64fb39abdf04b5d17f50 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,136 @@ | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using NUnit.Framework; | |||
using UnityEngine; | |||
using System.Reflection; | |||
using MLAgents.InferenceBrain; | |||
namespace MLAgents.Tests | |||
{ | |||
public class EditModeTestInternalBrainTensorApplier | |||
{ | |||
private class TestAgent : Agent | |||
{ | |||
public AgentAction GetAction() | |||
{ | |||
FieldInfo f = typeof(Agent).GetField( | |||
"action", BindingFlags.Instance | BindingFlags.NonPublic); | |||
return (AgentAction) f.GetValue(this); | |||
} | |||
} | |||
private Dictionary<Agent, AgentInfo> GetFakeAgentInfos() | |||
{ | |||
var goA = new GameObject("goA"); | |||
var agentA = goA.AddComponent<TestAgent>(); | |||
var infoA = new AgentInfo(); | |||
var goB = new GameObject("goB"); | |||
var agentB = goB.AddComponent<TestAgent>(); | |||
var infoB = new AgentInfo(); | |||
return new Dictionary<Agent, AgentInfo>(){{agentA, infoA},{agentB, infoB}}; | |||
} | |||
[Test] | |||
public void Contruction() | |||
{ | |||
var bp = new BrainParameters(); | |||
var tensorGenerator = new TensorApplier(bp, 0); | |||
Assert.IsNotNull(tensorGenerator); | |||
} | |||
[Test] | |||
public void ApplyContinuousActionOutput() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 3}, | |||
Data = new float[,] {{1, 2, 3}, {4, 5, 6}} | |||
}; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var applier = new ContinuousActionOutputApplier(); | |||
applier.Apply(inputTensor, agentInfos); | |||
var agents = agentInfos.Keys.ToList(); | |||
var agent = agents[0] as TestAgent; | |||
var action = agent.GetAction(); | |||
Assert.AreEqual(action.vectorActions[0], 1); | |||
Assert.AreEqual(action.vectorActions[1], 2); | |||
Assert.AreEqual(action.vectorActions[2], 3); | |||
agent = agents[1] as TestAgent; | |||
action = agent.GetAction(); | |||
Assert.AreEqual(action.vectorActions[0], 4); | |||
Assert.AreEqual(action.vectorActions[1], 5); | |||
Assert.AreEqual(action.vectorActions[2], 6); | |||
} | |||
[Test] | |||
public void ApplyDiscreteActionOutput() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 5}, | |||
Data = new float[,] {{0.5f, 22.5f, 0.1f, 5f, 1f}, | |||
{4f, 5f, 6f, 7f, 8f}} | |||
}; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var applier = new DiscreteActionOutputApplier(new int[]{2, 3}, 0); | |||
applier.Apply(inputTensor, agentInfos); | |||
var agents = agentInfos.Keys.ToList(); | |||
var agent = agents[0] as TestAgent; | |||
var action = agent.GetAction(); | |||
Assert.AreEqual(action.vectorActions[0], 1); | |||
Assert.AreEqual(action.vectorActions[1], 1); | |||
agent = agents[1] as TestAgent; | |||
action = agent.GetAction(); | |||
Assert.AreEqual(action.vectorActions[0], 1); | |||
Assert.AreEqual(action.vectorActions[1], 2); | |||
} | |||
[Test] | |||
public void ApplyMemoryOutput() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 5}, | |||
Data = new float[,] {{0.5f, 22.5f, 0.1f, 5f, 1f}, | |||
{4f, 5f, 6f, 7f, 8f}} | |||
}; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var applier = new MemoryOutputApplier(); | |||
applier.Apply(inputTensor, agentInfos); | |||
var agents = agentInfos.Keys.ToList(); | |||
var agent = agents[0] as TestAgent; | |||
var action = agent.GetAction(); | |||
Assert.AreEqual(action.memories[0], 0.5f); | |||
Assert.AreEqual(action.memories[1], 22.5f); | |||
agent = agents[1] as TestAgent; | |||
action = agent.GetAction(); | |||
Assert.AreEqual(action.memories[2], 6); | |||
Assert.AreEqual(action.memories[3], 7); | |||
} | |||
[Test] | |||
public void ApplyValueEstimate() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 1}, | |||
Data = new float[,] {{0.5f}, {8f}} | |||
}; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var applier = new ValueEstimateApplier(); | |||
applier.Apply(inputTensor, agentInfos); | |||
var agents = agentInfos.Keys.ToList(); | |||
var agent = agents[0] as TestAgent; | |||
var action = agent.GetAction(); | |||
Assert.AreEqual(action.value, 0.5f); | |||
agent = agents[1] as TestAgent; | |||
action = agent.GetAction(); | |||
Assert.AreEqual(action.value, 8); | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: be419f7ed5c24b24a6f2636d3b107535 | |||
timeCreated: 1537915674 |
@@ -0,0 +1,153 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using NUnit.Framework; | |||
using UnityEngine; | |||
using MLAgents.InferenceBrain; | |||
namespace MLAgents.Tests | |||
{ | |||
public class EditModeTestInternalBrainTensorGenerator | |||
{ | |||
private class TestAgent : Agent | |||
{ | |||
} | |||
private Dictionary<Agent, AgentInfo> GetFakeAgentInfos() | |||
{ | |||
var goA = new GameObject("goA"); | |||
var agentA = goA.AddComponent<TestAgent>(); | |||
var infoA = new AgentInfo() | |||
{ | |||
stackedVectorObservation = (new float[] {1f, 2f, 3f}).ToList(), | |||
memories = null, | |||
storedVectorActions = new float[] {1, 2}, | |||
actionMasks = null, | |||
}; | |||
var goB = new GameObject("goB"); | |||
var agentB = goB.AddComponent<TestAgent>(); | |||
var infoB = new AgentInfo() | |||
{ | |||
stackedVectorObservation = (new float[] {4f, 5f, 6f}).ToList(), | |||
memories = (new float[] {1f, 1f, 1f}).ToList(), | |||
storedVectorActions = new float[] {3, 4}, | |||
actionMasks = new bool[] {true, false, false, false, false}, | |||
}; | |||
return new Dictionary<Agent, AgentInfo>(){{agentA, infoA},{agentB, infoB}}; | |||
} | |||
[Test] | |||
public void Contruction() | |||
{ | |||
var bp = new BrainParameters(); | |||
var tensorGenerator = new TensorGenerator(bp, 0); | |||
Assert.IsNotNull(tensorGenerator); | |||
} | |||
[Test] | |||
public void GenerateBatchSize() | |||
{ | |||
var inputTensor = new Tensor(); | |||
var batchSize = 4; | |||
var generator = new BatchSizeGenerator(); | |||
generator.Generate(inputTensor, batchSize, null); | |||
Assert.IsNotNull(inputTensor.Data as int[]); | |||
Assert.AreEqual((inputTensor.Data as int[])[0], batchSize); | |||
} | |||
[Test] | |||
public void GenerateSequenceLength() | |||
{ | |||
var inputTensor = new Tensor(); | |||
var batchSize = 4; | |||
var generator = new SequenceLengthGenerator(); | |||
generator.Generate(inputTensor, batchSize, null); | |||
Assert.IsNotNull(inputTensor.Data as int[]); | |||
Assert.AreEqual((inputTensor.Data as int[])[0], 1); | |||
} | |||
[Test] | |||
public void GenerateVectorObservation() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 3} | |||
}; | |||
var batchSize = 4; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var generator = new VectorObservationGenerator(); | |||
generator.Generate(inputTensor, batchSize, agentInfos); | |||
Assert.IsNotNull(inputTensor.Data as float[,]); | |||
Assert.AreEqual((inputTensor.Data as float[,])[0, 0], 1); | |||
Assert.AreEqual((inputTensor.Data as float[,])[0, 2], 3); | |||
Assert.AreEqual((inputTensor.Data as float[,])[1, 0], 4); | |||
Assert.AreEqual((inputTensor.Data as float[,])[1, 2], 6); | |||
} | |||
[Test] | |||
public void GenerateRecurrentInput() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 5} | |||
}; | |||
var batchSize = 4; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var generator = new RecurrentInputGenerator(); | |||
generator.Generate(inputTensor, batchSize, agentInfos); | |||
Assert.IsNotNull(inputTensor.Data as float[,]); | |||
Assert.AreEqual((inputTensor.Data as float[,])[0, 0], 0); | |||
Assert.AreEqual((inputTensor.Data as float[,])[0, 4], 0); | |||
Assert.AreEqual((inputTensor.Data as float[,])[1, 0], 1); | |||
Assert.AreEqual((inputTensor.Data as float[,])[1, 4], 0); | |||
} | |||
[Test] | |||
public void GeneratePreviousActionInput() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 2}, | |||
ValueType = Tensor.TensorType.Integer | |||
}; | |||
var batchSize = 4; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var generator = new PreviousActionInputGenerator(); | |||
generator.Generate(inputTensor, batchSize, agentInfos); | |||
Assert.IsNotNull(inputTensor.Data as int[,]); | |||
Assert.AreEqual((inputTensor.Data as int[,])[0, 0], 1); | |||
Assert.AreEqual((inputTensor.Data as int[,])[0, 1], 2); | |||
Assert.AreEqual((inputTensor.Data as int[,])[1, 0], 3); | |||
Assert.AreEqual((inputTensor.Data as int[,])[1, 1], 4); | |||
} | |||
[Test] | |||
public void GenerateActionMaskInput() | |||
{ | |||
var inputTensor = new Tensor() | |||
{ | |||
Shape = new long[] {2, 5}, | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
var batchSize = 4; | |||
var agentInfos = GetFakeAgentInfos(); | |||
var generator = new ActionMaskInputGenerator(); | |||
generator.Generate(inputTensor, batchSize, agentInfos); | |||
Assert.IsNotNull(inputTensor.Data as float[,]); | |||
Assert.AreEqual((inputTensor.Data as float[,])[0, 0], 1); | |||
Assert.AreEqual((inputTensor.Data as float[,])[0, 4], 1); | |||
Assert.AreEqual((inputTensor.Data as float[,])[1, 0], 0); | |||
Assert.AreEqual((inputTensor.Data as float[,])[1, 4], 1); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: d2d2076c51c414ac7a91f8fbf15d4f7c | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,819 @@ | |||
using UnityEngine; | |||
using NUnit.Framework; | |||
using System.Reflection; | |||
namespace MLAgents.Tests | |||
{ | |||
public class TestAcademy : Academy | |||
{ | |||
public int initializeAcademyCalls; | |||
public int academyResetCalls; | |||
public int AcademyStepCalls; | |||
public override void InitializeAcademy() | |||
{ | |||
initializeAcademyCalls += 1; | |||
} | |||
public override void AcademyReset() | |||
{ | |||
academyResetCalls += 1; | |||
} | |||
public override void AcademyStep() | |||
{ | |||
AcademyStepCalls += 1; | |||
} | |||
} | |||
public class TestAgent : Agent | |||
{ | |||
public int initializeAgentCalls; | |||
public int collectObservationsCalls; | |||
public int agentActionCalls; | |||
public int agentResetCalls; | |||
public int agentOnDoneCalls; | |||
public override void InitializeAgent() | |||
{ | |||
initializeAgentCalls += 1; | |||
} | |||
public override void CollectObservations() | |||
{ | |||
collectObservationsCalls += 1; | |||
} | |||
public override void AgentAction(float[] vectorAction, string textAction) | |||
{ | |||
agentActionCalls += 1; | |||
AddReward(0.1f); | |||
} | |||
public override void AgentReset() | |||
{ | |||
agentResetCalls += 1; | |||
} | |||
public override void AgentOnDone() | |||
{ | |||
agentOnDoneCalls += 1; | |||
} | |||
} | |||
// This is an empty class for testing the behavior of agents and academy | |||
// It is left empty because we are not testing any brain behavior | |||
public class TestBrain : Brain | |||
{ | |||
public int numberOfCallsToInitialize = 0; | |||
public int numberOfCallsToDecideAction = 0; | |||
public static TestBrain Instantiate() | |||
{ | |||
return CreateInstance<TestBrain>(); | |||
} | |||
protected override void Initialize() | |||
{ | |||
numberOfCallsToInitialize++; | |||
} | |||
protected override void DecideAction() | |||
{ | |||
numberOfCallsToDecideAction++; | |||
agentInfos.Clear(); | |||
} | |||
} | |||
public class EditModeTestGeneration | |||
{ | |||
[Test] | |||
public void TestAcademy() | |||
{ | |||
// Use the Assert class to test conditions. | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
Assert.AreNotEqual(null, aca); | |||
Assert.AreEqual(0, aca.initializeAcademyCalls); | |||
Assert.AreEqual(0, aca.GetEpisodeCount()); | |||
Assert.AreEqual(0, aca.GetStepCount()); | |||
} | |||
[Test] | |||
public void TestAgent() | |||
{ | |||
GameObject agentGO = new GameObject("TestAgent"); | |||
agentGO.AddComponent<TestAgent>(); | |||
TestAgent agent = agentGO.GetComponent<TestAgent>(); | |||
Assert.AreNotEqual(null, agent); | |||
Assert.AreEqual(0, agent.initializeAgentCalls); | |||
} | |||
} | |||
public class EditModeTestInitialization | |||
{ | |||
private Brain GenerateTestBrain() | |||
{ | |||
return ScriptableObject.CreateInstance<TestBrain>(); | |||
} | |||
[Test] | |||
public void TestAcademy() | |||
{ | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
Assert.AreEqual(0, aca.initializeAcademyCalls); | |||
Assert.AreEqual(0, aca.GetStepCount()); | |||
Assert.AreEqual(0, aca.GetEpisodeCount()); | |||
Assert.AreEqual(false, aca.IsDone()); | |||
//This will call the method even though it is private | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod("InitializeEnvironment", | |||
BindingFlags.Instance | BindingFlags.NonPublic); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
Assert.AreEqual(1, aca.initializeAcademyCalls); | |||
Assert.AreEqual(0, aca.GetEpisodeCount()); | |||
Assert.AreEqual(0, aca.GetStepCount()); | |||
Assert.AreEqual(false, aca.IsDone()); | |||
Assert.AreEqual(0, aca.academyResetCalls); | |||
Assert.AreEqual(0, aca.AcademyStepCalls); | |||
} | |||
[Test] | |||
public void TestAgent() | |||
{ | |||
GameObject agentGO1 = new GameObject("TestAgent"); | |||
agentGO1.AddComponent<TestAgent>(); | |||
TestAgent agent1 = agentGO1.GetComponent<TestAgent>(); | |||
GameObject agentGO2 = new GameObject("TestAgent"); | |||
agentGO2.AddComponent<TestAgent>(); | |||
TestAgent agent2 = agentGO2.GetComponent<TestAgent>(); | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
TestBrain brain = TestBrain.Instantiate(); | |||
brain.brainParameters = new BrainParameters(); | |||
brain.brainParameters.vectorObservationSize = 0; | |||
agent1.GiveBrain(brain); | |||
agent2.GiveBrain(brain); | |||
Assert.AreEqual(false, agent1.IsDone()); | |||
Assert.AreEqual(false, agent2.IsDone()); | |||
Assert.AreEqual(0, agent1.agentResetCalls); | |||
Assert.AreEqual(0, agent2.agentResetCalls); | |||
Assert.AreEqual(0, agent1.initializeAgentCalls); | |||
Assert.AreEqual(0, agent2.initializeAgentCalls); | |||
Assert.AreEqual(0, agent1.agentActionCalls); | |||
Assert.AreEqual(0, agent2.agentActionCalls); | |||
MethodInfo AgentEnableMethod = typeof(Agent).GetMethod("OnEnableHelper", | |||
BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod("InitializeEnvironment", | |||
BindingFlags.Instance | BindingFlags.NonPublic); | |||
AgentEnableMethod.Invoke(agent2, new object[] { aca }); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
AgentEnableMethod.Invoke(agent1, new object[] { aca }); | |||
Assert.AreEqual(false, agent1.IsDone()); | |||
Assert.AreEqual(false, agent2.IsDone()); | |||
// agent1 was not enabled when the academy started | |||
// The agents have been initialized | |||
Assert.AreEqual(0, agent1.agentResetCalls); | |||
Assert.AreEqual(0, agent2.agentResetCalls); | |||
Assert.AreEqual(1, agent1.initializeAgentCalls); | |||
Assert.AreEqual(1, agent2.initializeAgentCalls); | |||
Assert.AreEqual(0, agent1.agentActionCalls); | |||
Assert.AreEqual(0, agent2.agentActionCalls); | |||
} | |||
} | |||
public class EditModeTestStep | |||
{ | |||
[Test] | |||
public void TestAcademy() | |||
{ | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod("InitializeEnvironment", | |||
BindingFlags.Instance | BindingFlags.NonPublic); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod("EnvironmentStep", | |||
BindingFlags.Instance | BindingFlags.NonPublic); | |||
int numberReset = 0; | |||
for (int i = 0; i < 10; i++) | |||
{ | |||
Assert.AreEqual(1, aca.initializeAcademyCalls); | |||
Assert.AreEqual(numberReset, aca.GetEpisodeCount()); | |||
Assert.AreEqual(i, aca.GetStepCount()); | |||
Assert.AreEqual(false, aca.IsDone()); | |||
Assert.AreEqual(numberReset, aca.academyResetCalls); | |||
Assert.AreEqual(i, aca.AcademyStepCalls); | |||
// The reset happens at the begining of the first step | |||
if (i == 0) | |||
{ | |||
numberReset += 1; | |||
} | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
} | |||
} | |||
[Test] | |||
public void TestAgent() | |||
{ | |||
GameObject agentGO1 = new GameObject("TestAgent"); | |||
agentGO1.AddComponent<TestAgent>(); | |||
TestAgent agent1 = agentGO1.GetComponent<TestAgent>(); | |||
GameObject agentGO2 = new GameObject("TestAgent"); | |||
agentGO2.AddComponent<TestAgent>(); | |||
TestAgent agent2 = agentGO2.GetComponent<TestAgent>(); | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
TestBrain brain = TestBrain.Instantiate(); | |||
MethodInfo AgentEnableMethod = typeof(Agent).GetMethod( | |||
"OnEnableHelper", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
agent1.agentParameters = new AgentParameters(); | |||
agent2.agentParameters = new AgentParameters(); | |||
brain.brainParameters = new BrainParameters(); | |||
// We use event based so the agent will now try to send anything to the brain | |||
agent1.agentParameters.onDemandDecision = false; | |||
agent1.agentParameters.numberOfActionsBetweenDecisions = 2; | |||
// agent1 will take an action at every step and request a decision every 2 steps | |||
agent2.agentParameters.onDemandDecision = true; | |||
// agent2 will request decisions only when RequestDecision is called | |||
brain.brainParameters.vectorObservationSize = 0; | |||
brain.brainParameters.cameraResolutions = new Resolution[0]; | |||
agent1.GiveBrain(brain); | |||
agent2.GiveBrain(brain); | |||
AgentEnableMethod.Invoke(agent1, new object[] { aca }); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
int numberAgent1Reset = 0; | |||
int numberAgent2Initialization = 0; | |||
int requestDecision = 0; | |||
int requestAction = 0; | |||
for (int i = 0; i < 50; i++) | |||
{ | |||
Assert.AreEqual(numberAgent1Reset, agent1.agentResetCalls); | |||
// Agent2 is never reset since intialized after academy | |||
Assert.AreEqual(0, agent2.agentResetCalls); | |||
Assert.AreEqual(1, agent1.initializeAgentCalls); | |||
Assert.AreEqual(numberAgent2Initialization, agent2.initializeAgentCalls); | |||
Assert.AreEqual(i, agent1.agentActionCalls); | |||
Assert.AreEqual(requestAction, agent2.agentActionCalls); | |||
Assert.AreEqual((i + 1) / 2, agent1.collectObservationsCalls); | |||
Assert.AreEqual(requestDecision, agent2.collectObservationsCalls); | |||
// Agent 1 resets at the first step | |||
if (i == 0) | |||
{ | |||
numberAgent1Reset += 1; | |||
} | |||
//Agent 2 is only initialized at step 2 | |||
if (i == 2) | |||
{ | |||
AgentEnableMethod.Invoke(agent2, new object[] { aca }); | |||
numberAgent2Initialization += 1; | |||
} | |||
// We are testing request decision and request actions when called | |||
// at different intervals | |||
if ((i % 3 == 0) && (i > 2)) | |||
{ | |||
//Every 3 steps after agent 2 is initialized, request decision | |||
requestDecision += 1; | |||
requestAction += 1; | |||
agent2.RequestDecision(); | |||
} | |||
else if ((i % 5 == 0) && (i > 2)) | |||
{ | |||
// Every 5 steps after agent 2 is initialized, request action | |||
requestAction += 1; | |||
agent2.RequestAction(); | |||
} | |||
AcademyStepMethod.Invoke(aca, new object[] { }); | |||
} | |||
} | |||
} | |||
public class EditModeTestReset | |||
{ | |||
[Test] | |||
public void TestAcademy() | |||
{ | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
int numberReset = 0; | |||
int stepsSinceReset = 0; | |||
for (int i = 0; i < 50; i++) | |||
{ | |||
Assert.AreEqual(stepsSinceReset, aca.GetStepCount()); | |||
Assert.AreEqual(1, aca.initializeAcademyCalls); | |||
Assert.AreEqual(numberReset, aca.GetEpisodeCount()); | |||
Assert.AreEqual(false, aca.IsDone()); | |||
Assert.AreEqual(numberReset, aca.academyResetCalls); | |||
Assert.AreEqual(i, aca.AcademyStepCalls); | |||
// Academy resets at the first step | |||
if (i == 0) | |||
{ | |||
numberReset += 1; | |||
} | |||
stepsSinceReset += 1; | |||
// Regularly set the academy to done to check behavior | |||
if (i % 5 == 3) | |||
{ | |||
aca.Done(); | |||
numberReset += 1; | |||
stepsSinceReset = 1; | |||
Assert.AreEqual(true, aca.IsDone()); | |||
} | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
} | |||
} | |||
[Test] | |||
public void TestAgent() | |||
{ | |||
GameObject agentGO1 = new GameObject("TestAgent"); | |||
agentGO1.AddComponent<TestAgent>(); | |||
TestAgent agent1 = agentGO1.GetComponent<TestAgent>(); | |||
GameObject agentGO2 = new GameObject("TestAgent"); | |||
agentGO2.AddComponent<TestAgent>(); | |||
TestAgent agent2 = agentGO2.GetComponent<TestAgent>(); | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
TestBrain brain = TestBrain.Instantiate(); | |||
MethodInfo AgentEnableMethod = typeof(Agent).GetMethod( | |||
"OnEnableHelper", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
agent1.agentParameters = new AgentParameters(); | |||
agent2.agentParameters = new AgentParameters(); | |||
brain.brainParameters = new BrainParameters(); | |||
// We use event based so the agent will now try to send anything to the brain | |||
agent1.agentParameters.onDemandDecision = false; | |||
agent1.agentParameters.numberOfActionsBetweenDecisions = 2; | |||
// agent1 will take an action at every step and request a decision every 2 steps | |||
agent2.agentParameters.onDemandDecision = true; | |||
// agent2 will request decisions only when RequestDecision is called | |||
brain.brainParameters.vectorObservationSize = 0; | |||
brain.brainParameters.cameraResolutions = new Resolution[0]; | |||
agent1.GiveBrain(brain); | |||
agent2.GiveBrain(brain); | |||
AgentEnableMethod.Invoke(agent2, new object[] { aca }); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
int numberAgent1Reset = 0; | |||
int numberAgent2Reset = 0; | |||
int numberAcaReset = 0; | |||
int acaStepsSinceReset = 0; | |||
int agent1StepSinceReset = 0; | |||
int agent2StepSinceReset = 0; | |||
int requestDecision = 0; | |||
int requestAction = 0; | |||
for (int i = 0; i < 5000; i++) | |||
{ | |||
Assert.AreEqual(acaStepsSinceReset, aca.GetStepCount()); | |||
Assert.AreEqual(1, aca.initializeAcademyCalls); | |||
Assert.AreEqual(numberAcaReset, aca.GetEpisodeCount()); | |||
Assert.AreEqual(false, aca.IsDone()); | |||
Assert.AreEqual(numberAcaReset, aca.academyResetCalls); | |||
Assert.AreEqual(i, aca.AcademyStepCalls); | |||
Assert.AreEqual(agent2StepSinceReset, agent2.GetStepCount()); | |||
Assert.AreEqual(numberAgent1Reset, agent1.agentResetCalls); | |||
Assert.AreEqual(numberAgent2Reset, agent2.agentResetCalls); | |||
// Agent 2 and academy reset at the first step | |||
if (i == 0) | |||
{ | |||
numberAcaReset += 1; | |||
numberAgent2Reset += 1; | |||
} | |||
//Agent 1 is only initialized at step 2 | |||
if (i == 2) | |||
{ | |||
AgentEnableMethod.Invoke(agent1, new object[] { aca }); | |||
} | |||
// Reset Academy every 100 steps | |||
if (i % 100 == 3) | |||
{ | |||
aca.Done(); | |||
numberAcaReset += 1; | |||
acaStepsSinceReset = 0; | |||
} | |||
// Set agent 1 to done every 11 steps to test behavior | |||
if (i % 11 == 5) | |||
{ | |||
agent1.Done(); | |||
} | |||
// Reseting agent 2 regularly | |||
if (i % 13 == 3) | |||
{ | |||
if (!(agent2.IsDone() || aca.IsDone())) | |||
{ | |||
// If the agent was already reset before the request decision | |||
// We should not reset again | |||
agent2.Done(); | |||
numberAgent2Reset += 1; | |||
agent2StepSinceReset = 0; | |||
} | |||
} | |||
// Request a decision for agent 2 regularly | |||
if (i % 3 == 2) | |||
{ | |||
requestDecision += 1; | |||
requestAction += 1; | |||
agent2.RequestDecision(); | |||
} | |||
else if (i % 5 == 1) | |||
{ | |||
// Request an action without decision regularly | |||
requestAction += 1; | |||
agent2.RequestAction(); | |||
} | |||
if (agent1.IsDone() && (((acaStepsSinceReset) % agent1.agentParameters.numberOfActionsBetweenDecisions == 0)) || aca.IsDone()) | |||
{ | |||
numberAgent1Reset += 1; | |||
agent1StepSinceReset = 0; | |||
} | |||
if (aca.IsDone()) | |||
{ | |||
numberAgent2Reset += 1; | |||
agent2StepSinceReset = 0; | |||
} | |||
acaStepsSinceReset += 1; | |||
agent1StepSinceReset += 1; | |||
agent2StepSinceReset += 1; | |||
//Agent 1 is only initialized at step 2 | |||
if (i < 2) | |||
{ | |||
agent1StepSinceReset = 0; | |||
} | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
} | |||
} | |||
} | |||
public class EditModeTestMaxStep | |||
{ | |||
[Test] | |||
public void TestAcademy() | |||
{ | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
FieldInfo maxStep = typeof(Academy).GetField( | |||
"maxSteps", BindingFlags.Instance | BindingFlags.NonPublic); | |||
maxStep.SetValue((object)aca, 20); | |||
int numberReset = 0; | |||
int stepsSinceReset = 0; | |||
for (int i = 0; i < 50; i++) | |||
{ | |||
Assert.AreEqual(stepsSinceReset, aca.GetStepCount()); | |||
Assert.AreEqual(1, aca.initializeAcademyCalls); | |||
Assert.AreEqual(false, aca.IsDone()); | |||
Assert.AreEqual(i, aca.AcademyStepCalls); | |||
Assert.AreEqual(numberReset, aca.GetEpisodeCount()); | |||
Assert.AreEqual(numberReset, aca.academyResetCalls); | |||
stepsSinceReset += 1; | |||
// Make sure max step is reached every 20 steps | |||
if (i % 20 == 0) | |||
{ | |||
numberReset += 1; | |||
stepsSinceReset = 1; | |||
} | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
} | |||
} | |||
[Test] | |||
public void TestAgent() | |||
{ | |||
GameObject agentGO1 = new GameObject("TestAgent"); | |||
agentGO1.AddComponent<TestAgent>(); | |||
TestAgent agent1 = agentGO1.GetComponent<TestAgent>(); | |||
GameObject agentGO2 = new GameObject("TestAgent"); | |||
agentGO2.AddComponent<TestAgent>(); | |||
TestAgent agent2 = agentGO2.GetComponent<TestAgent>(); | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
TestBrain brain = TestBrain.Instantiate(); | |||
MethodInfo AgentEnableMethod = typeof(Agent).GetMethod( | |||
"OnEnableHelper", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
FieldInfo maxStep = typeof(Academy).GetField( | |||
"maxSteps", BindingFlags.Instance | BindingFlags.NonPublic); | |||
maxStep.SetValue((object)aca, 100); | |||
agent1.agentParameters = new AgentParameters(); | |||
agent2.agentParameters = new AgentParameters(); | |||
brain.brainParameters = new BrainParameters(); | |||
// We use event based so the agent will now try to send anything to the brain | |||
agent1.agentParameters.onDemandDecision = false; | |||
agent1.agentParameters.numberOfActionsBetweenDecisions = 1; | |||
// agent1 will take an action at every step and request a decision every 2 steps | |||
agent2.agentParameters.onDemandDecision = true; | |||
// agent2 will request decisions only when RequestDecision is called | |||
agent1.agentParameters.maxStep = 20; | |||
agent2.agentParameters.maxStep = 30; | |||
brain.brainParameters.vectorObservationSize = 0; | |||
brain.brainParameters.cameraResolutions = new Resolution[0]; | |||
agent1.GiveBrain(brain); | |||
agent2.GiveBrain(brain); | |||
AgentEnableMethod.Invoke(agent2, new object[] { aca }); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
int numberAgent1Reset = 0; | |||
int numberAgent2Reset = 0; | |||
int numberAcaReset = 0; | |||
int acaStepsSinceReset = 0; | |||
int agent1StepSinceReset = 0; | |||
int agent2StepSinceReset = 0; | |||
for (int i = 0; i < 500; i++) | |||
{ | |||
Assert.AreEqual(acaStepsSinceReset, aca.GetStepCount()); | |||
Assert.AreEqual(1, aca.initializeAcademyCalls); | |||
Assert.AreEqual(i, aca.AcademyStepCalls); | |||
Assert.AreEqual(agent1StepSinceReset, agent1.GetStepCount()); | |||
Assert.AreEqual(agent2StepSinceReset, agent2.GetStepCount()); | |||
Assert.AreEqual(numberAcaReset, aca.GetEpisodeCount()); | |||
Assert.AreEqual(numberAcaReset, aca.academyResetCalls); | |||
Assert.AreEqual(numberAgent1Reset, agent1.agentResetCalls); | |||
Assert.AreEqual(numberAgent2Reset, agent2.agentResetCalls); | |||
//At the first step, Academy and agent 2 reset | |||
if (i == 0) | |||
{ | |||
numberAcaReset += 1; | |||
numberAgent2Reset += 1; | |||
} | |||
//Agent 1 is only initialized at step 2 | |||
if (i == 2) | |||
{ | |||
AgentEnableMethod.Invoke(agent1, new object[] { aca }); | |||
} | |||
// we request a decision at each step | |||
agent2.RequestDecision(); | |||
if (i > 3) | |||
{ | |||
// Make sure the academy max steps at 100 | |||
if (i % 100 == 0) | |||
{ | |||
acaStepsSinceReset = 0; | |||
agent1StepSinceReset = 0; | |||
agent2StepSinceReset = 0; | |||
numberAcaReset += 1; | |||
numberAgent1Reset += 1; | |||
numberAgent2Reset += 1; | |||
} | |||
else | |||
{ | |||
//Make sure the agents reset when their max steps is reached | |||
if (agent1StepSinceReset % 21 == 0) | |||
{ | |||
agent1StepSinceReset = 0; | |||
numberAgent1Reset += 1; | |||
} | |||
if (agent2StepSinceReset % 31 == 0) | |||
{ | |||
agent2StepSinceReset = 0; | |||
numberAgent2Reset += 1; | |||
} | |||
} | |||
} | |||
acaStepsSinceReset += 1; | |||
agent1StepSinceReset += 1; | |||
agent2StepSinceReset += 1; | |||
//Agent 1 is only initialized at step 2 | |||
if (i < 2) | |||
{ | |||
agent1StepSinceReset = 0; | |||
} | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
} | |||
} | |||
} | |||
public class EditModeTestMiscellaneous | |||
{ | |||
[Test] | |||
public void TestResetOnDone() | |||
{ | |||
GameObject agentGO1 = new GameObject("TestAgent"); | |||
agentGO1.AddComponent<TestAgent>(); | |||
TestAgent agent1 = agentGO1.GetComponent<TestAgent>(); | |||
GameObject agentGO2 = new GameObject("TestAgent"); | |||
agentGO2.AddComponent<TestAgent>(); | |||
TestAgent agent2 = agentGO2.GetComponent<TestAgent>(); | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
TestBrain brain = TestBrain.Instantiate(); | |||
MethodInfo AgentEnableMethod = typeof(Agent).GetMethod( | |||
"OnEnableHelper", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
agent1.agentParameters = new AgentParameters(); | |||
agent2.agentParameters = new AgentParameters(); | |||
brain.brainParameters = new BrainParameters(); | |||
// We use event based so the agent will now try to send anything to the brain | |||
agent1.agentParameters.onDemandDecision = false; | |||
// agent1 will take an action at every step and request a decision every steps | |||
agent1.agentParameters.numberOfActionsBetweenDecisions = 1; | |||
// agent2 will request decisions only when RequestDecision is called | |||
agent2.agentParameters.onDemandDecision = true; | |||
agent1.agentParameters.maxStep = 20; | |||
//Here we specify that the agent does not reset when done | |||
agent1.agentParameters.resetOnDone = false; | |||
agent2.agentParameters.resetOnDone = false; | |||
brain.brainParameters.vectorObservationSize = 0; | |||
brain.brainParameters.cameraResolutions = new Resolution[0]; | |||
agent1.GiveBrain(brain); | |||
agent2.GiveBrain(brain); | |||
AgentEnableMethod.Invoke(agent2, new object[] { aca }); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
AgentEnableMethod.Invoke(agent1, new object[] { aca }); | |||
int agent1ResetOnDone = 0; | |||
int agent2ResetOnDone = 0; | |||
int acaStepsSinceReset = 0; | |||
int agent1StepSinceReset = 0; | |||
int agent2StepSinceReset = 0; | |||
for (int i = 0; i < 50; i++) | |||
{ | |||
Assert.AreEqual(i, aca.AcademyStepCalls); | |||
Assert.AreEqual(agent1StepSinceReset, agent1.GetStepCount()); | |||
Assert.AreEqual(agent2StepSinceReset, agent2.GetStepCount()); | |||
Assert.AreEqual(agent1ResetOnDone, agent1.agentOnDoneCalls); | |||
Assert.AreEqual(agent2ResetOnDone, agent2.agentOnDoneCalls); | |||
// we request a decision at each step | |||
agent2.RequestDecision(); | |||
acaStepsSinceReset += 1; | |||
if (agent1ResetOnDone == 0) | |||
agent1StepSinceReset += 1; | |||
if (agent2ResetOnDone == 0) | |||
agent2StepSinceReset += 1; | |||
if ((i > 2) && (i % 21 == 0)) | |||
{ | |||
agent1ResetOnDone = 1; | |||
} | |||
if (i == 31) | |||
{ | |||
agent2ResetOnDone = 1; | |||
agent2.Done(); | |||
} | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
} | |||
} | |||
[Test] | |||
public void TestCumulativeReward() | |||
{ | |||
GameObject agentGO1 = new GameObject("TestAgent"); | |||
agentGO1.AddComponent<TestAgent>(); | |||
TestAgent agent1 = agentGO1.GetComponent<TestAgent>(); | |||
GameObject agentGO2 = new GameObject("TestAgent"); | |||
agentGO2.AddComponent<TestAgent>(); | |||
TestAgent agent2 = agentGO2.GetComponent<TestAgent>(); | |||
GameObject acaGO = new GameObject("TestAcademy"); | |||
acaGO.AddComponent<TestAcademy>(); | |||
TestAcademy aca = acaGO.GetComponent<TestAcademy>(); | |||
TestBrain brain = TestBrain.Instantiate(); | |||
MethodInfo AgentEnableMethod = typeof(Agent).GetMethod( | |||
"OnEnableHelper", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyInitializeMethod = typeof(Academy).GetMethod( | |||
"InitializeEnvironment", BindingFlags.Instance | BindingFlags.NonPublic); | |||
MethodInfo AcademyStepMethod = typeof(Academy).GetMethod( | |||
"EnvironmentStep", BindingFlags.Instance | BindingFlags.NonPublic); | |||
agent1.agentParameters = new AgentParameters(); | |||
agent2.agentParameters = new AgentParameters(); | |||
brain.brainParameters = new BrainParameters(); | |||
// We use event based so the agent will now try to send anything to the brain | |||
agent1.agentParameters.onDemandDecision = false; | |||
agent1.agentParameters.numberOfActionsBetweenDecisions = 3; | |||
// agent1 will take an action at every step and request a decision every 2 steps | |||
agent2.agentParameters.onDemandDecision = true; | |||
// agent2 will request decisions only when RequestDecision is called | |||
agent1.agentParameters.maxStep = 20; | |||
brain.brainParameters.vectorObservationSize = 0; | |||
brain.brainParameters.cameraResolutions = new Resolution[0]; | |||
agent1.GiveBrain(brain); | |||
agent2.GiveBrain(brain); | |||
AgentEnableMethod.Invoke(agent2, new object[] { aca }); | |||
AcademyInitializeMethod.Invoke(aca, new object[] { }); | |||
AgentEnableMethod.Invoke(agent1, new object[] { aca }); | |||
int j = 0; | |||
for (int i = 0; i < 500; i++) | |||
{ | |||
agent2.RequestAction(); | |||
Assert.LessOrEqual(Mathf.Abs(j * 0.1f + j * 10f - agent1.GetCumulativeReward()), 0.05f); | |||
Assert.LessOrEqual(Mathf.Abs(i * 0.1f - agent2.GetCumulativeReward()), 0.05f); | |||
AcademyStepMethod.Invoke((object)aca, new object[] { }); | |||
agent1.AddReward(10f); | |||
if ((i % 21 == 0) && (i > 0)) | |||
{ | |||
j = 0; | |||
} | |||
j++; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 3170fcbfa5f4d4a8ca82c50c750e9083 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,224 @@ | |||
using System; | |||
using NUnit.Framework; | |||
using UnityEngine; | |||
using MLAgents.InferenceBrain; | |||
using MLAgents.InferenceBrain.Utils; | |||
namespace MLAgents.Tests | |||
{ | |||
public class MultinomialTest | |||
{ | |||
[Test] | |||
public void TestEvalP() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
Data = new float[1, 3] {{0.1f, 0.2f, 0.7f}}, | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
Data = new float[1, 3], | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
m.Eval(src, dst); | |||
float[] reference = {2, 2, 1}; | |||
int i = 0; | |||
foreach (var f in dst.Data) | |||
{ | |||
Assert.AreEqual(reference[i], f); | |||
++i; | |||
} | |||
} | |||
[Test] | |||
public void TestEvalLogits() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
Data = new float[1, 3] {{Mathf.Log(0.1f) - 50, Mathf.Log(0.2f) - 50, Mathf.Log(0.7f) - 50}}, | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
Data = new float[1, 3], | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
m.Eval(src, dst); | |||
float[] reference = {2, 2, 2}; | |||
int i = 0; | |||
foreach (var f in dst.Data) | |||
{ | |||
Assert.AreEqual(reference[i], f); | |||
++i; | |||
} | |||
} | |||
[Test] | |||
public void TestEvalBatching() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
Data = new float[2, 3] | |||
{ | |||
{Mathf.Log(0.1f) - 50, Mathf.Log(0.2f) - 50, Mathf.Log(0.7f) - 50}, | |||
{Mathf.Log(0.3f) - 25, Mathf.Log(0.4f) - 25, Mathf.Log(0.3f) - 25}, | |||
}, | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
Data = new float[2, 3], | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
m.Eval(src, dst); | |||
float[] reference = {2, 2, 2, 0, 1, 0}; | |||
int i = 0; | |||
foreach (var f in dst.Data) | |||
{ | |||
Assert.AreEqual(reference[i], f); | |||
++i; | |||
} | |||
} | |||
[Test] | |||
public void TestSrcInt() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.Integer | |||
}; | |||
Assert.Throws<NotImplementedException>(() => m.Eval(src, null)); | |||
} | |||
[Test] | |||
public void TestDstInt() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.Integer | |||
}; | |||
Assert.Throws<ArgumentException>(() => m.Eval(src, dst)); | |||
} | |||
[Test] | |||
public void TestSrcDataNull() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Assert.Throws<ArgumentNullException>(() => m.Eval(src, dst)); | |||
} | |||
[Test] | |||
public void TestDstDataNull() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[1] | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Assert.Throws<ArgumentNullException>(() => m.Eval(src, dst)); | |||
} | |||
[Test] | |||
public void TestSrcWrongShape() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[1] | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[1] | |||
}; | |||
Assert.Throws<ArgumentException>(() => m.Eval(src, dst)); | |||
} | |||
[Test] | |||
public void TestDstWrongShape() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[1, 1] | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[1] | |||
}; | |||
Assert.Throws<ArgumentException>(() => m.Eval(src, dst)); | |||
} | |||
[Test] | |||
public void TestUnequalBatchSize() | |||
{ | |||
Multinomial m = new Multinomial(2018); | |||
Tensor src = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[1, 1] | |||
}; | |||
Tensor dst = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = new float[2, 1] | |||
}; | |||
Assert.Throws<ArgumentException>(() => m.Eval(src, dst)); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 668f4ac2d83814df5a8883722633e4e5 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,122 @@ | |||
using System; | |||
using NUnit.Framework; | |||
using MLAgents.InferenceBrain; | |||
using MLAgents.InferenceBrain.Utils; | |||
namespace MLAgents.Tests | |||
{ | |||
public class RandomNormalTest | |||
{ | |||
[Test] | |||
public void RandomNormalTestTwoDouble() | |||
{ | |||
RandomNormal rn = new RandomNormal(2018); | |||
Assert.AreEqual(-0.46666, rn.NextDouble(), 0.0001); | |||
Assert.AreEqual(-0.37989, rn.NextDouble(), 0.0001); | |||
} | |||
[Test] | |||
public void RandomNormalTestWithMean() | |||
{ | |||
RandomNormal rn = new RandomNormal(2018, 5.0f); | |||
Assert.AreEqual(4.53333, rn.NextDouble(), 0.0001); | |||
Assert.AreEqual(4.6201, rn.NextDouble(), 0.0001); | |||
} | |||
[Test] | |||
public void RandomNormalTestWithStddev() | |||
{ | |||
RandomNormal rn = new RandomNormal(2018, 1.0f, 4.2f); | |||
Assert.AreEqual(-0.9599, rn.NextDouble(), 0.0001); | |||
Assert.AreEqual(-0.5955, rn.NextDouble(), 0.0001); | |||
} | |||
[Test] | |||
public void RandomNormalTestWithMeanStddev() | |||
{ | |||
RandomNormal rn = new RandomNormal(2018, -3.2f, 2.2f); | |||
Assert.AreEqual(-4.2266, rn.NextDouble(), 0.0001); | |||
Assert.AreEqual(-4.0357, rn.NextDouble(), 0.0001); | |||
} | |||
[Test] | |||
public void RandomNormalTestTensorInt() | |||
{ | |||
RandomNormal rn = new RandomNormal(1982); | |||
Tensor t = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.Integer | |||
}; | |||
Assert.Throws<NotImplementedException>(() => rn.FillTensor(t)); | |||
} | |||
[Test] | |||
public void RandomNormalTestDataNull() | |||
{ | |||
RandomNormal rn = new RandomNormal(1982); | |||
Tensor t = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint | |||
}; | |||
Assert.Throws<ArgumentNullException>(() => rn.FillTensor(t)); | |||
} | |||
[Test] | |||
public void RandomNormalTestTensor() | |||
{ | |||
RandomNormal rn = new RandomNormal(1982); | |||
Tensor t = new Tensor | |||
{ | |||
ValueType = Tensor.TensorType.FloatingPoint, | |||
Data = Array.CreateInstance(typeof(float), new long[3] {3, 4, 2}) | |||
}; | |||
rn.FillTensor(t); | |||
float[] reference = new float[] | |||
{ | |||
-0.2139822f, | |||
0.5051259f, | |||
-0.5640336f, | |||
-0.3357787f, | |||
-0.2055894f, | |||
-0.09432302f, | |||
-0.01419199f, | |||
0.53621f, | |||
-0.5507085f, | |||
-0.2651141f, | |||
0.09315512f, | |||
-0.04918706f, | |||
-0.179625f, | |||
0.2280539f, | |||
0.1883962f, | |||
0.4047216f, | |||
0.1704049f, | |||
0.5050544f, | |||
-0.3365685f, | |||
0.3542781f, | |||
0.5951571f, | |||
0.03460682f, | |||
-0.5537263f, | |||
-0.4378373f, | |||
}; | |||
int i = 0; | |||
foreach (float f in t.Data) | |||
{ | |||
Assert.AreEqual(f, reference[i], 0.0001); | |||
++i; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 518c8e6e10fd94059a064ffbe65557af | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,24 @@ | |||
using NUnit.Framework; | |||
using UnityEngine; | |||
namespace MLAgents.Tests | |||
{ | |||
public class UtilitiesTests | |||
{ | |||
[Test] | |||
public void TestCumSum() | |||
{ | |||
var output = Utilities.CumSum(new int[]{1, 2, 3, 10}); | |||
CollectionAssert.AreEqual(output, new int[] {0, 1, 3, 6, 16}); | |||
output = Utilities.CumSum(new int[0]); | |||
CollectionAssert.AreEqual(output, new int[]{0}); | |||
output = Utilities.CumSum(new int[]{100}); | |||
CollectionAssert.AreEqual(output, new int[]{0, 100}); | |||
output = Utilities.CumSum(new int[]{-1, 10}); | |||
CollectionAssert.AreEqual(output, new int[]{0, -1, 9}); | |||
} | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
fileFormatVersion: 2 | |||
guid: 45ab7fc6851444d8ba622b4f63b8290b | |||
timeCreated: 1538775063 |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 6584f096f53dc43eeb32803b91f36c5c | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: f8097eaa1623c4a8ab4eff559e20fedb | |||
folderAsset: yes | |||
timeCreated: 1504127718 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 70626ce713f4a428e9b72ab06365ec0d | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,23 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!114 &11400000 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_GameObject: {fileID: 0} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 8b23992c8eb17439887f5e944bf04a40, type: 3} | |||
m_Name: 3DBallHardLearning | |||
m_EditorClassIdentifier: | |||
brainParameters: | |||
vectorObservationSize: 5 | |||
numStackedVectorObservations: 9 | |||
vectorActionSize: 02000000 | |||
cameraResolutions: [] | |||
vectorActionDescriptions: | |||
- | |||
- | |||
vectorActionSpaceType: 1 | |||
model: {fileID: 11400000, guid: 8be33caeca04d43498913448b5364f2b, type: 3} |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 4f74e089fbb75455ebf6f0495e30be6e | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 11400000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,31 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!114 &11400000 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_GameObject: {fileID: 0} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 41e9bda8f3cf1492fa74926a530f6f70, type: 3} | |||
m_Name: 3DBallHardPlayer | |||
m_EditorClassIdentifier: | |||
brainParameters: | |||
vectorObservationSize: 5 | |||
numStackedVectorObservations: 9 | |||
vectorActionSize: 02000000 | |||
cameraResolutions: [] | |||
vectorActionDescriptions: | |||
- | |||
- | |||
vectorActionSpaceType: 1 | |||
keyContinuousPlayerActions: [] | |||
axisContinuousPlayerActions: | |||
- axis: Horizontal | |||
index: 0 | |||
scale: -1 | |||
- axis: Vertical | |||
index: 1 | |||
scale: 1 | |||
discretePlayerActions: [] |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 55f48be32ac184c6ab67cf647100bac4 | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 11400000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,26 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!114 &11400000 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_GameObject: {fileID: 0} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 943466ab374444748a364f9d6c3e2fe2, type: 3} | |||
m_Name: 3DBallHeuristic | |||
m_EditorClassIdentifier: | |||
brainParameters: | |||
vectorObservationSize: 8 | |||
numStackedVectorObservations: 1 | |||
vectorActionSize: 02000000 | |||
cameraResolutions: [] | |||
vectorActionDescriptions: | |||
- | |||
- | |||
vectorActionSpaceType: 1 | |||
isExternal: 0 | |||
decision: {fileID: 0} | |||
decisionScript: {fileID: 11500000, guid: 67264e06e07fb40d8939b0860ebee773, type: 3} | |||
c_decision: RandomDecision |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 3a0cd58e7f0764eea8952cb416295fd0 | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 11400000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,23 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!114 &11400000 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_GameObject: {fileID: 0} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 8b23992c8eb17439887f5e944bf04a40, type: 3} | |||
m_Name: 3DBallLearning | |||
m_EditorClassIdentifier: | |||
brainParameters: | |||
vectorObservationSize: 8 | |||
numStackedVectorObservations: 1 | |||
vectorActionSize: 02000000 | |||
cameraResolutions: [] | |||
vectorActionDescriptions: | |||
- | |||
- | |||
vectorActionSpaceType: 1 | |||
model: {fileID: 11400000, guid: c282d4bbc4c8f4e78b2bb29eccd17557, type: 3} |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 383c589e8bb76464eadc2525b5b0f2c1 | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 11400000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,44 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!114 &11400000 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_GameObject: {fileID: 0} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 41e9bda8f3cf1492fa74926a530f6f70, type: 3} | |||
m_Name: 3DBallPlayer | |||
m_EditorClassIdentifier: | |||
brainParameters: | |||
vectorObservationSize: 8 | |||
numStackedVectorObservations: 1 | |||
vectorActionSize: 02000000 | |||
cameraResolutions: [] | |||
vectorActionDescriptions: | |||
- | |||
- | |||
vectorActionSpaceType: 1 | |||
isExternal: 0 | |||
keyContinuousPlayerActions: [] | |||
axisContinuousPlayerActions: | |||
- axis: Horizontal | |||
index: 0 | |||
scale: 1 | |||
- axis: Vertical | |||
index: 1 | |||
scale: 1 | |||
discretePlayerActions: | |||
- key: 12 | |||
branchIndex: 4 | |||
value: 0 | |||
- key: 0 | |||
branchIndex: 4 | |||
value: 0 | |||
- key: 0 | |||
branchIndex: 0 | |||
value: 0 | |||
- key: 0 | |||
branchIndex: 0 | |||
value: 0 |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 97d8f9d40dc8c452f932f7caa9549c7d | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 11400000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: f480b7a50f9974756b821ca885514018 | |||
folderAsset: yes | |||
timeCreated: 1497125575 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: c1d20401220d74fef901ca46558766ea | |||
folderAsset: yes | |||
timeCreated: 1501267188 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,77 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: logo1 | |||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} | |||
m_ShaderKeywords: _ALPHAPREMULTIPLY_ON | |||
m_LightmapFlags: 4 | |||
m_EnableInstancingVariants: 0 | |||
m_DoubleSidedGI: 0 | |||
m_CustomRenderQueue: 3000 | |||
stringTagMap: | |||
RenderType: Transparent | |||
disabledShaderPasses: [] | |||
m_SavedProperties: | |||
serializedVersion: 3 | |||
m_TexEnvs: | |||
- _BumpMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailAlbedoMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailMask: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailNormalMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _EmissionMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _MainTex: | |||
m_Texture: {fileID: 2800000, guid: 0d342588c0383439e92173c7356b6e4c, type: 3} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _MetallicGlossMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _OcclusionMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _ParallaxMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
- _BumpScale: 1 | |||
- _Cutoff: 0.5 | |||
- _DetailNormalMapScale: 1 | |||
- _DstBlend: 10 | |||
- _GlossMapScale: 1 | |||
- _Glossiness: 1 | |||
- _GlossyReflections: 1 | |||
- _Metallic: 0 | |||
- _Mode: 3 | |||
- _OcclusionStrength: 1 | |||
- _Parallax: 0.02 | |||
- _SmoothnessTextureChannel: 0 | |||
- _SpecularHighlights: 1 | |||
- _SrcBlend: 1 | |||
- _UVSec: 0 | |||
- _ZWrite: 0 | |||
m_Colors: | |||
- _Color: {r: 1, g: 1, b: 1, a: 1} | |||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1} |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: e35c6159207d7448e988c8cf0c137ab6 | |||
timeCreated: 1501267793 | |||
licenseType: Pro | |||
NativeFormatImporter: | |||
mainObjectFileID: 2100000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,76 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: logo2 | |||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} | |||
m_ShaderKeywords: | |||
m_LightmapFlags: 4 | |||
m_EnableInstancingVariants: 0 | |||
m_DoubleSidedGI: 0 | |||
m_CustomRenderQueue: -1 | |||
stringTagMap: {} | |||
disabledShaderPasses: [] | |||
m_SavedProperties: | |||
serializedVersion: 3 | |||
m_TexEnvs: | |||
- _BumpMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailAlbedoMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailMask: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailNormalMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _EmissionMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _MainTex: | |||
m_Texture: {fileID: 2800000, guid: 0d342588c0383439e92173c7356b6e4c, type: 3} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _MetallicGlossMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _OcclusionMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _ParallaxMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
- _BumpScale: 1 | |||
- _Cutoff: 0.5 | |||
- _DetailNormalMapScale: 1 | |||
- _DstBlend: 0 | |||
- _GlossMapScale: 1 | |||
- _Glossiness: 0.5 | |||
- _GlossyReflections: 1 | |||
- _Metallic: 0 | |||
- _Mode: 0 | |||
- _OcclusionStrength: 1 | |||
- _Parallax: 0.02 | |||
- _SmoothnessTextureChannel: 0 | |||
- _SpecularHighlights: 1 | |||
- _SrcBlend: 1 | |||
- _UVSec: 0 | |||
- _ZWrite: 1 | |||
m_Colors: | |||
- _Color: {r: 1, g: 1, b: 1, a: 1} | |||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1} |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 4efff3f0f46984b78ae6161ef6558291 | |||
timeCreated: 1501706173 | |||
licenseType: Free | |||
NativeFormatImporter: | |||
mainObjectFileID: 2100000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,83 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: Text | |||
m_Shader: {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} | |||
m_ShaderKeywords: | |||
m_LightmapFlags: 4 | |||
m_EnableInstancingVariants: 0 | |||
m_DoubleSidedGI: 0 | |||
m_CustomRenderQueue: -1 | |||
stringTagMap: {} | |||
disabledShaderPasses: [] | |||
m_SavedProperties: | |||
serializedVersion: 3 | |||
m_TexEnvs: | |||
- _BumpMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailAlbedoMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailMask: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _DetailNormalMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _EmissionMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _MainTex: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _MetallicGlossMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _OcclusionMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- _ParallaxMap: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
- _BumpScale: 1 | |||
- _ColorMask: 15 | |||
- _Cutoff: 0.5 | |||
- _DetailNormalMapScale: 1 | |||
- _DstBlend: 0 | |||
- _GlossMapScale: 1 | |||
- _Glossiness: 0.5 | |||
- _GlossyReflections: 1 | |||
- _Metallic: 0 | |||
- _Mode: 0 | |||
- _OcclusionStrength: 1 | |||
- _Parallax: 0.02 | |||
- _SmoothnessTextureChannel: 0 | |||
- _SpecularHighlights: 1 | |||
- _SrcBlend: 1 | |||
- _Stencil: 0 | |||
- _StencilComp: 8 | |||
- _StencilOp: 0 | |||
- _StencilReadMask: 255 | |||
- _StencilWriteMask: 255 | |||
- _UVSec: 0 | |||
- _UseUIAlphaClip: 0 | |||
- _ZWrite: 1 | |||
m_Colors: | |||
- _Color: {r: 1, g: 1, b: 1, a: 1} | |||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1} |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 58e2b2715aaee4686a912897f823f8f5 | |||
timeCreated: 1501268164 | |||
licenseType: Pro | |||
NativeFormatImporter: | |||
mainObjectFileID: 2100000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,90 @@ | |||
fileFormatVersion: 2 | |||
guid: 0d342588c0383439e92173c7356b6e4c | |||
timeCreated: 1501268935 | |||
licenseType: Pro | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 4 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 1 | |||
sRGBTexture: 1 | |||
linearTexture: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapsPreserveCoverage: 0 | |||
alphaTestReferenceValue: 0.5 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: 0.25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 6 | |||
cubemapConvolution: 0 | |||
seamlessCubemap: 0 | |||
textureFormat: 1 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
serializedVersion: 2 | |||
filterMode: -1 | |||
aniso: -1 | |||
mipBias: -1 | |||
wrapU: 0 | |||
wrapV: 0 | |||
wrapW: 0 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
compressionQuality: 50 | |||
spriteMode: 1 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: 0.5, y: 0.5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaUsage: 1 | |||
alphaIsTransparency: 1 | |||
spriteTessellationDetail: -1 | |||
textureType: 0 | |||
textureShape: 1 | |||
maxTextureSizeSet: 0 | |||
compressionQualitySet: 0 | |||
textureFormatSet: 0 | |||
platformSettings: | |||
- buildTarget: DefaultTexturePlatform | |||
maxTextureSize: 2048 | |||
textureFormat: -1 | |||
textureCompression: 1 | |||
compressionQuality: 50 | |||
crunchedCompression: 0 | |||
allowsAlphaSplitting: 0 | |||
overridden: 0 | |||
- buildTarget: Standalone | |||
maxTextureSize: 2048 | |||
textureFormat: -1 | |||
textureCompression: 1 | |||
compressionQuality: 50 | |||
crunchedCompression: 0 | |||
allowsAlphaSplitting: 0 | |||
overridden: 0 | |||
- buildTarget: WebGL | |||
maxTextureSize: 2048 | |||
textureFormat: -1 | |||
textureCompression: 1 | |||
compressionQuality: 50 | |||
crunchedCompression: 0 | |||
allowsAlphaSplitting: 0 | |||
overridden: 0 | |||
spriteSheet: | |||
serializedVersion: 2 | |||
sprites: [] | |||
outline: [] | |||
physicsShape: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 7f76e451b3030e54eac0f7c5488d22e9 | |||
folderAsset: yes | |||
timeCreated: 1506066534 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,334 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!1001 &100100000 | |||
Prefab: | |||
m_ObjectHideFlags: 1 | |||
serializedVersion: 2 | |||
m_Modification: | |||
m_TransformParent: {fileID: 0} | |||
m_Modifications: [] | |||
m_RemovedComponents: [] | |||
m_ParentPrefab: {fileID: 0} | |||
m_RootGameObject: {fileID: 1665577603478558} | |||
m_IsPrefabParent: 1 | |||
--- !u!1 &1536511242562482 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4095153324598508} | |||
- component: {fileID: 33624138613246242} | |||
- component: {fileID: 135537954369514846} | |||
- component: {fileID: 23926879167055144} | |||
- component: {fileID: 54606488393645454} | |||
m_Layer: 0 | |||
m_Name: Ball | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!1 &1665577603478558 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4162486845013972} | |||
m_Layer: 0 | |||
m_Name: Game | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!1 &1796982831911906 | |||
GameObject: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4426913383042176} | |||
- component: {fileID: 33771194379694972} | |||
- component: {fileID: 64845544452232838} | |||
- component: {fileID: 23074177913792258} | |||
m_Layer: 0 | |||
m_Name: Plane (1) | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!1 &1914042422505674 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4014323973652284} | |||
- component: {fileID: 33653230733766482} | |||
- component: {fileID: 65551894134645910} | |||
- component: {fileID: 23487775825466554} | |||
- component: {fileID: 114980646877373948} | |||
m_Layer: 0 | |||
m_Name: Platform | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!4 &4014323973652284 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1914042422505674} | |||
m_LocalRotation: {x: -0.069583125, y: 0.0049145464, z: 0.0702813, w: 0.99508524} | |||
m_LocalPosition: {x: 0, y: 2.22, z: -5} | |||
m_LocalScale: {x: 5, y: 0.19999997, z: 5} | |||
m_Children: | |||
- {fileID: 4426913383042176} | |||
m_Father: {fileID: 4162486845013972} | |||
m_RootOrder: 0 | |||
m_LocalEulerAnglesHint: {x: -8, y: 0, z: 8.08} | |||
--- !u!4 &4095153324598508 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1536511242562482} | |||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} | |||
m_LocalPosition: {x: 0, y: 6.2200003, z: -5} | |||
m_LocalScale: {x: 1, y: 1, z: 1} | |||
m_Children: [] | |||
m_Father: {fileID: 4162486845013972} | |||
m_RootOrder: 1 | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
--- !u!4 &4162486845013972 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1665577603478558} | |||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |||
m_LocalPosition: {x: -10.3, y: 9, z: 5} | |||
m_LocalScale: {x: 1, y: 1, z: 1} | |||
m_Children: | |||
- {fileID: 4014323973652284} | |||
- {fileID: 4095153324598508} | |||
m_Father: {fileID: 0} | |||
m_RootOrder: 0 | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
--- !u!4 &4426913383042176 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1796982831911906} | |||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |||
m_LocalPosition: {x: 0, y: 0.51, z: 0} | |||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} | |||
m_Children: [] | |||
m_Father: {fileID: 4014323973652284} | |||
m_RootOrder: 0 | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
--- !u!23 &23074177913792258 | |||
MeshRenderer: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1796982831911906} | |||
m_Enabled: 1 | |||
m_CastShadows: 0 | |||
m_ReceiveShadows: 0 | |||
m_DynamicOccludee: 1 | |||
m_MotionVectors: 1 | |||
m_LightProbeUsage: 1 | |||
m_ReflectionProbeUsage: 1 | |||
m_Materials: | |||
- {fileID: 2100000, guid: e35c6159207d7448e988c8cf0c137ab6, type: 2} | |||
m_StaticBatchInfo: | |||
firstSubMesh: 0 | |||
subMeshCount: 0 | |||
m_StaticBatchRoot: {fileID: 0} | |||
m_ProbeAnchor: {fileID: 0} | |||
m_LightProbeVolumeOverride: {fileID: 0} | |||
m_ScaleInLightmap: 1 | |||
m_PreserveUVs: 1 | |||
m_IgnoreNormalsForChartDetection: 0 | |||
m_ImportantGI: 0 | |||
m_StitchLightmapSeams: 0 | |||
m_SelectedEditorRenderState: 3 | |||
m_MinimumChartSize: 4 | |||
m_AutoUVMaxDistance: 0.5 | |||
m_AutoUVMaxAngle: 89 | |||
m_LightmapParameters: {fileID: 0} | |||
m_SortingLayerID: 0 | |||
m_SortingLayer: 0 | |||
m_SortingOrder: 0 | |||
--- !u!23 &23487775825466554 | |||
MeshRenderer: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1914042422505674} | |||
m_Enabled: 1 | |||
m_CastShadows: 1 | |||
m_ReceiveShadows: 1 | |||
m_DynamicOccludee: 1 | |||
m_MotionVectors: 1 | |||
m_LightProbeUsage: 1 | |||
m_ReflectionProbeUsage: 1 | |||
m_Materials: | |||
- {fileID: 2100000, guid: 00d852aac9443402984416f9dbcd22ea, type: 2} | |||
m_StaticBatchInfo: | |||
firstSubMesh: 0 | |||
subMeshCount: 0 | |||
m_StaticBatchRoot: {fileID: 0} | |||
m_ProbeAnchor: {fileID: 0} | |||
m_LightProbeVolumeOverride: {fileID: 0} | |||
m_ScaleInLightmap: 1 | |||
m_PreserveUVs: 1 | |||
m_IgnoreNormalsForChartDetection: 0 | |||
m_ImportantGI: 0 | |||
m_StitchLightmapSeams: 0 | |||
m_SelectedEditorRenderState: 3 | |||
m_MinimumChartSize: 4 | |||
m_AutoUVMaxDistance: 0.5 | |||
m_AutoUVMaxAngle: 89 | |||
m_LightmapParameters: {fileID: 0} | |||
m_SortingLayerID: 0 | |||
m_SortingLayer: 0 | |||
m_SortingOrder: 0 | |||
--- !u!23 &23926879167055144 | |||
MeshRenderer: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1536511242562482} | |||
m_Enabled: 1 | |||
m_CastShadows: 1 | |||
m_ReceiveShadows: 1 | |||
m_DynamicOccludee: 1 | |||
m_MotionVectors: 1 | |||
m_LightProbeUsage: 1 | |||
m_ReflectionProbeUsage: 1 | |||
m_Materials: | |||
- {fileID: 2100000, guid: edd958d75ed1448138de86f3335ea4fa, type: 2} | |||
m_StaticBatchInfo: | |||
firstSubMesh: 0 | |||
subMeshCount: 0 | |||
m_StaticBatchRoot: {fileID: 0} | |||
m_ProbeAnchor: {fileID: 0} | |||
m_LightProbeVolumeOverride: {fileID: 0} | |||
m_ScaleInLightmap: 1 | |||
m_PreserveUVs: 1 | |||
m_IgnoreNormalsForChartDetection: 0 | |||
m_ImportantGI: 0 | |||
m_StitchLightmapSeams: 0 | |||
m_SelectedEditorRenderState: 3 | |||
m_MinimumChartSize: 4 | |||
m_AutoUVMaxDistance: 0.5 | |||
m_AutoUVMaxAngle: 89 | |||
m_LightmapParameters: {fileID: 0} | |||
m_SortingLayerID: 0 | |||
m_SortingLayer: 0 | |||
m_SortingOrder: 0 | |||
--- !u!33 &33624138613246242 | |||
MeshFilter: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1536511242562482} | |||
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!33 &33653230733766482 | |||
MeshFilter: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1914042422505674} | |||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!33 &33771194379694972 | |||
MeshFilter: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1796982831911906} | |||
m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!54 &54606488393645454 | |||
Rigidbody: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1536511242562482} | |||
serializedVersion: 2 | |||
m_Mass: 1 | |||
m_Drag: 0 | |||
m_AngularDrag: 0.01 | |||
m_UseGravity: 1 | |||
m_IsKinematic: 0 | |||
m_Interpolate: 0 | |||
m_Constraints: 0 | |||
m_CollisionDetection: 0 | |||
--- !u!64 &64845544452232838 | |||
MeshCollider: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1796982831911906} | |||
m_Material: {fileID: 0} | |||
m_IsTrigger: 0 | |||
m_Enabled: 0 | |||
serializedVersion: 3 | |||
m_Convex: 0 | |||
m_CookingOptions: 14 | |||
m_SkinWidth: 0.01 | |||
m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!65 &65551894134645910 | |||
BoxCollider: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1914042422505674} | |||
m_Material: {fileID: 0} | |||
m_IsTrigger: 0 | |||
m_Enabled: 1 | |||
serializedVersion: 2 | |||
m_Size: {x: 1, y: 1, z: 1} | |||
m_Center: {x: 0, y: 0, z: 0} | |||
--- !u!114 &114980646877373948 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1914042422505674} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: aaba48bf82bee4751aa7b89569e57f73, type: 3} | |||
m_Name: | |||
m_EditorClassIdentifier: | |||
brain: {fileID: 11400000, guid: 383c589e8bb76464eadc2525b5b0f2c1, type: 2} | |||
agentParameters: | |||
agentCameras: [] | |||
maxStep: 5000 | |||
resetOnDone: 1 | |||
onDemandDecision: 0 | |||
numberOfActionsBetweenDecisions: 5 | |||
ball: {fileID: 1536511242562482} | |||
--- !u!135 &135537954369514846 | |||
SphereCollider: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1536511242562482} | |||
m_Material: {fileID: 13400000, guid: 56162663048874fd4b10e065f9cf78b7, type: 2} | |||
m_IsTrigger: 0 | |||
m_Enabled: 1 | |||
serializedVersion: 2 | |||
m_Radius: 0.5 | |||
m_Center: {x: 0, y: 0, z: 0} |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: ff026d63a00abdc48ad6ddcff89aba04 | |||
timeCreated: 1506066551 | |||
licenseType: Free | |||
NativeFormatImporter: | |||
mainObjectFileID: 100100000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,334 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!1001 &100100000 | |||
Prefab: | |||
m_ObjectHideFlags: 1 | |||
serializedVersion: 2 | |||
m_Modification: | |||
m_TransformParent: {fileID: 0} | |||
m_Modifications: [] | |||
m_RemovedComponents: [] | |||
m_ParentPrefab: {fileID: 0} | |||
m_RootGameObject: {fileID: 1236545525418104} | |||
m_IsPrefabParent: 1 | |||
--- !u!1 &1236545525418104 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4128795324062154} | |||
m_Layer: 0 | |||
m_Name: GameHard | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!1 &1334091176806954 | |||
GameObject: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4891208142487102} | |||
- component: {fileID: 33018876700343880} | |||
- component: {fileID: 64837101465786842} | |||
- component: {fileID: 23262352428609250} | |||
m_Layer: 0 | |||
m_Name: Plane (1) | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!1 &1836508099280124 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4261594809067724} | |||
- component: {fileID: 33000258395075262} | |||
- component: {fileID: 65716795579935884} | |||
- component: {fileID: 23004681142288168} | |||
- component: {fileID: 114716278740392856} | |||
m_Layer: 0 | |||
m_Name: Platform | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!1 &1943673078433006 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 5 | |||
m_Component: | |||
- component: {fileID: 4898959047766504} | |||
- component: {fileID: 33853974925079708} | |||
- component: {fileID: 135765715237510820} | |||
- component: {fileID: 23914679743685510} | |||
- component: {fileID: 54430881130472984} | |||
m_Layer: 0 | |||
m_Name: Ball | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!4 &4128795324062154 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1236545525418104} | |||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |||
m_LocalPosition: {x: -9, y: -2, z: 5} | |||
m_LocalScale: {x: 1, y: 1, z: 1} | |||
m_Children: | |||
- {fileID: 4261594809067724} | |||
- {fileID: 4898959047766504} | |||
m_Father: {fileID: 0} | |||
m_RootOrder: 0 | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
--- !u!4 &4261594809067724 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1836508099280124} | |||
m_LocalRotation: {x: -0.069583125, y: 0.0049145464, z: 0.0702813, w: 0.99508524} | |||
m_LocalPosition: {x: 0, y: 2.22, z: -5} | |||
m_LocalScale: {x: 5, y: 0.19999997, z: 5} | |||
m_Children: | |||
- {fileID: 4891208142487102} | |||
m_Father: {fileID: 4128795324062154} | |||
m_RootOrder: 0 | |||
m_LocalEulerAnglesHint: {x: -8, y: 0, z: 8.08} | |||
--- !u!4 &4891208142487102 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1334091176806954} | |||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |||
m_LocalPosition: {x: 0, y: 0.51, z: 0} | |||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} | |||
m_Children: [] | |||
m_Father: {fileID: 4261594809067724} | |||
m_RootOrder: 0 | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
--- !u!4 &4898959047766504 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1943673078433006} | |||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} | |||
m_LocalPosition: {x: 0, y: 6.2200003, z: -5} | |||
m_LocalScale: {x: 1, y: 1, z: 1} | |||
m_Children: [] | |||
m_Father: {fileID: 4128795324062154} | |||
m_RootOrder: 1 | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
--- !u!23 &23004681142288168 | |||
MeshRenderer: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1836508099280124} | |||
m_Enabled: 1 | |||
m_CastShadows: 1 | |||
m_ReceiveShadows: 1 | |||
m_DynamicOccludee: 1 | |||
m_MotionVectors: 1 | |||
m_LightProbeUsage: 1 | |||
m_ReflectionProbeUsage: 1 | |||
m_Materials: | |||
- {fileID: 2100000, guid: 776dd8b57653342839c3fb5f46ce664e, type: 2} | |||
m_StaticBatchInfo: | |||
firstSubMesh: 0 | |||
subMeshCount: 0 | |||
m_StaticBatchRoot: {fileID: 0} | |||
m_ProbeAnchor: {fileID: 0} | |||
m_LightProbeVolumeOverride: {fileID: 0} | |||
m_ScaleInLightmap: 1 | |||
m_PreserveUVs: 1 | |||
m_IgnoreNormalsForChartDetection: 0 | |||
m_ImportantGI: 0 | |||
m_StitchLightmapSeams: 0 | |||
m_SelectedEditorRenderState: 3 | |||
m_MinimumChartSize: 4 | |||
m_AutoUVMaxDistance: 0.5 | |||
m_AutoUVMaxAngle: 89 | |||
m_LightmapParameters: {fileID: 0} | |||
m_SortingLayerID: 0 | |||
m_SortingLayer: 0 | |||
m_SortingOrder: 0 | |||
--- !u!23 &23262352428609250 | |||
MeshRenderer: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1334091176806954} | |||
m_Enabled: 1 | |||
m_CastShadows: 0 | |||
m_ReceiveShadows: 0 | |||
m_DynamicOccludee: 1 | |||
m_MotionVectors: 1 | |||
m_LightProbeUsage: 1 | |||
m_ReflectionProbeUsage: 1 | |||
m_Materials: | |||
- {fileID: 2100000, guid: e35c6159207d7448e988c8cf0c137ab6, type: 2} | |||
m_StaticBatchInfo: | |||
firstSubMesh: 0 | |||
subMeshCount: 0 | |||
m_StaticBatchRoot: {fileID: 0} | |||
m_ProbeAnchor: {fileID: 0} | |||
m_LightProbeVolumeOverride: {fileID: 0} | |||
m_ScaleInLightmap: 1 | |||
m_PreserveUVs: 1 | |||
m_IgnoreNormalsForChartDetection: 0 | |||
m_ImportantGI: 0 | |||
m_StitchLightmapSeams: 0 | |||
m_SelectedEditorRenderState: 3 | |||
m_MinimumChartSize: 4 | |||
m_AutoUVMaxDistance: 0.5 | |||
m_AutoUVMaxAngle: 89 | |||
m_LightmapParameters: {fileID: 0} | |||
m_SortingLayerID: 0 | |||
m_SortingLayer: 0 | |||
m_SortingOrder: 0 | |||
--- !u!23 &23914679743685510 | |||
MeshRenderer: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1943673078433006} | |||
m_Enabled: 1 | |||
m_CastShadows: 1 | |||
m_ReceiveShadows: 1 | |||
m_DynamicOccludee: 1 | |||
m_MotionVectors: 1 | |||
m_LightProbeUsage: 1 | |||
m_ReflectionProbeUsage: 1 | |||
m_Materials: | |||
- {fileID: 2100000, guid: edd958d75ed1448138de86f3335ea4fa, type: 2} | |||
m_StaticBatchInfo: | |||
firstSubMesh: 0 | |||
subMeshCount: 0 | |||
m_StaticBatchRoot: {fileID: 0} | |||
m_ProbeAnchor: {fileID: 0} | |||
m_LightProbeVolumeOverride: {fileID: 0} | |||
m_ScaleInLightmap: 1 | |||
m_PreserveUVs: 1 | |||
m_IgnoreNormalsForChartDetection: 0 | |||
m_ImportantGI: 0 | |||
m_StitchLightmapSeams: 0 | |||
m_SelectedEditorRenderState: 3 | |||
m_MinimumChartSize: 4 | |||
m_AutoUVMaxDistance: 0.5 | |||
m_AutoUVMaxAngle: 89 | |||
m_LightmapParameters: {fileID: 0} | |||
m_SortingLayerID: 0 | |||
m_SortingLayer: 0 | |||
m_SortingOrder: 0 | |||
--- !u!33 &33000258395075262 | |||
MeshFilter: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1836508099280124} | |||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!33 &33018876700343880 | |||
MeshFilter: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1334091176806954} | |||
m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!33 &33853974925079708 | |||
MeshFilter: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1943673078433006} | |||
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!54 &54430881130472984 | |||
Rigidbody: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1943673078433006} | |||
serializedVersion: 2 | |||
m_Mass: 1 | |||
m_Drag: 0 | |||
m_AngularDrag: 0.01 | |||
m_UseGravity: 1 | |||
m_IsKinematic: 0 | |||
m_Interpolate: 0 | |||
m_Constraints: 0 | |||
m_CollisionDetection: 0 | |||
--- !u!64 &64837101465786842 | |||
MeshCollider: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1334091176806954} | |||
m_Material: {fileID: 0} | |||
m_IsTrigger: 0 | |||
m_Enabled: 0 | |||
serializedVersion: 3 | |||
m_Convex: 0 | |||
m_CookingOptions: 14 | |||
m_SkinWidth: 0.01 | |||
m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} | |||
--- !u!65 &65716795579935884 | |||
BoxCollider: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1836508099280124} | |||
m_Material: {fileID: 0} | |||
m_IsTrigger: 0 | |||
m_Enabled: 1 | |||
serializedVersion: 2 | |||
m_Size: {x: 1, y: 1, z: 1} | |||
m_Center: {x: 0, y: 0, z: 0} | |||
--- !u!114 &114716278740392856 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1836508099280124} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: edf26e11cf4ed42eaa3ffb7b91bb4676, type: 3} | |||
m_Name: | |||
m_EditorClassIdentifier: | |||
brain: {fileID: 11400000, guid: 4f74e089fbb75455ebf6f0495e30be6e, type: 2} | |||
agentParameters: | |||
agentCameras: [] | |||
maxStep: 5000 | |||
resetOnDone: 1 | |||
onDemandDecision: 0 | |||
numberOfActionsBetweenDecisions: 5 | |||
ball: {fileID: 1943673078433006} | |||
--- !u!135 &135765715237510820 | |||
SphereCollider: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 1943673078433006} | |||
m_Material: {fileID: 13400000, guid: 56162663048874fd4b10e065f9cf78b7, type: 2} | |||
m_IsTrigger: 0 | |||
m_Enabled: 1 | |||
serializedVersion: 2 | |||
m_Radius: 0.5 | |||
m_Center: {x: 0, y: 0, z: 0} |
@@ -0,0 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 50eec9166a3e043dd8102d117835dee6 | |||
timeCreated: 1515351281 | |||
licenseType: Pro | |||
NativeFormatImporter: | |||
externalObjects: {} | |||
mainObjectFileID: 100100000 | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: f4933f3f3e4b741de85835dd811541ff | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 6f62a2ccb3830437ea4e85a617e856b3 | |||
timeCreated: 1513216032 | |||
licenseType: Pro | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 35c41099ceec44889bdbe95ed86c97ac | |||
timeCreated: 1513216032 | |||
licenseType: Pro | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |