您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
243 行
7.8 KiB
243 行
7.8 KiB
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
// Class contains all necessary environment parameters
|
|
// to be defined and sent to external agent
|
|
|
|
public enum BrainType
|
|
{
|
|
Player,
|
|
Heuristic,
|
|
External,
|
|
Internal
|
|
}
|
|
|
|
public enum SpaceType
|
|
{
|
|
discrete,
|
|
continuous
|
|
}
|
|
;
|
|
|
|
|
|
|
|
|
|
/** Only need to be modified in the brain's inpector.
|
|
* Defines what is the resolution of the camera
|
|
*/
|
|
[System.Serializable]
|
|
public struct resolution
|
|
{
|
|
public int width;
|
|
/**< \brief The width of the observation in pixels */
|
|
public int height;
|
|
/**< \brief The height of the observation in pixels */
|
|
public bool blackAndWhite;
|
|
/**< \brief If true, the image will be in black and white.
|
|
* If false, it will be in colors RGB */
|
|
}
|
|
|
|
/** Should be modified via the Editor Inspector.
|
|
* Defines brain-specific parameters
|
|
*/
|
|
[System.Serializable]
|
|
public class BrainParameters
|
|
{
|
|
public int vectorObservationSize = 1;
|
|
/**< \brief If continuous : The length of the float vector that represents
|
|
* the state
|
|
* <br> If discrete : The number of possible values the state can take*/
|
|
|
|
[Range(1, 10)]
|
|
public int numStackedVectorObservations = 1;
|
|
|
|
public int vectorActionSize = 1;
|
|
/**< \brief If continuous : The length of the float vector that represents
|
|
* the action
|
|
* <br> If discrete : The number of possible values the action can take*/
|
|
|
|
public resolution[] cameraResolutions;
|
|
/**<\brief The list of observation resolutions for the brain */
|
|
|
|
public string[] vectorActionDescriptions;
|
|
/**< \brief The list of strings describing what the actions correpond to */
|
|
|
|
public SpaceType vectorActionSpaceType = SpaceType.discrete;
|
|
/**< \brief Defines if the action is discrete or continuous */
|
|
|
|
public SpaceType vectorObservationSpaceType = SpaceType.continuous;
|
|
/**< \brief Defines if the state is discrete or continuous */
|
|
}
|
|
|
|
[HelpURL("https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Agents-Editor-Interface.md#brain")]
|
|
/**
|
|
* Contains all high-level Brain logic.
|
|
* Add this component to an empty GameObject in your scene and drag this
|
|
* GameObject into your Academy to make it a child in the hierarchy.
|
|
* Contains a set of CoreBrains, which each correspond to a different method
|
|
* for deciding actions.
|
|
*/
|
|
public class Brain : MonoBehaviour
|
|
{
|
|
private bool isInitialized = false;
|
|
|
|
private Dictionary<Agent, AgentInfo> agentInfos =
|
|
new Dictionary<Agent, AgentInfo>(1024);
|
|
|
|
[Tooltip("Define state, observation, and action spaces for the Brain.")]
|
|
/**< \brief Defines brain specific parameters such as the state size*/
|
|
public BrainParameters brainParameters = new BrainParameters();
|
|
|
|
|
|
/**< \brief Defines what is the type of the brain :
|
|
* External / Internal / Player / Heuristic*/
|
|
[Tooltip("Describes how the Brain will decide actions.")]
|
|
public BrainType brainType;
|
|
|
|
//[HideInInspector]
|
|
///**< \brief Keeps track of the agents which subscribe to this brain*/
|
|
// public Dictionary<int, Agent> agents = new Dictionary<int, Agent>();
|
|
|
|
[SerializeField]
|
|
ScriptableObject[] CoreBrains;
|
|
|
|
/**< \brief Reference to the current CoreBrain used by the brain*/
|
|
public CoreBrain coreBrain;
|
|
|
|
// Ensures the coreBrains are not dupplicated with the brains
|
|
[SerializeField]
|
|
private int instanceID;
|
|
|
|
/// Ensures the brain has an up to date array of coreBrains
|
|
/** Is called when the inspector is modified and into InitializeBrain.
|
|
* If the brain gameObject was just created, it generates a list of
|
|
* coreBrains (one for each brainType) */
|
|
public void UpdateCoreBrains()
|
|
{
|
|
|
|
// If CoreBrains is null, this means the Brain object was just
|
|
// instanciated and we create instances of each CoreBrain
|
|
if (CoreBrains == null)
|
|
{
|
|
int numCoreBrains = System.Enum.GetValues(typeof(BrainType)).Length;
|
|
CoreBrains = new ScriptableObject[numCoreBrains];
|
|
foreach (BrainType bt in System.Enum.GetValues(typeof(BrainType)))
|
|
{
|
|
CoreBrains[(int)bt] =
|
|
ScriptableObject.CreateInstance(
|
|
"CoreBrain" + bt.ToString());
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
foreach (BrainType bt in System.Enum.GetValues(typeof(BrainType)))
|
|
{
|
|
if ((int)bt >= CoreBrains.Length)
|
|
break;
|
|
if (CoreBrains[(int)bt] == null)
|
|
{
|
|
CoreBrains[(int)bt] =
|
|
ScriptableObject.CreateInstance(
|
|
"CoreBrain" + bt.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the length of CoreBrains does not match the number of BrainTypes,
|
|
// we increase the length of CoreBrains
|
|
if (CoreBrains.Length < System.Enum.GetValues(typeof(BrainType)).Length)
|
|
{
|
|
int numCoreBrains = System.Enum.GetValues(typeof(BrainType)).Length;
|
|
ScriptableObject[] new_CoreBrains =
|
|
new ScriptableObject[numCoreBrains];
|
|
foreach (BrainType bt in System.Enum.GetValues(typeof(BrainType)))
|
|
{
|
|
if ((int)bt < CoreBrains.Length)
|
|
{
|
|
new_CoreBrains[(int)bt] = CoreBrains[(int)bt];
|
|
}
|
|
else
|
|
{
|
|
new_CoreBrains[(int)bt] =
|
|
ScriptableObject.CreateInstance(
|
|
"CoreBrain" + bt.ToString());
|
|
}
|
|
}
|
|
CoreBrains = new_CoreBrains;
|
|
}
|
|
|
|
// If the stored instanceID does not match the current instanceID,
|
|
// this means that the Brain GameObject was duplicated, and
|
|
// we need to make a new copy of each CoreBrain
|
|
if (instanceID != gameObject.GetInstanceID())
|
|
{
|
|
foreach (BrainType bt in System.Enum.GetValues(typeof(BrainType)))
|
|
{
|
|
if (CoreBrains[(int)bt] == null)
|
|
{
|
|
CoreBrains[(int)bt] =
|
|
ScriptableObject.CreateInstance(
|
|
"CoreBrain" + bt.ToString());
|
|
}
|
|
else
|
|
{
|
|
CoreBrains[(int)bt] =
|
|
ScriptableObject.Instantiate(CoreBrains[(int)bt]);
|
|
}
|
|
}
|
|
instanceID = gameObject.GetInstanceID();
|
|
}
|
|
|
|
// The coreBrain to display is the one defined in brainType
|
|
coreBrain = (CoreBrain)CoreBrains[(int)brainType];
|
|
|
|
coreBrain.SetBrain(this);
|
|
}
|
|
|
|
/// This is called by the Academy at the start of the environemnt.
|
|
public void InitializeBrain(Academy aca, Communicator communicator)
|
|
{
|
|
UpdateCoreBrains();
|
|
coreBrain.InitializeCoreBrain(communicator);
|
|
aca.BrainDecideAction += DecideAction;
|
|
isInitialized = true;
|
|
}
|
|
|
|
public void SendState(Agent agent, AgentInfo info)
|
|
{
|
|
// If the brain is not active or not properly initialized, an error is
|
|
// thrown.
|
|
if (!gameObject.activeSelf)
|
|
{
|
|
throw new UnityAgentsException(
|
|
string.Format("Agent {0} tried to request an action " +
|
|
"from brain {1} but it is not active.",
|
|
agent.gameObject.name, gameObject.name));
|
|
}
|
|
else if (!isInitialized)
|
|
{
|
|
throw new UnityAgentsException(
|
|
string.Format("Agent {0} tried to request an action " +
|
|
"from brain {1} but it was not initialized.",
|
|
agent.gameObject.name, gameObject.name));
|
|
}
|
|
else
|
|
{
|
|
agentInfos.Add(agent, info);
|
|
}
|
|
|
|
}
|
|
|
|
void DecideAction()
|
|
{
|
|
coreBrain.DecideAction(agentInfos);
|
|
agentInfos.Clear();
|
|
}
|
|
}
|