PompiPompi
|
|
« on: April 24, 2013, 10:49:37 AM » |
|
In a network game, it make sense to track bullets or almost any object with an ID. The ID is basically a 32 bit unsigned int that is increased whenever a new object of a specific type is created.
Every bullet the player shoots, the ID counter is increased by one. A shot gun that shoot several bullets(actually shells) at once will increase the bullet counter by more than one.
I am assuming that it is not possible for the players to shoot 4 billion bullets in one match\session. This makes everything easier to generate and deal with IDs since an unsigned int maximum number is 2^32-1.
Is there anything else to consider here? I just think of it like this and ignore the case that the counter might actually loop.
|
|
« Last Edit: April 24, 2013, 10:55:07 AM by PompiPompi »
|
Logged
|
Master of all trades.
|
|
|
Dr. Cooldude
Guest
|
|
« Reply #1 on: April 24, 2013, 10:58:37 AM » |
|
Unless someone plays it in over 1000 hours, that should be fine. for added safety, you could make the IDs reset every game round.
|
|
« Last Edit: April 24, 2013, 11:08:02 AM by Dr. Cooldude »
|
Logged
|
|
|
|
nickgravelyn
Guest
|
|
« Reply #2 on: April 24, 2013, 10:58:57 AM » |
|
You're probably safe just rolling it over if it does run out unless there's somehow a chance that the first bullet is still active in the simulation by the time the last one is fired. But yeah, if you fired 100 bullets per second it would still take (assuming my admittedly shakey math is right) 1193 hours to exhaust all of those IDs. I think you'll be safe.
|
|
|
Logged
|
|
|
|
Dr. Cooldude
Guest
|
|
« Reply #3 on: April 24, 2013, 11:07:12 AM » |
|
Well, if someone actually plays it in over 1000 hours, lets just call it a retro kill-screen. Offtopic: Nick Gravelyn, I didn't know you were on tigs! Love your XNA tutorials :D
|
|
|
Logged
|
|
|
|
Joshua
|
|
« Reply #4 on: April 24, 2013, 11:32:44 AM » |
|
Why not use the object pool pattern?
|
|
|
Logged
|
|
|
|
Sar
|
|
« Reply #5 on: April 24, 2013, 12:01:44 PM » |
|
Why not use the object pool pattern?
I'm guessing because the point of Ids is to synch up the same bullet on every machine to the server, not to index into an array of instances or anything.
|
|
|
Logged
|
|
|
|
Fallsburg
|
|
« Reply #6 on: April 24, 2013, 12:10:03 PM » |
|
That's not to say you couldn't (and shouldn't) use both an object pool and this id system.
You can also pool unused ids (if a bullet dies [and there's no way to go back in time] it could get added to a list that would be safe to pull from).
The biggest problem I see with this id system, is how do you handle two bullets shot by different players at the same time?
|
|
|
Logged
|
|
|
|
Dr. Cooldude
Guest
|
|
« Reply #7 on: April 24, 2013, 12:17:20 PM » |
|
The biggest problem I see with this id system, is how do you handle two bullets shot by different players at the same time?
I guess each players might have their own counter, but I'm not sure...
|
|
|
Logged
|
|
|
|
Fallsburg
|
|
« Reply #8 on: April 24, 2013, 12:26:11 PM » |
|
Yeah, I guess it could just be Player ID + Counter.
EDIT: Obviously not actually adding them, just the combination of the two.
|
|
|
Logged
|
|
|
|
nickgravelyn
Guest
|
|
« Reply #9 on: April 24, 2013, 12:29:25 PM » |
|
Or more generally you'd use a client/server architecture. One player is deemed the 'host'. All bullet IDs come from him. If another player shoots you'd simulate it locally with no ID (or some ID that signifies it's local only) so the local player sees it immediately on screen. Simultaneously you'd send a packet to the host to fire a bullet. The host then specifies an ID and sends that to all other players. A good read would be to see how the Source Engine handles networking for their games, most of which are shooters and therefore pretty similar to what you're doing here (though admittedly their bullets are just raycasts). https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
|
|
|
Logged
|
|
|
|
Dragonmaw
Guest
|
|
« Reply #10 on: April 24, 2013, 12:53:18 PM » |
|
This is assuming that you are actually creating bullet objects and not using hitscan. It's important if you want to do things like simulate bullet drop or impacts on the body, but plenty of games go the raycast route (as mentioned above).
If you have to track bullet ids, go with playername_bullet#, and unload the id once the object has disappeared. If you do this, you won't need 4b slots. More on the order of 100-200.
|
|
|
Logged
|
|
|
|
Martin 2BAM
|
|
« Reply #11 on: April 25, 2013, 12:31:46 AM » |
|
You're probably safe just rolling it over if it does run out unless there's somehow a chance that the first bullet is still active in the simulation by the time the last one is fired.
I agree, I wouldn't worry even if it wraps around to zero. Also the "Player ID/Object ID" seems the best way to go; even for 64 players you still have 67 million Object IDs available for each player. Worst case scenario: Someone could attack the server by spamming with a lot of bogus or repeated IDs, but that's somewhat easy to detect. If you still need like 2 billion objects there's another solution:As the server knows who each player is it can just keep 2 31-bit IDs internally server-side, one for the client that created the ID and another server-issued ID for the rest of the clients, remembering to address the object accordingly whenever it sends info. The 1 bit left out lets the client know if the ID is server-issued or one of their own. This allows players to reconnect without creating weird scenarios like the server telling the new client where to start with it's ids or having to clean up the objects for the player using that slot before.
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #12 on: April 25, 2013, 04:19:48 AM » |
|
This makes everything easier to generate and deal with IDs since an unsigned int maximum number is 2^32-1. unsigned int is 2^64-1 on my system, have you considered that?
|
|
|
Logged
|
What would John Carmack do?
|
|
|
kamac
|
|
« Reply #13 on: April 25, 2013, 06:05:13 AM » |
|
This makes everything easier to generate and deal with IDs since an unsigned int maximum number is 2^32-1. unsigned int is 2^64-1 on my system, have you considered that? Isn't that even better? He assumed 2^32-1 as standard, since that's the lowest for any decent PC (32-bit, I guess). I don't think here he has to consider somebody who is above that limit. He'll simply treat them as if they have 2^32-1.
|
|
|
Logged
|
|
|
|
PompiPompi
|
|
« Reply #14 on: April 25, 2013, 08:58:18 AM » |
|
Yea,
Well the idea was that in practice I could think as if I have infinte IDs, since in practice no one will ever reach it's limit. A pool seems like wasteful because instead of searching for a previous available ID, I can just "generate" a new one by increasing the "ID coutner" by one.
|
|
|
Logged
|
Master of all trades.
|
|
|
Martin 2BAM
|
|
« Reply #15 on: April 25, 2013, 10:27:30 AM » |
|
A network game should send the least amount of data.
With 64 bits IDs it would take 4 extra bytes per entity on each frame packet.
|
|
|
Logged
|
|
|
|
PompiPompi
|
|
« Reply #16 on: April 25, 2013, 10:58:45 AM » |
|
I am not sure it's an issue. There is a difference between latency and throughput. Of course if you can do networking with sending only 1 bit that would be super.
I am not an expert of network performance, but for games what kills a game is latency not throughput. Unless you have a lot of simultaneous entities. But this is not an MMORPG.
The key point is understanding the difference between latency and throughput... Usually you don't want to ping pong data in a game, or else it will be really terrible. The packet size or even packet amounts you send might not matter a lot compared to the delivering latency.
Ok, let's try to simpelfy this, I will use arbitrary numbers for this.
Let's say you have a latency of 100ms, and a throughput of 1k/1ms.
If you are sending 1k of data per update, latency will be 101ms. If you are sending 2k of data per update, latency will be 102ms. So the fact you are sending twice as much data doesn't matter that much.
|
|
|
Logged
|
Master of all trades.
|
|
|
Schrompf
|
|
« Reply #17 on: April 25, 2013, 11:34:38 AM » |
|
And how do you store the objects then? A simple bullet in 2D has at least position (2xfloat) and speed (2xfloat). So a 32Bit application can store at most 256 million of these. I don't see 4 billion ids being your limit at any time in the near future :-)
In addition: I suggest reusing the ID, because then you can store the objects by ID in a linear array, which yields the quickest access times by far. If you really want to use freely distributed IDs, your best bet is probably a map, which adds another 8 byte per bullet to your overhead, AND requires an additional allocation for each bullet. Don't do that, be smart.
|
|
|
Logged
|
Snake World, multiplayer worm eats stuff and grows DevLog
|
|
|
BorisTheBrave
|
|
« Reply #18 on: April 25, 2013, 01:09:54 PM » |
|
I don't see the point in an incrementing ID. The fact you are suggesting it means you are assigning all IDs from one machine, at which point you might as well use the memory address as the id.
If you are assigning ids from multiple machines (quite possible if you're implementing client side prediction), you'll then need to use GUIDs, or design a partitioning scheme for your ids.
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #19 on: April 25, 2013, 02:54:42 PM » |
|
This makes everything easier to generate and deal with IDs since an unsigned int maximum number is 2^32-1. unsigned int is 2^64-1 on my system, have you considered that? Isn't that even better? He assumed 2^32-1 as standard, since that's the lowest for any decent PC (32-bit, I guess). I don't think here he has to consider somebody who is above that limit. He'll simply treat them as if they have 2^32-1. My concern is that if you refer to say, std::numeric_limits<unsigned>::max(), the numbers could be very different. If you have a 64 bit server for example, you could end up with a situation where you're passing IDs to 32 bit clients that are too large,
|
|
|
Logged
|
What would John Carmack do?
|
|
|
|