UI tuner: handle both canvas modes, echo knob values
In-game capture revealed two canvas families: ScreenSpaceOverlay/ ScaleWithScreenSize (the HUD, ref 1920x1080 match=1) and WorldSpace/ ConstantPixelSize (NamePlate and friends). Unity ignores referenceResolution in ConstantPixelSize mode, so the old HUD_SCALE knob could never affect the in-world labels. Split into HUD_SCALE (referenceResolution) and WORLD_SCALE (scaleFactor), applied per mode. Also echoes the knob values and logs APPLIED lines, so a stale console edit is immediately obvious instead of looking like the fix did nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+36
-29
@@ -1,56 +1,63 @@
|
||||
// LIVE UI TUNER — paste into UnityExplorer's C# Console. Edit the knobs, Run, look,
|
||||
// repeat. Nothing persists; relaunching reverts everything.
|
||||
// LIVE UI TUNER — paste into UnityExplorer's C# Console. Edit knobs, Run, look, repeat.
|
||||
// Nothing persists; a scene change or relaunch reverts everything.
|
||||
//
|
||||
// IMPORTANT: run this IN-GAME (not the main menu). Different scenes have different
|
||||
// canvases, and the overlapping text is in the gameplay HUD.
|
||||
// This game has TWO canvas families, tuned by DIFFERENT properties:
|
||||
// 1. ScreenSpaceOverlay + ScaleWithScreenSize ("Canvas", "Canvas in front")
|
||||
// -> the HUD. Controlled by matchWidthOrHeight + referenceResolution.
|
||||
// 2. WorldSpace + ConstantPixelSize ("NamePlate", etc.)
|
||||
// -> in-world labels. Unity IGNORES referenceResolution here;
|
||||
// ONLY scaleFactor does anything.
|
||||
//
|
||||
// scaleFactor = (screenW/refW)^(1-match) * (screenH/refH)^match
|
||||
// match=1 scales by HEIGHT (logical height stays 1080 = the design height).
|
||||
// Lowering match shrinks logical height below 1080 and CRAMPS things vertically.
|
||||
// The tuner prints the knob values it actually used, so you can confirm your edit took.
|
||||
|
||||
// ---- KNOBS -----------------------------------------------------------------
|
||||
float MATCH = 1.0f; // 0 = scale by width, 1 = scale by height
|
||||
// HUD_SCALE shrinks/grows the HUD *without* cramping the layout.
|
||||
// <1 = smaller HUD + MORE logical room (use this to cure overlapping text)
|
||||
// Implemented by raising referenceResolution.y, because CanvasScaler.scaleFactor
|
||||
// is IGNORED in ScaleWithScreenSize mode (it only applies to ConstantPixelSize).
|
||||
float HUD_SCALE = 1.0f; // try 0.95, 0.9, 0.85
|
||||
bool LIST_ONLY = false; // true = report current state, change nothing
|
||||
float MATCH = 1.0f; // ScaleWithScreenSize only. 0=scale by width, 1=by height
|
||||
float HUD_SCALE = 1.0f; // ScaleWithScreenSize only. <1 = smaller HUD + more room
|
||||
float WORLD_SCALE = 1.0f; // ConstantPixelSize only. <1 = smaller in-world labels
|
||||
bool LIST_ONLY = false; // true = report only, change nothing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var log = new System.Text.StringBuilder();
|
||||
log.AppendLine($"KNOBS match={MATCH} hudScale={HUD_SCALE} worldScale={WORLD_SCALE} listOnly={LIST_ONLY}");
|
||||
log.AppendLine($"SCREEN {UnityEngine.Screen.width}x{UnityEngine.Screen.height} " +
|
||||
$"aspect={(float)UnityEngine.Screen.width / UnityEngine.Screen.height:F4}");
|
||||
|
||||
foreach (var cs in UnityEngine.Object.FindObjectsOfType<UnityEngine.UI.CanvasScaler>())
|
||||
{
|
||||
log.AppendLine($"BEFORE {cs.name}: mode={cs.uiScaleMode} ref={cs.referenceResolution} " +
|
||||
var cv = cs.GetComponent<UnityEngine.Canvas>();
|
||||
string render = cv ? cv.renderMode.ToString() : "?";
|
||||
log.AppendLine($"BEFORE {cs.name} [{cs.uiScaleMode}/{render}] ref={cs.referenceResolution} " +
|
||||
$"match={cs.matchWidthOrHeight} scaleFactor={cs.scaleFactor}");
|
||||
|
||||
if (!LIST_ONLY)
|
||||
{
|
||||
cs.matchWidthOrHeight = MATCH;
|
||||
if (HUD_SCALE > 0f && System.Math.Abs(HUD_SCALE - 1f) > 0.0001f)
|
||||
if (cs.uiScaleMode == UnityEngine.UI.CanvasScaler.ScaleMode.ScaleWithScreenSize)
|
||||
{
|
||||
// effective scale = screenH / refH, so refH = designH / HUD_SCALE
|
||||
var r = cs.referenceResolution;
|
||||
cs.referenceResolution = new UnityEngine.Vector2(r.x, 1080f / HUD_SCALE);
|
||||
log.AppendLine($" refResolution {r} -> {cs.referenceResolution}");
|
||||
cs.matchWidthOrHeight = MATCH;
|
||||
// effective scale = screenH / refH => refH = 1080 / HUD_SCALE
|
||||
if (HUD_SCALE > 0f && System.Math.Abs(HUD_SCALE - 1f) > 0.0001f)
|
||||
{
|
||||
var r = cs.referenceResolution;
|
||||
cs.referenceResolution = new UnityEngine.Vector2(r.x, 1080f / HUD_SCALE);
|
||||
log.AppendLine($" APPLIED ref {r} -> {cs.referenceResolution}");
|
||||
}
|
||||
}
|
||||
else if (cs.uiScaleMode == UnityEngine.UI.CanvasScaler.ScaleMode.ConstantPixelSize)
|
||||
{
|
||||
// referenceResolution is ignored in this mode; scaleFactor is the only lever
|
||||
if (WORLD_SCALE > 0f && System.Math.Abs(WORLD_SCALE - 1f) > 0.0001f)
|
||||
{
|
||||
float old = cs.scaleFactor;
|
||||
cs.scaleFactor = WORLD_SCALE;
|
||||
log.AppendLine($" APPLIED scaleFactor {old} -> {cs.scaleFactor}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// report the resulting logical canvas the UI is laid out in
|
||||
var cv = cs.GetComponent<UnityEngine.Canvas>();
|
||||
float sf = cv ? cv.scaleFactor : 0f;
|
||||
if (sf > 0)
|
||||
log.AppendLine($"AFTER {cs.name}: effectiveScale={sf:F4} " +
|
||||
$"logicalCanvas={UnityEngine.Screen.width / sf:F0}x{UnityEngine.Screen.height / sf:F0}");
|
||||
}
|
||||
|
||||
// Every canvas in the scene — the overlapping text may live on one we haven't touched
|
||||
foreach (var cv in UnityEngine.Object.FindObjectsOfType<UnityEngine.Canvas>())
|
||||
log.AppendLine($"CANVAS {cv.name} mode={cv.renderMode} scale={cv.scaleFactor:F4} " +
|
||||
$"hasScaler={(cv.GetComponent<UnityEngine.UI.CanvasScaler>() != null)} " +
|
||||
$"sortOrder={cv.sortingOrder}");
|
||||
|
||||
UnityExplorer.ExplorerCore.Log(log.ToString());
|
||||
|
||||
Reference in New Issue
Block a user