UDP based action

I’m wondering how reasoable working UDP protocol should be made.

To focus on something, let’s suppose that we have space-combat game. Up to 20-30 ships shoot at each other, plus we have some some ‘static’ stuff like meteors, space debris, space stations etc.
Everything should be computed on server - clients are not trusted (for computations/decision making, I’m skipping problem of aimbots here).

We have 6DOF. This means that ‘static’ object has 12 position properties (x,y,z,yaw,roll,pitch + the speeds for the same). By static I mean object that moves, but does not manuever (for example rotating meteor flying through space).

Static objects can be transmitted at very start of game + when they are created (for example dump missile probably will fit the bill). From this point on, they can be simulated on each machine, with only major events being transmitted (like collisions). On the other hand, they need to be acked from clients, so server will be sure that client knows about object.

Real problem is with maneuvering objects (spaceships, fire-and-forget rockets) plus with small projectiles (which probably fit ‘static’ object description, but there is just too many of them and they live for very short).

I suppose that for each active object, updated position+speeds have to be broadcast to everybody once per time slice. Probably there is also no need to ack packet every time - server will send updated version soon anyway. Client can make a prediction of movement between incoming packets.

[i]

  1. How large should be a timeslice ? 100ms ? 500ms ? Does it make sense to have timeslice smaller than ping for any client ?

  2. What is the best fragmentation of info ? Should separate packet be used for each object, or should as many active objects as possible be put into one packet ?
    [/i]

I suppose that it would make sense to have different timeslices for active objects depending how far they are from given player. But I’m interested in solving problem of close objects - more distant will be just less frequent update of same algo.

Biggest problem for me is projectiles. I suppose that client would send packet with ‘projectile fire’ info to server, containing exact position/direction at time of fire - so they will fire exactly at position where client wants it, not depending on ‘self lag’ from server. Server would just check if it is legal (direction and position of fire is in contained between start and end positions for some window of past time) and simulate based on it. But how high-frequency projectiles should be handled ? Let’s suppose that there is a gun emitting 10 projectiles per second, each living for 3-4 seconds. This means that every client will produce around 30 moving objects. With 10 clients in close viccinity, it means 300 objects, 100 of them created and 100 of destroyed each second, with variable position and direction.

Info for such small objects could be simplified - they need just position (x,y,z) direction (a,b) and speed ahead (v) (plus maybe time of fire and maybe time to live) But this still means 6-8 parameters per object. Bullets from one player will have probably very small delta between shots, so probably positions could be compressed. But still this seems to be a lot of data.


3) Do anybody have any idea how to solve projectiles ? Will computing deltas and compressing them for every player be enough to trim amount of data to reasonable amount ?

Well well well … one of my favorite topics! :wink:

Sending data to a server in timeslices is a rather brute-force and artificial criterion on how to transmit data. It does not take into account what is happening, how fast things are changing and so on.
You can be sure that the most important things will always happen (Murphy!) when the new timeslice has just begun.

The value for the timeslice does not so much depend on latency, but on bandwidth! For fixed slices, you will have to know about the lowest bandwidth connection. This has to transport all your data - otherwise you will flood a client. The sum of all data has to fit the bandwidth of the server. With 30 players, better forget about 100ms!

The timeslice approach also adds significant latency. If your slice is (let’s say) 300ms on the client and another 300ms on the server to redistribute, you add a mean of 300ms latency to any event. Good that you paid a lot of money for buying a 40ms-latency internet connection.

Put as much as possible, but only as much as really needed into one packet to keep overhead low. OTOH, make sure that the packet size does fit below certain limits (1k?) - otherwise the risc that the packet will be dropped (for fragmentation) increases.
So adjust your timeslices that the values are dividable by each other (100,200,400 e.g.) so that you can combine messages into single packets.

As you may notice, I don’t think that timesliced UDP messaging does make too much sense. Try to play Quake with 30 players over the internet. You will notice why I think so…

Certainly, I’m not thinking about constant timeslices in client->server direction. In addition to other things, amount of data will be a lot smaller.

But as for the server side - I really think that data requires some grouping, to avoid sending hundreds of small messages per second. But to group few events, some kind of timeslice has to be introduced - I do not see other way.

As for the bandwith, yes, of course, it has to be considered. For this discussion, let’s suppose that we have guaranteed 2-3KB (16-24Kb) to each client (with possibility of packet loss of course, but not seriuous - just to not depend on arrival on any single packet).

With 100ms timeslice, this would mean around 200-300 bytes per slice. This would be around 10 bytes per player in max setting… I think it could be done (with 100ms slice, differences in positions/speed would be very small, fitting in one byte probably). ‘Events’ would be probably quite rare looking at this scale - rocket fired every 10 seconds etc. This of course still leaves the problem of ‘frequent projectiles’.

So maybe let’s look at it in different way. We have some kind of timeslice - 200ms for example, for position/speed updates, which can be predicted and are not 50ms critical, due to inertia etc. All events would be send in separate packets as soon as possible. But what with machine guns ???

How about looking at it from the event perspective?

Say your opponent presses their space bar to fire – the server receives a notification, and if approved sends some kind of FireEventPacket to the client with the person who is firing, what type of weapon they have fired, and the time they fired (in case they began firing in the past and the client needs to take some action to acount for this discrepancy in what the local player sees). For something like the machine gun, this could maybe be handled by having machine gun events when the remote player presses their fire button and again when they release it. All of the hundreds of bullets could be entirely computed on the client side, as could the explosions, etc. The health/damage of the attacked ship could be estimated by the client and then confirmed whenever the server sends the next health/damage update for that ship.

Idea is good. But let’s suppose that I want to write my name on space station hull, all the time holding the fire button. This includes some, possibly non-trivial, manuvers with a ship. There is no chance that all these movements can be transmitted in full to every client - or is there ?

Problem here is that with positions updates between certain timeslices, it is not very important what exactly happened in between - for other players and for server, rough approximation is good enough (because it is not important if ship was in fact 0.1 meter to left or to right). On the other hand, with bullets, exact direction is very important - it can potentially hit something few second later and every small difference in shooting direction will change impact point by large amount (many, many meters - enough to make a difference between hit and miss).

Very unhandy with UDP messaging? Chances are good that either the one or the other package gets lost…

Then you press fire and nothing happens.

Again, I vote for TCP. Send a message saying that you started to fire, when this happened and maybe an estimated propability that the rounds will hit the target.
Then you can easily visualize the effect local and remote. The stopped-fire event later causes an accurate damage calculation.

First, don’t try to make a network game acting like an exact simulation. I cannot imagine this can be achieved. The BEST way to get around network artifacts is an appropriate design of the gameplay!
Here, make machineguns scatter so much that writing the name would be impossible.

Second, if your network transmission follows some fancy dead-reckoning theme, it might be possible to do, even though not perfect. Hard to do with UDP, again.

Transmit the motion changes with their respective timestamps whenever they occur. If much happens, they might not been transmitted in realtime but fill a queue first, but in then end will receive at the remote station in form of a ‘track’ that can be reconstructed.
Of course you need to know than that EVERY message will arrive. Packet loss is a bad thing. In this scenario.

OTOH, if you write slowly with your gun, very few data will have to be transmitted (1 message at each corner of a letter?).

Underlining your name afterwards could be done with 2 messages!

  1. {timestamp, startfire, turn-slowly-y}
  2. {timestamp, stopfire}

But ok, you asked for a UDP solution and I try to advertise TCP, so I’m getting off-topic a bit…

Not at all… This would be an example of the benefits of using UDP. For cirtical messages (like firing) you could require acks (and put them in the lower levels of your protocol or your message class heirarchy) and for health updates, location updates, etc. you wouldn’t worry about that and can avoid the overhead. Maintaing the TCP connection for information which will be outdated by a new packet by the time TCP gets the first one reset->received is not as far as I can see the most effective use of bandwith.
That being said, I’m curious if there are any games out there which open both a TCP and a UDP socket between server and client. It seems like the client would almost exclusively use the TCP socket to communicate with the server, and that messages from the server would be sent on whichever one was appropriate.

I do not think that TCP should be used at all in realtime games. Even if you will do all the job of reimplementation of it in UDP (requiring acking every message and retrasmitting it on timeout etc), you gain one basic benefit - messages can be trasmitted out of order. For any message which happens to get lost over and over, you are out of luck in any situation. But with UDP, rest of world will get updated, while with TCP, all other messages which are have arrived, will wait in line for single unlucky one.

TCP should be used if you want to be sure that you get messages reliably AND in order. If you do not care about one of this things, it can be very bad.

In situation we are talking about, we do not really care about order of things (it is not very important if ship A will fire rocket 200ms before or after ship B - clients can compansate for this). We also do not care about 100% reliability for at least some of messages - status, position etc.

Of course, there are messages which needs to be transmitted reliably. To achieve this, it is needed to build kind of TCP on top of UDP. But confirmation can work for each message on it’s own, without blocking stream on missing delivery.

For non-realtime games, like fantasy MMORPG it would be probably easiest to just stick to TCP. But for realtime stuff like FPS or simulators, I’m afraid UDP is only choice.

Now, we are back to question, which messages need to be acked and possibly retransmitted and which can be just updated every time. Unfortunately my idea with deltas would require getting every message. On the other hand, transmitting absolute positions and orientations every time require better resolution, but does not need to be retransmitted of failure (they will be send on next timeslice anyway).

As for notion about not striving to do full simulation, but approximation, I agree. Probably, shooter machine could simulate the shots exactly, while the rest of people out there would just see a random cloud of bullets instead of name. Maybe it could be even made into game, by making high ROF weapons inherently random at shooting, spreading bullets into bigger or smaller cone in front.

When in doubt, look to the experts. This document describes how Tribes2 handles network traffic:

http://www.garagegames.com/articles/gdc_networking/

Given the development speed benefits of TCP, might it not behoove you to properly abstract the networking details, implement with TCP, and then verify whether or not you need to go through the hassle of UDP?

[quote]Given the development speed benefits of TCP, might it not behoove you to properly abstract the networking details, implement with TCP, and then verify whether or not you need to go through the hassle of UDP?
[/quote]
Game has to be designed around network code. You cannot just bold it in late stage of development. I mean, you can, but you will need to rewrite major portions of it.

Look at gamasutra for postmortem of Xwing vs T-fighter. They have done exactly this - started with perfect networking (I do not remeber if it was UDP or TCP - anyway they hava 100% packets transferred, with no lag and no change in order). Afterward they have discovered that internet does not work this way and they have had to make really a LOT of changes.

Easy example - on even quite good connection, TCP stream can block for many seconds, because of single packet. You are out of game, because you wait for packet which will be not longer important at the time you will finally receive it.

TCP is out of question. The last and unbeatable argument for that is subject of thread. I would like to gather idea about creation of UDP protocol - TCP protocol can be talked about in different thread :slight_smile:

Grab the quakeworld sources. Copy the UDP code out of it and port it to java. I did it, it worked. Lost the sources some time ago as I’m not currently bothered about network gaming.

Cas :slight_smile:

Thanks for garagegames and quakeworld pointers - both sources are quite helpful.

With my total lack of money and time I simply haven’t got the resources to really consider complicated big-budget super-duper games any more.

I’m concentrating on simple games that can be downloaded and run on their own and played by people for a little stress relief during coffee breaks. I might make enough money out of it to quit the tedious consultancy I do at the moment and do it full time in which case I’ll reconsider - my original make-a-million scheme is still in all its frozen dead glory at the shavenpuppy website.

Cas :slight_smile:

I agree with you, that was not what I meant to convey. Perhaps a better explaination would be:

  1. Design your system, with the networking specifics properly abstracted
  2. Implement a reasonable prototype with TCP
  3. Test, if TCP won’t work, then you can move ahead with UDP

The benefit of this approach is

  1. If there is more than one person working on the project, alteration to the mechanics of networking should be isolatable
  2. The cost of testing a TCP implementation is negligible compared with the cost of implementing a UDP solution.

My 2 cents. Alot of really smart people work on optimizing TCP over the net…

Ah, but TCP was optimised to do something else very well. UDP is the best protocol for realtime games with relatively consistent lag characteristics but it does need a lot of extra work on the client.

I recommend using both protocols simultaneously.

Cas :slight_smile:

Yep. What would be really cool is a guaranteed, UDP-based protocol that allows to overwrite messages that failed to transmit at a given time (like a shared bytebuffer e.g.).

If such a beast existed in a form of a valid socket implementation to be able to run with NIO channels…

Maybe the gaming community can do this once and forever?

I was thinking about it. Use UDP for position updates and TCP for guaranteed, ordered, low-priority stuff (like chat messages). But:

  1. I think there is also a need for guaranteed messages which do not have to come in order - for example it is better to receive rocket fire event from player 3 before preceeding event from player 2 then to stall on it. Same goes for stuff like auxlilary object data - it is low priority and can come in any order (but needs to be acknowledged by client)
  2. I’m not sure, but AFAIK TCP connection uses more resources - with unconnected UDP you can serve as many clients as you want, without worrying about OS limits ?

As for point 2, it is of course not a critical point for me and my possible pet project, I would like for this discussion to go outside of scope what I can do and focus on high-end, scaling implementation.

Unfortunately, I think there is a problem with unconnected UDP sockets in java - they do a permission check on every access. This can be a performance problem for hundreds of packets per second. But if we are at the subject, handling hundreds of TCP streams in java, even using nio, is also not so bright…

Anyway, as far as I see, there would be a need to implement ‘update’ type messages through UDP and reliable out-of-order messages (also UDP). In such case, I think it would be easier to just bolt reliable in-order messages using same protocol, instead of opening second connection route just for that. After creationg of reliable OOO packets, adding order to them should be trivial - just simple buffer gathering missing packets before showing them to upper layer.

OOO - so at least we have name now for the missing protocol.

:smiley: