Question about networking data
by Andy Rollins · in Torque Game Engine Advanced · 01/22/2009 (2:38 pm) · 6 replies
Currently working on implementing a Navigation Grid as a basis for our AI system, I have basic grid object created on the server side (implemented as a Sceneobject).
I'd like to send that data to clients too so that they can render the grid whilst we're debugging and QA'ing the system.
Now I could use the ghosting system and add a mask bit to my sceneobject and using the normal packUpdate/unpackUpdate and send it that way, with potentially tens of thousands of grid points it's a lot more than will fit in a standard packet so I would have to split it down and send many packets - however that's where I'm into shaky ground.
I'm sure I've read somewhere that if in my packUpdate() function I set my mask bit again that TGEA will automatically call the function again straight after - can anyone confirm if that is right? and if there is a way to retrieve how many bits are in the packet so I can loop til I reach 1400/1500?
Secondly, I'm ok with it hanging the game for a few seconds whilst these updates go out as it's on for whilst we're QA'ing but is there a better/more efficient way of sending this data that anyone can think of?
I'd like to send that data to clients too so that they can render the grid whilst we're debugging and QA'ing the system.
Now I could use the ghosting system and add a mask bit to my sceneobject and using the normal packUpdate/unpackUpdate and send it that way, with potentially tens of thousands of grid points it's a lot more than will fit in a standard packet so I would have to split it down and send many packets - however that's where I'm into shaky ground.
I'm sure I've read somewhere that if in my packUpdate() function I set my mask bit again that TGEA will automatically call the function again straight after - can anyone confirm if that is right? and if there is a way to retrieve how many bits are in the packet so I can loop til I reach 1400/1500?
Secondly, I'm ok with it hanging the game for a few seconds whilst these updates go out as it's on for whilst we're QA'ing but is there a better/more efficient way of sending this data that anyone can think of?
#2
I guess this is where my knowledge of the whole rendering process falls down a bit, if I remove it as Sceneobject derived and instead send data via NetEvents how can I then get it rendered on the client? I had presumed I'd need a Sceneobject for that.
If that's the case why would I not just use packUpdate() methods for the Sceneobject over creating a netEvent? seems like the process would be nearly the same (minus setting mask bits)?
01/22/2009 (3:11 pm)
WOW, that's got to be one of the fastest replies ever!!I guess this is where my knowledge of the whole rendering process falls down a bit, if I remove it as Sceneobject derived and instead send data via NetEvents how can I then get it rendered on the client? I had presumed I'd need a Sceneobject for that.
If that's the case why would I not just use packUpdate() methods for the Sceneobject over creating a netEvent? seems like the process would be nearly the same (minus setting mask bits)?
#3
Anyway. There's a bit of difference between using a SceneObject over a NetEvent. You'll use up ghosting slots (it's limited) and you just can't split parts of the BitStream up without issuing more updates, and even then with the ungauranteed nature of this particular part of the networking system, how do you make sure the last part was received?
Sending the information each time even if it didn't change would help with that but you're wasting lots of network troughput and even then you have to figure out how to split those packets up if your grid is anything larger than a few vertices.
01/22/2009 (3:28 pm)
If you don't know how to render a grid, then it might be better to use what you're familiar with (ie, the approach you outlined yourself). But if you're curious, check out the GFX Draw Util class and how it can render primitives. A triangleList would do wonders there.Anyway. There's a bit of difference between using a SceneObject over a NetEvent. You'll use up ghosting slots (it's limited) and you just can't split parts of the BitStream up without issuing more updates, and even then with the ungauranteed nature of this particular part of the networking system, how do you make sure the last part was received?
Sending the information each time even if it didn't change would help with that but you're wasting lots of network troughput and even then you have to figure out how to split those packets up if your grid is anything larger than a few vertices.
#4
We've just move to TGEA so the whole GFX side is new to me, I'd quickly prototyped the rendering using PrimBuild as it's similar to openGl that I'm used to with TGE... I'll have a look at the GFX DrawUtil class for that.
Sorry for being a pain but I'm still a little confused with the rendering, once I have the netEvent received on the client I'll need to store that in a class that is pulled into rendering pipeline (for a sceneobject that's through prepRenderImage and RenderObject calls). So if I haven't derived from SceneObject what class should I use so that rendering occurs?
EDIT: looking at the lightning NetEvent in the SDK it updates the netEvent data on an already ghosted lighting class object (derived from Gamebase) - would the same approach be what you're suggesting?
01/22/2009 (4:02 pm)
Thanks again Stefan - that's some very good points, I hadn't considered the possibility of packet loss - guaranteed delivery netEvents are going to be a much better overall solution.We've just move to TGEA so the whole GFX side is new to me, I'd quickly prototyped the rendering using PrimBuild as it's similar to openGl that I'm used to with TGE... I'll have a look at the GFX DrawUtil class for that.
Sorry for being a pain but I'm still a little confused with the rendering, once I have the netEvent received on the client I'll need to store that in a class that is pulled into rendering pipeline (for a sceneobject that's through prepRenderImage and RenderObject calls). So if I haven't derived from SceneObject what class should I use so that rendering occurs?
EDIT: looking at the lightning NetEvent in the SDK it updates the netEvent data on an already ghosted lighting class object (derived from Gamebase) - would the same approach be what you're suggesting?
#5
I never used Lightning, sorry. Basically, keep the data somewhere and keep track of if it has been sent to the client or not. Update the client if needed, and when the client has got all the packets it just renders it from the array you keep the data in, list or whatever - (or if you're using a TriangleList, you put it into a Primitive Buffer).
Start with just passing the data around, and seeing if you can compare it by checking the output on the client vs server? I keep all the data in a seperate class (BuildingGrid, much similiar to your grid) and in GameTSCtrl::renderWorld () I just use drawPrimitives () on my buffer. Really simple. Can't remember where you render with PrimBuilder but it should be obvious after checking the source.
In the end, this also depends on your design. Is the grid uniformant? Are all the nodes placed with the same spacing between each other? If so then you can really limit the data being sent because the client can assume.
Sorry if I'm not as clear as I could be. Need some sleep. If you run into more issues, post :)
01/22/2009 (4:17 pm)
PrimBuild is a good idea! That, or just look at how the Editor creates its visual grid. It uses a TriangleList and is pretty straight forward. TriangleFans are even more simple, but not as performant IMO. Think they removed it in DX10 too.I never used Lightning, sorry. Basically, keep the data somewhere and keep track of if it has been sent to the client or not. Update the client if needed, and when the client has got all the packets it just renders it from the array you keep the data in, list or whatever - (or if you're using a TriangleList, you put it into a Primitive Buffer).
Start with just passing the data around, and seeing if you can compare it by checking the output on the client vs server? I keep all the data in a seperate class (BuildingGrid, much similiar to your grid) and in GameTSCtrl::renderWorld () I just use drawPrimitives () on my buffer. Really simple. Can't remember where you render with PrimBuilder but it should be obvious after checking the source.
In the end, this also depends on your design. Is the grid uniformant? Are all the nodes placed with the same spacing between each other? If so then you can really limit the data being sent because the client can assume.
Sorry if I'm not as clear as I could be. Need some sleep. If you run into more issues, post :)
#6
01/22/2009 (4:25 pm)
Thanks Stefan, need my sleep too ;) I'll give it a try over the weekend and see how it goes.
Torque Owner Stefan Lundmark