# 3. Subtitle Scale and Captions Part of [[Accessibility]]. Prev: [[2. Colorblind-Safe Palettes]]. Next: [[4. Reduced Motion]]. ## 3.1 In-game scale (all platforms) Subtitles and prompts are UI Toolkit Labels (or a dedicated subtitle view). Drive size from a float you own (for example 0.8-1.6), applied as `label.style.fontSize` or a USS class you swap. Persist it ([[High Scores, Saves and Player Stats]] / [[PlayerPrefs Advanced]]). Keep a **minimum readable size**. Do not scale the whole HUD until buttons fall off a Quest panel - scale the subtitle / dialogue / prompt text first ([[3. Glyph Prompts in UI Toolkit]], [[2. Localizing UI Toolkit and uGUI Text]]). Localized strings can grow: test German and a long Smart String ([[3. Smart Strings Plurals and Variables]]) at the largest scale. A captions **on/off** toggle is separate from scale. If a cutscene or a radio line has speech, offer captions ([[Timeline Basics]], [[Localization]] asset tables for voice). ## 3.2 System settings (Android and iPhonePlayer only) Official 6000.5 `UnityEngine.Accessibility.AccessibilitySettings` (read-only, updated from system settings): | API | Meaning | |---|---| | `fontScale` | User font scale in system settings | | `isBoldTextEnabled` | Bold text in system settings | | `isClosedCaptioningEnabled` | Closed captioning in system settings | | `fontScaleChanged` | Main-thread event when font scale changes | | `boldTextStatusChanged` | Bold text changed | | `closedCaptioningStatusChanged` | Captions changed | Supported platforms in the 6000.5 Scripting API remarks: **`RuntimePlatform.Android`** and **`RuntimePlatform.IPhonePlayer`**. On Editor, desktop, and Quest, treat these as **unavailable or undefined** unless you have tested them there - still use the in-game slider. ```csharp using UnityEngine; using UnityEngine.Accessibility; /// <summary> /// Combines an in-game scale with mobile system fontScale when present. /// NOT compiled in Unity. /// </summary> public sealed class SubtitleScaler : MonoBehaviour { [SerializeField] float userScale = 1f; [SerializeField] float min = 0.8f; [SerializeField] float max = 1.6f; public event System.Action<float> Changed; public float UserScale { get => userScale; set { userScale = Mathf.Clamp(value, min, max); Changed?.Invoke(EffectiveScale); } } public float EffectiveScale { get { float system = 1f; if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer) system = AccessibilitySettings.fontScale; return Mathf.Clamp(userScale * system, min, max * 1.25f); } } void OnEnable() { AccessibilitySettings.fontScaleChanged += OnFontScaleChanged; AccessibilitySettings.closedCaptioningStatusChanged += OnCaptionsChanged; } void OnDisable() { AccessibilitySettings.fontScaleChanged -= OnFontScaleChanged; AccessibilitySettings.closedCaptioningStatusChanged -= OnCaptionsChanged; } void OnFontScaleChanged() => Changed?.Invoke(EffectiveScale); void OnCaptionsChanged() { if (Application.platform != RuntimePlatform.Android && Application.platform != RuntimePlatform.IPhonePlayer) return; // If system captions are on, prefer showing your subtitle view. if (AccessibilitySettings.isClosedCaptioningEnabled) Changed?.Invoke(EffectiveScale); } } ``` Subscribe in the view; do not poll. On platforms where the events never fire, the in-game slider still works. I did not find a 6000.5 guarantee of default `fontScale` values in the Editor - clamp everything. ## 3.3 Exercise A subtitle Label, a slider 0.8-1.6, and a long localized line. At 1.6 the text must still wrap inside the panel, not off the Quest-safe area. On an Android/iOS device (if you have one), change system font size and confirm the event fires. ## Sources - `AccessibilitySettings` (6000.5): https://docs.unity3d.com/6000.5/Documentation/ScriptReference/Accessibility.AccessibilitySettings.html - Accessibility module intro (6000.5): https://docs.unity.com/en-us/engine/6000.5/manual/accessibility/module-intro