跳到主要内容

[REDACTED] — Devlog #01: ▓▓▓▓▓▓

· 阅读需 1 分钟
Hoang Nguyen
Creative Director

Redacted

Vigil № 0001 — [REDACTED]. Filed under classified. Details withheld.

Status

▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓ NOT FOR PUBLIC RELEASE ▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

What we can say:

  • Engine: not yet decided.
  • Genre: a sibling of Lil Sis, but the perspective is different.
  • Estimated reveal: when it's ready. Not before.

Subsequent dev logs for this project will appear here as the access tier rises. For now: light a candle and wait.

— H.

Horror Asset Exporter — Devlog #01: One-Click Pipeline

· 阅读需 1 分钟
Thang Le
Senior Lead Engineer

Horror Asset Exporter

Vigil № 0001 — Horror Asset Exporter. Opening dev log for the Blender add-on.

Why the rewrite

The first internal version was four operators stitched together with bpy.ops calls. It worked, but every release of Blender broke something. The new version is a single relic — one INVOKE_DEFAULT entry point that runs the whole pipeline.

What it does now

  1. Auto-LOD — Decimate modifier at 0.5 and 0.2 ratios, baked to LOD1 and LOD2. Custom angle threshold per asset class.
  2. PBR remap — Principled BSDF → HDRP/Lit + URP/Lit material templates. Outputs a .unityassetdata JSON the Unity side reads on import.
  3. Collider hints — convex hull, bounding box, or "use mesh" tag baked into custom properties. Read by an importer post-processor on the Unity side.

What's broken

  • Export of armatures with custom bone groups loses the group names. Investigating.
  • The LOD0 mesh is occasionally exported with double-sided normals on UV seams. Probably a Decimate modifier interaction.

Targeting v1.0.6 release end of the month.

Simple Paint — Devlog #01: GPU Brush Stamps

· 阅读需 1 分钟
Thang Le
Senior Lead Engineer

Simple Paint — brush stamps

Vigil № 0001 — Simple Paint. Picking up dev log notes for the painting tool after a long quiet stretch.

What changed in 2.0.1

  • Brush stamps now sample a texture instead of solid colour. Texture array, indexed by brush id.
  • The compute kernel runs on a render texture target now, not a CPU Texture2D. ~14x faster on the Pixel 7.
  • Pressure curve is a AnimationCurve baked to a 256-entry LUT each frame the curve changes. No per-stamp evaluation cost.

Known issues

  • Stamp seams visible when the user paints faster than the stamp spacing. Need to interpolate stamp positions between input samples.
  • Eraser is a colour brush right now. Real alpha erasing is the next pass.

The version on the Asset Store is still 2.0.0. Next push: brush spacing fix + the alpha eraser.

LIL SIS — Devlog #01: Building the Altar

· 阅读需 1 分钟
Thang Le
Senior Lead Engineer

Lil Sis — opening shot

Vigil № 0001. First public entry from the workshop for Lil Sis. This is the dev log — it will be updated as the relic takes shape.

Where we are

The wooden house is standing. HDRP volumes are placed: low-altitude fog, exposure clamped to under 0.5 in interiors, single-bounce SSGI on. The corridor that leads to the bedroom is the spine of the whole game and we've been polishing its lighting for two weeks.

The "blood message" system uses a runtime decal projector with a custom URP… wait, no. HDRP. Sorry. Force of habit from the tool side.

What's next

  • First pass on the spatial audio cue for the sister's voice. Binaural via Steam Audio.
  • Sanity meter UI — currently a placeholder, must feel like a relic, not a HUD bar.
  • One puzzle prototype: the family photo that rearranges when not looked at.

More to come. Light a candle.

Advanced Vertex Displacement for Flesh & Gore

· 阅读需 2 分钟
Thang Le
Senior Lead Engineer

Flesh and Gore

The Art of Visceral Realism

In modern horror game development, the "feel" of an environment is often just as important as its visual fidelity. When it comes to organic, fleshy surfaces—think of the pulsating walls in a biological nightmare or the squishy impact of a weapon on a monster—standard static meshes often fall short. This is where Advanced Vertex Displacement comes into play.

Using Unity's Universal Render Pipeline (URP) and Shader Graph, we can move beyond simple texture swaps and into the realm of dynamic, responsive geometry. By manipulating vertex positions in real-time, we create an illusion of depth and movement that feels unsettlingly real.

The Mathematics of Pulsation

The core of a good "flesh" shader is the combination of multiple sine waves operating at different frequencies and amplitudes. We don't want a uniform pulse; that feels mechanical. Instead, we use a Noise-Driven Displacement approach. By sampling a Perlin or Simplex noise texture and using it to offset the vertex normal, we achieve that irregular, organic heaving that characterizes living tissue.

// Conceptual logic for vertex offset
float3 offset = normal * noiseValue * displacementStrength;
positionOS.xyz += offset;

Implementing in URP Shader Graph

  1. Vertex Position Node: Start by getting the object-space position.
  2. Normal Vector Node: Displacement should almost always happen along the vertex normal to maintain the volume's integrity.
  3. Time-Based Noise: Use a Time node multiplied by a speed constant to scroll a 3D noise function.
  4. Tessellation (Optional): For high-end hardware, adding hardware tessellation allows for much finer detail without requiring incredibly dense base meshes.

Performance Considerations

Vertex displacement is computationally cheaper than some might think, especially when handled entirely on the GPU. However, the biggest bottleneck is often Shadow Mapping. Displaced vertices must also be accounted for in the Shadow Caster pass, otherwise, the shadows will remain static while the mesh pulses, breaking the immersion. Ensure your Shader Graph has the "Shadow Caster" pass properly configured to use the same displacement logic.

By layering these techniques with subsurface scattering and a high-quality specular map (to give that "wet" look), you can create environments that don't just look scary—they feel alive.

Volumetric Fog in URP: A Deep Dive

· 阅读需 2 分钟
Thang Le
Senior Lead Engineer

Volumetric Fog

The Atmosphere of Dread

Fog is a staple of the horror genre, famously used in Silent Hill to mask hardware limitations. Today, however, fog is a deliberate stylistic and atmospheric choice. Volumetric Fog—fog that interacts with light sources and casts shadows—is the gold standard for creating "thick" atmosphere.

Raymarching: The Engine of Volume

Most volumetric fog systems in modern engines like Unity URP rely on Raymarching. The shader "marches" a ray from the camera into the scene, sampling the light and density at various points along that ray.

The challenge is the sheer number of samples required. A naive implementation will tank the frame rate. To optimize this, we use a Froxel-based approach (Frustum Voxels). By dividing the camera frustum into a 3D grid of voxels, we can pre-calculate the lighting for each voxel once per frame and then simply sample that grid during the main rendering pass.

Optimizing for URP

Unity's URP doesn't include a robust volumetric fog out of the box (unlike HDRP). To implement this effectively, we use Scriptable Render Features.

  1. Downsampling: Render the volumetric effect at a lower resolution (e.g., half or quarter res) and then upsample it using a bilateral filter to preserve edges.
  2. Temporal Reprojection: Use data from the previous frame to "fill in the blanks," allowing for fewer samples per frame while maintaining a smooth look.
  3. Phase Function: Implementing a Henyey-Greenstein phase function allows for realistic forward and backward scattering, making the fog "glow" when a light source is behind it.

Strategic Implementation

In horror, fog isn't just about visibility; it's about what it hides. By dynamically adjusting fog density based on player location or sanity levels, you can create a shifting sense of claustrophobia. For example, as the player's "Fear" meter rises, the fog's Extinction coefficient can increase, pulling the "wall of mist" closer to the player.

Performance-wise, always keep an eye on your Overdraw. Thick volumes of fog can overlap with other transparent effects (like particles), leading to significant GPU pressure. Balancing the Froxel resolution with the camera's far clip plane is the key to maintaining 60 FPS on mid-range hardware.

Binaural Audio: The Secret to True Fear

· 阅读需 2 分钟
Thang Le
Senior Lead Engineer

Binaural Audio

Hearing the Unseen

In horror, what the player doesn't see is often more terrifying than what they do. Sound is the primary tool for building this "unseen" threat. While standard stereo panning provides some directionality, Binaural Audio (using Head-Related Transfer Functions, or HRTF) creates a true 3D soundscape that tricks the brain into perceiving sounds as coming from specific points in 3D space—including above, below, and behind.

The Science of HRTF

HRTF accounts for how the human ear, head, and torso filter sound based on its arrival angle. Our brains use these subtle changes in frequency and timing to locate a sound source. By applying these filters to digital audio in real-time, we can simulate a sound originating from anywhere around the player's head.

Implementing in Unity

Unity provides several options for spatial audio. For a professional horror title, relying solely on the built-in spatializer is often insufficient.

  1. Oculus Spatializer or SteamAudio: These plugins offer robust HRTF implementations that work across various platforms. They allow for advanced features like Acoustic Propagation.
  2. Real-time Occlusion: If a monster is behind a door, the sound shouldn't just be quieter; it should be muffled. Using low-pass filters driven by raycasts from the audio source to the listener is essential for immersion.
  3. Reverb Zones: Dynamic reverb that changes based on the volume of the room (e.g., a small tiled bathroom vs. a massive vaulted cathedral) adds a sense of "place" to the audio.

The Psychological Impact

In a "hide and seek" horror game, binaural audio is a gameplay mechanic. The player must listen for the subtle creak of a floorboard or the wet breath of a stalker to survive. By using Audio Cues that are specifically positioned behind the player, you trigger a primal "fight or flight" response.

A pro tip for horror devs: use Infrasound (very low-frequency sounds, usually below 20Hz). While players might not "hear" it, these frequencies are known to cause feelings of anxiety and unease in humans. Layering these subtle tones into your binaural soundscape can elevate the tension without the player ever knowing why they feel so disturbed.

Custom Scriptable Render Features for Glitch Effects

· 阅读需 2 分钟
Thang Le
Senior Lead Engineer

Glitch Effects

Disrupting Reality

The "glitch" aesthetic has become synonymous with psychological horror and tech-noir. Whether it's the screen tearing of a found-footage camera or the visual degradation of a character losing their mind, these effects need to be more than just a simple overlay. To achieve high-performance, high-fidelity glitching in Unity's Universal Render Pipeline (URP), we must leverage Scriptable Render Features.

Why Not Just Post-Processing?

While Unity's Post-Processing Stack is powerful, it can be restrictive when you need to inject custom logic into specific parts of the rendering pipeline. Scriptable Render Features allow us to:

  • Draw specific objects with custom shaders.
  • Create multiple passes with intermediate textures.
  • Execute logic before or after specific URP events (e.g., After Transparent, Before Post-Processing).

Building the Glitch Pass

A convincing digital glitch usually consists of three core components:

  1. Chromatic Aberration: Splitting the RGB channels. In a glitch, this should be jittery and non-uniform.
  2. Block Displacement: Shifting random rectangular segments of the screen horizontally.
  3. Scanline Interferences: Adding subtle horizontal lines and "static" noise.

In our custom ScriptableRenderPass, we grab the cameraColorTarget, blit it to a temporary render texture using our "Glitch Shader," and then blit it back.

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get("GlitchPass");
// Execution logic here...
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}

Driving the Sanity Meter

The beauty of a custom Render Feature is how easily it can be tied to gameplay systems. By exposing a glitchIntensity parameter in the Render Feature, we can drive it from a "Sanity" or "Corruption" script in C#. As the player's sanity drops, we increase the frequency and amplitude of the block displacement and the severity of the chromatic aberration.

By using a ComputeBuffer or a simple GlobalFloat, we can update these values once per frame on the GPU, ensuring that even the most chaotic visual meltdowns don't impact our CPU performance. This allows for a seamless transition from a clear image to a fractured, terrifying reality.

Compute Shaders for Large-Scale Horror Entities

· 阅读需 2 分钟
Thang Le
Senior Lead Engineer

Compute Shaders Swarm

The Power of the Swarm

There is something primal about the fear of being overwhelmed by numbers. A single monster is a threat, but a swarm of thousands of scuttling insects or shadows is a nightmare. Traditionally, simulating thousands of individual AI entities would crush the CPU. To achieve this in real-time, we must move the simulation to the GPU using Compute Shaders.

GPGPU: Beyond Rendering

Compute Shaders allow us to use the massive parallel processing power of the GPU for non-rendering tasks—in this case, flocking behavior and physics. By storing our entity data (position, rotation, velocity) in a StructuredBuffer, we can update thousands of entities simultaneously in a single dispatch call.

The Boids Algorithm

For a convincing swarm, we use a modified Boids algorithm. Each entity follows three simple rules:

  1. Separation: Avoid crowding neighbors.
  2. Alignment: Steer towards the average heading of neighbors.
  3. Cohesion: Steer towards the average position of neighbors.

In a horror context, we add a fourth rule: Targeting/Avoidance. The swarm should actively move toward the player or avoid light sources.

Rendering the Swarm

Once the Compute Shader has updated the positions in the StructuredBuffer, we don't want to send that data back to the CPU (which is slow). Instead, we use GPU Instancing. We provide the buffer directly to a specialized vertex shader that positions the meshes based on the data already sitting in GPU memory.

// In the vertex shader
StructuredBuffer<EntityData> _EntityBuffer;
uint instanceID = UNITY_GET_INSTANCE_ID(v);
float3 pos = _EntityBuffer[instanceID].position;

Performance and Scale

With this architecture, simulating 10,000 entities becomes trivial. The bottleneck shifts from CPU logic to GPU fill rate and vertex processing. To optimize further, we can implement GPU Culling, where the Compute Shader checks if an entity is within the camera frustum before deciding whether it should be rendered.

This technique was used to great effect in titles like A Plague Tale: Innocence for their rat swarms. By leveraging Compute Shaders, indie developers can now achieve a level of scale that was previously reserved for AAA studios, creating truly overwhelming horror experiences.

Why "P.T." Still Haunts Level Designers

· 阅读需 2 分钟
Hoang Nguyen
Creative Director

PT Corridor

The Genius of the Infinite Loop

When Hideo Kojima released P.T. (Playable Teaser) in 2014, it changed the landscape of horror games forever. Despite being a single hallway, it managed to evoke more terror than many sprawling open-world titles. For level designers, P.T. is a masterclass in Psychological Loop-Fatigue and spatial manipulation.

The Power of the Mundane

The environment of P.T. is aggressively normal. A cluttered L-shaped hallway, a bathroom, and a radio. By using high-fidelity assets and realistic lighting, the designers grounded the player in a recognizable reality. This grounding is essential; the more "normal" a space feels, the more impactful the subtle deviations become.

As the player loops through the hallway, the deviations start small: a swinging light, a cockroach on the wall, a slightly different radio broadcast. This is Iterative Environmental Storytelling. The player becomes intimately familiar with every inch of the space, making them hyper-aware of any change, no matter how minute.

Masterful Pacing and Scripting

P.T. doesn't rely on traditional jump scares (though it has them). Instead, it uses the loop to build unbearable tension. The "puzzle" elements—like looking through a hole in the wall or finding hidden picture fragments—require the player to interact deeply with the environment.

From a technical standpoint, the "loop" is a clever bit of level streaming. As the player exits through the basement door, they are seamlessly teleported back to the start of the hallway. Each loop increment triggers a new set of scripted events and material swaps, effectively turning a single static asset into a dynamic, evolving narrative device.

Legacy in Level Design

The influence of P.T. can be seen in almost every "walking simulator" horror game that followed, from Layers of Fear to Visage. It proved that you don't need a massive map to create a massive sense of dread. By focusing on detail, sound, and the subversion of a safe space, level designers can create experiences that linger in the player's mind long after the console is turned off.

P.T. remains a haunting reminder of what happens when level design and psychological manipulation are perfectly aligned. It's not just a hallway; it's a window into the player's own mounting anxiety.