How to send variables over network [UdonSharp]

In this small tutorial I will show you how you can send variables over network without using synced variables. This method relies on the fact that you only have a finite amount of possible values that you want to send via an event (e.g. a number ranging from 1-100).

I’ll also point out that this approach is only a workaround until we are able to send variables in Udon directly. It should be considered bad coding practice to do something like this, but there is currently no other way that would not cause timing issues.

This approach here worked for me and I use it for hundreds of possible values in my world without any issues or deathruns. You can find an example from me here: https://github.com/Reimajo/EstrelElevatorEmulator/blob/master/ConvertedForUdon/ElevatorRequester.cs

First of all, we need to define a function to “encode” the variable that we want to send. In my example, I have 3 elevators (from elevator 0 to elevator 2) and 14 floor numbers (from floor 0 to floor 13):

public void RequestElevatorTarget(int elevatorNumber, int floor)

This is the function that each player can later call to request a certain elevator to a certain floor.
Now inside this function, we need to call a network event. In my example, I will send the network event to the master which is controlling the elevator. This means that if localplayer is master, he can directly call the function without sending a network event. Here you also see which function call results from a network event. “SetInternalTarget” is the receiving function that needs both the elevator number and floor number again. But how do we send those two numbers over network?

if (Networking.LocalPlayer.isMaster)
{
     //master doesn't need to send a request over network
     _networkingController.ELREQ_SetInternalTarget(elevatorNumber, floor);
     return;
}

Well, we can encode those values into a function name:

string functionName = $"MOE{elevatorNumber}T{floor}";
Debug.Log($"Sending Network function {functionName} to master");
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, functionName);

This function name will be sent over network. Notice how I keep this function name as short as possible to ensure that network overhead is minimal.
Now all we need is to turn this into a function as follows:

public void RequestElevatorTarget(int elevatorNumber, int floor)
{
    if (Networking.LocalPlayer.isMaster)
    {
        //master doesn't need to send a request over network
        _networkingController.SetInternalTarget(elevatorNumber, floor);
        return;
    }
    string functionName = $"MOE{elevatorNumber}T{floor}";
    Debug.Log($"Sending Network function {functionName} to master");
    SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, functionName);
}

So now that the sending site is set up, we need to define the receiving site. This site needs to be inside the same class and needs to cover each possible value that we may receive. In my example, those are 3 elevators * 14 floors = 42 possible function names.

Because we are programmers and programmers are lazy people, I made a tool, ensuring that we don’t need to write the following code ourselves.


We now need to feed abstract code into this generator.

In this code, we will use placeholders:
#J1# for our elevator number
#1# for our floor number.

Now we need to feed the generator with every possible number.
#1# (our floor number from 0 to 13) will go into “Array 1”.
Notice how there is a number line generator on the top right who will do this for you.
So in this input field is now: 0,1,2,3,4,5,6,7,8,9,10,11,12,13

Now we define all elevators for #J1# as follows: 0,1,2
Then we put this abstract code into the input field:

public void MOE#J1#T#1#()
{
   _networkingController.SetInternalTarget(#J1#, #1#);
}

This is how the generator looks like now:


When you hit “Start horrible conversion for Udon”, you will then receive the generated code for the receiving site. Simply copy this code into your class now and you are done! Notice how this was already a more complicated example. In most cases, you only need to define #1# since you are only sending one variable instead of two. The converter also allows you to go even further if you want. I hope this helped you!

Again, here is how your whole class can look like now:

2 Likes