using System.Collections.Generic; using System; using UnityEngine; namespace Unity.MLAgents.SideChannels { /// /// Side channels provide an alternative mechanism of sending/receiving data from Unity /// to Python that is outside of the traditional machine learning loop. ML-Agents provides /// some specific implementations of side channels, but users can create their own. /// /// To create your own, you'll need to create two, new mirrored classes, one in Unity (by /// extending ) and another in Python by extending a Python class /// also called SideChannel. Then, within your project, use /// and /// to register and unregister your /// custom side channel. /// public abstract class SideChannel { // The list of messages (byte arrays) that need to be sent to Python via the communicator. // Should only ever be read and cleared by a ICommunicator object. internal List MessageQueue = new List(); /// /// An int identifier for the SideChannel. Ensures that there is only ever one side channel /// of each type. Ensure the Unity side channels will be linked to their Python equivalent. /// /// The integer identifier of the SideChannel. public Guid ChannelId { get; protected set; } internal void ProcessMessage(byte[] msg) { try { using (var incomingMsg = new IncomingMessage(msg)) { OnMessageReceived(incomingMsg); } } catch (Exception ex) { // Catch all errors in the sidechannel processing, so that a single // bad SideChannel implementation doesn't take everything down with it. Debug.LogError($"Error processing SideChannel message: {ex}.\nThe message will be skipped."); } } /// /// Is called by the communicator every time a message is received from Python by the SideChannel. /// Can be called multiple times per simulation step if multiple messages were sent. /// /// The incoming message. protected abstract void OnMessageReceived(IncomingMessage msg); /// /// Queues a message to be sent to Python during the next simulation step. /// /// The byte array of data to be sent to Python. protected void QueueMessageToSend(OutgoingMessage msg) { MessageQueue.Add(msg.ToByteArray()); } } }