Texture2D.ReadPixels unknown error "not inside drawing frame"

I am getting this error when running ReadPixels on a Texture2D object.

ReadPixels was called to read pixels from system frame buffer, while not inside drawing frame.
UnityEngine.Texture2D:ReadPixels(Rect, Int32, Int32, Boolean)

The code was not erroring before so I don’t know what’s changed (it’s a simple script, not much to go wrong). I’m using this to take a snapshot of the screen, which I then fade out to create fading transitions between cameras etc. The strange thing is it still works perfectly (the screen is successfully captured into a Texture2D object), however this error has started showing.

I’ve tried searching for the whole error and parts of it on Google and I can’t find a single result. Can anyone shed some light on this error?

Have you tried putting this code into a Coroutine? Perhaps the timing of the screen capture is off, and this is causing the complaint. Give it a shot and let us know if it works.

To do this:

  1. Put your screen capture code in a method, and give it the “IEnumerator” return type.

  2. At the beginning of the method, add the following line (C#):

yield return new WaitForEndOfFrame();

  1. Call your method like this (C#):

StartCoroutine(methodName());

Here is a script component that should allow capturing a RenderTexture without waiting for the next main rendering to finish. Attach it to your camera and immediately after calling camera.Render(), RenderResult will contain a texture in system memory containing the render result. The works because ReadPixels is executed while the “drawing Frame” of the camera is still active.

using UnityEngine;

public class CameraCapture : MonoBehaviour
{
	public Texture2D RenderResult;
	
	void OnPostRender () 
	{
		Camera owner = GetComponent< Camera >();
		RenderTexture target = owner.targetTexture;
		
		if( target == null )
			return; 
		
		RenderResult = new Texture2D( target.width, target.height, TextureFormat.ARGB32, true );
		Rect rect = new Rect( 0, 0, target.width, target.height );
		RenderResult.ReadPixels( rect, 0, 0, true );
	}
}

I have a method that generates the error above. The method does a on time immediate render of GL graphics to a RenderTexture and onwards to a Texture2D using ReadPixels(). Is this no longer possible? Do I have to set a flag when I need a texture, then wait for the end of the frame to create it and return it to an event handler?