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