Skip to content

LeonNikolai/Unity-Field-Enum-Reference

Repository files navigation

Field Reference Enum (Unity Package)

A package that aims to reduce reflection by automatically generating code to access class fields through enums and references, this also has the side effect of making it possible to easily make logic to select individual fields as a exposed field in the Unity Inspector without custom editors.

This relies on the rozlyn source generators.

Installation

Using the Unity Package Manager

  1. Open Package Manager
    • In the window topbar menu navigate Window/Package Management/Package Manager
  2. Install from git url
    • Click the + icon, then click "Install package from git URL..."
  3. In the name field input, type either https://github.com/LeonNikolai/Unity-Field-Enum-Reference.git.

Using manifest.json

  1. Navigate to and open /Packages/manifest.json in your unity project folder (Not /Assets)
  2. Add the line "com.leon-nikolai.field-ref": "https://github.com/LeonNikolai/Unity-Field-Enum-Reference.git",, anywhere between "dependencies":{ and the next }

Usage Examples

using FieldRef;
// Usage Example
[FieldRef(typeof(float))]
public class Player
{
    public float MaxHealth;
    public float Speed;
}

The above code would generate this

// <auto-generated/>
namespace FieldRef.Generated
{
    public static partial class PlayerExtension
    {
        public enum FieldRef_float
        {
            MaxHealth = 0,
            Speed = 1,
        }
        
        public static ref float GetFieldRef(this Player self, FieldRef_float target)
        {
            switch (target)
            {
                case FieldRef_float.MaxHealth: return ref self.MaxHealth;
                case FieldRef_float.Speed: return ref self.Speed;
                default: throw new System.ArgumentOutOfRangeException(nameof(target));
            }
        }
    }
}

This is useful when creating modifier systems in unity, this allows a way to select field targets without reflection or custom inspector editors in Unity.

// Usage Example
[System.Serializable]
public class PlayerModifier
{
    public PlayerExtensions.FieldRef_float TargetValue;
    public Operation ModifierOperation;
    public float ModifierValue;

    public enum Operation
    {
        Add,
        Multiply,
    }

    public void ApplyModifier(Player player)
    {
        ref var field = ref player.GetFieldRef(TargetValue);
        switch (ModifierOperation)
        {
            case Operation.Add:
                field += ModifierValue;
                break;
            case Operation.Multiply:
                field *= ModifierValue;
                break;
        }
    }
}

Partial Classes

If the class is partial, it will put the enum and methods directly into the partial class instead of extension methods.

using FieldRef;
// Usage Example (Partial)
[FieldEnum(typeof(float))]
public partial class Player
{
    public float MaxHealth;
    public float Speed;
}

Above code would generate this

// <auto-generated/>
public partial class Player
{
    public enum FieldRef_float
    {
        MaxHealth = 0,
        Speed = 1,
    }
    
    public ref float GetFieldRef(FieldRef_float target)
    {
        switch (target)
        {
            case FieldRef_float.MaxHealth: return ref this.MaxHealth;
            case FieldRef_float.Speed: return ref this.Speed;
            default: throw new System.ArgumentOutOfRangeException(nameof(target));
        }
    }
}

Static Fields

Support for static fields is also works, they are added as a separate enum and method for code clarity. In a modifier system this might be used to differentiate between global and entity specific modifiers.

using FieldRef;
// Usage Example (Static)
[FieldRef(typeof(float))]
public partial class Enemy
{
    public float BaseMaxHealth;
    public float BaseSpeed;
    public static float EnemyMaxHealthMultiplier;
    public static float EnemySpeedMultiplier;
}

Would generate this

// <auto-generated/>
public partial class Enemy
{
    public enum FieldRef_float
    {
        BaseMaxHealth = 0,
        BaseSpeed = 1,
    }
    
    public ref float GetFieldRef(FieldRef_float target)
    {
        switch (target)
        {
            case FieldRef_float.BaseMaxHealth: return ref this.BaseMaxHealth;
            case FieldRef_float.BaseSpeed: return ref this.BaseSpeed;
            default: throw new System.ArgumentOutOfRangeException(nameof(target));
        }
    }
    public enum StaticFieldRef_float
    {
        EnemyMaxHealthMultiplier = 0,
        EnemySpeedMultiplier = 1,
    }
    
    public static ref float GetFieldRef(StaticFieldRef_float target)
    {
        switch (target)
        {
            case StaticFieldRef_float.EnemyMaxHealthMultiplier: return ref Enemy.EnemyMaxHealthMultiplier;
            case StaticFieldRef_float.EnemySpeedMultiplier: return ref Enemy.EnemySpeedMultiplier;
            default: throw new System.ArgumentOutOfRangeException(nameof(target));
        }
    }
}

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages