Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
4
Question by Steve 9 · Apr 07, 2011 at 07:49 PM · networkrpccommunication

Clearing out buffered RPC calls from old Network.Instantiate() calls?

OK, I know that Network.Instantiate() works using buffered RPC calls; does anyone have a recommended system for getting rid of those buffered calls after they're no longer needed?

The issue, as I'm sure many of you have come across, is that those buffered RPCs can stack up after they're useful. The symptom that brought this to our attention is that, because Network.Destroy() doesn't use buffered RPC calls, new clients get the calls to Instantiate already-destroyed objects and don't get corresponding messages to destroy them. This results in ghost copies of whatever it is you instantiate and destroy.

Now, one solution would be to add a buffered RPC call that destroys the objects. Which would work, but the RPC buffer could get really bloated with unnecessary calls, and we'd need to be careful about initialization--we wouldn't really want clients to load models, animations, etc. for things that don't really exist anymore.

So we're thinking we'd like to use Network.RemoveRPCsInGroup() to get rid of the RPCs (reserving a bunch of communication groups to be claimed by each Network.Instantiate() call). Has anyone tried this, who can share their experiences/pitfalls encountered? The other option I can think of would be to make explicit all of the RPC calls included in Network.Instantiate(), which seems less ideal...

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

6 Replies

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by PrimeDerektive · May 03, 2011 at 06:03 PM

Didn't they fix this in 3.2? What's new in Unity 3.2

Networking: It's now possible to remove Network.Instantiate calls from the RPC buffer by calling Network.RemoveRPCs on the first NetworkView in the instantiated object.

So, right before you destroy your Network.Instantiated object, I imagine you do something like:

Network.RemoveRPCs(objectImDestroying.GetComponent(NetworkView)); 

(I think. If the object has multiple networkViews you might need to use GetComponents and call RemoveRPCs on the first entry in the array it returns).

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Steve 9 · May 03, 2011 at 07:39 PM 0
Share

Hot diggity! That sounds like exactly what I wanted! I will definitely try this...

avatar image Zhapness · May 04, 2011 at 12:49 PM 0
Share

Not working... at least not for me, i used it like this.

@RPC function DestroyBuffered(ObjectToDestroy : GameObject) {
Network.RemoveRPCs(ObjectToDestroy.GetComponent(NetworkView)); Network.Destroy(ObjectToDestroy);
}

avatar image Steve 9 · May 04, 2011 at 03:49 PM 0
Share

It works for me. $$anonymous$$uch better than our convoluted stuff; thanks a ton! Zaphness: I'm sure it needs to be done on the same machine that initiated the instantiation; when you call DestroyBuffered(), do you RPC it to everyone?.

avatar image PrimeDerektive · May 04, 2011 at 04:02 PM 0
Share

Glad to help! That issue was one of my longstanding irks with the built-in networking; I was very pleased when I saw they fixed it.

avatar image Steve 9 · May 04, 2011 at 06:22 PM 0
Share

Whoah, actually I have to add a big caveat: this doesn't look like it works as completely as the gross remove-by-group solution, which causes occasional strangeness if (like us, so far) you don't use the levelPrefix. In most cases, yes, it gets rid of ghost players who disconnected; but this solution leaves some things reappearing in later levels for late joiners. I could be mistaken, but I'm afraid I won't have time to investigate much further for a while...

Show more comments
avatar image
1

Answer by AKAssassin · Apr 18, 2011 at 09:59 PM

You would use RemoveRPCS and give it the Netowork.player that you want to remove the buffered stuff for. So if you know you used Network.Instantiate() or your own instantiate from a specific client that disconnected all you need to do is call RemoveRPCS(Network.player) for which ever network player disconnected and you shouldn't see their buffered RPCs anymore.

This works for me.

In code it would look like this.

function OnPlayerDisconnected(player: NetworkPlayer) {
    //Destroy all the objects currently in the scene created by this player and remove his info from the list
    Network.RemoveRPCs(player);
    Network.DestroyPlayerObjects(player);
}

This should do the trick.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Steve 9 · Apr 19, 2011 at 02:06 PM 0
Share

Thanks! Unfortunately, in our situation this isn't enough for two reasons. First, our server is authoritative for everything (except input, of course); so when players disconnect, we have to recall which server-owned objects were created for that player and net-destroy them as well (switching to a client-authoritative architecture would work for players, but add action-resolution complexity). Second and more importantly, we net-instantiate non-player things; for those, destroying-by-player just wouldn't be possible. Anyway, the destroying-by-group seems to be working for us so far...

avatar image
0

Answer by Zhapness · May 02, 2011 at 11:18 PM

Hi I am a bit new to programming, so can you show or explain how to add the Buffered Network.Destroy RPC Call?

Really need this.

Thanks.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by orakga · May 29, 2011 at 08:54 AM

I'd like to add a note to this thread.

I just spent the whole day struggling with this issue (sidetracked by this issue, rather), because the RemoveRPCs call didn't appear to be working correctly.

What I instead discovered was that when I call an RPC on the SERVER and perform Network.Instantiate, it actually ends up creating a separate instance of a network-instantiated object FROM EACH CONNECTED PLAYER. (I confirmed that there were multiple instances of the same object being instantiated right on top of each other, all with their own unique viewIDs belonging to each player; I confirmed it with their Network.Player as well)

I don't know if this is a bug or intended behavior (I don't see why it should behave this way, TBH), but due to this I was not able to remove the RPC(s) correctly from the buffer for the longest time.

In the end, what I did was:

  • Instead of Network.Instantiating the object from within an RPC on the server,

  • I called Network.Instantiate directly from the server

That did the trick for me. No more duplicate copies of the object, and RemoveRPCs started behaving "correctly" as well.

I guess the point I'm trying to make is, if you are having ghost objects even after RemoveRPC-ing, check to see how many instances are actually spawned before you try Network.Destroy or RemoveRPC. If you have multiple copies, you could be having similar issues of RPC-induced server-side Network.Instantiations actually instantiating on the Client(s) side.

If I'm not making sense, I apologize. I literally spent 8 hours cutting this issue from every angle and am not sure if I'm even thinking straight anymore. ;D-

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Quadgnim · Oct 13, 2012 at 04:26 AM 0
Share

sounds like it was expected behavior if I understand what you did. If you did:

void Somewherincode() { . . networkView.RPC("dosomething", RPC$$anonymous$$ode.All); . . )

void dosomething() { Network.Instantiate(....) }

Then yes, you'll end up having every client run a Network.Instantiate and create the same object on top of itself. This is because Network.Instantiate already does an RPC call to all clients so you're double dipping if you will.

Ins$$anonymous$$d you have two options:

  1. Just call Network.Instantiate and that's it. It'll create one copy on every client and also add the object to the server buffer to create the object on any new clients that join

  2. alternatively use your RPC call, but in the remote function just do an Instantiate without the "Network." in front of it. But if you do it this way you first have to create a viewid and pass it in, so all the remote objects share the same network id, like this:

void Somewherincode() { . . NetworkViewID _nvid = Network.AllocateViewID(); networkView.RPC("dosomething", RPC$$anonymous$$ode.All, _nvid); . . )

void dosomething(NetworkViewID _nvid ) { GameObject _go = Instantiate(....); NetworkView _nv = (NetworkView)_go.GetComponent(typeod(NetworkView)); _nv.viewID = _nvid; }

Note: In my final version I'm using RPC$$anonymous$$ode.All, not a buffered mode. This is my preference so I can control when things are instantiated and destroyed, but you might want to use AllBuffered.

avatar image
0

Answer by jorgenpt · Oct 07, 2012 at 06:15 AM

Like PrimeDerektive says in the "accepted" answer, you should use Network.RemoveRPCs. One subtlety that isn't clear is that the RPCs are buffered on the server, even if you call Network.Instantiate on one of the clients. This means that you should use a method like this:

 [RPC]
 void RemoveBufferedInstantiate (NetworkViewID viewID) {
     if (Network.isServer) {
         Network.RemoveRPCs (viewID);
     } else {
         networkView.RPC ("RemoveBufferedInstantiate", RPCMode.Server, viewID);
     }
 }

With this code, you can call `RemoveBufferedInstantiate (networkView.viewID);` without having to consider if you're on the server or the client.

Your code would then look like:

 RemoveBufferedInstantiate (someObject.networkView.viewID);
 Network.Destroy (someObject);
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Deleting client objects if internet connection was lost... 0 Answers

RPC and inheritance 1 Answer

Send GameObject active in network to all clients 2 Answers

Disconnect a player from a network 1 Answer

Check client RPC and Instantiation calls 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges