Update readme docs for our systems

This commit is contained in:
Michal Adam Pikulski
2025-10-21 12:37:53 +02:00
parent 2fb77e1040
commit 7096dffb54
4 changed files with 637 additions and 659 deletions

View File

@@ -1,78 +1,196 @@
# Camera Screen Adaptation System
This system helps adapt your 2D game's orthographic camera to different screen sizes, ensuring content is displayed consistently across various devices. It also provides tools for anchoring game objects to screen edges.
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](#what-this-solves)
- [Architecture at a Glance](#architecture-at-a-glance)
- [Quick Start (Code-First)](#quick-start-code-first)
- [Create and Wire Components in Code](#create-and-wire-components-in-code)
- [Manual Recalculate / Listen for Changes](#manual-recalculate--listen-for-changes)
- [Components](#components)
- [`ScreenReferenceMarker`](#screenreferencemarker)
- [`CameraScreenAdapter`](#camerascreenadapter)
- [`EdgeAnchor`](#edgeanchor)
- [Common Case Studies](#common-case-studies)
- [HUD Top Bar (safe top margin)](#hud-top-bar-safe-top-margin)
- [Side Buttons (left/right margins)](#side-buttons-leftright-margins)
- [Cinemachine Virtual Camera](#cinemachine-virtual-camera)
- [Tips & Best Practices](#tips--best-practices)
- [Troubleshooting / FAQ](#troubleshooting--faq)
- [Paths & Namespaces](#paths--namespaces)
- [Change Log](#change-log)
## 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
```csharp
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
```csharp
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
### 1. ScreenReferenceMarker
### `ScreenReferenceMarker`
Defines the reference sizes and margins used by both the adapter and anchors.
This component defines the target width and edge margins for your level content.
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.
- **Target Width**: The desired width to be displayed on screen
- **Edge Margins**: Distances from screen edges for anchoring objects
- **Visualization**: Editor-only visualization of the reference sizes
Typical setup:
- Place at the world-space center of your playable area or camera focus.
- Tune margins to match your HUD/world layout needs.
### 2. CameraScreenAdapter
### `CameraScreenAdapter`
Computes and applies orthographic size to a `Camera` or `CinemachineCamera` so that the screen horizontally fits `targetWidth`.
Automatically adjusts the camera's orthographic size to ensure the target width (defined by the ScreenReferenceMarker) matches the screen width.
Highlights:
- Fields: `referenceMarker`, `adjustOnStart`, `adjustOnScreenResize`.
- Event: `OnCameraAdjusted` fires after a size update.
- Works with built-in `Camera` (must be orthographic) or with `CinemachineCamera`.
- **Reference Marker**: Link to your ScreenReferenceMarker
- **Adapt on Resolution Change**: Automatically update when screen resolution changes
Formula:
- `orthoSize = (targetWidth / 2f) * (Screen.height / Screen.width)`.
### 3. EdgeAnchor
Public helpers:
- `AdjustCamera()` — recalculate and apply now.
- `GetControlledCamera()` — returns the underlying `Camera` instance.
Anchors game objects to screen edges, maintaining consistent distance when the camera's orthographic size changes.
### `EdgeAnchor`
Anchors a `Transform` to a chosen screen edge using the same marker margins.
- **Anchor Edge**: Which edge to anchor to (Top, Bottom, Left, Right)
- **Reference Marker**: Uses the same marker as the CameraScreenAdapter
- **Additional Offset**: Extra distance from the edge margin
- **Continuous Update**: Whether to update position every frame
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
### 4. CameraScreenVisualizer
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.
Helper component for visualizing camera boundaries in the editor.
## Common Case Studies
## Setup Instructions
### 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:
```csharp
anchor.anchor = EdgeAnchor.AnchorEdge.Top;
anchor.additionalOffset = 0.1f; // small breathing room
```
- Keep `continuousUpdate = true` for device rotation/platform switches.
### Basic Setup
### Side Buttons (left/right margins)
- For a left button column:
```csharp
anchor.anchor = EdgeAnchor.AnchorEdge.Left;
anchor.additionalOffset = 0.2f;
```
- Mirror for right side with `Right`.
- Adjust `marker.leftMargin/rightMargin` to push them inward safely.
1. **Create the Reference Marker:**
- Add a new empty GameObject to your scene
- Add the `ScreenReferenceMarker` component to it
- Position it at the center of your target view
- Set the `targetWidth` to match your level's ideal width
- Adjust margin values as needed
### 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.
2. **Configure the Camera:**
- Add the `CameraScreenAdapter` component to your main camera
- Reference the ScreenReferenceMarker you created
- Optionally, add `CameraScreenVisualizer` for better editor visualization
## 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.
3. **Anchor Game Objects:**
- For any objects that should maintain position relative to screen edges:
- Add the `EdgeAnchor` component
- Set the desired anchor edge (e.g., Top)
- Reference the same ScreenReferenceMarker
- Adjust additional offset if needed
## 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.
### Example: Top-Edge Anchoring
## Paths & Namespaces
- Scripts: `Assets/Scripts/AppleHillsCamera/`
- `ScreenReferenceMarker.cs`
- `CameraScreenAdapter.cs`
- `EdgeAnchor.cs`
- Namespace: `AppleHillsCamera`
For objects that need to stay a fixed distance from the top of the screen:
1. Set up your ScreenReferenceMarker with an appropriate topMargin value
2. Add EdgeAnchor to the object you want to anchor
3. Set AnchorEdge to Top
4. Adjust additionalOffset for fine-tuning
## Tips for Level Design
- Place the ScreenReferenceMarker at the center of your scene's critical content
- Use the visual gizmos to see how your reference width relates to camera boundaries
- Test your scene in different aspect ratios to ensure proper adaptation
- For complex levels, you might want multiple reference markers for different sections
## Runtime Considerations
- The system automatically adapts when the screen size changes
- The CameraScreenAdapter can be disabled if you need to temporarily override the automatic sizing
- EdgeAnchor components can be disabled when their objects don't need to maintain edge alignment
## 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.