I have a SyncVar variable of type GameObject. I’d like to write a hook function for that variable which runs callbacks (via a C# event) when the value is updated. Consider this example of a node in a tree structure.
class Node : NetworkBehaviour
{
[SyncVar(hook="ParentHook")]
private GameObject m_parentObj;
// Can't use variable of type "Node",
// because [SyncVar] cannot be applied to component types.
// Hook function: emit ParentChanged event when value changes.
private void ParentHook (GameObject obj)
{
if (obj == m_parentObj)
return;
m_parentObj = obj; // Is this line required?
if (ParentChanged)
ParentChanged();
}
// Access m_parentObj as a Node rather than a GameObject.
public Node Parent {
get {
return m_parentObj != null ? m_parentObj.GetComponent<Node>() : null;
}
}
// Event fired with the parent is changed. Triggered in SyncVar hook.
public event System.Action ParentChanged;
}
After showing this code to some colleagues, I have the following questions:
-
Is it even legal to have a SyncVar of type GameObject?
-
In a SyncVar hook, does the developer need to set the variable to the new value? Is line 13 required?
2.1) If the answer to 2 is “yes”, then is it a bug that SyncVar variables of type GameObject still maintain their original value until the hook function completes? That is to say, on line 14, m_parentObj still has its previous value. All other variable types are updated on assignment.
2.2) If the answer to 2 is “no”, then is the hook called before or after the variable has been set to the new value? I would say that it should be after, since callbacks (e.g. C# events) could be fired from the hook, and those callback functions would expect the new value to be in place.
2.2.1) If hooks are run before the variable is set, and the developer is not expected to set the variable manually, then I cannot run callbacks or emit events from within a SyncVar hook function. That’s fine, as I can remove the hook entirely and add a setter to the “Parent” property on line 19:
// Access m_parentObj as a Node rather than a GameObject.
public Node Parent {
get {
return m_parentObj != null ? m_parentObj.GetComponent<Node>() : null;
}
set {
// 'value' is of type Node. Get the GameObject.
GameObject obj = value != null ? value.gameObject : null;
if (obj == m_parentObj)
return;
m_parentObj = obj;
if (ParentChanged != null)
ParentChanged();
}
}
However, the SyncVar documentation states that:
Would I fall foul of this in the example above? Or does it refer to if the SyncVar variable itself has getter/setter functions?
I’m sure there was more documentation for SyncVar hooks, but it seems to have disappeared recently. There certainly used to be a page definitively listing the permissible SyncVar types, but that has disappeared.