- Home /
How to properly destroy non-instantiated objects over a network?
After more than a week testing and retesting many different ways to do this and examining every post I can find here and elsewhere, I am starting to think this is not even possible via any means within unity. This not so much a code question but a concept clarification as I really just don't get Unity's take on networking.
Is there a way to destroy an object which was in the scene when the game was started - non-Network.Instantiate'd - and have it permanently removed from the scene so that it does not reappear for players joining later. Surely there is some way the server can do this. I have tried sending messages and RPCs in every possible combination I can think of but I just can't make it work. It would be counter productive if I were to post the code in question because as I have said I have tried so many combinations which simply haven't worked.
Add to this the fact of starting 2 clients and a server to check it thousands of times and I'm sure you can relate to my current state of sanity :)
I just find it mind-boggling bizarre that Unity doesn't seem to be able to do this. At the moment it seems like I would need to Network.Instantiate every item that might possibly be destroyed during a game. Surely that can't be the case - can it?
Again not looking for specific code examples but conceptual de-obfuscation, any help very much appreciated. I hope I have just misunderstood or overlooked something and hopefully your response will provide a simple solution which makes me look very foolish :)
Ok so it "should" work by sending a buffered RPC call to some function you write to destroy the objects... Sounds like you've tried to do that?
Yes I have. I just have trouble accepting that I need to have a networkView for every item that could potentially be manipulated over the network. Is that really a necessity? For a multiplayer game this is going to really amount to enormous amounts of buffered information over a moderate timeframe which is my worry.
For example if I have a large number of destructible objects in a scene, each one needs a networkView and a buffer entry. I can never clear that buffer while the game is running because the objects will start reappearing as players connect. It's not similar to instantiated objects where mostly the RPC buffer can be cleared when they are no longer needed as in the case of projectiles or even players.
This is more like the server needs to permanently forget the object existed but I just can't see a way around it without giving them all a network view and having them always in the buffer. Seems very restrictive and resource heavy to me.
You don't. Have a scene object which acts as a comms hub and takes a parameter that identifies the object to destroy.
While I am vaguely familiar with the concept I don't understand how that will alleviate the buffer issue. I'm not being contrary, I simply don't understand the mechanism. Perhaps you could elaborate a little?
Do you mean just use a single networkView on the hub object and serialise everything through that? How would I distinguish between large numbers of similar/identical objects if they don't have a networkView? Thanks for taking the time to discuss this.
The general approach you're taking should work, however I think you're setting yourself up for future pain using indexes ins$$anonymous$$d of IDs. As far as I know RPC calls are only guaranteed to be in order if they're buffered. If a client receives two doDmg calls out of order, or misses one due to some race condition or other, then the wrong object is going to be destroyed and your indexes will be out of sync. To solve this, you would need a unique ID which is the same between server and client.
I'm curious as to your reason for not wanting to use a NetworkView on each of the components that needs to be network aware.
You mention efficiency above, but the approach you're taking here (using indexes rather than IDs) would require iterating over the entire list for every change. It $$anonymous$$AY be a smaller network overhead to send a list of integers ins$$anonymous$$d of the buffered RPC calls (depending on how the buffering is implemented in Unity's networking) but the processing on the client seems much less efficient.
If the goal is to $$anonymous$$imise network overhead, be sure that this is something that is actually needed. Be sure that Unity's RPC buffering doesn't aggregate calls and that you really do need to shave off that bit of overhead. By the time you add your calls to send and receive the list of destroyed objects, add in some stability to avoid race conditions, etc. You're going to have sunk quite a lot of time and effort into optimising this one aspect of Unity's networking and you might find that it wasn't actually that important whether the connection process took 2 seconds or 5 seconds.
Answer by HackDaddy · Feb 22, 2014 at 08:21 AM
Since I have an answer that resolves from several different inputs, I will try to encapsulate the approach I took as an answer.
I used a single networkview on an empty game object and made all destructibles children of that object. I used a dictionary to store references to the destructible objects and also gave them an ID via attached script which matched the index in the dictionary. The result was that I had direct access to the object for both getting (via raycasthit - ID) and setting health (via RPC - index) with no iteration involved.
Destroy was called locally on server with RPC to others. No buffered RPCs required.
Again thanks to those who helped out with most useful guidance.
Your answer
Follow this Question
Related Questions
Reducing lag in networking. 1 Answer
Network RPC buffer issue 0 Answers
How can I delete or destroy an instance of an object IN A MULTIPLAYER GAME?. 2 Answers
Network.Destroy doesn't remove objects on other systems? 2 Answers
Destroy instances created continuosly of a prefab in a network game... 0 Answers