-
Notifications
You must be signed in to change notification settings - Fork 20
Actions
The Action
is a Network Synchronizer feature that allow to execute some code in sync, on all the clients.
Usually, this feature is used to perform an action on some in common nodes. Take as an example the Doors in Apex Legends, usually the character can interact with it to open/close the door: this action is performed in sync on all the clients so that many can interact with the door in real time.
However, this functionality is really useful to send information between client and server too: for example to signal health loss, some gameplay event, etc..
To use this feature, the first thing you have to do is register the Action
, using NetworkSync.register_action
:
extends KinematicBody
class_name Door
func _ready():
var can_be_triggered_on_client_side = true
NetworkSync.register_action(self, "door_interact", "door_interact_encoder", can_be_triggered_on_client_side)
func door_interact(force: float):
# Open / Close the door using `force` amount
func door_interact_encoder(encoder: InputNetworkEncoder):
encoder.register_input("force", 0.0, DataBuffer.DATA_TYPE_POSITIVE_UNIT_REAL, DataBuffer.COMPRESSION_LEVEL_3)
The code is simple, let's see what each parameter does:
- The first parameter is the object that owns the action.
- The second parameter is the function executed when the action is triggered.
- The third parameter is the function used to instruct the NetSync about how to encode the parameters in a really compact buffer (to optimize the bandwidth usage).
On client, to trigger this action is enough calling the function NetworkSync.trigger_action_by_name
; which we can put in a function to expose the functionality as an API:
[...]
func interact(force):
NetworkSync.trigger_action_by_name(self, "door_interact", [force])
On client side, it's possible to just call the exposed API the_door.interact()
, to open the door in sync across all the clients.
Sometimes it's desirable to validate an action done by the client to make cheating much complicated: For example, we may want to give some health to the door, so the character can break it. This new damage Action
should be validated before the server send it to all the other clients.
During the Action
registration it's possible to specify the validation function:
func _ready():
var can_be_triggered_on_client_side = true
NetworkSync.register_action(self, "damage", "damage_encoder", can_be_triggered_on_client_side, false, "damage_validate")
func damage(amount):
[...]
func damage_encoder(encoder: InputNetworkEncoder):
[...]
func damage_validate(amount):
var is_valid = is_destructible == false
return is_valid
On the above example, the action is executed right away on the client who triggered the action, even before the server has validated it. That's totally fine, but sometimes it's desirable that even the client who triggered the action waits the server validation.
To do that it's enough pass true
on the 5th parameter of register_action
:
func _ready():
var can_be_triggered_on_client_side = true
var wait_validation = true
NetworkSync.register_action(self, "damage", "damage_encoder", can_be_triggered_on_client_side, wait_validation, "damage_validate")
Note: In case the client that triggered the action, took for granted the server validation, and the server discard the action, that's not a big issue: The server will instruct the client to rewind back and re-sync.
This is less common but nevertheless useful; sometimes you will need that the server triggers an action only on a specific peer. The last parameter of trigger_action_by_name
is an array of recipients peers:
NetworkSync.trigger_action_by_name(self, "notify_health_loss", [new_health], [get_network_master()])
This feature can be used only by the server.
Some specific actions will be triggered by the server; in that case it's really nice to instruct the NetSync about this particular behavior, so it can refuse those actions when triggered by the clients (This is good to make cheating difficult).
func _ready():
var can_be_triggered_on_client_side = false
NetworkSync.register_action(self, "start_match", "start_match_encoder", can_be_triggered_on_client_side)
Community & Support
- Open an issue
- Start a new discussion