Kyle Banks

Create a Fullscreen Background Image in Unity2D with a SpriteRenderer

Written by @kylewbanks on Dec 24, 2016.

A common requirement for 2D games is to have some sort of fullscreen background, be it a color, sprite, particle system, or anything else, to provide mood and aesthetic to the contents of your game. While a static color can be used to great effect, this post will go over the technique that I use for fullscreen background images in Unity using a standard SpriteRenderer and just a little touch of code to retain the original image’s aspect ratio. Maintaining the image’s aspect ratio prevents it from being stretched or squished, and it’s important due to the wide array of screen sizes available to mobile and desktop users alike.

When I originally set about to write the code for this, it took longer than I’d care to admit because I wasn’t thinking properly about how Unity handles scale. I had originally intended to maintain the aspect ratio on the scale itself using the same logic you would use to resize or crop an image, yet after writing the logic to do this I just couldn’t get the image to maintain it’s proper aspect ratio. I stared at and tweaked the math time and time again, yet the image would still be stretched. This was especially frustrating considering I was certain the math was correct, which it was, however Unity scale is not related to the actual resolution of the Sprite! Finally I realized, as I’ll show below, that Unity makes this much simpler than I had originally envisioned.

Setup

The first thing we’ll need is an actual background image. I’ll be using this image, but feel free to use whatever image you like.

Next we’ll need a GameObject, I’ll be calling mine Background, with a SpriteRenderer component. Go ahead and attach your preferred background image to the SpriteRenderer in the Sprite property, and you should have a setup like so:

Background GameObject
Unscaled background image

The only problem is, depending on the size of your image and the target device resolution, your image likely won’t fit perfectly and you’ll end up with something like the image to the right.

What we could do is set the scale of the Background to match the camera size in the editor, but you won’t have much luck running on actual devices considering the width of the Unity camera is dynamic (while the height always remains constant), and scales based on the resolution of the device you’re running on. A better solution would be to write a little code to dynamically scale the Background as needed.

All we’ll need to do is set the scale of the Background based on it’s Sprite’s size compared to the size of the Camera at runtime, and maintain the aspect ratio of the original image. As we’ll see in the code below, Unity actually makes maintaining the aspect ratio really easy for us.

The Script

What we’ll do is create a new script called FullscreenSprite, and attach it to the Background GameObject like so:

Attack new FullscreenSprite script to Background GameObject

As for the actual contents of the code, we’ll start off by simply grabbing a reference to the attached SpriteRenderer to determine the size of the sprite, as well as the size of and camera we’re working with:

void Awake() {
    SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();

    float cameraHeight = Camera.main.orthographicSize * 2;
    Vector2 cameraSize = new Vector2(Camera.main.aspect * cameraHeight, cameraHeight);
    Vector2 spriteSize = spriteRenderer.sprite.bounds.size;   
}

As you can see, we start off by grabbing the SpriteRenderer component. Next we determine the height of the camera using the orthographicSize property, which is essentially half the camera’s height in Unity units (not pixels). By default this is 5. We determine the full cameraSize using the height we already calculated, and multiplying it by the camera’s aspect ratio to determine the width (aspect ratio = width / height). Finally, the spriteSize is simply grabbed from the SpriteRenderer’s sprite.

The next thing we’ll need to do is to determine what scale we need in order to fill the camera:

Vector2 scale = transform.localScale;
if (cameraSize.x >= cameraSize.y) { // Landscape (or equal)
    scale *= cameraSize.x / spriteSize.x;
} else { // Portrait
    scale *= cameraSize.y / spriteSize.y;
}

We determine if the camera is in a landscape (or equal) orientation, or portrait using the cameraSize we calculated in the previous step, and comparing it’s x (width) to it’s y (height). Based on the orientation, we multiply the current scale with either the width or height of the camera, divided by the corresponding width or height of the sprite.

For instance, if your cameraSize is 9, 5 and your spriteSize is 4, 3, we’ll be multiplying the scale by cameraSize.x / spriteSize.x = 9 / 4 = 2.25. Likewise if your camera were 5, 9 we’d multiply the scale by cameraSize.y / spriteSize.y = 9 / 3 == 3. The purpose is to scale the sprite to match the larger dimension of the camera’s size.

The resulting scale maintains the aspect ratio of the image, because Unity assigns the GameObject with a scale of 1, 1 by default, even if the image is 1000x500 pixels, for example. If an image is 1000x500 and you set the scale to 2, 2, the rendered image would be 2000x1000 - the exact same aspect ratio. We use this to our advantage because as long as we keep the X and Y scale as the same value, we don’t have to do any extra aspect ratio calculation, it’s all handled internally by Unity anyways!

The last thing we need to do is simply apply the new scale:

transform.position = Vector2.zero; // Optional
transform.localScale = scale;

You’ll see I’m also setting the position to 0, 0 here. This is entirely optional, I just like to add this when appropriate to ensure that even if the Background is accidentally moved in the Unity editor, it’s set to the appropriate position at runtime.

The only thing left to do now is to run the game and see the background image in all it’s fullscreen glory:

Fullscreen Images in Unity2D

The red lines within the scene editor indicate the bounds of the camera, and as you can see, whether the game is run in landscape or portrait orientation, the image is scaled accordingly and maintains it’s aspect ratio!

And just in case anything wasn’t clear while following along, here’s the full script:

using UnityEngine;

public class FullscreenSprite : MonoBehaviour {
    
    void Awake() {
        SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
        
        float cameraHeight = Camera.main.orthographicSize * 2;
        Vector2 cameraSize = new Vector2(Camera.main.aspect * cameraHeight, cameraHeight);
        Vector2 spriteSize = spriteRenderer.sprite.bounds.size;
        
        Vector2 scale = transform.localScale;
        if (cameraSize.x >= cameraSize.y) { // Landscape (or equal)
            scale *= cameraSize.x / spriteSize.x;
        } else { // Portrait
            scale *= cameraSize.y / spriteSize.y;
        }
        
        transform.position = Vector2.zero; // Optional
        transform.localScale = scale;
    }
}

And that’s all there is to it! As I said in the intro, I wanted to write this post because as I was initially developing the logic, I wasn’t taking into account the way Unity scales sprites. I was thinking more in terms of image resizing where you need to actually calculate and use the aspect ratio when determining the width and height to scale to. Hopefully this post will be helpful to anyone making the same mistakes I was!

Let me know if this post was helpful on Twitter @kylewbanks or down below!