Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Instantiate / Destroy

Discussion in 'Multiplayer' started by JohnGalt, Feb 6, 2008.

  1. JohnGalt

    JohnGalt

    Joined:
    Nov 27, 2007
    Posts:
    85
    It doesn't seem that the next code removes the Network.Instantiate call:

    if (networkView.isMine)
    {
    Network.RemoveRPCs(networkView.viewID);
    Network.Destroy(networkView.viewID);
    }

    It removes all the other RPCs but when I connect with another client, I still see that the object is being created, as result of the Network.Instantiate RPC.

    Is this as expected? can it be a bug? am I missing something!!!

    The documentation for Network.Instantiate explicitly says:

    "Internally this is an RPC call so when Network.RemoveRPCs is called for the group number, the object will be removed."

    But I don't see this behaviour.

    In fact, looking at the log, I see:

    "Added RPC '__RPCNetworkInstantiate' to buffer."

    and after a few lines, when calling to RemoveRPCs:

    "0 RPC function were removed with RemoveRPC"

    how can you get 0 RPC function removed when the object was created with a RPC (Network.Instantiate)?

    I have also tried doing the same thing but in the server,

    if (Network.isServer)
    {
    .... same as above
    }

    but with the same result.


    Is it possible that the difference is in using RemoveRPCs(player) versus using RemoveRPCs(viewID)?

    I can confirm that RemoveRPCs(NetworkPlayer) works ok, here it is the log message:

    RPC __RPCNetworkInstantiate with AllocatedID: 0, player ID 1 and group 0, removed from RPC buffer.
    UnityEngine.Network:RemoveRPCs(NetworkPlayer)


    please help, thank you!
     
  2. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    277
    Network.Instantiate cannot be removed from the RPC buffer based on view IDs. Sorry this isn't clearly mentioned in the docs, I'll look into that. This is because you can do Network.Instantiate anywhere, it doesn't rely on a network view and thus a network view ID. You can remove them from the buffer based on NetworkPlayer (as you found out) or group number.

    The workaround, if you require this functionality, is to do the instantiations manually yourself with RPC functions, see here.
     
  3. JohnGalt

    JohnGalt

    Joined:
    Nov 27, 2007
    Posts:
    85
    Ok, that gives me at least peace of mind!! :)

    I was thinking about the solution of having my missiles created in a special unique group for every player, and destroying the group with RemoveRPCs(player, group).

    But I'll go for the solution of manually creating with my own RPC, it's simpler.

    Thank you indeed!
     
  4. JohnGalt

    JohnGalt

    Joined:
    Nov 27, 2007
    Posts:
    85
    Trying to implement it, I have come to realize that manually creating the RPC is not solution... why? Let me explain.

    I have 10 missiles flying in the air, synchronized in all the computers, all of them created by the same airplane with the manual RPC method. This airplane has of course the same viewID in all the computers. Problem is... If I call RemoveRPC() on the airplane's networkView, I will lost the RPCs for every other missile...

    The more general problem is... How do I create/destroy objects that are temporal in game, so that clients connected after the object destruction dont see its creation.
     
  5. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Ok, what I am doing now is NOT doing a Network.Destroy by itself, but calling an RPC that is ALL.Buffered that calls the Network.Destroy.

    Yes, seems like a silly extra step, but what it does is it buffers the destroy for all future players that connect and the objects that were detsroyed before they connected are then killed off as soon as they connect and the buffer is run through.

    It works really well and is stable... it's a shame for such a silly extra step, but it is small and you just have to change your way of thinking just a little to make sure you implement it this way for all objects that might get destroyed during game play that you need to keep destroyed on new people connecting.
     
  6. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    Personally, I felt that I was creating rather significant buffers when doing my teams management. Originally, I used buffered RPCs for this, but later, I decided to keep the structures on the server, and make sure every client that connects gets exactly the information needed.

    It's a little extra work and book-keeping, but it feels better. Also, I noticed in JCsUMTRaceON with the "buffered teams approach" that it would cause some flickering when people connected and the whole history of team creations, people joining and people leaving was run through. And that even though I deleted the buffers in "idle mode" (i.e. when all players had left the server).

    So, personally, I'm pretty much through with buffered RPCs, even though I think it's really cool to have them and I think there's many cases where they're extremely useful. But I think one really has be aware of what one is doing with them ;-)

    Sunny regards,
    Jashan
     
  7. JohnGalt

    JohnGalt

    Joined:
    Nov 27, 2007
    Posts:
    85
    I don't think that this idea would work for me. In my game 7 players can be firing missiles for 1 hour... If a new player joins after this, he will find that there are thousands of RPCs queues with creation-fly-destroy sequence of missiles that were once created.

    I haven't found a solution yet. I would love that Network.Destroy had an optional parameter telling it to also forget about the Network.Instance RPC.
     
  8. JohnGalt

    JohnGalt

    Joined:
    Nov 27, 2007
    Posts:
    85
    If I understand you correctly you advocate to have every creation and destroy centralized in the server and avoid the RPCs. Maybe... but, except for this little quirk, I found RPCs to be a powerful and extremely productive concept, and I specially love the unity clean implementation.

    Now I'm going for the solution of having every missile in its own Group, and when the missile is done I'll call Network.Destroy(player, group).

    My main concern with this approach is how to make sure that every missile gets its own unique group, how to synchronize it among all the players. I suppose that I'll asign every airplane its own starting index...

    Airplane 1: From 1000-1100
    Airplane 2: From 1100-1200

    and so on...

    My game is 8 players max, so the only real 'problem' is making sure that as the players join they get the right range for their missiles. Easy task with RPCs.

    I think that it's not going to be that difficult after all :)
     
  9. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    No, not avoid RPCs but avoid buffered RPCs. For instance, instead of creating and destroying your missiles via buffered RPCs, you could keep track of which missiles are currently "alive" on the server. Then, when a new player joins in, just send him what's currently happening "on demand", and ideally, only send it, if it's relevant to the player.

    That way, you can avoid buffered RPCs altogether. Quite a bit of the communication will probably still happen via RPCs, but you simply don't need to buffer them anymore, and you don't have to mess with hundreds of groups. Furthermore, it might be that where your new player spawns, there are no relevant missiles. That's also something you might want to take care of on the server.

    Sunny regards,
    Jashan
     
  10. JohnGalt

    JohnGalt

    Joined:
    Nov 27, 2007
    Posts:
    85

    Ok, roger that!!

    My current policy is "every player is responsible for its objects", but it may change if I see that this project gets too messy.

    Anyway, I still have pending the Network.RemoveRPC(player, group) implementation. I'll keep you informed :)
     
  11. ntourte

    ntourte

    Joined:
    Dec 15, 2009
    Posts:
    27
    So I'm playing with this workaround, because being able to control instantiations on the client level is handy (i.e. multiple players in different levels, Network.Instantiate would be silly because they would all spawn as if in the same level), and I use the method of passing around a network view id to identify the instantiated prefab. The prefab has a network view, and it's supposed to pass around the transform deltas... but that doesn't seem to be working. Is there no way to use the automagicness of the deltas without Network.Instantiate, or did I do something wrong?

    ED: figured it out. It does work fine. I was trying to use different prefabs (i.e. a prefab for my player verses a prefab for other players verses a prefab for the server), but that breaks it. You need to use the same uber prefab and disable the stuff you don't need. Blech.

    ED: ED: ok, so I'm confused. If the server is running the movement script on the object, it propagates to the client(s). On the other hand, if the client is running a movement script and anticipating being authoritative on the position itself, it doesn't seem to update anything. I wonder if it has anything to do with ownership? But you can't change who owns the network view... help!
     
  12. Scorch

    Scorch

    Joined:
    Jan 12, 2011
    Posts:
    20
    Its weird that the Unity Network "state machine" does not understand when an object is totally gone, why keep it around at all. If it just did that it seems this would completely solve the problem.
     
  13. zhapness

    zhapness

    Joined:
    Apr 10, 2011
    Posts:
    58
    Hi
    Can you send some code on how to make the function you are talking about, i dont quite understand that part of programming yet.

    Thanks :)
     
  14. Aralox

    Aralox

    Joined:
    May 3, 2006
    Posts:
    12
    Thanks for the suggestion Jashan, seems like a much clearer way to go that dealing with invisible buffers!