using UnityEngine; using UnityEngine.UI; /// /// Creates the small per-canvas language switcher used to verify UI localization. /// The bar is intentionally built from Unity UI primitives so it has no sprite dependency. /// public sealed class LocalizationLanguageTestBar : MonoBehaviour { private const string BarName = "__LocalizationLanguageTestBar"; private static readonly string[] Labels = { "中文", "EN", "FR", "RU" }; private static readonly Color[] Colors = { new Color(0.12f, 0.48f, 0.24f, 0.96f), new Color(0.10f, 0.36f, 0.72f, 0.96f), new Color(0.48f, 0.20f, 0.64f, 0.96f), new Color(0.66f, 0.20f, 0.16f, 0.96f) }; private static Sprite backgroundSprite; private static LocalizationLanguageTestBar instance; public static void EnsureForActiveCanvases() { // If we already have a bar, just bring it to front and return. if (instance != null) { instance.transform.SetAsLastSibling(); return; } // Find the first valid root ScreenSpace canvas and create one bar there. Canvas[] canvases = Resources.FindObjectsOfTypeAll(); for (int i = 0; i < canvases.Length; i++) { Canvas canvas = canvases[i]; if (canvas == null || !canvas.isActiveAndEnabled || !canvas.gameObject.scene.IsValid()) continue; // Only place the bar on Screen Space - Overlay canvases. if (canvas.renderMode != RenderMode.ScreenSpaceOverlay) continue; // Skip sub-canvases (e.g. Dropdown List) to avoid placing debug bars on overlays. if (canvas.transform.parent != null && canvas.transform.parent.GetComponentInParent() != null) continue; EnsureForCanvas(canvas); break; } } private static void EnsureForCanvas(Canvas canvas) { Transform canvasTransform = canvas.transform; for (int i = 0; i < canvasTransform.childCount; i++) { LocalizationLanguageTestBar existing = canvasTransform.GetChild(i).GetComponent(); if (existing != null) { instance = existing; existing.transform.SetAsLastSibling(); return; } } GameObject barObject = new GameObject(BarName, typeof(RectTransform), typeof(LocalizationLanguageTestBar)); barObject.transform.SetParent(canvasTransform, false); RectTransform bar = barObject.GetComponent(); bar.anchorMin = new Vector2(0f, 1f); bar.anchorMax = new Vector2(0f, 1f); bar.pivot = new Vector2(0f, 1f); bar.sizeDelta = new Vector2(276f, 30f); bar.anchoredPosition = new Vector2(8f, -8f); for (int i = 0; i < Labels.Length; i++) CreateButton(bar, Labels[i], i); bar.SetAsLastSibling(); instance = barObject.GetComponent(); } private void OnDestroy() { if (instance == this) instance = null; } private static void CreateButton(RectTransform parent, string label, int language) { GameObject buttonObject = new GameObject("Language_" + label, typeof(RectTransform), typeof(Image), typeof(Button)); buttonObject.transform.SetParent(parent, false); RectTransform rect = buttonObject.GetComponent(); rect.anchorMin = new Vector2(0f, 0.5f); rect.anchorMax = new Vector2(0f, 0.5f); rect.pivot = new Vector2(0f, 0.5f); rect.sizeDelta = new Vector2(66f, 28f); rect.anchoredPosition = new Vector2(language * 70f, 0f); if (backgroundSprite == null) { Texture2D texture = new Texture2D(1, 1, TextureFormat.RGBA32, false); texture.SetPixel(0, 0, Color.white); texture.Apply(); backgroundSprite = Sprite.Create(texture, new Rect(0, 0, 1, 1), new Vector2(0.5f, 0.5f)); } Image image = buttonObject.GetComponent(); image.sprite = backgroundSprite; image.color = Colors[language]; image.raycastTarget = true; Button button = buttonObject.GetComponent