Search Unity

Discussion Scriptable Object event system for multiplayer?

Discussion in 'Scripting' started by imaginereadingthis, Mar 10, 2023.

  1. imaginereadingthis

    imaginereadingthis

    Joined:
    Jul 25, 2020
    Posts:
    97
    Hello everyone,

    I was watching this video on how to make a flexible event system using scriptable objects (
    ) and it got me thinking. How would this kind of event system work in a multiplayer game? I really want to use an event-based design pattern to minimize dependencies in my game, but I also don't want to have a situation where players raise each other's events.

    For example, if there would be an event for when the player jumps off the ground and another player is subscribed to the same event, it would quickly turn into a mess. Would that mean we'd have to define events specifically for each player? What if the game had 100+ players? I'm just trying to wrap my head around this. Scriptable objects aside, how would an event-based design pattern even work in multiplayer? I'm still somewhat of a beginner and I haven't looked into Unity's new NetCode system, but I am planning on learning Steam's multiplayer system in the future. Can you guys give me some advice or resources on how to implement such an event system in a multiplayer game?
     
    alishaaalu29 likes this.
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    If every player signaled the same GameEvent, then yes the GameEventListener's out there listening to that GameEvent would receive it regardless of the player in a multiplayer setup.

    With that said, as the person in the video demonstrates, you can set it up where it passes along various information. Specifically a sender (the component) and some data.

    In your code that receives the event you could parse this data to determine who sent it and react accordingly.

    For example every player related event may fire on a Component inside the Player's GameObject. Meaning that the Component passed along as the sender is inside that specific Player's gameobject. If you had a "PlayerEntity" script on the root of the player you could do something like:
    Code (csharp):
    1. var player = sender.GetComponentInParent<PlayerEntity>();
    And now you know which player sent the message.

    Alternatively you could include some information as the 'data' argument that identifies which player sent it.

    ...

    If you wanted to get even more generic so your GameEventListener could call some lego style logic things (like a spawn script, or a play audio script). You could build this filtering logic into the GameEventListener.

    Just add a 3rd argument to the Raise and OnRaiseEvent methods, say maybe a string, and then in GameEventListener add a serialized public string field called 'filter'. Then you do a comparison of the serialized string to the string passed in and if it doesn't match you don't raise the event. Then back in the player where you raise the event from, you pass in some string that identifies the player (or whatever identity you want to give it).

    ...

    This is all on the simpler approach side. You could get way more complex than even this.

    I know the system I use which we call 'ProxyMediator' does basically what is in the video but with some extra bells and whistles and ties into out so-called "T&I system":
    https://github.com/lordofduct/space...cepuppy.triggers/Runtime/src/ProxyMediator.cs

    And I'm pretty sure @Kurt-Dekker has his data-sacks doing this event stuff with more robust aspects too.
     
    Last edited: Mar 10, 2023
  3. imaginereadingthis

    imaginereadingthis

    Joined:
    Jul 25, 2020
    Posts:
    97
    Woah, thank you so much for writing such a detailed response! I haven't even thought of all those things. I'll definitely try all of those methods out and see what works best.
     
    iLollipop likes this.