t1k:unity:dots-core:zstring
| Field | Value |
|---|---|
| Module | dots-core |
| Version | 2.3.2 |
| Effort | high |
| Tools | — |
Keywords: formatting, interpolation, string, zero-allocation
How to invoke
Section titled “How to invoke”/t1k:unity:dots-core:zstringZString — Zero-Allocation String Builder
Section titled “ZString — Zero-Allocation String Builder”Zero-allocation string builder via ThreadStatic buffers + ArrayPool. Eliminates intermediate allocations during concatenation, formatting, and joining. Only allocates final string.
Version: 2.6.0 | License: MIT | Min Unity: 2021.3+ | Status: Production-ready
Related skills:
zlinq(zero-alloc LINQ) ·memorypack(zero-alloc serialization) ·dots-ecs(useFixedStringinside Burst)
When This Skill Triggers
Section titled “When This Skill Triggers”- Using
ZString.Concat,ZString.Format, orZString.Join TextMeshProSetTextFormatorSetTextwith string building- Reducing GC allocations in UI update loops (HUD, scoreboard)
- Debug logging or profiler markers in managed code
- Any
using Cysharp.Text;
Installation
Section titled “Installation”UPM Git URL (add to Packages/manifest.json):
{ "dependencies": { "com.cysharp.zstring": "https://github.com/Cysharp/ZString.git?path=src/ZString.Unity/Assets/Scripts/ZString#2.6.0" }}Or OpenUPM: openupm add com.cysharp.zstring | Or .unitypackage from GitHub Releases.
Min Unity: 2021.3+ | Dependency: System.Runtime.CompilerServices.Unsafe/6.0.0 (included in .unitypackage, add manually for git).
TextMeshPro: Auto-enabled when com.unity.textmeshpro is imported. Or define ZSTRING_TEXTMESHPRO_SUPPORT manually.
Core API
Section titled “Core API”using Cysharp.Text;
// Static — simplest, short-lived stringsZString.Concat(x, y, z); // replaces x + y + zZString.Format("HP: {0}/{1}", hp, maxHp); // replaces string.FormatZString.Join(',', items); // replaces string.Join
// TextMeshPro direct (zero temp allocation)tmp.SetTextFormat("Score: {0}", score);
// Builder — complex multi-stepusing var sb = ZString.CreateStringBuilder();sb.Append("Player: ");sb.AppendFormat("HP: {0}/{1}", hp, maxHp);string result = sb.ToString(); // buffer returned to pool on Dispose
// UTF-8 builder (network/binary)using var sb = ZString.CreateStringBuilder(out var utf8Bytes);sb.Append("player="); sb.Append(playerId);socket.Send(utf8Bytes); // raw UTF-8, no UTF-16 intermediateBest Use Cases vs Avoid
Section titled “Best Use Cases vs Avoid”| Use ZString | Avoid ZString |
|---|---|
| UI HUD text (SetTextFormat) | [BurstCompile] methods |
| Debug logging in Update | IJobEntity / IJobChunk |
| Profiler markers | Use FixedString for Burst |
| Editor tools | Tight simulation loops |
| Network logging (UTF-8) | — |
Critical Gotchas
Section titled “Critical Gotchas”1. NOT Burst-Compatible (BLOCKER) — ThreadStatic violates Burst constraints. Error: BC1064: ThreadStatic field access not supported. → See references/burst-incompatibility-guide.md
2. Requires using var disposal — CreateStringBuilder() without using → buffer never returned to pool (leak). Always write using var sb = ZString.CreateStringBuilder().
3. Nested using corruption — Don’t mix ZString.Format() inside an active builder scope. The static method may acquire the same pool buffer.
4. Buffer reuse across frames — Don’t hold Utf16ValueStringBuilder refs across frames. Build and consume in the same scope.
5. IL2CPP + High stripping — May throw MissingMethodException: ReflectionTypeLoadException. Fix: set Managed Stripping Level to “Medium”, or add Assets/link.xml. → See references/il2cpp-stripping-guide.md
6. Format specifiers — Max 16 type parameters in generic variants. No custom IFormatProvider.
Allocation Savings
Section titled “Allocation Savings”| Scenario | Traditional | ZString |
|---|---|---|
| Concat 3 values | 2-3 allocs | 1 alloc |
| Format 2 args | 2-5 allocs | 1 alloc |
| Builder 10 appends | 2-3 allocs | 1 alloc |
| 1K logs/frame | ~5-10KB GC | ~1KB GC |
DOTS Hybrid Pattern
Section titled “DOTS Hybrid Pattern”Burst computes (no strings) → managed presenter formats with ZString:
// Managed MonoBehaviour reads DOTS data, uses ZString for displaypublic partial class CombatUI : MonoBehaviour{ private void Update() { damageText.SetTextFormat("Damage: {0:F0}", lastDamage); // OK }}Reference Files
Section titled “Reference Files”| File | Contents |
|---|---|
| burst-incompatibility-guide.md | Root cause, hybrid architecture, FixedString workarounds, decision tree |
| il2cpp-stripping-guide.md | IL2CPP stripping fix, Link.xml patterns, deployment checklist |