diff --git a/CHANGELOG.md b/CHANGELOG.md index 548b31a..8f0773d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.5.0] - 2023/06/18 + +### Added + +- New `ExitApplication` script +- New `PauseApplication` script +- New editor mesh debugger: Window > Analysis > Mesh Debugger +- Behavior help URLs + +### Changed + +- Refactored the `Compare` class + - Changed the `Compare.Test` function to two distinct functions: `Compare.Equal` and `Compare.NotEqual` + - The generics are now applied to the functions instead of the class, i.e., `Compare.Equal` instead of `Compare.Equal` + ## [1.4.0] - 2022/05/20 ### Added diff --git a/Documentation~/articles/benchmarking.md b/Documentation~/articles/benchmarking.md index f499f89..0e7d71a 100644 --- a/Documentation~/articles/benchmarking.md +++ b/Documentation~/articles/benchmarking.md @@ -23,9 +23,9 @@ Benchmark.Run(1000, Foo, Bar, Baz); ## 🎏 Compare Equality -Alternatively, sometimes it is useful to test if the results of two functions are equal. The **Debug Tools** package comes with another static class [Compare](/api/Zigurous.Debug/Compare-1) to handle these tests. The class uses generics to know the type of value you are looking to compare, and it returns the percentage of results that are equal. +Sometimes it is useful to test if multiple functions return the same results. The **Debug Tools** package comes with another static class [Compare](/api/Zigurous.Debug/Compare-1) to handle these tests. The class uses generics to know the type of value you are looking to compare, and it returns the percentage of results that are equal (or not equal) for a given amount of iterations. ```csharp -Compare.Test(Foo, Bar, 1000); -Compare.Test(Foo, Bar, 1000); +Compare.Equal(Foo, Bar, 1000); +Compare.NotEqual(Foo, Bar, 1000); ``` diff --git a/Documentation~/articles/index.md b/Documentation~/articles/index.md index f22fb87..c532821 100644 --- a/Documentation~/articles/index.md +++ b/Documentation~/articles/index.md @@ -30,4 +30,6 @@ The **Debug Tools** package contains assets and scripts for debugging Unity proj #### 🎨 [Debug Shaders](/manual/shaders) +#### 🖇️ [Mesh Debugger](/manual/mesh-debugger) + #### ✏️ [Drawing](/manual/drawing) diff --git a/Documentation~/articles/mesh-debugger.md b/Documentation~/articles/mesh-debugger.md new file mode 100644 index 0000000..b8fe60d --- /dev/null +++ b/Documentation~/articles/mesh-debugger.md @@ -0,0 +1,11 @@ +--- +slug: "/manual/mesh-debugger" +--- + +# Mesh Debugger + +The **Debug Tools** package includes a custom editor window for debugging and visualizing mesh data. To open this debugger, use the menu `Window > Analysis > Mesh Debugger`. + +When a mesh is selected in the hierarchy while the window is open, a wireframe will be drawn around the current face of the mesh, and vertex and UV information will be shown in the editor. The window provides buttons to move to the next or previous face. + +![](../images/mesh-debugger.jpg) diff --git a/Documentation~/data/sidenav.json b/Documentation~/data/sidenav.json index 5346580..ba4471d 100644 --- a/Documentation~/data/sidenav.json +++ b/Documentation~/data/sidenav.json @@ -39,6 +39,10 @@ "name": "Debug Shaders", "path": "/manual/shaders" }, + { + "name": "Mesh Debugger", + "path": "/manual/mesh-debugger" + }, { "name": "Drawing", "path": "/manual/drawing" diff --git a/Documentation~/images/mesh-debugger.jpg b/Documentation~/images/mesh-debugger.jpg new file mode 100644 index 0000000..01a2cfc Binary files /dev/null and b/Documentation~/images/mesh-debugger.jpg differ diff --git a/Editor.meta b/Editor.meta new file mode 100644 index 0000000..692c999 --- /dev/null +++ b/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f3012dd2e8cb1d14a8f856af725af14d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/MeshDebugger.cs b/Editor/MeshDebugger.cs new file mode 100644 index 0000000..6cb9812 --- /dev/null +++ b/Editor/MeshDebugger.cs @@ -0,0 +1,175 @@ +using UnityEditor; +using UnityEngine; + +namespace Zigurous.Debug.Editor +{ + public sealed class MeshDebugger : EditorWindow + { + private Mesh currentMesh; + private MeshFilter currentMeshFilter; + private SkinnedMeshRenderer currentSkinnedMeshRenderer; + private int currentFace = 0, numFaces = 0, newFace = 0; + private GUIStyle labelStyle = null; + private Vector3 p1, p2, p3; + + [MenuItem("Window/Analysis/Mesh Debugger")] + public static void ShowWindow() + { + EditorWindow.GetWindow(typeof(MeshDebugger), true, "Mesh Debugger"); + } + + private void OnEnable() + { + SceneView.duringSceneGui -= OnSceneGUI; + SceneView.duringSceneGui += OnSceneGUI; + + OnSelectionChange(); + } + + private void OnDestroy() + { + SceneView.duringSceneGui -= OnSceneGUI; + } + + private void OnSelectionChange() + { + currentMesh = null; + currentSkinnedMeshRenderer = null; + numFaces = 0; + + if (Selection.activeGameObject) + { + currentMeshFilter = Selection.activeGameObject.GetComponentInChildren(); + + if (currentMeshFilter != null) + { + currentMesh = currentMeshFilter.sharedMesh; + numFaces = currentMesh.triangles.Length / 3; + } + else + { + currentSkinnedMeshRenderer = Selection.activeGameObject.GetComponentInChildren(); + + if (currentSkinnedMeshRenderer != null) + { + currentMesh = currentSkinnedMeshRenderer.sharedMesh; + numFaces = currentMesh.triangles.Length / 3; + } + } + } + + currentFace = 0; + newFace = currentFace; + + Repaint(); + } + + private void OnGUI() + { + if (currentMesh == null) + { + EditorGUILayout.LabelField("Current selection contains no mesh"); + return; + } + + EditorGUILayout.LabelField("Number of faces", numFaces.ToString()); + EditorGUILayout.LabelField("Current face", currentFace.ToString()); + + newFace = EditorGUILayout.IntField("Jump to face", currentFace); + + if (newFace != currentFace) + { + if (newFace >= 0 && newFace < numFaces) { + currentFace = newFace; + } + } + + EditorGUILayout.BeginHorizontal(); + + if (GUILayout.Button("Previous Face")) + { + currentFace = (currentFace - 1) % numFaces; + + if (currentFace < 0) { + currentFace = currentFace + numFaces; + } + } + + if (GUILayout.Button("Next Face")) { + currentFace = (currentFace + 1) % numFaces; + } + + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + int redIndex = currentMesh.triangles[currentFace * 3]; + int greenIndex = currentMesh.triangles[currentFace * 3 + 1]; + int blueIndex = currentMesh.triangles[currentFace * 3 + 2]; + + EditorGUILayout.LabelField("Red vertex", $"Index: {redIndex}, UV: ({currentMesh.uv[redIndex].x}, {currentMesh.uv[redIndex].y})"); + EditorGUILayout.LabelField("Green vertex", $"Index: {greenIndex}, UV: ({currentMesh.uv[greenIndex].x}, {currentMesh.uv[greenIndex].y})"); + EditorGUILayout.LabelField("Blue vertex", $"Index: {blueIndex}, UV: ({currentMesh.uv[blueIndex].x}, {currentMesh.uv[blueIndex].y})"); + } + + private void OnSceneGUI(SceneView sceneView) + { + if (currentMesh == null) { + return; + } + + int index1 = currentMesh.triangles[currentFace * 3]; + int index2 = currentMesh.triangles[currentFace * 3 + 1]; + int index3 = currentMesh.triangles[currentFace * 3 + 2]; + + if (currentMeshFilter != null) + { + p1 = currentMeshFilter.transform.TransformPoint(currentMesh.vertices[index1]); + p2 = currentMeshFilter.transform.TransformPoint(currentMesh.vertices[index2]); + p3 = currentMeshFilter.transform.TransformPoint(currentMesh.vertices[index3]); + } + else if (currentSkinnedMeshRenderer != null) + { + p1 = currentSkinnedMeshRenderer.transform.TransformPoint(currentMesh.vertices[index1]); + p2 = currentSkinnedMeshRenderer.transform.TransformPoint(currentMesh.vertices[index2]); + p3 = currentSkinnedMeshRenderer.transform.TransformPoint(currentMesh.vertices[index3]); + } + + Handles.color = Color.red; + Handles.SphereHandleCap(0, p1, Quaternion.identity, 0.2f * HandleUtility.GetHandleSize(p1), EventType.Repaint); + Handles.color = Color.green; + Handles.SphereHandleCap(0, p2, Quaternion.identity, 0.2f * HandleUtility.GetHandleSize(p2), EventType.Repaint); + Handles.color = Color.blue; + Handles.SphereHandleCap(0, p3, Quaternion.identity, 0.2f * HandleUtility.GetHandleSize(p3), EventType.Repaint); + + Handles.color = Color.white; + Handles.DrawDottedLine(p1, p2, 5f); + Handles.DrawDottedLine(p2, p3, 5f); + Handles.DrawDottedLine(p3, p1, 5f); + + if (labelStyle == null) + { + labelStyle = new GUIStyle(GUI.skin.label); + labelStyle.normal.textColor = Color.white; + labelStyle.fixedWidth = 40; + labelStyle.fixedHeight = 20; + labelStyle.alignment = TextAnchor.MiddleCenter; + labelStyle.fontSize = 12; + labelStyle.clipping = TextClipping.Overflow; + } + + Handles.Label(p1, index1.ToString(), labelStyle); + Handles.Label(p2, index2.ToString(), labelStyle); + Handles.Label(p3, index3.ToString(), labelStyle); + + sceneView.Repaint(); + } + + private void OnInspectorUpdate() + { + Repaint(); + } + + } + +} diff --git a/Editor/MeshDebugger.cs.meta b/Editor/MeshDebugger.cs.meta new file mode 100644 index 0000000..7ed08e2 --- /dev/null +++ b/Editor/MeshDebugger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08d9ecff8983ad744aa14c4afcc181a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Zigurous.Debug.Editor.asmdef b/Editor/Zigurous.Debug.Editor.asmdef new file mode 100644 index 0000000..d6458f9 --- /dev/null +++ b/Editor/Zigurous.Debug.Editor.asmdef @@ -0,0 +1,17 @@ +{ + "name": "Zigurous.Debug.Editor", + "references": [ + "GUID:0186cdaa7ccbaeb4f91d3907506784d7" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Editor/Zigurous.Debug.Editor.asmdef.meta b/Editor/Zigurous.Debug.Editor.asmdef.meta new file mode 100644 index 0000000..91b855d --- /dev/null +++ b/Editor/Zigurous.Debug.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 045545c2591da4e4099246d349849f66 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md index c1f5a56..283aee7 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ The **Debug Tools** package contains assets and scripts for debugging Unity proj - [Benchmarking](https://docs.zigurous.com/com.zigurous.debug/manual/benchmarking) - [Framerate Display](https://docs.zigurous.com/com.zigurous.debug/manual/framerate) - [Debug Shaders](https://docs.zigurous.com/com.zigurous.debug/manual/shaders) +- [Mesh Debugger](https://docs.zigurous.com/com.zigurous.debug/manual/mesh-debugger) +- [Drawing](https://docs.zigurous.com/com.zigurous.debug/manual/drawing) ## Installation diff --git a/Runtime/Compare.cs b/Runtime/Compare.cs index 5ca7a82..64b903a 100644 --- a/Runtime/Compare.cs +++ b/Runtime/Compare.cs @@ -3,13 +3,12 @@ namespace Zigurous.Debug { /// - /// Compares how many results are equal between two functions. + /// Compares the results of multiple functions for equality. /// - /// The type of value to compare. - public static class Compare where T: IEquatable + public static class Compare { /// - /// Tests the equality of the results of two functions with a given + /// Compares how many results of the two functions are equal for a given /// amount of iterations. /// /// The first function to execute. @@ -18,7 +17,8 @@ public static class Compare where T: IEquatable /// Logs the final comparison result. /// Logs the result of each iteration of the functions. /// The percentage of equal results. - public static float Test(Func foo, Func bar, int iterations, bool log = true, bool logIndividual = false) + public static float Equal(Func foo, Func bar, int iterations, bool log = true, bool logIndividual = false) + where T : IEquatable { #if UNITY_EDITOR || DEVELOPMENT_BUILD int amountEqual = 0; @@ -29,7 +29,10 @@ public static float Test(Func foo, Func bar, int iterations, bool log = tr T resultBar = bar(); bool equal = resultFoo.Equals(resultBar); - if (equal) amountEqual++; + + if (equal) { + amountEqual++; + } if (log && logIndividual) { UnityEngine.Debug.Log($"[Compare] {resultFoo.ToString()} vs {resultBar.ToString()} | {(equal ? "Equal" : "Not Equal")}"); @@ -48,6 +51,50 @@ public static float Test(Func foo, Func bar, int iterations, bool log = tr #endif } + /// + /// Compares how many results of the two functions are not equal for a + /// given amount of iterations. + /// + /// The first function to execute. + /// The second function to execute. + /// The amount of times each function is executed. + /// Logs the final comparison result. + /// Logs the result of each iteration of the functions. + /// The percentage of equal results. + public static float NotEqual(Func foo, Func bar, int iterations, bool log = true, bool logIndividual = false) + where T : IEquatable + { + #if UNITY_EDITOR || DEVELOPMENT_BUILD + int amountNotEqual = 0; + + for (int i = 0; i < iterations; i++) + { + T resultFoo = foo(); + T resultBar = bar(); + + bool equal = resultFoo.Equals(resultBar); + + if (!equal) { + amountNotEqual++; + } + + if (log && logIndividual) { + UnityEngine.Debug.Log($"[Compare] {resultFoo.ToString()} vs {resultBar.ToString()} | {(equal ? "Equal" : "Not Equal")}"); + } + } + + float percentNotEqual = (float)amountNotEqual / (float)iterations; + + if (log) { + UnityEngine.Debug.Log($"[Compare] {amountNotEqual.ToString()}/{iterations.ToString()} ({(percentNotEqual * 100f).ToString()}%) not equal results"); + } + + return percentNotEqual; + #else + return float.NaN; + #endif + } + } } diff --git a/Runtime/Draw.cs b/Runtime/Draw.cs index 665d00a..4a3c30c 100644 --- a/Runtime/Draw.cs +++ b/Runtime/Draw.cs @@ -18,6 +18,7 @@ private struct Box3D public Vector3 localFrontTopRight { get; private set; } public Vector3 localFrontBottomLeft { get; private set; } public Vector3 localFrontBottomRight { get; private set; } + public Vector3 localBackTopLeft => -localFrontBottomRight; public Vector3 localBackTopRight => -localFrontBottomLeft; public Vector3 localBackBottomLeft => -localFrontTopRight; @@ -27,6 +28,7 @@ private struct Box3D public Vector3 frontTopRight => localFrontTopRight + origin; public Vector3 frontBottomLeft => localFrontBottomLeft + origin; public Vector3 frontBottomRight => localFrontBottomRight + origin; + public Vector3 backTopLeft => localBackTopLeft + origin; public Vector3 backTopRight => localBackTopRight + origin; public Vector3 backBottomLeft => localBackBottomLeft + origin; diff --git a/Runtime/ExitApplication.cs b/Runtime/ExitApplication.cs new file mode 100644 index 0000000..4485f64 --- /dev/null +++ b/Runtime/ExitApplication.cs @@ -0,0 +1,98 @@ +using UnityEngine; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif + +namespace Zigurous.Debug +{ + /// + /// Quits the application via user input. + /// + [AddComponentMenu("Zigurous/Debug/Exit Application")] + [HelpURL("https://docs.zigurous.com/com.zigurous.debug/api/Zigurous.Debug/ExitApplication")] + public sealed class ExitApplication : MonoBehaviour + { + #if ENABLE_INPUT_SYSTEM + /// + /// The input action that quits the application. + /// + [Tooltip("The input action that quits the application.")] + [Header("Input System")] + public InputAction quitInput = new InputAction("ExitApplication", InputActionType.Button, "/escape"); + #endif + + #if ENABLE_LEGACY_INPUT_MANAGER + /// + /// The keycode that quits the application. + /// + [Tooltip("The keycode that quits the application.")] + [Header("Legacy Input Manager")] + public KeyCode quitKey = KeyCode.Escape; + + /// + /// The optional modifier key to be held down to quit the application. + /// + [Tooltip("The optional modifier key to be held down to quit the application.")] + public KeyCode quitKeyModifier = KeyCode.None; + #endif + + #if ENABLE_INPUT_SYSTEM + private void Awake() + { + quitInput.performed += OnQuit; + } + + private void OnDestroy() + { + quitInput.Dispose(); + } + + private void OnEnable() + { + quitInput.Enable(); + } + + private void OnDisable() + { + quitInput.Disable(); + } + + private void OnQuit(InputAction.CallbackContext context) + { + if (context.performed) { + Quit(); + } + } + #endif + + #if ENABLE_LEGACY_INPUT_MANAGER + private void Update() + { + if (Input.GetKeyDown(quitKey)) + { + if (quitKeyModifier == KeyCode.None || Input.GetKey(quitKeyModifier)) { + Quit(); + } + } + } + #endif + + /// + /// Quits the application, or exits playmode if running in the editor. + /// + public void Quit() + { + #if UNITY_EDITOR + if (Application.isEditor) + { + UnityEditor.EditorApplication.ExitPlaymode(); + return; + } + #endif + + Application.Quit(); + } + + } + +} diff --git a/Runtime/ExitApplication.cs.meta b/Runtime/ExitApplication.cs.meta new file mode 100644 index 0000000..c4b89cb --- /dev/null +++ b/Runtime/ExitApplication.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ab1552eef99574459510537a5d67ee3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/FPSDisplay.cs b/Runtime/FPSDisplay.cs index 759d1fa..7222a2b 100644 --- a/Runtime/FPSDisplay.cs +++ b/Runtime/FPSDisplay.cs @@ -8,6 +8,7 @@ namespace Zigurous.Debug /// Displays the framerate of the application in realtime. /// [AddComponentMenu("Zigurous/Debug/FPS Display")] + [HelpURL("https://docs.zigurous.com/com.zigurous.debug/api/Zigurous.Debug/FPSDisplay")] public class FPSDisplay : MonoBehaviour { /// diff --git a/Runtime/PauseApplication.cs b/Runtime/PauseApplication.cs new file mode 100644 index 0000000..41c35e8 --- /dev/null +++ b/Runtime/PauseApplication.cs @@ -0,0 +1,130 @@ +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif + +namespace Zigurous.Debug +{ + /// + /// Pauses the application via user input. + /// + [AddComponentMenu("Zigurous/Debug/Pause Application")] + [HelpURL("https://docs.zigurous.com/com.zigurous.debug/api/Zigurous.Debug/PauseApplication")] + public sealed class PauseApplication : MonoBehaviour + { + #if ENABLE_INPUT_SYSTEM + /// + /// The input action that pauses the application. + /// + [Tooltip("The input action that pauses the application.")] + [Header("Input System")] + public InputAction pauseInput = new InputAction("PauseApplication", InputActionType.Button, "/pause"); + #endif + + #if ENABLE_LEGACY_INPUT_MANAGER + /// + /// The keycode that pauses the application. + /// + [Tooltip("The keycode that pauses the application.")] + [Header("Legacy Input Manager")] + public KeyCode pauseKey = KeyCode.Break; + + /// + /// The optional modifier key to be held down to pause the application. + /// + [Tooltip("The optional modifier key to be held down to pause the application.")] + public KeyCode pauseKeyModifier = KeyCode.None; + #endif + + /// + /// Whether the application is currently paused or not (Read only). + /// + #if UNITY_EDITOR + public bool paused => EditorApplication.isPaused; + #else + public bool paused { get; private set; } + #endif + + #if ENABLE_INPUT_SYSTEM + private void Awake() + { + pauseInput.performed += OnPause; + } + + private void OnDestroy() + { + pauseInput.Dispose(); + } + + private void OnEnable() + { + pauseInput.Enable(); + } + + private void OnDisable() + { + pauseInput.Disable(); + } + + private void OnPause(InputAction.CallbackContext context) + { + if (context.performed) + { + if (paused) { + Resume(); + } else { + Pause(); + } + } + } + #endif + + #if ENABLE_LEGACY_INPUT_MANAGER + private void Update() + { + if (Input.GetKeyDown(pauseKey)) + { + if (pauseKeyModifier == KeyCode.None || Input.GetKey(pauseKeyModifier)) + { + if (paused) { + Resume(); + } else { + Pause(); + } + } + } + } + #endif + + /// + /// Pauses the application. + /// + public void Pause() + { + #if UNITY_EDITOR + EditorApplication.isPaused = true; + #else + paused = true; + Time.timeScale = 0f; + #endif + } + + /// + /// Resumes the application. + /// + public void Resume() + { + #if UNITY_EDITOR + EditorApplication.isPaused = false; + #else + paused = false; + Time.timeScale = 1f; + #endif + } + + } + +} diff --git a/Runtime/PauseApplication.cs.meta b/Runtime/PauseApplication.cs.meta new file mode 100644 index 0000000..c459b66 --- /dev/null +++ b/Runtime/PauseApplication.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 92cd4baf56dcd7e4685a19dd2431a35f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Zigurous.Debug.asmdef b/Runtime/Zigurous.Debug.asmdef index 81fab9e..b6f770e 100644 --- a/Runtime/Zigurous.Debug.asmdef +++ b/Runtime/Zigurous.Debug.asmdef @@ -1,6 +1,8 @@ { "name": "Zigurous.Debug", - "references": [], + "references": [ + "GUID:75469ad4d38634e559750d17036d5f7c" + ], "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, @@ -10,4 +12,4 @@ "defineConstraints": [], "versionDefines": [], "noEngineReferences": false -} +} \ No newline at end of file diff --git a/package.json b/package.json index 43622e1..28942a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.zigurous.debug", - "version": "1.4.0", + "version": "1.5.0", "displayName": "Debug Tools", "description": "The Debug Tools package contains assets and scripts for debugging Unity projects. Included in the package are scripts for enhanced console logging, benchmarking, displaying framerate, and more. The package also comes with shaders to visualize different vertex data.", "unity": "2019.4", @@ -8,6 +8,9 @@ "documentationUrl": "https://docs.zigurous.com/com.zigurous.debug", "changelogUrl": "https://docs.zigurous.com/com.zigurous.debug/changelog", "licensesUrl": "https://docs.zigurous.com/com.zigurous.debug/license", + "dependencies": { + "com.unity.inputsystem": "1.2.0" + }, "keywords": [ "debug", "debugging",