If you own a Unity Pro license you are able to draw the screen content to a texture by using a RenderTexture. An alternativ way for Unity Free users is the usage of Texture2D.ReadPixels. It can be used to capture the whole screen of the application or just a smaller part of it. In this post I explain an implementation of a screenshot functionality that I used in my current project: a mobile game named Gezz.

The screenshot camera should do the following things: Capture a defined part of the screen, put it into a Texture2D instance and fire an event if the screenshot has been made, so the application can do things with it (e.g. save it to disk or share it on twitter etc.).

The ScreenshotCamera class consists of two methods: TakeScreenshot & OnPostRender.

TakeScreenshot method

The first one should be called by another script like a button callback function for instance.

	public void TakeScreenshot (float startX, float startY, float endX, float endY)
	{
		oldAntiAliasingSettings = QualitySettings.antiAliasing;
		QualitySettings.antiAliasing = 0;
		captureRect = new Rect (startX, startY, endX - startX, endY - startY);
		noAACountdown = 2;
		capturing = true;
	}

To get a clean shot we first need to turn off AntiAliasing for the moment. The old AA-setting will be restored afterwards. To do this we store the old settings before changing AA to zero. Then the rectangle defining the screen part to be copied is instantiated.  The countdown value is used to make sure that the changes to the AntiAliasing settings have taken effect. Add one for each frame to wait before the screen will be captured. Lastly a flag named capturing is set. This is important for the second method of the ScreenshotCamera behaviour.

OnPostRender

The OnPostRender method is called every frame after the camera has finished rendering the screen. If the flag capturing is set true it will decrement the countdown until it reaches zero. If this is the case, the screen will be captured. For this a Texture2D instance is created using the dimensions of the previously created rectangle. Then the ReadPixels call gets the pixels from the screen and fills the texture. The capturing flag is then set to false again and the old AntiAliasing settings are restored. Now the ScreenshotCamera fires an event to let all waiting scripts know that the screen has been captured and the texture is ready to be used.

	void OnPostRender ()
	{
		if (capturing)
		{
			noAACountdown--;
			if (noAACountdown > 0)
				return;

			screenshot = new Texture2D (Mathf.RoundToInt (captureRect.width), Mathf.RoundToInt (captureRect.height), TextureFormat.ARGB32, false);
			screenshot.ReadPixels (captureRect, 0, 0, false);
			screenshot.Apply ();

			capturing = false;

			QualitySettings.antiAliasing = oldAntiAliasingSettings;

			if (ScreenReadyEvent != null)
				ScreenReadyEvent ();
		}
	}

The ScreenshotCamera behaviour 

And this is the complete script. You can simply copy it and attach it to a camera. Btw: This also works for mobile games.

using UnityEngine;
using System.Collections;

public class ScreenshotCamera : MonoBehaviour
{

	public delegate void ScreenReadyEventDelegate ();

	public event ScreenReadyEventDelegate ScreenReadyEvent;

	public Texture2D screenshot { get; private set; }

	private bool capturing = false;

	private Rect captureRect;

	private int oldAntiAliasingSettings;

	private int noAACountdown;

	public void TakeScreenshot (float startX, float startY, float endX, float endY)
	{
		oldAntiAliasingSettings = QualitySettings.antiAliasing;
		QualitySettings.antiAliasing = 0;
		captureRect = new Rect (startX, startY, endX - startX, endY - startY);
		noAACountdown = 2;
		capturing = true;
	}

	void OnPostRender ()
	{
		if (capturing)
		{
			noAACountdown--;
			if (noAACountdown > 0)
				return;

			screenshot = new Texture2D (Mathf.RoundToInt (captureRect.width), Mathf.RoundToInt (captureRect.height), TextureFormat.ARGB32, false);
			screenshot.ReadPixels (captureRect, 0, 0, false);
			screenshot.Apply ();

			capturing = false;

			QualitySettings.antiAliasing = oldAntiAliasingSettings;

			if (ScreenReadyEvent != null)
				ScreenReadyEvent ();
		}
	}

}