- Edited
Hi, I am attempting to make a high performance framework for Godot (C# only)
The end goal is a multithreaded game logic "engine" that uses godot for presentation.
PubSub.cs
My first feature is "done", and I would greatly appreciate feedback regarding usability.
Features
- Thread safe: supports any number of publishers and subscribers
- No allocations: sending/receiving messages doesn't allocate (no GC pressure).
- Pull, not push: Incoming Messages are enqueued for reading during the subscriber's update logic.
- No marshaling: stays in managed code land.
Godot already has this feature! (Signals)
The built-in godot signals
workflow marshals back-and-forth between native and managed code. This PubSub is faster for C# to C# messaging.
Check it out
- You can view the code here: https://github.com/jasonswearingen/godot-csharp-tech/blob/master/lib/PubSub.cs
- A demo project using it is here: https://github.com/jasonswearingen/godot-csharp-tech/tree/master/demo-projects/ball-run
- The "enemy" publishes it's collisions scripts/enemy.cs
- and a child node of the player subscribes to it script/SubExample.cs
This is for CSharp developers: maybe later we could interop this with GDScript but I want to get a solid C# framework firstly.
Example use
Best to look at the code posted in the "check it out", but:
//Publisher:
var channel = pubSub.GetChannel<int>("myKey"); //create/get a channel for sending/receiving messages
channel.Publish(1);
//Subscriber:
var channel = pubSub.GetChannel<int>("myKey"); //create/get a channel for sending/receiving messages
var queue = new ConcurrentQueue<int>(); //create a thread safe queue that messages will be put in.
channel.Subscribe(queue); //now whenever a publish occurs, the queue will get the message
while(queue.TryDequeue(out var message)){ Console.Writeline(message); } //do work with the message
My own "self critique"
The subscriber needs to discover the PubSub Channel's key
and message
type. I don't see an easy solution for this, so in my demo the subscriber reads static values from the publisher's class. This works but is verbose. Probably the workaround is to have a central registry (class) with all standard Channel keys+message types, but it's still pretty not ideal. Ideally, you could subscribe to a channel and consume it's messages without searching for either the key or message type.