12
\$\begingroup\$

My background and gameobjects are 2d sprites not UI images ,I want to know how to make my background scale with screen size and positions of 2d sprits on it don't change after building game (webGl) like scale canvas with screen size and anchor points in UI elements .

Before building the game enter image description here

After building enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ It looks like your content has scaled perfectly to match the height of your display area. Would you like it to scale to match the width instead? Note that this will mean you show more area above and below the currentlt displayed content, which depending on your setup might reveal gaps or require letterboxing. \$\endgroup\$
    – DMGregory
    Commented Jan 21, 2019 at 12:12
  • \$\begingroup\$ I want to make it to match the width like it match the height of my display area. and don't display the blue area of the camera \$\endgroup\$
    – Sh.Adel
    Commented Jan 21, 2019 at 12:29

3 Answers 3

22
\$\begingroup\$

You can adjust the camera's height so it scales with the width of the screen like so:

(Place this script on your Camera object)

[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class MatchWidth : MonoBehaviour {

    // Set this to the in-world distance between the left & right edges of your scene.
    public float sceneWidth = 10;

    Camera _camera;
    void Start() {
        _camera = GetComponent<Camera>();
    }

    // Adjust the camera's height so the desired scene width fits in view
    // even if the screen/window size changes dynamically.
    void Update() {
        float unitsPerPixel = sceneWidth / Screen.width;

        float desiredHalfHeight = 0.5f * unitsPerPixel * Screen.height;

        _camera.orthographicSize = desiredHalfHeight;
    }
}

If you're using a perspective camera, then instead you'd use...

public float horizontalFoV = 90.0f;

// ...

void Update() {
   float halfWidth = Mathf.Tan(0.5f * horizontalFoV * Mathf.Deg2Rad);

   float halfHeight = halfWidth * Screen.height / Screen.width;

   float verticalFoV = 2.0f * Mathf.Atan(halfHeight) * Mathf.Rad2Deg;

   _camera.fieldOfView = verticalFoV;
}

If you want to shrink your viewport to add letterboxes instead of showing additional height above/below, you can use the technique described in this answer.

\$\endgroup\$
5
  • \$\begingroup\$ Is there any drawback to using this script to always scale my camera rather than having to write flexible code all the time? I don't see why this isn't a built-in way to apply this technique in-engine. \$\endgroup\$
    – Pop Car
    Commented Aug 10, 2020 at 19:05
  • \$\begingroup\$ I'd suspect it's not built-in because it's trivial to write for ourselves in the rare instances when we need it. An event-based approach would be a bit more efficient than the update polling I show above, but overall the cost of this script should be very minor. \$\endgroup\$
    – DMGregory
    Commented Aug 10, 2020 at 19:10
  • 3
    \$\begingroup\$ I suspect you don't wanna do this in Update, but rather with every orientation change, window resize, etc. \$\endgroup\$
    – ecv
    Commented Feb 21, 2021 at 21:50
  • \$\begingroup\$ Minor question: why is the field called "orthographicSize", whereas in the Inspector it is called "Size"? I thought fields have the same name in the inspector as in the code. \$\endgroup\$ Commented Nov 14 at 17:57
  • \$\begingroup\$ The field is called "orthographic size" because it applies only when the camera is in orthographic (not perspective) mode. That clarification is not needed in the inspector, because when the camera is not in orthographic mode, this field is not displayed at all, so they can get away with a shorter name without misleading an inspector user that this will affect perspective cameras. \$\endgroup\$
    – DMGregory
    Commented Nov 14 at 18:02
0
\$\begingroup\$

Using 2D, you likely don't want to manipulate the camera. I recommend adjusting the scale of the background object (container or sprite).

[SerializeField] private Camera mainCamera;
[SerializeField] private SpriteRenderer spriteRenderer;

private void Start() {
    var spriteBounds = spriteRenderer.bounds; // Sprite to fit viewport
    var worldScale = mainCamera.ViewportToWorldPoint(Vector3.one);
    var localScale = 2 * Math.Max(
        worldScale.x / spriteBounds.size.x * transform.localScale.x,
        worldScale.y / spriteBounds.size.y * transform.localScale.y);

    transform.localScale = new Vector3(localScale, localScale, 1);
}

You can apply this script to the background sprite itself or to a container which holds the background sprite.

\$\endgroup\$
-1
\$\begingroup\$

I think if you decrease the scale size to 1x from above the Game view, it will fit.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .