-
-
Notifications
You must be signed in to change notification settings - Fork 307
Decoupling Netcoding (Events)
When an RPC is called on a networkObject, it is obvious that the code inside the RPC of the networkObject will be called.
However, if you want to scale the game, or make your project more readable and clean, the logic should not be contained in the networkObject.
For example, if you want to shoot a gun, you invoke SendRpc(RPC_Shoot, Receivers.All)
//RPC for Shooting
public override void Shoot(RpcArgs args)
{
// Shoot Logic here...
// Which means that for every RPC,
// networkObject won't really have a single responsibility
// and end up bloated over time, with an ugly amount of code.
}
However, using the Observer Pattern, we can simply notify other components/scripts, to do the logic instead!
Hence, the project will be scale-able, since the code is properly divided.
And single-responsibility pattern applies, which is always a part of clean code.
Look at it in practice!
public Action ShootEvent;
//RPC for Shooting
public override void Shoot(RpcArgs args)
{
// The subscriber(s) to shootEvent, do the actual logic.
if (ShootEvent != null)
ShootEvent();
}
The other components/scripts, cannot subscribe to the networkObject, since they don't know when it is fully setup and ready. They cannot subscribe on Awake/Start, since it is unknown if NetworkStart() will be done by then.
Forge got that covered though! In every networkObject, there is an Action, called networkStarted
Hence, with other components/scripts, we subscribe to it, so as we are notified when the networkObject is no longer null, and we can now properly subscribe to all its events!
Of course, a reference to it, prior to NetworkStart() is required for this design, usually by simply using the Inspector and dragging a network's object to the objects that will subscribe to it.
You may be confused, so let's see it in action!
public class ExampleNetworkObject: ExampleNetworkObjectBehavior
{
public Action ShootEvent;
//RPC for Shooting
public override void Shoot(RpcArgs args)
{
// The subscriber to shootEvent, does the actual logic.
if (ShootEvent != null)
ShootEvent();
}
}
public class ShootLogic : MonoBehaviour
{
// This is by default referenced, via the Inspector.
public ExampleNetworkObject networkObject;
public void Start()
{
// This ensures that the subscriptions happen AFTER
// the networkObject's NetworkStart()
// which means that it will NOT be null.
// In this way, we ensure the subscriptions will
// never happen on a null object, and actually subscribe.
networkObject.networkStarted += StartSubscriptions();
}
public void NetworkSubscriptions()
{
// When networkObject fires off the ShootEvent
// it will trigger OnShoot automatically
networkObject.ShootEvent += OnShoot;
}
public void OnShoot()
{
// Shoot Logic here...
}
}
So, whenever we invoke SendRPC(RPC_SHOOT, Receivers.All);
, it will always and succesfully call OnShoot()
, and the logic is decoupled clearly. It is also extremely readable for everyone, and in this way, networkObject will never get bloated, since the single-responsibility pattern applies.
And of course, as a reminder, we used the networkStarted
event, to subscribe on the networkObject, when it is initialized and hence not null (subscribing to a null object, will lead to an error)
If you want to pass RpcArgs, instead of just notifying the RPC function happened, with a few small tweaks on the above, it should all work smoothly.
public class ExampleNetworkObject: ExampleNetworkObjectBehavior
{
public Action<RpcArgs> ShootEvent;
//RPC for Shooting
public override void Shoot(RpcArgs args)
{
// The subscriber to shootEvent, does the actual logic.
if (ShootEvent != null)
ShootEvent(args);
}
}
public class ShootLogic : MonoBehaviour
{
//...
public void OnShoot(RpcArgs args)
{
// Shoot Logic here...
}
}
Getting Started
Network Contract Wizard (NCW)
Remote Procedure Calls (RPCs)
Unity Integration
Basic Network Samples
Scene Navigation
Master Server
Netcoding Design Patterns
Troubleshooting
Miscellaneous
-
Connection Cycle Events
-
Rewinding
-
Network Logging
-
Working with Multiple Sockets
-
Modify Master and Standalone servers
-
NAT Hole Punching
-
UDP LAN Discovery
-
Offline Mode
-
Ping Pong
-
Lobby System
-
Upgrading Forge Remastered to Develop branch or different version
-
Forge Networking Classic to Remastered Migration Guide
-
Script to easily use Forge Networking from sources
-
Run Two Unity Instances with Shared Assets for Easiest Dedicated Client Workflow