-
Notifications
You must be signed in to change notification settings - Fork 10
Layer and tag constants
[assembly: Medicine.GenerateUnityConstants] enables a source generator that reads your Unity project settings and emits a strongly-typed Constants class with:
- Tags (
Constants.Tag) - Layers (
Constants.Layer) - Layer masks (
Constants.LayerMask) - Convenience extensions for
CompareTagand tag handles
- Define the assembly attribute anywhere in your assembly:
[assembly: Medicine.GenerateUnityConstants]- Apply the "Update project settings" quick fix in your IDE. (Switch to Unity so that the settings are reloaded.)
You can also configure Unity manually by adding
-additionalfile:"ProjectSettings/TagManager.asset"to the Additional Compiler Arguments list in Project Settings → Player → Other Settings.
- Use the generated types:
public sealed class Example : MonoBehaviour
{
void Awake()
{
// layers
gameObject.layer = (int)Constants.Layer.Default;
// layer masks (bit masks)
var groundMask = Constants.LayerMask.Ground | Constants.LayerMask.Terrain;
// tags
if (gameObject.CompareTag(Constants.Tag.Player))
Debug.Log("Player!");
}
}When the generator runs, it emits Medicine.Constants.g.cs containing:
namespace Medicine;
public static partial class Constants
{
public enum Tag : uint
{
@SomeTag = 20000u,
@AnotherTag = 20001u,
...
}
public enum Layer : uint
{
@Default = 00,
@TransparentFX = 01,
@Ignore_Raycast = 02,
...
}
[System.Flags]
public enum LayerMask : uint
{
None = 0,
All = 0xffffffff,
@Default = 1u << 00,
@TransparentFX = 1u << 01,
...
}
public static partial class ConstantsExtensions
{
public static UnityEngine.TagHandle GetHandle(this Constants.Tag tag)
=> UnsafeUtility.As<Constants.Tag, UnityEngine.TagHandle>(ref tag);
public static bool CompareTag(this GameObject gameObject, Constants.Tag tag)
=> gameObject.CompareTag(tag.GetHandle());
public static bool CompareTag(this Component component, Constants.Tag tag)
=> component.CompareTag(tag.GetHandle());
}
}- The generator parses the
TagManager.assetfile - simply edit layers/tags in Unity, hitCtrl+Sand changes will be instantly reflected in your code. -
Tags are assigned sequential IDs starting at
20000u. They exist to be stable, typed tokens that can be turned into aTagHandle. - Layers are assigned their actual layer index (0..31).
-
LayerMask values are
1u << layerIndex. - Names are sanitized into valid C# identifiers:
- Always prefixed with
@to avoid keyword conflicts. - Non-identifier characters become
_.
- Always prefixed with
- Empty entries generate placeholders, allowing you to reference layers that aren't yet defined in the project (e.g., in the inspector).
The string-based CompareTag(string) has obvious performance and usability flaws. There exists a faster CompareTag(TagHandle) API, but it is a bit annoying to use.
The generator provides:
- A
GetHandleextension method which converts the enum value to aTagHandle. - Overloads of
CompareTagthat acceptConstants.Tag, so you can compare against the enum directly.
Practical usage:
if (gameObject.CompareTag(Constants.Tag.Enemy))
{
// ...
}This keeps your code:
- Refactor-safe (rename tags/layers and get compiler errors where you need to update usage)
- IDE-friendly (autocomplete instead of string literals)
- Compatible with Unity’s fast tag handle path
The generated Medicine.Constants class is partial and lives in your assembly, so you can extend it with your own constants:
namespace Medicine
{
public static partial class Constants
{
public const int MaxPlayers = 4;
}
}If you add [assembly: Medicine.GenerateUnityConstants] but the generator can’t find TagManager.asset as an AdditionalText, it reports MED018:
TagManager.asset not found. Your project isn't configured for constants generation.
There is an IDE-side quick fix that lets you fix this in the project settings automatically - just remember to switch to Unity after applying so that the settings are reloaded.
You can also configure Unity manually by adding -additionalfile:"ProjectSettings/TagManager.asset" to the Additional Compiler Arguments list in Project Settings → Player → Other Settings.
That’s the sanitization step: anything that isn’t a letter/digit/underscore is converted to _, and the name is prefixed with @.
If you want cleaner identifiers, rename the tag/layer in Unity to something C#-friendly (Player, EnemyBoss, UI_Overlay, etc.).