Add a system for setting up "real" camera framing to work between devices (#26)
- In-level authoring utility to designate level bounds - Camera Adapter component to be placed on a level's camera to perform the adjustments - EdgeAnchor tool, which allows anchoring of game objects to the screen bounds Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: #26
This commit is contained in:
127
Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs
Normal file
127
Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using UnityEngine;
|
||||
using Unity.Cinemachine;
|
||||
using System;
|
||||
|
||||
namespace AppleHillsCamera
|
||||
{
|
||||
/// <summary>
|
||||
/// Adjusts the camera's orthographic size to match the target width from a ScreenReferenceMarker.
|
||||
/// Works with both regular cameras and Cinemachine virtual cameras.
|
||||
/// </summary>
|
||||
public class CameraScreenAdapter : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Reference that defines the target width to match")]
|
||||
public ScreenReferenceMarker referenceMarker;
|
||||
|
||||
[Tooltip("Whether to adjust the camera automatically on Start")]
|
||||
public bool adjustOnStart = true;
|
||||
|
||||
[Tooltip("Whether to adjust the camera automatically when the screen size changes")]
|
||||
public bool adjustOnScreenResize = true;
|
||||
|
||||
// Event that other components can subscribe to when camera is adjusted
|
||||
public event Action OnCameraAdjusted;
|
||||
|
||||
private Camera _regularCamera;
|
||||
private CinemachineCamera _virtualCamera;
|
||||
private int _lastScreenWidth;
|
||||
private int _lastScreenHeight;
|
||||
private bool _usingCinemachine;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Try to get regular camera first
|
||||
_regularCamera = GetComponent<Camera>();
|
||||
|
||||
// Try to get Cinemachine camera if no regular camera or if both exist
|
||||
_virtualCamera = GetComponent<CinemachineCamera>();
|
||||
|
||||
// Determine which camera type we're using
|
||||
_usingCinemachine = _virtualCamera != null;
|
||||
|
||||
_lastScreenWidth = Screen.width;
|
||||
_lastScreenHeight = Screen.height;
|
||||
|
||||
if (!_usingCinemachine && _regularCamera == null)
|
||||
{
|
||||
Debug.LogError("CameraScreenAdapter: No camera component found. Add this script to a GameObject with either Camera or CinemachineCamera component.");
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (adjustOnStart)
|
||||
{
|
||||
AdjustCamera();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (adjustOnScreenResize &&
|
||||
(Screen.width != _lastScreenWidth || Screen.height != _lastScreenHeight))
|
||||
{
|
||||
AdjustCamera();
|
||||
_lastScreenWidth = Screen.width;
|
||||
_lastScreenHeight = Screen.height;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually trigger camera adjustment to match the reference width.
|
||||
/// </summary>
|
||||
public void AdjustCamera()
|
||||
{
|
||||
if (referenceMarker == null)
|
||||
{
|
||||
Debug.LogWarning("CameraScreenAdapter: Missing reference marker.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the orthographic size based on the target width and screen aspect ratio
|
||||
float targetWidth = referenceMarker.targetWidth;
|
||||
float screenAspect = (float)Screen.height / Screen.width;
|
||||
|
||||
// Orthographic size is half the height, so we calculate:
|
||||
// orthoSize = (targetWidth / 2) * (screenHeight / screenWidth)
|
||||
float orthoSize = (targetWidth / 2f) * screenAspect;
|
||||
|
||||
// Apply the calculated size to the camera
|
||||
if (_usingCinemachine)
|
||||
{
|
||||
// Apply to Cinemachine virtual camera
|
||||
var lens = _virtualCamera.Lens;
|
||||
lens.OrthographicSize = orthoSize;
|
||||
_virtualCamera.Lens = lens;
|
||||
Debug.Log($"Cinemachine Camera adapted: Width={targetWidth}, Aspect={screenAspect:F2}, OrthoSize={orthoSize:F2}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply to regular camera
|
||||
if (_regularCamera.orthographic)
|
||||
{
|
||||
_regularCamera.orthographicSize = orthoSize;
|
||||
Debug.Log($"Camera adapted: Width={targetWidth}, Aspect={screenAspect:F2}, OrthoSize={orthoSize:F2}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("CameraScreenAdapter: Regular camera is not in orthographic mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify subscribers that the camera has been adjusted
|
||||
OnCameraAdjusted?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the camera component being controlled by this adapter
|
||||
/// </summary>
|
||||
public Camera GetControlledCamera()
|
||||
{
|
||||
return _usingCinemachine ? _virtualCamera.GetComponent<Camera>() : _regularCamera;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user