-
Notifications
You must be signed in to change notification settings - Fork 2
Networking
There are multiple concepts used for networking in CyanTriggers and Udon itself. While this area will cover the basics, it is best to also check VRChat’s official documentation on this subject. Link to VRChat’s networking Docs.
In CyanTriggers, every Event has a broadcast type. The default broadcast type is Local, which is not networked to other clients. There are two other broadcast types which are networked:
- Send to All This broadcast type will tell everyone in the instance to execute the actions of this event.
- Send to Owner This broadcast type will tell only the Owner of the object to execute the actions of this event. No one else will execute the actions. Using these networked broadcast types allows for users to coordinate events with other users in the room.
Every GameObject has an owner. By default, the owner of an object will be the master of the instance. For pickups, the owner will be the last person to hold the item. The only other way to change the owner of an object, is to set it in Udon or CyanTriggers using the Networking.SetOwner action. Ownership of a GameObject is only important for networking related items, such as Position sync and Synced Variables. Only the Owner of an object can update the synced position of that object. The owner is also the only player that can modify synced variables and have the value sent to all other players.
Every UdonBehaviour has a Sync Method. The Sync Method affects how the object is treated for networking purposes. Sync Method mainly controls when variables sync data with other clients. If Sync Method None is chosen, then all networking is disabled for the UdonBehaviour. Note that disabling the GameObject or the UdonBehaviour will prevent any synced variables from syncing and it is not recommended. By default CyanTrigger will try to auto set the sync mode, but you can manually select a sync mode if needed.
There are 4 different types of Sync Methods that can be used on a CyanTrigger:
Continuous Sync Method will periodically multiple times per second serialize the synced variables on the UdonBehaviour, even if the values have not changed. You cannot control when this happens. Continuous Sync should only be used when you have fast changing values that need to be updated often. If the UdonBehaviour is on a GameObject that also has the VRCObjectSync component, then it is required to use Continuous Sync. The majority of time it is recommended to use Manual Sync instead of Continuous. Continuous Sync Method cannot be used on GameObjects that contain other UdonBehaviours with Manual Sync.
Manual Sync Method will not do anything until the user calls UdonBehaviour.RequestSerialization. Only then will it serialize variable data and sync the values. Manual Sync Method cannot be used on GameObjects that contain other UdonBehaviours with Continuous Sync or if the GameObject has the VRCObjectSync Component. See VRChat’s documentation for this networking mode.
Manual with auto request is a special version of Manual in that CyanTrigger will automatically determine if RequestSerialization needs to be called. If an event ever sets a synced variable, that event will also call RequestSerialization. This simplifies things for users as they no longer need to call one action. If you want absolute control over when items are synced, it is recommended to use “Manual” instead to ensure timing.
None Sync Method will ensure that the UdonBehaviour does not sync anything. Synced variables and Networked events will be ignored, and everything will be local to the user only. If this is the only UdonBehaviour on the GameObject, then this object will not have ownership either. Sync Method None can be used on GameObjects with other UdonBehaviours with different Sync Methods.
CyanTrigger by default will try to auto determine the Sync Method needed. This will disable the option of selecting the Sync Method and display what it thinks it should be. If the Sync Method selected is not desired, you can uncheck Auto Set Sync Mode and select the one needed. Auto Set Sync Mode will look through all actions and inputs used on the CyanTrigger to help determine the Sync Method. Having synced variables and networked events will ensure that this object is synced. In the case where there are no synced variables or networked events, but ownership is needed, then checking the owner of the GameObject using the “This GameObject” variable will ensure that the CyanTrigger has networking enabled.
CyanTriggers can define synced Global variables. These variables will be saved (serialized) and set to all players in the instance. If you are the owner of an object, before the synced variables are serialized, the PreSerialization event will be called. When serialization has finished, PostSerialization will be called with the results on if everything was successful or if anything failed. On all remote clients, OnDeserialization will be called when new variable data is received. You can use this event to check for variable updates. Note that OnVariableChanged will be called automatically even when a synced variable is changed over the network.
Event Replay is a new method of syncing events for late joiners. On any event with the “Send to All” broadcast, there is an option for what happens with this event when a player joins later. While similar, Event Replay is not the same as SDK2 Buffering. While provided for you to use, Event Replay is less efficient compared to Synced Variables. It is always better to use Synced Variables instead.
None is the same as no Replay. Nothing will be handled for late joiners and only players in the instance will get the event through the “Send to All” broadcast.
Replay Once will save if the event has fired at all, and replay it one time for users who join after. This can be used for one time events, or used to set the state in a multi state system.
Replay Parity will save if the event has fired at all, and replay it one time if it was fired an odd number of times, or replay it two times if it was fired an even number of times. Replay Parity is intended for events that Toggle object states.
Replay All will save if the event has fired at all, and replay it for every time it was fired. Replay All is intended for events where counting is required.
The Clear Replay action will reset all replay data for a given event, as if it has never fired. Using Clear Replay is necessary when you have multiple Events with Replay that modify the same objects or properties.
In this example, there are two events set to Replay Once. Both events will modify the same GameObjects: “Door/Open” and “Door/Closed”. Due to this, we need to ensure that only one of these events will replay for late joiners to keep everything synced. This is where the Clear Replay action comes in. On calling “_Open”, we know that “_Close” should not be called, and the replay data is cleared. On calling “_Close”, we know that “_Open” should not be called, and the replay data is cleared.
CyanTrigger Event Replay is not the same as SDK2 Buffering! While the UI to enable it is similar, most situations will act differently. There are two main areas where Event Replay differs:
Event Replay does not keep the call order for events. In SDK2, order is kept when calling buffered events. With CyanTrigger, Replayed events will always play in the order they were defined in the trigger. When comparing CyanTrigger on different objects, the replay order could change every time.
Order Example in CyanTrigger
Order Example in SDK2 VRC_Trigger
In this example, the CyanTrigger and VRC_Trigger appear to do the same thing. On Interact, call a custom to disable an object, then call a custom to enable the object. In SDK2, the GameObject will always be enabled, as that was the last event to be called. In CyanTrigger with Replay, the GameObject will be enabled for those in the room, but will be disabled for late joiners. This is because late joiners will always replay the “Enable” event first, and then replay the “Disable” event second, leaving the object disabled. This is where the ClearReplay action is used to determine exactly what happens for late joiners.
For Event Replay, the object’s enabled state matters. SDK2 doesn’t care if the object or VRC Trigger is enabled. Buffered events will always execute for late joiners, even when the object is disabled at start. For Replay to work properly both the GameObject and the UdonBehaviour must be enabled at start. If either are disabled at start, then users will not act on replay data until the object is enabled. This means that if a replay event is fired before the object is enabled, users in the instance will fire the event and also replay it when the object is enabled, over-counting it.