using Unity.Barracuda; using System; using UnityEngine; using UnityEngine.Serialization; using Unity.MLAgents.Actuators; using Unity.MLAgents.Sensors.Reflection; namespace Unity.MLAgents.Policies { /// /// Defines what type of behavior the Agent will be using /// [Serializable] public enum BehaviorType { /// /// The Agent will use the remote process for decision making. /// if unavailable, will use inference and if no model is provided, will use /// the heuristic. /// Default, /// /// The Agent will always use its heuristic /// HeuristicOnly, /// /// The Agent will always use inference with the provided /// neural network model. /// InferenceOnly } /// /// Options for controlling how the Agent class is searched for s. /// public enum ObservableAttributeOptions { /// /// All ObservableAttributes on the Agent will be ignored. This is the /// default behavior. If there are no ObservableAttributes on the /// Agent, this will result in the fastest initialization time. /// Ignore, /// /// Only members on the declared class will be examined; members that are /// inherited are ignored. This is a reasonable tradeoff between /// performance and flexibility. /// /// This corresponds to setting the /// [BindingFlags.DeclaredOnly](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=netcore-3.1) /// when examining the fields and properties of the Agent class instance. /// ExcludeInherited, /// /// All members on the class will be examined. This can lead to slower /// startup times. /// ExamineAll } /// /// A component for setting an instance's behavior and /// brain properties. /// /// At runtime, this component generates the agent's policy objects /// according to the settings you specified in the Editor. [AddComponentMenu("ML Agents/Behavior Parameters", (int)MenuGroup.Default)] public class BehaviorParameters : MonoBehaviour { [HideInInspector, SerializeField] BrainParameters m_BrainParameters = new BrainParameters(); public delegate void PolicyUpdated(bool isInHeuristicMode); internal event PolicyUpdated OnPolicyUpdated; /// /// The associated for this behavior. /// public BrainParameters BrainParameters { get { return m_BrainParameters; } internal set { m_BrainParameters = value; } } [HideInInspector, SerializeField] NNModel m_Model; /// /// The neural network model used when in inference mode. /// This should not be set at runtime; use /// to set it instead. /// public NNModel Model { get { return m_Model; } set { m_Model = value; UpdateAgentPolicy(); } } [HideInInspector, SerializeField] InferenceDevice m_InferenceDevice = InferenceDevice.Burst; /// /// How inference is performed for this Agent's model. /// This should not be set at runtime; use /// to set it instead. /// public InferenceDevice InferenceDevice { get { return m_InferenceDevice; } set { m_InferenceDevice = value; UpdateAgentPolicy(); } } [HideInInspector, SerializeField] BehaviorType m_BehaviorType; /// /// The BehaviorType for the Agent. /// public BehaviorType BehaviorType { get { return m_BehaviorType; } set { m_BehaviorType = value; UpdateAgentPolicy(); } } [HideInInspector, SerializeField] string m_BehaviorName = "My Behavior"; /// /// The name of this behavior, which is used as a base name. See /// for the full name. /// This should not be set at runtime; use /// to set it instead. /// public string BehaviorName { get { return m_BehaviorName; } set { m_BehaviorName = value; UpdateAgentPolicy(); } } /// /// The team ID for this behavior. /// [HideInInspector, SerializeField, FormerlySerializedAs("m_TeamID")] public int TeamId; // TODO properties here instead of Agent [FormerlySerializedAs("m_useChildSensors")] [HideInInspector] [SerializeField] [Tooltip("Use all Sensor components attached to child GameObjects of this Agent.")] bool m_UseChildSensors = true; [HideInInspector] [SerializeField] [Tooltip("Use all Actuator components attached to child GameObjects of this Agent.")] bool m_UseChildActuators = true; /// /// Whether or not to use all the sensor components attached to child GameObjects of the agent. /// Note that changing this after the Agent has been initialized will not have any effect. /// public bool UseChildSensors { get { return m_UseChildSensors; } set { m_UseChildSensors = value; } } /// /// Whether or not to use all the actuator components attached to child GameObjects of the agent. /// Note that changing this after the Agent has been initialized will not have any effect. /// public bool UseChildActuators { get { return m_UseChildActuators; } set { m_UseChildActuators = value; } } [HideInInspector, SerializeField] ObservableAttributeOptions m_ObservableAttributeHandling = ObservableAttributeOptions.Ignore; /// /// Determines how the Agent class is searched for s. /// public ObservableAttributeOptions ObservableAttributeHandling { get { return m_ObservableAttributeHandling; } set { m_ObservableAttributeHandling = value; } } /// /// Returns the behavior name, concatenated with any other metadata (i.e. team id). /// public string FullyQualifiedBehaviorName { get { return m_BehaviorName + "?team=" + TeamId; } } void Awake() { OnPolicyUpdated += mode => { }; } internal IPolicy GeneratePolicy(ActionSpec actionSpec, ActuatorManager actuatorManager) { switch (m_BehaviorType) { case BehaviorType.HeuristicOnly: return new HeuristicPolicy(actuatorManager, actionSpec); case BehaviorType.InferenceOnly: { if (m_Model == null) { var behaviorType = BehaviorType.InferenceOnly.ToString(); throw new UnityAgentsException( $"Can't use Behavior Type {behaviorType} without a model. " + "Either assign a model, or change to a different Behavior Type." ); } return new BarracudaPolicy(actionSpec, m_Model, m_InferenceDevice, m_BehaviorName); } case BehaviorType.Default: if (Academy.Instance.IsCommunicatorOn) { return new RemotePolicy(actionSpec, FullyQualifiedBehaviorName); } if (m_Model != null) { return new BarracudaPolicy(actionSpec, m_Model, m_InferenceDevice, m_BehaviorName); } else { return new HeuristicPolicy(actuatorManager, actionSpec); } default: return new HeuristicPolicy(actuatorManager, actionSpec); } } /// /// Query the behavior parameters in order to see if the Agent is running in Heuristic Mode. /// /// true if the Agent is running in Heuristic mode. public bool IsInHeuristicMode() { if (BehaviorType == BehaviorType.HeuristicOnly) { return true; } return BehaviorType == BehaviorType.Default && ReferenceEquals(Model, null) && (!Academy.IsInitialized || Academy.IsInitialized && !Academy.Instance.IsCommunicatorOn); } internal void UpdateAgentPolicy() { var agent = GetComponent(); if (agent == null) { return; } agent.ReloadPolicy(); OnPolicyUpdated?.Invoke(IsInHeuristicMode()); } } }