From a90292f47fb1930cb13564fa5c9f07fc74bffa33 Mon Sep 17 00:00:00 2001 From: Sinai <49360850+sinai-dev@users.noreply.github.com> Date: Sat, 19 Feb 2022 17:50:10 +1100 Subject: [PATCH] Prevent Unity crashing on PropertyInfo evaluation Unity crashes from checking Canvas.renderingDisplaySize on a Canvas set to WorldSpace with no worldCamera set. --- src/CacheObject/CacheMember.cs | 8 ++++---- src/CacheObject/CacheProperty.cs | 4 ++++ src/Inspectors/InspectorManager.cs | 8 ++++---- src/Runtime/UnityCrashPrevention.cs | 23 +++++++++++++++++++++++ src/UnityExplorer.csproj | 1 + 5 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 src/Runtime/UnityCrashPrevention.cs diff --git a/src/CacheObject/CacheMember.cs b/src/CacheObject/CacheMember.cs index 6eee8b5..65ee475 100644 --- a/src/CacheObject/CacheMember.cs +++ b/src/CacheObject/CacheMember.cs @@ -21,7 +21,7 @@ namespace UnityExplorer.CacheObject { public abstract Type DeclaringType { get; } public string NameForFiltering { get; protected set; } - public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ?? (m_declaringInstance = Owner.Target.TryCast(DeclaringType))); + public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ??= Owner.Target.TryCast(DeclaringType)); private object m_declaringInstance; public abstract bool IsStatic { get; } @@ -94,8 +94,8 @@ namespace UnityExplorer.CacheObject base.SetValueState(cell, args); } - private static readonly Color evalEnabledColor = new Color(0.15f, 0.25f, 0.15f); - private static readonly Color evalDisabledColor = new Color(0.15f, 0.15f, 0.15f); + private static readonly Color evalEnabledColor = new(0.15f, 0.25f, 0.15f); + private static readonly Color evalDisabledColor = new(0.15f, 0.15f, 0.15f); protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell) { @@ -242,7 +242,7 @@ namespace UnityExplorer.CacheObject var sig = GetSig(member); - //ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})"); + // ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})"); CacheMember cached; Type returnType; diff --git a/src/CacheObject/CacheProperty.cs b/src/CacheObject/CacheProperty.cs index 5f3cea9..d4ed940 100644 --- a/src/CacheObject/CacheProperty.cs +++ b/src/CacheObject/CacheProperty.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using UnityEngine; using UnityExplorer.Inspectors; +using UnityExplorer.Runtime; namespace UnityExplorer.CacheObject { @@ -28,6 +30,8 @@ namespace UnityExplorer.CacheObject { try { + UnityCrashPrevention.CheckPropertyInfoEvaluation(this); + object ret; if (HasArguments) ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments()); diff --git a/src/Inspectors/InspectorManager.cs b/src/Inspectors/InspectorManager.cs index 97b878d..3eacacf 100644 --- a/src/Inspectors/InspectorManager.cs +++ b/src/Inspectors/InspectorManager.cs @@ -18,7 +18,7 @@ namespace UnityExplorer { public static class InspectorManager { - public static readonly List Inspectors = new List(); + public static readonly List Inspectors = new(); public static InspectorBase ActiveInspector { get; private set; } private static InspectorBase lastActiveInspector; @@ -94,17 +94,17 @@ namespace UnityExplorer } private static void CreateInspector(object target, bool staticReflection = false, - CacheObjectBase sourceCache = null) where T : InspectorBase + CacheObjectBase parentObject = null) where T : InspectorBase { var inspector = Pool.Borrow(); Inspectors.Add(inspector); inspector.Target = target; - if (sourceCache != null && sourceCache.CanWrite) + if (parentObject != null && parentObject.CanWrite) { // only set parent cache object if we are inspecting a struct, otherwise there is no point. if (target.GetType().IsValueType && inspector is ReflectionInspector ri) - ri.ParentCacheObject = sourceCache; + ri.ParentCacheObject = parentObject; } UIManager.SetPanelActive(UIManager.Panels.Inspector, true); diff --git a/src/Runtime/UnityCrashPrevention.cs b/src/Runtime/UnityCrashPrevention.cs new file mode 100644 index 0000000..2ed142a --- /dev/null +++ b/src/Runtime/UnityCrashPrevention.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using UnityExplorer.CacheObject; + +namespace UnityExplorer.Runtime +{ + public static class UnityCrashPrevention + { + public static void CheckPropertyInfoEvaluation(CacheProperty cacheProp) + { + if (cacheProp.PropertyInfo.Name == "renderingDisplaySize" + && cacheProp.Owner.Target is Canvas canvas + && canvas.renderMode == RenderMode.WorldSpace + && !canvas.worldCamera) + { + throw new Exception("Canvas is set to RenderMode.WorldSpace but has no worldCamera, cannot get value."); + } + } + } +} diff --git a/src/UnityExplorer.csproj b/src/UnityExplorer.csproj index 57eb7df..1711686 100644 --- a/src/UnityExplorer.csproj +++ b/src/UnityExplorer.csproj @@ -259,6 +259,7 @@ +