This project was a lot of fun! I was given the task of creating our enemies for the 7th game project at TGA, and my group chose Alan Wake II for our reference, which meant I got to create very cool effects for the enemies. I first looked at the shade enemies from AWII for inspiration, and together with my group we came up with a concept that more aligned with our idea: a humanoid silhouette, that appears to be a void in the world.
The enemies are rigged by Joanna Soufi Karlsson. Tall enemies are animated by Joanna, small enemies are animated by Sandra Sandal.
Since I knew I would be able to sit for a good while in Unreal Engine, and then convert my shaders and VFX into HLSL, I decided to spend my time getting comfortable with Material Functions, and what kind of material functions I'd use in the future. My strengths at the moment are not in scripting and coding, so I made my shaders and VFX using as simple a concept as possible - scrolling textures - and create something that gives the illusion of being more complex than it is. This idea is the base idea for the biggest enemy visual: the oil-slick, aurora-esque shield effect, which the player use their flashlight to destroy.
A lot of these features are not fully implemented yet, as technical limitations made them harder to work on, but this gave me more time to write my own HLSL include file, where I could translate my Material Functions into neat and easy code blocks I could reference in all my .hlsl files for the enemies.
The secondary shader, which in itself consists of two material functions, is the vertex shader that makes the enemy model constantly pulse and move, even when the enemy is standing still. I wanted both a constant vertex wobble (which is achieved by a simple scrolling noise over time), as well as a secondary vertex wobble that changes according to the camera vector. Both of these vertex shaders are then added to each other, and plopped into the world position offset input.
Almost all parts of the enemy shader materials are built up with several material functions, which get their inputs from the user directly. This makes it possible to offset each shader start frame, so that no enemies will have the exakt same timing on their shader.
This setup also let me easily control both the time-based vertex wobble, as well as the camera based one.
The camera-based vertex shader material function.
The time-based vertex shader material function.
The vertex wobble shaders in action.
The enemies have a huge variety of animations, and a few of them show them phasing through the floor. I created a VFX to mask where they clip through the models, this re-uses a lot of the textures and material functions I already made.
I got to use a variety of programs for this project, and one of the more interesting ones was sitting down with EmberGen. In it, I generated a wispy smoke flipbook texture, which was initally used as the smoke particles. The result looked very stiff, so in the end I decided to use Skeletal Mesh location nodes in Niagara to get the particles to behave like I wanted, but I'm still pleased with my little EmberGen smoke.
Conclusion & takeaways
This project was both fun and frustrating, but in the end I did learn a lot about how to create complex-looking shaders from very basic features. The overall look of the enemies turned out pretty much how I envisioned, and getting the particles to follow the enemy movement was a big step forward for me.