Skip to content

Latest commit

 

History

History
463 lines (366 loc) · 19.2 KB

File metadata and controls

463 lines (366 loc) · 19.2 KB

DebugPanel_GithubBanner

UDebug Panel is a lightweight and versatile ingame debug panel for Unity with C#. It can be incredible useful to be able to modify gameplay parameters while on the target device. This asset simplifies the process of creating a panel with debut options in your Unity projects, allowing you to focus on what matters: gameplay.

A debug panel, is a user interface that provides developers with tools and information to aid in debugging and profiling during the development of a software application or game.

This asset provides a suit of premade elements (buttons, int selector, float selector, enum selection, etc), while allowing for the creation of new ones, with ease.

If you find any issue, please report it here.

TRY THE WEB DEMO | RATE ASSET

DebugPanel_MainScreenshot

📋 Table of Contents

  1. Features
  2. Installation
  3. After Installing
  4. Getting Started
  5. Sections
  6. Automatic Debug Actions
  7. Manual Debug Actions
  8. Custom Debug Actions
  9. Build Stripping
  10. Rate Asset

🍰 Features

  • Simple API: Unity Debug Panel provides an intuitive and easy-to-use API with C#.

    UDebugPanel.Show();
    UDebugPanel.Hide();
    
    IDebugActionsSection section = UDebugPanel.AddSection("Section name");
    section.AddButton("Button name", () => Debug.Log("Button click"));
  • Adaptative: The different widgets support and adapt to different screen aspect ratios, making it a good fit for both, desktop and mobile.

    DebugPanel_Orientation

  • Smart: You can automatically generate a debug options section using a class. Using reflection, changes that occur on the debug panel will affect the class instance.

    DebugPanel_AutomaticWidgetCreation

  • Organization: Organize your options using sections.

    DebugPanel_Organization

  • Fuzzy search: Quickly find the options you were looking for with the search bar!

    DebugPanel_FuzzySearch

  • Lightweight: While your game is running, the panel does not exist at all until you want to show it. When is hidden again, the panel is completely destroyed, so it does not impact the performance of your game.

📦 Installation

Download and import from the Unity Asset Store. You can move the root folder anywhere you want in your project. The package has the following dependencies:

Note

If you are using Assembly Definitions, you may need to include the DebugPanel.Runtime assembly to your assemblies.

Note

Works with both New and Old Input Systems.

✔️ After Installing

To quickly check if everything has been setup properly, you can go to DebugPanel/Examples/Scenes/ and open any of the example scenes. When you run any of those scenes, a simple functionality example should play.

📚 Getting Started

Showing / Hiding

  • For showing the panel, you just need to call the Show method. The internal logic will take care of everything else.
    UDebugPanel.Show();
  • For hiding the panel, just call the Hide method.
    UDebugPanel.Hide();
  • For convenience, you can also toggle the panel. Just call the Toggle method.
    UDebugPanel.Toggle();

Automatic Toggle

We already provide some handy automatic input toggles for you.

UDebugPanel.SetupToggleInput();

By calling UDebugPanel.SetupToggleInput(), you will automatically setup toggle for:

  • Keyboard F1 key.
  • Middle mouse button.
  • Triple finger tap on screen.

You can modify this behaviour using the method parameters.

Controller navigation

The panel has support for navigation with a controller or keyboard. You can enable controller navigation by calling:

UDebugPanel.SetControllerSupport(true);

Note

Must be called before showing the panel, to take effect.

DebugPanel_ControllerInput

📂Sections

Debug actions are divided within different sections. These sections allow you to better organize your actions. You cannot create a debug action outside of a section.

  • Creating a new section is very simple, you just need to call AddSection and provide a section name:
    IDebugActionsSection section = UDebugPanel.AddSection("Section name");
  • Removing a section is equally as simple. Just call RemoveSection, and provide the section you want to remove.
    UDebugPanel.RemoveSection(section);

Note

You don't need to show the panel before creating actions/sections.

Note

You can see this functionality on the example DebugPanel.Sections.

🤖 Automatic Debug Actions

This asset has the ability of scanning for properties and methods in C# classes, to automatically create the adecuate widgets. By default, only public properties are used for creating debug actions, the rest are ignored (unless specified with the attribute ShowAsDebugAction).

Adding Objects

One of such classes may look like this:

class Options
{
    [NumberStep(5)]
    public int IntProperty { get; set; }
            
    [NumberStep(2.5f)] 
    public float FloatProperty { get; set; }
            
    [NumberRange(-10, 10)] 
    public long LongProperty { get; set; }
            
    [DisplayName("Bool Property Custom Display Name")]
    public bool BoolProperty { get; set; }
    public EnumProperty EnumProperty { get; set; }
            
    public string StringValue { get; } = "Text";
    public int IntValue => IntProperty;
    public float FloatValue => FloatProperty;
    public long LongValue => LongProperty;
    public bool BoolValue => BoolProperty;

    [DontShowAsDebugAction]
    public EnumProperty EnumValue => EnumProperty;
            
    [ShowAsDebugAction]
    EnumProperty PrivateEnumValue { get; set; }
            
    public void Method()
    {
        Debug.Log("Calling Method");
    }

    [ShowAsDebugAction]
    void PrivateMethod()
    {
         Debug.Log("Calling Private Method");
    }
            
    [Category("Another Section")]
    public int IntProperty2 { get; set; }
            
    [Category("Another Section")]
    public int FloatProperty2 { get; set; }
}

Then we add the class like this:

UDebugPanel.AddOptionsObject(new ExampleOptionsObject());

And we will get debug options like this:

Reflection

Adding Static Objects

You can also use static classes to define your debug actions, by using the attribute [DebugActionsObject]. Then, call UDebugPanel.AddGlobalOptionsObject() once to automatically add all the static classes with the attribute as debug actions.

[DebugActionsObject]
static class OptionsAutomatic
{
    public static int IntProperty { get; set; }
            
    [NumberStep(2.5f)] 
    public static float FloatProperty { get; set; }
            
    [NumberRange(-10, 10)] 
    public static long LongProperty { get; set; }
}

Then we add all the classes like this:

UDebugPanel.AddGlobalOptionsObjects();

Reflection Attributes

We provide several attributes to add felxibility to the automatic debug actions creation:

  • DisplayName: Sets a custom name for your debug action.
  • Category: Sets the section where the debug action will be created.
  • NumberStep(number): for number properties (int, float, long), allows to set the step used when clicking on the widget left or right arrows.
  • NumberRange(numberMin, numberMax): for number properties (int, float, long), allows to set a minimum and maximum value on the widget.
  • ShowAsDebugAction: Cretes the debug action when the property is private.
  • DontShowAsDebugAction: Does not create the debug action when the property is public.

Note

You can see this functionality on the example DebugPanel.Reflection.

▶️ Manual Debug Actions

This is the most important part of this asset, the debug actions (or widgets). Once you have a section, you add debug actions to it:

Info:

  • Info: a static string that cannot be changed one submited.

    section.AddInfo("Some info that never changes");

    image

  • Dynamic Info: a getter for a string that it's updated every frame.

    section.AddInfoDynamic(() => "Some info that can change");

    image

Buttons:

  • Button: a simple button with a name.
    section.AddButton("Button name", () => Debug.Log("Pressed"));
    image

Toggle:

  • Toggle: a simple bool toggle with a name. Requests a setter and a getter for the value.
    bool someBool = false;
    section.AddToggle("Toggle name", val => someBool = val, () => someBool);
    image

Number selectors:

  • Int: an int selector with a name. Requests a setter and a getter for the value.

    int someInt = 0;
    section.AddIntSelector("Int name", val => someInt = val, () => someInt);

    image

  • Float: a float selector with a name. Requests a setter and a getter for the value.

    float someFloat = 0f;
    section.AddFloatSelector("Float name", val => someFloat = val, () => someFloat);

    image

  • Long: a long selector with a name. Requests a setter and a getter for the value.

    long someLong = 0;
    section.AddLongSelector("Long name", val => someLong = val, () => someLong);

    image

Advanced Buttons:

  • Button large info: a button that opens a popup which can show information as text.

    section.AddButtonLargeInfo("Button name", () => "This is some large info");

    image image

  • Button string input: a button that opens a popup where you can set a string value.

    section.AddButtonStringInput("Button name", () => "Empty", v => Debug.Log($"Selected {v}");

    image image

  • Button string selector: a button that opens a popup where you can select a string value. The current selected value is stored and shown on the button text.

    string _stringValue= "Empty";
    section.AddButtonStringSelector("Button name", () => _stringValue, v => _stringValue = v);

    image image

  • Button list input: a button that opens a popup where you can select an item from a list of items.

    List<string> _elementsList = new() {"Element1", "Element2", "Element3"};
    section.AddButtonListInput("Button name", () => _elementsList, i => Debug.Log($"Selected {_elementsList[i]}"));

    image image

  • Button list selector: a button that opens a popup where you can select an item from a list of items. The current selected value is stored and shown on the button text.

    List<string> _elementsList = new() {"Element1", "Element2", "Element3"};
    section.AddButtonListSelector("Button name", () => _elementsList, i => Debug.Log($"Selected {_elementsList[i]}"));

    image image

  • Button enum selector: a button that opens a popup where you can select the value of an enum. The current selected value is stored and shown on the button text.

    TestEnum _elementEnumSelected = TestEnum.Element1;
    section.AddButtonEnumSelector("Button name",  i => _elementEnumSelected = i, () => _elementEnumSelected);

    image image

Nested Containers:

  • Nested conatiner: a button that opens a popup which can have more debug actions.
    section.AddButtonActionsContainer("Actions", s =>
    {
        s.AddButton("Another Button 1", () => Debug.Log("Button pressed"));
        s.AddButton("Another Button 2", () => Debug.Log("Button pressed"));
        s.AddButton("Another Button 3", () => Debug.Log("Button pressed"));
    });
    image image

Note

You can see debug actions functionality on the example DebugPanel.Widgets.

🆕 Creating More Debug Actions

Some times, your game may have specific needs that cannot be properly met by the default provided widgets. That's why you can create your own. We are going to use the Info action as an example.

  1. The first thing you need to do is create a new class and inherit from DebugAction. This interface will force you to implement DebugActionWidget InitWidget(DebugActionWidget viewInstance) method, which is responsable for setting the values from the action, to the widget Ui. We will not implement it for now. We should first set the information that the action will hold. In this case it's a string for the info.

    public sealed class InfoDebugAction : DebugAction
    {
        readonly string _info
    
        public InfoDebugAction(string info)
        {
            _info = info;
            ActionName = info; // ActionName is used for search box functionality
        }
    
        public override void InitWidget(DebugActionWidget viewInstance)
        {
            throw new NotImplementedException();
        }
    }
  2. Next, we need a new DebugActionWidget, which will be the actual GameObject placed on the Ui. Since the widget is made of a label, we will add a reference to it. We will also add an Init method to set the label value.

    public sealed class InfoDebugActionWidget : DebugActionWidget
    {
        public TextMeshProUGUI Label;
    
        public void Init(string info)
        {
            Label!.text = info;
        }
    }
  3. Going back to the InfoDebugAction class, we need to implement InitWidget. The widget itself will be automatically instantiated internally. We need to init it here.

    public sealed class IntDebugAction : IDebugAction
    {    
        readonly string _info
    
        public InfoDebugAction(string info)
        {
            _info = info;
            ActionName = info;
        }
    
        public override void InitWidget(DebugActionWidget viewInstance)
        {
            InfoDebugActionWidget widget = (InfoDebugActionWidget)viewInstance;
            widget.Init(ActionName);
        }
    }
  4. For being able to use this new action on a section, just add an extension method that does this:

    public static IDebugAction AddInfo(this IDebugActionsSection section, string info)
    {
        InfoDebugAction debugAction = new InfoDebugAction(info);
        section.Add(debugAction);
        return debugAction;
    }
  5. Cool! Finally, befor using the action, you just need to let the Debug Panel know that it should link the new debug action with the new widget prefab.

     UDebugPanel.RegisterWidgetPrefab<InfoDebugAction>(InfoDebugActionWidgetPrefab);
  6. That's it. Everything is set up for using your new debug action.

Note

You can see an example of a custom widget at the example scene DebugPanel.CustomWidgets.

Creating more popups

Note

You can see an example of how to create custom popups on DebugPanel.CustomPopups.

🧹 Build Stripping

When building your game for production, you may want to remove the Resources/UDebugPanel.prefab, since it won't be used. By default, Resources files are included in the build. To avoid that, we provide some functionality that can be hooked up to your build process.

  • UDebugPanelBuildUtils.StripFromBuild();: hides the prefab from the Unity build system.
  • UDebugPanelBuildUtils.UnstripFromBuild();: makes the prefab visible again for Unity.

For production builds, these two methods can be used on a Build hook script, like this:

public class MyBuildHooks : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
    // Called before the build starts
    public void OnPreprocessBuild(BuildReport report)
    {
        UDebugPanelBuildUtils.StripFromBuild();
    }

    // Called after the build finishes
    public void OnPostprocessBuild(BuildReport report)
    {
        UDebugPanelBuildUtils.UnstripFromBuild();
    }

    // Determines the order if multiple preprocessors exist
    public int callbackOrder => 0;
}

This ensures that the prefab is not on the build, but its ready again when the build finishes!

Note

You may need to include the DebugPanel.Editor Assembly to your assemblies.

If you found the documentation helpful and are enjoying our asset, we'd truly appreciate it if you could leave a positive rating on the Asset Store — it really helps us out ❤️.