Install via the Unity Package Manager (UPM) using a Git URL pointing to the package subfolder in this repository.
- Open Window → Package Manager in Unity.
- Click the + button and choose Add package from git URL…
- Enter the following URL and click Add:
https://github.com/liortal53/BuildMetadata.git?path=Assets/BuildMetadata
The
?path=Assets/BuildMetadatasuffix tells UPM to treat that subdirectory as the package root (wherepackage.jsonlives), rather than the repository root.
To lock to a specific version, append a tag or commit SHA:
https://github.com/liortal53/BuildMetadata.git?path=Assets/BuildMetadata#1.0.0
- Unity 2021.2+ (Roslyn source generator support)
- Git must be installed and on your system
PATH
A Unity build produces a binary that, once compiled, has no inherent memory of when or where it was built, which Git commit it came from, or what environment variables were set on the build machine. This information is invaluable for debugging ("which exact build is this?"), analytics, and CI/CD traceability — but it simply isn't available at runtime through normal Unity APIs.
BuildMetadata solves this by capturing that information at build time and baking it into the game, so it is always accessible at runtime without any manual steps. Version strings, Git branch and commit SHA, build timestamp, machine name, OS, scripting defines, and any custom environment-specific values are gathered the moment the build starts and written to a JSON file that ships with the game. At runtime a single static property gives you everything.
BuildMetadata hooks into the Unity build pipeline to record a snapshot before every build — version strings, Git branch/commit, timestamp, platform settings, and any custom fields you define. At runtime, your game loads this data from a single JSON file via a clean static API.
Custom fields are added by marking a class with [CustomBuildMetadata]. A Roslyn source generator folds the class's properties directly into BuildMetadataData at compile time. No separate JSON files, no boilerplate.
- Unity build starts.
BuildMetadataProcessorruns at preprocess, constructs aBuildMetadataDatawith core values.- It discovers all
[CustomBuildMetadata]classes viaTypeCache, instantiates each, and uses reflection to set their generated backing fields on the same object. - The unified object is serialized to
Resources/Generated/BuildMetadata.json. - At runtime,
Build.Metadatadeserializes lazily from that JSON.
The source generator (Roslyn) runs at C# compile time: it finds [CustomBuildMetadata] classes and emits a partial BuildMetadataData with the corresponding [SerializeField] backing fields and read-only properties. XML doc comments are forwarded to the generated properties.
using BuildMetadata;
var info = Build.Metadata;
Debug.Log($"v{info.AppVersion} {info.GitSha1.Substring(0, 7)} {info.BuildTimestamp}");
// Custom fields land directly on Build.Metadata
Debug.Log(info.CiPipelineId);Create a class in the Runtime assembly (same assembly as BuildMetadataData):
[CustomBuildMetadata]
public class CIMetadata
{
/// <summary>Pipeline ID from CI environment.</summary>
public string CiPipelineId => Environment.GetEnvironmentVariable("CI_PIPELINE_ID") ?? "local";
public string CiTriggeredBy => Environment.GetEnvironmentVariable("CI_TRIGGERER") ?? "unknown";
public bool CiIsAutomated => !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI"));
}After Unity recompiles, Build.Metadata.CiPipelineId, Build.Metadata.CiTriggeredBy, and Build.Metadata.CiIsAutomated are available.
When BuildMetadata.Generator/CustomBuildMetadataGenerator.cs changes:
dotnet build BuildMetadata.Generator/ -c Release
cp BuildMetadata.Generator/bin/Release/netstandard2.0/BuildMetadata.Generator.dll \
Assets/BuildMetadata/Runtime/Analyzers/BuildMetadata.Generator.dllThen Assets → Refresh in Unity and regenerate project files via Edit → Preferences → External Tools → Regenerate project files.
- Unity 2021.2+ (Roslyn source generator support)
- .NET SDK to rebuild the generator DLL
- Git on
PATHfor branch / SHA capture
[CustomBuildMetadata]classes must be in the Runtime assembly so the generator can emit thepartial BuildMetadataDataextension into the same compilation.- Only public instance properties with a getter are picked up — fields and static properties are ignored.
- Property types must be Unity-serializable (
string,int,bool,float, etc.). BuildReportis not accessible inside[CustomBuildMetadata]classes; they are instantiated with no arguments.- Property names must be unique across all
[CustomBuildMetadata]classes.
Assets/BuildMetadata/
├── Editor/
│ ├── BuildMetadataProcessor.cs # IPreprocessBuildWithReport hook
│ ├── Utilities/
│ │ └── GitUtility.cs # Git command runner
│ └── BuildMetadata.Editor.asmdef
└── Runtime/
├── BuildMetadataData.cs # Partial, immutable data container
├── Build.cs # Static API: Build.Metadata
├── CustomBuildMetadataAttribute.cs # [CustomBuildMetadata] attribute
├── Analyzers/
│ └── BuildMetadata.Generator.dll # Roslyn source generator
└── BuildMetadata.Runtime.asmdef
BuildMetadata.Generator/ # Generator source (.NET Standard 2.0 project)
├── BuildMetadata.Generator.csproj
└── CustomBuildMetadataGenerator.cs
MIT — see LICENSE.