com.elestrago.unity.generated-code-dump
v1.0.2
Published
Writes the output of every Roslyn source generator in the project to Library/ after each compile, so tools and AI agents can read the real generated code.
Maintainers
Readme
Generated Code Dump
Writes the output of every Roslyn source generator in the project to Library/GeneratedCodeDump/ after each compile, so tools and AI agents can read the real generated code.
A source generator is a plug-in for the C# compiler that writes extra code while an assembly compiles. Unity runs them inside its compiler and never saves what they write. A tool or AI agent reading the project sees only the attributes and partial declarations, not the members the generators add, so it has to guess them.
This package compiles each assembly again with Unity's own compiler and keeps every file the generators wrote. Each file gets header lines that say when it was dumped, and name the assembly, the generator and the file.
Install
Add the scoped registry and the dependency to Packages/manifest.json:
{
"scopedRegistries": [
{
"name": "eLeSTRaGo",
"url": "https://registry.npmjs.org",
"scopes": [
"com.elestrago.unity"
]
}
],
"dependencies": {
"com.elestrago.unity.generated-code-dump": "1.0.2"
}
}- Editor-only: one assembly,
GeneratedCodeDump.Editor, for the Editor platform. Nothing ships in a player build. - Unity 2022.3 or newer. Tested on 6000.0.65f1.
- No package dependencies.
Turn it on
The dump is off by default. The switch belongs to one user in one project, so each developer turns it on for themselves. Use any of these:
- Preferences: Preferences > Generated Code Dump, toggle Dump generated code.
- Menu:
Tools/Generated Code Dump/Enabled(checked while on). - File: write this to
UserSettings/GeneratedCodeDumpSettings.json, for example from a shell:
{"enabled": true}The menu and the toggle write that same file. An open Editor applies an edit within about a second, even while it is in the background, and a closed one reads the file at its next start. A missing file means off. An invalid file, anything but a JSON object whose enabled is true or false, also means off and logs a warning, and it warns again only if the file changes and is still invalid.
UserSettings/ is Unity's per-user folder, so the switch survives deleting Library/. Unity's standard .gitignore ignores /[Uu]ser[Ss]ettings/. If yours does not, add that line, or the switch gets committed.
Turning the dump on runs a full dump. Source generators ship as analyzers, plug-in DLLs the compiler loads for an assembly, so a full dump replays every assembly that loads at least one analyzer; an assembly without one has nothing to dump. A replay runs Unity's compiler again for one assembly, with the same inputs Unity used but its outputs sent to the dump's own folders instead of Unity's.
A full dump also runs when an Editor starts with the dump on, and when a domain reload finds Library/GeneratedCodeDump/ missing while the dump is on, so deleting that folder forces one. After that, each compile replays only the assemblies it rebuilt without errors. Turning the dump off drops the replays that have not started yet; the folder stays but is no longer refreshed.
| Menu item | Does |
| --- | --- |
| Tools/Generated Code Dump/Dump Now | Runs a full dump once, even while the dump is off. |
| Tools/Generated Code Dump/Open Folder | Creates Library/GeneratedCodeDump/ if needed and opens it. |
| Tools/Generated Code Dump/Preferences… | Opens the Preferences/Generated Code Dump page. |
While the dump is off, nothing under Library/GeneratedCodeDump/ is created, except by Dump Now or Open Folder. Neither of them turns the dump on. More in Turning it on and off, When a dump runs, and the examples Turn on the dump and Dump Now.
What you get
A real dump of this repository's example project (its test generators live in External/ and are not shipped):
Library/GeneratedCodeDump/
.work/
Assembly-CSharp/
GeneratedCodeDump.TestGenerators.Classic/
Aux_.g.cs
ExampleBehaviour.generated.cs
ExampleBehaviour~31a944ea.generated.cs
GeneratedCodeDump.TestGenerators.Incremental/
Example.ExampleBehaviour.Dumpable.g.cs
Summary.Info.g.cs
Unity.SourceGenerators/
AssemblyMonoScriptTypes.generated.cs
GeneratedCodeDump.Example.Module/
... (the same three generator folders)
... (one folder per other assembly with generated files)Assembly-CSharp/is the compiled assembly:Assembly-CSharpor an asmdef name.Unity.SourceGenerators/is the generator assembly, the DLL the generator ships in.Unity.SourceGeneratorsis Unity's own and runs on most assemblies.Example.ExampleBehaviour.Dumpable.g.csis the hint name, the file name the generator gave the file. It is kept as one flat name, with no namespace folders.ExampleBehaviour~31a944ea.generated.cs: two generators in one generator assembly gave the same hint name, so the generator whose full type name sorts later alphabetically gets a short hash before the ending. A short hash is~plus 8 hex digits computed from the full name it stands for, here the generator's type name plus the hint name; the same name always gives the same hash, so the file name stays unique and stable from one dump to the next.Aux_.g.cs: a name Windows reserves (CON,AUX,NUL,COM1, …) gets a_, soAux.g.csbecomesAux_.g.cs.- An assembly whose generators write nothing has no folder. Each replay deletes the files its generators no longer write.
.work/holds the dump's own bookkeeping, not generated code. It is Hidden on Windows; skip it when you search.
Every dumped file gets four header lines with full names:
// <auto-generated/>
// Dumped: 2026-09-12 10:15:03 UTC
// Assembly: Assembly-CSharp
// Generator: GeneratedCodeDump.TestGenerators.Incremental / GeneratedCodeDump.TestGenerators.Incremental.DumpableGenerator
// Hint: Example.ExampleBehaviour.Dumpable.g.cs
namespace Example
{
partial class ExampleBehaviourDumped: is when the replay's compiler started, in UTC. The lines go after a // <auto-generated/> line, at the end of a // <auto-generated> comment block, or else at the top; the file's BOM and line endings are kept. They push the generator's code 4 lines down: add 4 to a line number in a compiler message about a generated file to find that line in the dumped file.
Long paths get shorter names, for example UnityEditor.Rendering.HighDefinition.Compositor.CompositionLaye~f7565493.g.cs from a deep project on Windows. The dump keeps every path within the OS limit: 259 characters for a file path on Windows, 1023 bytes on macOS and Linux. When a path is too long, it shortens names in this order until the path fits: the assembly folder, then the generator folder, then the file name, each to its start plus a short hash. A file that still does not fit is skipped with a warning (see Caveats). See Reading the output and Long paths for the full rules.
Find a file
A shortened name loses part of the type name, but the header lines always hold the full names, so search the headers:
grep -rl --exclude-dir=.work "Hint: .*ExampleBehaviour" Library/GeneratedCodeDump
grep -rl --exclude-dir=.work "Assembly: Assembly-CSharp" Library/GeneratedCodeDumpMost search tools skip Library/ because it is git-ignored, so point agents at the path explicitly, for example in CLAUDE.md or AGENTS.md. A file dumped before your last source edit is stale. A file held open by another program is not replaced: it keeps its older content and Dumped: line, and the next dump retries it. More searches are in the example Read the dump.
Batch mode and CI
With the dump on, a -batchmode Editor start runs a full dump and waits for it, so a CI job or an agent can read the dump as soon as Unity exits after -quit. Any batch run while the dump is on, such as -runTests or a build, does the same when it starts.
PROJECT=/path/to/project
UNITY=~/Unity/Hub/Editor/6000.0.65f1/Editor/Unity
SETTINGS="$PROJECT/UserSettings/GeneratedCodeDumpSettings.json"
mkdir -p "$(dirname "$SETTINGS")"
printf '{"enabled": true}\n' > "$SETTINGS"
"$UNITY" -batchmode -nographics -projectPath "$PROJECT" -quit -logFile unity.log
grep '\[Generated Code Dump\]' unity.log
ls "$PROJECT/Library/GeneratedCodeDump"When the dump starts, the log shows [Generated Code Dump] queued <N> assemblies, at most <M> compiling at once; output in Library/GeneratedCodeDump/, where <M> is how many assemblies compile at once. Every message and warning from the dump starts with [Generated Code Dump].
The wait is capped at 300 seconds per round of compiles. A round is one set of assemblies compiled side by side, so 11 assemblies at 6 at once take 2 rounds and wait at most 600 seconds. Past the cap, Unity logs a warning and carries on, and the next Editor session dumps the rest. See Batch mode and CI and the example Dump in batch mode.
Caveats
- The dump relies on Unity internals, not public API: the compiler argument files Unity writes under
Library/Bee/, and the compiler (DotNetSdkRoslyn) and runtime (NetCoreRuntime) that ship with the Editor. If a Unity update breaks one of them, the dump logs a[Generated Code Dump]warning and stops. It never breaks the project's compile. See Warnings and failures. - It only reads Unity's build outputs and never touches them. The dump goes under
Library/, the switch underUserSettings/; nothing is added toAssets/or to the compile. - 2022.3 is the declared minimum but has not been verified.
- After a compile, an assembly that failed is not replayed until it compiles again. A full dump replays it anyway.
- It does not rely on Windows' long-path support. A project path too deep for the limits gets files skipped, with the warning
[Generated Code Dump] <Assembly>: <N> files skipped: their path is over the <limit>-character limit of this OS; move the project to a shorter path.(the limit is 259 characters on Windows and 1023 bytes on macOS and Linux). - A full dump costs about one compile per assembly that loads an analyzer. At most half the logical CPUs compile at once (1 to 8), and in the Editor this runs in the background. See Performance.
Upgrading from 1.0.0
1.0.0 kept its switch and its dump in Library/com.elestrago.unity.generated-code-dump/, with namespace folders in the dump. The first Editor start with this version, batch mode included, moves the old Settings.json to UserSettings/GeneratedCodeDumpSettings.json, unless that file already exists, and deletes the old folder and the old temp folder. Scripts that read the 1.0.0 paths must switch to the flat layout above. Details in Upgrading from 1.0.0.
Documentation
- Manual: the full guide. It covers what the package does, the switch, when a dump runs, the output and path limits, batch mode, warnings and the 1.0.0 migration. It ends with Internals for contributors.
- Examples: four short tasks with shell snippets: turn the dump on, read it, Dump Now and Open Folder, and batch mode.
- API reference: every type in the package's one assembly, all of them internal, with where each is declared.
In short, the dump reads the compiler arguments Unity saved for each assembly, sends every output to a temporary folder, runs Unity's bundled compiler, and moves the generated files into place. The steps are in How it works.
License
MIT. See LICENSE.md.
