ColumbiaCGUI / MercuryMessaging

A framework and encompassing toolkit to facilitate nonspatial communication in the Unity game engine.
Other
42 stars 8 forks source link

MercuryMessaging vs traditional event messaging via delegates #3

Open rcoppy opened 3 years ago

rcoppy commented 3 years ago

Hi @celvezio! It's Alex the undergrad; asking this here instead of in an email so it can be archived for reference (if the question ends up being useful).

When first going through the readme for MM I got slightly confused about the need the framework is addressing. (Later on I clicked through to your abstract on ACM and I think I get it now.)

But! Just for my own clarity:

Here's (roughly, this is pseudocode) an example of how past teams I've worked with would have handled event messaging in C#/Unity.

// stateful object in the gameworld
public class Node : Monobehaviour {

    // lifecycle events

    void Awake() {
        // register self to messaging system
        Messenger.DisableAllNodesHandler += OnDisableAllNodes;
        this.SetActive(true);
    }

    void Destroy() {
        // unregister self from messaging system
        Messenger.DisableAllNodesHandler -= OnDisableAllNodes;
    }

    // actual callback

    void OnDisableAllNodes() {
        this.SetActive(false);
    }

}

// 'messaging system' via a delegate
public class Messenger {

    // 'disable nodes' event
    public static delegate void DisableAllNodesHandler();

}

// 'game logic'
public class GameWorld {

    static void Main() {

        // initialize nodes in the scene
        for (var i = 0; i < 20; i++) {
            GameObject.Instantiate(Node);
        }

        // disable nodes in the scene via callback
        Messenger.DisableAllNodesHandler();

    }
}

Is the idea behind this framework to provide a wrapper component to gameobjects that obviates the need to explicitly add and register a callback method? (i.e. void OnDisableNodes)

Aside from the fact that all possible events need to be hardcoded in ahead of time to the Messenger class as delegates, this method has felt fairly flexible to me. (We used it widely, for instance, on Into the Dark: Narakan, a 4-years-in-dev Unity project, without much trouble.)

Looking at the quickstart example boilerplate,

GetComponent<MmRelayNode>().MmInvoke(MmMethod.SetActive, true,
    new MmControlBlock(MmLevelFilterHelper.Default, MmActiveFilter.All,
    default(MmSelectedFilter), MmNetworkFilter.Local));

And having only cursorily looked at the documentation, my sense is:

MmRelayNode is functionally equivalent to Messenger in my example (i.e. it's the actual event handler that observers are subscribing to)... OR I have it backwards and relay nodes are actually attached as components to observers. (But then what are they subscribing to?)

MmMethod.SetActive, true looks a little bit like automagic--SetActive(true) will be invoked on observer instances, but how is MmMethod's SetActive related to Monobehaviour's SetActive? Where is it defined?

MmControlBlock looks like it adds secondary functionality--it enables filtering through and sampling more precisely which observers you want to target with a message broadcast from the subscribed to controller.

Finally, for reference here's a quote from your ACM abstract:

When components need to communicate horizontally, programmers must connect those components manually and register/unregister events as needed. Moreover, events and callback signatures may be incompatible, making modular UIs cumbersome to build and share within or across applications.

The upshot of all this:

MercuryMessaging automates and abstracts out the Awake() and Destroy() portions of my example; and by abstracting the need for hardcoded event handlers/delegates directly addresses the incompatible callback problem. (Do I have that right?)

So, my outstanding question is, is there a catch? (Which to some degree I think you've addressed here.)

But then there's also this asynchronous UNET/networking component I haven't even started looking into yet--Is there possibly a UML diagram somewhere that points out all the relationships between different parts of the framework?

I hope this wasn't too lengthy, thank you for your time!

-Alex