Supporting Widescreen on a camera clamping script?

I have a script that controls what the bounds of an Orthographic camera are, somewhat loosely based on shieldgenerator7’s answer here, from this thread: https://answers.unity.com/questions/433665/need-help-with-2d-orthographic-camera-zooming.htm

It works ALMOST perfectly. However… when it hits widescreen layouts, it’s got severe jitter issues. It has a tendency to flip back and forth, and never stay in one place after screen sizes past 16:x are tried. The camera itself is rotated slightly by 10 on x, however this otherwise works perfectly for 3:2, 4:3, and 5:4.

Is there any good way to handle widescreen sizes with camera bounding boxes? The script I have so far is below:

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

public class CameraController : MonoBehaviour
{
    public Camera screenCamera;
    public GameObject boundsMarker;
    public Bounds visibleBounds;
    public Transform playerTarget;
   
    [SerializeField]
    float boundingBoxPadding = 2f;

    [SerializeField]
    float minimumOrthographicSize = 5f;
    [SerializeField]
    float zoomSpeed = 20f;

    Vector2 cameraSizeWorld;
    Vector2 halfSize;

    private void Awake()
    {
        screenCamera = GetComponent<Camera>();
    }

    // Start is called before the first frame update
    void Start()
    {
        playerTarget = WorldController.Instance.cameraTarget;
        Vector3 tPos = playerTarget.position;
        tPos.z = -20;
        transform.position = tPos;
    }

    private void FixedUpdate()
    {
        // In case the box gets updated during play //
        visibleBounds = boundsMarker.GetComponent<BoxCollider>().bounds;

        if (playerTarget != null)
        {
            Vector3 tPos = playerTarget.position;
            tPos.z = -20;
            transform.position = tPos;
            updateExtents();
        }
    }

    private void updateExtents()
    {
        cameraSizeWorld = Camera.main.ViewportToWorldPoint(Vector2.one) - Camera.main.ViewportToWorldPoint(Vector2.zero);
        halfSize = cameraSizeWorld / 2;
    }

    private void LateUpdate()
    {
        Vector3 v3 = transform.position;
        v3.x = Mathf.Clamp(v3.x, visibleBounds.min.x + halfSize.x, visibleBounds.max.x - halfSize.x);
        v3.y = Mathf.Clamp(v3.y, visibleBounds.min.y + halfSize.y, visibleBounds.max.y - halfSize.y);
        transform.position = v3;
    }
}
1 Like

I think it might be a timing problem because FixedUpdate and LateUpdate are on separate loops, as this diagram shows:

Try this: instead of using LateUpdate(), make your own “MyLateUpdate()” and make it public, then call it directly at the end of your player’s FixedUpdate(), obviously giving the player a reference to this script in one of the usual Unity ways.

Actually, come to think of it, do that but ALSO combine the code presently in the FixedUpdate() into this new MyLateUpdate(), obviously doing the updateExtents first, then the clamps.

That seems possibly logical… however, it -only- starts happening when the viewing angle goes into Widescreen: Specifically, 16:10 and 16:9 on the Editor. Everything else is just fine. I don’t think that’s an update order issue exactly, but I will test it.

It both did and didn’t work. It now encompasses the entire stage, which it should do… but it also breaks following the target, and doesn’t resize at all with everything outside LateUpdate. I think LateUpdate is essential for this to fully work.

Your updateExtents certainly seems extremely straightforward, as does the clamping.

Why don’t you start putting some of those various values in a debug UI.Text object onscreen and see why comparisons are doing what they’re doing?

Since it is an ortho camera it should not care how wide it is. With a perspective camera I suppose there might be weirdness in the bounds once the lateral FOV width reaches 180 degrees…

The link’s broken now.

But I imagine it might have something to do with the camera view being larger than the bounding box. I never tested such a case. Did you happen to solve this issue already?