1
\$\begingroup\$

I am creating a 2D game for Android as a school project.

Game Sceenshot

The objective of the game is to find differences between the top image and the bottom image.

I have 1 main camera, which views the entire scene (the hub and a central image) - I am not using a canvas.

The two views of my scene are drawn with two additional cameras, using the viewport rect to shape them to the top and bottom panes.

The player can zoom the views of these cameras in sync, to look at details in the two images. I do this by modifying the viewport rect of the cameras.

Both image views zoomed in on the same tree in the middle

This works for me, but I get inconsistent cropping when I play the game at a different screen resolution.

If I play my game on a different screen resolution, say 720 x 1520, the sides of the images are cropped, so the player can't see the differences there.

Cropped Example

That happens when I use this code, let's call it "A":

using System;
using System.Collections;
using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class aaaaaaa : MonoBehaviour
{
    #region FIELDS
    public Color wireColor = Color.white;
    public float UnitsSize = 1; // size of your scene in unity units
    public Constraint constraint = Constraint.Portrait;
    public static aaaaaaa Instance;
    public new Camera camera;

    private float _width;
    private float _height;
    //*** bottom screen
    private Vector3 _bl;
    private Vector3 _bc;
    private Vector3 _br;
    //*** middle screen
    private Vector3 _ml;
    private Vector3 _mc;
    private Vector3 _mr;
    //*** top screen
    private Vector3 _tl;
    private Vector3 _tc;
    private Vector3 _tr;
    #endregion

    #region PROPERTIES
    public float Width
    {
        get
        {
            return _width;
        }
    }
    public float Height
    {
        get
        {
            return _height;
        }
    }

    // helper points:
    public Vector3 BottomLeft
    {
        get
        {
            return _bl;
        }
    }
    public Vector3 BottomCenter
    {
        get
        {
            return _bc;
        }
    }
    public Vector3 BottomRight
    {
        get
        {
            return _br;
        }
    }
    public Vector3 MiddleLeft
    {
        get
        {
            return _ml;
        }
    }
    public Vector3 MiddleCenter
    {
        get
        {
            return _mc;
        }
    }
    public Vector3 MiddleRight
    {
        get
        {
            return _mr;
        }
    }
    public Vector3 TopLeft
    {
        get
        {
            return _tl;
        }
    }
    public Vector3 TopCenter
    {
        get
        {
            return _tc;
        }
    }
    public Vector3 TopRight
    {
        get
        {
            return _tr;
        }
    }
    #endregion

    #region METHODS
    private void Awake()
    {
        camera = GetComponent<Camera>();
        Instance = this;
        ComputeResolution();
    }

    private void ComputeResolution()
    {
        float leftX, rightX, topY, bottomY;

        if (constraint == Constraint.Landscape)
        {
            camera.orthographicSize = 1f / camera.aspect * UnitsSize / 2f;
        }
        else
        {
            camera.orthographicSize = UnitsSize / 2f;
        }

        _height = 2f * camera.orthographicSize;
        _width = _height * camera.aspect;

        float cameraX, cameraY;
        cameraX = camera.transform.position.x;
        cameraY = camera.transform.position.y;

        leftX = cameraX - _width / 2;
        rightX = cameraX + _width / 2;
        topY = cameraY + _height / 2;
        bottomY = cameraY - _height / 2;

        //*** bottom
        _bl = new Vector3(leftX, bottomY, 0);
        _bc = new Vector3(cameraX, bottomY, 0);
        _br = new Vector3(rightX, bottomY, 0);
        //*** middle
        _ml = new Vector3(leftX, cameraY, 0);
        _mc = new Vector3(cameraX, cameraY, 0);
        _mr = new Vector3(rightX, cameraY, 0);
        //*** top
        _tl = new Vector3(leftX, topY, 0);
        _tc = new Vector3(cameraX, topY, 0);
        _tr = new Vector3(rightX, topY, 0);
    }

    private void Update()
    {
#if UNITY_EDITOR
        ComputeResolution();
#endif
    }

    void OnDrawGizmos()
    {
        Gizmos.color = wireColor;

        Matrix4x4 temp = Gizmos.matrix;
        Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
        if (camera.orthographic)
        {
            float spread = camera.farClipPlane - camera.nearClipPlane;
            float center = (camera.farClipPlane + camera.nearClipPlane) * 0.5f;
            Gizmos.DrawWireCube(new Vector3(0, 0, center), new Vector3(camera.orthographicSize * 2 * camera.aspect, camera.orthographicSize * 2, spread));
        }
        else
        {
            Gizmos.DrawFrustum(Vector3.zero, camera.fieldOfView, camera.farClipPlane, camera.nearClipPlane, camera.aspect);
        }
        Gizmos.matrix = temp;
    }
    #endregion

    public enum Constraint { Landscape, Portrait }
}

I can still zoom with this code, but it doesn't help the player see the cropped parts:

Zoomed, but still cropped

I tried using an alternative code, call it "B", but I have the opposite problem.

The image looks whole (there are black spaces above and below, but I suppose that is not a problem) but when I zoom, the images get too large and overlap my controls.

Code B example Code B zoomed in, overlapping controls

Here is the "B" code that does this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class ssadzxcz : 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;
    }
}

How can I solve this, to show my whole image and zoom correctly?

Thank you very much for your help, it really is very valuable to me. In the editor, the image appears in a renderer sprite (it's just an image, duplicated above and below) I have tried to use canvas and a texture that draws the image when I activate the zoom, but I did not get that when touching an area of the image it detected the colliders of the main image. The player touches with the finger the area of the image that he wants, and the differences would be marked by an invisible collider for him, if he touches one of them the success will be marked, and if he is wrong, he will lose a life.

\$\endgroup\$
  • \$\begingroup\$ Thank you, this is much clearer now with the images and code you've added. I've tried to reorganize your question to help it read smoothly. Can you tell us, the two images you're showing through each camera, are they just textures? Displayed on SpriteRenderers, Quads, or UI Image components? Or is there something the cameras need to composite together to produce each image? How do you handle the player clicking on the regions that are different? \$\endgroup\$ – DMGregory Apr 17 at 17:06
  • \$\begingroup\$ It looks like you signed in with your other account again. Remember to sign in with the account that created this question, so that you can reply with comments, or edit your question without waiting for approval. \$\endgroup\$ – DMGregory Apr 20 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.