13 KiB

name, description
name description
th1-ui-visual-style TH1 project visual design and prefab-authoring workflow for Unity UI prefabs, especially Outside menu, questionnaire, wiki, library, multiplayer, selection, and other BundleResources prefab UI work. Use when Codex needs to design, create, revise, review, or rebuild TH1 UI visuals, choose existing UI sprites/images, match prefab color/typography/button/scrollbar conventions, preserve a workflow where Codex creates the prefab and the user later edits visual details in Unity, or avoid runtime UI/layout injection that makes prefab edits ineffective.

TH1 UI Visual Style

Use this after th1-base and alongside .agents/skills/th1-ui-patterns when UI work has a visual/prefab surface.

TH1 UI should look like the existing Outside, Wiki, Library, Menu, Select, and Multiplay prefabs: image-sliced, purple-blue/cream, decorative but readable, and resource-driven. Do not default to flat runtime-created rectangles unless the surrounding UI already does that.

First Moves

  1. Inspect comparable prefabs before editing:
rg --files Unity/Assets/BundleResources/Prefab/UI/Outside -g "*.prefab"
rg -n "m_Name:|m_Sprite:|m_Color:|m_fontColor:|m_fontSize:|m_Transition:" Unity/Assets/BundleResources/Prefab/UI/Outside/UIOutsideLibrary.prefab Unity/Assets/BundleResources/Prefab/UI/Outside/UIOutsideWiki.prefab Unity/Assets/BundleResources/Prefab/UI/Outside/UIOutsideMenu.prefab
  1. Inspect reusable UI images:
rg --files Unity/Assets/BundleResources/TH1UI/Common Unity/Assets/BundleResources/TH1UI/Outside Unity/Assets/BundleResources/ArtResources/TH1UI/Common -g "*.png"
  1. Prefer modifying/building the actual prefab hierarchy. A prefab with only a root script and runtime-generated UI is not acceptable for major Outside UI unless the user explicitly asks for a prototype.

  2. Before touching code, define ownership:

    • Prefab-owned: hierarchy, static layout, RectTransform sizes/anchors/pivots, layout groups, masks, sprites, colors, fonts, text sizes, tab/button visuals, panel backgrounds, decorative elements, and static content roots.
    • Code-owned: data binding, button callbacks, opening/closing, active-state switching, dynamic list population into existing content roots, and gameplay/data state.

Prefab Handoff Contract

TH1 UI prefab work follows this collaboration model: Codex creates or updates the prefab structure first, then the user edits the prefab's visual details in Unity. Therefore runtime code must not overwrite the user's Inspector changes.

Hard rules:

  • Do not add layout or visual components at runtime to prefab-owned UI nodes. Forbidden examples include AddComponent<LayoutElement>(), AddComponent<HorizontalLayoutGroup>(), AddComponent<VerticalLayoutGroup>(), AddComponent<ContentSizeFitter>(), adding Image, adding TextMeshProUGUI, or creating tab/button/container nodes in Init, Awake, Start, OnOpen, or SetContent.
  • Do not mutate prefab-owned layout from code: no anchorMin, anchorMax, pivot, anchoredPosition, sizeDelta, offsetMin, offsetMax, SetParent, SetSiblingIndex, or layout padding/spacing changes for static UI nodes.
  • Do not hardcode visual styling that the user should tune in prefab: no code-owned tab colors, button sprites, text colors, font sizes, panel backgrounds, or decorative state unless the user explicitly requests code-driven visuals.
  • Do not implement "fallback creation" for missing prefab references. Missing static nodes should be fixed in the prefab, or the code should fail softly/log and skip the feature. Runtime fallback creation hides prefab wiring errors and makes Unity-side edits meaningless.
  • It is acceptable to resolve existing prefab references by serialized fields or by Transform.Find name fallback, as long as the code only reads references and does not create, reparent, resize, restyle, or add components.
  • Dynamic content is allowed only inside prefab-owned containers. Prefer a separate item prefab for dynamic rows/cards. Runtime-created children must not be the main frame, tabs, static panels, scroll view structure, or visual system.
  • Temporary migration/bootstrap code that modifies prefab structure must be removed before handoff. Do not leave it in production UI scripts.

Allowed code examples:

CloseButton.onClick.RemoveAllListeners();
CloseButton.onClick.AddListener(Close);
SettingContentRoot.gameObject.SetActive(tab == HeroPanelTab.Setting);
row.SetContent(data);

Forbidden handoff-breaking examples:

if (go.GetComponent<LayoutElement>() == null) go.AddComponent<LayoutElement>();
rect.anchoredPosition = new Vector2(40f, -76f);
buttonImage.sprite = ResourceLoader.Load<Sprite>("...");
text.fontSize = 26f;
child.SetParent(runtimeCreatedRoot, false);

When updating an existing script for a prefab, actively remove old runtime UI construction if it touches the static frame. Replace it with serialized references or read-only reference resolution.

Visual Rules

  • Use existing sliced sprites for panels, buttons, rows, labels, scrollbars, masks, and decorative strips. Most mature prefabs tint images white and let the sprite carry the shape/color.
  • Build windows from CommonWindowBG, CommonPanelBG, CommonWindowTopStripeBG1/2, CommonLinearBG, and appropriate Outside-specific preview/background art.
  • Use CommonLabelBG, CommonSelectLabelBG, CommonEmpireLabelBG, CommonHeroRowBG, GoodsShowBG, or feature-specific row art for list rows and badges.
  • Use CommonScrollbarVerticalBG and CommonScrollbarVerticalSlideBG for scrollbars. Avoid default Unity scrollbar visuals in finished UI.
  • Use CommonCircleBG_256, CommonCircleBlue, AvatarCircleBG, or avatar masks for icon/avatar slots.
  • Use DecoDashedHoriLine, top stripes, small stars, and feature-specific line art as separators instead of plain 1px solid lines when the UI is prominent.
  • Keep translucent black overlays for modal/blocker/background dimming. Common values in existing prefabs are alpha around 0.44, 0.59, and 0.84.

Color Language

Treat raw Image colors as tints over art, not as the main visual system.

  • Common image tint: white 1,1,1,1.
  • Main text/dark UI ink: deep purple-blue around 0.25,0.23,0.42, 0.19,0.19,0.44, or 0.14,0.18,0.36.
  • Light text: white or near-white.
  • Secondary text: grays around 0.53, 0.65, 0.82.
  • Highlight/accent: warm gold/yellow around 0.91,0.72,0.36 or 0.96,0.84,0.54.
  • Danger/error: restrained red, typically text-only unless a prefab already has red art.

Avoid making a new TH1 Outside panel predominantly teal, green, flat black, or modern dashboard gray unless matching a specific existing asset.

Typography

Use TMP like existing prefabs:

  • TH1 UI uses exactly two font tiers per language, defined by Export/Multilingual.asset FontGroups:
    • FontID 1 is the body font group: ZH SourceHanSansCN-Medium, TDZH SourceHanSansTC-Medium, EN Roboto-Regular, JP SourceHanSansJP-Medium, KR SourceHanSansKR-Medium.
    • FontID 2 is the title font group: ZH SourceHanSansCN-Heavy, TDZH SourceHanSansTC-Heavy, EN Roboto-Black, JP SourceHanSansJP-Heavy, KR SourceHanSansKR-Heavy.
  • Treat those two font groups as the only weight system. Do not create a third visual weight with TMP fontWeight, synthetic FontStyles.Bold, alternate font assets, or per-language one-off font substitutions.
  • Headings, major action labels, tabs, and title-like button labels should use the title font group (FontID 2). Body copy, descriptions, metadata, helper text, ordinary row text, and input text should use the body font group (FontID 1).
  • For prefab-authored text, set the MultilingualTextMono.FontID to 2 for title-tier text and 1 for body-tier text. Keep TMP m_fontWeight at 400 and m_fontStyle normal unless the UI already has a special non-weight semantic such as italic placeholder text.
  • For runtime-created TMP, assign the current language font through MultilingualManager.Instance.GetMultilingualFont(2) for title-tier text or GetMultilingualFont(1) for body-tier text. Do not set fontWeight = Heavy/Bold/Black or fontStyle = Bold as a substitute for choosing the correct font group.
  • Ordinary labels: 22, 24, or 26.
  • Small helper/body text: 18 or 20.
  • Section/window titles: 28 or 32.
  • Large action text or splash/menu labels: 45+; reserve 48, 68, 80 for title-screen/hero-scale text.
  • Match existing font colors: deep purple-blue on light/cream panels, white on dark art, gray for disabled/secondary.

Text should fit fixed prefab bounds. Prefer shorter labels or adjusted RectTransforms over viewport-scaled fonts.

Buttons

  • Use an Image as targetGraphic; choose a project sprite before using a plain color rectangle.
  • Common choices:
    • CommonReturnButton.png for back/close-style buttons.
    • CheckButton1.png, CheckButton2.png, CheckButton_Gray.png for toggles/options.
    • ItemButtonBG.png / ItemButtonSelectedBG.png for list item states.
    • SelectButton1.png or feature-specific Outside button art for primary list/selection actions.
    • MenuButtonBG.png / MenuButtonBGSpecial.png for main menu-like entries.
    • NextTurnButton.png only when the rounded/action-callout shape fits the context.
  • Existing prefabs use both m_Transition: 0 and m_Transition: 1; art-driven buttons often use no transition, while default controls and scrollbars often use ColorTint. Match nearby prefabs.
  • Do not create a button that is just a colored rounded rectangle with TMP text if there is a suitable project button sprite.

Prefab Structure

Use recognizable hierarchy names seen across existing prefabs:

BG, BG2, TopBar, Title, Text, Icon, Preview, Panel, Scroll View, Viewport, Content, Scrollbar Vertical, Sliding Area, Handle, CloseButton, Blocker, Option1, Selected, Label.

For a new Outside feature panel:

  1. Root contains blocker/background image, close/back button, and main content root.
  2. Main content uses actual prefab children for left nav, right detail/body, scroll areas, footer/action buttons.
  3. Lists use item prefabs or repeatable row children with sprite backgrounds.
  4. Runtime may populate data rows, but the static frame, scroll views, and common controls should be visible in the prefab.

For a handoff-ready prefab:

  • Expose important nodes as serialized fields on the View/MonoBehaviour, or resolve them by stable existing names.
  • Keep all layout components that the user may tune on the prefab object itself, not in code.
  • If code needs tab or panel switching, wire existing roots and toggle only SetActive.
  • If code needs selected/unselected visuals, prefer prefab child state objects, selected overlays, or prewired sprites. Do not assign colors/sprites/font sizes in code unless that is an intentional gameplay state.

Resource Map

Commonly reused UI sprites:

  • Unity/Assets/BundleResources/ArtResources/TH1UI/Common/CommonPanelBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonWindowBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonWindowTopStripeBG1.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonWindowTopStripeBG2.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonLabelBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonSelectLabelBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonCircleBG_256.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonScrollbarVerticalBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonBG/CommonScrollbarVerticalSlideBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonButton/CommonReturnButton.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonButton/CheckButton1.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonButton/CheckButton2.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonButton/ItemButtonBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonButton/ItemButtonSelectedBG.png
  • Unity/Assets/BundleResources/TH1UI/Common/CommonDeco/DecoDashedHoriLine.png
  • Unity/Assets/BundleResources/TH1UI/Outside/OutsideMenu/MenuButtonBG.png
  • Unity/Assets/BundleResources/TH1UI/Outside/OutsideLibrary/UIOutsideLibraryItemBG.png
  • Unity/Assets/BundleResources/TH1UI/Outside/OutsideHistory/OutsideHistoryItemBG.png

Read references/prefab-audit.md when you need the source audit details or sprite frequency evidence.

Verification

  • Run git diff --check.
  • For C# UI code changes, run dotnet build Unity/TH1.Hotfix.csproj --no-restore.
  • For prefab visual work, verify in Unity Editor or Unity MCP when available. If not available, at minimum inspect the prefab YAML for real child hierarchy, sprite refs, button targetGraphics, and scroll view structure.
  • Report if a prefab still relies on runtime-only construction for its main frame.
  • Before finishing any UI prefab/code handoff, scan changed UI scripts for forbidden runtime prefab mutation:
rg -n "AddComponent<.*(Layout|Image|TextMeshProUGUI|ContentSizeFitter)|LayoutElement|HorizontalLayoutGroup|VerticalLayoutGroup|ContentSizeFitter|anchoredPosition|sizeDelta|anchorMin|anchorMax|offsetMin|offsetMax|SetParent|SetSiblingIndex|ResourceLoader.Load<Sprite>|fontSize|\\.color\\s*=" Unity/Assets/Scripts/TH1_UI

Review matches in changed files. Existing matches elsewhere may be unrelated, but new matches in handoff UI scripts must be justified or removed.