game dev post: Weird West dissolvin’ walls

One of many things I worked on on Weird West is the hiding of walls/floors/etc between player and camera.

When I joined the project, roof-hiding and the-floors-above-you hiding were all that was in; the camera went top-down at about 80 degrees when you entered a building. I found that a bit disorienting and wanted to try to figure out a way to smoothly hide the walls, but as with my fire propagation stuff, this was complicated by the fact that a ton of levels had already been built and I didn’t want to add complexity or fixup work onto other folks’ tasks. So this is a wall-hiding system that doesn’t know what a wall is.

Walls dissolve (using TAA dither) from ankle-height up in a plumbob shape:

Initially I was just trying to math-bodge my way out of the problems that come with using a cylinder, but this is better and was a suggestion from Mike Blackney (Dead Static Drive’s solution does it). The plumbob shape (which is just two dot products multiplied together) reduces a lot of times close to the player character where bits of wall off to the sides of the player would be hidden incorrectly when using a cylinder. I also spheremask a small area right around the player for if you’re right up against a wall and don’t want to lose sight of your character.

We’re just fading wall pixels based on where they are relative to the player and camera, so if you walk into a tight corner towards the bottom of the screen, most of the walls won’t hide, which is an edge case that was deemed acceptable, especially since you have control of the camera pitch. The ideal thing, of course, would be to actually know which wall actors to hide when you’re in a given room, but we don’t. All this wall-fading stuff only kicks in when you’re under a roof, except there are some objects that opt into doing it at all times, like trees when you’re in a forest.

Everything in Weird West uses the same three or four materials, so it was easy to set up material params to opt-out of this per object; eg doors, doorframes, interactables never dissolve (unless they’re on a dissolved floor of a building). You could also disable or enable it per-object instead of per-material by adding a component to that actor, which just set the appropriate material parameters on the owner. None of these wall meshes were designed with this effect in mind, so initially it looked a bit bad, but then VFX cool-guy Ewan Croft made the wall material two-sided and had the backfaces coloured black, which worked nicely and means the interior wall parts you can suddenly see just look like they’re in darkness, rather than like missing polys.

The roofs hide when you’re under them, but also when you’re aiming under them, which was a hassle to get right consistently. If you’re aiming into a building you want to see who’s in there (it might be a baddie) but you also want to show the roof if you’re aiming at someone on the roof, even though your aim line might be going straight through a bottom-floor window of the same building. Plus, if you do this (find which buildings we’re aiming into) with a bunch of traces out in your aim direction from your aim location, moving either your character or your aim a little bit can get different results from frame to frame, and now we’re flickering the roof and nobody is having a good time. Plus the windows aren’t at a consistent height!

To fix the frame-to-frame issue I just rounded the player location we do all our traces from to the nearest half-meter-ish. This needed some tweaking to not just skip certain windows as you strafe past while aiming into them. If you’re not aiming, I think I just ended up tracing up from the player to find the roof, and hiding the right building layers; if there is no roof I think I’m doing radial traces out in a few-meters-wide circle around the player, and looking for a nearby-enough roof to be worth hiding. If you ARE aiming, I ignore the player’s location and do quite a lot of traces out in the aim direction in like a 30 degree arc, checking upwards for a roof every couple of meters out. The aim direction is rounded to the nearest 35 degrees-ish, again so that we don’t flicker the roofs as we thumb the right stick.

The aiming system ended up having sort of a soft lock-on thing; if you’re considered to be “aiming” at something it’s highlighted red. That’s convenient – if it happens, I just forget all this other stuff and act like the player is standing where the target is standing. So if someone is sniping you from a top level window, and you’re aiming at them, you can see the whole top floor. The way layers were set up for the game means you can’t easily do both “show building A’s top floor” and “show building B’s bottom floor”, but I don’t think it ever comes up.

The actual hiding-chunks-of-building stuff, as opposed to the fadey walls, was all Jouan Amate I believe – the results of the traces I mentioned go into a C++ system of his which hides stuff using Layers (an oft-forgotten Unreal feature). Characters, furniture, etc, which needs to hide along with the floor it’s on, has a FloorSensingComponent, and that lets a guy suddenly become visible if he walks out onto the balcony of a hidden floor of a building, for instance. Or hide a vulture when it lands on a hidden roof. That stuff was all very clever and I was pleased not to have to do it. Thanks Jouan!


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *