Configuring properties from code
In netfox, there are multiple nodes that accept property paths as their configuration, for various purposes. These can be configured as lists of strings in the editor.
In bigger projects, with many scenes and deeper class trees, manually configuring property paths may be tedious and unscaleable. Potentially, there may be cases where these properties are only known at runtime, not when working in the Editor.
There are solutions for both cases.
Adding properties from code
Properties can be added at run-time with the following methods:
TickInterpolator::add_property(node, property)
StateSynchronizer::add_state(node, property)
RollbackSynchronizer::add_state(node, property)
RollbackSynchronizer::add_input(node, property)
node is a reference to a node - it may be a string or a NodePath pointing to an existing node, or a Node instance. When using paths, the path itself is considered relative to the configured root node.
After calling any of the methods above, calling process_settings()
is not
necessary - it will be called automatically.
Warning
The same as with process_settings()
, configuration changes are not
synchronized automatically! You, the developer, must ensure that
configuration changes happen on all peers, at the same time.
Adding properties automatically, in the editor
You can ensure that certain properties are added to netfox's nodes'
configuration by making your class a @tool
script, and implementing the
following methods:
- TickInterpolator:
_get_interpolated_properties()
- StateSynchronizer:
_get_synchronized_state_properties()
- RollbackSynchronizer:
_get_rollback_state_properties()
for state_get_rollback_input_properties()
for input
These must return an array, with each element being a string, or a two-element array.
Strings are interpreted as property names.
Arrays are interpreted as node-property pairs. Similarly to the add_*
methods, the node may be a string, a NodePath, or an actual Node
instance. When using strings or NodePaths, keep in mind that the path is
considered relative to the node itself, not the configured root.
Each of these nodes will explore nodes under their root
node, and call the
above methods if implemented. The results will be added to the node
configuration.
This exploration is implemented in the nodes' _get_configuration_warnings()
method, which is called when the node tree changes ( i.e. nodes are added /
removed ), and when opening the scene.
The exploration also runs when before saving the scene, to make sure that any updates are picked up.
Tip
To make sure that the updated methods are picked up, save your scene. The exploration is ran before every scene save.
An example implementation for the above methods:
func _get_interpolated_properties():
# Specify a list of properties
return ["position", "quaternion"]
func _get_synchronized_state_properties() -> Array:
# Specify inherited properties and more
return super() + [
"health", "name",
[weapon, "ammo"], # Specify a property on another node
["Hand/Weapon", "ammo"] # Specify node by path
]
func _get_rollback_state_properties() -> Array:
return [
"transform", # Specify a property on self
[weapon, "ammo"] # Specify a property on another node
]
func _get_rollback_input_propertes() -> Array:
# Specify a list of properties
return ["movement", "is_jumping"]
See the Property configuration example.
Note
In general, it's best practice to only specify node's own properties. An exception is when the given node has no script attached.
Caveats
Node renames and removals are not tracked. Unless fixed manually, they will result in invalid property warnings.
A workaround is to reset the node's state/input/property configuration to an empty array and save again. This will gather the tracked properties with the right node names.