Lights and Effects

Chico Queiroz

September 2015

 In this article by Matt Smith and Chico Queiroz, authors of Unity 5.x Cookbook, we will cover the following topics:

  • Using lights and cookie textures to simulate a cloudy day
  • Adding a custom Reflection map to a scene
  • Creating a laser aim with Projector and Line Renderer
  • Reflecting surrounding objects with Reflection Probes
  • Setting up an environment with Procedural Skybox and Directional Light

(For more resources related to this topic, see here.)

Introduction

Whether you're willing to make a better-looking game, or add interesting features, lights and effects can boost your project and help you deliver a higher quality product. In this article, we will look at the creative ways of using lights and effects, and also take a look at some of Unity's new features, such as Procedural Skyboxes, Reflection Probes, Light Probes, and custom Reflection Sources.

Lighting is certainly an area that has received a lot of attention from Unity, which now features real-time Global Illumination technology provided by Enlighten. This new technology provides better and more realistic results for both real-time and baked lighting. For more information on Unity's Global Illumination system, check out its documentation at http://docs.unity3d.com/Manual/GIIntro.html.

The big picture

There are many ways of creating light sources in Unity. Here's a quick overview of the most common methods.

Lights

Lights are placed into the scene as game objects, featuring a Light component. They can function in Realtime, Baked, or Mixed modes. Among the other properties, they can have their Range, Color, Intensity, and Shadow Type set by the user. There are four types of lights:

  • Directional Light: This is normally used to simulate the sunlight
  • Spot Light: This works like a cone-shaped spot light
  • Point Light: This is a bulb lamp-like, omnidirectional light
  • Area Light: This baked-only light type is emitted in all directions from a rectangle-shaped entity, allowing for a smooth, realistic shading

For an overview of the light types, check Unity's documentation at http://docs.unity3d.com/Manual/Lighting.html.

Different types of lights

Environment Lighting

Unity's Environment Lighting is often achieved through the combination of a Skybox material and sunlight defined by the scene's Directional Light. Such a combination creates an ambient light that is integrated into the scene's environment, and which can be set as Realtime or Baked into Lightmaps.

Emissive materials

When applied to static objects, materials featuring the Emission colors or maps will cast light over surfaces nearby, in both real-time and baked modes, as shown in the following screenshot:

Projector

As its name suggests, a Projector can be used to simulate projected lights and shadows, basically by projecting a material and its texture map onto the other objects.

Lightmaps and Light Probes

Lightmaps are basically texture maps generated from the scene's lighting information and applied to the scene's static objects in order to avoid the use of processing-intensive real-time lighting.

Light Probes are a way of sampling the scene's illumination at specific points in order to have it applied onto dynamic objects without the use of real-time lighting.

The Lighting window

The Lighting window, which can be found through navigating to the Window | Lighting menu, is the hub for setting and adjusting the scene's illumination features, such as Lightmaps, Global Illumination, Fog, and much more. It's strongly recommended that you take a look at Unity's documentation on the subject, which can be found at http://docs.unity3d.com/Manual/GlobalIllumination.html.

Using lights and cookie textures to simulate a cloudy day

As it can be seen in many first-person shooters and survival horror games, lights and shadows can add a great deal of realism to a scene, helping immensely to create the right atmosphere for the game. In this recipe, we will create a cloudy outdoor environment using cookie textures. Cookie textures work as masks for lights. It functions by adjusting the intensity of the light projection to the cookie texture's alpha channel. This allows for a silhouette effect (just think of the bat-signal) or, as in this particular case, subtle variations that give a filtered quality to the lighting.

Getting ready

If you don't have access to an image editor, or prefer to skip the texture map elaboration in order to focus on the implementation, please use the image file called cloudCookie.tga, which is provided inside the 1362_06_01 folder.

How to do it...

To simulate a cloudy outdoor environment, follow these steps:

  1. In your image editor, create a new 512 x 512 pixel image.
  2. Using black as the foreground color and white as the background color, apply the Clouds filter (in Photoshop, this is done by navigating to the Filter | Render | Clouds menu).

    Learning about the Alpha channel is useful, but you could get the same result without it. Skip steps 3 to 7, save your image as cloudCookie.png and, when changing texture type in step 9, leave Alpha from Greyscale checked.

  3. Select your entire image and copy it.
  4. Open the Channels window (in Photoshop, this can be done by navigating to the Window | Channels menu).
  5. There should be three channels: Red, Green, and Blue. Create a new channel. This will be the Alpha channel.
  6. In the Channels window, select the Alpha 1 channel and paste your image into it.

  7. Save your image file as cloudCookie.PSD or TGA.
  8. Import your image file to Unity and select it in the Project view.
  9. From the Inspector view, change its Texture Type to Cookie and its Light Type to Directional. Then, click on Apply, as shown:

  10. We will need a surface to actually see the lighting effect. You can either add a plane to your scene (via navigating to the GameObject | 3D Object | Plane menu), or create a Terrain (menu option GameObject | 3D Object | Terrain) and edit it, if you so you wish.
  11. Let's add a light to our scene. Since we want to simulate sunlight, the best option is to create a Directional Light. You can do this through the drop-down menu named Create | Light | Directional Light in the Hierarchy view.
  12. Using the Transform component of the Inspector view, reset the light's Position to X: 0, Y: 0, Z: 0 and its Rotation to X: 90; Y: 0; Z: 0.
  13. In the Cookie field, select the cloudCookie texture that you imported earlier. Change the Cookie Size field to 80, or a value that you feel is more appropriate for the scene's dimension. Please leave Shadow Type as No Shadows.

  14. Now, we need a script to translate our light and, consequently, the Cookie projection. Using the Create drop-down menu in the Project view, create a new C# Script named MovingShadows.cs.
  15. Open your script and replace everything with the following code:
    using UnityEngine;
    using System.Collections;
    
    public class MovingShadows : MonoBehaviour{
    public float windSpeedX;
    public float windSpeedZ;
    private float lightCookieSize;
    private Vector3 initPos;
    
    void Start(){
       initPos = transform.position;
       lightCookieSize = GetComponent<Light>().cookieSize;
    }
    
    void Update(){
       Vector3 pos = transform.position;
       float xPos= Mathf.Abs (pos.x);
       float zPos= Mathf.Abs (pos.z);
       float xLimit = Mathf.Abs(initPos.x) + lightCookieSize;
       float zLimit = Mathf.Abs(initPos.z) + lightCookieSize;
    
       if (xPos >= xLimit)
         pos.x = initPos.x;
    
       if (zPos >= zLimit)
         pos.z = initPos.z;
    
       transform.position = pos;
       float windX = Time.deltaTime * windSpeedX;
       float windZ = Time.deltaTime * windSpeedZ;
       transform.Translate(windX, 0, windZ, Space.World);
    }
    }
  16. Save your script and apply it to the Directional Light.
  17. Select the Directional Light. In the Inspector view, change the parameters Wind Speed X and Wind Speed Z to 20 (you can change these values as you wish, as shown).

  18. Play your scene. The shadows will be moving.

How it works...

With our script, we are telling the Directional Light to move across the X and Z axis, causing the Light Cookie texture to be displaced as well. Also, we reset the light object to its original position whenever it traveled a distance that was either equal to or greater than the Light Cookie Size. The light position must be reset to prevent it from traveling too far, causing problems in real-time render and lighting. The Light Cookie Size parameter is used to ensure a smooth transition.

The reason we are not enabling shadows is because the light angle for the X axis must be 90 degrees (or there will be a noticeable gap when the light resets to the original position). If you want dynamic shadows in your scene, please add a second Directional Light.

There's more...

In this recipe, we have applied a cookie texture to a Directional Light. But what if we were using the Spot or Point Lights?

Creating Spot Light cookies

Unity documentation has an excellent tutorial on how to make the Spot Light cookies. This is great to simulate shadows coming from projectors, windows, and so on. You can check it out at http://docs.unity3d.com/Manual/HOWTO-LightCookie.html.

Creating Point Light Cookies

If you want to use a cookie texture with a Point Light, you'll need to change the Light Type in the Texture Importer section of the Inspector.

Adding a custom Reflection map to a scene

Whereas Unity Legacy Shaders use individual Reflection Cubemaps per material, the new Standard Shader gets its reflection from the scene's Reflection Source, as configured in the Scene section of the Lighting window. The level of reflectiveness for each material is now given by its Metallic value or Specular value (for materials using Specular setup). This new method can be a real time saver, allowing you to quickly assign the same reflection map to every object in the scene. Also, as you can imagine, it helps keep the overall look of the scene coherent and cohesive. In this recipe, we will learn how to take advantage of the Reflection Source feature.

Getting ready

For this recipe, we will prepare a Reflection Cubemap, which is basically the environment to be projected as a reflection onto the material. It can be made from either six or, as shown in this recipe, a single image file.

To help us with this recipe, it's been provided a Unity package, containing a prefab made of a 3D object and a basic Material (using a TIFF as Diffuse map), and also a JPG file to be used as the reflection map. All these files are inside the 1362_06_02 folder.

How to do it...

To add Reflectiveness and Specularity to a material, follow these steps:

  1. Import batteryPrefab.unitypackage to a new project. Then, select battery_prefab object from the Assets folder, in the Project view.
  2. From the Inspector view, expand the Material component and observe the asset preview window. Thanks to the Specular map, the material already features a reflective look. However, it looks as if it is reflecting the scene's default Skybox, as shown:

  3. Import the CustomReflection.jpg image file. From the Inspector view, change its Texture Type to Cubemap, its Mapping to Latitude - Longitude Layout (Cylindrical), and check the boxes for Glossy Reflection and Fixup Edge Seams. Finally, change its Filter Mode to Trilinear and click on the Apply button, shown as follows:

  4. Let's replace the Scene's Skybox with our newly created Cubemap, as the Reflection map for our scene. In order to do this, open the Lighting window by navigating to the Window | Lighting menu. Select the Scene section and use the drop-down menu to change the Reflection Source to Custom. Finally, assign the newly created CustomReflection texture as the Cubemap, shown as follows:

  5. Check out for the new reflections on the battery_prefab object.

How it works...

While it is the material's specular map that allows for a reflective look, including the intensity and smoothness of the reflection, the refection itself (that is, the image you see on the reflection) is given by the Cubemap that we have created from the image file.

There's more...

Reflection Cubemaps can be achieved in many ways and have different mapping properties.

Mapping coordinates

The Cylindrical mapping that we applied was well-suited for the photograph that we used. However, depending on how the reflection image is generated, a Cubic or Spheremap-based mapping can be more appropriate. Also, note that the Fixup Edge Seams option will try to make the image seamless.

Sharp reflections

You might have noticed that the reflection is somewhat blurry compared to the original image; this is because we have ticked the Glossy Reflections box. To get a sharper-looking reflection, deselect this option; in which case, you can also leave the Filter Mode option as default (Bilinear).

Maximum size

At 512 x 512 pixels, our reflection map will probably run fine on the lower-end machines. However, if the quality of the reflection map is not so important in your game's context, and the original image dimensions are big (say, 4096 x 4096), you might want to change the texture's Max Size at the Import Settings to a lower number.

Creating a laser aim with Projector and Line Renderer

Although using GUI elements, such as a cross-hair, is a valid way to allow players to aim, replacing (or combining) it with a projected laser dot might be a more interesting approach. In this recipe, we will use the Projector and Line components to implement this concept.

Getting ready

To help us with this recipe, it's been provided with a Unity package containing a sample scene featuring a character holding a laser pointer, and also a texture map named LineTexture. All files are inside the 1362_06_03 folder. Also, we'll make use of the Effects assets package provided by Unity (which you should have installed when installing Unity).

How to do it...

To create a laser dot aim with a Projector, follow these steps:

  1. Import BasicScene.unitypackage to a new project. Then, open the scene named BasicScene. This is a basic scene, featuring a player character whose aim is controlled via mouse.
  2. Import the Effects package by navigating to the Assets | Import Package | Effects menu. If you want to import only the necessary files within the package, deselect everything in the Importing package window by clicking on the None button, and then check the Projectors folder only. Then, click on Import, as shown:

  3. From the Inspector view, locate the ProjectorLight shader (inside the Assets | Standard Assets | Effects | Projectors | Shaders folder). Duplicate the file and name the new copy as ProjectorLaser.
  4. Open ProjectorLaser. From the first line of the code, change Shader "Projector/Light" to Shader "Projector/Laser". Then, locate the line of code – Blend DstColor One and change it to Blend One One. Save and close the file.

    The reason for editing the shader for the laser was to make it stronger by changing its blend type to Additive. However, if you want to learn more about it, check out Unity's documentation on the subject, which is available at http://docs.unity3d.com/Manual/SL-Reference.html.

  5. Now that we have fixed the shader, we need a material. From the Project view, use the Create drop-down menu to create a new Material. Name it LaserMaterial. Then, select it from the Project view and, from the Inspector view, change its Shader to Projector/Laser.
  6. From the Project view, locate the Falloff texture. Open it in your image editor and, except for the first and last columns column of pixels that should be black, paint everything white. Save the file and go back to Unity.

  7. Change the LaserMaterial's Main Color to red (RGB: 255, 0, 0). Then, from the texture slots, select the Light texture as Cookie and the Falloff texture as Falloff.

  8. From the Hierarchy view, find and select the pointerPrefab object (MsLaser | mixamorig:Hips | mixamorig:Spine | mixamorig:Spine1 | mixamorig:Spine2 | mixamorig:RightShoulder | mixamorig:RightArm | mixamorig:RightForeArm | mixamorig:RightHand | pointerPrefab). Then, from the Create drop-down menu, select Create Empty Child. Rename the new child of pointerPrefab as LaserProjector.
  9. Select the LaserProjector object. Then, from the Inspector view, click the Add Component button and navigate to Effects | Projector. Then, from the Projector component, set the Orthographic option as true and set Orthographic Size as 0.1. Finally, select LaserMaterial from the Material slot.
  10. Test the scene. You will be able to see the laser aim dot, as shown:

  11. Now, let's create a material for the Line Renderer component that we are about to add. From the Project view, use the Create drop-down menu to add a new Material. Name it as Line_Mat.
  12. From the Inspector view, change the shader of the Line_Mat to Particles/Additive. Then, set its Tint Color to red (RGB: 255;0;0).
  13. Import the LineTexture image file. Then, set it as the Particle Texture for the Line_Mat, as shown:

  14. Use the Create drop-down menu from Project view to add a C# script named LaserAim. Then, open it in your editor.
  15. Replace everything with the following code:
    using UnityEngine;
    using System.Collections;
    public class LaserAim : MonoBehaviour {
    
    public float lineWidth = 0.2f;
    public Color regularColor = new Color (0.15f, 0, 0, 1);
    public Color firingColor = new Color (0.31f, 0, 0, 1);
    public Material lineMat;
    private Vector3 lineEnd;
    private Projector proj;
    private LineRenderer line;
    
    void Start () {
       line = gameObject.AddComponent<LineRenderer>();
       line.material = lineMat;
       line.material.SetColor("_TintColor", regularColor);
       line.SetVertexCount(2);
       line.SetWidth(lineWidth, lineWidth);
       proj = GetComponent<Projector> ();
    }
    
    void Update () {
       RaycastHit hit;
       Vector3 fwd = transform.TransformDirection(Vector3.forward);
    
       if (Physics.Raycast (transform.position, fwd, out hit))
       {
         lineEnd = hit.point;
         float margin = 0.5f;
         proj.farClipPlane = hit.distance + margin;
     
       } else {
         lineEnd = transform.position + fwd * 10f;
       }
       line.SetPosition(0, transform.position);
       line.SetPosition(1, lineEnd);
    
       if(Input.GetButton("Fire1")){
         float lerpSpeed = Mathf.Sin (Time.time * 10f);
         lerpSpeed = Mathf.Abs(lerpSpeed);
         Color lerpColor = Color.Lerp(regularColor,
    firingColor, lerpSpeed);
         line.material.SetColor("_TintColor", lerpColor);
    
       }
       if(Input.GetButtonUp("Fire1")){
         line.material.SetColor("_TintColor", regularColor);
       }
    }
    }
  16. Save your script and attach it to the LaserProjector game object.
  17. Select the LaserProjector GameObject. From the Inspector view, find the Laser Aim component and fill the Line Material slot with the Line_Mat material, as shown:

  18. Play the scene. The laser aim is ready, and looks as shown:

    In this recipe, the width of the laser beam and its aim dot have been exaggerated. Should you need a more realistic thickness for your beam, change the Line Width field of the Laser Aim component to 0.05, and the Orthographic Size of the Projector component to 0.025. Also, remember to make the beam more opaque by setting the Regular Color of the Laser Aim component brighter.

How it works...

The laser aim effect was achieved by combining two different effects: a Projector and Line Renderer.

A Projector, which can be used to simulate light, shadows, and more, is a component that projects a material (and its texture) onto other game objects. By attaching a projector to the Laser Pointer object, we have ensured that it will face the right direction at all times. To get the right, vibrant look, we have edited the projector material's Shader, making it brighter. Also, we have scripted a way to prevent projections from going through objects, by setting its Far Clip Plane on approximately the same level of the first object that is receiving the projection. The line of code that is responsible for this action is—proj.farClipPlane = hit.distance + margin;.

Regarding the Line Renderer, we have opted to create it dynamically, via code, instead of manually adding the component to the game object. The code is also responsible for setting up its appearance, updating the line vertices position, and changing its color whenever the fire button is pressed, giving it a glowing/pulsing look.

For more details on how the script works, don't forget to check out the commented code, available within the 1362_06_03 | End folder.

Reflecting surrounding objects with Reflection Probes

If you want your scene's environment to be reflected by game objects, featuring reflective materials (such as the ones with high Metallic or Specular levels), then you can achieve such effect using Reflection Probes. They allow for real-time, baked, or even custom reflections through the use of Cubemaps.

Real-time reflections can be expensive in terms of processing; in which case, you should favor baked reflections, unless it's really necessary to display dynamic objects being reflected (mirror-like objects, for instance). Still, there are some ways real-time reflections can be optimized. In this recipe, we will test three different configurations for reflection probes:

  • Real-time reflections (constantly updated)
  • Real-time reflections (updated on-demand) via script
  • Baked reflections (from the Editor)

Getting ready

For this recipe, we have prepared a basic scene, featuring three sets of reflective objects: one is constantly moving, one is static, and one moves whenever it is interacted with. The Probes.unitypackage package that is containing the scene can be found inside the 1362_06_04 folder.

How to do it...

To reflect the surrounding objects using the Reflection probes, follow these steps:

  1. Import Probes.unitypackage to a new project. Then, open the scene named Probes. This is a basic scene featuring three sets of reflective objects.
  2. Play the scene. Observe that one of the systems is dynamic, one is static, and one rotates randomly, whenever a key is pressed.
  3. Stop the scene.
  4. First, let's create a constantly updated real-time reflection probe. From the Create drop-down button of the Hierarchy view, add a Reflection Probe to the scene (Create | Light | Reflection Probe). Name it as RealtimeProbe and make it a child of the System 1 Realtime | MainSphere game object. Then, from the Inspector view, the Transform component, change its Position to X: 0; Y: 0; Z: 0, as shown:

  5. Now, go to the Reflection Probe component. Set Type as Realtime; Refresh Mode as Every Frame and Time Slicing as No time slicing, shown as follows:

  6. Play the scene. The reflections will be now be updated in real time. Stop the scene.
  7. Observe that the only object displaying the real-time reflections is System 1 Realtime | MainSphere. The reason for this is the Size of the Reflection Probe. From the Reflection Probe component, change its Size to X: 25; Y: 10; Z: 25. Note that the small red spheres are now affected as well. However, it is important to notice that all objects display the same reflection. Since our reflection probe's origin is placed at the same location as the MainSphere, all reflective objects will display reflections from that point of view.

  8. If you want to eliminate the reflection from the reflective objects within the reflection probe, such as the small red spheres, select the objects and, from the Mesh Renderer component, set Reflection Probes as Off, as shown in the following screenshot:

  9. Add a new Reflection Probe to the scene. This time, name it OnDemandProbe and make it a child of the System 2 On Demand | MainSphere game object. Then, from the Inspector view, Transform component, change its Position to X: 0; Y: 0; Z: 0.
  10. Now, go to the Reflection Probe component. Set Type as Realtime, Refresh Mode as Via scripting, and Time Slicing as Individual faces, as shown in the following screenshot:

  11. Using the Create drop-down menu in the Project view, create a new C# Script named UpdateProbe.
  12. Open your script and replace everything with the following code:
    using UnityEngine;
    using System.Collections;
    
    public class UpdateProbe : MonoBehaviour {
    private ReflectionProbe probe;
    
    void Awake () {
       probe = GetComponent<ReflectionProbe> ();
       probe.RenderProbe();
    }
    
    public void RefreshProbe(){
       probe.RenderProbe();
    }
    }
  13. Save your script and attach it to the OnDemandProbe.
  14. Now, find the script named RandomRotation, which is attached to the System 2 On Demand | Spheres object, and open it in the code editor.
  15. Right before the Update() function, add the following lines:
    private GameObject probe;
    private UpdateProbe up;
    void Awake(){
    probe = GameObject.Find("OnDemandProbe");
    up = probe.GetComponent<UpdateProbe>();
    }
  16. Now, locate the line of code called transform.eulerAngles = newRotation; and, immediately after it, add the following line:
    up.RefreshProbe();
  17. Save the script and test your scene. Observe how the Reflection Probe is updated whenever a key is pressed.
  18. Stop the scene. Add a third Reflection Probe to the scene. Name it as CustomProbe and make it a child of the System 3 On Custom | MainSphere game object. Then, from the Inspector view, the Transform component, change its Position to X: 0; Y: 0; Z: 0.
  19. Go to the Reflection Probe component. Set Type as Custom and click on the Bake button, as shown:

  20. A Save File dialog window will show up. Save the file as CustomProbe-reflectionHDR.exr.
  21. Observe that the reflection map does not include the reflection of red spheres on it. To change this, you have two options: set the System 3 On Custom | Spheres GameObject (and all its children) as Reflection Probe Static or, from the Reflection Probe component of the CustomProbe GameObject, check the Dynamic Objects option, as shown, and bake the map again (by clicking on the Bake button).

  22. If you want your reflection Cubemap to be dynamically baked while you edit your scene, you can set the Reflection Probe Type to Baked, open the Lighting window (the Assets | Lighting menu), access the Scene section, and check the Continuous Baking option as shown. Please note that this mode won't include dynamic objects in the reflection, so be sure to set System 3 Custom | Spheres and System 3 Custom | MainSphere as Reflection Probe Static.

How it works...

The Reflection Probes element act like omnidirectional cameras that render Cubemaps and apply them onto the objects within their constraints. When creating Reflection Probes, it's important to be aware of how the different types work:

  • Real-time Reflection Probes: Cubemaps are updated at runtime. The real-time Reflection Probes have three different Refresh Modes: On Awake (Cubemap is baked once, right before the scene starts); Every frame (Cubemap is constantly updated); Via scripting (Cubemap is updated whenever the RenderProbe function is used).
    Since Cubemaps feature six sides, the Reflection Probes features Time Slicing, so each side can be updated independently. There are three different types of Time Slicing: All Faces at Once (renders all faces at once and calculates mipmaps over 6 frames. Updates the probe in 9 frames); Individual Faces (each face is rendered over a number of frames. It updates the probe in 14 frames. The results can be a bit inaccurate, but it is the least expensive solution in terms of frame-rate impact); No Time Slicing (The Probe is rendered and mipmaps are calculated in one frame. It provides high accuracy, but it also the most expensive in terms of frame-rate).
  • Baked: Cubemaps are baked during editing the screen. Cubemaps can be either manually or automatically updated, depending whether the Continuous Baking option is checked (it can be found at the Scene section of the Lighting window).
  • Custom: The Custom Reflection Probes can be either manually baked from the scene (and even include Dynamic objects), or created from a premade Cubemap.

There's more...

There are a number of additional settings that can be tweaked, such as Importance, Intensity, Box Projection, Resolution, HDR, and so on. For a complete view on each of these settings, we strongly recommend that you read Unity's documentation on the subject, which is available at http://docs.unity3d.com/Manual/class-ReflectionProbe.html.

Setting up an environment with Procedural Skybox and Directional Light

Besides the traditional 6 Sided and Cubemap, Unity now features a third type of skybox: the Procedural Skybox. Easy to create and setup, the Procedural Skybox can be used in conjunction with a Directional Light to provide Environment Lighting to your scene. In this recipe, we will learn about different parameters of the Procedural Skybox.

Getting ready

For this recipe, you will need to import Unity's Standard Assets Effects package, which you should have installed when installing Unity.

How to do it...

To set up an Environment Lighting using the Procedural Skybox and Directional Light, follow these steps:

  1. Create a new scene inside a Unity project. Observe that a new scene already includes two objects: the Main Camera and a Directional Light.
  2. Add some cubes to your scene, including one at Position X: 0; Y: 0; Z: 0 scaled to X: 20; Y: 1; Z: 20, which is to be used as the ground, as shown:

  3. Using the Create drop-down menu from the Project view, create a new Material and name it MySkybox. From the Inspector view, use the appropriate drop-down menu to change the Shader of MySkybox from Standard to Skybox/Procedural.
  4. Open the Lighting window (menu Window | Lighting), access the Scene section. At the Environment Lighting subsection, populate the Skybox slot with the MySkybox material, and the Sun slot with the Directional Light from the Scene.
  5. From the Project view, select MySkybox. Then, from the Inspector view, set Sun size as 0.05 and Atmosphere Thickness as 1.4. Experiment by changing the Sky Tint color to RGB: 148; 128; 128, and the Ground color to a value that resembles the scene cube floor's color (such as RGB: 202; 202; 202). If you feel the scene is too bright, try bringing the Exposure level down to 0.85, shown as follows:

  6. Select the Directional Light and change its Rotation to X: 5; Y: 170; Z: 0. Note that the scene should resemble a dawning environment, something like the following scene:

  7. Let's make things even more interesting. Using the Create drop-down menu in the Project view, create a new C# Script named RotateLight. Open your script and replace everything with the following code:
    using UnityEngine;
    using System.Collections;
    public class RotateLight : MonoBehaviour {
    public float speed = -1.0f;
    void Update () {
       transform.Rotate(Vector3.right * speed * Time.deltaTime);
    }
    }
  8. Save it and add it as a component to the Directional Light.
  9. Import the Effects Assets package into your project (via the Assets | Import Package | Effects menu).
  10. Select the Directional Light. Then, from Inspector view, Light component, populate the Flare slot with the Sun flare.
  11. From the Scene section of the Lighting window, find the Other Settings subsection. Then, set Flare Fade Speed as 3 and Flare Strength as 0.5, shown as follows:

  12. Play the scene. You will see the sun rising and the Skybox colors changing accordingly.

How it works...

Ultimately, the appearance of Unity's native Procedural Skyboxes depends on the five parameters that make them up:

  • Sun size: The size of the bright yellow sun that is drawn onto the skybox is located according to the Directional Light's Rotation on the X and Y axes.
  • Atmosphere Thickness: This simulates how dense the atmosphere is for this skybox. Lower values (less than 1.0) are good for simulating the outer space settings. Moderate values (around 1.0) are suitable for the earth-based environments. Values that are slightly above 1.0 can be useful when simulating air pollution and other dramatic settings. Exaggerated values (like more than 2.0) can help to illustrate extreme conditions or even alien settings.
  • Sky Tint: It is the color that is used to tint the skybox. It is useful for fine-tuning or creating stylized environments.
  • Ground: This is the color of the ground. It can really affect the Global Illumination of the scene. So, choose a value that is close to the level's terrain and/or geometry (or a neutral one).
  • Exposure: This determines the amount of light that gets in the skybox. The higher levels simulate overexposure, while the lower values simulate underexposure.

It is important to notice that the Skybox appearance will respond to the scene's Directional Light, playing the role of the Sun. In this case, rotating the light around its X axis can create dawn and sunset scenarios, whereas rotating it around its Y axis will change the position of the sun, changing the cardinal points of the scene.

Also, regarding the Environment Lighting, note that although we have used the Skybox as the Ambient Source, we could have chosen a Gradient or a single Color instead—in which case, the scene's illumination wouldn't be attached to the Skybox appearance.

Finally, also regarding the Environment Lighting, please note that we have set the Ambient GI to Realtime. The reason for this was to allow the real-time changes in the GI, promoted by the rotating Directional Light. In case we didn't need these changes at runtime, we could have chosen the Baked alternative.

Summary

In this article you have learned and had hands-on approach to a number Unity's lighting system features, such as cookie textures, Reflection maps, Lightmaps, Light and Reflection probes, and Procedural Skyboxes. The article also demonstrated the use of Projectors.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Unity 5.x Cookbook

Explore Title