Gunship-X -- A.E.G.I.S. and Salvo Projectiles
by Daniel Eden · 12/06/2008 (2:46 pm) · 6 comments
As noted elsewhere, I've been slack and/ or busy of late so I haven't really been putting much work into my Gunship-X project. That changed last week, however, when I finally got some time to myself and put some work into the game. Aside from the prerequisite bug fixes, most of the work's been put into beefing up and enhancing the improving the feel of weaponry in the game (making it look a little nicer, feel more fun to use, etc), on modelling some ground structures, and on adding support code for said structures.
In the (admittedly low-quality) video you can see the new A.E.G.I.S defensive buildings able to be deployed in the mission by the Support class. They're relatively simple structures -- moderately heavily armoured, fitted with regenerating shields, and armed with a rapid fire (and unlimited ammunition) autocannon, that while inaccurate does quite a bit of damage and imparts no small amount of kinetic energy when it hits. They're not game-balanced yet, of course, so their accuracy and damage may be subject to change in the future. =)
Of particular note in this clip is the improvements I've made to the "salvo" projectile class (used by both the player's autocannon at the beginning and the A.E.G.I.S. throughout). This is a pretty cool piece of code that allows you to do extremely rapid-fire or shotgun-like weapons without having to worry about that annoying "don't always show up immediately when you fire them" bug that plagues Torque projectiles.
The autocannon on the Assault gunship is firing at a rate of around 1800 rounds a minute while the dual cannons on the A.E.G.I.S. are firing at around half that (each). As you can see, they put an awful lot of projectiles into the air -- with relatively little overhead (especially compared to stock Torque projectiles). I played around with shooting at higher rate of fire but there doesn't seem to be much reason to bother going much higher than what I've got. The additional processing expense and visual clutter just don't warrant it.
You can't quite see it in the video due to the quality but those very same "salvo" projectiles make use of some new material-based effects code that causes the projectile collision effects to change based on the surface they're hitting. They'll pop up rocks and dust hitting stone and earth, clods of mud hitting swamp, globs of molten rock hitting lava, sparks hitting metal, and so on. I've found the sparks-on-metal especially adds to the appearance of the game. They let you know just when you're landing hits on another gunship and it looks fairly cool to see a gunship covered in sparks from a hail of gunfire.
During my week of development I did have one doozey of a bug. It took over an hour and dozens of release builds to track down a bug that seemed pretty basic: in release builds, the A.E.G.I.S. turrets fired a single round and then ceased firing completely. Nothing I could do seemed to make them shoot again.
I looked through targeting code, prop states, triggers -- all sorts of stuff related to how the turrets acquire and engage their targets and couldn't find anything. I made changes to how they activate their weapons, the conditions under which they'll shoot, how they're animated and oriented at their target -- anything I could think of that could have a potential impact on the problem -- but I couldn't seem to find out what was wrong.
After an hour or so of of pulling out my hair going through code line-by-line, making small changes, and rebuilding the executable, I had finally had enough and opted to shut down all my programming stuff to go play a game of Left4Dead with some mates.
In the midst of closing down my programs -- as my cursor hovered over the Exit option in UltraEdit32 -- the answer hit me. I was looking in the wrong place. The problem wasn't in the code, it was in the script.
I'd spent so much time coding over the last few days that I was completely ignoring the scripting side of things. I was suffering from tunnel vision concerning the problem. If the bug only occurred with the new objects and the new objects exist only because of the new code, my reasoning went, then obviously the bug exists only because of the new code. While that's often true, it isn't a hard-and-fast rule. In this particular case, it was completely and utterly wrong.
So, after an hour of pure frustration and ultimately fruitless toil, I finally began looking in the right place. Ten minutes later I had my answer.
It turned out that the problem came from a little helper function (read: "cheat") I've got automatically-enabled in debug builds that grants you infinite ammunition (for testing purposes only, of course -- it's not like I've ever used it to wtfpwn someone in a game -- that I'll admit to anyway). In a debug build, you load up the mission, place an A.E.G.I.S. and everything's hunkeydorey. It starts shooting at enemies and continues shooting at enemies until it's destroyed or the mission ends.
In release builds, however, things occur slightly differently. Without the cheat enabled, the weapons platform fires once and then RUNS OUT OF AMMO. Given they're supposed to have infinite ammo, this is... problematic at best.
When all was done and said, the fix was a single line of script -- one static field in a prop state datablock that specifies whether or not the weapon uses ammunition. Set to false, the problem vanished. Go figure.
The lesson to be learned here is that you can often unintentionally blinker yourself to when and where bugs exist. Sometimes you're better off taking a step back and chilling out rather than trying to force your way through an issue. Though you can sometimes break through a roadblock by bashing your head against it over and over, usually you just end up with a headache. =)
In the (admittedly low-quality) video you can see the new A.E.G.I.S defensive buildings able to be deployed in the mission by the Support class. They're relatively simple structures -- moderately heavily armoured, fitted with regenerating shields, and armed with a rapid fire (and unlimited ammunition) autocannon, that while inaccurate does quite a bit of damage and imparts no small amount of kinetic energy when it hits. They're not game-balanced yet, of course, so their accuracy and damage may be subject to change in the future. =)
Of particular note in this clip is the improvements I've made to the "salvo" projectile class (used by both the player's autocannon at the beginning and the A.E.G.I.S. throughout). This is a pretty cool piece of code that allows you to do extremely rapid-fire or shotgun-like weapons without having to worry about that annoying "don't always show up immediately when you fire them" bug that plagues Torque projectiles.
The autocannon on the Assault gunship is firing at a rate of around 1800 rounds a minute while the dual cannons on the A.E.G.I.S. are firing at around half that (each). As you can see, they put an awful lot of projectiles into the air -- with relatively little overhead (especially compared to stock Torque projectiles). I played around with shooting at higher rate of fire but there doesn't seem to be much reason to bother going much higher than what I've got. The additional processing expense and visual clutter just don't warrant it.
You can't quite see it in the video due to the quality but those very same "salvo" projectiles make use of some new material-based effects code that causes the projectile collision effects to change based on the surface they're hitting. They'll pop up rocks and dust hitting stone and earth, clods of mud hitting swamp, globs of molten rock hitting lava, sparks hitting metal, and so on. I've found the sparks-on-metal especially adds to the appearance of the game. They let you know just when you're landing hits on another gunship and it looks fairly cool to see a gunship covered in sparks from a hail of gunfire.
During my week of development I did have one doozey of a bug. It took over an hour and dozens of release builds to track down a bug that seemed pretty basic: in release builds, the A.E.G.I.S. turrets fired a single round and then ceased firing completely. Nothing I could do seemed to make them shoot again.
I looked through targeting code, prop states, triggers -- all sorts of stuff related to how the turrets acquire and engage their targets and couldn't find anything. I made changes to how they activate their weapons, the conditions under which they'll shoot, how they're animated and oriented at their target -- anything I could think of that could have a potential impact on the problem -- but I couldn't seem to find out what was wrong.
After an hour or so of of pulling out my hair going through code line-by-line, making small changes, and rebuilding the executable, I had finally had enough and opted to shut down all my programming stuff to go play a game of Left4Dead with some mates.
In the midst of closing down my programs -- as my cursor hovered over the Exit option in UltraEdit32 -- the answer hit me. I was looking in the wrong place. The problem wasn't in the code, it was in the script.
I'd spent so much time coding over the last few days that I was completely ignoring the scripting side of things. I was suffering from tunnel vision concerning the problem. If the bug only occurred with the new objects and the new objects exist only because of the new code, my reasoning went, then obviously the bug exists only because of the new code. While that's often true, it isn't a hard-and-fast rule. In this particular case, it was completely and utterly wrong.
So, after an hour of pure frustration and ultimately fruitless toil, I finally began looking in the right place. Ten minutes later I had my answer.
It turned out that the problem came from a little helper function (read: "cheat") I've got automatically-enabled in debug builds that grants you infinite ammunition (for testing purposes only, of course -- it's not like I've ever used it to wtfpwn someone in a game -- that I'll admit to anyway). In a debug build, you load up the mission, place an A.E.G.I.S. and everything's hunkeydorey. It starts shooting at enemies and continues shooting at enemies until it's destroyed or the mission ends.
In release builds, however, things occur slightly differently. Without the cheat enabled, the weapons platform fires once and then RUNS OUT OF AMMO. Given they're supposed to have infinite ammo, this is... problematic at best.
When all was done and said, the fix was a single line of script -- one static field in a prop state datablock that specifies whether or not the weapon uses ammunition. Set to false, the problem vanished. Go figure.
The lesson to be learned here is that you can often unintentionally blinker yourself to when and where bugs exist. Sometimes you're better off taking a step back and chilling out rather than trying to force your way through an issue. Though you can sometimes break through a roadblock by bashing your head against it over and over, usually you just end up with a headache. =)
About the author
#2
12/07/2008 (4:14 am)
That looks pretty awesome. Those material effects sound interesting - I'm trying to do something similar. It surprised me how much material-based functionality there already is in TGE, and how extensible it is.
#3
Anyway... nice job!
Luck!
Guimo
12/07/2008 (4:40 am)
Amazing... I wanted to do some rapid fire about two years ago and utterly failed. I wont ask how you did it as it is your technology (and Im no longer programming that game anyway) but hopefully you will be kind enough to share your knowledge as a resource in the future. Anyway... nice job!
Luck!
Guimo
#4
12/07/2008 (6:33 am)
Glad someone else brought up the resource question ;). I'd be interested as well, if only to know how you got about the problem. No flak guns currently in my game design...
#5
A detailed explanation of paragraph 3 would be nice.
12/07/2008 (7:01 am)
Those are cool cannons.A detailed explanation of paragraph 3 would be nice.
Quote:
Of particular note in this clip is the improvements I've made to the "salvo" projectile class (used by both the player's autocannon at the beginning and the A.E.G.I.S. throughout). This is a pretty cool piece of code that allows you to do extremely rapid-fire or shotgun-like weapons without having to worry about that annoying "don't always show up immediately when you fire them" bug that plagues Torque projectiles.
#6
It's doubtful it'll see release a resource in any way, shape, or form given it's based on my own codebase which is significantly different to stock TGE's.
@Steve
Having each projectile as its own object that is scoped and networked individually works fairly well for weapons with a relatively low rate of fire. Seldom do you run into any issues unless you've got a lot of other objects taking network priority over the projectiles.
However, if you've got weapons with a very high rate of fire you can easily exceed how much data can be sent from the server to the client in any given update (since each individual projectile sends its datablock, position, velocity, etc). If you've got lots of projectiles being created in close proximity and/ or in rapid succession, you can often see a noticeable delay between when the projectile is created on the server and when it appears on the client.
In most cases the worst you'll get is the appearance of projectiles being generated meters ahead of the weapon, but if you're really straining the network, projectiles may not show up until after they've hit something and exploded or, in very rare cases, not at all.
The salvo projectile class bypasses the issue by being ghosted to the client ahead of time and just synching start, delta, and end information between the server and client and then using those values to interpolate the correct position of the projectile generation accordingly. You still get "lag" from when you press the trigger to when the bullets start appearing, but you don't get the delayed appearance problem. It's also significantly lighter on the network than a bunch of equivalent projectiles.
12/08/2008 (4:02 pm)
@GuimoIt's doubtful it'll see release a resource in any way, shape, or form given it's based on my own codebase which is significantly different to stock TGE's.
@Steve
Having each projectile as its own object that is scoped and networked individually works fairly well for weapons with a relatively low rate of fire. Seldom do you run into any issues unless you've got a lot of other objects taking network priority over the projectiles.
However, if you've got weapons with a very high rate of fire you can easily exceed how much data can be sent from the server to the client in any given update (since each individual projectile sends its datablock, position, velocity, etc). If you've got lots of projectiles being created in close proximity and/ or in rapid succession, you can often see a noticeable delay between when the projectile is created on the server and when it appears on the client.
In most cases the worst you'll get is the appearance of projectiles being generated meters ahead of the weapon, but if you're really straining the network, projectiles may not show up until after they've hit something and exploded or, in very rare cases, not at all.
The salvo projectile class bypasses the issue by being ghosted to the client ahead of time and just synching start, delta, and end information between the server and client and then using those values to interpolate the correct position of the projectile generation accordingly. You still get "lag" from when you press the trigger to when the bullets start appearing, but you don't get the delayed appearance problem. It's also significantly lighter on the network than a bunch of equivalent projectiles.
Torque Owner kcpdad
60 Tons