4/17/16

Recently, I had the misfortune of dealing with a number of issues in Unreal, and all because of doors. One of the last features that the designers wanted me to add to the monster was the ability to slip under doors and gates. "How hard could this possibly be?" I wondered to myself.

As it turns out, it was much harder than it should've been.

First try: The sensible approach

My first attempt was using Unreal's NavLink system. Nav Link Proxies allow you to have your AI take routes that aren't part of a level's navmesh, and have the ability to set up "Smart Links" which can have additional scripting added to them. The idea was to use this system to make the monster play an animation and warp to the other link, but there were some issues with this approach. The primary issue is that you can't remove all of the normal links and use only smart links. My research seems to suggest that this is a long-standing bug in UE4, so there's not much I can do about it. (As an aside, it's times like these that make me regret not trying to convince the team to make our own branch of the 4.9 codebase) If the monster chooses the 'dumb' link, which seemed to happen randomly, it would run into the door/gate and become permanently stuck. Clearly, a new approach was needed.

Second try: The unpleasant approach

After that, my next idea was to add a higher tier of pathfinding for the monster. By generating a set of links, I could create a small pathfinding graph that represented the level. With a basic A* implementation, I could make the monster select movement targets while attempting to reach a certain position or object. This was an incredibly large undertaking, but the result would likely work well. As such, I made all of the necessary preparations for pulling an all-nighter. However, this is not the solution in our build.
I constructed all of the necessary objects, but when I went to actually get them generating links I noticed something odd. specifically, none of them were linking up. I'd written a small function that used a quick pathfinding check to see if one link was reachable from another, but they always failed top make a connection. As it turns out, the returning value was always 'error'. Note that Unreal didn't provide any specifics, nor did I find any way of seeing what precisely this error was. After yet more research, I found out that this is yet another long-standing bug in Unreal. Epic really needs to crack down on some of these. Frustrated, but not yet asleep, I thought up another way.

Third try: The 'Why the hell not' approach

With all of the obvious and reasonable solutions out of the way, it was clearly time for a disgusting hack. After searching some more, I found a way to make Unreal ignore a given solid object when building the navmesh. However, as demonstrated by the first approach, this kills an AI's movement when they walk move an unexpected solid. To prevent this, I put a box trigger around every door and gate. Then, I made a special collision layer for the monster that would make doors/gates ignore all collisions with it. When the monster entered the trigger, it would change and be able to pass through! As an added bonus, the monster would even pass through the floor and fall out of the level, despite the fact that the floor is supposed to collide with it! To prevent that little issue, I had to temporarily disable gravity, while also changing collision layers and animations. Lastly, I needed to adjust the monster's speed. The monster is supposed to be slowed down by these obstacles, after all.

So, that's how I came up with a dumb solution for a dumb problem. I really hate that I had to do this, since it's a much less elegant and flexible solution, but I don't really see any available alternatives. As long as it holds together, I suppose it'll have to do.

4/7/16

As the beta milestone (the effective 'due date' for the monster) approaches, I've started filling in the remaining gaps that are left over from earlier in development.

One of those gaps is art. I gave the monster a graphical upgrade several weeks ago, but I've gotten plenty of feedback since then. I've also added more abilities to the monster since then, which require more animations.

The two biggest complaints about the monster were that it wasn't very scary, and that it was still hard to tell when the player was taking damage. The designers haven't had a chance to play with the monster's stats yet, but I still found it odd that my damage feedback wasn't doing enough. One thing that we'd been wanting to do for a while is make it more apparent that the monster was nearby, so I added a noise effect that grows as you get closer to it. In addition, I made the damage effect on the player smoother and slightly reduced the monster's damage. This seems to have greatly improved player reactions to getting hurt.

One of our designers added a nice cinematic introducing the monster, where it leaps down to attack you but is driven away by a flickering ceiling light. We think it's really nice, and much scarier than normal interactions with the monster. Part of this is because the player can fight back, but we've also identified a few other things that could use improvement. First off, the monster is almost always seen from a high angle. In other words, it looks harmless because the player towers over it. Just making the monster taller than the player has added to the monster's scare factor by a decent bit. I also pumped up the alpha and particle count to try and make the monster look a little bit more solid than before.

The last thing to add, which I addressed last weekend, is animation. There were two main situations where the monster needed animations: Blinking, and slipping under doors. Blinking especially needed an animation, because the player needed a warning that the monster was about to appear. I spent a long time considering how to make the blink look. The blink is probably the most 'outlandish' thing that the monster is capable of, so I wasn't really sure how to make it work visually. Most of the monster's abilities are closely tied to the fact that it's more of a cloud than a solid object, but teleportation doesn't really fit as obviously. Ultimately, I decided to interpret the blink as the monster slipping into a crack and popping out elsewhere, which I've represented with the monster's particles compressing and flying into the ground, while a second animation has them pop out and expand at its destination. It may not be perfect, but I think it fits nicely nevertheless.

The slipping animation was much easier. I scaled down the monster's particles, then made them stationary and emitted them using a flat disk. The result is a mostly-flat shadow creeping around. I'm pretty happy with the result, and also a little sad because I think a bigger, more elaborate version of it might've made for a creepier design overall. My original idea was for the shadow to be a vague squid-like silhouette that scurried around the floor and walls, and I still kinda regret not giving it a shot.