I have a perspective camera which has bounds which I wish to constrain within larger bounds. All the bounds are calculated in world space.
The code for containing the camera within the constraining bounds is straightforward:
var camRect = this.cameraComponent.GetCameraWorldRect();
var correction = Vector3.zero;
if (camRect.xMin < constrainingRect.xMin)
{
correction.x += Mathf.Abs(constrainingRect.xMin - camRect.xMin);
}
if (camRect.xMax > constrainingRect.xMax)
{
correction.x -= Mathf.Abs(constrainingRect.xMax - camRect.xMax);
}
if (camRect.yMin < constrainingRect.yMin)
{
correction.y += Mathf.Abs(constrainingRect.yMin - camRect.yMin);
}
if (camRect.yMax > constrainingRect.yMax)
{
correction.y -= Mathf.Abs(constrainingRect.yMax - camRect.yMax);
}
this.cameraComponent.transform.position += correction;
This can be visualized as:
The problem I am facing is that I have a UI object that is covering the right hand side of the screen and I am uncertain how to correctly calculate the width of the UI object so that the constrained camera bounds can take it into account.
The camera that is drawing the UI object is configured as follows:
The camera that is being constrained is configured as follows:
Apart from the layer, the parameters which affect the rendering of the objects for each camera configuration are the same.
The UI object has the following configuration with a Canvas Renderer:
This is how I am currently attempting to calculate to width of the UI object but given that the UI is being rendered using a perspective camera I wasn't too certain that ScreenToWorldPosition was correct.
private float CalculateMenuWidth()
{
// Generate padding to account for the side menu
var canvas = LevelEditor.Instance.Menu.GetComponentInParent<Canvas>();
var menuRect = LevelEditor.Instance.Menu.GetComponent<RectTransform>();
var menuRectMax = menuRect.rect.max * canvas.scaleFactor;
var menuRectMin = menuRect.rect.min * canvas.scaleFactor;
if (this.cameraComponent.orthographic)
{
return Mathf.Abs(this.cameraComponent.ScreenToWorldPoint(menuRectMax).x - this.cameraComponent.ScreenToWorldPoint(menuRectMin).x);
}
// Perspective camera requires distance for ScreenToWorldPoint
var distance = Mathf.Abs(this.cameraComponent.transform.position.z);
return Mathf.Abs(this.cameraComponent.ScreenToWorldPoint(new Vector3(menuRectMax.x, 0f, distance)).x - this.cameraComponent.ScreenToWorldPoint(new Vector3(menuRectMin.x, 0f, distance)).x);
}
However, the size of menu returned by the method above appears to be too large.
How can I correctly calculate the width of the UI object so it appears that the camera constraints do not allow the camera to travel past the UI object?
EDIT: I've added a link to a Unity project which is the minimal working example for reproducing the issue.
https://www.dropbox.com/s/mq36mfqz5wvvsch/CameraConstraintGUIIssue.zip
The camera can be controlled with WASD to translate and the Shift key will speed up the movement.
The camera is constrained inside the checkerboard. An offset is created so that the camera should stop moving to the right once the right edge of the checkerboard is adjacent to the left edge of the menu. Unfortunately, I can't seem to calculate the size of the menu correctly so this occurs.
The code for constraining the camera and calculating the menu size is in EditorCamera.cs.
Edit2:
The constraint from KingDolphin
The constraint I am attempting to calculate (quoted from above, An offset is created so that the camera should stop moving to the right once the right edge of the checkerboard is adjacent to the left edge of the menu.):