| | using System.IO.Abstractions; |
| | using System.Text.RegularExpressions; |
| | using UnityEngine; |
| | using System.IO; |
| | using Unity.MLAgents.Policies; |
| | using UnityEngine.Serialization; |
| |
|
| | namespace Unity.MLAgents.Demonstrations |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | [RequireComponent(typeof(Agent))] |
| | [AddComponentMenu("ML Agents/Demonstration Recorder", (int)MenuGroup.Default)] |
| | public class DemonstrationRecorder : MonoBehaviour |
| | { |
| | |
| | |
| | |
| | [FormerlySerializedAs("record")] |
| | [Tooltip("Whether or not to record demonstrations.")] |
| | public bool Record; |
| |
|
| | |
| | |
| | |
| | |
| | [Tooltip("Number of steps to record. The editor will stop playing when it reaches this threshold. " + |
| | "Set to zero to record indefinitely.")] |
| | public int NumStepsToRecord; |
| |
|
| | |
| | |
| | |
| | |
| | [FormerlySerializedAs("demonstrationName")] |
| | [Tooltip("Base demonstration file name. If multiple files are saved, the additional " + |
| | "filenames will have a unique number appended.")] |
| | public string DemonstrationName; |
| |
|
| | |
| | |
| | |
| | |
| | [FormerlySerializedAs("demonstrationDirectory")] |
| | [Tooltip("Directory to save the demo files. Will default to " + |
| | "{Application.dataPath}/Demonstrations if not specified.")] |
| | public string DemonstrationDirectory; |
| |
|
| | DemonstrationWriter m_DemoWriter; |
| | internal const int MaxNameLength = 16; |
| |
|
| | const string k_ExtensionType = ".demo"; |
| | const string k_DefaultDirectoryName = "Demonstrations"; |
| | IFileSystem m_FileSystem; |
| |
|
| | Agent m_Agent; |
| |
|
| | void OnEnable() |
| | { |
| | m_Agent = GetComponent<Agent>(); |
| | } |
| |
|
| | void Update() |
| | { |
| | if (!Record) |
| | { |
| | return; |
| | } |
| |
|
| | LazyInitialize(); |
| |
|
| | |
| | if (NumStepsToRecord > 0 && m_DemoWriter.NumSteps >= NumStepsToRecord) |
| | { |
| | Application.Quit(0); |
| | #if UNITY_EDITOR |
| | UnityEditor.EditorApplication.isPlaying = false; |
| | #endif |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | internal DemonstrationWriter LazyInitialize(IFileSystem fileSystem = null) |
| | { |
| | if (m_DemoWriter != null) |
| | { |
| | return m_DemoWriter; |
| | } |
| |
|
| | if (m_Agent == null) |
| | { |
| | m_Agent = GetComponent<Agent>(); |
| | } |
| |
|
| | m_FileSystem = fileSystem ?? new FileSystem(); |
| | var behaviorParams = GetComponent<BehaviorParameters>(); |
| | if (string.IsNullOrEmpty(DemonstrationName)) |
| | { |
| | DemonstrationName = behaviorParams.BehaviorName; |
| | } |
| | if (string.IsNullOrEmpty(DemonstrationDirectory)) |
| | { |
| | DemonstrationDirectory = Path.Combine(Application.dataPath, k_DefaultDirectoryName); |
| | } |
| |
|
| | DemonstrationName = SanitizeName(DemonstrationName, MaxNameLength); |
| | var filePath = MakeDemonstrationFilePath(m_FileSystem, DemonstrationDirectory, DemonstrationName); |
| | var stream = m_FileSystem.File.Create(filePath); |
| | m_DemoWriter = new DemonstrationWriter(stream); |
| |
|
| | AddDemonstrationWriterToAgent(m_DemoWriter); |
| |
|
| | return m_DemoWriter; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | internal static string SanitizeName(string demoName, int maxNameLength) |
| | { |
| | var rgx = new Regex("[^a-zA-Z0-9 -]"); |
| | demoName = rgx.Replace(demoName, ""); |
| | |
| | if (demoName.Length > maxNameLength) |
| | { |
| | demoName = demoName.Substring(0, maxNameLength); |
| | } |
| | return demoName; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | internal static string MakeDemonstrationFilePath( |
| | IFileSystem fileSystem, string demonstrationDirectory, string demonstrationName |
| | ) |
| | { |
| | |
| | if (!fileSystem.Directory.Exists(demonstrationDirectory)) |
| | { |
| | fileSystem.Directory.CreateDirectory(demonstrationDirectory); |
| | } |
| |
|
| | var literalName = demonstrationName; |
| | var filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType); |
| | var uniqueNameCounter = 0; |
| | while (fileSystem.File.Exists(filePath)) |
| | { |
| | |
| | |
| | literalName = demonstrationName + "_" + uniqueNameCounter; |
| | filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType); |
| | uniqueNameCounter++; |
| | } |
| |
|
| | return filePath; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | public void Close() |
| | { |
| | if (m_DemoWriter != null) |
| | { |
| | RemoveDemonstrationWriterFromAgent(m_DemoWriter); |
| |
|
| | m_DemoWriter.Close(); |
| | m_DemoWriter = null; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void OnDestroy() |
| | { |
| | Close(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | public void AddDemonstrationWriterToAgent(DemonstrationWriter demoWriter) |
| | { |
| | var behaviorParams = GetComponent<BehaviorParameters>(); |
| | demoWriter.Initialize( |
| | DemonstrationName, |
| | behaviorParams.BrainParameters, |
| | behaviorParams.FullyQualifiedBehaviorName |
| | ); |
| | m_Agent.DemonstrationWriters.Add(demoWriter); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | public void RemoveDemonstrationWriterFromAgent(DemonstrationWriter demoWriter) |
| | { |
| | m_Agent.DemonstrationWriters.Remove(demoWriter); |
| | } |
| | } |
| | } |
| |
|