Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Thursday, June 8, for a Q&A with Unity's Content Pipeline group here on the forum, and on the Unity Discord, and discuss topics around Content Build, Import Workflows, Asset Database, and Addressables!
    Dismiss Notice

How does SetReceivingEnabled work?

Discussion in 'Multiplayer' started by jashan, Jan 18, 2008.

  1. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,304
    In my game, it's possible that a match is taking place for some users, while others are still "waiting in the lobby". Basically the way I handle this is by having the "lobby-people" not loading the level in the load level RPC.

    For the "action in the level", I have reserved an own group. Now I would expect that if I do:

    Code (csharp):
    1.  
    2. foreach (NetworkPlayer player in Network.connections) {
    3.     Network.SetReceivingEnabled(player, theLevelGroup false);
    4. }
    5.  
    Right in the load level RPC (before loading the level) for the "lobby-players", they should not receive any of the RPCs sent to group theLevelGroup. However, on the "lobby-client", I'm getting a lot of errors along the line of:

    and

    I made sure that the RPCs I'm getting those errors for area really in that group that's being ignored.

    What am I doing wrong here? And: How would be the right way to do this?

    Jashan
     
  2. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    277
    I'm guessing the action clients are instantiating new network objects using RPC. These RPCs are blocked on the lobby client side, since they don't receive for that group number (the action group). Since the instantiation never occurred on the lobby client he thus fails to look up the view ID for the new object when a network update arrives. Since the group is checked on a per Network View basis, the lobby client never get the opportunity of checking the group (since the view doesn't exist on his side), he just displays the error message.

    If this is the case, then you should rather use SetSendingEnabled on the server and disable the appropriate group for the lobby clients. That way they won't get these network updates at all.
     
  3. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,304
    Hi Larus,

    thanks for the answer - that confirms that groups are checked after a message has been routed to the network view, which explains the current behavior. So, SetReceivingEnabled sure won't work. Thinking about it, that would be a wasteful approach, anyways...

    Using SetSendingEnabled sounds cool, except for that I can only switch off a group completely that way. By doing that, also my clients that need to receive the messages would be blocked off. So, this would only work for me, if I could specify the NetworkPlayer which is effected by SetSendingEnabled.

    Setup is like this: Clients send server RPC "start the level X for us, please", server sends load level to everyone who is "ready to play" (and not to those, who are not) and starts spawning the relevant object through Network.Instantiate(...). Before starting that, I could either disable receiving the group messages on the client (which I can't really do because groups are a level "below" the NetworkViews which don't exist on the relevant clients), OR tell the server "please do not send to NetworkPlayer a, b, c, d on group G" (but keep on sending to these NetworkPlayers for the other groups, of course).

    Would that currently be possible? Did I miss something? I think that would be needed, wouldn't it?

    I sure need a way for clients to say "I don't want to get this'n'that" - with SendSendingEnabled(NetworkPlayer, Group, enabled), I could do that by doing an RPC from the client to the server telling the server to stop sending messages to "me". Basically, a way to subscribe to groups on a "per player basis".

    Jashan
     
  4. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    277
    Do you mean that at the time the level is loaded, some clients might skip loading the level (server only sends load level command to the ones who are "ready to play")?

    If all clients should be loading the level the case is like the one depicted in the NetworkLevelLoaded script in the network example project. While the do-not-receive clients are busy loading a level you could just disable their network message queue processing by setting Network.isMessageQueueRunning to false. When the client is ready he can enable message processing again. Its also posted here: http://unity3d.com/support/documentation/Components/net-NetworkLevelLoad.html

    If some clients do not load the level and some do you in essence have two "games" (one action, one lobby) running at once. I think this would be hard to achieve elegantly at the moment. You could make sure all clients get RPC instantiations messages so they at least create the network views in question. In their scripts they might disable these object or just hide them in some manner and disable receiving on them (their group). You can network instantiate (RPC) in one group and place the instantiated object in another one. The network instantiated objects will exist on the lobby clients but just be inactive.

    I'll add a feature request for this. Maybe it will be added at some point.
     
  5. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,304
    Exactly - and that's just the beginning: In future versions, there will be different "matches" taking place all at the same time on the same server. For that, I really need a way of grouping the messages - and the current NetworkView.group won't help me with that for the reasons mentioned above.

    Some of these matches will take place in the same "level", for that, the current implementation with groups would be sufficient. However, there will also be matches taking place in different levels simultanuously (there's some tricks involved in that, but it should work very well as long as the server implementation is very efficient).

    In the current version, this would be an option - but in the long run, I'll have multiple levels being played simultanuously on the server. However, the clients will only have one level. Instantiating all the objects on the clients would then probably create quite a mess and waste a lot of bandwidth ;-)

    What I'll try for now is, below an abstract layer, to send the messages directly to the NetworkPlayers instead of using RPCMode.All and RPCMode.Others. I would assume that this comes with a bit of a performance hit, but I need this flexibility.

    That would be really good. By using an abstact layer in between, I will probably be able to convert to the "Unity-style", once "the Unity-style" is available...

    Do you think when implementing that feature, you would use SetSendingEnabled(...), just with another parameter? Or is that too early to make a decision on that? Knowing how this would be designed into the Unity-API would help me design my abstraction... I'd like to do this in a way that once the Unity feature is available, all I need is a global search and replace and then I can drop my workaround...

    Jashan
     
  6. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    277
    Overloading SetSendingEnabled with the extra player parameter is the initial thought, yes. Of course I can't promise anything.
     
  7. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,304
    Hm... I'm having a little problem with implementing this myself: It seems as if I can't send RPCs from the server to the server.

    When I'm using my own network player on the server to send an RPC, I get an error that this player is not connected (which is not quite true, because I am connected). Then, I tried it with RPCMode.Server. Since I am the server, I would assume this should work. Unfortunately, it does not.

    Only when I'm doing RPCMode.All, the server gets the message itself. But that doesn't help me much because I need to send the message specifically to those players registered...

    Now, there's obviously ways to work around this (I could change all RPC-calls from the server to directly call the RPC "in place" as a simple method call), but as what I'm doing right now already IS a workaround, I'd rather not do this... Is there any chance SetSendingEnabled(NetworkPlayer, GroupID, enabled) will make it into 2.0.2?

    Aside of the struggles I'm having right now with sending a message from the server to the server, there's also the issue that with a "home grown filtering system", I can't use Network.Instantiate or State synchronization (the RPCs from "under the hood" will go to everyone ). So, not being able to create a filter and neither being able to create a solid workaround is kind of a show-stopper for me...

    Or am I just missing something obvious?

    Jashan
     
  8. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    277
    A Remote Procedure Call, in theory, can not be directed to oneself, then it's not a remote procedure call but a local one. Why can't you invoke the function locally, it would have exactly the same effect?

    I don't believe so, sorry. It's too late in the cycle.

    Well, you can implement your own filter system, in a way, if it only uses RPCs. Then you can fire them off to individual network players as appropriate. As soon as you are doing state synchronization, however, you cannot direct the traffic yourself, so I guess for you its useless. I am looking into more fine grained control for a future release.

    You can also do the instantiate with one group and send synch info with another, then block that other group with SetReceivingEnabled, but its wastes bandwidth. Might be OK if this condition is only temporary for a short period.

    You might be able to run a tiny lobby server apart from the action server? The lobby server would be a sort of coordinator for telling clients when they should connect to the action server. Those who want to can do it but the others stay put. Of course that would mean the action clients lose contact with the lobby server and this would be a completely different method from the one you want to use. I guess this is the way the usual lobby servers work.
     
  9. Aria-Lliane

    Aria-Lliane

    Joined:
    Feb 9, 2013
    Posts:
    14
    Having the same problem as jashan, I'm very looking forward for the development of this area on Unity, currently, dividing a server's capability's between (number of levels\maps)*(number of each level's instances) is quite an "impossible mission", having several areas\maps\levels separated, all running with players on each is currently a fools errand.

    What unity currently does is expecting everyone(every player+server) to be in the same level at the same time, which is quite unthinkable on any online style game, from Online FPSs(where you can have several matches running) to MMORPGs(where you have from Character creation screens, to dugeons, to pvp areas), even on a simple chat room program there can be private rooms.