Skip to content

t1k:unity:dots-core:zstring

FieldValue
Moduledots-core
Version2.3.2
Efforthigh
Tools

Keywords: formatting, interpolation, string, zero-allocation

/t1k:unity:dots-core:zstring

ZString — 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 (use FixedString inside Burst)


  • Using ZString.Concat, ZString.Format, or ZString.Join
  • TextMeshPro SetTextFormat or SetText with string building
  • Reducing GC allocations in UI update loops (HUD, scoreboard)
  • Debug logging or profiler markers in managed code
  • Any using Cysharp.Text;

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.


using Cysharp.Text;
// Static — simplest, short-lived strings
ZString.Concat(x, y, z); // replaces x + y + z
ZString.Format("HP: {0}/{1}", hp, maxHp); // replaces string.Format
ZString.Join(',', items); // replaces string.Join
// TextMeshPro direct (zero temp allocation)
tmp.SetTextFormat("Score: {0}", score);
// Builder — complex multi-step
using 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 intermediate

Use ZStringAvoid ZString
UI HUD text (SetTextFormat)[BurstCompile] methods
Debug logging in UpdateIJobEntity / IJobChunk
Profiler markersUse FixedString for Burst
Editor toolsTight simulation loops
Network logging (UTF-8)

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 disposalCreateStringBuilder() 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.


ScenarioTraditionalZString
Concat 3 values2-3 allocs1 alloc
Format 2 args2-5 allocs1 alloc
Builder 10 appends2-3 allocs1 alloc
1K logs/frame~5-10KB GC~1KB GC

Burst computes (no strings) → managed presenter formats with ZString:

// Managed MonoBehaviour reads DOTS data, uses ZString for display
public partial class CombatUI : MonoBehaviour
{
private void Update()
{
damageText.SetTextFormat("Damage: {0:F0}", lastDamage); // OK
}
}

FileContents
burst-incompatibility-guide.mdRoot cause, hybrid architecture, FixedString workarounds, decision tree
il2cpp-stripping-guide.mdIL2CPP stripping fix, Link.xml patterns, deployment checklist