You can use Unity’s RenderTexture functionality to create some cool effects, and in this tutorial I’ll show you how to create an in-game security camera that projects a camera’s view onto an in-game TV 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.
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.
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.
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.
Create a New Project
Create a new 3D Unity project.
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.
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.
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:
Type the new layer’s name in the User Layer 8 field, and that name should be ‘vampire’.
With the vampire object selected in the Hierarchy, set its layer to vampire:
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
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.
Create a Material from the Render Texture
Create a new material using the SecurityCameraTexture you just created:
- Right-click anywhere in the Assets folder
- Choose Create > Material, and name it SecurityFootage
- 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).
- Drag SecurityCameraTexture into the material’s Texture property (the little box in the upper-right corner with the mountain picture in it):
You’ve now created a material that will display the SecurityCameraTexture on any surface it’s applied to.
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:
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):
- Select SecurityCamera in the Hierarchy
- In the Inspector, drop-down the Culling Mask list
- Untick the vampire layer (ticked layers are the layers this camera can see).
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.
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):
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.
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:
- Created a Render Texture
- Created a camera that draws what it sees onto that Render Texture
- Created a material that displays the Render Texture
- 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).
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
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.
public class CameraSnapshot : MonoBehaviour
RenderTexture securityCameraTexture; // drag the render texture onto this field in the Inspector
Camera securityCamera; // drag the security camera onto this field in the inspector
public IEnumerator SaveCameraView()
yield return new WaitForEndOfFrame();
// get the camera's render texture
RenderTexture rendText= RenderTexture.active;
RenderTexture.active = securityCamera.targetTexture;
// render the texture
// 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);
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.
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.
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).