├── .gitattributes ├── .github └── workflows │ └── generate-docs.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Documentation~ ├── articles │ ├── benchmarking.md │ ├── drawing.md │ ├── framerate.md │ ├── index.md │ ├── installation.md │ ├── logging.md │ ├── mesh-debugger.md │ └── shaders.md ├── data │ ├── header.json │ └── sidenav.json └── images │ └── mesh-debugger.jpg ├── Editor.meta ├── Editor ├── MeshDebugger.cs ├── MeshDebugger.cs.meta ├── Zigurous.Debug.Editor.asmdef └── Zigurous.Debug.Editor.asmdef.meta ├── LICENSE.md ├── LICENSE.md.meta ├── Materials.meta ├── Materials ├── Debug_Bitangents.mat ├── Debug_Bitangents.mat.meta ├── Debug_Normals.mat ├── Debug_Normals.mat.meta ├── Debug_Tangents.mat ├── Debug_Tangents.mat.meta ├── Debug_UV1.mat ├── Debug_UV1.mat.meta ├── Debug_UV2.mat ├── Debug_UV2.mat.meta ├── Debug_VertexColor.mat └── Debug_VertexColor.mat.meta ├── Prefabs.meta ├── Prefabs ├── FPSDisplay.prefab └── FPSDisplay.prefab.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── Benchmark.cs ├── Benchmark.cs.meta ├── Compare.cs ├── Compare.cs.meta ├── Draw.cs ├── Draw.cs.meta ├── ExitApplication.cs ├── ExitApplication.cs.meta ├── FPSDisplay.cs ├── FPSDisplay.cs.meta ├── Log.cs ├── Log.cs.meta ├── PauseApplication.cs ├── PauseApplication.cs.meta ├── Zigurous.Debug.asmdef └── Zigurous.Debug.asmdef.meta ├── Shaders.meta ├── Shaders ├── Bitangents.shader ├── Bitangents.shader.meta ├── Normals.shader ├── Normals.shader.meta ├── Tangents.shader ├── Tangents.shader.meta ├── UV1.shader ├── UV1.shader.meta ├── UV2.shader ├── UV2.shader.meta ├── VertexColor.shader └── VertexColor.shader.meta ├── package.json └── package.json.meta /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-detectable=false 2 | *.css linguist-detectable=false 3 | *.js linguist-detectable=false 4 | -------------------------------------------------------------------------------- /.github/workflows/generate-docs.yml: -------------------------------------------------------------------------------- 1 | name: Generate Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | generate: 15 | name: Docs 16 | uses: zigurous/docs/.github/workflows/unity-package.yml@main 17 | with: 18 | package_title: "Debug Tools" 19 | package_base_path: com.zigurous.debug 20 | package_workflow: generate-docs.yml 21 | package_artifact: docs 22 | secrets: 23 | token: ${{ secrets.DOCS_TOKEN }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /**/obj/ 2 | /**/obj.meta 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | ./docs~/ 2 | .github/ 3 | .gitattributes 4 | .gitignore 5 | .gitmodules 6 | /**/obj/ 7 | /**/obj.meta 8 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ 2 | @zigurous:registry=https://npm.pkg.github.com 3 | //npm.pkg.github.com/:_authToken= 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [1.5.0] - 2023/06/18 9 | 10 | ### Added 11 | 12 | - New `ExitApplication` script 13 | - New `PauseApplication` script 14 | - New editor mesh debugger: `Window > Analysis > Mesh Debugger` 15 | - Behavior help URLs 16 | 17 | ### Changed 18 | 19 | - Refactored the `Compare` class 20 | - Changed the `Compare.Test` function to two distinct functions: `Compare.Equal` and `Compare.NotEqual` 21 | - The generics are now applied to the functions instead of the class, i.e., `Compare.Equal` instead of `Compare.Equal` 22 | 23 | ## [1.4.0] - 2022/05/20 24 | 25 | ### Added 26 | 27 | - New `Draw` class with additional methods compared to Unity's debug draw functions 28 | - Added additional compiler directives to compile-out code in release builds 29 | - Added `Reset` function to `FPSDisplay` to automatically set text component reference 30 | 31 | ### Changed 32 | 33 | - Changed `FPSDisplay.displayFormat` setter from protected to public so custom formats can be set without needing to extend the class 34 | - Changed `FPSDisplay.nextUpdate` from public to private (only needed internally) 35 | - Changed default `FPSDisplay.refreshRate` from 1s to 0.125s 36 | 37 | ## [1.3.0] - 2021/11/06 38 | 39 | ### Added 40 | 41 | - New debug materials to visualize various vertex data 42 | - Bitangets 43 | - Normals 44 | - Tangents 45 | - UV1 46 | - UV2 47 | - VertexColor 48 | 49 | ## [1.2.0] - 2021/07/10 50 | 51 | ### Added 52 | 53 | - Static class `Benchmark` to replace `ComparePerformance` 54 | - Static class `Compare` to replace `CompareResults` 55 | - Overloads for logging messages with custom prefixes 56 | - New `Log.Assertion` methods 57 | 58 | ### Removed 59 | 60 | - MonoBehaviour `ComparePerformance` 61 | - MonoBehaviour `CompareResults` 62 | 63 | ### Changed 64 | 65 | - Package description 66 | - Documentation comments 67 | - [FPSDisplay]: The `SetDisplayFormat` method can now be overriden 68 | 69 | ## [1.1.0] - 2021/06/28 70 | 71 | ### Changed 72 | 73 | - Improved FPS display formatting 74 | - Namespace changed from DebugTools to Debug 75 | - [AddComponentMenu] added to FPSDisplay 76 | 77 | ## [1.0.4] - 2021/04/13 78 | 79 | ### Changed 80 | 81 | - Package description 82 | 83 | ### Fixed 84 | 85 | - Moved non-compiled assets outside of the Runtime directory 86 | 87 | ## [1.0.3] - 2021/03/26 88 | 89 | ### Changed 90 | 91 | - Renamed "Debug" class to "Log" to prevent naming conflict with Unity 92 | 93 | ## [1.0.2] - 2021/03/21 94 | 95 | ### Changed 96 | 97 | - Updated package metadata 98 | 99 | ## [1.0.1] - 2021/03/07 100 | 101 | ### Changed 102 | 103 | - Updated package metadata 104 | 105 | ## [1.0.0] - 2021/02/27 106 | 107 | ### Added 108 | 109 | - Enhanced console logging 110 | - Performance and equality testing 111 | - FPS Display 112 | - Shaders 113 | - Bitangets 114 | - Normals 115 | - Tangents 116 | - UV1 117 | - UV2 118 | - VertexColor 119 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c0f37102c93dbe4a8a14c5952a3ba22 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/articles/benchmarking.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual/benchmarking" 3 | --- 4 | 5 | # Benchmarking 6 | 7 | The **Debug Tools** package comes with a static class to perform function benchmark tests. The [Benchmark](/api/Zigurous.Debug/Benchmark) class can be used to measure the execution time of a single function or the comparison between multiple functions. 8 | 9 | ```csharp 10 | // Measures the execution time of Foo over 1000 iterations. 11 | float time = Benchmark.Measure(Foo, 1000); 12 | 13 | // Compares the difference in execution time between Foo and Bar over 1000 iterations. 14 | float difference = Benchmark.Compare(Foo, Bar, 1000); 15 | 16 | // Performs a benchmark the executes each function 1000 times. 17 | // The time of each function will be logged individually. 18 | // You can pass as many functions as you want. 19 | Benchmark.Run(1000, Foo, Bar, Baz); 20 | ``` 21 | 22 |
23 | 24 | ## 🎏 Compare Equality 25 | 26 | 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. 27 | 28 | ```csharp 29 | Compare.Equal(Foo, Bar, 1000); 30 | Compare.NotEqual(Foo, Bar, 1000); 31 | ``` 32 | -------------------------------------------------------------------------------- /Documentation~/articles/drawing.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual/drawing" 3 | --- 4 | 5 | # Drawing 6 | 7 | The **Debug Tools** package includes additional functions for drawing debug information similar to Unity's `Debug.DrawLine` and `Debug.DrawRay` functions. Specifically, the package provides functions to draw wireframe boxes. 8 | 9 |
10 | 11 | ## 📦 Box 12 | 13 | Draws a wireframe box at a given position, scale, and rotation. This can be used to visualize the bounding box of an object. 14 | 15 | ```csharp 16 | Draw.Box(transform.position, transform.localScale, transform.rotation, Color.green); 17 | ``` 18 | 19 |
20 | 21 | ## 📤 BoxCast 22 | 23 | Draws a wireframe box using the same parameters as `Physics.BoxCast`. This can be used to visualize a boxcast from one point to another. 24 | 25 | ```csharp 26 | Draw.BoxCast(transform.position, transform.localScale / 2f, transform.forward, transform.rotation, 10f, Color.blue); 27 | ``` 28 | -------------------------------------------------------------------------------- /Documentation~/articles/framerate.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual/framerate" 3 | --- 4 | 5 | # Framerate Display 6 | 7 | The **Debug Tools** package comes with a script and prefab to display the framerate of the game in realtime. This can be useful if you need to know the framerate outside of the Unity editor. 8 | 9 |
10 | 11 | ## 📟 Prefab 12 | 13 | Simply drag the `FPSDisplay.prefab` into your scene, and you are done! It already comes pre-formatted and is contained within its own UI canvas. You can further customize the display to your liking. By default it is displayed in the top-right corner with zero decimal digits. 14 | 15 |
16 | 17 | ## 📺 Custom 18 | 19 | You can also create your own display if you prefer and add the [FPSDisplay](/api/Zigurous.Debug/FPSDisplay) script to it manually. The script allows you to customize the number of decimal digits to display and how often you want it to refresh. At the minimum, you must pass a reference to a UI Text component that displays the framerate. 20 | -------------------------------------------------------------------------------- /Documentation~/articles/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual" 3 | --- 4 | 5 | # Debug Tools 6 | 7 | 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. 8 | 9 |
10 | 11 | ## Overview 12 | 13 | #### ⚙️ [Installation](/installation) 14 | 15 | #### 🧰 [Scripting API](/api/Zigurous.Debug) 16 | 17 | #### 📋 [Changelog](/changelog) 18 | 19 | #### ⚖️ [License](/license) 20 | 21 |
22 | 23 | ## Reference 24 | 25 | #### 📝 [Logging](/manual/logging) 26 | 27 | #### ⏱️ [Benchmarking](/manual/benchmarking) 28 | 29 | #### ⏰ [Framerate Display](/manual/framerate) 30 | 31 | #### 🎨 [Debug Shaders](/manual/shaders) 32 | 33 | #### 🖇️ [Mesh Debugger](/manual/mesh-debugger) 34 | 35 | #### ✏️ [Drawing](/manual/drawing) 36 | -------------------------------------------------------------------------------- /Documentation~/articles/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/installation" 3 | --- 4 | 5 | # Installation 6 | 7 | Use the Unity [Package Manager](https://docs.unity3d.com/Manual/upm-ui.html) to install the **Debug Tools** package. 8 | 9 | 1. Open the Package Manager in `Window > Package Manager` 10 | 2. Click the add (`+`) button in the status bar 11 | 3. Select `Add package from git URL` from the add menu 12 | 4. Enter the following Git URL in the text box and click Add: 13 | 14 | ```http 15 | https://github.com/zigurous/unity-debug-tools.git 16 | ``` 17 | 18 |
19 | 20 | ## 🏷️ Namespace 21 | 22 | Import the package namespace in each script or file you want to use it. You may need to regenerate project files/assemblies first. 23 | 24 | ```csharp 25 | using Zigurous.Debug; 26 | ``` 27 | 28 |
29 | 30 | ## 💻 Source Code 31 | 32 | The source code for the **Debug Tools** package is in the following repository: 33 | 34 | - https://github.com/zigurous/unity-debug-tools 35 | -------------------------------------------------------------------------------- /Documentation~/articles/logging.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual/logging" 3 | --- 4 | 5 | # Logging 6 | 7 | The **Debug Tools** package provides a static class with more robust logging functions compared to `UnityEngine.Debug`. The [Log](/api/Zigurous.Debug/Log) class can log messages, warnings, and errors to the console. One primary difference is you can log multiple messages through a single function call. 8 | 9 | ```csharp 10 | Log.Message(a, b, c); 11 | Log.Warning(a, b, c); 12 | Log.Error(a, b, c); 13 | ``` 14 | 15 | You can also provide a custom prefix to display for the message as well as a given context. 16 | 17 | ```csharp 18 | Log.Message(foo, "[Zigurous]:"); 19 | Log.Warning(foo, "[Zigurous]:"); 20 | Log.Error(foo, "[Zigurous]:"); 21 | 22 | Log.Message(foo, context); 23 | Log.Warning(foo, context); 24 | Log.Error(foo, context); 25 | ``` 26 | 27 |
28 | 29 | ## 📚 Customization 30 | 31 | You can customize the delimiter used when logging multiple messages, and you can set a global prefix that is displayed before each message in order to separate them from others. 32 | 33 | ```csharp 34 | Log.delimiter = ","; 35 | Log.prefix = "[Zigurous]:"; 36 | ``` 37 | 38 | The class also handles null checking to not cause any errors if you log an invalid object. You can even set the string that is displayed when a null reference is logged. 39 | 40 | ```csharp 41 | Log.nullReference = "Null"; 42 | ``` 43 | -------------------------------------------------------------------------------- /Documentation~/articles/mesh-debugger.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual/mesh-debugger" 3 | --- 4 | 5 | # Mesh Debugger 6 | 7 | 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`. 8 | 9 | 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. 10 | 11 | ![](../images/mesh-debugger.jpg) 12 | -------------------------------------------------------------------------------- /Documentation~/articles/shaders.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: "/manual/shaders" 3 | --- 4 | 5 | # Debug Shaders 6 | 7 | The **Debug Tools** package comes with several shaders to visualize different vertex data. These shaders are located under `Zigurous > Debug` within the shader selection menu. 8 | 9 |
10 | 11 | ## UV 12 | 13 | ``` 14 | v2f vert (appdata v) 15 | { 16 | v2f o; 17 | o.pos = UnityObjectToClipPos(v.vertex); 18 | o.uv = float4(v.texcoord.xy, 0, 0); 19 | return o; 20 | } 21 | ``` 22 | 23 | ![](https://docs.unity3d.com/uploads/Main/SL-DebugUV1.png) 24 | 25 |
26 | 27 | ## Normals 28 | 29 | ``` 30 | v2f vert (appdata v) 31 | { 32 | v2f o; 33 | o.pos = UnityObjectToClipPos(v.vertex); 34 | o.color.xyz = v.normal * 0.5 + 0.5; 35 | o.color.w = 1.0; 36 | return o; 37 | } 38 | ``` 39 | 40 | ![](https://docs.unity3d.com/uploads/Main/SL-DebugNormals.png) 41 | 42 |
43 | 44 | ## Tangents 45 | 46 | ``` 47 | v2f vert (appdata v) 48 | { 49 | v2f o; 50 | o.pos = UnityObjectToClipPos(v.vertex); 51 | o.color = v.tangent * 0.5 + 0.5; 52 | return o; 53 | } 54 | ``` 55 | 56 | ![](https://docs.unity3d.com/uploads/Main/SL-DebugTangents.png) 57 | 58 |
59 | 60 | ## Bitangents 61 | 62 | ``` 63 | v2f vert (appdata v) 64 | { 65 | v2f o; 66 | o.pos = UnityObjectToClipPos(v.vertex); 67 | float3 bitangent = cross(v.normal, v.tangent.xyz) * v.tangent.w; 68 | o.color.xyz = bitangent * 0.5 + 0.5; 69 | o.color.w = 1.0; 70 | return o; 71 | } 72 | ``` 73 | 74 | ![](https://docs.unity3d.com/uploads/Main/SL-DebugBinormals.png) 75 | 76 |
77 | 78 | ## Vertex Color 79 | 80 | ``` 81 | v2f vert (appdata v) 82 | { 83 | v2f o; 84 | o.pos = UnityObjectToClipPos(v.vertex); 85 | o.color = v.color; 86 | return o; 87 | } 88 | ``` 89 | 90 | ![](https://docs.unity3d.com/uploads/Main/SL-DebugColors.png) 91 | -------------------------------------------------------------------------------- /Documentation~/data/header.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Manual", 4 | "path": "/manual" 5 | }, 6 | { 7 | "name": "Scripting API", 8 | "path": "/api" 9 | }, 10 | { 11 | "name": "Changelog", 12 | "path": "/changelog" 13 | }, 14 | { 15 | "name": "License", 16 | "path": "/license" 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /Documentation~/data/sidenav.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "📌 Overview", 4 | "items": [ 5 | { 6 | "name": "Getting Started", 7 | "path": "/manual" 8 | }, 9 | { 10 | "name": "Installation", 11 | "path": "/installation" 12 | }, 13 | { 14 | "name": "Changelog", 15 | "path": "/changelog" 16 | }, 17 | { 18 | "name": "License", 19 | "path": "/license" 20 | } 21 | ] 22 | }, 23 | { 24 | "title": "📖 Reference", 25 | "items": [ 26 | { 27 | "name": "Logging", 28 | "path": "/manual/logging" 29 | }, 30 | { 31 | "name": "Benchmarking", 32 | "path": "/manual/benchmarking" 33 | }, 34 | { 35 | "name": "Framerate Display", 36 | "path": "/manual/framerate" 37 | }, 38 | { 39 | "name": "Debug Shaders", 40 | "path": "/manual/shaders" 41 | }, 42 | { 43 | "name": "Mesh Debugger", 44 | "path": "/manual/mesh-debugger" 45 | }, 46 | { 47 | "name": "Drawing", 48 | "path": "/manual/drawing" 49 | } 50 | ] 51 | }, 52 | { 53 | "title": "💬 Contact", 54 | "items": [ 55 | { 56 | "name": "Discord", 57 | "href": "https://discord.gg/DdYyWVb", 58 | "icon": "launch" 59 | }, 60 | { 61 | "name": "Twitter", 62 | "href": "https://twitter.com/zigurous", 63 | "icon": "launch" 64 | } 65 | ] 66 | }, 67 | { 68 | "title": "🔗 Other Links", 69 | "items": [ 70 | { 71 | "name": "GitHub", 72 | "href": "https://github.com/zigurous/unity-debug-tools", 73 | "icon": "launch" 74 | }, 75 | { 76 | "name": "Asset Store", 77 | "href": "https://assetstore.unity.com/publishers/51884", 78 | "icon": "launch" 79 | }, 80 | { 81 | "name": "YouTube", 82 | "href": "https://youtube.com/c/zigurous?sub_confirmation=1", 83 | "icon": "launch" 84 | }, 85 | { 86 | "name": "Patreon", 87 | "href": "https://patreon.com/zigurous", 88 | "icon": "launch" 89 | } 90 | ] 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /Documentation~/images/mesh-debugger.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zigurous/unity-debug-tools/76a63c2f3b5b6dfca5d8b0055e5c42b3e3c2d56f/Documentation~/images/mesh-debugger.jpg -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3012dd2e8cb1d14a8f856af725af14d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/MeshDebugger.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Zigurous.Debug.Editor 5 | { 6 | public sealed class MeshDebugger : EditorWindow 7 | { 8 | private Mesh currentMesh; 9 | private MeshFilter currentMeshFilter; 10 | private SkinnedMeshRenderer currentSkinnedMeshRenderer; 11 | private int currentFace = 0, numFaces = 0, newFace = 0; 12 | private GUIStyle labelStyle = null; 13 | private Vector3 p1, p2, p3; 14 | 15 | [MenuItem("Window/Analysis/Mesh Debugger")] 16 | public static void ShowWindow() 17 | { 18 | EditorWindow.GetWindow(typeof(MeshDebugger), true, "Mesh Debugger"); 19 | } 20 | 21 | private void OnEnable() 22 | { 23 | SceneView.duringSceneGui -= OnSceneGUI; 24 | SceneView.duringSceneGui += OnSceneGUI; 25 | 26 | OnSelectionChange(); 27 | } 28 | 29 | private void OnDestroy() 30 | { 31 | SceneView.duringSceneGui -= OnSceneGUI; 32 | } 33 | 34 | private void OnSelectionChange() 35 | { 36 | currentMesh = null; 37 | currentSkinnedMeshRenderer = null; 38 | numFaces = 0; 39 | 40 | if (Selection.activeGameObject) 41 | { 42 | currentMeshFilter = Selection.activeGameObject.GetComponentInChildren(); 43 | 44 | if (currentMeshFilter != null) 45 | { 46 | currentMesh = currentMeshFilter.sharedMesh; 47 | numFaces = currentMesh.triangles.Length / 3; 48 | } 49 | else 50 | { 51 | currentSkinnedMeshRenderer = Selection.activeGameObject.GetComponentInChildren(); 52 | 53 | if (currentSkinnedMeshRenderer != null) 54 | { 55 | currentMesh = currentSkinnedMeshRenderer.sharedMesh; 56 | numFaces = currentMesh.triangles.Length / 3; 57 | } 58 | } 59 | } 60 | 61 | currentFace = 0; 62 | newFace = currentFace; 63 | 64 | Repaint(); 65 | } 66 | 67 | private void OnGUI() 68 | { 69 | if (currentMesh == null) 70 | { 71 | EditorGUILayout.LabelField("Current selection contains no mesh"); 72 | return; 73 | } 74 | 75 | EditorGUILayout.LabelField("Number of faces", numFaces.ToString()); 76 | EditorGUILayout.LabelField("Current face", currentFace.ToString()); 77 | 78 | newFace = EditorGUILayout.IntField("Jump to face", currentFace); 79 | 80 | if (newFace != currentFace) 81 | { 82 | if (newFace >= 0 && newFace < numFaces) { 83 | currentFace = newFace; 84 | } 85 | } 86 | 87 | EditorGUILayout.BeginHorizontal(); 88 | 89 | if (GUILayout.Button("Previous Face")) 90 | { 91 | currentFace = (currentFace - 1) % numFaces; 92 | 93 | if (currentFace < 0) { 94 | currentFace = currentFace + numFaces; 95 | } 96 | } 97 | 98 | if (GUILayout.Button("Next Face")) { 99 | currentFace = (currentFace + 1) % numFaces; 100 | } 101 | 102 | EditorGUILayout.EndHorizontal(); 103 | 104 | EditorGUILayout.Space(); 105 | 106 | int redIndex = currentMesh.triangles[currentFace * 3]; 107 | int greenIndex = currentMesh.triangles[currentFace * 3 + 1]; 108 | int blueIndex = currentMesh.triangles[currentFace * 3 + 2]; 109 | 110 | EditorGUILayout.LabelField("Red vertex", $"Index: {redIndex}, UV: ({currentMesh.uv[redIndex].x}, {currentMesh.uv[redIndex].y})"); 111 | EditorGUILayout.LabelField("Green vertex", $"Index: {greenIndex}, UV: ({currentMesh.uv[greenIndex].x}, {currentMesh.uv[greenIndex].y})"); 112 | EditorGUILayout.LabelField("Blue vertex", $"Index: {blueIndex}, UV: ({currentMesh.uv[blueIndex].x}, {currentMesh.uv[blueIndex].y})"); 113 | } 114 | 115 | private void OnSceneGUI(SceneView sceneView) 116 | { 117 | if (currentMesh == null) { 118 | return; 119 | } 120 | 121 | int index1 = currentMesh.triangles[currentFace * 3]; 122 | int index2 = currentMesh.triangles[currentFace * 3 + 1]; 123 | int index3 = currentMesh.triangles[currentFace * 3 + 2]; 124 | 125 | if (currentMeshFilter != null) 126 | { 127 | p1 = currentMeshFilter.transform.TransformPoint(currentMesh.vertices[index1]); 128 | p2 = currentMeshFilter.transform.TransformPoint(currentMesh.vertices[index2]); 129 | p3 = currentMeshFilter.transform.TransformPoint(currentMesh.vertices[index3]); 130 | } 131 | else if (currentSkinnedMeshRenderer != null) 132 | { 133 | p1 = currentSkinnedMeshRenderer.transform.TransformPoint(currentMesh.vertices[index1]); 134 | p2 = currentSkinnedMeshRenderer.transform.TransformPoint(currentMesh.vertices[index2]); 135 | p3 = currentSkinnedMeshRenderer.transform.TransformPoint(currentMesh.vertices[index3]); 136 | } 137 | 138 | Handles.color = Color.red; 139 | Handles.SphereHandleCap(0, p1, Quaternion.identity, 0.2f * HandleUtility.GetHandleSize(p1), EventType.Repaint); 140 | Handles.color = Color.green; 141 | Handles.SphereHandleCap(0, p2, Quaternion.identity, 0.2f * HandleUtility.GetHandleSize(p2), EventType.Repaint); 142 | Handles.color = Color.blue; 143 | Handles.SphereHandleCap(0, p3, Quaternion.identity, 0.2f * HandleUtility.GetHandleSize(p3), EventType.Repaint); 144 | 145 | Handles.color = Color.white; 146 | Handles.DrawDottedLine(p1, p2, 5f); 147 | Handles.DrawDottedLine(p2, p3, 5f); 148 | Handles.DrawDottedLine(p3, p1, 5f); 149 | 150 | if (labelStyle == null) 151 | { 152 | labelStyle = new GUIStyle(GUI.skin.label); 153 | labelStyle.normal.textColor = Color.white; 154 | labelStyle.fixedWidth = 40; 155 | labelStyle.fixedHeight = 20; 156 | labelStyle.alignment = TextAnchor.MiddleCenter; 157 | labelStyle.fontSize = 12; 158 | labelStyle.clipping = TextClipping.Overflow; 159 | } 160 | 161 | Handles.Label(p1, index1.ToString(), labelStyle); 162 | Handles.Label(p2, index2.ToString(), labelStyle); 163 | Handles.Label(p3, index3.ToString(), labelStyle); 164 | 165 | sceneView.Repaint(); 166 | } 167 | 168 | private void OnInspectorUpdate() 169 | { 170 | Repaint(); 171 | } 172 | 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /Editor/MeshDebugger.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 08d9ecff8983ad744aa14c4afcc181a7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Zigurous.Debug.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Zigurous.Debug.Editor", 3 | "references": [ 4 | "GUID:0186cdaa7ccbaeb4f91d3907506784d7" 5 | ], 6 | "includePlatforms": [ 7 | "Editor" 8 | ], 9 | "excludePlatforms": [], 10 | "allowUnsafeCode": false, 11 | "overrideReferences": false, 12 | "precompiledReferences": [], 13 | "autoReferenced": true, 14 | "defineConstraints": [], 15 | "versionDefines": [], 16 | "noEngineReferences": false 17 | } -------------------------------------------------------------------------------- /Editor/Zigurous.Debug.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 045545c2591da4e4099246d349849f66 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Zigurous 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8589f427c14bc84cb0ab9c0b47a7eca 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c33b595ef3c5b1d488c8e0596f7bf7e7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/Debug_Bitangents.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Debug_Bitangents 11 | m_Shader: {fileID: 4800000, guid: 799185a077972f94a94413ba62eea208, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/Debug_Bitangents.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9a7df69618fd29a42a5e434b85202514 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/Debug_Normals.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Debug_Normals 11 | m_Shader: {fileID: 4800000, guid: 128dc0c4016252441906789fa41d7e0d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/Debug_Normals.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e262d1e59c54df43a3751e6b3e71d63 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/Debug_Tangents.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Debug_Tangents 11 | m_Shader: {fileID: 4800000, guid: ceb9d40400658184a94d27f3b2311566, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/Debug_Tangents.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1e75dbbea7f6bc42bec333416b957e5 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/Debug_UV1.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Debug_UV1 11 | m_Shader: {fileID: 4800000, guid: 4af31441edc01314bb567e90b33b2ee7, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/Debug_UV1.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9be49e8ef766a7648a858d3488b8770f 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/Debug_UV2.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Debug_UV2 11 | m_Shader: {fileID: 4800000, guid: b56c8bdfcdce88949ab83bafd1ecbfb6, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/Debug_UV2.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dfa775b39fcefad4cb444bc4bf4848bb 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/Debug_VertexColor.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Debug_VertexColor 11 | m_Shader: {fileID: 4800000, guid: 6d47743c9f1966046943571f10b6b632, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/Debug_VertexColor.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 941ee3154d02c154a8c040ec88674227 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8a9a9cb35c3fbc84dbe4dce434c7d8c8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Prefabs/FPSDisplay.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &2560411229158870746 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 2560411229158870742} 12 | - component: {fileID: 2560411229158870743} 13 | - component: {fileID: 2560411229158870744} 14 | - component: {fileID: 7135560934737295104} 15 | m_Layer: 5 16 | m_Name: FPSDisplay 17 | m_TagString: Untagged 18 | m_Icon: {fileID: 0} 19 | m_NavMeshLayer: 0 20 | m_StaticEditorFlags: 0 21 | m_IsActive: 1 22 | --- !u!224 &2560411229158870742 23 | RectTransform: 24 | m_ObjectHideFlags: 0 25 | m_CorrespondingSourceObject: {fileID: 0} 26 | m_PrefabInstance: {fileID: 0} 27 | m_PrefabAsset: {fileID: 0} 28 | m_GameObject: {fileID: 2560411229158870746} 29 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 30 | m_LocalPosition: {x: 0, y: 0, z: 0} 31 | m_LocalScale: {x: 0, y: 0, z: 0} 32 | m_Children: 33 | - {fileID: 2560411230916416748} 34 | m_Father: {fileID: 0} 35 | m_RootOrder: 0 36 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 37 | m_AnchorMin: {x: 0, y: 0} 38 | m_AnchorMax: {x: 0, y: 0} 39 | m_AnchoredPosition: {x: 0, y: 0} 40 | m_SizeDelta: {x: 0, y: 0} 41 | m_Pivot: {x: 0, y: 0} 42 | --- !u!223 &2560411229158870743 43 | Canvas: 44 | m_ObjectHideFlags: 0 45 | m_CorrespondingSourceObject: {fileID: 0} 46 | m_PrefabInstance: {fileID: 0} 47 | m_PrefabAsset: {fileID: 0} 48 | m_GameObject: {fileID: 2560411229158870746} 49 | m_Enabled: 1 50 | serializedVersion: 3 51 | m_RenderMode: 0 52 | m_Camera: {fileID: 0} 53 | m_PlaneDistance: 100 54 | m_PixelPerfect: 0 55 | m_ReceivesEvents: 1 56 | m_OverrideSorting: 0 57 | m_OverridePixelPerfect: 0 58 | m_SortingBucketNormalizedSize: 0 59 | m_AdditionalShaderChannelsFlag: 0 60 | m_SortingLayerID: 0 61 | m_SortingOrder: 0 62 | m_TargetDisplay: 0 63 | --- !u!114 &2560411229158870744 64 | MonoBehaviour: 65 | m_ObjectHideFlags: 0 66 | m_CorrespondingSourceObject: {fileID: 0} 67 | m_PrefabInstance: {fileID: 0} 68 | m_PrefabAsset: {fileID: 0} 69 | m_GameObject: {fileID: 2560411229158870746} 70 | m_Enabled: 1 71 | m_EditorHideFlags: 0 72 | m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} 73 | m_Name: 74 | m_EditorClassIdentifier: 75 | m_UiScaleMode: 0 76 | m_ReferencePixelsPerUnit: 100 77 | m_ScaleFactor: 1 78 | m_ReferenceResolution: {x: 800, y: 600} 79 | m_ScreenMatchMode: 0 80 | m_MatchWidthOrHeight: 0 81 | m_PhysicalUnit: 3 82 | m_FallbackScreenDPI: 96 83 | m_DefaultSpriteDPI: 96 84 | m_DynamicPixelsPerUnit: 1 85 | --- !u!114 &7135560934737295104 86 | MonoBehaviour: 87 | m_ObjectHideFlags: 0 88 | m_CorrespondingSourceObject: {fileID: 0} 89 | m_PrefabInstance: {fileID: 0} 90 | m_PrefabAsset: {fileID: 0} 91 | m_GameObject: {fileID: 2560411229158870746} 92 | m_Enabled: 1 93 | m_EditorHideFlags: 0 94 | m_Script: {fileID: 11500000, guid: 45e8fac3decf75e4ab5ee244c5fb9b29, type: 3} 95 | m_Name: 96 | m_EditorClassIdentifier: 97 | displayText: {fileID: 2560411230916416746} 98 | refreshRate: 0.125 99 | m_Decimals: 0 100 | --- !u!1 &2560411230916416749 101 | GameObject: 102 | m_ObjectHideFlags: 0 103 | m_CorrespondingSourceObject: {fileID: 0} 104 | m_PrefabInstance: {fileID: 0} 105 | m_PrefabAsset: {fileID: 0} 106 | serializedVersion: 6 107 | m_Component: 108 | - component: {fileID: 2560411230916416748} 109 | - component: {fileID: 2560411230916416745} 110 | - component: {fileID: 2560411230916416746} 111 | - component: {fileID: 2560411230916416747} 112 | m_Layer: 5 113 | m_Name: Text 114 | m_TagString: Untagged 115 | m_Icon: {fileID: 0} 116 | m_NavMeshLayer: 0 117 | m_StaticEditorFlags: 0 118 | m_IsActive: 1 119 | --- !u!224 &2560411230916416748 120 | RectTransform: 121 | m_ObjectHideFlags: 0 122 | m_CorrespondingSourceObject: {fileID: 0} 123 | m_PrefabInstance: {fileID: 0} 124 | m_PrefabAsset: {fileID: 0} 125 | m_GameObject: {fileID: 2560411230916416749} 126 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 127 | m_LocalPosition: {x: 0, y: 0, z: 0} 128 | m_LocalScale: {x: 1, y: 1, z: 1} 129 | m_Children: [] 130 | m_Father: {fileID: 2560411229158870742} 131 | m_RootOrder: 0 132 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 133 | m_AnchorMin: {x: 1, y: 1} 134 | m_AnchorMax: {x: 1, y: 1} 135 | m_AnchoredPosition: {x: -8, y: -8} 136 | m_SizeDelta: {x: 0, y: 0} 137 | m_Pivot: {x: 0.5, y: 0.5} 138 | --- !u!222 &2560411230916416745 139 | CanvasRenderer: 140 | m_ObjectHideFlags: 0 141 | m_CorrespondingSourceObject: {fileID: 0} 142 | m_PrefabInstance: {fileID: 0} 143 | m_PrefabAsset: {fileID: 0} 144 | m_GameObject: {fileID: 2560411230916416749} 145 | m_CullTransparentMesh: 0 146 | --- !u!114 &2560411230916416746 147 | MonoBehaviour: 148 | m_ObjectHideFlags: 0 149 | m_CorrespondingSourceObject: {fileID: 0} 150 | m_PrefabInstance: {fileID: 0} 151 | m_PrefabAsset: {fileID: 0} 152 | m_GameObject: {fileID: 2560411230916416749} 153 | m_Enabled: 1 154 | m_EditorHideFlags: 0 155 | m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 156 | m_Name: 157 | m_EditorClassIdentifier: 158 | m_Material: {fileID: 0} 159 | m_Color: {r: 1, g: 1, b: 1, a: 1} 160 | m_RaycastTarget: 0 161 | m_Maskable: 0 162 | m_OnCullStateChanged: 163 | m_PersistentCalls: 164 | m_Calls: [] 165 | m_FontData: 166 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 167 | m_FontSize: 14 168 | m_FontStyle: 0 169 | m_BestFit: 0 170 | m_MinSize: 1 171 | m_MaxSize: 40 172 | m_Alignment: 2 173 | m_AlignByGeometry: 0 174 | m_RichText: 1 175 | m_HorizontalOverflow: 1 176 | m_VerticalOverflow: 1 177 | m_LineSpacing: 1 178 | m_Text: 0 179 | --- !u!114 &2560411230916416747 180 | MonoBehaviour: 181 | m_ObjectHideFlags: 0 182 | m_CorrespondingSourceObject: {fileID: 0} 183 | m_PrefabInstance: {fileID: 0} 184 | m_PrefabAsset: {fileID: 0} 185 | m_GameObject: {fileID: 2560411230916416749} 186 | m_Enabled: 1 187 | m_EditorHideFlags: 0 188 | m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3} 189 | m_Name: 190 | m_EditorClassIdentifier: 191 | m_EffectColor: {r: 0, g: 0, b: 0, a: 0.5} 192 | m_EffectDistance: {x: 1, y: -1} 193 | m_UseGraphicAlpha: 1 194 | -------------------------------------------------------------------------------- /Prefabs/FPSDisplay.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2cfe12a0b437f904ca80fa4cba45e4fe 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Debug Tools 2 | 3 | [![](https://img.shields.io/badge/github-repo-blue?logo=github)](https://github.com/zigurous/unity-debug-tools) [![](https://img.shields.io/github/package-json/v/zigurous/unity-debug-tools)](https://github.com/zigurous/unity-debug-tools/releases) [![](https://img.shields.io/badge/docs-link-success)](https://docs.zigurous.com/com.zigurous.debug) [![](https://img.shields.io/github/license/zigurous/unity-debug-tools)](https://github.com/zigurous/unity-debug-tools/blob/main/LICENSE.md) 4 | 5 | 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. 6 | 7 | ## Reference 8 | 9 | - [Logging](https://docs.zigurous.com/com.zigurous.debug/manual/logging) 10 | - [Benchmarking](https://docs.zigurous.com/com.zigurous.debug/manual/benchmarking) 11 | - [Framerate Display](https://docs.zigurous.com/com.zigurous.debug/manual/framerate) 12 | - [Debug Shaders](https://docs.zigurous.com/com.zigurous.debug/manual/shaders) 13 | - [Mesh Debugger](https://docs.zigurous.com/com.zigurous.debug/manual/mesh-debugger) 14 | - [Drawing](https://docs.zigurous.com/com.zigurous.debug/manual/drawing) 15 | 16 | ## Installation 17 | 18 | Use the Unity [Package Manager](https://docs.unity3d.com/Manual/upm-ui.html) to install the **Debug Tools** package. 19 | 20 | 1. Open the Package Manager in `Window > Package Manager` 21 | 2. Click the add (`+`) button in the status bar 22 | 3. Select `Add package from git URL` from the add menu 23 | 4. Enter the following Git URL in the text box and click Add: 24 | 25 | ``` 26 | https://github.com/zigurous/unity-debug-tools.git 27 | ``` 28 | 29 | ## Namespace 30 | 31 | Import the package namespace in each script or file you want to use it. You may need to regenerate project files/assemblies first. 32 | 33 | ```csharp 34 | using Zigurous.Debug; 35 | ``` 36 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a4993ea28e683de4b918c63614adc473 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10738018f9fc3034fbd18aef34122dc3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Benchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Zigurous.Debug 5 | { 6 | /// 7 | /// Measures the execution time of functions. 8 | /// 9 | public static class Benchmark 10 | { 11 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 12 | /// 13 | /// A stopwatch that measures execution time. 14 | /// 15 | private static Stopwatch stopwatch = new Stopwatch(); 16 | #endif 17 | 18 | /// 19 | /// Measures the execution time of a function with a given amount of 20 | /// iterations. 21 | /// 22 | /// The function to be executed. 23 | /// The amount of times the function is executed. 24 | /// Logs the result to the console. 25 | /// The execution time of the function in milliseconds. 26 | public static double Measure(Action foo, int iterations, bool log = true) 27 | { 28 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 29 | stopwatch.Reset(); 30 | stopwatch.Start(); 31 | 32 | for (int i = 0; i < iterations; i++) { 33 | foo(); 34 | } 35 | 36 | stopwatch.Stop(); 37 | double time = stopwatch.Elapsed.TotalMilliseconds; 38 | 39 | if (log) { 40 | UnityEngine.Debug.Log($"[Benchmark] {time.ToString()}ms | {foo.ToString()}"); 41 | } 42 | 43 | return time; 44 | #else 45 | return double.NaN; 46 | #endif 47 | } 48 | 49 | /// 50 | /// Compares the execution time between two functions with a given 51 | /// amount of iterations. 52 | /// 53 | /// The first function to be executed. 54 | /// The second function to be executed. 55 | /// The amount of times each function is executed. 56 | /// Logs the result to the console. 57 | /// The difference in execution time of the two functions in milliseconds. 58 | public static double Compare(Action foo, Action bar, int iterations, bool log = true) 59 | { 60 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 61 | double timeFoo = Measure(foo, iterations, false); 62 | double timeBar = Measure(bar, iterations, false); 63 | double difference = timeFoo - timeBar; 64 | 65 | if (log) { 66 | UnityEngine.Debug.Log($"[Benchmark] {timeFoo.ToString()}ms vs {timeBar.ToString()}ms | {difference.ToString()}ms"); 67 | } 68 | 69 | return difference; 70 | #else 71 | return double.NaN; 72 | #endif 73 | } 74 | 75 | /// 76 | /// Performs a benchmark that runs each provided function a given amount 77 | /// of iterations. 78 | /// 79 | /// The amount of times each function is executed. 80 | /// The functions to be executed. 81 | public static void Run(int iterations, params Action[] functions) 82 | { 83 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 84 | for (int i = 0; i < functions.Length; i++) { 85 | Measure(functions[i], iterations); 86 | } 87 | #endif 88 | } 89 | 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /Runtime/Benchmark.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7143b887ddead3f41a621d6b5b94a97a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Compare.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Zigurous.Debug 4 | { 5 | /// 6 | /// Compares the results of multiple functions for equality. 7 | /// 8 | public static class Compare 9 | { 10 | /// 11 | /// Compares how many results of the two functions are equal for a given 12 | /// amount of iterations. 13 | /// 14 | /// The first function to execute. 15 | /// The second function to execute. 16 | /// The amount of times each function is executed. 17 | /// Logs the final comparison result. 18 | /// Logs the result of each iteration of the functions. 19 | /// The percentage of equal results. 20 | public static float Equal(Func foo, Func bar, int iterations, bool log = true, bool logIndividual = false) 21 | where T : IEquatable 22 | { 23 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 24 | int amountEqual = 0; 25 | 26 | for (int i = 0; i < iterations; i++) 27 | { 28 | T resultFoo = foo(); 29 | T resultBar = bar(); 30 | 31 | bool equal = resultFoo.Equals(resultBar); 32 | 33 | if (equal) { 34 | amountEqual++; 35 | } 36 | 37 | if (log && logIndividual) { 38 | UnityEngine.Debug.Log($"[Compare] {resultFoo.ToString()} vs {resultBar.ToString()} | {(equal ? "Equal" : "Not Equal")}"); 39 | } 40 | } 41 | 42 | float percentEqual = (float)amountEqual / (float)iterations; 43 | 44 | if (log) { 45 | UnityEngine.Debug.Log($"[Compare] {amountEqual.ToString()}/{iterations.ToString()} ({(percentEqual * 100f).ToString()}%) equal results"); 46 | } 47 | 48 | return percentEqual; 49 | #else 50 | return float.NaN; 51 | #endif 52 | } 53 | 54 | /// 55 | /// Compares how many results of the two functions are not equal for a 56 | /// given amount of iterations. 57 | /// 58 | /// The first function to execute. 59 | /// The second function to execute. 60 | /// The amount of times each function is executed. 61 | /// Logs the final comparison result. 62 | /// Logs the result of each iteration of the functions. 63 | /// The percentage of equal results. 64 | public static float NotEqual(Func foo, Func bar, int iterations, bool log = true, bool logIndividual = false) 65 | where T : IEquatable 66 | { 67 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 68 | int amountNotEqual = 0; 69 | 70 | for (int i = 0; i < iterations; i++) 71 | { 72 | T resultFoo = foo(); 73 | T resultBar = bar(); 74 | 75 | bool equal = resultFoo.Equals(resultBar); 76 | 77 | if (!equal) { 78 | amountNotEqual++; 79 | } 80 | 81 | if (log && logIndividual) { 82 | UnityEngine.Debug.Log($"[Compare] {resultFoo.ToString()} vs {resultBar.ToString()} | {(equal ? "Equal" : "Not Equal")}"); 83 | } 84 | } 85 | 86 | float percentNotEqual = (float)amountNotEqual / (float)iterations; 87 | 88 | if (log) { 89 | UnityEngine.Debug.Log($"[Compare] {amountNotEqual.ToString()}/{iterations.ToString()} ({(percentNotEqual * 100f).ToString()}%) not equal results"); 90 | } 91 | 92 | return percentNotEqual; 93 | #else 94 | return float.NaN; 95 | #endif 96 | } 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /Runtime/Compare.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b59696d94edaef48a220f42a5c50db9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Draw.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Zigurous.Debug 4 | { 5 | /// 6 | /// Additional debug functions for drawing shapes. 7 | /// 8 | public static class Draw 9 | { 10 | /// 11 | /// The data representation of a 3D box. 12 | /// 13 | private struct Box3D 14 | { 15 | public Vector3 origin { get; private set; } 16 | 17 | public Vector3 localFrontTopLeft { get; private set; } 18 | public Vector3 localFrontTopRight { get; private set; } 19 | public Vector3 localFrontBottomLeft { get; private set; } 20 | public Vector3 localFrontBottomRight { get; private set; } 21 | 22 | public Vector3 localBackTopLeft => -localFrontBottomRight; 23 | public Vector3 localBackTopRight => -localFrontBottomLeft; 24 | public Vector3 localBackBottomLeft => -localFrontTopRight; 25 | public Vector3 localBackBottomRight => -localFrontTopLeft; 26 | 27 | public Vector3 frontTopLeft => localFrontTopLeft + origin; 28 | public Vector3 frontTopRight => localFrontTopRight + origin; 29 | public Vector3 frontBottomLeft => localFrontBottomLeft + origin; 30 | public Vector3 frontBottomRight => localFrontBottomRight + origin; 31 | 32 | public Vector3 backTopLeft => localBackTopLeft + origin; 33 | public Vector3 backTopRight => localBackTopRight + origin; 34 | public Vector3 backBottomLeft => localBackBottomLeft + origin; 35 | public Vector3 backBottomRight => localBackBottomRight + origin; 36 | 37 | /// 38 | /// Creates a new box with a specified origin and size. 39 | /// 40 | /// The origin of the box. 41 | /// Half the size of the box in each dimension. 42 | public Box3D(Vector3 origin, Vector3 halfExtents) 43 | { 44 | this.origin = origin; 45 | this.localFrontTopLeft = new Vector3(-halfExtents.x, halfExtents.y, -halfExtents.z); 46 | this.localFrontTopRight = new Vector3(halfExtents.x, halfExtents.y, -halfExtents.z); 47 | this.localFrontBottomLeft = new Vector3(-halfExtents.x, -halfExtents.y, -halfExtents.z); 48 | this.localFrontBottomRight = new Vector3(halfExtents.x, -halfExtents.y, -halfExtents.z); 49 | } 50 | 51 | /// 52 | /// Creates a new box with a specified origin, size, and rotation. 53 | /// 54 | /// The origin of the box. 55 | /// Half the size of the box in each dimension. 56 | /// The orientation of the box. 57 | public Box3D(Vector3 origin, Vector3 halfExtents, Quaternion orientation) 58 | : this(origin, halfExtents) 59 | { 60 | Rotate(orientation); 61 | } 62 | 63 | /// 64 | /// Rotates the box to the specified orientation. 65 | /// 66 | /// The orientation to rotate the box to. 67 | public void Rotate(Quaternion orientation) 68 | { 69 | localFrontTopLeft = RotatePointAroundPivot(localFrontTopLeft, Vector3.zero, orientation); 70 | localFrontTopRight = RotatePointAroundPivot(localFrontTopRight, Vector3.zero, orientation); 71 | localFrontBottomLeft = RotatePointAroundPivot(localFrontBottomLeft, Vector3.zero, orientation); 72 | localFrontBottomRight = RotatePointAroundPivot(localFrontBottomRight, Vector3.zero, orientation); 73 | } 74 | 75 | /// 76 | /// Rotates a point around a pivot. 77 | /// 78 | /// The point to rotate. 79 | /// The pivot to rotate around. 80 | /// The orientation to rotate the point to. 81 | /// The rotated point. 82 | private Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion orientation) 83 | { 84 | Vector3 direction = point - pivot; 85 | return pivot + orientation * direction; 86 | } 87 | 88 | /// 89 | /// Draws the box with a given color. 90 | /// 91 | /// The color to draw the box with. 92 | public void Draw(Color color) 93 | { 94 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 95 | UnityEngine.Debug.DrawLine(frontTopLeft, frontTopRight, color); 96 | UnityEngine.Debug.DrawLine(frontTopRight, frontBottomRight, color); 97 | UnityEngine.Debug.DrawLine(frontBottomRight, frontBottomLeft, color); 98 | UnityEngine.Debug.DrawLine(frontBottomLeft, frontTopLeft, color); 99 | 100 | UnityEngine.Debug.DrawLine(backTopLeft, backTopRight, color); 101 | UnityEngine.Debug.DrawLine(backTopRight, backBottomRight, color); 102 | UnityEngine.Debug.DrawLine(backBottomRight, backBottomLeft, color); 103 | UnityEngine.Debug.DrawLine(backBottomLeft, backTopLeft, color); 104 | 105 | UnityEngine.Debug.DrawLine(frontTopLeft, backTopLeft, color); 106 | UnityEngine.Debug.DrawLine(frontTopRight, backTopRight, color); 107 | UnityEngine.Debug.DrawLine(frontBottomRight, backBottomRight, color); 108 | UnityEngine.Debug.DrawLine(frontBottomLeft, backBottomLeft, color); 109 | #endif 110 | } 111 | 112 | } 113 | 114 | /// 115 | /// Draws a wireframe box at a given position, scale, and rotation. 116 | /// 117 | /// The position of the box. 118 | /// The scale of the box. 119 | /// The rotation of the box. 120 | /// The color of the box. 121 | public static void Box(Vector3 position, Vector3 scale, Quaternion rotation, Color color) 122 | { 123 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 124 | new Box3D(position, scale / 2f, rotation).Draw(color); 125 | #endif 126 | } 127 | 128 | /// 129 | /// Draws a wireframe box using the same parameters as Physics.BoxCast. 130 | /// 131 | /// The center of the box. 132 | /// Half the size of the box in each dimension. 133 | /// The direction in which to cast the box. 134 | /// The rotation of the box. 135 | /// The length of the cast. 136 | /// The color of the box. 137 | public static void BoxCast(Vector3 center, Vector3 halfExtents, Vector3 direction, Quaternion orientation, float distance, Color color) 138 | { 139 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 140 | center += (direction.normalized * distance); 141 | Box(center, halfExtents, orientation, color); 142 | #endif 143 | } 144 | 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /Runtime/Draw.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 592a660f82cc4a44e91b67f662f8b230 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/ExitApplication.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | #if ENABLE_INPUT_SYSTEM 3 | using UnityEngine.InputSystem; 4 | #endif 5 | 6 | namespace Zigurous.Debug 7 | { 8 | /// 9 | /// Quits the application via user input. 10 | /// 11 | [AddComponentMenu("Zigurous/Debug/Exit Application")] 12 | [HelpURL("https://docs.zigurous.com/com.zigurous.debug/api/Zigurous.Debug/ExitApplication")] 13 | public sealed class ExitApplication : MonoBehaviour 14 | { 15 | #if ENABLE_INPUT_SYSTEM 16 | /// 17 | /// The input action that quits the application. 18 | /// 19 | [Tooltip("The input action that quits the application.")] 20 | [Header("Input System")] 21 | public InputAction quitInput = new InputAction("ExitApplication", InputActionType.Button, "/escape"); 22 | #endif 23 | 24 | #if ENABLE_LEGACY_INPUT_MANAGER 25 | /// 26 | /// The keycode that quits the application. 27 | /// 28 | [Tooltip("The keycode that quits the application.")] 29 | [Header("Legacy Input Manager")] 30 | public KeyCode quitKey = KeyCode.Escape; 31 | 32 | /// 33 | /// The optional modifier key to be held down to quit the application. 34 | /// 35 | [Tooltip("The optional modifier key to be held down to quit the application.")] 36 | public KeyCode quitKeyModifier = KeyCode.None; 37 | #endif 38 | 39 | #if ENABLE_INPUT_SYSTEM 40 | private void Awake() 41 | { 42 | quitInput.performed += OnQuit; 43 | } 44 | 45 | private void OnDestroy() 46 | { 47 | quitInput.Dispose(); 48 | } 49 | 50 | private void OnEnable() 51 | { 52 | quitInput.Enable(); 53 | } 54 | 55 | private void OnDisable() 56 | { 57 | quitInput.Disable(); 58 | } 59 | 60 | private void OnQuit(InputAction.CallbackContext context) 61 | { 62 | if (context.performed) { 63 | Quit(); 64 | } 65 | } 66 | #endif 67 | 68 | #if ENABLE_LEGACY_INPUT_MANAGER 69 | private void Update() 70 | { 71 | if (Input.GetKeyDown(quitKey)) 72 | { 73 | if (quitKeyModifier == KeyCode.None || Input.GetKey(quitKeyModifier)) { 74 | Quit(); 75 | } 76 | } 77 | } 78 | #endif 79 | 80 | /// 81 | /// Quits the application, or exits playmode if running in the editor. 82 | /// 83 | public void Quit() 84 | { 85 | #if UNITY_EDITOR 86 | if (Application.isEditor) 87 | { 88 | UnityEditor.EditorApplication.ExitPlaymode(); 89 | return; 90 | } 91 | #endif 92 | 93 | Application.Quit(); 94 | } 95 | 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /Runtime/ExitApplication.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ab1552eef99574459510537a5d67ee3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/FPSDisplay.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using UnityEngine; 3 | using UnityEngine.UI; 4 | 5 | namespace Zigurous.Debug 6 | { 7 | /// 8 | /// Displays the framerate of the application in realtime. 9 | /// 10 | [AddComponentMenu("Zigurous/Debug/FPS Display")] 11 | [HelpURL("https://docs.zigurous.com/com.zigurous.debug/api/Zigurous.Debug/FPSDisplay")] 12 | public class FPSDisplay : MonoBehaviour 13 | { 14 | /// 15 | /// The UI text that display the framerate. 16 | /// 17 | [Tooltip("The UI text that display the framerate.")] 18 | public Text displayText; 19 | 20 | /// 21 | /// The text format of the framerate display. 22 | /// 23 | public string displayFormat { get; set; } 24 | 25 | /// 26 | /// The amount of seconds between display updates. 27 | /// 28 | [Tooltip("The amount of seconds between display updates.")] 29 | public float refreshRate = 0.125f; 30 | 31 | /// 32 | /// The time of the next framerate update. 33 | /// 34 | private float nextUpdate; 35 | 36 | [SerializeField] 37 | [Tooltip("The number of decimal digits to display.")] 38 | private int m_Decimals = 0; 39 | 40 | /// 41 | /// The number of decimal digits to display. 42 | /// 43 | public int decimals 44 | { 45 | get => m_Decimals; 46 | set 47 | { 48 | m_Decimals = value; 49 | SetDisplayFormat(value); 50 | } 51 | } 52 | 53 | private void Reset() 54 | { 55 | displayText = GetComponentInChildren(); 56 | } 57 | 58 | private void OnValidate() 59 | { 60 | SetDisplayFormat(decimals); 61 | } 62 | 63 | private void Awake() 64 | { 65 | SetDisplayFormat(decimals); 66 | } 67 | 68 | private void Update() 69 | { 70 | if (Time.unscaledTime > nextUpdate) 71 | { 72 | nextUpdate = Time.unscaledTime + refreshRate; 73 | float fps = 1f / Time.unscaledDeltaTime; 74 | UpdateDisplay(fps); 75 | } 76 | } 77 | 78 | /// 79 | /// Updates the display with the given framerate. 80 | /// 81 | /// The framerate to display. 82 | protected virtual void UpdateDisplay(float fps) 83 | { 84 | if (displayText != null) { 85 | displayText.text = fps.ToString(displayFormat); 86 | } 87 | } 88 | 89 | /// 90 | /// Sets the text format of the framerate display. 91 | /// 92 | /// The number of decimal digits to display. 93 | protected virtual void SetDisplayFormat(int decimals) 94 | { 95 | int length = 1 + decimals; 96 | if (decimals > 0) length++; 97 | 98 | StringBuilder stringBuilder = new StringBuilder(length); 99 | stringBuilder.Append('0'); 100 | 101 | if (decimals > 0) 102 | { 103 | stringBuilder.Append('.'); 104 | stringBuilder.Insert(2, "0", decimals); 105 | } 106 | 107 | displayFormat = stringBuilder.ToString(); 108 | } 109 | 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /Runtime/FPSDisplay.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 45e8fac3decf75e4ab5ee244c5fb9b29 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Log.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Zigurous.Debug 4 | { 5 | /// 6 | /// Provides more robust console logging functions compared to 7 | /// UnityEngine.Debug. 8 | /// 9 | public static class Log 10 | { 11 | /// 12 | /// A prefix appended to every log message printed to the console. 13 | /// 14 | public static string prefix = "[Zigurous] "; 15 | 16 | /// 17 | /// The display string for any null references that are logged to the 18 | /// console. 19 | /// 20 | public static string nullReference = "Null"; 21 | 22 | /// 23 | /// The delimiter used when joining multiple messages into a single log 24 | /// message printed to the console. 25 | /// 26 | public static string delimiter = ", "; 27 | 28 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 29 | /// 30 | /// Handles the creation of strings in a more optimized way. 31 | /// 32 | private static StringBuilder stringBuilder = new StringBuilder(); 33 | #endif 34 | 35 | /// 36 | /// Logs a message to the Unity console. 37 | /// 38 | /// The message to log. 39 | public static void Message(object message) 40 | { 41 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 42 | Message(message, Log.prefix); 43 | #endif 44 | } 45 | 46 | /// 47 | /// Logs a message to the Unity console with a custom prefix. 48 | /// 49 | /// The message to log. 50 | /// The prefix of the message. 51 | public static void Message(object message, string prefix) 52 | { 53 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 54 | stringBuilder.Clear(); 55 | 56 | if (message != null) { 57 | UnityEngine.Debug.Log(stringBuilder.Append(prefix).Append(message)); 58 | } else { 59 | UnityEngine.Debug.Log(stringBuilder.Append(prefix).Append(Log.nullReference)); 60 | } 61 | #endif 62 | } 63 | 64 | /// 65 | /// Logs a message to the Unity console under a given context. 66 | /// 67 | /// The message to log. 68 | /// The context of the message. 69 | public static void Message(object message, UnityEngine.Object context) 70 | { 71 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 72 | Message(message, Log.prefix, context); 73 | #endif 74 | } 75 | 76 | /// 77 | /// Logs a message to the Unity console with a custom prefix under a 78 | /// given context. 79 | /// 80 | /// The message to log. 81 | /// The prefix of the message. 82 | /// The context of the message. 83 | public static void Message(object message, string prefix, UnityEngine.Object context) 84 | { 85 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 86 | stringBuilder.Clear(); 87 | 88 | if (message != null) { 89 | UnityEngine.Debug.Log(stringBuilder.Append(prefix).Append(message), context); 90 | } else { 91 | UnityEngine.Debug.Log(stringBuilder.Append(prefix).Append(Log.nullReference), context); 92 | } 93 | #endif 94 | } 95 | 96 | /// 97 | /// Logs multiple messages as a single message to the Unity console. 98 | /// 99 | /// The messages to log. 100 | public static void Message(params object[] messages) 101 | { 102 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 103 | stringBuilder.Clear(); 104 | stringBuilder.Append(Log.prefix); 105 | stringBuilder.Join(messages); 106 | UnityEngine.Debug.Log(stringBuilder); 107 | #endif 108 | } 109 | 110 | /// 111 | /// Logs a warning message to the Unity console. 112 | /// 113 | /// The message to log. 114 | public static void Warning(object message) 115 | { 116 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 117 | Warning(message, Log.prefix); 118 | #endif 119 | } 120 | 121 | /// 122 | /// Logs a warning message to the Unity console with a custom prefix. 123 | /// 124 | /// The message to log. 125 | /// The prefix of the message. 126 | public static void Warning(object message, string prefix) 127 | { 128 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 129 | stringBuilder.Clear(); 130 | 131 | if (message != null) { 132 | UnityEngine.Debug.LogWarning(stringBuilder.Append(prefix).Append(message)); 133 | } else { 134 | UnityEngine.Debug.LogWarning(stringBuilder.Append(prefix).Append(Log.nullReference)); 135 | } 136 | #endif 137 | } 138 | 139 | /// 140 | /// Logs a warning message to the Unity console under a given context. 141 | /// 142 | /// The message to log. 143 | /// The context of the message. 144 | public static void Warning(object message, UnityEngine.Object context) 145 | { 146 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 147 | Warning(message, Log.prefix, context); 148 | #endif 149 | } 150 | 151 | /// 152 | /// Logs a warning message to the Unity console with a custom prefix 153 | /// under a given context. 154 | /// 155 | /// The message to log. 156 | /// The prefix of the message. 157 | /// The context of the message. 158 | public static void Warning(object message, string prefix, UnityEngine.Object context) 159 | { 160 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 161 | stringBuilder.Clear(); 162 | 163 | if (message != null) { 164 | UnityEngine.Debug.LogWarning(stringBuilder.Append(prefix).Append(message), context); 165 | } else { 166 | UnityEngine.Debug.LogWarning(stringBuilder.Append(prefix).Append(Log.nullReference), context); 167 | } 168 | #endif 169 | } 170 | 171 | /// 172 | /// Logs multiple warning messages as a single message to the Unity 173 | /// console. 174 | /// 175 | /// The messages to log. 176 | public static void Warning(params object[] messages) 177 | { 178 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 179 | stringBuilder.Clear(); 180 | stringBuilder.Append(Log.prefix); 181 | stringBuilder.Join(messages); 182 | UnityEngine.Debug.LogWarning(stringBuilder); 183 | #endif 184 | } 185 | 186 | /// 187 | /// Logs an error message to the Unity console. 188 | /// 189 | /// The message to log. 190 | public static void Error(object message) 191 | { 192 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 193 | Error(message, Log.prefix); 194 | #endif 195 | } 196 | 197 | /// 198 | /// Logs an error message to the Unity console with a custom prefix. 199 | /// 200 | /// The message to log. 201 | /// The prefix of the message. 202 | public static void Error(object message, string prefix) 203 | { 204 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 205 | stringBuilder.Clear(); 206 | 207 | if (message != null) { 208 | UnityEngine.Debug.LogError(stringBuilder.Append(prefix).Append(message)); 209 | } else { 210 | UnityEngine.Debug.LogError(stringBuilder.Append(prefix).Append(Log.nullReference)); 211 | } 212 | #endif 213 | } 214 | 215 | /// 216 | /// Logs an error message to the Unity console under a given context. 217 | /// 218 | /// The message to log. 219 | /// The context of the message. 220 | public static void Error(object message, UnityEngine.Object context) 221 | { 222 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 223 | Error(message, Log.prefix, context); 224 | #endif 225 | } 226 | 227 | /// 228 | /// Logs an error message to the Unity console with a custom prefix 229 | /// under a given context. 230 | /// 231 | /// The message to log. 232 | /// The prefix of the message. 233 | /// The context of the message. 234 | public static void Error(object message, string prefix, UnityEngine.Object context) 235 | { 236 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 237 | stringBuilder.Clear(); 238 | 239 | if (message != null) { 240 | UnityEngine.Debug.LogError(stringBuilder.Append(prefix).Append(message), context); 241 | } else { 242 | UnityEngine.Debug.LogError(stringBuilder.Append(prefix).Append(Log.nullReference), context); 243 | } 244 | #endif 245 | } 246 | 247 | /// 248 | /// Logs multiple error messages as a single message to the Unity 249 | /// console. 250 | /// 251 | /// The messages to log. 252 | public static void Error(params object[] messages) 253 | { 254 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 255 | stringBuilder.Clear(); 256 | stringBuilder.Append(Log.prefix); 257 | stringBuilder.Join(messages); 258 | UnityEngine.Debug.LogError(stringBuilder); 259 | #endif 260 | } 261 | 262 | /// 263 | /// Logs an assertion message to the Unity console. 264 | /// 265 | /// The message to log. 266 | public static void Assertion(object message) 267 | { 268 | #if UNITY_ASSERTIONS && (UNITY_EDITOR || DEVELOPMENT_BUILD) 269 | Assertion(message, Log.prefix); 270 | #endif 271 | } 272 | 273 | /// 274 | /// Logs an assertion message to the Unity console with a custom prefix. 275 | /// 276 | /// The message to log. 277 | /// The prefix of the message. 278 | public static void Assertion(object message, string prefix) 279 | { 280 | #if UNITY_ASSERTIONS && (UNITY_EDITOR || DEVELOPMENT_BUILD) 281 | stringBuilder.Clear(); 282 | 283 | if (message != null) { 284 | UnityEngine.Debug.LogAssertion(stringBuilder.Append(prefix).Append(message)); 285 | } else { 286 | UnityEngine.Debug.LogAssertion(stringBuilder.Append(prefix).Append(Log.nullReference)); 287 | } 288 | #endif 289 | } 290 | 291 | /// 292 | /// Logs an assertion message to the Unity console under a given context. 293 | /// 294 | /// The message to log. 295 | /// The context of the message. 296 | public static void Assertion(object message, UnityEngine.Object context) 297 | { 298 | #if UNITY_ASSERTIONS && (UNITY_EDITOR || DEVELOPMENT_BUILD) 299 | Assertion(message, Log.prefix, context); 300 | #endif 301 | } 302 | 303 | /// 304 | /// Logs an assertion message to the Unity console with a custom prefix 305 | /// under a given context. 306 | /// 307 | /// The message to log. 308 | /// The prefix of the message. 309 | /// The context of the message. 310 | public static void Assertion(object message, string prefix, UnityEngine.Object context) 311 | { 312 | #if UNITY_ASSERTIONS && (UNITY_EDITOR || DEVELOPMENT_BUILD) 313 | stringBuilder.Clear(); 314 | 315 | if (message != null) { 316 | UnityEngine.Debug.LogAssertion(stringBuilder.Append(prefix).Append(message), context); 317 | } else { 318 | UnityEngine.Debug.LogAssertion(stringBuilder.Append(prefix).Append(Log.nullReference), context); 319 | } 320 | #endif 321 | } 322 | 323 | /// 324 | /// Logs multiple assertion messages as a single message to the Unity 325 | /// console. 326 | /// 327 | /// The messages to log. 328 | public static void Assertion(params object[] messages) 329 | { 330 | #if UNITY_ASSERTIONS && (UNITY_EDITOR || DEVELOPMENT_BUILD) 331 | stringBuilder.Clear(); 332 | stringBuilder.Append(Log.prefix); 333 | stringBuilder.Join(messages); 334 | UnityEngine.Debug.LogAssertion(stringBuilder); 335 | #endif 336 | } 337 | 338 | /// 339 | /// Joins multiple messages into a single message. 340 | /// 341 | private static void Join(this StringBuilder stringBuilder, object[] messages) 342 | { 343 | #if UNITY_EDITOR || DEVELOPMENT_BUILD 344 | if (messages == null) 345 | { 346 | stringBuilder.Append(Log.nullReference); 347 | return; 348 | } 349 | 350 | for (int i = 0; i < messages.Length - 1; i++) 351 | { 352 | object message = messages[i]; 353 | 354 | if (message != null) { 355 | stringBuilder.Append(message).Append(Log.delimiter); 356 | } else { 357 | stringBuilder.Append(Log.nullReference).Append(Log.delimiter); 358 | } 359 | } 360 | 361 | if (messages.Length > 0) 362 | { 363 | object lastMessage = messages[messages.Length - 1]; 364 | 365 | if (lastMessage != null) { 366 | stringBuilder.Append(lastMessage); 367 | } else { 368 | stringBuilder.Append(Log.nullReference); 369 | } 370 | } 371 | #endif 372 | } 373 | 374 | } 375 | 376 | } 377 | -------------------------------------------------------------------------------- /Runtime/Log.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 496fc10cdafb1414aacbbdcc0deb673e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/PauseApplication.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using UnityEditor; 3 | #endif 4 | using UnityEngine; 5 | #if ENABLE_INPUT_SYSTEM 6 | using UnityEngine.InputSystem; 7 | #endif 8 | 9 | namespace Zigurous.Debug 10 | { 11 | /// 12 | /// Pauses the application via user input. 13 | /// 14 | [AddComponentMenu("Zigurous/Debug/Pause Application")] 15 | [HelpURL("https://docs.zigurous.com/com.zigurous.debug/api/Zigurous.Debug/PauseApplication")] 16 | public sealed class PauseApplication : MonoBehaviour 17 | { 18 | #if ENABLE_INPUT_SYSTEM 19 | /// 20 | /// The input action that pauses the application. 21 | /// 22 | [Tooltip("The input action that pauses the application.")] 23 | [Header("Input System")] 24 | public InputAction pauseInput = new InputAction("PauseApplication", InputActionType.Button, "/pause"); 25 | #endif 26 | 27 | #if ENABLE_LEGACY_INPUT_MANAGER 28 | /// 29 | /// The keycode that pauses the application. 30 | /// 31 | [Tooltip("The keycode that pauses the application.")] 32 | [Header("Legacy Input Manager")] 33 | public KeyCode pauseKey = KeyCode.Break; 34 | 35 | /// 36 | /// The optional modifier key to be held down to pause the application. 37 | /// 38 | [Tooltip("The optional modifier key to be held down to pause the application.")] 39 | public KeyCode pauseKeyModifier = KeyCode.None; 40 | #endif 41 | 42 | /// 43 | /// Whether the application is currently paused or not (Read only). 44 | /// 45 | #if UNITY_EDITOR 46 | public bool paused => EditorApplication.isPaused; 47 | #else 48 | public bool paused { get; private set; } 49 | #endif 50 | 51 | #if ENABLE_INPUT_SYSTEM 52 | private void Awake() 53 | { 54 | pauseInput.performed += OnPause; 55 | } 56 | 57 | private void OnDestroy() 58 | { 59 | pauseInput.Dispose(); 60 | } 61 | 62 | private void OnEnable() 63 | { 64 | pauseInput.Enable(); 65 | } 66 | 67 | private void OnDisable() 68 | { 69 | pauseInput.Disable(); 70 | } 71 | 72 | private void OnPause(InputAction.CallbackContext context) 73 | { 74 | if (context.performed) 75 | { 76 | if (paused) { 77 | Resume(); 78 | } else { 79 | Pause(); 80 | } 81 | } 82 | } 83 | #endif 84 | 85 | #if ENABLE_LEGACY_INPUT_MANAGER 86 | private void Update() 87 | { 88 | if (Input.GetKeyDown(pauseKey)) 89 | { 90 | if (pauseKeyModifier == KeyCode.None || Input.GetKey(pauseKeyModifier)) 91 | { 92 | if (paused) { 93 | Resume(); 94 | } else { 95 | Pause(); 96 | } 97 | } 98 | } 99 | } 100 | #endif 101 | 102 | /// 103 | /// Pauses the application. 104 | /// 105 | public void Pause() 106 | { 107 | #if UNITY_EDITOR 108 | EditorApplication.isPaused = true; 109 | #else 110 | paused = true; 111 | Time.timeScale = 0f; 112 | #endif 113 | } 114 | 115 | /// 116 | /// Resumes the application. 117 | /// 118 | public void Resume() 119 | { 120 | #if UNITY_EDITOR 121 | EditorApplication.isPaused = false; 122 | #else 123 | paused = false; 124 | Time.timeScale = 1f; 125 | #endif 126 | } 127 | 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /Runtime/PauseApplication.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 92cd4baf56dcd7e4685a19dd2431a35f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Zigurous.Debug.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Zigurous.Debug", 3 | "references": [ 4 | "GUID:75469ad4d38634e559750d17036d5f7c" 5 | ], 6 | "includePlatforms": [], 7 | "excludePlatforms": [], 8 | "allowUnsafeCode": false, 9 | "overrideReferences": false, 10 | "precompiledReferences": [], 11 | "autoReferenced": true, 12 | "defineConstraints": [], 13 | "versionDefines": [], 14 | "noEngineReferences": false 15 | } -------------------------------------------------------------------------------- /Runtime/Zigurous.Debug.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0186cdaa7ccbaeb4f91d3907506784d7 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b6f41d1b8258a9438a3472d9c8282a2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/Bitangents.shader: -------------------------------------------------------------------------------- 1 | Shader "Zigurous/Debug/Bitangents" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | Fog { Mode Off } 8 | 9 | CGPROGRAM 10 | 11 | #pragma vertex vert 12 | #pragma fragment frag 13 | 14 | #include "UnityCG.cginc" 15 | 16 | struct appdata 17 | { 18 | float4 vertex : POSITION; 19 | float3 normal : NORMAL; 20 | float4 tangent : TANGENT; 21 | }; 22 | 23 | struct v2f 24 | { 25 | float4 pos : SV_POSITION; 26 | float4 color : COLOR; 27 | }; 28 | 29 | v2f vert (appdata v) 30 | { 31 | v2f o; 32 | o.pos = UnityObjectToClipPos(v.vertex); 33 | float3 bitangent = cross(v.normal, v.tangent.xyz) * v.tangent.w; 34 | o.color.xyz = bitangent * 0.5 + 0.5; 35 | o.color.w = 1.0; 36 | return o; 37 | } 38 | 39 | fixed4 frag (v2f i) : SV_Target 40 | { 41 | return i.color; 42 | } 43 | 44 | ENDCG 45 | } 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Shaders/Bitangents.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 799185a077972f94a94413ba62eea208 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Normals.shader: -------------------------------------------------------------------------------- 1 | Shader "Zigurous/Debug/Normals" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | CGPROGRAM 8 | 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | 12 | #include "UnityCG.cginc" 13 | 14 | struct appdata 15 | { 16 | float4 vertex : POSITION; 17 | float3 normal : NORMAL; 18 | }; 19 | 20 | struct v2f 21 | { 22 | float4 pos : SV_POSITION; 23 | fixed4 color : COLOR; 24 | }; 25 | 26 | v2f vert (appdata v) 27 | { 28 | v2f o; 29 | o.pos = UnityObjectToClipPos(v.vertex); 30 | o.color.xyz = v.normal * 0.5 + 0.5; 31 | o.color.w = 1.0; 32 | return o; 33 | } 34 | 35 | fixed4 frag (v2f i) : SV_Target 36 | { 37 | return i.color; 38 | } 39 | 40 | ENDCG 41 | } 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Shaders/Normals.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 128dc0c4016252441906789fa41d7e0d 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Tangents.shader: -------------------------------------------------------------------------------- 1 | Shader "Zigurous/Debug/Tangents" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | CGPROGRAM 8 | 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | 12 | #include "UnityCG.cginc" 13 | 14 | struct appdata 15 | { 16 | float4 vertex : POSITION; 17 | float4 tangent : TANGENT; 18 | }; 19 | 20 | struct v2f 21 | { 22 | float4 pos : SV_POSITION; 23 | fixed4 color : COLOR; 24 | }; 25 | 26 | v2f vert (appdata v) 27 | { 28 | v2f o; 29 | o.pos = UnityObjectToClipPos(v.vertex); 30 | o.color = v.tangent * 0.5 + 0.5; 31 | return o; 32 | } 33 | 34 | fixed4 frag (v2f i) : SV_Target 35 | { 36 | return i.color; 37 | } 38 | 39 | ENDCG 40 | } 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Shaders/Tangents.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ceb9d40400658184a94d27f3b2311566 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/UV1.shader: -------------------------------------------------------------------------------- 1 | Shader "Zigurous/Debug/UV 1" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | CGPROGRAM 8 | 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | 12 | #include "UnityCG.cginc" 13 | 14 | struct appdata 15 | { 16 | float4 vertex : POSITION; 17 | float4 texcoord : TEXCOORD0; 18 | }; 19 | 20 | struct v2f 21 | { 22 | float4 pos : SV_POSITION; 23 | float4 uv : TEXCOORD0; 24 | }; 25 | 26 | v2f vert (appdata v) 27 | { 28 | v2f o; 29 | o.pos = UnityObjectToClipPos(v.vertex); 30 | o.uv = float4(v.texcoord.xy, 0, 0); 31 | return o; 32 | } 33 | 34 | half4 frag (v2f i) : SV_Target 35 | { 36 | half4 c = frac(i.uv); 37 | if (any(saturate(i.uv) - i.uv)) { 38 | c.b = 0.5; 39 | } 40 | return c; 41 | } 42 | 43 | ENDCG 44 | } 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Shaders/UV1.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4af31441edc01314bb567e90b33b2ee7 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/UV2.shader: -------------------------------------------------------------------------------- 1 | Shader "Zigurous/Debug/UV 2" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | CGPROGRAM 8 | 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | 12 | #include "UnityCG.cginc" 13 | 14 | struct appdata 15 | { 16 | float4 vertex : POSITION; 17 | float4 texcoord1 : TEXCOORD1; 18 | }; 19 | 20 | struct v2f 21 | { 22 | float4 pos : SV_POSITION; 23 | float4 uv : TEXCOORD0; 24 | }; 25 | 26 | v2f vert (appdata v) 27 | { 28 | v2f o; 29 | o.pos = UnityObjectToClipPos(v.vertex); 30 | o.uv = float4(v.texcoord1.xy, 0, 0); 31 | return o; 32 | } 33 | 34 | half4 frag (v2f i) : SV_Target 35 | { 36 | half4 c = frac(i.uv); 37 | if (any(saturate(i.uv) - i.uv)) { 38 | c.b = 0.5; 39 | } 40 | return c; 41 | } 42 | 43 | ENDCG 44 | } 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Shaders/UV2.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b56c8bdfcdce88949ab83bafd1ecbfb6 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/VertexColor.shader: -------------------------------------------------------------------------------- 1 | Shader "Zigurous/Debug/Vertex Color" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | CGPROGRAM 8 | 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | 12 | #include "UnityCG.cginc" 13 | 14 | struct appdata 15 | { 16 | float4 vertex : POSITION; 17 | fixed4 color : COLOR; 18 | }; 19 | 20 | struct v2f 21 | { 22 | float4 pos : SV_POSITION; 23 | fixed4 color : COLOR; 24 | }; 25 | 26 | v2f vert (appdata v) 27 | { 28 | v2f o; 29 | o.pos = UnityObjectToClipPos(v.vertex); 30 | o.color = v.color; 31 | return o; 32 | } 33 | 34 | fixed4 frag (v2f i) : SV_Target 35 | { 36 | return i.color; 37 | } 38 | 39 | ENDCG 40 | } 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Shaders/VertexColor.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6d47743c9f1966046943571f10b6b632 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.zigurous.debug", 3 | "version": "1.5.0", 4 | "displayName": "Debug Tools", 5 | "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.", 6 | "unity": "2019.4", 7 | "repository": "https://github.com/zigurous/unity-debug-tools", 8 | "documentationUrl": "https://docs.zigurous.com/com.zigurous.debug", 9 | "changelogUrl": "https://docs.zigurous.com/com.zigurous.debug/changelog", 10 | "licensesUrl": "https://docs.zigurous.com/com.zigurous.debug/license", 11 | "dependencies": { 12 | "com.unity.inputsystem": "1.2.0" 13 | }, 14 | "keywords": [ 15 | "debug", 16 | "debugging", 17 | "benchmarking", 18 | "performance", 19 | "framerate", 20 | "logging", 21 | "tools", 22 | "shaders" 23 | ], 24 | "publishConfig": { 25 | "registry": "https://npm.pkg.github.com/@zigurous" 26 | }, 27 | "author": { 28 | "name": "Zigurous", 29 | "email": "support@zigurous.com", 30 | "url": "https://zigurous.com" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a422b45884abef54cab67345f73cbef4 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------