Tank Tactics -- getting distracted by bells and whistles

posted in ferrous' Journal
Published August 20, 2015
Advertisement
Okay, so I have to admit, I dig the WarThunder Ground forces kill cam. And I'm attempting a rough duplication of it here. I'm learning a lot about shaders, rendering things always on top, and about the Animation class in Unity. Though I was a little disappointed by swapping materials through animation, this seemed broken, and I don't know why, other than in code, you have to swap the entire material array, and not just an entry at a time. (If it's broken, they shouldn't expose it...)

And I still don't like what I have here. I like the bullet outline, that's handy, it also always renders on top. I like the glow effect, but I don't like how it's the entire hull, which is what's getting penetrated here, i'd rather just show the surface portion that was penetrated. I might have to see if I can dig into all the vertices and do something, or maybe just give up and play a particle effect.

Anyway, I also fixed my turret turning slightly, i'm casting a ray from the muzzle to the target and setting the rotations on the turret that way, but introduced more bugs with it, silly PzII main gun being off center turret threw off my math. I'll have to do something there, maybe even mild IK. Though I'm tempted to cheat and just move to first person mode. I still need to finish remapping the collision texture I use. I've colored about 1/3 of it, and need to go in and assign armor values for the rest. It's boring work though. I also need to clean up the end of the bullet cam, it leaves things in a messy state, and do something about the timescale I have currently set. Ideally it would do some lerping between start and target. I could just get rid of gravity entirely and do a raycast to see what gets hit, or fire a phantom bullet first at full speed to see what I hit, then use an AnimationCurve to adjust the timescale as the bullet travels.

And Unity Physics never fails to disappoint, it seems to do all sorts of weirdness. Okay, I get not handling a projectile that's travelling at 1000 m/s, but even after lowering that to 250 m/s and lowering the gravity on my shell by the 1/4 as well, in a sort of pseudo time scaling, I still get strange collision behavior. And upping the solver iteration count and lowering the Fixed Timestep doesn't completely alleviate it either, though it does make it better. I've already marked the shell as Continous and tried both Extrapolate and Interpolate.


And then there's the setting to think about. I'm trying to justify WWII tanks and some sort of X-Com or Pirates like gameplay, with the player accepting missions for different factions and controlling a small hodge podge force of two tank platoons, with possibly some support infantry, if I can swing it. (or i could try to toss the WWII trappings)
1 likes 7 comments

Comments

Gian-Reto

Having been working on a similar vehicle based shooter-style game prototype which also drew a lot of inspirations from WoT/WT in Unity, I can feel your pain 100%

Expecially the physics part. Man, PhysX is such a Pain in the behind.... and while the old Unity 4 version was bad, the new one is outright broken! I don't care if it runs faster when the new wheel colliders are completly useless and non-convex mesh colliders no longer work. The new PhysX trashed my motion physics (which took many days and week to tune because even the old wheel colliders where crap) and my damage system (which relied on non-convex mesh colliders to model armour zones and module hitboxes) in one go!

My Unity 5 port is now temporary laid on ice while either uPhysics delivers their newest version or I find the courage to come up with my own pseudo-physics system.... gonna test out Unreal Engine 4 in the meantime, so the time is not wasted smile.png

Turret control was also quite a problem for me but solved that.... I even have a running autoaim system that does usable pre-aiming based on the current movement vector of the target. The off center gun of my vehicle was also a problem, but I solved that with a constant (that tell the system how much off center the gun is) and a function that decreases the influence over distance. Works flawlessly for me.

I use a secondary game object for both turret and gun, all player or autoaim input manipulates this "target" game object, and each frame the actual turret and gun work towards matching this target for rotation. No need for raycasting.

If you like I can describe my solution in more detail. Its not rocket sience, just many many hours lost trying to get it working ;)

about the projectile, if you have the physics budget for it (like, you are not trying to simulate dozens of vehicles on a small mobile chip), forget about colliders for the projectile... use raycasts. Calculate how far the projectile will fly in a frame (or use a good estimate), calculate the arc of the flightpath (or again, use a good estimate), use the latter to adjust the ray direction (so you get an approximation of the actual ballistic trajectory over many frames), and the former to decide how long your ray should be.

Let me tell you, once the formulas to calculate it are correct, your collisions will work 100% accurate... its not even that worse a hit for performance, as the rays you shoot every frame are quite short.

And yes, I tried it with up to 950 m/s muzzle velocity, works fine.

Speaking about performance, just because this was the biggest performance hog for me and I only found out after a year:

Don't INSTANCIATE and DESTROY anything. Ever. Especially not projectiles you fire out at multiple shots per second. Create your own pooling system, precreate the projectiles (as many as you need) at startup, cycle through the pool while firing, setting projectiles that hit something or reached max distance to inactive and return them to the pool to be fired again.

You will see a MASSIVE decrease in FPS loss when firing an automatic weapon this way.

Hope this helps

August 20, 2015 04:10 PM
ferrous

Thanks for the post, seems like we're working on similar things, which is cool! I'd love to hear more about your Turret control, I tried doing an offset, but I think I had an error somewhere, so I just scrapped it momentarily to continue working on other things.

I'm having a little bit less problems with wheel controllers since my tanks are not driving via physics, it's all turn based motion along a calculated path, though at some point I should animate them and have the treads move and some bounce up and down, etc, so I may have to move to a more physics driven system, though I'm going to avoid it if I can.

The shot physics have been a real pain, it's good to hear the raycast method will work as a backup, I was tempted to move to something like that. Though it's kind of sad, as isn't that what Continous / Interpolate/Extrapolate are supposed to be doing?

I've been hit by the instantiate and destroy thing on other projects, and I've actually got a whole set of bookmarks for unity performance. There's a bunch of places where there are surprising hidden costs. I can share those if you're interested.

Do you have any playable samples or video to look at of your project?

August 20, 2015 08:30 PM
Eck

X-Com? Pirates!? /swoon Those are in my top-5 games of all-time list.

I was also going to suggest trying raycast for each frame. I haven't gone too far into my combat system yet, but that's the direction I started and I haven't run into many issues. Just make sure you don't ray cast into your gun barrel or the bullet itself. Performance might be an issue, but not for my turn-based combat. :)

August 21, 2015 02:58 AM
Gian-Reto

X-Com? Pirates!? /swoon Those are in my top-5 games of all-time list.

I was also going to suggest trying raycast for each frame. I haven't gone too far into my combat system yet, but that's the direction I started and I haven't run into many issues. Just make sure you don't ray cast into your gun barrel or the bullet itself. Performance might be an issue, but not for my turn-based combat. smile.png

true about the barrel.... if you model it with colliders for physical interaction(which will give you headaches of its own because you have to test for collisions and deactivate turret control in the collision direction if you go the manual route instead of physical forces for turning your turret), or give it a damage model, you need to give the first ray some space just to be sure.

You can of course go the WoT route and have the shot leave the turret directly so you can get away with missing barrel collision in close combat, then you need to make sure the shot will either ignore the barrel damage model, or the whole damage model of your own tank.

Thanks for the post, seems like we're working on similar things, which is cool! I'd love to hear more about your Turret control, I tried doing an offset, but I think I had an error somewhere, so I just scrapped it momentarily to continue working on other things.

I'm having a little bit less problems with wheel controllers since my tanks are not driving via physics, it's all turn based motion along a calculated path, though at some point I should animate them and have the treads move and some bounce up and down, etc, so I may have to move to a more physics driven system, though I'm going to avoid it if I can.

The shot physics have been a real pain, it's good to hear the raycast method will work as a backup, I was tempted to move to something like that. Though it's kind of sad, as isn't that what Continous / Interpolate/Extrapolate are supposed to be doing?

I've been hit by the instantiate and destroy thing on other projects, and I've actually got a whole set of bookmarks for unity performance. There's a bunch of places where there are surprising hidden costs. I can share those if you're interested.

Do you have any playable samples or video to look at of your project?

Avoid physics and approximate it where you can. PhysX is a can of worms, just waiting to blow up, there is a good reason WoT developers for example shelved their physics system and developed an extremly simplified physics of their own design. Even if you think tanks lying on their backs, behaving like race cars or flying all over the place after crashing into each other is fun, even to get these kind of "wrong" physical reactions look realistic is a real pain.

PhysX, after all, is nothing but an extremly complicated hack... colleague of mine that had never dabbled with a physics engine before was SHOCKED when I told him that I could "increase the iteration count".... "so it isn't using actual physically accurate formulas"?

Well, lets just say even though we all know most things in games are smoke and mirrors, he has a point there.

On the same note, never trust collisions under high speed circumstances! As with other things, I understand there is a "precision error" on even continuos collisions, which will grow larger with higher speeds.

On the other hand, rayCast work in a different way which makes them 100% accurate even in such situations, with known limitations (straight line for example). Feel free to experiment with the colliders, I personally gave that up and removed all colliders from the bullets. Haven't regretted it.

I can see if I can get simplified excerpts from my code that might help you. On the other hand, I am always interested in things relating to performance improvements... so if you have something to share, I will gladly have a look.

Sadly all my vids are kind of old, from last year and Unity 4. I will have to set up a Youtube account at some point and start sharing some of my stuff, though it is all still very experimental and rough smile.png

August 21, 2015 07:54 AM
ferrous

Yeah, I need to setup a youtube account as well, i've been just uploading a new version of the Unity web player every so often, but with chrome auto-disabling it by default, it's becoming a less and less viable option for showing my work. My stuff is all rough as well =)

Computers do a lot of approximation, even sin and cos are approximated using taylor series, so the iteration count doesn't bother me too much. That said, I've been more impressed with other physics engines and yeah, moving away from relying on it seems like the prudent course of action. Especially since I want to do shot replays like WarT does, and adjusting the timescale doesn't seem increase how often the physics is run, so movement looks very chunky with fast moving objects. (My other option is to use my own fake timescale, which is what I have now, I had to crank it down to moving at 1/10th speed to get semi accurate results)

The last article I bookmarked about Unity and perf had to do with collections, structs and enums:

http://www.gamasutra.com/blogs/RobertZubek/20150811/250750/C_memory_and_performance_tips_for_Unity_part_2.php (the part 1 is also good)

Which I need to actually go through my pathfinding code and double check, I might be hitting some of those cases. (And the pathfinding code IS a bit of a pig, so it might be worthwhile to see if I will benefit from those)

August 21, 2015 03:46 PM
ferrous

Moving at slower than a snail's pace, but I've fixed my turret issues. I also had to temporarily turn off all of the aiming tanks colliders while doing my raycast to avoid self intersection. I wish they had a raycast function that was Physics.RayCast(ray, out hit, Colliders[] collidersToIgnore), so I didn't have to turn them off and on manually.

August 26, 2015 04:26 PM
Gian-Reto

I might be (too) late now with my code excerpt (Reallife happened, as it usually does)...

Still, here is an excerpt from my code showing the Area where I resolve the Problem with the guns placement (which is only really a problem under autoaim conditions in my game prototype, as the player else gets a crosshair that is drawn by using the guns position anyway).

.

.

.

// control the targets
if (targetLocked) {
// adjust target position to make up for target speed and direction
CalculateLeading(targetLock);

// correction needed because the gun does not sit in the middle
float distance = Vector3.Distance(horizontalTarget.position, adjustedTargetLock.transform.position);

float currentX = horizontalTarget.localEulerAngles.x;
float currentZ = horizontalTarget.localEulerAngles.z;
horizontalTarget.LookAt(adjustedTargetLock.transform);
horizontalTarget.localEulerAngles = new Vector3(currentX, horizontalTarget.localEulerAngles.y + horizontalCorrection/Mathf.Sqrt(distance), currentZ);

float currentY = verticalTarget.localEulerAngles.y;
currentZ = verticalTarget.localEulerAngles.z;
verticalTarget.LookAt(adjustedTargetLock.transform);
verticalTarget.localEulerAngles = new Vector3(verticalTarget.localEulerAngles.x-distance/mountedWeapon.getActiveMag().GetLoadedAmmo().distanceForBulletDrop, currentY, currentZ);

.

.

.

Every vehicle has a value assigned that denotes the main weapons shift to the side... using that value and the distance to the target, the code computes how much correction is needed for the Y rotation:

horizontalTarget.localEulerAngles.y + horizontalCorrection/Mathf.Sqrt(distance)

Code is horrible, I know... and don't ask for the mathematical formula used for the calculation above, it was designed "empirically" (and then tested thouroughly... it works well enough :)).

Oh, and if you are interested in the code for my leading method (that shifts the autoaim target to adjust for current target trajectory), let me know...

September 03, 2015 02:35 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement