OnSerializeNetworkView to only one recipient

Hello everyone !

I am facing a network problem with the legacy network system of Unity (I can’t change my whole network system to Unet unfortunately …)

#Context

I have two clients and one server. On each client, I instantiate an empty considered as a cursor (I allocate dynamically the NetworkViewID using Network.AllocateViewID()). This instantiation is also done on the server (not on other clients) and I send the allocated NetworkViewID to the server at the same time I ask for the instantiation (using a simple RPC). Then, I update the 3D position of the cursor through a NetworkView with a script as observed entity. This script is simply called Cursor. I also send a simple integer.

Only the clients can change the position of their own cursor.

Since I am using state synchronisation with my Network view, I wrote the OnSerializeNetworkView inside my Cursor script :

void OnSerializeNetworkView( BitStream stream, NetworkMessageInfo info )
{
    Vector3 position = Vector3.zero;            
    int index = 0;
            
    if ( stream.isWriting )
    {
        index = particleEffectIndex;
        stream.Serialize( ref index );

        position = Position;
        stream.Serialize( ref position );
    }
    else
    {
        stream.Serialize( ref index );
        if ( index != particleEffectIndex )
        {
            // Do some stuff
            particleEffectIndex = index;
        }

        stream.Serialize( ref position );
        Position = position;
    }
}


#Problem

However, this function serializes the data on all my computers. Since the cursor of a client doesn’t exist on the other client, I get the following error :

View ID AllocatedID: 153 not found during lookup. Strange behaviour may occur
Received state update for view id' AllocatedID: 153' but the NetworkView doesn't exist

#Solutions tried

Since only the client can change the 3D position of the cursor I tried the following :

void OnSerializeNetworkView( BitStream stream, NetworkMessageInfo info )
{
    Vector3 position = Vector3.zero;            
    int index = 0;
            
    if ( stream.isWriting && Network.IsClient)
    {
        // Write data
    }
    else if( Network.IsServer )
    {
        // Read data
    }
}

Though, the position of the cursor isn’t correct. It goes to its correct position and then return back to (0,0,0).

Though, I don’t have the error anymore when I move the cursor on one client.


#Question

Is there any way to prevent the server to send the data to other client / to select the recipient of the OnSerializeNetworkView function ?

I haven’t tested it, but if it’s possible the only way to achieve this in the old network system (RakNet) is to use “network groups” and enable / disable the sending / receiving for a certain “group-player” pair.

You need to set the NetworkView’s group variable for each object to a different value so you can use Network.SetReceivingEnabled and Network.SetSendingEnabled.

You haven’t mentioned it, but did you actually set the NetworkViewID of the objects on both sides(server and client)? Did you allocate them manually with AllocateViewID?

Most of the documentation only mentioned RPC calls in relation with network groups. If this doesn’t work there’s no way to implement this with state synchronisation. In this case you have to use RPCs instead which can be send to specific users.

I finally found a very simple way to do what I want ! :smiley:

In my Cursor script, I added the following code :

void Awake()
{
    // All network messages and RPC calls go through this group number
    networkView.group = 1;

    // Disable transmission of messages and RPC calls on the network group number 1.
    if( Network.isServer )
    {
        Network.SetSendingEnabled( 1, false );
    }
}

Thus, the server won’t relay the data of my cursor from one client to the other. Thanks for your help @Bunny83 !