Skip to content

Adjust Attributes

Attributes provide a simple and clean way to expose fields, properties, and methods in the Adjust module. Mark your class members either with [Adjust] or one of it's type-specific versions and register the context to make them adjustable at runtime.

Common Attribute Parameters

All Adjust attributes inherit from AdjustAttribute and support these common parameters:

ParameterTypeDefaultDescription
NamestringnullDisplay name in the UI (defaults to member name)
CategorystringnullCategory to group the element under
GroupstringnullGroup within a category for vertical organization
Priorityint0Display order (higher values shown first)
ForceReadOnlyboolfalseMakes the element read-only even if it has a setter
Widthuint0Custom width in pixels (0 = auto)
CommandstringnullCommand name for Console command line access

Values

[Adjust]

The base attribute that works with any supported type. Debby automatically selects the appropriate UI control.

Example:

csharp
public class GameSettings : MonoBehaviour
{
    [Adjust(Category = "Adjustable Values")]
    private int _numberPicker;

    [AdjustFloat(Category = "Adjustable Values", IsSlider = true, Min = 0f, Max = 10f)]
    private float _numberSlider;

    [Adjust(Category = "Adjustable Values")]
    private Color _colorPicker;

    [Adjust(Category = "Adjustable Values")]
    private bool _boolToggle;
    
    [Adjust(Category = "Adjustable Values")]
    private string _stringPicker;

    [Adjust(Category = "Adjustable Values")]
    private Vector3 _vector3Field;
}

Result:

Generic Adjust Values

[AdjustInt] / [AdjustFloat] / [AdjustDouble] / [AdjustLong] / [AdjustUInt] / [AdjustULong]

Specialized attributes for primitive number types values with additional options for sliders and bounds.

AdjustInt slider and picker

Additional Parameters:

  • IsSlider: Display as slider instead of picker
  • Min: Minimum value
  • Max: Maximum value
  • PageSize: Increment/decrement step size (default: 1 and 0.1 for decimals)

Example:

csharp
public class NumericValues : MonoBehaviour
{
    // Int with slider
    [AdjustInt(name: "Health", isSlider: true, min: 0, max: 100)]
    private int _health = 100;

    // Float with custom step size
    [AdjustFloat(name: "Move Speed", min: 0f, max: 20f, pageSize: 0.5f)]
    private float _moveSpeed = 5f;

    // Double for high-precision values
    [AdjustDouble(min: 0.0, max: 1.0, pageSize: 0.001)]
    public double PrecisionValue = 0.5;

    // Long for large numbers
    [AdjustLong(min: 0L, pageSize: 1000L)]
    public long TotalCurrency = 0L;

    // UInt for IDs
    [AdjustUInt]
    public uint EntityID = 0;

    // ULong for very large values
    [AdjustULong]
    public ulong UniverseSeed = 12345UL;
}

[AdjustString]

Specialized attribute for string values, it allows providing a list of options to pick from, which will be displayed as a dropdown.

Example:

csharp
public class PlayerData : MonoBehaviour
{
    [AdjustString(name: "Display Name", options: new [] {"Player", "Enemy"})]
    public string DisplayName = "Player";

    [AdjustString(category: "Debug", command: "debugmsg")]
    public string DebugMessage = "";
}

Actions

[AdjustAction]

Marks a method to be displayed as a button in the Adjust module.

AdjustAction buttons

Additional Parameters:

  • icon (DebbyIcon): Icon displayed on the button

Supported Method Signatures:

  • void MethodName() - Simple synchronous method
  • Task MethodName() - Async method
  • Awaitable MethodName() - Unity Awaitable (Unity 6.0+)
  • UniTask MethodName() - UniTask (if package installed)
  • Methods with Action<float> progress callback for async operations

Example - Basic Actions:

csharp
using UnityEngine;
using Debology.Debby.Modules.Adjust.Attributes;
using Debology.Debby.Elements;

public class GameActions : MonoBehaviour
{
    [AdjustAction(name: "Reset Game", icon: DebbyIcon.Refresh)]
    public void ResetGame()
    {
        Debug.Log("Game reset!");
    }

    [AdjustAction(name: "Spawn Enemy", category: "Debug", icon: DebbyIcon.Add)]
    private void SpawnEnemy()
    {
        // Spawn logic here
    }

    [AdjustAction(name: "Clear Save Data", priority: -10)]
    public void ClearSaveData()
    {
        PlayerPrefs.DeleteAll();
    }

    [AdjustAction(command: "pause")]
    public void TogglePause()
    {
        Time.timeScale = Time.timeScale > 0 ? 0 : 1;
    }
}

Example - Async Actions:

csharp
using System.Threading.Tasks;
using UnityEngine;
using Debology.Debby.Modules.Adjust.Attributes;
using Debology.Debby.Elements;

public class AsyncActions : MonoBehaviour
{
    // Task-based async
    [AdjustAction(name: "Load Level", icon: DebbyIcon.Play)]
    public async Task LoadLevelAsync()
    {
        Debug.Log("Loading level...");
        await Task.Delay(2000);
        Debug.Log("Level loaded!");
    }

    // With progress callback
    [AdjustAction(name: "Download Assets", icon: DebbyIcon.Download)]
    public async Task DownloadAssetsAsync(Action<float> progress)
    {
        for (int i = 0; i <= 100; i += 10)
        {
            progress?.Invoke(i / 100f);
            await Task.Delay(200);
        }
        Debug.Log("Download complete!");
    }

    // Unity Awaitable
    [AdjustAction(name: "Process Data")]
    public async Awaitable ProcessDataAsync()
    {
        await Awaitable.WaitForSecondsAsync(1f);
        Debug.Log("Processing complete!");
    }
}

INFO

When an async method is executing, the button is disabled and displays a progress bar.

Categories and Groups

You can organize your adjustable values into categories and groups to make them easier to find and keep relevant adjustables together.

Categories

Categories create top-level horizontal sections with titles. Use them to group related settings.

csharp
public class OrganizedSettings : MonoBehaviour
{
    [Adjust(category: "Graphics")]
    public bool EnableShadows = true;

    [Adjust(category: "Graphics")]
    public bool EnablePostProcessing = true;

    [Adjust(category: "Audio")]
    public float MasterVolume = 1f;

    [Adjust(category: "Audio")]
    public float MusicVolume = 0.8f;
}

Categories in Adjust

Groups

Groups create vertical sub-sections within categories. Use them for fine-grained organization.

csharp
public class DetailedSettings : MonoBehaviour
{
    // Graphics category, Quality group
    [AdjustInt(category: "Graphics", group: "Quality", min: 0, max: 5)]
    public int QualityLevel = 3;

    [Adjust(category: "Graphics", group: "Quality")]
    public bool VSync = true;

    // Graphics category, Effects group
    [Adjust(category: "Graphics", group: "Effects")]
    public bool Bloom = true;

    [Adjust(category: "Graphics", group: "Effects")]
    public bool MotionBlur = false;
}

Groups within categories

Priority

Use priority to control display order within categories. Higher values appear first.

csharp
public class PriorityExample : MonoBehaviour
{
    [Adjust(priority: 100)] // Shown first
    public bool EnableFeature = true;

    [Adjust(priority: 50)]
    public int FeatureLevel = 1;

    [Adjust(priority: 1)] // Shown last
    public string DebugInfo = "Info";
}

Commands

Any adjustable value or action can be accessed via the Console command line by setting the command parameter.

csharp
[AdjustContext(commandPrefix: "game")]
public class GameController : MonoBehaviour
{
    [AdjustFloat(command: "speed", min: 0f, max: 10f)]
    public float GameSpeed = 1f;

    [AdjustInt(command: "score")]
    public int Score = 0;

    [AdjustAction(command: "reset")]
    public void Reset()
    {
        Score = 0;
        GameSpeed = 1f;
    }
}

Console usage:

> game.speed 2.5      // Set game speed to 2.5
> game.score          // Get current score
> game.score 100      // Set score to 100
> game.reset          // Execute reset action

Read-Only Values

Use forceReadOnly: true to display values that cannot be modified.

csharp
public class SystemInfo : MonoBehaviour
{
    [Adjust(name: "Platform", forceReadOnly: true)]
    public string Platform => Application.platform.ToString();

    [Adjust(name: "FPS", forceReadOnly: true)]
    public int CurrentFPS => Mathf.RoundToInt(1f / Time.deltaTime);

    [Adjust(name: "Memory (MB)", forceReadOnly: true)]
    public float MemoryUsage => UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / 1048576f;
}

Read-only values

Custom Width

Control element width with the width parameter (in pixels).

csharp
public class CustomWidths : MonoBehaviour
{
    [Adjust(width: 200)]
    public string ShortField = "Compact";

    [Adjust(width: 400)]
    public string LongField = "This field is wider";

    [AdjustAction(name: "Wide Button", width: 300)]
    public void WideButton() { }
}

Width

Context Attribute

[AdjustContext]

Optional attribute to configure context-specific settings.

Parameters:

  • icon (DebbyIcon): Icon displayed on the context tab
  • commandPrefix (string): Prefix for all commands in this context

Context with custom icon

Example:

csharp
using UnityEngine;
using Debology.Debby.Modules.Adjust.Attributes;
using Debology.Debby.Elements;

[AdjustContext(icon: DebbyIcon.Settings, commandPrefix: "player")]
public class PlayerController
{
    [Adjust(command: "health")]
    public int Health = 100;

    [AdjustAction(command: "reset")]
    public void ResetPlayer()
    {
        Health = 100;
        transform.position = Vector3.zero;
    }
}

With the commandPrefix set, Console commands would be:

> player.health 50
> player.reset

Complete Example

Here's a comprehensive example demonstrating all attribute features:

csharp
using System;
using System.Threading.Tasks;
using UnityEngine;
using Debology.Debby.Modules.Adjust.Attributes;
using Debology.Debby.Elements;

[AdjustContext(icon: DebbyIcon.Player, commandPrefix: "player")]
public class PlayerCharacter : MonoBehaviour
{
    // Basic stats with sliders
    [AdjustInt(
        name: "Health",
        category: "Stats",
        isSlider: true,
        min: 0,
        max: 100,
        priority: 100,
        command: "hp"
    )]
    private int _health = 100;

    [AdjustFloat(
        name: "Speed",
        category: "Stats",
        isSlider: true,
        min: 0f,
        max: 20f,
        pageSize: 0.5f,
        priority: 90,
        command: "speed"
    )]
    private float _speed = 5f;

    // Position tracking (read-only)
    [Adjust(
        name: "Position",
        category: "Transform",
        forceReadOnly: true,
        priority: 100
    )]
    public Vector3 Position => transform.position;

    // Grouped abilities
    [Adjust(
        name: "Can Jump",
        category: "Abilities",
        group: "Movement"
    )]
    public bool CanJump = true;

    [Adjust(
        name: "Can Dash",
        category: "Abilities",
        group: "Movement"
    )]
    public bool CanDash = false;

    [Adjust(
        name: "Can Fly",
        category: "Abilities",
        group: "Movement"
    )]
    public bool CanFly = false;

    // Actions
    [AdjustAction(
        name: "Heal to Full",
        category: "Actions",
        icon: DebbyIcon.Health,
        command: "heal"
    )]
    private void HealToFull()
    {
        _health = 100;
        Debug.Log("Player healed to full health!");
    }

    [AdjustAction(
        name: "Reset Position",
        category: "Actions",
        icon: DebbyIcon.Refresh,
        command: "resetpos"
    )]
    private void ResetPosition()
    {
        transform.position = Vector3.zero;
        Debug.Log("Player position reset!");
    }

    [AdjustAction(
        name: "Unlock All Abilities",
        category: "Actions",
        icon: DebbyIcon.Star
    )]
    private async Task UnlockAllAbilitiesAsync(Action<float> progress)
    {
        var abilities = new[] { "Jump", "Dash", "Fly" };

        for (int i = 0; i < abilities.Length; i++)
        {
            progress?.Invoke((i + 1) / (float)abilities.Length);
            await Task.Delay(500);
            Debug.Log($"Unlocked: {abilities[i]}");
        }

        CanJump = CanDash = CanFly = true;
        Debug.Log("All abilities unlocked!");
    }

    void Start()
    {
        // Register this context with Debby
        Debby.Adjust.RegisterContext(this, "Player", gameObject);
    }
}