Files
AppleHillsProduction/docs/camera_adaptation_readme.md
2025-10-21 12:37:57 +02:00

7.7 KiB
Raw Blame History

Camera Screen Adaptation System

Adapts your 2D orthographic camera to different aspect ratios while keeping gameplay/UI elements aligned to screen edges. Includes a reference marker for target content width and utilities for edge anchoring.

Table of Contents

What This Solves

  • Consistent horizontal framing across devices: a fixed target world-space width always fits the screen.
  • Stable world-space margins from the physical screen edges for placing HUD/world elements.
  • Works with both a regular Camera and Cinemachine's CinemachineCamera.

Architecture at a Glance

  • Reference: ScreenReferenceMarker defines targetWidth and world-space margins (topMargin, bottomMargin, leftMargin, rightMargin).
  • Adapter: CameraScreenAdapter computes orthographic size from targetWidth and aspect and applies it to the controlled camera. Emits OnCameraAdjusted.
  • Anchoring: EdgeAnchor positions objects relative to the computed screen edges using the same marker margins.

Quick Start (Code-First)

Create and Wire Components in Code

using AppleHillsCamera;
using UnityEngine;

public class CameraAdaptationBootstrap : MonoBehaviour
{
    [SerializeField] private Camera mainCamera; // assign in inspector or find at runtime

    private void Awake()
    {
        // 1) Create/locate the marker
        var markerGO = new GameObject("ScreenReferenceMarker");
        var marker = markerGO.AddComponent<ScreenReferenceMarker>();
        marker.targetWidth = 16f; // your desired world-space width
        marker.topMargin = 1f;    // tune margins for your HUD

        // 2) Set up the adapter on your camera
        var adapter = mainCamera.gameObject.AddComponent<CameraScreenAdapter>();
        adapter.referenceMarker = marker;
        adapter.adjustOnStart = true;
        adapter.adjustOnScreenResize = true;

        // 3) Anchor a sample HUD object to the top edge
        var hud = GameObject.CreatePrimitive(PrimitiveType.Quad);
        var anchor = hud.AddComponent<EdgeAnchor>();
        anchor.referenceMarker = marker;
        anchor.anchor = EdgeAnchor.AnchorEdge.Top;
        anchor.additionalOffset = 0.25f; // extra spacing from the top margin
        anchor.continuousUpdate = true;  // keep tracking when aspect changes
    }
}

Manual Recalculate / Listen for Changes

using AppleHillsCamera;
using UnityEngine;

public class CameraAdaptationHooks : MonoBehaviour
{
    [SerializeField] private CameraScreenAdapter adapter;

    private void OnEnable()
    {
        // Listen when the camera size is applied
        adapter.OnCameraAdjusted += OnAdjusted;
    }

    private void OnDisable()
    {
        adapter.OnCameraAdjusted -= OnAdjusted;
    }

    public void ForceRecalculateNow()
    {
        adapter.AdjustCamera();
    }

    private void OnAdjusted()
    {
        Debug.Log("Camera adjusted to match target width.");
        // Reposition custom elements if you dont use EdgeAnchor
    }
}

Components

ScreenReferenceMarker

Defines the reference sizes and margins used by both the adapter and anchors.

Key fields:

  • targetWidth (float): world-space width that should fully fit the viewport.
  • topMargin, bottomMargin, leftMargin, rightMargin (float): world-space distances from the corresponding screen edges.
  • Scene gizmos: visualizes width line, screen rectangle, and margin guides in the editor.

Typical setup:

  • Place at the world-space center of your playable area or camera focus.
  • Tune margins to match your HUD/world layout needs.

CameraScreenAdapter

Computes and applies orthographic size to a Camera or CinemachineCamera so that the screen horizontally fits targetWidth.

Highlights:

  • Fields: referenceMarker, adjustOnStart, adjustOnScreenResize.
  • Event: OnCameraAdjusted fires after a size update.
  • Works with built-in Camera (must be orthographic) or with CinemachineCamera.

Formula:

  • orthoSize = (targetWidth / 2f) * (Screen.height / Screen.width).

Public helpers:

  • AdjustCamera() — recalculate and apply now.
  • GetControlledCamera() — returns the underlying Camera instance.

EdgeAnchor

Anchors a Transform to a chosen screen edge using the same marker margins.

Common fields (names based on code):

  • referenceMarker (ScreenReferenceMarker)
  • anchor (EdgeAnchor.AnchorEdge): Top, Bottom, Left, Right
  • additionalOffset (float): extra spacing beyond the margin
  • continuousUpdate (bool): update every frame and on camera adjustments

Usage tips:

  • Use continuousUpdate for elements that must track aspect changes at runtime.
  • Combine with local offsets/parenting for precise UI/HUD placements in world space.

Common Case Studies

HUD Top Bar (safe top margin)

  • Set marker.topMargin to the vertical padding you want from the top edge.
  • Add EdgeAnchor to your top bar root:
anchor.anchor = EdgeAnchor.AnchorEdge.Top;
anchor.additionalOffset = 0.1f; // small breathing room
  • Keep continuousUpdate = true for device rotation/platform switches.

Side Buttons (left/right margins)

  • For a left button column:
anchor.anchor = EdgeAnchor.AnchorEdge.Left;
anchor.additionalOffset = 0.2f;
  • Mirror for right side with Right.
  • Adjust marker.leftMargin/rightMargin to push them inward safely.

Cinemachine Virtual Camera

  • Add CameraScreenAdapter to the GameObject with CinemachineCamera.
  • The adapter detects Cinemachine and writes to Lens.OrthographicSize.
  • Everything else (margins and EdgeAnchor) works the same.

Tips & Best Practices

  • Pick a targetWidth that matches the core gameplay area horizontally; verify extremes (16:9, 19.5:9, 4:3).
  • Prefer EdgeAnchor for HUD/world labels instead of manual scripts—anchors auto-update on resize and on OnCameraAdjusted.
  • For one-off bespoke layouts, listen to OnCameraAdjusted and move objects yourself.
  • Ensure regular cameras are set to orthographic; the adapter warns if not.

Troubleshooting / FAQ

  • My camera didnt change size:
    • Ensure referenceMarker is assigned.
    • For built-in Camera, confirm orthographic is enabled.
    • If using Cinemachine, verify the component is CinemachineCamera on the same GameObject.
  • Anchored objects are offset oddly:
    • Check additionalOffset and your objects pivot/bounds.
    • Verify marker margins and that the marker sits at the world center you expect.
  • It works in Play but gizmos look wrong in Scene:
    • Scene gizmos approximate using Scene/Game view sizes; rely on Play Mode for truth.

Paths & Namespaces

  • Scripts: Assets/Scripts/AppleHillsCamera/
    • ScreenReferenceMarker.cs
    • CameraScreenAdapter.cs
    • EdgeAnchor.cs
  • Namespace: AppleHillsCamera

Change Log

  • v1.1: Added Table of Contents, code-first snippets, case studies, and aligned terms with actual APIs (OnCameraAdjusted, Cinemachine support).
  • v1.0: Original overview and setup guide.