nccgs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/.claude/agents/nccgs-accessibility-specialist.md +26 -0
  2. package/.claude/agents/nccgs-adversarial-reviewer.md +26 -0
  3. package/.claude/agents/nccgs-ai-programmer.md +26 -0
  4. package/.claude/agents/nccgs-analytics-engineer.md +26 -0
  5. package/.claude/agents/nccgs-art-direction-lead.md +26 -0
  6. package/.claude/agents/nccgs-audio-direction-lead.md +26 -0
  7. package/.claude/agents/nccgs-creative-director.md +26 -0
  8. package/.claude/agents/nccgs-documentation-manager.md +26 -0
  9. package/.claude/agents/nccgs-economy-designer.md +26 -0
  10. package/.claude/agents/nccgs-engine-programmer.md +26 -0
  11. package/.claude/agents/nccgs-game-design-lead.md +26 -0
  12. package/.claude/agents/nccgs-game-designer.md +26 -0
  13. package/.claude/agents/nccgs-gameplay-programmer.md +26 -0
  14. package/.claude/agents/nccgs-level-designer.md +26 -0
  15. package/.claude/agents/nccgs-live-ops-designer.md +26 -0
  16. package/.claude/agents/nccgs-localization-lead.md +26 -0
  17. package/.claude/agents/nccgs-narrative-lead.md +26 -0
  18. package/.claude/agents/nccgs-network-programmer.md +26 -0
  19. package/.claude/agents/nccgs-performance-analyst.md +26 -0
  20. package/.claude/agents/nccgs-producer.md +26 -0
  21. package/.claude/agents/nccgs-production-coordinator.md +23 -0
  22. package/.claude/agents/nccgs-programming-lead.md +26 -0
  23. package/.claude/agents/nccgs-prototyper.md +26 -0
  24. package/.claude/agents/nccgs-qa-engineer.md +26 -0
  25. package/.claude/agents/nccgs-qa-lead.md +26 -0
  26. package/.claude/agents/nccgs-release-engineer.md +26 -0
  27. package/.claude/agents/nccgs-release-lead.md +26 -0
  28. package/.claude/agents/nccgs-security-engineer.md +26 -0
  29. package/.claude/agents/nccgs-sound-designer.md +26 -0
  30. package/.claude/agents/nccgs-systems-designer.md +26 -0
  31. package/.claude/agents/nccgs-technical-architect.md +26 -0
  32. package/.claude/agents/nccgs-technical-artist.md +26 -0
  33. package/.claude/agents/nccgs-technical-director.md +26 -0
  34. package/.claude/agents/nccgs-tools-programmer.md +26 -0
  35. package/.claude/agents/nccgs-ui-programmer.md +26 -0
  36. package/.claude/agents/nccgs-unity-build-specialist.md +26 -0
  37. package/.claude/agents/nccgs-unity-content-specialist.md +26 -0
  38. package/.claude/agents/nccgs-unity-implementer.md +26 -0
  39. package/.claude/agents/nccgs-unity-rendering-specialist.md +26 -0
  40. package/.claude/agents/nccgs-unity-systems-specialist.md +26 -0
  41. package/.claude/agents/nccgs-unity-ui-specialist.md +26 -0
  42. package/.claude/agents/nccgs-ux-designer.md +26 -0
  43. package/.claude/agents/nccgs-verification-engineer.md +26 -0
  44. package/.claude/agents/nccgs-world-builder.md +26 -0
  45. package/.claude/agents/nccgs-writer.md +26 -0
  46. package/.claude/nccgs/THIRD_PARTY_NOTICES.md +13 -0
  47. package/.claude/nccgs/VERSION +1 -0
  48. package/.claude/nccgs/constitution.md +131 -0
  49. package/.claude/nccgs/hooks/agent-audit.mjs +10 -0
  50. package/.claude/nccgs/hooks/common.mjs +41 -0
  51. package/.claude/nccgs/hooks/post-compact.mjs +1 -0
  52. package/.claude/nccgs/hooks/pre-compact.mjs +8 -0
  53. package/.claude/nccgs/hooks/protect-git.mjs +22 -0
  54. package/.claude/nccgs/hooks/protect-write.mjs +17 -0
  55. package/.claude/nccgs/hooks/session-start.mjs +15 -0
  56. package/.claude/nccgs/hooks/session-stop.mjs +7 -0
  57. package/.claude/nccgs/protocols/agent-contract.md +34 -0
  58. package/.claude/nccgs/protocols/context-packets.md +13 -0
  59. package/.claude/nccgs/protocols/evidence.md +15 -0
  60. package/.claude/nccgs/protocols/model-routing.md +22 -0
  61. package/.claude/nccgs/protocols/orchestration.md +26 -0
  62. package/.claude/nccgs/protocols/unity-boundary.md +11 -0
  63. package/.claude/nccgs/settings.fragment.json +77 -0
  64. package/.claude/nccgs/studio.json +347 -0
  65. package/.claude/nccgs/tools/configure-models.mjs +39 -0
  66. package/.claude/nccgs/unity-skills-manifest.json +727 -0
  67. package/.claude/nccgs/workflow-catalog.json +317 -0
  68. package/.claude/rules/nccgs-canonical-docs.md +19 -0
  69. package/.claude/rules/nccgs-editor-tools.md +12 -0
  70. package/.claude/rules/nccgs-localization.md +12 -0
  71. package/.claude/rules/nccgs-networking.md +13 -0
  72. package/.claude/rules/nccgs-performance.md +14 -0
  73. package/.claude/rules/nccgs-rendering.md +16 -0
  74. package/.claude/rules/nccgs-security.md +13 -0
  75. package/.claude/rules/nccgs-tests.md +18 -0
  76. package/.claude/rules/nccgs-ui.md +14 -0
  77. package/.claude/rules/nccgs-unity-assets.md +21 -0
  78. package/.claude/rules/nccgs-unity-code.md +22 -0
  79. package/.claude/skills/accessibility-review/SKILL.md +14 -0
  80. package/.claude/skills/architecture-decision/SKILL.md +14 -0
  81. package/.claude/skills/asset-audit/SKILL.md +14 -0
  82. package/.claude/skills/audit/SKILL.md +16 -0
  83. package/.claude/skills/audit/references/dimensions.md +46 -0
  84. package/.claude/skills/balance-review/SKILL.md +14 -0
  85. package/.claude/skills/bug-triage/SKILL.md +14 -0
  86. package/.claude/skills/build-live-game/SKILL.md +317 -0
  87. package/.claude/skills/build-live-game/references/achievements.md +779 -0
  88. package/.claude/skills/build-live-game/references/apis.md +280 -0
  89. package/.claude/skills/build-live-game/references/authentication.md +437 -0
  90. package/.claude/skills/build-live-game/references/battlepass.md +860 -0
  91. package/.claude/skills/build-live-game/references/cloud-code.md +563 -0
  92. package/.claude/skills/build-live-game/references/cloud-save.md +474 -0
  93. package/.claude/skills/build-live-game/references/deployment.md +216 -0
  94. package/.claude/skills/build-live-game/references/player-account.md +813 -0
  95. package/.claude/skills/build-live-game/references/remote-config.md +96 -0
  96. package/.claude/skills/build-live-game/references/tooling.md +431 -0
  97. package/.claude/skills/closure/SKILL.md +14 -0
  98. package/.claude/skills/code-review/SKILL.md +14 -0
  99. package/.claude/skills/compatibility-review/SKILL.md +14 -0
  100. package/.claude/skills/context-pack/SKILL.md +14 -0
  101. package/.claude/skills/dependency-review/SKILL.md +14 -0
  102. package/.claude/skills/design/SKILL.md +20 -0
  103. package/.claude/skills/design-review/SKILL.md +14 -0
  104. package/.claude/skills/evidence-review/SKILL.md +14 -0
  105. package/.claude/skills/hotfix/SKILL.md +14 -0
  106. package/.claude/skills/implement-in-app-purchases/README.md +233 -0
  107. package/.claude/skills/implement-in-app-purchases/SKILL.md +158 -0
  108. package/.claude/skills/implement-in-app-purchases/references/api-notes.md +562 -0
  109. package/.claude/skills/implement-in-app-purchases/references/codeless-catalog.md +331 -0
  110. package/.claude/skills/implement-in-app-purchases/references/convert-adapty.md +268 -0
  111. package/.claude/skills/implement-in-app-purchases/references/convert-essentialkit.md +239 -0
  112. package/.claude/skills/implement-in-app-purchases/references/convert-revenuecat.md +275 -0
  113. package/.claude/skills/implement-in-app-purchases/references/convert-unipay.md +145 -0
  114. package/.claude/skills/implement-in-app-purchases/references/migration-v4-to-v5.md +204 -0
  115. package/.claude/skills/implement-in-app-purchases/references/path-add-iap-to-new-project.md +198 -0
  116. package/.claude/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md +356 -0
  117. package/.claude/skills/implement-in-app-purchases/references/path-convert-native-storekit.md +446 -0
  118. package/.claude/skills/implement-in-app-purchases/references/path-implement-iap-d2c.md +680 -0
  119. package/.claude/skills/implement-in-app-purchases/references/platform-notes.md +204 -0
  120. package/.claude/skills/implement-in-app-purchases/references/pre-check.md +205 -0
  121. package/.claude/skills/incident-recovery/SKILL.md +14 -0
  122. package/.claude/skills/initialize-ai-navigation/SKILL.md +95 -0
  123. package/.claude/skills/initialize-ai-navigation/references/navigation-system.md +794 -0
  124. package/.claude/skills/levelplay-unity-integration/CHANGELOG.md +57 -0
  125. package/.claude/skills/levelplay-unity-integration/README.md +74 -0
  126. package/.claude/skills/levelplay-unity-integration/SKILL.md +1126 -0
  127. package/.claude/skills/levelplay-unity-integration/references/banner-api.md +920 -0
  128. package/.claude/skills/levelplay-unity-integration/references/best-practices.md +536 -0
  129. package/.claude/skills/levelplay-unity-integration/references/ilrd-api.md +337 -0
  130. package/.claude/skills/levelplay-unity-integration/references/initialization-api.md +630 -0
  131. package/.claude/skills/levelplay-unity-integration/references/interstitial-api.md +899 -0
  132. package/.claude/skills/levelplay-unity-integration/references/ios-setup.md +491 -0
  133. package/.claude/skills/levelplay-unity-integration/references/migration-sdk-9.md +666 -0
  134. package/.claude/skills/levelplay-unity-integration/references/privacy-settings.md +608 -0
  135. package/.claude/skills/levelplay-unity-integration/references/rewarded-api.md +902 -0
  136. package/.claude/skills/localization/SKILL.md +135 -0
  137. package/.claude/skills/localization/references/api-notes.md +76 -0
  138. package/.claude/skills/localization/resources/L10nBatchProcessor.cs +69 -0
  139. package/.claude/skills/localization/resources/LocalizedFontAsset.cs +18 -0
  140. package/.claude/skills/localize-game/SKILL.md +14 -0
  141. package/.claude/skills/migrate-project/SKILL.md +21 -0
  142. package/.claude/skills/migrate-project/references/procedure.md +63 -0
  143. package/.claude/skills/milestone-review/SKILL.md +14 -0
  144. package/.claude/skills/new-unity-project/SKILL.md +179 -0
  145. package/.claude/skills/optimize-audio/SKILL.md +199 -0
  146. package/.claude/skills/optimize-audio/resources/audio-import-api.md +146 -0
  147. package/.claude/skills/optimize-audio/resources/platform-settings.md +48 -0
  148. package/.claude/skills/optimize-text-mesh-pro/SKILL.md +182 -0
  149. package/.claude/skills/optimize-web/SKILL.md +393 -0
  150. package/.claude/skills/optimize-web/resources/WebOptimizer.cs +21 -0
  151. package/.claude/skills/optimize-web/resources/toktx-examples.sh +11 -0
  152. package/.claude/skills/performance-audit/SKILL.md +14 -0
  153. package/.claude/skills/physics-3d-collision/SKILL.md +442 -0
  154. package/.claude/skills/physics-3d-collision/references/troubleshooting.md +41 -0
  155. package/.claude/skills/physics-3d-collision/resources/CollisionDebugger.cs +33 -0
  156. package/.claude/skills/plan-feature/SKILL.md +14 -0
  157. package/.claude/skills/playtest/SKILL.md +14 -0
  158. package/.claude/skills/project-stage/SKILL.md +14 -0
  159. package/.claude/skills/prototype-feature/SKILL.md +14 -0
  160. package/.claude/skills/qa-plan/SKILL.md +14 -0
  161. package/.claude/skills/release/SKILL.md +18 -0
  162. package/.claude/skills/release-readiness/SKILL.md +14 -0
  163. package/.claude/skills/retrospective/SKILL.md +14 -0
  164. package/.claude/skills/review/SKILL.md +16 -0
  165. package/.claude/skills/security-audit/SKILL.md +14 -0
  166. package/.claude/skills/setup-multiplayer-services/SKILL.md +39 -0
  167. package/.claude/skills/setup-multiplayer-services/references/dgs-entrypoint.md +79 -0
  168. package/.claude/skills/setup-multiplayer-services/references/entrypoints.md +213 -0
  169. package/.claude/skills/setup-multiplayer-services/references/examples.md +33 -0
  170. package/.claude/skills/setup-multiplayer-services/references/implementation-fit.md +30 -0
  171. package/.claude/skills/setup-multiplayer-services/references/underlying-services.md +11 -0
  172. package/.claude/skills/setup-multiplayer-services/references/workflows-prerequisites.md +17 -0
  173. package/.claude/skills/setup-vivox-voice-chat/SKILL.md +118 -0
  174. package/.claude/skills/setup-vivox-voice-chat/evals/.env.example +6 -0
  175. package/.claude/skills/setup-vivox-voice-chat/evals/README.md +101 -0
  176. package/.claude/skills/setup-vivox-voice-chat/evals/promptfooconfig.yaml +32 -0
  177. package/.claude/skills/setup-vivox-voice-chat/evals/tests/init-and-login.yaml +76 -0
  178. package/.claude/skills/setup-vivox-voice-chat/evals/tests/text-chat.yaml +65 -0
  179. package/.claude/skills/setup-vivox-voice-chat/evals/tests/voice-channels.yaml +74 -0
  180. package/.claude/skills/setup-vivox-voice-chat/references/events-and-participants.md +79 -0
  181. package/.claude/skills/setup-vivox-voice-chat/references/init-and-login.md +92 -0
  182. package/.claude/skills/setup-vivox-voice-chat/references/text-chat.md +93 -0
  183. package/.claude/skills/setup-vivox-voice-chat/references/troubleshooting.md +47 -0
  184. package/.claude/skills/setup-vivox-voice-chat/references/voice-channels.md +90 -0
  185. package/.claude/skills/shader-graph-create-custom-node/SKILL.md +25 -0
  186. package/.claude/skills/shader-graph-create-custom-node/resources/all_hints.hlsl +182 -0
  187. package/.claude/skills/sprint-plan/SKILL.md +14 -0
  188. package/.claude/skills/sprite-editor/SKILL.md +66 -0
  189. package/.claude/skills/sprite-editor/references/api_reference.md +151 -0
  190. package/.claude/skills/sprite-editor/references/background.md +112 -0
  191. package/.claude/skills/sprite-editor/references/templates.md +72 -0
  192. package/.claude/skills/sprite-editor/scripts/AutomaticSliceTexture.cs +40 -0
  193. package/.claude/skills/sprite-editor/scripts/GenerateNewSpriteRects.cs +200 -0
  194. package/.claude/skills/sprite-editor/scripts/GetTextureSourceImageSize.cs +32 -0
  195. package/.claude/skills/sprite-editor/scripts/GetTextureToSlice.cs +55 -0
  196. package/.claude/skills/sprite-editor/scripts/GridSliceTexture.cs +40 -0
  197. package/.claude/skills/sprite-editor/scripts/IsometricSliceTexture.cs +141 -0
  198. package/.claude/skills/sprite-editor/scripts/README.md +134 -0
  199. package/.claude/skills/sprite-editor/scripts/SetPivotExample.cs +58 -0
  200. package/.claude/skills/sprite-editor/scripts/SpriteToPng.cs +88 -0
  201. package/.claude/skills/status/SKILL.md +16 -0
  202. package/.claude/skills/story-readiness/SKILL.md +14 -0
  203. package/.claude/skills/test/SKILL.md +16 -0
  204. package/.claude/skills/ui/SKILL.md +142 -0
  205. package/.claude/skills/ui-imgui/SKILL.md +186 -0
  206. package/.claude/skills/ui-imgui/references/gui-elements.md +156 -0
  207. package/.claude/skills/ui-imgui/references/templates.md +141 -0
  208. package/.claude/skills/ui-review/SKILL.md +14 -0
  209. package/.claude/skills/ui-ugui/SKILL.md +282 -0
  210. package/.claude/skills/ui-ugui/references/scrollview-setup.md +29 -0
  211. package/.claude/skills/ui-uitk/SKILL.md +235 -0
  212. package/.claude/skills/ui-uitk/references/common-issues.md +74 -0
  213. package/.claude/skills/ui-uitk/references/custom-elements.md +241 -0
  214. package/.claude/skills/ui-uitk/references/painter2d.md +282 -0
  215. package/.claude/skills/ui-uitk/references/pointermanipulator-guide.md +94 -0
  216. package/.claude/skills/ui-uitk/references/svg-icons.md +136 -0
  217. package/.claude/skills/ui-uitk/references/ui-runtime-binding.md +234 -0
  218. package/.claude/skills/ui-uitk/references/uss-guide.md +138 -0
  219. package/.claude/skills/unity-cli/CHANGELOG.md +233 -0
  220. package/.claude/skills/unity-cli/SECURITY.md +22 -0
  221. package/.claude/skills/unity-cli/SKILL.md +414 -0
  222. package/.claude/skills/unity-cli/references/auth-license-cloud.md +146 -0
  223. package/.claude/skills/unity-cli/references/build-run-test.md +349 -0
  224. package/.claude/skills/unity-cli/references/collaboration.md +472 -0
  225. package/.claude/skills/unity-cli/references/config-hub.md +103 -0
  226. package/.claude/skills/unity-cli/references/diagnostics-maintenance.md +326 -0
  227. package/.claude/skills/unity-cli/references/editors-install.md +327 -0
  228. package/.claude/skills/unity-cli/references/integration-advanced.md +472 -0
  229. package/.claude/skills/unity-cli/references/projects-templates.md +574 -0
  230. package/.claude/skills/unity-package-management/SKILL.md +304 -0
  231. package/.claude/skills/unity-package-management/references/select-packages.md +108 -0
  232. package/.claude/skills/urp-postprocessing/SKILL.md +188 -0
  233. package/.claude/skills/urp-postprocessing/references/code-templates.md +119 -0
  234. package/.claude/skills/urp-postprocessing/references/effect-reference.md +86 -0
  235. package/.claude/skills/validate-urp-render-graph-renderer-feature/SKILL.md +269 -0
  236. package/.claude/skills/work/SKILL.md +36 -0
  237. package/.claude/skills/work/references/classification.md +41 -0
  238. package/.claude/skills/work/references/closure.md +50 -0
  239. package/.claude/skills/work/references/feature-contracts.md +32 -0
  240. package/.claude/skills/work/references/verification.md +26 -0
  241. package/CLAUDE.md +6 -0
  242. package/LICENSE +21 -0
  243. package/README.md +162 -0
  244. package/THIRD_PARTY_NOTICES.md +23 -0
  245. package/UPGRADING.md +32 -0
  246. package/VERSION +1 -0
  247. package/docs/ARCHITECTURE.md +73 -0
  248. package/docs/HUONG-DAN-MIGRATE-VA-SU-DUNG.md +324 -0
  249. package/docs/MIGRATION-MATRIX.md +23 -0
  250. package/docs/PROJECT-POLICY.md +67 -0
  251. package/docs/WORKFLOWS.md +61 -0
  252. package/package-assets/setup-vivox-voice-chat-evals.gitignore +7 -0
  253. package/package.json +41 -0
  254. package/scaffold/.nccgs/bugs/.gitkeep +1 -0
  255. package/scaffold/.nccgs/closures/.gitkeep +1 -0
  256. package/scaffold/.nccgs/context/.gitkeep +1 -0
  257. package/scaffold/.nccgs/decisions/.gitkeep +1 -0
  258. package/scaffold/.nccgs/evidence/.gitkeep +1 -0
  259. package/scaffold/.nccgs/features/.gitkeep +1 -0
  260. package/scaffold/.nccgs/migrations/.gitkeep +1 -0
  261. package/scaffold/.nccgs/playtests/.gitkeep +1 -0
  262. package/scaffold/.nccgs/project.yaml +103 -0
  263. package/scaffold/.nccgs/requirements.yaml +10 -0
  264. package/scaffold/.nccgs/reviews/.gitkeep +1 -0
  265. package/scaffold/.nccgs/state.md +40 -0
  266. package/scaffold/.nccgs/templates/agent-handoff.md +25 -0
  267. package/scaffold/.nccgs/templates/architecture-decision.md +27 -0
  268. package/scaffold/.nccgs/templates/closure-record.md +51 -0
  269. package/scaffold/.nccgs/templates/context-packet.yaml +17 -0
  270. package/scaffold/.nccgs/templates/evidence-record.md +23 -0
  271. package/scaffold/.nccgs/templates/feature-contract.md +35 -0
  272. package/scaffold/.nccgs/templates/migration-plan.md +40 -0
  273. package/scaffold/.nccgs/templates/waiver.md +11 -0
  274. package/scripts/cli.mjs +56 -0
  275. package/scripts/install.mjs +267 -0
  276. package/scripts/sync-unity-skills.mjs +126 -0
  277. package/scripts/validate.mjs +205 -0
  278. package/tests/framework.test.mjs +121 -0
@@ -0,0 +1,199 @@
1
+ ---
2
+ name: optimize-audio
3
+ description: Optimizes Unity 6 audio memory, CPU cost, and playback quality through correct import settings and mixer configuration. Use when the user wants to reduce audio memory usage, choose the right Load Type for short clips versus music versus ambient beds, configure platform-appropriate sample rates and codecs, force 3D audio to mono, or reduce AudioMixer CPU cost from deep group trees or effects running on silent paths.
4
+ ---
5
+ ## Critical Rules
6
+
7
+ - Do not make changes before reporting findings to the user
8
+ - Follow steps in strict order; never jump ahead
9
+ - STOP at every `WAIT` checkpoint and await the user's response before continuing
10
+ - Quality is more important than speed: measure before and after every change
11
+ - Always verify results in a device build; Editor audio stats are indicative only
12
+
13
+ ## 0. Set up the execution path
14
+
15
+ Every C# step below runs inside a live Editor through the Unity CLI. **The `unity-cli` skill owns
16
+ getting you there** — installing the CLI, confirming a connected Editor, adding the project's
17
+ `com.unity.pipeline` package, telling a genuinely absent Editor apart from one stuck in Safe Mode,
18
+ and discovering the Editor's command catalog. Follow it first; don't re-derive any of it here.
19
+
20
+ Two things it can't know for you:
21
+
22
+ - **You need `eval` in particular**, not just a reachable Editor. Confirm it appears in the
23
+ catalog. Its presence depends on the Pipeline package version, not on the CLI, so a healthy
24
+ install can still lack it — if it's missing, say so and stop.
25
+ - **Do not hand-edit `.meta` files to change import settings.** Importer values only take effect
26
+ through `SaveAndReimport()` in a live Editor, so an unreachable Editor is a stop, not a cue to
27
+ edit metadata directly.
28
+
29
+ Run C# with `unity command eval --code '<snippet>'`. Discover the parameter shape from
30
+ `unity command --format json` rather than assuming one. `unity command` defaults to a 30 second
31
+ timeout.
32
+
33
+ ### Passing C# to `eval`
34
+
35
+ `eval` compiles a **statement block, not a file**. Two consequences, both of which cause a compile
36
+ error rather than a warning:
37
+
38
+ - **No `using` directives.** The compiler reads `using UnityEngine;` as a resource-disposal
39
+ statement and rejects it (`CS0210`).
40
+ - **Types must be fully qualified.** A bare `AssetDatabase` or `AudioImporter` does not resolve
41
+ (`CS0246` / `CS0103`), and a bare `Object` is ambiguous with `object` (`CS0104`).
42
+
43
+ The recipes in [resources/audio-import-api.md](resources/audio-import-api.md) are written
44
+ fully qualified so they can be passed to `eval` as-is.
45
+
46
+ ## 1. Pre-Flight: Detect Audio System
47
+
48
+ Before doing anything else, establish the audio environment:
49
+
50
+ 1. **Detect platform and sample rate:** Use `eval` to read `EditorUserBuildSettings.activeBuildTarget` and `AudioSettings.outputSampleRate`. The output sample rate affects whether overriding clip sample rates will actually save memory.
51
+ 2. **Detect AudioMixer presence:** Use the mixer-asset query recipe in [resources/audio-import-api.md](resources/audio-import-api.md) to see if a mixer graph exists. If none exists, note that routing and effect costs are not a concern.
52
+ 3. **Detect AudioListener:** Use the scene-component query recipe in [resources/audio-import-api.md](resources/audio-import-api.md) for `UnityEngine.AudioListener` to confirm exactly one listener is present. Multiple listeners produce incorrect spatialization; zero listeners produce silence.
53
+ 4. **Proceed** only after platform and listener state are confirmed.
54
+
55
+ ## 2. Assess Current State
56
+
57
+ Before recommending any change, gather observable data:
58
+
59
+ 1. **Find all AudioSources:** Use the scene-component query recipe in [resources/audio-import-api.md](resources/audio-import-api.md) for `UnityEngine.AudioSource`. For each result, use **one** `eval` call to batch-read properties — see the batch read recipe in [resources/audio-import-api.md](resources/audio-import-api.md).
60
+ 2. **Inspect mixer topology:** If a mixer was found in Pre-Flight, use `eval` to read the AudioMixer's exposed parameters and group count. A group count above ~8 or effects on the Master group are immediate flags.
61
+ 3. **Check DSP buffer size:** Use the DSP buffer recipe in [resources/audio-import-api.md](resources/audio-import-api.md) to read buffer size. See DSP Buffer Size Guidelines in [resources/platform-settings.md](resources/platform-settings.md) for recommended values.
62
+ 4. **Report findings before making changes:** Summarize ALL detected sources, the listener count, and mixer depth to the user. Flag any immediate risks (e.g., stereo clip with `spatialBlend = 1`, Decompress On Load on a clip > 1 MB, reverb on the Master group).
63
+
64
+ **WAIT for the user to review the assessment before proceeding.**
65
+
66
+ ## 3. Understand Request
67
+
68
+ Route to the correct section based on what the user needs:
69
+
70
+ | User Says | Path |
71
+ |-----------|------|
72
+ | "audio memory too high" / "memory profiler shows audio" | Section 4 — Import settings audit |
73
+ | "load times slow" / "decompression stall" | Section 4 — Load Type review |
74
+ | "DSP spike" / "mixer CPU" / "audio CPU high" | Section 4B — Mixer audit |
75
+ | "3D sound wrong" / "only left channel plays" / "stereo in 3D" | Section 4A — Force To Mono + spatial settings |
76
+ | "quality artifacts" / "voice sounds bad" / "Vorbis crackling" | Section 4C — Compression quality tuning |
77
+ | "mobile audio battery" / "mobile memory" | Section 4D — Mobile sample rate override |
78
+ | "set import settings on all clips" / "batch audio settings" | Section 4 — Bulk import audit |
79
+ | "streaming" / "background loading" / "Addressables audio" | Section 4E — Streaming and async load |
80
+
81
+ If the symptom is ambiguous, ask: "Is the problem audio memory usage, DSP CPU spikes, or audio playback quality?"
82
+
83
+ ## 4. Primary Diagnostic Workflow
84
+
85
+ Use the findings from Section 2 to determine which sub-section applies. More than one may apply simultaneously.
86
+
87
+ ### 4A. Force To Mono and Spatial Settings
88
+
89
+ For any AudioSource where `spatialBlend > 0` (3D positioned sound):
90
+
91
+ 1. **Check clip channel count:** Use `eval` to read `audioSource.clip.channels`. If `channels == 2` and `spatialBlend == 1`, only the left channel plays — this is a bug, not a feature.
92
+ 2. **Recommend Force To Mono:** Use the read importer recipe in [resources/audio-import-api.md](resources/audio-import-api.md) to inspect current settings, then apply Force To Mono using the force-to-mono recipe.
93
+ 3. **Apply and reimport:** Report before/after channel counts to the user.
94
+ 4. **Verify spatial blend:** Use `eval` to confirm `audioSource.spatialBlend` is `1.0` (full 3D) and `audioSource.rolloffMode` is set to an appropriate curve.
95
+
96
+ ### 4B. AudioMixer Audit
97
+
98
+ 1. **Measure group depth:** Use `eval` to walk the mixer's group tree and count levels. More than 3 levels (Master → SFX / Music / Voice → sub-bus) adds routing overhead every frame, even when children are silent.
99
+ 2. **Check effects on silent groups:** Use `eval` to query each group's effects list. Effects such as `AudioReverbFilter` run their DSP at full cost even when no AudioSource routes to that group.
100
+ 3. **Flag SFX Reverb on parent groups:** This is the most expensive built-in effect. If found on the Master or a high-level group, flag it explicitly.
101
+ 4. **Present recommendations to the user:**
102
+ - Remove or bypass effects on groups that have no active sources.
103
+ - Use **snapshots** to switch mix states (combat / explore / pause) rather than toggling effects at runtime.
104
+ - Flatten unnecessary sub-buses; redirect sources to a shallower ancestor.
105
+
106
+ **WAIT for the user to approve the mixer changes before applying.**
107
+
108
+ 5. **Verify DSP buffer size:** If `bufferLength` from Pre-Flight is very small (< 256), recommend increasing it — see DSP Buffer Size Guidelines in [resources/platform-settings.md](resources/platform-settings.md).
109
+
110
+ ### 4C. Compression Quality Tuning
111
+
112
+ 1. **Read current compression format:** Use the read importer recipe in [resources/audio-import-api.md](resources/audio-import-api.md) to read `compressionFormat` and `quality` for the clips reported by the user.
113
+ 2. **Apply the platform matrix:** See the Compression Format Matrix in [resources/platform-settings.md](resources/platform-settings.md) for per-platform recommendations.
114
+ 3. **Warn about lossy sources:** Use the lossy source check recipe in [resources/audio-import-api.md](resources/audio-import-api.md). If the original file is MP3, warn the user that lossy source quality is lost permanently after Unity re-encodes. Recommend WAV or AIFF sources.
115
+
116
+ ### 4D. Mobile Sample Rate Override
117
+
118
+ 1. **Identify SFX clips on mobile target:** Use the scene-component query recipe for `UnityEngine.AudioSource` and filter for non-music, non-dialogue clips.
119
+ 2. **Read current sample rate setting:** Use the read importer recipe in [resources/audio-import-api.md](resources/audio-import-api.md) to read `sampleRateSetting` and `sampleRateOverride` for each clip.
120
+ 3. **Apply mobile override:** Use the sample rate override recipe in [resources/audio-import-api.md](resources/audio-import-api.md). See Sample Rate Recommendations in [resources/platform-settings.md](resources/platform-settings.md) for per-use-case rates.
121
+ 4. **Report savings:** Halving the sample rate halves the PCM memory cost. Report the estimated saving for each clip changed.
122
+
123
+ ### 4E. Load Type and Streaming
124
+
125
+ 1. **Audit Load Type per clip:** Use `eval` to read `clip.loadType` for each clip found in Section 2.
126
+ 2. **Apply the decision rule:** See Load Type Decision Table in [resources/platform-settings.md](resources/platform-settings.md).
127
+ 3. **Flag mismatches:** See Load Type Mismatch Flags in [resources/platform-settings.md](resources/platform-settings.md). Report both types of mismatches to the user.
128
+ 4. **Apply `Load In Background`** for any Streaming clip — use the Load In Background recipe in [resources/audio-import-api.md](resources/audio-import-api.md).
129
+
130
+ ## 5. Validation
131
+
132
+ After any import setting or mixer change:
133
+
134
+ 1. **Re-read clip stats:** Use `eval` to re-read `clip.loadType`, `clip.channels`, `AudioSettings.outputSampleRate`, and the importer's `compressionFormat` to confirm the change applied after reimport.
135
+ 2. **Confirm AudioSource routing:** Use the scene-component query recipe for `UnityEngine.AudioSource` and verify `audioSource.outputAudioMixerGroup` is assigned as expected after any mixer restructure.
136
+ 3. **Report delta:** State the before and after values for each setting changed. Do not assume the change was effective without reading back the applied importer values.
137
+ 4. **Iterate limit:** Maximum 3 adjust-and-verify cycles before pausing to ask the user for feedback.
138
+
139
+ ## 6. Troubleshooting
140
+
141
+ ### Stereo clip on a 3D AudioSource — only left channel audible
142
+
143
+ 1. Confirm `audioSource.spatialBlend == 1`.
144
+ 2. Confirm `audioSource.clip.channels == 2`.
145
+ 3. Enable `forceToMono` in the AudioClip importer and reimport. Unity mixes both channels to mono during import, preserving level with `normalize = true` (keep on).
146
+ 4. If the user does not want to reimport: set `audioSource.panStereo = 0` as a runtime workaround, but warn this does not recover stereo information.
147
+
148
+ ### Decompress On Load clip causes memory spike
149
+
150
+ 1. Confirm `clip.loadType == AudioClipLoadType.DecompressOnLoad` and `clip.length` is long (> 5 s).
151
+ 2. Switch to `Streaming` if it is music or ambience, `CompressedInMemory` if played only occasionally.
152
+ 3. If the clip is short but still large: check `clip.channels` (stereo wastes double the memory) and `clip.frequency` (high sample rate on a mobile target wastes memory). Apply Force To Mono and/or sample rate override.
153
+
154
+ ### AudioMixer CPU spike — DSP thread hot
155
+
156
+ 1. Confirm with the mixer-asset query recipe that the mixer graph exists.
157
+ 2. Use `eval` to list all groups and their attached effects. Look for reverb, chorus, or EQ on high-level groups.
158
+ 3. Move expensive effects down to leaf groups that are only active when sources are playing.
159
+ 4. Use snapshots to bypass effect chains during gameplay states where they are not heard (e.g., bypass reverb during a menu).
160
+ 5. If the DSP buffer is small (64 or 128 samples), raise it — see DSP Buffer Size Guidelines in [resources/platform-settings.md](resources/platform-settings.md).
161
+
162
+ ### Vorbis quality artifacts on dialogue
163
+
164
+ 1. Confirm `defaultSampleSettings.compressionFormat == AudioCompressionFormat.Vorbis`.
165
+ 2. Confirm `defaultSampleSettings.quality` — default is 0.5, which is often audible on voice. Raise to 0.7–0.85.
166
+ 3. On iOS: switch to AAC instead of Vorbis (hardware decode, better quality at equivalent bitrate).
167
+ 4. Confirm the source file is lossless (WAV or AIFF). MP3 sources cannot recover quality lost before Unity's re-encode.
168
+
169
+ ### AudioListener count is not exactly one
170
+
171
+ - **Zero listeners:** All audio will be silent. Use `eval` to add an `AudioListener` component to the main camera: `UnityEngine.Camera.main.gameObject.AddComponent<UnityEngine.AudioListener>()`.
172
+ - **Multiple listeners:** Unity uses the last enabled one, producing unpredictable spatialization. Use the scene-component query recipe for `UnityEngine.AudioListener` and disable all but the intended one.
173
+
174
+ ### `Load In Background` causes first-play silence
175
+
176
+ This is expected behavior: the clip has not finished loading when `Play()` is first called. Mitigate with:
177
+ 1. Preload the clip at scene start by calling `clip.LoadAudioData()` before it is needed.
178
+ 2. Use `AudioSource.PlayScheduled()` with a slight delay to allow async load to complete.
179
+ 3. For AudioSources that must play immediately: switch to `CompressedInMemory` (synchronous on first play) rather than `Streaming` with background load.
180
+
181
+ ## 7. Completion
182
+
183
+ After finishing the audit or optimization:
184
+
185
+ - Summarize every setting changed with before/after values.
186
+ - List any clips or groups that still need attention (e.g., clips that require on-device measurement to confirm savings).
187
+ - If the user needs runtime memory measurement, point them at the Memory Profiler package, which reports the largest AudioClips by runtime byte cost.
188
+ - If mixer CPU is still high after the audit, point them at the Unity Profiler's Audio module for DSP thread profiling.
189
+
190
+ ## Detailed References
191
+
192
+ - **Platform settings, compression matrix, load types, sample rates:** [resources/platform-settings.md](resources/platform-settings.md)
193
+ - **AudioImporter API recipes and code patterns:** [resources/audio-import-api.md](resources/audio-import-api.md)
194
+
195
+ ## See Also
196
+
197
+ - **Memory Profiler package** — finds the largest AudioClips by runtime byte cost.
198
+ - **Unity Profiler, Audio module** — DSP CPU markers and frame-time budget.
199
+ - `audio-setup-mixers` — creating mixers and routing Audio Sources into groups.
@@ -0,0 +1,146 @@
1
+ # Audio Import API Recipes
2
+
3
+ C# code recipes for `unity command eval --code '<snippet>'`. All examples target the Unity 6
4
+ AudioImporter API.
5
+
6
+ `eval` compiles a statement block, so there are no `using` directives and every type is written
7
+ fully qualified. Each recipe `return`s its result as a string rather than calling `Debug.Log`, so
8
+ the value comes back on the CLI's stdout instead of only reaching the Editor console.
9
+
10
+ ## Read AudioClip Importer Settings
11
+
12
+ ```csharp
13
+ var path = UnityEditor.AssetDatabase.GetAssetPath(audioSource.clip);
14
+ var importer = (UnityEditor.AudioImporter)UnityEditor.AssetImporter.GetAtPath(path);
15
+ return $"forceToMono={importer.forceToMono}, loadType={importer.defaultSampleSettings.loadType}, " +
16
+ $"compressionFormat={importer.defaultSampleSettings.compressionFormat}, " +
17
+ $"quality={importer.defaultSampleSettings.quality}, " +
18
+ $"sampleRateSetting={importer.defaultSampleSettings.sampleRateSetting}, " +
19
+ $"sampleRateOverride={importer.defaultSampleSettings.sampleRateOverride}");
20
+ ```
21
+
22
+ ## Force To Mono and Reimport
23
+
24
+ ```csharp
25
+ var path = UnityEditor.AssetDatabase.GetAssetPath(audioSource.clip);
26
+ var importer = (UnityEditor.AudioImporter)UnityEditor.AssetImporter.GetAtPath(path);
27
+ importer.forceToMono = true;
28
+ importer.SaveAndReimport();
29
+ return $"Reimported {path} — channels now: {audioSource.clip.channels}");
30
+ ```
31
+
32
+ ## Set Load Type
33
+
34
+ ```csharp
35
+ var path = UnityEditor.AssetDatabase.GetAssetPath(audioSource.clip);
36
+ var importer = (UnityEditor.AudioImporter)UnityEditor.AssetImporter.GetAtPath(path);
37
+ var settings = importer.defaultSampleSettings;
38
+ settings.loadType = UnityEngine.AudioClipLoadType.Streaming; // or CompressedInMemory, DecompressOnLoad
39
+ importer.defaultSampleSettings = settings;
40
+ importer.SaveAndReimport();
41
+ ```
42
+
43
+ ## Enable Load In Background
44
+
45
+ ```csharp
46
+ var path = UnityEditor.AssetDatabase.GetAssetPath(audioSource.clip);
47
+ var importer = (UnityEditor.AudioImporter)UnityEditor.AssetImporter.GetAtPath(path);
48
+ importer.loadInBackground = true;
49
+ importer.SaveAndReimport();
50
+ ```
51
+
52
+ ## Set Compression Format and Quality
53
+
54
+ ```csharp
55
+ var path = UnityEditor.AssetDatabase.GetAssetPath(audioSource.clip);
56
+ var importer = (UnityEditor.AudioImporter)UnityEditor.AssetImporter.GetAtPath(path);
57
+ var settings = importer.defaultSampleSettings;
58
+ settings.compressionFormat = UnityEngine.AudioCompressionFormat.Vorbis;
59
+ settings.quality = 0.7f; // 0.0–1.0; raise to 0.7–0.85 for dialogue
60
+ importer.defaultSampleSettings = settings;
61
+ importer.SaveAndReimport();
62
+ ```
63
+
64
+ ## Override Sample Rate (Mobile)
65
+
66
+ ```csharp
67
+ var path = UnityEditor.AssetDatabase.GetAssetPath(audioSource.clip);
68
+ var importer = (UnityEditor.AudioImporter)UnityEditor.AssetImporter.GetAtPath(path);
69
+ var settings = importer.defaultSampleSettings;
70
+ settings.sampleRateSetting = UnityEditor.AudioSampleRateSetting.OverrideSampleRate;
71
+ settings.sampleRateOverride = 22050u;
72
+ importer.defaultSampleSettings = settings;
73
+ importer.SaveAndReimport();
74
+ ```
75
+
76
+ ## Read AudioSource Properties (Batch)
77
+
78
+ Read multiple properties in a single `eval` call:
79
+
80
+ ```csharp
81
+ var src = audioSource;
82
+ return $"clip={src.clip?.name}, loadType={src.clip?.loadType}, " +
83
+ $"channels={src.clip?.channels}, frequency={src.clip?.frequency}, " +
84
+ $"spatialBlend={src.spatialBlend}, rolloff={src.rolloffMode}, " +
85
+ $"mixerGroup={src.outputAudioMixerGroup?.name ?? "None"}, " +
86
+ $"bypassEffects={src.bypassEffects}");
87
+ ```
88
+
89
+ ## Read DSP Buffer Size
90
+
91
+ ```csharp
92
+ UnityEngine.AudioSettings.GetDSPBufferSize(out int bufferLength, out int numBuffers);
93
+ return $"DSP buffer: {bufferLength} samples x {numBuffers} buffers");
94
+ ```
95
+
96
+ ## Check Source File Format (Lossy Warning)
97
+
98
+ ```csharp
99
+ var path = UnityEditor.AssetDatabase.GetAssetPath(clip);
100
+ if (path.EndsWith(".mp3", System.StringComparison.OrdinalIgnoreCase))
101
+ return $"'{clip.name}' is MP3 — lossy source quality is lost permanently after Unity re-encodes. Recommend WAV or AIFF sources.");
102
+ ```
103
+
104
+ ## Resolving `audioSource` / `clip` inside a snippet
105
+
106
+ The recipes above are written against an `audioSource` or `clip` variable. `eval` runs each
107
+ snippet in a fresh scope, so nothing carries over between calls — resolve the object at the top of
108
+ the same snippet that uses it.
109
+
110
+ By scene object:
111
+
112
+ ```csharp
113
+ var sources = UnityEngine.Object.FindObjectsByType<UnityEngine.AudioSource>(
114
+ UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None);
115
+ var audioSource = System.Array.Find(sources, s => s.gameObject.name == "TheGameObjectName");
116
+ ```
117
+
118
+ By asset path, when you already know the clip:
119
+
120
+ ```csharp
121
+ var clip = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.AudioClip>("Assets/Audio/Foo.wav");
122
+ ```
123
+
124
+ ## Enumerate scene components
125
+
126
+ Substitute the component type (`UnityEngine.AudioSource`, `UnityEngine.AudioListener`). Inactive
127
+ objects are included deliberately — a disabled second listener still counts against the
128
+ one-listener rule.
129
+
130
+ ```csharp
131
+ var found = UnityEngine.Object.FindObjectsByType<UnityEngine.AudioSource>(
132
+ UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None);
133
+ var names = System.Linq.Enumerable.Select(found, c => c.gameObject.name);
134
+ return $"count={found.Length}: {string.Join(", ", names)}";
135
+ ```
136
+
137
+ ## Enumerate mixer assets
138
+
139
+ An `AudioMixer` is a project asset, not a scene object, so it is found through the asset database
140
+ rather than a scene query.
141
+
142
+ ```csharp
143
+ var guids = UnityEditor.AssetDatabase.FindAssets("t:AudioMixer");
144
+ var paths = System.Linq.Enumerable.Select(guids, UnityEditor.AssetDatabase.GUIDToAssetPath);
145
+ return $"count={guids.Length}: {string.Join(", ", paths)}";
146
+ ```
@@ -0,0 +1,48 @@
1
+ # Audio Platform Settings Reference
2
+
3
+ ## Compression Format Matrix
4
+
5
+ | Platform | Recommended Format | Notes |
6
+ |---|---|---|
7
+ | PC / cross-platform | Vorbis, quality 0.5–0.7 | Raise to 0.7–0.85 for dialogue; default 0.5 often adds artifacts |
8
+ | iOS | AAC | Hardware decode; cheapest CPU |
9
+ | Android | Vorbis | Software decode |
10
+ | Xbox | XMA | Use platform override in import settings |
11
+ | PlayStation | ATRAC9 | Use platform override in import settings |
12
+ | Web | Vorbis | Browser handles decode |
13
+
14
+ ## Sample Rate Recommendations
15
+
16
+ | Use Case | Recommended Rate |
17
+ |---|---|
18
+ | PC / console music and voice | 44100 Hz |
19
+ | PC / console SFX | 44100 Hz |
20
+ | Mobile SFX | 22050 Hz |
21
+ | Mobile dialogue | 22050 or 44100 Hz |
22
+ | UI clicks / blips | 22050 Hz |
23
+
24
+ Halving the sample rate halves the PCM memory cost. Always report the estimated saving for each clip changed.
25
+
26
+ ## Load Type Decision Table
27
+
28
+ | Load Type | Behavior | Use For |
29
+ |---|---|---|
30
+ | Decompress On Load | PCM in memory at load; zero per-play CPU | Short SFX < 200 KB (uncompressed) |
31
+ | Compressed In Memory | Stays compressed; decompresses on play | Medium clips played occasionally |
32
+ | Streaming | Streams from disk; minimal RAM, higher disk I/O | Music, long ambience, voice-overs |
33
+
34
+ ### Load Type Mismatch Flags
35
+
36
+ - **Decompress On Load** on a clip > 1 MB bloats memory.
37
+ - **Streaming** on a clip that plays dozens of times simultaneously adds disk pressure.
38
+ - Always apply `Load In Background` for any Streaming clip to prevent the main thread stalling on first play.
39
+
40
+ ## DSP Buffer Size Guidelines
41
+
42
+ | Setting | Buffer Size | Use Case |
43
+ |---|---|---|
44
+ | Best Latency | 256 | Rhythm games, real-time synthesis |
45
+ | Good Latency | 512 | General gameplay |
46
+ | Best Performance | 1024 | Ambient/cinematic, battery-saving |
47
+
48
+ A very small buffer (64 or 128) costs more CPU per frame. If `bufferLength` is < 256, recommend increasing to "Good Latency" or "Best Performance" to trade latency for CPU stability.
@@ -0,0 +1,182 @@
1
+ ---
2
+ name: optimize-text-mesh-pro
3
+ description: >
4
+ Covers TextMeshPro font stacks, dynamic fallback atlases, padding and
5
+ sampling ratios, SDF16, AutoSize discipline, worldspace vs UGUI, and Memory
6
+ Profiler font-data capture. Use when the user mentions TextMeshPro,
7
+ Text Mesh Pro, TMP (TextMeshPro), font asset, dynamic atlas, TMP localization,
8
+ CJK (Chinese, Japanese, Korean) fonts, font alignment across
9
+ scripts, mixed western and eastern fonts, text rendering performance, profiler
10
+ markers related to text generation or glyph rasterization, font fallback
11
+ strategy, font normalization, multilingual or localized text rendering, SDF
12
+ font quality, or text-related memory issues—not for UI Toolkit layout
13
+ (unity-ui-toolkit) or non-TMP uGUI (unity-ui).
14
+ ---
15
+
16
+ # Optimize TextMeshPro
17
+
18
+ ## Triage — identify the symptom first
19
+
20
+ Before providing tips, identify which category the user's issue falls into. If the user has not described a specific symptom, ask: "Are you seeing a **memory/atlas bloat**, **visual quality**, **CPU/performance**, **build size**, or **localization/alignment** issue with TextMeshPro?"
21
+
22
+ | Symptom | Go To |
23
+ |---|---|
24
+ | Memory Profiler shows large or multiple TMP atlases | [Font Stack & Dynamic Fallbacks](#font-stack--dynamic-fallbacks), [Memory Profiler: Include Font Data](#memory-profiler-include-font-data) |
25
+ | Inconsistent glyph weight, fuzzy edges, visual quality | [Padding & Sampling Ratios](#padding--sampling-ratios), [Font Asset Scale](#font-asset-scale), [Atlas Render Mode: SDF16](#atlas-render-mode-sdf16) |
26
+ | CPU spikes during text updates or Canvas rebuilds | [AutoSize](#autosize), [Worldspace vs Canvas Text](#worldspace-vs-canvas-text) |
27
+ | Build size too large from shipped font files | [Dynamic OS Atlas Population](#dynamic-os-atlas-population-tmp-320-pre3) |
28
+ | Mixed Latin + CJK alignment looks off | [Font Normalization](#font-normalization) |
29
+ | Need multiple font styles (italic, outline, glow) | [Material Presets](#material-presets) |
30
+
31
+ ---
32
+
33
+ ## Core Rules
34
+
35
+ - **Main font = static asset with all glyphs baked in.** Add **dynamic** fallbacks via the Fallback list (or TMP Settings) for everything else. Keep dynamic atlas size at **512-1024** to bound peak memory.
36
+ - **Dynamic fallback fonts -> enable `Clear Dynamic Data On Build`.** Otherwise editor-baked glyphs ship in the player.
37
+ - **Keep Padding-to-Sampling-Point-Size ratio consistent across primary + fallback fonts.** Mismatch produces inconsistent glyph weight on the same line.
38
+ - **Latin sampling point size 70-90; CJK 36-50.** Different scripts need different sampling sizes for clean SDF.
39
+ - **Font asset Scale = 1.** Anything else (e.g., 0.9) breaks standard point-size math.
40
+ - **Disable AutoSize at runtime once layout is locked.** AutoSize is for design, not for live counters.
41
+ - **Worldspace text -> use `TextMeshPro`, not `TextMeshProUGUI`.** Canvas overhead in worldspace is not free.
42
+ - **Parent often-changing TMP UI to its own Canvas** to bound rebuild cost.
43
+ - **TMP material presets > duplicating font assets** for italic / bold / outline / glow variants of the same font.
44
+ - **For shipping multilingual builds on iOS/Android, evaluate `Atlas Population Mode = Dynamic OS`** (TMP 3.2.0-pre.3+) to leverage system fonts and shrink the build.
45
+
46
+ ---
47
+
48
+ ## Font Stack & Dynamic Fallbacks
49
+
50
+ If the user reports memory bloat from TMP atlases, advise this font stack pattern:
51
+
52
+ ```
53
+ Main font asset (static, all required Latin glyphs baked)
54
+ -> Fallback 1: Dynamic font (atlas 512 or 1024) for CJK
55
+ -> Fallback 2: Dynamic font for symbols / emoji
56
+ ```
57
+
58
+ **NEVER ship a dynamic fallback font asset without enabling `Clear Dynamic Data On Build`.** Every glyph baked while testing in the editor is included in the player build if this toggle is off.
59
+
60
+ ---
61
+
62
+ ## Padding & Sampling Ratios
63
+
64
+ If the user reports inconsistent stroke widths or glyph weight differences between primary and fallback fonts, check the padding-to-sampling-point-size ratio.
65
+
66
+ The ratio is `Padding / SamplingPointSize`. With Padding = 9 and Sampling Point Size = 90, ratio = **10%**.
67
+
68
+ - A primary font with one ratio and a fallback with a different ratio produces **inconsistent stroke widths** on the same line.
69
+ - Pick a ratio (10% is a safe default), apply it to all font assets in the chain.
70
+
71
+ Recommended sampling point sizes:
72
+
73
+ - **Latin scripts**: 70-90.
74
+ - **CJK scripts**: 36-50 (CJK glyphs are visually denser; smaller sampling sizes still produce clean SDF and save atlas memory).
75
+
76
+ ---
77
+
78
+ ## Font Asset Scale
79
+
80
+ If the user reports point sizes not matching design specs, check the font asset Scale value. Some imported TMP font assets ship with `Scale = 0.9` instead of `1.0`. The Scale value participates in the point-size-to-pixels math, so a non-1 scale produces non-standard point sizes. Advise the user to **set Scale = 1 on all font assets before adjusting padding ratios**.
81
+
82
+ ---
83
+
84
+ ## Sprite Assets
85
+
86
+ If the user reports slow loading times for TMP Sprite Assets on mobile, check the source texture's Texture Type. It must be set to **Default** (not Sprite). Sprite type creates child sub-objects that TMP doesn't use; Default avoids them.
87
+
88
+ ---
89
+
90
+ ## AutoSize
91
+
92
+ If the user reports CPU spikes on text fields that change frequently (timers, counters, chat, dynamic player names), check whether `enableAutoSizing` is on. AutoSize resizes the text whenever the string changes, causing constant CPU spikes.
93
+
94
+ Advise: **disable AutoSize and hard-code the chosen point size** once layout is locked. Keep AutoSize on only for genuinely static labels that auto-fit on locale change.
95
+
96
+ ---
97
+
98
+ ## Atlas Render Mode: SDF16
99
+
100
+ If a static font with point size **72 or larger** looks unclear or has fuzzy edges, advise switching the **Atlas Render Mode** to **SDF16**. Higher precision SDF for big glyphs, at slightly more atlas memory.
101
+
102
+ ---
103
+
104
+ ## Font Normalization
105
+
106
+ If the user reports misaligned Latin + CJK text on the same line, walk them through this procedure:
107
+
108
+ 1. **Window -> TextMeshPro -> Settings -> Import TMP Example & Extras** (one-time per project).
109
+ 2. Add the **`TMP_TextInfoDebugTool`** component to the TextMeshPro object displaying misaligned text.
110
+ 3. Enable **ShowLines** toggle - the ascender, descender, and baseline render as overlays.
111
+ 4. Mix Latin + CJK strings; if the lines diverge, **adjust ascender/descender on the TMP Font Asset** until they align.
112
+
113
+ > **Caveat**: importing TMP Examples & Extras has been observed to cause an infinite import loop on some project layouts. If it happens, close Unity and re-open - the import resolves on the second attempt.
114
+
115
+ ---
116
+
117
+ ## Material Presets
118
+
119
+ If the user needs multiple styles (italic, bold, outline, glow) of the same font, advise material presets instead of duplicating font assets. Presets share the same font texture but override shader parameters.
120
+
121
+ How to create:
122
+
123
+ 1. Select a TMP Text GameObject.
124
+ 2. In Inspector, find the **Material** section.
125
+ 3. **Right-click the Material header -> Create Material Preset.**
126
+ 4. Rename the new material and tweak settings.
127
+ 5. On the TMP Text component, pick the preset from the **Material Preset dropdown**.
128
+
129
+ ---
130
+
131
+ ## Dynamic OS Atlas Population (TMP 3.2.0-pre.3)
132
+
133
+ If the user is shipping multilingual builds and concerned about build size, advise evaluating **`Atlas Population Mode = Dynamic OS`** (TMP 3.2.0-pre.3+):
134
+
135
+ - In Editor: still uses the source font from the project.
136
+ - In a player build: **the source font is not included**. At runtime, Unity searches the device for a font with the matching Family + Style name.
137
+
138
+ Recommended system fonts for CJK:
139
+
140
+ | Platform | Recommended system font |
141
+ |---|---|
142
+ | **Android** | NotoSans (covers Chinese, Japanese, Korean glyphs broadly). |
143
+ | **iOS** | PingFang for Simplified/Traditional Chinese. iOS uses **unique fonts per language** for CJK (different families for Chinese, Japanese, Korean) - check the fallback chain when shipping a single TMP setup across all three. |
144
+
145
+ Wins: build size shrinks (no shipped CJK font files) and memory drops (system font is shared with the OS).
146
+
147
+ ---
148
+
149
+ ## Memory Profiler: Include Font Data
150
+
151
+ If Memory Profiler shows unexpectedly large font asset sizes in the Editor, check whether **Include Font Data** is enabled on the `.ttf` / `.ttc` import settings. The Editor includes the source font file in the asset by default, but on device (especially with Dynamic OS), this cost is not paid.
152
+
153
+ To make Editor captures match device: on the font file -> deselect **Include Font Data** in the import settings. Memory Profiler will then show overhead **without** the underlying font file.
154
+
155
+ ---
156
+
157
+ ## Worldspace vs Canvas Text
158
+
159
+ If the user has worldspace text (damage numbers, signs, holograms) using `TextMeshProUGUI`, advise switching to **`TextMeshPro`**. Worldspace Canvas is a known inefficiency.
160
+
161
+ If a `TextMeshProUGUI` element's `text` changes often (timers, counters, chat), advise **parenting it under a child GameObject with its own Canvas component**. Canvas rebuilds are scoped per-Canvas, so isolating the volatile field cuts rebuild cost on the rest of the UI.
162
+
163
+ ---
164
+
165
+ ## Common Pitfalls
166
+
167
+ If the user's setup matches any of these, flag it:
168
+
169
+ - One giant dynamic font asset for all languages instead of static main + dynamic fallback - the dynamic atlas balloons.
170
+ - Inconsistent padding ratio across primary + fallback - same line of text looks like two fonts.
171
+ - Font asset Scale = 0.9 inherited from import - point sizes won't match design specs.
172
+ - Leaving AutoSize on for live counters - hidden CPU spikes.
173
+ - World-space `TextMeshProUGUI` inside a worldspace Canvas - extra rebuilds for no benefit; use `TextMeshPro`.
174
+ - Forgetting **Clear Dynamic Data On Build** on dynamic fallback fonts - editor-test glyphs ship in the player.
175
+ - Capturing Memory Profiler in Editor with Include Font Data on, then being surprised the on-device build is smaller.
176
+ - Sprite asset source texture set to Sprite type - mobile loading slows from extra child sub-objects.
177
+
178
+ ---
179
+
180
+ ## References
181
+
182
+ - TextMeshPro - Atlas Population Mode (Unity Manual): https://docs.unity3d.com/Packages/com.unity.textmeshpro@latest/manual/FontAssets.html