There are a few things to understand when you want to create a cluster application. The root issue is that MiddleVR will run a Unity instance (player) per computer that make up the VR system. This requires multiple levels of synchronization, which we defined in section "Cluster - Concepts" of the user guide.
On each cluster node, the Unity player will be running. This means that all your scripts will still be running on all cluster nodes.
The theory is the following: if your application is deterministic ("whose resulting behavior is entirely determined by its initial state and inputs, and which is not random"), its state at the end of each frame will be the same on all machines.
This means that the initial state and inputs for each frame must be the same on all machines.
- user input: keyboard,mouse,joystick, trackers, GUI inputs,
- network input: you might need to send network data to all cluster clients,
- time input: the elapsed time and time to render each frame (delta time) might be different on each cluster node.
For the parts that have a random component, you will need to synchronise the state manually. For example in Unity, rigid bodies (physicalized objects) don't behave the same on all computers. At the end of the frame, a cube might be at different positions on different cluster nodes. This is why MiddleVR has the VRManagerPostFrame script that will synchronize the state of those objects.
You can first try to use the SimpleCluster option of the VRManager.
This will try to automatically determine which objects need their position/orientation to be synchronized by the VRManagerPostFrame script. For the moment this is all the objects that react to physics, ie objects that have a Rigid Body component and are not Kinematic, and all First Person Controllers.
MiddleVR will automatically add the
script that will synchronize their position/orientation. Note that
this will only work if all your objects are already created and not
dynamically added later on in the application. You might then need to
manually add the
VRClusterObject script. You can also
manually add the MiddleVR/Scripts/Cluster/VRClusterObject.cs script to
the nodes that you want to synchronize.
Note: The Simple Cluster option this will only work if all your objects are already created and not dynamically added later on in the application. For objects dynamically created, make sure to manually add the VRClusterObject script (on all cluster nodes).
If you have a script that gets inputs from the keyboard, the mouse or a joystick, this script will probably only work with the master because no physical key/button from the keyboard/mouse/joystick on the clients is pressed!
This is why you have to get input events (keyboard / mouse / wand / trackers) from MiddleVR. MiddleVR will synchronize the state of all the devices it handles from the master to all clients.
So instead of : Input.GetKeys(...), you need to use: MiddleVR.VRDeviceMgr.IsKeyPressed and other methods to managed the different devices.
See section "Input devices" in the User Guide.
Note: Make sure that your scripts always execute *after* the VRManagerScript.
MiddleVR automatically gets during start-up the seed of Unity for pseudo-random values and synchronizes it across the cluster.
You can safely use the Random functions of Unity after the first call to VRManager.Update on all cluster nodes. The seed being synchronized on all cluster clients, the Random functions will output the same sequences on all of them.
Unity's physics gives random events, so you have to synchronize the position and orientation of those nodes. If you're using the SimpleCluster option from the VRManager, MiddleVR will automatically add the VRClusterObject script to objects that react to physics (i.e. that have a Rigid Body component and are not kinematic).
Note: The Simple Cluster option this will only work if all your objects are already created and not dynamically added later on in the application. You might then need to manually add the VRClusterObject script.
If one of your script uses Unity time (Time.time) for some computation, be aware that this time might not be the same on all cluster nodes. Instead you can use MiddleVR.VRKernel.GetTime() which gives the elapsed time since the server started and is correctly synchronized on the cluster.
The delta time (time since the last frame) is used to get a time-dependent translation/rotation speed. When you create your first 3D application, you will say that you want an object to move 1 meter each frame. If the framerate changes, your object's speed will change.
The issue is that the delta time may be different on all the different computers of the cluster. Not every computer will take the same time to complete the rendering of a frame. So if any of the script of your application is using Unity's delta time (Time.deltaTime), it should instead use the MiddleVR's delta time, which is synchronized among the cluster: MiddleVR.VRKernel.GetDeltaTime();
Unity particle system and tree generator/animations uses random elements that MiddleVR cannot synchronize on the cluster because it doesn't have access to those values. Unity Technologies has developped a solution to overcome this issue. MiddleVR can be used in conjuction with this solution. Contact us for more information.
Skyboxes don't correcly work with asymmetric cameras (stereo cameras or cameras used for head tracking in front of a VR wall), so you should replace them by a big sphere or cube geometry.
Some shaders, like the water shader, don't get along with asymetric cameras. They need to be adapted.
If as a result of your scripts, objects have random positions/orientations, you can apply to them the VRClusterObject which will synchronize their position/orientation at each end of frame.