Advanced

The Advanced documentation covers more specialized features of GD-Sync that are intended for projects with more complex networking requirements. Here you will find additional APIs, optimization techniques, and advanced systems that give you greater control over how your multiplayer game behaves and performs.

It is recommended to first have a good understanding of the core GD-Sync features before using the advanced functionality described in this section. These features build upon concepts introduced throughout the rest of the documentation and are intended for more advanced use cases.

Remote Exposure Permissions

By default, remotely exposed functions, signals, and variables can be accessed by any connected peer. GD-Sync also provides an optional permission system that allows you to restrict who is allowed to interact with them.

This is useful for securing gameplay logic. For example, a function that starts a match should typically only be callable by the host, while a signal or variable may only be intended to be modified by clients. If a peer without the required permission attempts to perform a remote action, the request is automatically rejected.

Permissions can be specified when exposing a function, signal, or variable. If no permission is provided, the default behavior remains unchanged and any connected peer is allowed to interact with the exposed object.

GDScript
func _ready() -> void:
	GDSync.expose_func(test_function1)
	GDSync.expose_func(test_function2, ENUMS.EXPOSE_PERMISSION.CLIENT)
	GDSync.expose_func(test_function3, ENUMS.EXPOSE_PERMISSION.HOST)

	GDSync.call_func(test_function1)
	GDSync.call_func(test_function2)
	GDSync.call_func(test_function3)

func test_function1() -> void:
	# Can be called by anyone
	pass

func test_function2() -> void:
	# Can only be called by clients
	pass

func test_function3() -> void:
	# Can only be called by the host
	pass

The following permissions are available:

ENUMS.EXPOSE_PERMISSION.ANYONE (Default) - Any connected peer may interact with the exposed function, signal, or variable.

ENUMS.EXPOSE_PERMISSION.CLIENT - Only clients may interact with the exposed function, signal, or variable.

ENUMS.EXPOSE_PERMISSION.HOST - Only the host may interact with the exposed function, signal, or variable.

Area of Interest (AOI)

The Area of Interest (AOI) system limits synchronization to players that are close enough to view an object. Instead of sending every update to every client, the host only sends synchronized state to players that are currently within an object's visibility range. This significantly reduces network traffic in larger worlds while remaining fully automatic for built in synchronization.

AOI revolves around two nodes. InterestViewer represents what a player can see, while InterestObject represents what can be seen. The host continuously compares both nodes and decides which clients should receive updates for every synchronized object.

Area of Interest is completely optional. If an entity does not contain an InterestObject, it behaves exactly like any other synchronized object and its state is sent to every player.

An InterestViewer should be added to every player. It reports the player's position to the host, allowing the host to determine which InterestObjects are currently relevant.

By default the InterestViewer uses the position of its parent, although another Node2D or Node3D can be assigned through the target property if required. The update_rate controls how often the player's position is reported to the host. Increasing this value makes objects appear and disappear more smoothly while slightly increasing bandwidth usage.

InterestViewers also support interest_layers. Layers allow different groups of objects to be filtered independently. A player only receives an InterestObject when both nodes share at least one enabled layer. This is useful for separating interiors, dimensions, teams, spectator objects, or any other gameplay specific grouping.

Every player must own their own InterestViewer. Without ownership, the player's position is never reported to the host and AOI cannot function correctly.

An InterestObject is added to any entity whose synchronized state should only be visible to nearby players. This commonly includes players, NPCs, projectiles, pickups, vehicles, and world objects.

The visibility_radius defines how close a player must be before updates begin. The exit_margin adds a small buffer before a player leaves the object's area of interest, preventing objects from rapidly appearing and disappearing while standing near the edge of the radius.

Like InterestViewer, InterestObject supports interest_layers, allowing objects to belong to one or more visibility groups. The update_rate determines how frequently moving objects update their position on the host.

Objects that never move can enable is_static. Static objects report their position once and no longer perform movement updates, reducing network traffic while still correctly handling players entering and leaving their visibility range.

The host_receives_state property forces synchronized state to continue being sent to the host even when the host is outside the object's visibility range. This is useful when the host performs authoritative gameplay logic, validation, or server side simulation.

The hide_parent_out_of_range option automatically hides the parent node whenever the local player is outside the object's area of interest. When the object becomes relevant again, show_parent_delay briefly delays making it visible so synchronized state has time to arrive first.

InterestObject also provides the client_entered(client_id : int) and client_exited(client_id : int) signals, allowing gameplay or visual effects to react whenever a player enters or leaves the object's visibility range.

To enable AOI, add an InterestViewer and an InterestObject as direct children of the player scene. Other entities, such as enemies, projectiles, pickups, and world objects, usually only require an InterestObject.

Once an InterestObject exists, every built in synchronization node within that entity automatically uses it. PropertySynchronizer, SynchronizedAnimationPlayer, and the other synchronized nodes only send updates to clients that are currently inside the object's area of interest. No additional configuration is required.

Manual synchronization can also make use of AOI through the GDSync.sync_var_relevant(), GDSync.call_func_relevant(), and GDSync.emit_signal_remote_relevant() methods. These behave the same as their standard equivalents, except they only send updates to clients that currently consider the object relevant. If no InterestObject exists, they automatically fall back to a normal broadcast.