| Home Page | Recent Changes | Preferences

Foxpaw/Developer Journal

November 22, 2003

I came up with a brute-force solution to a problem I've been having with calculating the correct rotation for things in the editor. The solution actually turned out pretty good. It's essentially a very small scale neural network system. I thought that it would be a bit slow, but it's not noticeable, and it's only used in the editor, where framerate wouldn't be as important anyway. I wouldn't use something like that in Tick, for sure, but this is a "one time" function that gets called only based on a certain user action, and they can't really perform that action frequently enough to strain the framerate.

Later that day...

I fixed another problem that had been bugging me for a long time. The editor is much improved now, in my opinion. My progress has been stifled somewhat however, with the discovery of an engine limit. It turns out that although in theory Unreal Units are all relative, this is not the case.

First I found that lightradius and soundradius are in a certain set scale. That's not that big of an issue however, as static lights are best kept small, and dynamic lights can be made quite large. (dynamic lights operate on a vastly different scale than static lights)

Apparently, the engine automatically clips things that are more than about 60,000 unreal units from the camera. That is bad, because although fighter craft have long since disappeared into the blackness of space by that point, large capital ships are clipped before they could rightly be seen.

I've covered up the clipping by using black fog (I've had it all along, I just had to adjust it to go to the clipping distance) but it's still a bit short. When a capital ship begins to fade into view, it's still pretty far away, for a fighter craft, but certainately not at the range that standoff combat between large capital ships may occur at. It also doesn't look very good against a non-black background because it always fades to black, not to whatever color the object is behind. It would be nice if there was a "fade to translucent" of some sort.

Also, I've noticed a boon to the relative slowness of the fighters: number 1, it makes the capital ships feel huger. number 2, it makes space feel bigger. The maximum size for a map in UT2003 is pretty big, but not really big enough to do a large space area justice. However, because the fighter ships are relatively slow, they can fly for quite some time before hitting the edge of the world. (The heavy fighter I designed has just enough fuel to fly from one corner of the "world" to the other, though since the carriers are closer to the edge you could concievably hit the edge if you flew directly away from the enemy carrier for a while. This can be remedied somewhat, because the map is not as big as it could be. It actually only takes up about half the maximum map size.

Musicalglass: I can suggest a possible solution to this problem. When your ships are far away, you can use scaling to simulate distance on your LOD models. They do it in movie compositing all the time. However, if you use linear scaling it will not appear correct: objects will appear to be moving faster when they are farther away. I searched around for the equation which will accuratately simulate distance, but I mostly found a lot of dissertation pdfs dealing with 3d accoustics and such, but I know I've seen that equation somewhere. I believe it's: scaling is inversely proportional to the square of the distance. So if I'm not mistaken, you should be able to control your scaling by the square of time and achieve an accurate simulation of distance. There's a book by Industrial Light and Magic which discloses many of the ratios for such things as what speed to move a scaled model to make it appear to be a large model, etc.

Foxpaw: Unfortunately, scaling probrably isn't an option, because if I change the scale of things, that will also affect the physics simulation. :/ Also, static meshes don't work well with LOD because of the way they are handled by the video card. I could implement a software LOD, but there again - changing the mesh will change it's physics properties.

Musicalglass: At that point Physics shouldn't be necessary. If I understand the problem: you have a really big ship like a mothership and the problem occurs when it's approaching or departing at a great distance. You would have the ship come to a complete stop at say, 59000 units and temporarily suspend any physics. The physics is now being simulated by scaling. You don't even need an LOD. You just scale the model itself

Foxpaw: Well, I can't just simulate the physics by scaling - there's still stuff happening there that needs to be simulated. IE a dogfight in progress can't be paused just because it's getting far away, and I can't arbitrarily change the drawscales because that changes the physics simulation (not to mention it would change the drawscale for everyone, not just the person far away.

November 27th, 2003

I'm not really sure what coding to do next: I feel like everythings "done," but it obviously isn't. I just don't know where to jump in I guess. I guess I'll work on the menu system some more.

December 9th, 2003

It's been more than 10 days since I updated this and I haven't really done any coding. I think I'm experiencing a case of the "winter blahs." I think I'm going to modify the camera code a bit, and then maybe do some ground-based stuff.

December 13th, 2003

I made nifty bullet-style weapons with fancy penetration and everything! I think that various "realism" mods have had something like this in them, but mine's better! :D

Simply enough, all bullets have a muzzle energy, drag coefficient, hard target penetration coefficient (ships, walls, etc.) and a soft target penetration coefficient. (people) The weapons then does a series of successive traces, and every time it hits something, it figures out whether its hard or soft, and how thick it is. Then the bullet does damage, slows down, transfers momentum, and travels through the target as applicable. It also makes fancy chips and junk come out of the point where it "penetrated" a hard object, and makes blood and stuff come out of the place where it "penetrates" a soft object.

Though it would be very nifty to have dynamically projected "portals" projected on things so you could see "through" the cavity left by the bullet, this would be too processor intensive. To that end, only static "hole" decals are going to be used, and then only on pieces of the world. (Constantly computing projector locations for moving and rotating ships uses too much processing power.

The penetration is mostly going to be relatively weak through hard objects, otherwise a human player could just spray aimlessly at walls and hit people a couple of rooms over. The hard target penetration is going to be sufficiently low that only relatively thin objects (like a railing, fence, maybe a lamp post) can be penetrated. Of course, different weapons will have different penetrations, the human submachinegun has relatively low penetration, while the assault rifle has reasonable penetration. Sniper rifles would be an ideal candidate for this sort of penetration, however I'm going to have the sniper rifle be like.. that rifle in Deep Space Nine. The one that teleports it's projectile to just in front of it's target, so every shot is at point blank.

December 16th, 2003

Apparently my pathfinding code doesn't work anymore. It pulls either an "infinite recursion," (not actually infinite, just more than 250 calls) or a "runaway loop." This is kind of strange since it never used to do that, and it used to run quite fast even with multiple AI players running around.

I have two potential solutions: Number 1, I can have the editor preprocess the path information. This is more or less what Epic does, but I don't really want to do it that way because then you can't have the path network "learn" in real-time. (IE if someone sprays a bunch of napalm around a navpoint, it should be excluded from pathmaking by any bot that knows it's exteremely dangerous.) The second potential system is to have a heirarchial type of path network. Essentially, the path network would be split up into larger areas, and the path would be generated area - area. Then each time an area was entered, a path would be generated pathnode - pathnode to get from that area to the next area. This method would greatly reduce the path length that had to be considered at any one time, however, it requires more effort for the mapper as they will have to set up the areas as well as the individual pathnodes.

December 18, 2003

I've temporarily fixed the pathfinding system by instituting a hard limit on maximum path length. It's not the ideal solution, but for any reasonably-sized map it should be fine. Unlike Epic's pathnodes, there is no need for mine to be a set maximum distance apart, so you can cover a large outdoor area relatively easily by just placing one pathnode at every place where the bots are going to need to turn. Basically, the bots need to be able to make a beeline from one node to another, but distance doesn't matter.

Having said that I still need to come up with a solution to having multiple sets of pathnodes on a level. Obviously there are going to be some paths that persons on foot can travel, but some vehicles may not be able to make it. Aircraft and spacecraft also should use an airborne set of paths, instead of attempting to follow along the ground. (Though maybe I could just have them fly a given distance above the ground path network.)

December 24th, 2003

I implemented a snazzy path caching scheme to speed up the pathfinding. It's very nifty - but it still has the same problem as before, it's not amiable to changing path values. That part kinda sucks. However, it does result in a 25-50 times reduction in time spent pathfinding, so I guess it's okay.

The existing paths, without caching, were working okay now, but I wanted to do a lot MORE pathfinding. Presently the bots pick somewhere they want to go and pathfind their merry way there. I want them to use pathfinding to pick where to go too. IE:

  1. Bot scans availible pickups in the world
  2. Bot traces path to each pickup to find approximate time to acquire. (No aggregation of pickups will be considered for now. EG it's worth it to travel twice as far to pickup one health vial instead of another, if there's four more health vials on the way..)
  3. Bot pathfinds its way to the pickup.

This of course requires a great deal of pathfinding every time the bot wants to decide what to do. The bots are actually pretty good as it is, even though their AI is incredibly simple. The only real improvements that they "need" are to pick up weapons and such when they need one. Many times I'll loose a three-round burst into a bot and watch it heave over, with it's gun clattering to the floor, only to have it crawl and stagger back to it's feet and hightail it away from me empty handed. (Instead if picking up the gun that it dropped and is mere feet away.)

Fortunately, the whole thing is rather "leet" if I do say so myself. Which I wouldn't. Because I don't use that expression. But if I did, then I would. :P The mod makes gratuitous use of Karma, which is good for plenty of eye-candy. It's got the Karma injury system brainstormed over on Karma Ragdoll, and when you get ragdolled in this manner, you also drop the weapon you were carrying. (Understandable, since you've just been sent flying from an explosion or otherwise sent off your feet.) This is super neat because the attachment falls from your hand and uses Karma to tumble away on the ground. So, while you are getting tossed away by a concussive blast, your weapon goes too, but likely will not end up in exactly the same place as you. Sometimes it will land near you, and if you manage to stagger back to your feet you can just grab it and get back into the action, other times it will have gone over a railing into some lava, or landed up on a ledge where you can't reach it so you'll have to find another.

I played a mutator at one point that made you drop your weapon if you got hurt badly, but I didn't like it very much compared to this. In that one, you'd be running along and suddenly your weapon would change. (when you got hit) That I found very frustrating and all around not very fun. In my mod, the feel is much different, since you're sent flying anyway and will be lucky to even survive.

Speaking of which, I'm not really sure what I should do about the deaths. Right now, if you're using the first person camera, the camera follows your head when you're ragdolling. (Some internal adjustments are done to prevent you from seeing clipping should your head end up through a wall or something.) This is quite nifty actually. The same thing happens when you die. My first thoughts were when I implemented it, that it's very reminiscent of DOOM. :P

Anyways, when you are sent ragdolling, it's basically the same regardless of whether you're dead or just severely wounded. I'm not sure if this is good or bad. The only way you can really tell which it is is if you're dead, you can respawn by clicking fire, whereas if you're just severely wounded, clicking fire does nothing until you are back up. Actually, if you have a secondary weapon you can draw your secondary while you lie on the ground and can sort of half-decently shoot it. Very nifty. Anyways, the other obvious way to tell, of course, is that if you aren't dead you'll claw your way back to your feet after a short time spent wounded. I'm not sure if I should make a way to easily tell between being dead and just being wounded.

I've been making lots of eye-candy lately instead of doing "real" programming, and I'm quite proud of the results. (As you can probrably tell by the amount of rambling about this cool feature and that :P) The final part I've made that I also think is super cool, is loads of blood and a more-or-less realistic "combat inspired blood distribution." :P

Basically, when you are wounded by different things, different stuff can happen. This can be custom scripted by modellers and skinners, or they could use one of the default types. It's kind of like the species code.. only a lot better, because that just defines gibs and blood and stuff. This allows you to script responses to different types of attack. For instance, if a Terran is shot and the bullet penetrates his body and comes out the other side (did I mention I made nifty ballistics and penetration calculations :D) blood sprays from his backside. (and he generally dies) These blood droplets then fly through the air eventually landing somewhere. This means A) if you have a decent framerate you can see the blood spray from the body before it gets smeared all over a wall, and B) the blood is patterned on the wall depending on the angle of the hit and such. Shooting a person above you tends to cause blood to spray upwards and lightly coat an area, while shooting someone below you tends to create a dense splatter on the floor some distance behind them. Other damage types have different responses, for instance impact damage (taken from falling too far, hitting something too fast, getting hit by a car, etc.) leave a bloody mark where you impacted, but only if the impact was severe, or the person was already heavily wounded to begin with. If a heavily wounded terran is ragdolled and slides down a ramp or stairs, he'll leave a smeared trail of blood wherever he slides.

All in all I'm very excited about it.

O-GL: Good work Foxpaw. I agree your pathfinding is fine and that the bots really need to change their path to pickup their weapon first then, remember who they are fighting also .... You should do a "stat all" and see how much time your code saves. I find the UT2003 bots use too much processing power as they are now and its hard to play a big botmatch with say, 16 bots.

On the Karma Ragdoll thing, are you still using the crouch thing to get back up? What happens with the head camera when the ragdoll falls face down? Cant ppl just look at their health to see if they are still alive, and when they are dead the hud will be gone?

I like your blood effects ... especially if they are easy to apply (don't expect modellers to touch code). Oh, yea, you dont happen to know where in the Unreal Source the code is for destroying certain ragdoll parts/limbs do ya? I can't seem to find it :(.

Foxpaw: Ah, your camera follows the ragdoll by location only - otherwise, you end up seeing "outide the world" . The rotation of the camera continues to face the same direction as you are "aiming," except of course you can't change your aim when you are ragdolled. For the time being there isn't much of a HUD, but I reckon I'll add one eventually. There's an ammo display, and some crude text messages to show what weapons and junk you're carrying, but no health display yet.

As for the dismembering code, I'm not surprised that you would have difficulty finding it. I tried a while ago and it took me a while to figure out how it was done. It's hard to spot because it's spread out over a number of functions.

Anyways, the long and the short of it is, there's this array called HitFX that stores a bunch of information about damage the pawn has taken. Eventually, ProcessHitFX gets called and it iterates through the stored hits, and if the element of HitFX in questions has bSever true, then it spawns the appropriate gib and calls "HideBone" on the bone. Note that the gibs are separate meshes that have been made to look like severed parts of the original ragdoll, but are not really.

HideBone is a function declared just below that. It's pretty simple, it basically just sets the bone's scale (skeletal equivalient of drawscale) to 0, effectively meaning it doesn't get rendered.

So basically, the "severing" of a bone just involves setting the bone's scale to 0 and spawning an appropriate gib. DoDamageFX in xPawn seems to be the function to call if you want to force dismemberment on something. (Passing a damagetype with bAlwaysSever)

December 25, 2003

Got Homeworld 2 and Unreal II for Christmas. Programming is unofficially suspended until I finish/get bored of both. :D

MythOpus: I was so dissapointed of Unreal 2 :( Homeworld 2 on the other hand *almost* owns ;)

Foxpaw: Well, I just finished Unreal 2. I didn't think it was too bad, but it was kind of short compared to many FPS games. Also, I think they REALLY cut corners to improve performance. Ragdolls don't last very long, decals/projectors from damage FX are sparse and also fade out very quickly. Plus, there was environment maps on pretty much everything - even people's skins had an environment map on them - seems a bit excessive. Having said that, the game does have a good bit of polish that was lacking in UT2003, and the story was consistent throughout.

Also, a perennial problem in FPS games, the first mission was very well done, later missions were less so. The first mission was very Aliens versus Predator 2-like in atmosphere, which I think was good. The later missions I felt were kind of lacking. The robot lair place, inhabited by hovering robots, apparently still had need of walkways and bridges. On avalon, the Skaarj were very easy, what with them always trying to close with you you could easily hose them down with the flamethrower or shotgun. The very last mission on the Dorian Gray was kind of neat, but way too easy since right near the start you get that green gravity gun thing that kills anything that the projectile even comes close. :/

MythOpus: Overall, It was a pretty good game.. but they did cut a LOT of corners. I agree with what you said about the levels and I only encountered the skaarj what, 3-4 times in the game? Come on ! The storyline was okay... up until the last mission. I didn't like that one bit... It was just so... not Unreal. That weapon too. The last one you get, doesn't it look familiar... say.. from Half Life O_o? I think they could have done much better and it seemed that they go really bored with the project and didn't put as much effort at the end as when they started :( Major Bummer....

MythOpus: Quick question, where can I find your 'work' ?

Foxpaw: So far, just on my hard drive. I don't think it's quite ready to be released to anyone yet.

MythOpus: Bummer... Well keep up the good work :tup:

January 2nd, 2004

I've been making various visual improvements, but I'm still snagged on the ~60,000 UU maximum draw distance. I tried scaling everything down to allieviate this, but that caused all hell to break loose when things got too small and the loss of precision with integers started causing visual problems that were even worse. Plus, scaling everything down was going to force me to remove one of the cooler features of my mod, (the ability to walk around inside the ship while in flight or landed) which I didn't really want to do. So, for the time being things remain invisible at moderately long distances. I also tried having "stand-ins" for things that were far away that would appear at 60,000 UUs away and scale appropriately to make them look farther away, but I scrapped that when I realized that that would not look good if a player was using a stereoscopic display of any sort.

January 3rd, 2004

I decided to make the stand-in actors anyway. This won't look right to anyone using a stereoscopic display, but I'll have to settle for the time being. It will in fact look quite bizarre to them because the stand-ins are relatively close to the camera. (This is to prevent them being obscured by fog.)

Fortunately, the appropriate placement and drawscale was easy - it's a straight linear scaling. IE, something twice as far is half the size on-screen. This seems only logical, but some games use a non-linear scaling so you can make out details better at long distances. (Homeworld is an ideal example of this.. the difference in size between ships is much lesser when zoomed out.) Anyways, this made it very easy to make a seamless transition from stand-in the the real thing and vice versa. There's a few visual glitches that would be difficult if not near impossible to rectify - for like if a missile impacts a capital ship, the explosion will not appear on the stand-in. You could fix that by giving EVERYTHING a stand-in, which would be easy enough to do, but I don't want to have stand-ins for stuff that's REALLY far away. I tried setting everything to use them, but ended up with annoying glittering pixels of fighters that were really far away. I guess it might look okay at, say 65000x40000 resolution though. :P

This situation normally wouldn't be all that bad, if not for the great differences in size of different ships. That was something that kind of bugged me in Homeworld - the fighters were approaching the size of the frigates. The frigates had little windows painted on them to show that they were real big, but then a fighter would fly by with a cockpit about a dozen frigate windows long. Also the asteroids were pretty puny compared to the size of the ships. I've never visited one, but it's my understanding that asteroids are generally pretty big compared to pretty much anything man-made. Unless maybe you count the great wall of China. I hear it's pretty big. Anyways, my ships have appropriate scaling, so the fighters are relatively tiny compared to carriers. (Though the difference in scale is not as much as I would like, they also have to be scaled appropriately to persons on the ground, and the Unreal Engine does have a maximum map size, ya know. ;))

Also, I got rid of the environment maps on ships. They looked fancy in the editor, but looked crappy in-game. When it's dark, (as it tends to be in deep space) the environment map (which doesn't appear to be affected much by changes in light level) becomes much brighter than the diffuse texture, and ends up looking lousy. That's the grey with white polka dots you see in the screenshots I posted earlier. Now that the environment map is gone, the ships look a lot better. (Well, not the carriers, because they didn't have environment maps. Only player ships had the crappy environment maps on them.) Speaking of which, I'll post new screenshots soon. I got a new computer, and I'm doing all my programming on that one now, but that one isn't connected to the internet, so I have to lug a hard drive in between computers to transfer files and such. Or I guess I could compress them and use a floppy disk. I don't like floppy disks though.

MythOpus: Get a CD-RW drive and get a CD-W and burn the code stuff onto it, move it onto the other HD and then delete the files on the CD-W afterwards. I think you may need too CD-RW drives though, I forget :)

Foxpaw: Unfortunately, I tried that but it didn't work for me. At least, it didn't work when I tried to use DirectCD to copy stuff onto a CD to take to my programming/gaming machine. The programming/gaming machine might be able to transfer stuff to the internet-connected machine via that method though. I'll have to try that.

O-GL: Whats the specks0rz of your new b0xs0rz? Why dont u buy a $30 switch? But that would destroy your setup I guess ... internet is so evil when trying to do work!

Foxpaw: Well, it's a 2.4Gig with 512 Megs of DDR Ram. The only real catch is it has some crappy video card made by Intel in it. As far as the internet goes, I don't have it hooked up but I probrably could do so easily. The two computers are at opposite ends of the house, but I believe that my ISP will supply more cable modems for relatively cheap. I haven't really looked into it yet though.

January 6th, 2004

Heuristastic! Plus, I curse integers again. In lieu of actual knowledge of how to do a coordinate rotation on a Euler angle using another Euler angle, I implemented a theoretically slow heuristic instead. It's not actually noticeably slow and the only time it ever gets called is when a ship is loaded, built, or otherwise spawned. Even so, it runs surprisingly fast considering that it's a nested loop with numerous comparisons and operations taking place. Unfortuantely, due to some wacky loss of precision with integers, it's only accurate to within one unreal rotation unit in the roll direction, but hey, that's still 99.999999999999644728632119949907% accurate, according to notepad, which is probrably better far tighter tolerance than the human designer is going to be able to manage anyway.

I also came up with a scheme to have all ships carry liquid ballast. I also have a feeling I wrote this already, but maybe not. Anyways, the liquid ballast can be pumped around the ship (this is handled automatically) to keep the center of mass, well.. centered. I decided I needed something like this because once your ships starts taking heavy fire and a good chunk of it is absent, the center of mass of your ship shifts way off the center and once it shifts laterally past your thrusters, you're going nowhere except in a circle. Once you start getting close to that point you can only fly by shifting the engine balance all the way to one side and using all your vector exhaust to stay straight. This makes it extremely difficult to aim and the AI can't handle it at all. (The AI compensation heuristic only kicks in once it's half-decently lined up.) Granted, by the time you've lost that much of your ship there's not much you can do, since most of your systems are probrably offline by then, but still... Anways, the problem I've been having with the ballast is twofold - number one, more ballast is needed to maintain stability than I had realised. This is bad because it roughly doubles the weight of your ship. Also, there's a slight problem in that the ballast adds a great deal of mass to the ship, which slows it down. Fast "flag carrier" ships may prefer no ballast for maximum speed, and sacrifice the stability instead. Also, placing the ballast closer to the outside of the ship makes more of an impact with less added mass. This is good. However, the outermost parts of the ship are liable to be the first ones destroyed, so keeping your ballast at the end of your wings has it's own downside there, too. However, to keep it more central, where it will be safer, requires more mass to be added, reducing the potential speed of your craft...

In other news, the AI now has slightly more of a clue of what to do. I've been developing so far under the premise of the "carrier attack" gametype, because it offers some of everything, so all of the code can be tested within the same level and gametype, which is good because it spares me from making more levels and gametypes just to test different features. Anyways, the AI now has the wit to attack the enemy carrier, as well as engaging enemy pilots en route to the friendly carrier. However, they don't yet have the brains to avoid ramming into things. Generally, that's not a problem, but the AI from one carrier has a tendancy to crash inside the hangar of it's carrier as it launches. This will be improved in the near future. And new screenshots are coming soon. Soon! They're still on the other computer.

And then some!

I wrote some stuff for collision avoidance. Unfortunately, it turned out to be rediculously slow. Initially I was using traces to detect nearby objects. You can't just take the difference in location between two objects because the location of a large ship may be a considerable distance from the surface of that ship. So I was using traces. This was slow. I figured it was because of the traces. I found out traces aren't that slow after all.

I substituted it for what seemed ingenious. I'd just use a dummy actor with cylinder collision, set it's location to the location of the ship detecting nearby objects, and go through it's touchingactors array. Seems simple and fast. It wasn't.

I was quite shocked to find that this ran at about a third of the speed of the trace method. Why, I have no plausable explanation. I did some optimization but still only got it down to taking about twice the time of the trace method. I don't like either method, however, because the trace method is too slow to use with more than about 8 bots at a time, and the dummy actor method is even slower. To remedy this, I have a couple of pontential solutions. I can reduce the extents of the traces used to detect nearby objects. A zero-extent trace would be ideal but if the extents are too small the ships think they have a clear path when they actually do not - obviously a bad thing. The extents have to be generous because there is no reasonably fast way to determine the extents of a static mesh from within unrealscript. Therefore, there's no real way to determine the extents you need to use except to have a generous preset amount that should cover the majority of ships that that particular AI will be flying.

O-GL: Holy crap dude, how fast do you work lol? The reason why the cylinder method is probably working so slow is because it is colliding with the Karma collision hull. If the cylinder actor has bCollideActors, bBlockActors, or bBlockPlayers=true and you set its location inside a Karma hull, then you will get a major fps drop. If you did "if (setlocation(predictedLocationAtTimeX))" that could work quite well if you were finding collsion between world geometry. But I would not recommend that method for collision between karma actors because setting a cylinders location somewhere in a Karma hull is horrendously slow. You'd have to use traces but they are quite slow, especially if you use more than one.

Foxpaw: Hmm, I did suspect it was something relating to collisions, since using Clock and Unclock I traced the only time consuming statement to be a single SetLocation call, which was taking 5-6ms every time it was called. I'm pretty sure you can manually turn off Karma collision between any two given Karma objects, but I'll have to try it and find out if I can disable the collision between Karma objects and non-Karma objects. Also I'll have to find out if that's going to even speed things up much: the cylinder is probrably still going to collide with other Karma objects, (other stuff that needs to be avoided) but maybe it won't be so bad if the cylinder doesn't have it's origin within a Karma actor.

O-GL: You could do some extra work and make a rough cylinder for the models, and then turn off Karma collision and turn on cylinder collision to test if the two models are colliding. It won't be accurate because the cylinder probably wont fit the models, but I guess you just want a rough guess on when to stop. Here's a rough demonstration of a function inside each karma class that you want to test for collision:

// Turns off karma collision and turns on cylinder collision
simulated function TurnOnCylinderCollision()
{
   SetCollision( false, false, false );
   aDummyActor.SetCollisionSize(CollisionRadius, CollisionHeight);
   aDummyActor.SetCollision( true, true, true );
   aDummyActor.SetLocation(Location);
}

Another problem is you need a list of all the objects that are colliding so you can call this function in each of them. I use ControllerList because my colliding actors are pawns, but your case may be different. After you've found any collisions and notified the correct objects of what to do, then you can just do the opposite (TurnOffCylinderCollision) after your tests have finished and your karma collision won't even know it happened :D.

Foxpaw: I don't quite see what you are proposing. I sort of do - but not quite. I set all karma objects to non-colliding, then just have cylinder collision to approximate the Karma collision and check the collision between the cylinders? That may just be crazy enough to work, :D but it seems like it might be expensive in terms of switching over all the collisions, as well as maintaining the extra actors for the cylinder collision - as there may be hundreds of Karma simulated actors in play at any given time.

As a sidenote, turning off collision with the ship attempting to find out if it's colliding or not had no effect. KDisableCollision/KEnableCollision apparently only works when both actors are Karma simulated.

O-GL: Sorry, I was kinda tired and thinking about 3 other uscript problems when I wrote that :P. I have no idea how to make a cylinder the right size, unless you know the size of your Karma actors in UU and good at guessing. Maybe there's a better solution?

Jaunary 9th, 2004

I made a super-fancy skybox substitute. Screenshots are coming. Honest! :P I don't really like the way it looks, in that it isn't black so it doesn't look like space to me. However, it is much fancier from a technological standpoint, and probrably draws faster. I was stuck for a way to draw stuff "under" the world, which could then show through by making a HOM effect deliberately. I didn't have success with that, but then it hit me: the skybox gets drawn first, then the world gets drawn on top of it. So, I could draw stuff "under" the world by simply putting a static mesh sheet in the skybox that would automatically move and rotate so it was always facing the camera. Unfortunately, it's not perfect. There's a slight visual glitch that I'm not sure how I can fix, if I can fix it at all. I didn't want to use a scriptedtexture to update the stuff on the sheet, (since obviously it has to look different when you look differnt directions) because that would sacrifice compatibility with Mac and Linux, which I didn't really want to do if I could avoid it. The glitch is caused by a Gimbal Lock issue which may be difficult to resolve. I'll make a scriptedtexture version for DirectX users, which will be free of the visual glitch. I'll post the screenshots up soon, on account of I have to go to work now, but maybe when I get back. Then people can decide for themselves.

The new screenshots also show off a fugly ship I made. More of a modification of an existing ship. My interceptors were getting chewed up by the enemy carrier and didn't really ahve anything that could cause appreciable damage to it, so rather than go to all the trouble of implementing some more weapon types, I just hopped into the vehicle editor and tacked on 5 of the biggest anti-fighter cannons and another generator to power the whole mess. This was all done without leaving the game, mind you, so hopefully the new screenshots will give more of an idea as to the vehicle design part. Also included are some shots showing some more action. Coming soon!

January 11th, 2004

Quite the frustrating day. I don't know why I didn't think of it before, but I realized that if I moved the "safe distance" from ships out of the ship AI and into the actual ship components, I could make an quasi-trace in Unrealscript. It actually worked quite well, and very fast too. Because I wasn't constrained to the "upright cylinder" collision, I was able to make a custom cylinder collision, where the cylinder is essentially the length of the trace, while the radius is the extents of it. This worked surprisingly well, and also allowed me to compensate for the movement of other ships (no use going around if it's moving out of your way already. Formerly there was a "right of way" system and the other ship was assumed to be getting out of your way if you had the right of way.) as well as compensating for the movement of the ship in question. (Fast moving ships are going to need to predict collision farther in advance than slower moving ships)

Unfortunately, this improved collision prediction system showed a big failing in the avoidance system, specifically that the ships would get kind of antsy if other ships were around, but not moving in such a way that a collision was likely. (IE flying in formation) These ships weren't picked up at all by the old system, so the ships didn't get antsy about it, but that wasn't really that bad, since those ships are virtually never on an actual collision course. This is what I spent most of the day trying to fix.

First, I figured I could use something like the code the fighters use to break off an attack run on a capital ship when they get too close. (This is not related to the collision avoidance, because the range at which they break off and such is not collision-related - it's based on the ship's estimated combat capabilities, as well as those of the target. IE get in close to carriers who can't defend themselves well, stay away from gunships, stay at long range and harrass large capital ships, etc.) Anyways, that didn't pan out, because the collision avoidance operates at much closer ranges and so that sort of gentle course alteration didn't work very well. Making it just plain steeper didn't work well, as the fighters would attempt to make a tight turn and their momentum would carry them into the thing they were trying to avoid.

Secondly, I remembered some stuff from calculus about the surface of a circle and so on. I figured that, similarly, I could find the point on a sphere that was the minimum "safe" distance away from the carrier, and the portion of the circumference that represented the distance the fighter would travel in the time it was predicting ahead by. This didn't work. The fighters overshot the predicted point, then tried to do a 180 to correct, and hit the carrier.

After fiddling with that for a little while, I came up with another idea: I could set the "predicted point" some distance ahead of the fighter: basically, where the fighter is expected to be a second (or some arbitrary amount of time) from now. Then, I could have large objects "push" on the predicted points. So, if you could imagine, it's like magnets of the same polarity, the large objects "push" the predicted endpoint away from the ship. Then, the fighter aims for the adjusted predicted point. This seems to work good and produces a very smoothe avoidance.

After I got that taken care of I've been trying to streamline everything. I think the core functionality is all in now, so there shouldn't be any other major loads placed on the system from now on. (I hope.) Unfortunately, the game can get kind of slow when you get large numbers of ships flying around. I'm not sure where the time is being taken, however, so I've been taking various measurements to try to find the bottleneck. I've been hoping I'll find one horribe error I've made somewhere that's sucking up all the cycles, but more likely it's distributed and can't be easily fixed like that. It's a bit perplexing, however, as there seems to be a great deal of time unaccounted for. The timing measurements that I took don't add up to anywhere near the reported times in stat all. Earlier, it was reporting about 10ms script processing per ship I added to the world. However, my timer only found about 6 to 8 of those milliseconds.

Even 6 to 8 milliseconds per ship, however, is much higher than I want, since I want the ability to have lots of fighter craft. Unfortunately, the code all appears to be pretty much optimal, though I did manage to squeeze 0.05 ms per component out of the resource model. (energy, fuel, ammo, and such) The old model had each component on a ship do it's own resourcing and go through a modest nested loop to compute resource distribution. The new method is slightly different, but theoretically should execute at nearly the same rate: instead of each component doing it's own resourcing with a nested loop, I made only one component on the ship do the resourcing, and it uses a doubly nested loop. So, basically:

Called once per component:

  • For each component...
    • Do resourcing between Self and j

became:

  • For each component...
    • For each component...
      • Do resourcing between j and k.

Theoretically these should be almost exactly the same. The only reason I was changing it was because there was a single redundant line that only needed to get called once a tick, but was getting called once a component. However, that call was cached anyway, so it was akin to an assignment. But, I was desparate. I was pleasantly shocked to find that the new method resulted in a 25% decrease in execution time! (0.2ms per component to 0.15ms per component) This, coupled with other information gleaned during the earlier timings, suggests to me that there is a considerable amount of overhead involved in every Unrealscript function call. (Rudimentary tests suggest about 0.009ms per function call, which doesn't seem like much, but can add up if you use recursion or function calls in loops.)

To try to gain some speed I've been swapping some of the more time-critical code from Object Oriented Programming to Procedural Programming. So far the results have been favourable, from a performance standpoint anyway. It does sacrifice some readability. I've also been caching anything that gets called even half-ways frequently. (Center of Mass, master component, (the one that administers the resource model) nearest controller. (for ships with more than one pilot/gunner/whatever, this points to the component that houses the controls for this component. On fighters this is generally the cockpit everywhere, larger ships might have a turret controlling some pieces, while the cockpit controls others..) I also cached a dynamic array of related components, which saves me from doing the recursion to find them all as frequently. (ship parts that are a part of the ship in question)

All these improvements have brought the speed to the point that you could concievably have a moderate sized game, by UT bot count standards anyway, depending on your machine and your desired framerate, anyway. I just know that there's still something hiding in the code gobbling up cycles, because I made a test ship that was light a freighter, with just a big stack of bulkheads and no engines or weapons (they time okay, but I strongly suspect they are the culprit) and I could make like 20 of them and still have a decent framerate. So I know that it's not Karma going slow, nor is it rendering, nor is it a problem at the heart of my vehicle code. I just know it's in there somewhere... and I need to make it go faster, since I want to have each side able to have at least a couple dozen fighters.

January 11th, 2003

Apparently, using SetLocation is a fairly costly operation, even on non-colliding invisible things that can't affect anything as a result of moving. Hmmm. Turns out this was causing a slowdown in weapons and engines, since I always had the "firecontroller" (the business portion of the weapon) move to the point where the projectile/beam/whatever should come out of, and this needs to be constantly updated to stay in sync with a weapon that's likely also moving. This was costing many a cycle. I fixed it (a tad bit hackily) by simply changing all references to the firecontroller's location/rotation to "effectivelocation/effectiverotation", and the two "effective" variables are set to the location/rotation where weapons fire should come from, instead of moving the actual firecontroller. This way is much faster. In theory. The framerate felt slower, even though it was actually faster. It's probrably just me. The fighters also started ramming into things again, this was because I forgot to change a reference in the AI to the firecontroller's location and rotation. (It uses this to line up it's weapons) I remembered that while I was writing the above.

Mortal Monkey:

The weapons then does a series of successive traces, and every time it hits something, it figures out whether its hard or soft, and how thick it is.

Would it not be benificial to use ForEach TraceActors instead of a normal Trace? I thought I read somewhere that it's just as fast.

Foxpaw: Ah, that won't achieve the desired effect because that will just give you a list of things that were hit and where - there's no way to find the point at which the trace stops penetrating using that method. Also, the things that get penetrated (and how deeply) alter the ballistics of the bullet, so, you can't specify an "endtrace" right off the start like that. You are correct, though, that TraceActors would be a faster method, if I had a way to find the depth penetrated.

January 14th, 2004

I cooked up a scheme while I was at university today, to do faster coordinate rotations. I was thinking about how games use trig tables so they can just look up the result very quickly. Then I thought, why not have a coordinate rotation table? I could just have an array with 65536 cubed elements, and easily specify the rotation as an index into the array and get the result! Ingenious! Unfortunately, the lousy compiler won't let me make an array with 281474976710656 elements. It wouldn't even let me nest structs with arrays in them, and then make arrays of those structs, etc. (the compiler hung when I tried) I may (maybe) try doing it with dynamic arrays, but they might not be as fast because they probrably won't get a contiguous block of 3 or 4 megs in RAM so it'd be skipping around a lot.

The fun never stops!

I was having a slight problem with Karma things "exploding" from trying to rotate too fast. This was only really a problem with the bots, though, because a human can't really turn fast enough for it to be a problem, unless they are getting really low framerates. (Reason's being they can't move the mouse fast enough to turn that fast, and even if they could, they couldn't see where they were trying to turn to since you can't see the rotation cursor thingy once it's past about 45 degress off the rotation of the ship. (though with practice you can wing it around and have it stop pretty much where you wanted it to) The bots however, gleefully do a 180 in their desired direction on a fairly regular basis, such as when turning around for another attack run on a carrier. This was causing a big problem. I tried a couple of fancy solutions, like storing the most recent "good" rigid body state, and restoring it if imminent Karma breakdown was detected, but this didn't work too good. It just resulted in the ship being reset to the instant before Karma broke down, and since it was under virtually identical conditions, it basically entered a loop of breaking down and being restored every couple of ticks.

So, I decided to prevent the problem in the first place by smoothing the rotation of the AI. Basically, the AI's "aim" is metered out to the vehicle over a few ticks instead of giving it an instantaneous change in direction. I tried making them just have a maxmimum 90 degree offset in their "aim," but that didn't work very good, and used more cycles than this way. The new way is super simple and surprisingly effective. Basically, every tick, the vehicle's "aim" and the vehicle's AI's "aim" are averaged. Now, you might say, "every tick you average them? Why, my good man, that will cause synchronization issues on different machines on a network! Surely such methods are folly!" But they aren't. It's framerate dependant for a reason: because the Karma explosion problem is. The slower the framerate, the gentler you have to be, (keep in mind these are futuristic space fighters, doing a 180 in 0.2 seconds is "gentle") and the slower framerate results in less averages and thus a smoother motion. Besides, the AI is only simulated on the server side anyway, and the clients get the vehicle's updated aim, so they'll still be synchronized. So put that in your pipe and smoke it! :P

I've also been trying to eliminate the visual glitch I was having with the backdrops. Basically it's like, if you can imagine a perfect sphere with the backdrop as it's texture, and you're looking at it from the inside. Because it's a perfect sphere, you get the same effect by panning and rotating the 2D texture and can forego all triangles, which is good, because a perfect sphere would require an infinite number of triangles, which could really bog down the framerate. ;)

However, it's trickier than one might think: It has to pan seamlessly, which means you have to have a seamless wraparound. This is easy enough If your image tiles. In theory. It's actually not so simple. Horizontally, it tiles. That's simple enough. Vertically, it doesn't. It sort of "collapses." Remember this is supposed to be the inside of a perfect sphere, and if you try to fold a piece of paper into a sphere you'll find that one axis tiles, and the other end you just kind of have to scrunch it all together to fit. The inspiration and pioneer of this technique, Homeworld, had it easy. They just gimbal locked at two poles so they never had that problem - because you can't roll when nearly level or "yaw" when pitched all the way up or down, they can just draw it un-scrunched and it still looks okay. Of course, if you were to measure things the view is actually quite distored in places using that cop-out, but you don't really notice, unless you were to bust out a ruler, then maybe you could see that when pitched all the way up or down the scale doesn't agree at different angles.. but I digress.

Point is, I want to use something like the system they use, only better, because I can't have gimbal lock, for obvious reasons. It's very important that the background pan and rotate realistically, because my experience while developing the backdrop system so far has shown me that the background is very important to your sense of direction. When the backdrop was just fixed and didn't pan or anything, I couldn't tell where I was going. When it was going backwards, I could never accurately judge how far to turn, and so on. Point is, it has to be perfect! I want to avoid using a pseudo-skybox approach though, because I want to keep it entirely 2D, because it'll look better.

O-GL: 2D might look better, but it wont move better if its scrolling along in 3d in front of a camera. Thats what polygons are for. Plus, if you are drawing that 2D picture to the canvas, that would probably be very slow.

Foxpaw: Actually, I'm not drawing it to the canvas (I would have, but I couldn't find a way to, so instead I just hacked it into a custom Material and have it on a flat static mesh that moves so it's always in front of the camera, in the skybox. It does scroll a little bit unusually, but I was hoping that there was a solution. Unfortunately, looking at the Homeworld source it looks as though they actually draw their's using polygons too, but they do a couple low-level things with the rendering to sort of "unroll" a sphere as it's drawn. Unfortunately, I don't believe that there's any way for me to do that in Unrealscript. :( So for the time being the backdrop system may have to sit on the back-burner.

January 15th, 2004

I implemented a nifty system to help the bots make more intelligent aiming decisions. I had the idea a while ago but I was surprised at how elegant it turned out. It won't get called alot, it'll get cached, and it's not processing intensive anyway, so I can afford to make it elegant. Basically, every ship is issued a "classification," which, interestingly enough, is a reference to a class. These classes form a heirarchy which is very handy. I was able to encapsulate virtually everything in the base classification class as well.

The solution turned out really good. Each "class" of vehicle/ship has two things: a rate function, and a list of subclasses in the defaultproperties. Interestingly enough, "subclasses" don't actually have to be a subclass, allowing for a non-linear descent down the "class tree."

Basically, a function is called on the base class, which iterates through it's list of subclasses, and calls the Rate function of each. Rate returns a float, and whichever subclass returned the highest value get's a function called in it, which does the same thing as this just did. (only, of course, iterating though that subclasses subclass list instead of the base classes list.)

Rate is a simple static function that gets overridden in each class. It takes a struct as input, (for extensibility) which contains a considerable amount of statistical information about the ship in question. (Firepower, armor, manueverability, mass, resource processing capabilities, sensor range, resource storage abilities, etc.) The rate function just has to return some floating point value to indicate how closely the vehicle matches this particular subclass. For instance, let's say the ship in question was a superiority fighter. The process might go something like this:

The Base Class calls Rate in C_StrikeCraft, C_Capital, and C_Station. The vehicle has a relatively low mass, so C_StrikeCraft returns a high value. C_Station returns high if the vehicle passed to it is nearly immobile, which is not the case, so it returns a low value. C_Capital is looking for high mass, so returns a low value.

C_StrikeCraft now iterates through it's list: C_Fighter, C_Gunship, C_Transport. The fighter has no turrets, and a relatively high manueverability compared to it's weapons, so C_Gunship returns a low value. The fighter doesn't have much storage, but it has a fair bit of fuel and energy considering it's size, so C_Transport returns a moderate value. The fighter is very agile, however, so C_Fighter returns a high value.

C_Fighter now iterates through it's list: C_SuperiorityFighter, C_Bomber, C_Interceptor. C_Interceptor likes manueverable craft with lots of weapons, but weapons take priority. Since the fighter in question is more manueverable than it is heavily armed, C_Interceptor returns a moderately high value. C_Bomber heavily favors weapons over manueverability. Because it wants LOTS of firepower, and the fighter only has a moderate amount, it returns a relatively low value. The high manueverability helps the rating from C_Bomber, but not by alot. C_SuperiorityFighter focuses mainly on manueverability. The more manueverable/faster the vehicle in question is, the higher the rating from C_SuperiorityFighter. C_SuperiorityFighter also gives points for weapons, but not as much as C_Interceptor. C_SuperiorityFighter returns a high value because the vehicle is question has lots of manueverability.

At this point, C_SuperiorityFighter would go through it's subclasses, if it had any, which it doesn't. So instead it just returns itself back up the chain to give the eventual result.

That was a bit of an example, but I was having difficulty putting it into words. One advantage of this system is it's easily extendable, and it's heirarchial nature allows for "IsA"-like calls. For instance, if a hostile ship was approaching a transport of some kind, it might do something like:

if ( IsVehicleClass( Incoming, class'C_Fighter' ) )
{
  // We can't outrun it. Is it harmless?
  if ( !IsVehicleClass( Incoming, class'C_Transport' ) )
  {
    // We won't be able to outrun a fighter or a gunship. Best
    // to head for the nearest friendly units and call for
    // backup.
  }
} else ( IsVehicleClass( Incoming, class'C_Capital' ) )
{
  // We can outrun it. Fly directly away from Incoming.
}

In this way it doesn't need to check through the myriad of types, and doesn't need to bother with whether an incoming fighter is a superiority fighter, a bomber, or an interceptor. Similarly, if it's a capital ship, it's a fairly safe bet we can get away. There's no sense bothing which what class of capital ship it is, or whether it's armed with anti-fighter or anti-capital ship weaponry, etcetera.

Another big advantage is it allows you to approximate the role of any ship. Since a player can design a ship in any style and with any combination of armament, etc. they please, the AI needs some way to know what's dangerous to it, what it's dangerous to, etcetera. This way, the AI can transparently pick targets intelligently. Superiority fighters will engage enemy fighters, interceptors will engage bombers, and bombers will engage capital ships, without the user having to specify to the ship or AI what sort of ship it's piloting and what it should do with it.

I had this idea sitting around for a while, but I was getting kind of annoyed when the interceptors I built almost always went straight for the enemy carrier, ignoring enemy bombers launching from the enemy carrier.

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In