Monthly Archives: June 2015

In-Game Security Camera using Render Texture

Since the release of Unity 5, Render Texture functionality is available to all Unity users (yes, even in the free version)! You can use this functionality to create some cool effects, and in this tutorial I’ll show you how to create a cool in-game security camera that projects a camera’s view onto a screen.

What is a Render Texture?

A Render Texture is a texture you can draw onto, and then use like any other sprite/texture. One of the coolest things you can do with a render texture is use it as the target for a camera’s view – so the camera draws what it sees onto the texture (instead of displaying it on the screen).

Additionally I’ll include a script that saves the Render Texture to a .PNG file, which you can do with as you please.

security_cam_no_vampire

Displaying a security camera feed on a TV (ignore the vampire…more on that later).

This technique resembles a security camera setup. You have a camera, which sees the image, and then records it to the Render Texture (which is the equivalent of a video tape or hard drive holding the image), then finally the image is projected onto the TV screen.

Downloads

You can download the completed Unity package (Unity 5+ required), or you can follow along with the tutorial (or both!).

The package contains a single demo scene, which displays some random objects (and a vampire!). A camera is pointed at the random objects, and it displays them on a TV screen.

The vampire is included to show off a nice trick – you can choose what a camera can and can’t see (vampires can’t be seen by mirrors or cameras, of course).

In the sample scene you can play around with the following controls:

  • Arrow keys – move the security camera
  • V – toggle the vampire’s visibility
  • S – save a .PNG of the security camera’s current view.

Step-by-Step

If you’re experienced with Unity you can probably skim through this and understand it easily.

For those of you new to Unity I cover all but the most basic steps in detail. If you do get lost or stuck, just open up the asset package – it’s a very simple project – and look at the objects and their settings.

The great thing about this technique is that the core functionality doesn’t require a single line of code. It’s all done in the Unity editor.

The project has two scripts, but they are for extra functionality (one script to move the camera around and another to save the Render Texture as a .PNG).

Create a New Project

Create a new 3D Unity project.

The only assets you need are two sprites (a TV and a vampire). You can grab them from the download above or just use your own.

Place your TV somewhere in the scene, and place some random objects elsewhere (these are the objects you will record with the security camera). Place your vampire among the random objects.

To drop the TV and vampire sprites into the scene you will need to select them and change their texture type to Sprite.

You’ll need to increase the TV’s size to make it suitable. A scale of about (4, 4, 1) will be about right. It will also help to change the scene view to 2D while placing your objects in the scene.

You can create spheres and cubes, etc. straight from the Unity main menu (Main Menu > GameObject > 3D Object > Cube, for example), or you can just create some random items by dragging some sprites into the scene. You just need something for the camera to look at.

Once you have a handful of items, a TV screen, and a vampire set up roughly like the image below, move on to the next step.

Make your scene look something like this

Make your scene look something like this

Create the Vampire

By creating a special layer and telling our security camera to ignore that layer, we can make our vampire invisible to the camera.

Select your vampire object in the Hierarchy, then select Add Layer… in the Layer drop-down list in the Inspector to create a new layer, like so:

Create a new layer

Create a new layer

Type the new layer’s name in the User Layer 8 field, and that name should be ‘vampire’.

layer2

Call it ‘vampire’

With the vampire object selected in the Hierarchy, set its layer to vampire:

vampire

Setting the layer doesn’t do anything right now, but it will take effect once we’ve done a couple more things.

Create a Render Texture

Right-click anywhere in the Assets folder and select Create > Render Texture. A new Render Texture asset is created. Name it SecurityCameraTexture.
Create a Render Texture

Create a Render Texture

With SecurityCameraTexture selected, set its size to 480×270 in the Inspector. The size determines its resolution, including the .PNG image that will be created from the camera view.
Set the Render Texture's size

Set the Render Texture’s size

Create a Material from the Render Texture

 Create a new material using the SecurityCameraTexture you just created:
  1.  Right-click anywhere in the Assets folder
  2. Choose Create > Material, and name it SecurityFootage
  3. With the new material selected, change its Shader property (in the Inspector) to Mobile/Diffuse (you need to make it a material that accepts a texture, which it doesn’t by default).
  4. Drag SecurityCameraTexture into the material’s Texture property (the little box in the upper-right corner with the mountain picture in it):
    material

    Create the material

    You’ve now created a material that will display the SecurityCameraTexture on any surface it’s applied to.

Security Camera

Add a new camera to the scene (Main Menu > GameObject > Camera).
Rename the new camera to SecurityCamera.
Drag SecurityCameraTexture into SecrityCamera‘s Target Texture field. This makes your camera’s view go into the render texture instead of onto the screen, as if the camera is recording footage instead of just displaying it to the game screen.
When the camera is selected you will see a small preview of what it can see in the Scene window:
cam_view

When a camera is selected its view is shown in a preview window inside the Scene view. Your scene won’t look quite like this image yet

Move SecurityCamera to a position where it can see all  your objects and the vampire. You’ll need to make sure the camera is in front of your scene in 3D space so it can look into the scene at your objects. When you can see everything (not the TV screen though) in the Camera Preview window you can move to the next step.

Filter out the Vampire

In my image above you can’t see the vampire in the preview (also the objects are displayed on the TV screen, but we’ll get to that bit soon). To filter out the vampire, select SecurityCamera in the Hierarchy, then remove the vampire layer from its Culling Mask (so it doesn’t ‘see’ anything assigned to the vampire layer):

  1. Select SecurityCamera in the Hierarchy
  2. In the Inspector, drop-down the Culling Mask list
  3. Untick the vampire layer (ticked layers are the layers this camera can see).
culling_Mask

Filter out anything in the vampire layer

 If the vampire is still visible in your camera preview, go back and make sure you’ve set the vampire’s layer to vampire.

Build a TV

Add a Plane object to your scene (Main Menu > GameObject > 3D Object > Plane). Rename the Plane to TV Screen.

If you’ve not used planes before it can be a little tricky. Because a plane is a flat, 2D surface it may not be visible depending on its orientation and your current view. Rotate it until it is a flat rectangle facing the camera. Switching between 3D and 2D scene views can help you shape it correctly.

Manipulate TV Screen until it fills your TV sprite’s screen. Make sure it is placed just in front of the actual TV sprite so it is visible to the main camera.

Drag SecurityFootage onto TV Screen‘s Materials > Element 0 property (you’ll need to expand the Materials list like in the screen below):

plane_mat

Set the plane’s material as the SecurityFootage you previously created

Now you’ve assigned the material to the TV screen. As you’ll recall from the previous step, this material will display whatever the security camera sees.

If your TV image appears upside down you will need to rotate your plane to get it looking correct.

That’s It!

You don’t even need to run the scene to see the scene objects (except for the vampire) displayed on the TV screen. Awesome.

Let’s run through the basic steps we just did:

  1. Created a Render Texture
  2. Created a camera that draws what it sees onto that Render Texture
  3. Created a material that displays the Render Texture
  4. Finally, created a TV screen made out of that material

So, like a real security camera, we are capturing vision and sending it to a screen via a kind of recording device (the Render Texture is kind of like film in a camera).

Enhancements

The sample project linked above contains a couple of extra scripts. The first script adds some user controls so you can move the security camera and toggle the vampire on and off; the second script takes the security camera’s view and saves it as a .PNG image file when you press the ‘S’ key. The second script is listed and explained below.

Saving the Render Texture

I adapted this code from the great Unity Answers post by ‘Mate-O’ (http://answers.unity3d.com/questions/22954/how-to-save-a-picture-take-screenshot-from-a-camer.html).
 The code is quite simple – it just reads the Render Texture’s pixels and encodes them to a .PNG, and finally saves the .PNG. The comments explain what each part of the code is doing.
using UnityEngine;
using System.Collections;
using System;

public class CameraSnapshot : MonoBehaviour
{
[SerializeField]
RenderTexture securityCameraTexture;  // drag the render texture onto this field in the Inspector
[SerializeField]
Camera securityCamera; // drag the security camera onto this field in the inspector

void LateUpdate()
{

    if (Input.GetKeyDown("s"))
    {
        StartCoroutine(SaveCameraView());
    }

}

public IEnumerator SaveCameraView()
{
    yield return new WaitForEndOfFrame();

    // get the camera's render texture
    RenderTexture rendText= RenderTexture.active;
    RenderTexture.active = securityCamera.targetTexture;

    // render the texture
    securityCamera.Render();

    // create a new Texture2D with the camera's texture, using its height and width
    Texture2D cameraImage= new Texture2D(securityCamera.targetTexture.width, securityCamera.targetTexture.height, TextureFormat.RGB24, false);
    cameraImage.ReadPixels(new Rect(0, 0, securityCamera.targetTexture.width, securityCamera.targetTexture.height), 0, 0);
    cameraImage.Apply();
    RenderTexture.active = rendText;

    // store the texture into a .PNG file
    byte[] bytes = cameraImage.EncodeToPNG();

    // save the encoded image to a file
    System.IO.File.WriteAllBytes(Application.persistentDataPath + "/camera_image.png", bytes);
}
}

When this script is added to the scene, you can press the ‘s’ key to get a snapshot of the camera. You can then access the saved file in your game.

Summary

A Render Texture is a canvas that you can draw onto. By assigning a Render Texture as a camera’s output you tell that camera to draw what it sees onto the Render Texture.

Since a Render Texture is a texture, you can assign it to a material. Then you can add that material to an object and effectively project the Render Texture’s contents onto that object’s surface.

The security camera is a great metaphor for how it works. The camera is the camera, the Render Texture is the video recording, and the material is the screen you project the video onto.

What Next?

You should now understand how to use Render Textures, and can adapt this technique for any purpose. The .PNG output option also opens up a lot of potential. Render Textures were not available to non-Pro Unity users before Unity 5 opened up the feature (and many others), so kudos to Unity for making their great tool even greater.

Some ideas for using these techniques:

  • Combining sprites to form a new image that you save to .PNG and use in the game (e.g. composing a face by adding different features together).
  • Infra-red cameras that can see creatures invisible to the naked eye.
  • See if you can work out a way to modify the camera output (e.g. make the TV screen black-and-white or green like an old computer screen).