For desktop games you can control the supported aspect ratios directly in
Edit -> Project Settings -> Player -> Resolution and Presentation
But for mobile, or situations where your aspect ratio might change during play (eg. resizing a window dynamically), or you want to use letterboxing for artistic effect, we'll need an in-game solution.
You can attach the following script to your Camera to resize its viewport to fill the biggest, centered rectangle of your target aspect ratio that will fit in your current screen/window.
Note that this won't on its own set the resolution of the frame buffer you're rendering to. If you want to render only eg. 640x480, I'd recommend setting up your camera to render to a RenderTexture
with that resolution. Then you can present the resulting texture to the screen using a screenspace overlay canvas with a RawImage
, or a second camera.
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class CameraCrop : MonoBehaviour {
// Set this to your target aspect ratio, eg. (16, 9) or (4, 3).
public Vector2 targetAspect = new Vector2(16, 9);
Camera _camera;
void Start () {
_camera = GetComponent<Camera>();
UpdateCrop();
}
// Call this method if your window size or target aspect change.
public void UpdateCrop() {
// Determine ratios of screen/window & target, respectively.
float screenRatio = Screen.width / (float)Screen.height;
float targetRatio = targetAspect.x / targetAspect.y;
if(Mathf.Approximately(screenRatio, targetRatio)) {
// Screen or window is the target aspect ratio: use the whole area.
_camera.rect = new Rect(0, 0, 1, 1);
}
else if(screenRatio > targetRatio) {
// Screen or window is wider than the target: pillarbox.
float normalizedWidth = targetRatio / screenRatio;
float barThickness = (1f - normalizedWidth)/2f;
_camera.rect = new Rect(barThickness, 0, normalizedWidth, 1);
}
else {
// Screen or window is narrower than the target: letterbox.
float normalizedHeight = screenRatio / targetRatio;
float barThickness = (1f - normalizedHeight) / 2f;
_camera.rect = new Rect(0, barThickness, 1, normalizedHeight);
}
}
}
Because this doesn't change your camera's FoV or Height settings, the composition of game content displayed inside the camera view will stay the same - it will just grow or shrink the whole view to fit in the new crop.
Out of the box, the letterbox / pillarbox bars will just be the default colour of the framebuffer (generally cleared to black). You can fill these areas with graphics using a screenspace overlay canvas or additional cameras.