This example showcases the usage of SyncSys add-on to simplify networking of scene spawns/despawns over network.
Even though the example showcases it in 2D this system is general enough and can be used for 3D or even UI too.
Verified to work with Godot 3.1.
Godot's main unit of abstraction is node/scene and high level networking provides great tools for networking some aspects of that abstraction. However in my opinion that's not enough. What's the main pain-point and missing feature I have in high level networking is inability to easily network node spawns/despawns. That's why I created the SyncSys addon as a workaround. Also later an optional replication feature was added.
System consists of the 2 new nodes: SyncRoot
and SyncNode
.
When a SyncNode
is added under a SyncRoot
in hierarchy then (if the SyncRoot
node is a network master) the SyncNode
's direct parent addition/removal will be networked if enabled
is set to true, and replicated if replicated
is set to true.
SyncNode
's parent name
and network master id
is carried over the network properly when spawned.
Clients listen to server or masters. Server automatically relays events from masters to puppets.
System was designed with dedicated servers in mind. Currently server-as-player may not work properly, to be improved in the future.
There can be as many SyncRoot
nodes in a hierarchy as one wishes. It's up to the server/master to manage them. They will co-exist simultaneously just fine. This could be used to achieve streaming different parts of open-world map to different clients without much effort.
addons/sync_sys
folder into the addons
folder of your project.SyncSys
plugin under Project -> Project Settings -> Plugins
.SyncRoot
node, somewhere appropriate in your SceneTree. Usually an AutoLoad works great. Make sure to call sync_client(id)
when new client connects to the server, to update that client with the current state of the world.SyncNode
(or any of it's subclasses) as the direct child of the given scene's root. Tweak the settings to your liking, see API reference for more info.SyncRoot
's node in hierarchy. NOTE: Due to engine's RPC limitations, if you're instantiating the same scene multiple times make sure to explicitly name the instances differently. Or add children with add_child(your_instance_here, true)
, the second argument must be set to true
.sync_client(id)
-- used to sync whole sync root tree state to the clientsync_spawn(node)
-- synchronizes spawn of the given node over network, usually doesn't need to be called directly because SyncNode will do it for us automaticallysync_spawn(node)
-- synchronizes despawn of the given node over network, usually doesn't need to be called directly because SyncNode will do it for us automaticallyclear(free=true)
-- removes and frees all children, if argument free is set the children will also be queued for free upon being removedsignal spawned(data)
-- this signal is called when the initial spawn data is sent, it will awlays get called once on node spawn if node enabled even if replication itself is disabledsignal replicated(data)
-- this signal is called when the new replication data arrives, it's not getting called if the replication for this node is disabledvar enabled : bool
-- if this node is enabled it's spawning and despawning will be synchronized over networkvar replicated : bool
-- whether or not automatic replication is enabledvar force_reliable : bool
-- by default replication (except for spawn/despawn messages) is sent as unreliable, turn this on if you wish for it to be always sent as reliablevar interval : float
-- interval at which replication happens if enabledfuncref validate(old_data, new_data)
-- a FuncRef to custom validation function. It will be called before received replication data is applied to the SyncNode (and later sent out to other nodes, if server). To prevent malicious (hacking/cheating) clients you can correct the values by modifiying values stored inside the new_data
dictionary.var data : Dictionary
-- this dictionary gets sent from master to puppets if replicated is set to truereplicate(reliable=true)
-- this function can be called to replicate the data dictionary over to puppets, will only work on masters. Doesn't usually need to be called directly, it's called automatically under the hood. Although you can call it directly if you've disabled automatic replication and want to control exactly when the replication data is sent out.This node simplifies synchronization of Node2D
nodes over network. It will automatically replicate and apply parent's transform.
It writes/reads it's state to data.transform
be careful not to manipulate it unless you know what you're doing.
var interpolate : bool
-- whether or not received transform should be interpolated (smoothed motion)var lerp_speed : bool
-- how much of interpolation to apply if interpolate
is enabledPretty much the same as SyncTransform2D but works on Spatial
nodes.
This node simplifies synchronization of RigidBody2D
nodes. It will automatically replicate rigidbody state and apply it. This node attempts to extrapolate/dead reckon on missing packets, also allows sleeping puppet bodies to sleep until they recieve a packet with actual movement from the master.
It writes/reads it's state to data.transform
, data.linear_velocity
, data.angular_velocity
be careful not to manipulate it unless you know what you're doing.
var interpolate : bool
-- whether or not received transform should be interpolated (smoothed motion)var lerp_speed : bool
-- how much of interpolation to apply if interpolate
is enabledvar epsilon : bool
-- position/force difference threshold above which body will forcefully woken up (if sleeping) and made to reconcileintegrate_forces(state)
-- due to godot limitations you should call this function in your parent's node _integrate_forces(state)
function, see example here.Pretty much the same as SyncRigidBody2D but works on RigidBody
nodes.
Initial release
Ability for host play added. Server now can spawn objects for himself and sync node emulates replication to itself, so the code stays the same as for remote clients.
Introduction of specific SyncNode subclasses to simplify common replication usecases:
Examples moved to the examples
directory instead of being placed in the project root.
Implemented ability to supply validate
callback to SyncNode. This makes it possible to cope with malicious clients.
Clients now replicate strictly to server. Server replicates to everyone.
Spawning and despawning is now server authoritative, SyncRoot masters no longer honored, only servers.