Unity Visibility/Fog of War Effect

Here’s a method for ‘fog of war’ from an old Unity project. This is the kind used in games like XCOM where the world geometry outside the visible range of your units is darkened, but still at least partially visible.

I added a circle mesh (an extremely short cylinder will also work) to the player unit prefab with a radius the same as the units view radius. The circle is on its own layer (UnitViewDistance), and is textured with a radial gradient going from white to transparent black.

Screen Shot 2016-03-24 at 17.21.40

I added a camera (UnitViewCamera) with a depth of 0 (all other cameras are depth 1, so UnitViewCamera renders first). UnitViewCamera’s culling mask is set so that it only renders the UnitViewDistance layer, and it renders into a RenderTexture created in code. The result of all this is a transparent image with various white blobs, something like this:

mask

The RenderTexture is then plugged into a shader and used as a mask. The intensity of the mask texel is used to lerp the colour of the final texel between full colour (at 1) and desaturated (at 0):

fixed4 frag (v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    float bwCol = col.r*.3 + col.g*.59 + col.b*.11;

    fixed4 maskCol = tex2D(_viewTex, i.uv);
    float maskIntensity = maskCol.r;

    col = lerp(bwCol, col, maskIntensity);
    return col;
}

Here’s a screenshot of a programmer-art world demonstrating the (very subtle) effect – the unit is off-screen to the bottom-right, so you can see the cubes desaturating towards the top-left:

Screen Shot 2016-03-24 at 17.39.21

Advertisements

UE4 Quick tip: ‘X-ray’ material

One of my prototypes needed an ability for the player to see certain objects through walls. I didn’t want the objects to be visible at all times, just when the player looked directly at them.

To prevent an object being obscured by the objects in front of it we just need to disable depth testing, which we can do in the object’s material. Set the material’s blend mode to Translucent and tick Disable Depth Test in the Translucency section of the material properties:

materialprops

Apply the material to a mesh and you’ll be able to see it through whatever objects are in front of it. To make the effect localised I added a very simple bit of maths to the opacity node:

Capture

This calculates the distance of the current pixel from the centre of the screen and uses it to determine the opacity – so the pixels fade out as they leave a very narrow radius around the centre.

Here’s a video of the material applied to the Starter Content chair: