using System; using System.Collections; using UnityEngine; using UnityEngine.Perception.GroundTruth; using UnityEngine.Perception.Randomization.Configuration; using UnityEngine.Perception.Randomization.Parameters; namespace UnityEngine.Perception.Randomization.Scenarios { public abstract class ScenarioBase : MonoBehaviour { static ScenarioBase s_ActiveScenario; [HideInInspector] public bool quitOnComplete = true; [HideInInspector] public bool deserializeOnStart; [HideInInspector] public string serializedConstantsFileName = "constants"; /// /// Returns the active parameter scenario in the scene /// public static ScenarioBase ActiveScenario { get => s_ActiveScenario; private set { if (s_ActiveScenario != null) throw new ScenarioException("There cannot be more than one active ParameterConfiguration"); s_ActiveScenario = value; } } /// /// Returns the file location of the JSON serialized constants /// public string serializedConstantsFilePath => Application.dataPath + "/StreamingAssets/" + serializedConstantsFileName + ".json"; /// /// The number of frames that have elapsed since the current scenario iteration was Setup /// public int currentIterationFrame { get; private set; } /// /// The number of frames that have elapsed since the scenario was initialized /// public int framesSinceInitialization { get; private set; } /// /// The current iteration index of the scenario /// public int currentIteration { get; protected set; } /// /// Returns whether the current scenario iteration has completed /// public abstract bool isIterationComplete { get; } /// /// Returns whether the entire scenario has completed /// public abstract bool isScenarioComplete { get; } /// /// Called before the scenario begins iterating /// public virtual void OnInitialize() { } /// /// Called when each scenario iteration starts /// public virtual void OnIterationSetup() { } /// /// Called at the start of every frame /// public virtual void OnFrameStart() { } /// /// Called right before the scenario iterates /// public virtual void OnIterationTeardown() { } /// /// Called when the scenario has finished iterating /// public virtual void OnComplete() { } /// /// To be overriden in derived Scenario classes /// public abstract string OnSerialize(); /// /// To be overriden in derived Scenario classes /// public abstract void OnDeserialize(string json); /// /// Serializes the scenario's constants to a JSON file located at serializedConstantsFilePath /// public abstract void Serialize(); /// /// Deserializes constants saved in a JSON file located at serializedConstantsFilePath /// public abstract void Deserialize(); void OnEnable() { ActiveScenario = this; if (deserializeOnStart) Deserialize(); } void OnDisable() { s_ActiveScenario = null; } void Start() { foreach (var config in ParameterConfiguration.configurations) config.ValidateParameters(); OnInitialize(); StartCoroutine(UpdateLoop()); } IEnumerator UpdateLoop() { // TODO: remove this yield when the perception camera no longer skips the first frame of the simulation yield return null; while (!isScenarioComplete) { DatasetCapture.StartNewSequence(); foreach (var config in ParameterConfiguration.configurations) config.ResetParameterStates(currentIteration); foreach (var config in ParameterConfiguration.configurations) config.ApplyParameters(currentIteration, ParameterApplicationFrequency.OnIterationSetup); OnIterationSetup(); while (!isIterationComplete) { foreach (var config in ParameterConfiguration.configurations) config.ApplyParameters(framesSinceInitialization, ParameterApplicationFrequency.EveryFrame); OnFrameStart(); yield return null; currentIterationFrame++; framesSinceInitialization++; } OnIterationTeardown(); currentIteration++; currentIterationFrame = 0; } OnComplete(); // Disable perception cameras foreach (var perceptionCamera in FindObjectsOfType()) perceptionCamera.enabled = false; if (quitOnComplete) #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #else Application.Quit(); #endif } } }