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());
}
}
}