Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring and fixing of HeapExplorer #12

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

arturaz
Copy link

@arturaz arturaz commented Jan 21, 2023

Hi there.

First of all, let me express how much I am thankful for the work you have put into the HeapExplorer. I had to find out a memory leak recently and it is astonishing how bad the Unity Memory Profiler is at telling the reason of why an object is pinned in the memory. And that's 5 years after its announcement!

HeapExplorer helped me to track down several leaks, but then I noticed that I still had an object lingering (as evidenced both by debug code and Unity Memory Profiler) which your tool did not see. That meant that HeapExplorer has a bug, which I decided to track down.

HeapExplorer seems to have been written pre-modern Unity/C# days, so in process of understanding how it works I changed a lot of code. The changed code uses a bit different coding paradigms, uses newer C# version and is large, which I know is a lot to take in in a pull request. But I do believe it is a change for the better and I hope you will merge this into the main codebase.

If you decide that you don't want that, I would be grateful if you pointed out to the existence of this fork in your main repository README.md for the users.

As always, if you have any questions you can ping me at Discord (arturaz#1619) for rapid information exchange. I am more than glad to help understand any of the things I have changed, even though I did my best to document everything in code.

Here's a full list of things that were changed.

  • Introduced the Option<A> type to represent values that might not be there.

    • Replaced values representing failure (like -1) with Option to indicate the possibility of failure.
  • Replaced possibly-invalid types with Options. Now if you if have an instance - it's guaranteed to be valid.

  • Replaced magic values (like using positive integers for managed object indexes and negative integers for static object indexes) with proper semantic types to help with code clarity.

  • Replaced dangerous numeric casts that could under/overflow with typesafe alternatives (PInt positive 32bit integer type) that guarantee no such things can happen.

  • Replaced instances of List which were being used as stacks with Stack.

  • Replaced as many fields in objects as possible with readonly ones to indicate that we have no intent of changing them after the object is constructed. This is a part of 'objects should stay valid after construction' philosophy.

  • Added logging for potentially dangerous operations (like int -> uint).

  • Replaced primitive loop guards with cycle tracking that tracks seen objects. This eliminates the false positives and errors out sooner if we actually have an error.

  • Replaced places where things got cancelled silently with emitting warnings / errors. Failures should never be silent.

  • Fixed algorithm that checks if a type contains reference types: it didn't account for nested value-types which eventually have reference types in them and only looked for reference types in the first level.

  • Fixed bad lookups in PackedCoreTypes. Also made PackedCoreTypes to be fully initialized, without any missing entries.

  • Added a warning about the inability to crawl the [ThreadStatic] variables.

HeapExplorer: Detected following fields as [ThreadStatic] static fields. We do not know how to determine the memory location of these fields, thus we can not crawl them. Take that in mind:
Field[index=7144, name=indentLevel, static=True, offset=-1, managedTypesArrayIndex=32124]
@ [assembly 'mscorlib'] [type 'System.Int32']

Field[index=7651, name=ts_slotArray, static=True, offset=-1, managedTypesArrayIndex=16744]
@ [assembly 'mscorlib'] [type 'System.Threading.ThreadLocal.LinkedSlotVolatile<System.Collections.Concurrent.ConcurrentBag.WorkStealingQueue<Sentry.Extensibility.ISentryEventProcessor>>[]']
  • Improved search speed by:

    • caching search results.
    • downcasing everything before the search and then using fast ordinal string comparisons instead of slower OrdinalIgnoreCase comparisons.
  • Improved documentation by adding new docstrings and converting existing docstrings into proper XMLDocs. Now IDEs and tools can properly render the documentation.

  • Rewrote a part of code using C# 7.3 (supported since Unity 2019) to enhance readability.

  • bumped version to 4.1.2

  • Added capability to copy the root path as text by right-clicking on the root entry in "Find GC roots" window.

Example:

Static fields are global variables. Anything they reference will not be unloaded.

[0] StaticField, Name: s_Instance, In Type: TMPro.TMP_Settings, Of Type: TMPro.TMP_Settings
Source Field: 's_Instance' of type 'TMPro.TMP_Settings'

[1] Managed, Addr: 0x27E7D474A80, Type: TMPro.TMP_Settings
Source Field: 'm_defaultFontAsset' of type 'TMPro.TMP_FontAsset'

[2] Managed, Addr: 0x27E7C21DA80, Type: TMPro.TMP_FontAsset
Source Field: 'm_KerningTable' of type 'TMPro.KerningTable'

[3] Managed, Addr: 0x27E7BF02C60, Type: TMPro.KerningTable
Source Field: 'kerningPairs' of type 'System.Collections.Generic.List<TMPro.KerningPair>'

[4] Managed, Addr: 0x27E7C24FA80, Type: System.Collections.Generic.List<TMPro.KerningPair>
Source Field: '_items' of type 'TMPro.KerningPair[]'

[5] Managed, Addr: 0x27E7C150B70, Type: TMPro.KerningPair[]
  • Added information about source fields that are pointing to the object in "Find GC roots" window.

image

  • Added progress reporting to Unity when a memory snapshot is being converted from the Unity format to our format.

* Introduced the `Option<A>` type to represent values that might not be there.
  * Replaced values representing failure (like `-1`) with `Option` to indicate the possibility of failure.

* Replaced possibly-invalid types with `Option`s. Now if you if have an instance - it's guaranteed to be valid.

* Replaced magic values (like using positive integers for managed object indexes and negative integers for static object indexes) with proper semantic types to help with code clarity.

* Replaced dangerous numeric casts that could under/overflow with typesafe alternatives (`PInt` positive 32bit integer type) that guarantee no such things can happen.

* Replaced instances of `List` which were being used as stacks with `Stack`.

* Replaced as many fields in objects as possible with readonly ones to indicate that we have no intent of changing them after the object is constructed. This is a part of 'objects should stay valid after construction' philosophy.

* Added logging for potentially dangerous operations (like int -> uint).

* Replaced primitive loop guards with cycle tracking that tracks seen objects. This eliminates the false positives and errors out sooner if we actually have an error.

* Replaced places where things got cancelled silently with emitting warnings / errors. Failures should never be silent.

* Fixed algorithm that checks if a type contains reference types: it didn't account for nested value-types which eventually have reference types in them and only looked for reference types in the first level.

* Fixed bad lookups in `PackedCoreTypes`. Also made `PackedCoreTypes` to be fully initialized, without any missing entries.

* Added a warning about the inability to crawl the `[ThreadStatic]` variables.

* Improved search speed by:
  * caching search results.
  * downcasing everything before the search and then using fast ordinal string comparisons instead of slower `OrdinalIgnoreCase` comparisons.

* Improved documentation by adding new docstrings and converting existing docstrings into proper XMLDocs. Now IDEs and tools can properly render the documentation.

* Rewrote a part of code using C# 7.3 (supported since Unity 2019) to enhance readability.

* bumped version to 4.1.2

* Added capability to copy the root path as text in "Find GC roots" window.

* Added information about source fields that are pointing to the object in "Find GC roots" window.

* Added progress reporting to Unity when a memory snapshot is being converted from the Unity format to our format.
@pschraut
Copy link
Owner

Thank you for the time and effort you put into Heap Explorer to improve it and of course for the PR. The changes look really useful, but it will take me a while to go over all of this, because as you wrote, it's a massive change-set.

@pschraut
Copy link
Owner

On a brief inspection, I found two things that no longer work:

  1. The Heap Explorer tests have compile errors. When you add HEAPEXPLORER_ENABLE_TESTS to the Scripting Symbols under Player Settings, you'll see those errors.

  2. Existing memory snapshots cannot be read anymore. Upon loading an "old" snapshot, an ArgumentOutOfRangeException is thrown:

ArgumentOutOfRangeException: value can't be negative
Parameter name: value
Actual value was -1.
HeapExplorer.Utilities.PInt.createOrThrow (System.Int32 value) (at Assets/UnityHeapExplorer/Editor/Scripts/Utilities/PInt.cs:51)
HeapExplorer.PackedManagedField.Read (System.IO.BinaryReader reader) (at Assets/UnityHeapExplorer/Editor/Scripts/PackedTypes/PackedManagedField.cs:83)
HeapExplorer.PackedManagedField.Read (System.IO.BinaryReader reader, HeapExplorer.PackedManagedField[]& value) (at Assets/UnityHeapExplorer/Editor/Scripts/PackedTypes/PackedManagedField.cs:76)
HeapExplorer.PackedManagedType.Read (System.IO.BinaryReader reader, HeapExplorer.PackedManagedType[]& value, System.String& stateString) (at Assets/UnityHeapExplorer/Editor/Scripts/PackedTypes/PackedManagedType.cs:411)
HeapExplorer.PackedMemorySnapshot.LoadFromFile (System.String filePath) (at Assets/UnityHeapExplorer/Editor/Scripts/PackedTypes/PackedMemorySnapshot.cs:157)

Can you fix these issues?

The old data files contain fields serialized with `-1` offsets. We know these are invalid and should be skipped during reading.
@arturaz
Copy link
Author

arturaz commented Jan 22, 2023

Hey there. Fixed the things you requested.

@arturaz
Copy link
Author

arturaz commented Jan 23, 2023

By the way, if you see this pattern:

{if (someOption.valueOut(out var someValue)) {
  // code goes here.
}}

Then the extra curly braces are to prevent the someValue leaking out into outer scope and being accidentally used with an invalid value. It's not the most pretty thing, but it's the best you can do with C#, unfortunately. The alternative is to write a custom Enumerator for Option<A> so it could be used in foreach statements, but that has slightly worse performance because you have to invoke MoveNext() on the enumerator twice.

@pschraut
Copy link
Owner

Thank you for the fixes. I'm most likely going to take a look at it over the course of the weekend.

…ng read for non-array types.

Now instead of having `bool isArray` and `PInt arrayRank` we have one field `Option<PInt> arrayRank` which makes sure we are not capable of representing the illegal state.
@pschraut
Copy link
Owner

pschraut commented Feb 5, 2023

Trying to open the latest changes from this PR in Unity 2020.3.38f1 (.NET Standard 2.0) shows the following compile errors:

Assets\UnityHeapExplorer\Editor\Scripts\Utilities\Either.cs(3,33): error CS1514: { expected
Assets\UnityHeapExplorer\Editor\Scripts\Utilities\Either.cs(38,2): error CS1513: } expected
Assets\UnityHeapExplorer\Editor\Scripts\Utilities\Unit.cs(1,33): error CS1514: { expected
Assets\UnityHeapExplorer\Editor\Scripts\Utilities\Unit.cs(8,2): error CS1513: } expected

Can you fix these compile errors and make sure it runs in Unity 2020.3?

@arturaz
Copy link
Author

arturaz commented Feb 12, 2023

Whoops, that fell through :) Fixed!

@pschraut
Copy link
Owner

Thank you for the fixes.

I tested your recent changes. Unfortunately there are compile errors in the Heap Explorer tests. When you add HEAPEXPLORER_ENABLE_TESTS to the Scripting Symbols under Player Settings, you'll see those errors. I'm testing with Unity 2020.3.38f1.

Can you fix the compile errors?

@arturaz
Copy link
Author

arturaz commented Feb 28, 2023

Fixed it. For real this time. Sorry about the previous ones. I checked out the package with Unity 2019.4.40f1 and made sure it compiles and the tests pass.

image

@JonnyOThan
Copy link

Hi! I merged this PR on top of the current head: https://github.com/JonnyOThan/UnityHeapExplorer

The referencing field info is fantastic! But I'm sometimes seeing issues where clicking on empty shell objects does not display their fields. There are a few errors from the log as well:

HeapExplorer: address 0 should not be accessed!
UnityEngine.Debug:LogError(Object)
HeapExplorer.Utilities.Utils:zeroAddressAccessError(String) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/Utilities/Utils.cs:12)
HeapExplorer.MemoryReader:TryBeginRead(UInt64) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/MemoryReader.cs:30)
HeapExplorer.AbstractMemoryReader:ReadUInt64(UInt64) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/MemoryReader.cs:247)
HeapExplorer.AbstractMemoryReader:ReadPointer(UInt64) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/MemoryReader.cs:250)
HeapExplorer.ArrayPropertyGridItem:OnInitialize() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/ArrayPropertyGridItem.cs:23)
HeapExplorer.PropertyGridItem:Initialize() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridItem.cs:67)
HeapExplorer.PropertyGridControl:AddType(BuildChildrenArgs) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridControl.cs:289)
HeapExplorer.PropertyGridControl:Inspect(PackedMemorySnapshot, PackedManagedObject) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridControl.cs:85)
HeapExplorer.PropertyGridView:Inspect(PackedManagedObject) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridView.cs:79)
HeapExplorer.AbstractManagedObjectsView:OnListViewSelectionChange(Nullable`1) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedObjectsView/ManagedObjectsView.cs:295)
HeapExplorer.AbstractManagedObjectsControl:OnSelectionChanged(TreeViewItem) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedObjectsView/ManagedObjectsControl.cs:116)
HeapExplorer.AbstractTreeView:SelectionChanged(IList`1) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/AbstractTreeView.cs:274)
UnityEditor.IMGUI.Controls.TreeView:OnGUI(Rect)
HeapExplorer.AbstractTreeView:OnGUI() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/AbstractTreeView.cs:198)
HeapExplorer.AbstractManagedObjectsView:OnGUI() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedObjectsView/ManagedObjectsView.cs:319)
HeapExplorer.ManagedEmptyShellObjectsView:OnGUI() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedEmptyShellObjectsView/ManagedEmptyShellObjectsView.cs:54)
HeapExplorer.HeapExplorerWindow:DrawView() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/HeapExplorerWindow.cs:450)
HeapExplorer.HeapExplorerWindow:OnGUI() (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/HeapExplorerWindow.cs:361)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
Exception: Expected Option<System.UInt64> to be `Some` but it was `None`
HeapExplorer.Utilities.Option`1[A].getOrThrow (System.String message) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/Utilities/Option.cs:52)
HeapExplorer.ArrayPropertyGridItem.OnInitialize () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/ArrayPropertyGridItem.cs:23)
HeapExplorer.PropertyGridItem.Initialize () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridItem.cs:67)
HeapExplorer.PropertyGridControl.AddType (HeapExplorer.PropertyGridItem+BuildChildrenArgs args) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridControl.cs:289)
HeapExplorer.PropertyGridControl.Inspect (HeapExplorer.PackedMemorySnapshot snapshot, HeapExplorer.PackedManagedObject managedObject) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridControl.cs:85)
HeapExplorer.PropertyGridView.Inspect (HeapExplorer.PackedManagedObject managedObject) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/PropertyGrid/PropertyGridView.cs:79)
HeapExplorer.AbstractManagedObjectsView.OnListViewSelectionChange (System.Nullable`1[T] item) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedObjectsView/ManagedObjectsView.cs:295)
HeapExplorer.AbstractManagedObjectsControl.OnSelectionChanged (UnityEditor.IMGUI.Controls.TreeViewItem selectedItem) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedObjectsView/ManagedObjectsControl.cs:116)
HeapExplorer.AbstractTreeView.SelectionChanged (System.Collections.Generic.IList`1[T] selectedIds) (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/AbstractTreeView.cs:274)
UnityEditor.IMGUI.Controls.TreeViewController.NotifyListenersThatSelectionChanged () (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeViewController.NewSelectionFromUserInteraction (System.Collections.Generic.List`1[T] newSelection, System.Int32 itemID) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeViewController.SelectionClick (UnityEditor.IMGUI.Controls.TreeViewItem itemClicked, System.Boolean keepMultiSelection) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeViewController.HandleUnusedMouseEventsForItem (UnityEngine.Rect rect, UnityEditor.IMGUI.Controls.TreeViewItem item, System.Int32 row) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeViewController.DoItemGUI (UnityEditor.IMGUI.Controls.TreeViewItem item, System.Int32 row, System.Single rowWidth, System.Boolean hasFocus) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeViewController.IterateVisibleItems (System.Int32 firstRow, System.Int32 numVisibleRows, System.Single rowWidth, System.Boolean hasFocus) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeViewController.OnGUI (UnityEngine.Rect rect, System.Int32 keyboardControlID) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeView.TreeViewWithMultiColumnHeader (UnityEngine.Rect rect) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.IMGUI.Controls.TreeView.OnGUI (UnityEngine.Rect rect) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
HeapExplorer.AbstractTreeView.OnGUI () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/AbstractTreeView.cs:198)
HeapExplorer.AbstractManagedObjectsView.OnGUI () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedObjectsView/ManagedObjectsView.cs:319)
HeapExplorer.ManagedEmptyShellObjectsView.OnGUI () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/ManagedEmptyShellObjectsView/ManagedEmptyShellObjectsView.cs:54)
HeapExplorer.HeapExplorerWindow.DrawView () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/HeapExplorerWindow.cs:450)
HeapExplorer.HeapExplorerWindow.OnGUI () (at Library/PackageCache/com.oddworm.heapexplorer@c844e73a29/Editor/Scripts/HeapExplorerWindow.cs:361)
System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <9577ac7a62ef43179789031239ba8798>:0)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <9577ac7a62ef43179789031239ba8798>:0)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <9577ac7a62ef43179789031239ba8798>:0)
UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.HostView.Invoke (System.String methodName) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition, UnityEngine.Rect viewRect) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.DockArea.DrawView (UnityEngine.Rect viewRect, UnityEngine.Rect dockAreaRect) (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEditor.DockArea.OldOnGUI () (at <afa5b9a1793446ff98b741dc036c4c6e>:0)
UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, UnityEngine.Matrix4x4 worldTransform, UnityEngine.Rect clippingRect, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Boolean canAffectFocus) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUI (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.IMGUIContainer.HandleEvent (UnityEngine.UIElements.EventBase evt) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatchUtilities.PropagateEvent (UnityEngine.UIElements.EventBase evt) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.MouseEventDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcher.ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, System.Boolean imguiEventIsInitiallyUsed) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEventQueue () (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcher.OpenGate () (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcherGate.Dispose () (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.EventDispatcher.Dispatch (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, UnityEngine.UIElements.DispatchMode dispatchMode) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.BaseVisualElementPanel.SendEvent (UnityEngine.UIElements.EventBase e, UnityEngine.UIElements.DispatchMode dispatchMode) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.UIElementsUtility.DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel panel) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.UIElements.UIElementsUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at <06214b245dbb4d10a9cefd10639bb04e>:0)
UnityEngine.GUIUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at <fe7ee1881b524b0d9443f74417fb598b>:0)

@arturaz
Copy link
Author

arturaz commented Jul 3, 2024

I feel it's worth mentioning I have quit game development as a field. I am still available to answer any questions that anyone could have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants