using System;
using System.Collections.Generic;
using UnityEngine;
namespace MLAgents
{
///
/// Brain receive data from Agents through calls to SubscribeAgentForDecision. The brain then updates the
/// actions of the agents at each FixedUpdate.
/// The Brain encapsulates the decision making process. Every Agent must be assigned a Brain,
/// but you can use the same Brain with more than one Agent. You can also create several
/// Brains, attach each of the Brain to one or more than one Agent.
/// Brain assets has several important properties that you can set using the Inspector window.
/// These properties must be appropriate for the Agents using the Brain. For example, the
/// Vector Observation Space Size property must match the length of the feature
/// vector created by an Agent exactly.
///
public abstract class Brain : ScriptableObject
{
[SerializeField] public BrainParameters brainParameters;
///
/// List of agents subscribed for decisions.
///
protected List m_Agents = new List(1024);
[NonSerialized]
private bool m_IsInitialized;
///
/// Registers an agent to current batch so it will be processed in DecideAction.
///
///
public void SubscribeAgentForDecision(Agent agent)
{
LazyInitialize();
m_Agents.Add(agent);
}
///
/// If the Brain is not initialized, it subscribes to the Academy's DecideAction Event and
/// calls the Initialize method to be implemented by child classes.
///
protected void LazyInitialize()
{
if (!m_IsInitialized)
{
var academy = FindObjectOfType();
if (academy)
{
m_IsInitialized = true;
academy.BrainDecideAction += BrainDecideAction;
academy.DestroyAction += Shutdown;
Initialize();
}
}
}
///
/// Called by the Academy when it shuts down. This ensures that the Brain cleans up properly
/// after scene changes.
///
private void Shutdown()
{
if (m_IsInitialized)
{
m_Agents.Clear();
m_IsInitialized = false;
}
}
///
/// Calls the DecideAction method that the concrete brain implements.
///
private void BrainDecideAction()
{
DecideAction();
// Clear the agent Decision subscription collection for the next update cycle.
m_Agents.Clear();
}
///
/// Is called only once at the beginning of the training or inference session.
///
protected abstract void Initialize();
///
/// Is called once per Environment Step after the Brain has been initialized.
///
protected abstract void DecideAction();
}
}