Hi there. I’m the author of NatCorder, a video recording API for Unity. Ever since upgrading from Unity 2019.4.5 to 2019.4.18, I’ve stumbled upon a bug in the UI system that wasn’t there before:
I’m using a canvas scaler on a UI canvas that’s set to ‘screen space - camera’, allowing it to be rendered to texture. I have a reference resolution set to some high resolution (currently, 1440x2560) but in code, I’m rendering the game camera to a texture that is (720x1280). Note that because the aspect ratios are the same, and because the canvas scaler is set to match width or height evenly (0.5 on the slider), the canvas scaler should be doing a linear down-scaling. Heres how it looks in editor:
But when I render it to texture using the following code:
// Render the screen
var reTex = RenderTexture.GetTemporary(720, 1280, 24);
uiCamera.targetTexture = reTex;
uiCamera.Render();
uiCamera.targetTexture = null;
// Write out
var tex2D = new Texture2D(reTex.width, reTex.height);
RenderTexture.active = reTex;
tex2D.ReadPixels(new Rect(0, 0, tex2D.width, tex2D.height), 0, 0);
var jpgData = tex2D.EncodeToJPG();
var path = Path.Combine(Directory.GetCurrentDirectory(), "screenshot.jpg");
File.WriteAllBytes(path, jpgData);
The screenshot comes out like so:
I’ve tracked the problem down to this line in
CanvasScaler:: HandleScaleWithScreenSize
:
Vector2 screenSize = new Vector2(Screen.width, Screen.height);
I’m not sure what might have changed, because before this was never an issue. The fix is simple enough, something like the following:
var screenSize = Camera.current.targetTexture ?
new Vector2(Camera.current.targetTexture.width, Camera.current.targetTexture.height) :
new Vector2(Screen.width, Screen.height);
Which produces the expected:
But this is only a partial fix. The other half, so to speak, is listening to Camera.onPreCull and re-calculating the scale factor each time it’s called. The problem is that I can’t get this to work for some reason. Instead, I have to explicitly have
HandleScaleWithScreenSize
called before I call Camera::Render
. Any ideas?