docs.unity3d.com
    Warning

    Warning: Unity Simulation is deprecated as of December 2023, and is no longer available.

    Publisher/Subscriber convenience classes

    While you can always implement your own classes which leverage our IPublisher and ISubscriber interfaces as described in Communicating with external processes, we've included a few boilerplate classes that should help accelerate the development of simple publisher/subscriber behaviors.

    Using the Communication boilerplate classes

    using UnityEngine;
    
    namespace Unity.Simulation.Foundation
    {
        public abstract class PublisherBehaviour<T> : MonoBehaviour where T : IMessage
        {
            protected IPublisher Publisher { get; set; }
            public bool CanPublish => Connector != null && Publisher != null;
    
            [field: SerializeField]
            public virtual string Topic { get; set; }
    
            protected virtual void Start()
            {
                var connector = ConnectorInjector.FindConnector(this);
                if (connector == null)
                {
                    Debug.LogWarning(
                        $"{name}'s {GetType().Name} couldn't find a valid connector, can't publish to {Topic}");
                    Publisher = null;
                    return;
                }
                Publisher = connector.RegisterPublisher<T>(Topic);
            }
    
            public virtual void Publish(T msg)
            {
                Publisher.Publish(msg);
            }
        }
    
    
    
        public class BoolPublisherExample : PublisherBehaviour<BoolMsg> {}
    
    
    
        public abstract class AutoPublisher<T> : PublisherBehaviour<T> where T : IMessage
        {
            float m_TimeUntilNextPublish = 0f;
    
            [field: SerializeField]
            public float PublishFrequency { get; set; } = 0.01f;
    
            [field: SerializeField]
            public bool PublishInFixedUpdate { get; set; } = false;
    
            float PublishPeriod => 1.0f / PublishFrequency;
    
            protected abstract T CreateMessage();
    
            protected virtual void Update()
            {
                if (PublishInFixedUpdate)
                {
                    return;
                }
                CheckTimeAndMaybePublish();
            }
    
            protected void FixedUpdate()
            {
                if (!PublishInFixedUpdate)
                {
                    return;
                }
                CheckTimeAndMaybePublish();
            }
    
            void CheckTimeAndMaybePublish()
            {
                m_TimeUntilNextPublish -= Time.deltaTime;
                if (m_TimeUntilNextPublish <= 0f)
                {
                    var message = CreateMessage();
                    Publish(message);
                    m_TimeUntilNextPublish += PublishPeriod;
                }
            }
        }
    
    
    
        public abstract class SubscriberBehaviour<T> : MonoBehaviour where T : IMessage
        {
            protected IConnector Connector { get; set; }
            protected abstract System.Action<T> Callback { get; }
    
            [field: SerializeField]
            public virtual string Topic { get; set; }
    
            protected virtual void Start()
            {
                Connector = ConnectorInjector.FindConnector(this);
                if (Connector == null)
                {
                    Debug.LogWarning(
                        $"{name}'s {GetType().Name} couldn't find a valid connector, can't subscribe to {Topic}");
                    return;
                }
                // We wrap the callback here with our own in order to error-check and log before invocation
                Connector.Subscribe<T>(Topic, msg => ReceiveMessage(msg, Callback));
            }
    
            void ReceiveMessage(T msg, System.Action<T> callback)
            {
                if (callback == null)
                {
                    Debug.LogError($"{name} cannot invoke callback for {msg.MessageTypeId.MessageTypeName} because " +
                        $"the callback has been destroyed.");
                    return;
                }
                TimeDebug.StepInEditorLog($"Received: {msg}");
                callback.Invoke(msg);
            }
        }
    }
    

    PublisherBehaviour

    A PublisherBehaviour contains a minimal implementation of the logic needed to Publish a message. Note that it does NOT include logic for determining how to populate a message or when to publish it.

    Specifying Type

    Unity does not allow generically defined MonoBehaviours in Scenes. So, although the entirety of this class's logic is implemented here in its virtual members, for each Message type you wish to publish you must create a new child class for the specific type.

    Example Publisher implementation

    This is all that's required to create a Publisher for a given type. However, note that no logic is implemented in Update. While this class CAN publish bool messages, you would need to either override Update or create another Component to hold the logic for when and what it should publish.

    AutoPublisher

    If you want your Publisher to automatically publish on a fixed frequency, you can inherit from AutoPublisher instead.

    Providing the message

    When using AutoPublisher, you only need to provide the message to be published. This is done by overriding this CreateMessage method with your implementation which populates the fields of the expected message type and returns it.

    SubscriberBehaviours

    Like the PublisherBehaviour, SubscriberBehaviours are the minimum necessary implementation for listening to a Topic and subsequently handling its Message.

    Define the Callback

    SubscriberBehaviours are a little more complicated. You must, at a minimum, provide a Callback to be invoked when the Subscriber receives a Message on its Topic.


    Updated 2022-08-31T23:11:26.000Z


    Copyright © 2023 Unity Technologies
    • Legal
    • Privacy Policy
    • Cookies
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)
    "Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
    Generated by DocFX.