Stumbling over Unity3D: Fixed Resolution

ProgDozer
3 min readDec 20, 2017

--

Tilemaps weren’t the first thing I ran into that gave me problems out of the gate with my new game. Another thing you usually care about with retro games is actually having a fixed, low-resolution display. You want those pixels, you want to be rendering at NES or Gameboy resolutions, and you want it to preserve that aspect ratio when you play in other resolutions. In particular, I’m targeting the DOS demograph, so that means a 320x240 internal resolution. Except Unity doesn’t really have the concept of an Internal Resolution.

In LibGDX when I made C:\raft I used the Scene2D, passed it a camera with a scaling viewport that preserves aspect ratio, and set the dimensions of the viewport to a fixed value. I did some fun trickery on top of that with rendering to a texture, but that was solely for the palette swapping shader and for cleaner scaling because before I was getting distorted pixels. Godot’s viewport comes out of the box with the ability to have an base resolution and set the way things scale for you!

Unity makes things a bit tough, as it tries to make things easier for high resolution games that can benefit from a flexible, scalable UI. Text heavy UIs with tons of windows look weird with deadspace around them, though. If you designed your assets around your fixed resolution, they can also scale horribly or have blank space around them. You can’t just rely on the resolution/aspect ratio settings in the Player settings of your project, either, because they don’t work too well for Fullscreen, and they have no impact at all in the editor’s Game View when you’re testing things.

How I did a render texture in LibGDX for fun ended up becoming an actual requirement to get a fixed resolution in Unity with preserved aspect ratio. My scene consists of 2 cameras and 2 canvases now. Camera 1, which renders to the 320x240 texture, is for Canvas 1, which is set to scale at a constant pixel rate and contains my actual scene’s UI. Rendering to the texture actually will make the camera fixed to that size, and thus so will be the camera, so I can draw to it in pixel units if I feel like it (I did). Then the next step was actually rendering the texture, which is what the second camera and canvas were for. The second canvas actually scales to the screen viewport while preserving the aspect ratio, only drawing the raw image of the render texture in it. This positions the texture properly and letterboxes it. All good!

Except it’s not. All this fiddling with canvases and scaling, I forgot an important part. The original canvas isn’t scaled with the game screen, but it still exists in the scene, and I need it to because there’s buttons and stuff. I had been accustomed to things that could scale my viewport also scaling the input within it, so of course once I had to separate it into 2 steps things because disconnected. Painfully, you can’t just tell the EventSystem to scale its input or say which camera specifically it should be using, else I could easily just tell it to use the camera that’s rendering to a texture instead of the one projecting to the display.

So I did something I really didn’t want to do and ended up having to write another script, this time to override input processing for the mouse. Thankfully a Unity’s UI code is on Bitbucket because I guess they know people will want to override the crap out of it since it just doesn’t do what anyone wants.

I know how the texture is going to be positioned on scaled, so I recreated those calculations and override Unity’s UI processing of mouse input. By scaling input to where the render texture supposedly is and to its size, the GraphicsRaycaster of the GUI actually detects properly and I finally have a working UI again that now works in any resolution.

Seriously, this could have been avoided if things just weren’t so disjointed.

Shout out to Ocias for the Pixel Art Camera, which I used for my render textured camera/canvas. This allowed my fixed resolution view to scale beautifully and be pixel aligned.

--

--

ProgDozer

Disgruntled and opinionated writing about programming and the state of software. @nhydock