3D Animated Skybox

763 total views, 2 views today

In this tutorial we’ll be working on creating a 3D animated skybox as an extension of the static skyboxes you see in most Unity games.

Note: If you just want to know how to get a 3D skybox working without the research stuff, skip to Part 2.

In video games, a skybox provides an inexpensive far-away backdrop to the main playable area in which players are bound (figure 1). To varying degrees, their counterpart in pre-rendered media (such as films and animations) would be the matte painting.

Figure 1: A city environment.

With or without any low-resolution props in between, they contribute to a sense of a much bigger world that’s so far away that it’s impossible to actually ever reach. This is ideal, of course, since a skybox is usually nothing more than 6 static images plastered on the faces of an inverted cube with the camera always at the center (figure 2).

Figure 2: A skybox material in Unity.

Some games may opt to use a sphere, a hemisphere, or even a cylinder, but the intent and end result are almost always the same and the illusion of a vast world easily breaks once the player/camera leaves the intended bounds by any means, including glitches, “noclip”, and hacks (figure 3).

Figure 3: Outside the playable bounds.

3D skyboxes allow for much more dynamic scenery which can include moving parts and motion parallax if necessary, along with the ability to apply post-processing that’s easily limited to the skybox (by applying it using the second camera). They help overcome some of the limitations of actually having massive objects placed at large distances away from the world center. These limitations include the camera draw distance limit, floating-point precision, and the general difficulty of working with large scales.

Part 1 – Research

Let’s take a look at how this is done by first deconstructing an existing game. Source games such as Half-Life 2 and Left 4 Dead 2 are well-known for using this technique (figure 4).


Figure 4: Motion parallax in the first map (apartments) of Left 4 Dead’s first campaign, “No Mercy”.

Attempting to leave the playable area results in a void (figure 5).


Figure 5: Using noclip to move outside the playable bounds causes the 3D skybox to disappear. Note how most of the buildings surrounding the main hospital building area are untextured gray polygons. The heavy fog makes them fit in without being too noticeable.

Turning around reveals the actual playable area on this level (figure 6).


Figure 6: The playable area with and without the 3D skybox render layered behind it.

Going down, we can finally see the scaled-down 3D skybox geometry with a clearing for the playable area as rendered above (figure 7).


Figure 7: The hidden 3D skybox geometry beneath the playable area.

It’s clear a second camera is rendering this geometry behind the player camera as entities in the area of the downscaled geometry are rendered as giants above (figure 8).


Figure 8: We shoot our own unfortunate team member Louis so that we may learn more about the 3D skybox rendering technique. While behing shot, he’s rendered by both the player camera and the skybox camera, resulting in 2x the pain.

This can create some freakish results when viewed from the actual playable area above (figure 9, 10).


Figure 9: Nope.


Figure 10: NOPE.

Part 2 – Implementation (AKA, the actual tutorial…)

Okay, now that we know how this effect is done, let’s get to setting it up in Unity.

Optional assets:




I used these assets in my demo because they look cool. I’ve listed them as affiliate links above in case you want to check them out.

You probably already have a camera in your scene, so just add another as “3D Skybox Camera”.

The main camera in my scene is “3rdPersonCamera” which is a prefab from Invector’s FREE third person controller.

In the Source engine, it seems that the 3D skybox is greatly offset from the main scene and scaled to 1/16 the size so a limited clipping plane can be used to filter the main scene. In Unity we can use layers to sort what we want to render with the main camera, and what should only be limited to rendering using the 3D skybox camera.

Go to the Tags & Layers inspector by clicking on any game object’s Layer mask drop down and hitting “Add Layer…”.

Name the layer “3D Skybox”.

Select your main camera and set the Clear Flags to “Depth Only”. This is so we’ll have a blank slate for  the actual skybox in the scene will be rendered using the 3D skybox camera.

Open up the Culling Mask drop down, and uncheck the 3D skybox layer. This will exclude any and all objects with their layer set to 3D Skybox.

Make sure the Depth is 0 (or any value greater than the Depth for the 3D skybox camera). This ensures that we’ll render after the 3D skybox camera.

Select your 3D skybox camera and do the opposite. Only check the 3D skybox layer so no other layer will be rendered. You can do this easily by first selecting “Nothing” to uncheck all the other layers. Also make sure that for Clear Flags, you have Skybox selected.

Set the Depth to anything less than the Depth for the main camera (and/or other cameras) to ensure the Skybox renders first. This way, we have proper scene composition. You have the background (the 3D skybox render), followed by foreground components (the main camera render).

I’ve created a new “folder” game object to store the elements of my 3D skybox and set all children to be on the 3D skybox layer.

Like Source, you can even move the 3D skybox objects to some offset location if you don’t want them occupying the same space as the main scene components while you work in the Scene view, although this is only for organization. Even though the objects are right in front of the main camera, they will render as part of the background. You can notice the difference when looking at the scene view vs. the game view.

My ground is simply a plane with a fully metallic and shiny Standard shader/PBR material.

Notice how it reflects the elements of the 3D skybox perfectly? We can use a reflection probe to get this working. Go ahead and drop one into the scene.

If you want the highest quality realtime settings, you can copy/change the settings highlighted in red from below.

These settings are for higher-end gaming rigs and you can probably get away with less (non-realtime reflections, lower resolution, etc.). Refer to the the official documentation on the reflection probe component for details on what each parameter does.

We have a problem, still. If we play the scene and rotate the main camera, the skybox render doesn’t match!


This can be fixed easily with just a single line of code.
Create a new script named, “SkyboxCamera” and paste the following.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SkyboxCamera : MonoBehaviour
{
    Camera camera;

    void Start()
    {
        camera = GetComponent<Camera>();
    }
    void LateUpdate()
    {
        camera.fieldOfView = Camera.main.fieldOfView;
        transform.rotation = Camera.main.transform.rotation;
    }
}

All we did is add one line of code inside LateUpdate to match the rotation of the main camera. I also added in some code to force matching the field of view, since that’s important for some cases, too.

Now attach this script to the 3D skybox camera object and that’s it! We’re done!

We can even add post-processing to each camera individually if we want, but in my case I only have one active behaviour on the main camera since the bloom, colour grading, etc. will carry down to everything rendered behind (the skybox included).