Skip to content

Slides from my GIC lecture about creating tools in Unity

Notifications You must be signed in to change notification settings

patrykf-dev/tools-unity-gic-2024

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

On 27.11.2024 I had the pleasure of presenting my lecture Tool your way to inner peace in Unity development at the Game Industry Conference in Poznan. It was a great experience, just look at the photo 😃

In this repo I'm sharing the slides and all the code samples I used during my talk. If you have any questions, feel free to ask them by opening an issue.

Photo from my lecture

Description

I explored a general approach to tool development. Emphasis was placed on best practices, including good UX design principles. I showcased real-life examples, including tools from my solo projects and custom solutions built for a commercial project, StarHeroes.

Code samples

Custom editor buttons based on Unity toolbar extender:

[InitializeOnLoad]
public class YourEditorButtons
{
    static YourEditorButtons()
    {
        ToolbarExtender.RightToolbarGUI.Add(OnRightToolbarGUI);
    }

    private static void OnRightToolbarGUI()
    {
        GUILayout.FlexibleSpace();

        if (GUILayout.Button(new GUIContent("Setup scenes", "tooltip")))
        {
            ScenesPresetTool.LoadFullPreset();
            EditorSceneManager.OpenScene("Path/To/Scene.unity");
        }

        if (GUILayout.Button(new GUIContent("Reimport files", "tooltip")))
        {
            if (EditorWarningPopup.UserAccepted())
            {
                YourReimporter.ReimportFragileFiles();
            }
        }

        if (GUILayout.Button(new GUIContent("Tools windows", "tooltip")))
        {
            EditorToolsWindow.Init();
        }
    }
}

Custom editor window with seperate tabs:

public class EditorToolsWindow : OdinEditorWindow
{
    [SerializeField, HideLabel, TabGroup("WEAPONS")]
    private WeaponsToolTab _weaponsToolTab = new();

    [SerializeField, HideLabel, TabGroup("OTHER")]
    private OtherToolsTab _otherTab = new();

    public static void Init()
    {
        GetWindow<EditorToolsWindow>().Show(true);
    }
}

[Serializable]
public class WeaponsToolTab
{
    [Button(ButtonSizes.Large)]
    public void PrintWeaponStats() { }
}

[Serializable]
public class OtherToolsTab
{
    [Button(ButtonSizes.Large)]
    public void DoStuff() { }
}

Tool for changing aspect ratio of the game window in the editor:

public class GameWindowAspectRatioTool
{
    private const int OFFSET = 7;
    private const int USER_RATIOS_COUNT = 5;
    private static int _currentIndex = OFFSET;

    [MenuItem("Tools/Switch aspect ratio %["))]
    public static void SwitchAspectRatio()
    {
        var assembly = typeof(UnityEditor.Editor).Assembly;
        var gameView = assembly.GetType("UnityEditor.GameView");
        var instance = EditorWindow.GetWindow(gameView);
        var method = gameView.GetMethod("SizeSelectionCallback");
        method.Invoke(instance, new object[] { _currentIndex });

        if (++_currentIndex >= OFFSET + USER_RATIOS_COUNT)
        {
            _currentIndex = OFFSET;
        }
    }
}

Tool for reimporting assets without restarting the editor:

public void Reimport(string[] assetPaths)
{
    var importOptions = ImportAssetOptions.ForceUpdate | 
        ImportAssetOptions.ImportRecursive | 
        ImportAssetOptions.ForceSynchronousImport;

    AssetDatabase.StartAssetEditing();

    foreach (var path in assetPaths)
    {
        AssetDatabase.ImportAsset(path, importOptions);
    }

    AssetDatabase.StopAssetEditing();
    
    AssetDatabase.Refresh(importOptions);
}

Tool for loading and unloading packages:

public class PackagesTab
{
    private List<string> ADDITIONAL_PACKAGES = new()
    {
        "[email protected]",
        "[email protected]",
        "[email protected]",
        "[email protected]"
    };

    [Button(ButtonSizes.Large)]
    public void InstallAdditionalPackages()
    {
        foreach (var package in ADDITIONAL_PACKAGES)
        {
            UnityEditor.PackageManager.Client.Add(package);
        }
    }

    [Button(ButtonSizes.Large)]
    public void UninstallAdditionalPackages()
    {
        foreach (var package in ADDITIONAL_PACKAGES)
        {
            UnityEditor.PackageManager.Client.Remove(package);
        }
    }
}

Inspector extensions for better UX in a custom component:

public class OctreeGraphComponent : MonoBehaviour
{
    [FoldoutGroup("Gizmos")]
    public bool OctreeBounds;

    [FoldoutGroup("Gizmos")]
    private bool DrawBakeResult;

    [FoldoutGroup("Gizmos"), EnableIf(nameof(DrawBakeResult))]
    private int CubeSize;

    [FoldoutGroup("Gizmos"), EnableIf(nameof(DrawBakeResult))]
    [EnumToggleButtons]
    private GizmoDisplayMode DisplayMode;

    [FoldoutGroup("Gizmos"), EnableIf(nameof(DrawBakeResult))]
    private bool DrawJustOneCube = false;

    [FoldoutGroup("Gizmos"), EnableIf(nameof(DrawJustOneCube))]
    [InlineButton(nameof(NextCube), SdfIconType.ArrowRight, "")]
    [InlineButton(nameof(PreviousCube), SdfIconType.ArrowLeft, "")]
    private int CubeIndex;

    private void NextCube() => CubeIndex++;

    private void PreviousCube() => CubeIndex--;

    private void OnDrawGizmosSelected() => DrawGizmos();
}

About

Slides from my GIC lecture about creating tools in Unity

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published