using System; using UnityEngine; using UnityEngine.Perception.Randomization.Samplers; namespace UnityEngine.Perception.Randomization.Parameters { /// /// Parameters, in conjunction with a parameter configuration, are used to create convenient interfaces for /// randomizing simulations. /// [Serializable] public abstract class Parameter { /// /// Returns the display name of a parameter type /// /// A subclass of Parameter /// The parameter type's display name public static string GetDisplayName(Type type) { return type.Name.Replace("Parameter", ""); } [HideInInspector, SerializeField] internal bool collapsed; /// /// The name of the parameter /// [HideInInspector] public string name = "Parameter"; /// /// The target this parameter apply a sample to /// [HideInInspector, SerializeField] public ParameterTarget target = new ParameterTarget(); /// /// Indicates whether this parameter has a target GameObject /// public bool hasTarget => target.gameObject != null; /// /// The sample type generated by this parameter /// public abstract Type sampleType { get; } /// /// An array containing a reference to each sampler field in this parameter /// public abstract ISampler[] samplers { get; } /// /// Constructs a new parameter /// protected Parameter() { InitializeSamplers(); } /// /// Deterministically ensures that no sampler shares the same seed when a parameter is initialized /// void InitializeSamplers() { var i = 0; foreach (var sampler in samplers) { sampler.Rebase(SamplerUtility.IterateSeed((uint)i++, SamplerUtility.largePrime)); sampler.ResetState(); } } internal void RandomizeSamplers() { foreach (var sampler in samplers) { sampler.Rebase(SamplerUtility.GenerateRandomSeed()); sampler.ResetState(); } } /// /// Resets sampler states and then offsets those states using the current scenario iteration /// /// The current scenario iteration public void ResetState(int scenarioIteration) { foreach (var sampler in samplers) sampler.ResetState(scenarioIteration); } /// /// Applies one sampled value to this parameters assigned target gameobject /// internal abstract void ApplyToTarget(int seedOffset); /// /// Validates parameter settings /// internal virtual void Validate() { if (hasTarget) { if (target.component == null) throw new ParameterValidationException($"Null component target on parameter \"{name}\""); if (string.IsNullOrEmpty(target.propertyName)) throw new ParameterValidationException($"Invalid property target on parameter \"{name}\""); } } } }