-
Notifications
You must be signed in to change notification settings - Fork 413
Lots of NullReferenceException in Unity 5.2.0f3 (doesn't work) #8
Comments
Hi, thanks for that report. From what I can tell, the error appeared for you as a type I fetched using reflection from Unity is null. That's a very complex and weird situation, as the class UnityEngine.GUIClip is not even showing up in the Assembly browser (though searching for it results in that class existing). I implemented it in that version to allow for grouped scaling. If you won't miss this feature, commenting out the contents of the functions BeginNoClip, MoveClipsUp and RestoreClips in GUIScalUtility should fix the error. But I would prefer if we could sort that out:) |
Forget about the Unity version - didn't read your header too closely;) I'm using the same version, I've no idea what could cause this. Afaik reflection works on every system the same. |
Reflection works fine: GetTopRect is found (!= null), it is static and gets no arguments. The NullReferenceException is being thrown somewhere inside of the GetTopRect call, that's the point. Brand new project, Unity 5.2.0f3, Mac OS X El Capitan, reproduced stably. |
Hm, then it's, as you said, inside the call which we have no control over. Try a random reflection call, if you know about reflection Thanks! |
Hm InspectType seems to be broken.... using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using System.Collections;
public class NodeEditorReflectionTest : EditorWindow
{
[MenuItem ("Window/NodeEditor Reflection Test")]
public static void Create ()
{
EditorWindow.GetWindow<NodeEditorReflectionTest> ();
}
public void OnGUI ()
{
GUIScaleUtility.Init ();
if (GUILayout.Button ("GUILayoutUtulity.s_SpaceStyle / Random Reflection Stuff"))
{
Assembly UnityEngine = Assembly.GetAssembly (typeof (UnityEngine.GUI));
Type GUILayoutUtilityType = UnityEngine.GetType ("UnityEngine.GUILayoutUtility");
FieldInfo spaceStyle = GUILayoutUtilityType.GetField ("s_SpaceStyle", BindingFlags.Static | BindingFlags.NonPublic);
GUIStyle s_SpaceStyle = (GUIStyle)spaceStyle.GetValue (null);
Debug.Log ("Test finished, private GUIStyle '" + s_SpaceStyle.name + "' received");
}
if (GUILayout.Button ("GUIClip.getTopRect / Error Problem"))
{
Rect topRect = GUIScaleUtility.getTopRect;
Debug.Log ("Test finished, topRect " + topRect.ToString () + " received");
}
if (GUILayout.Button ("GUIClip.getTopRectScreenSpace / Potential Error Problem"))
{
Rect topRectScreenSpace = GUIScaleUtility.getTopRectScreenSpace;
Debug.Log ("Test finished, topRectScreenSpace " + topRectScreenSpace.ToString () + " received");
}
if (GUILayout.Button ("Inspect GUIClip"))
{
InspectType ("UnityEngine", "UnityEngine.GUIClip");
}
}
public static void InspectType (string assemblyName, string typeName)
{
Assembly UnityEngine = Assembly.Load (assemblyName);
Type type = UnityEngine.GetType (typeName);
foreach (MemberInfo member in type.GetMembers ())
{
Debug.Log (member.MemberType.ToString () + ": " + member.ToString ());
}
}
} Make sure you have Node_Editor inside the project. |
My guess: the problem is inside of the Unity window/clip management logic in different operating systems (GetTopRect can be required to be called in specific moments). It is always a risk that when you use undocumented functionality, it may work unexpectedly. It is even more problematic with updates (Unity will not try to keep compatibility of such stuff). |
Yes, I'll need to keep an eye on the updates to keep it supported. I took your guess and updated the window. Just click the 'Start GUIClip.getTopRect complete test' button and cause as many event types as you can;) Each type will only be checked once. Please send me the output again:) using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using System.Collections.Generic;
public class NodeEditorReflectionTest : EditorWindow
{
[MenuItem ("Window/NodeEditor Reflection Test")]
public static void Create ()
{
EditorWindow.GetWindow<NodeEditorReflectionTest> ();
}
public bool performTest = false;
public List<EventType> checkedTypes = new List<EventType> ();
public void OnGUI ()
{
GUIScaleUtility.Init ();
if (GUILayout.Button ("GUILayoutUtulity.s_SpaceStyle / Random Reflection Stuff"))
{
Assembly UnityEngine = Assembly.GetAssembly (typeof (UnityEngine.GUI));
Type GUILayoutUtilityType = UnityEngine.GetType ("UnityEngine.GUILayoutUtility");
FieldInfo spaceStyle = GUILayoutUtilityType.GetField ("s_SpaceStyle", BindingFlags.Static | BindingFlags.NonPublic);
GUIStyle s_SpaceStyle = (GUIStyle)spaceStyle.GetValue (null);
Debug.Log ("Test finished, private GUIStyle '" + s_SpaceStyle.name + "' received");
}
if (GUILayout.Button ("GUIClip.getTopRect / Error Problem"))
{
Rect topRect = GUIScaleUtility.getTopRect;
Debug.Log ("Test finished, topRect " + topRect.ToString () + " received");
}
if (GUILayout.Button ("GUIClip.getTopRectScreenSpace / Potential Error Problem"))
{
Rect topRectScreenSpace = GUIScaleUtility.getTopRectScreenSpace;
Debug.Log ("Test finished, topRectScreenSpace " + topRectScreenSpace.ToString () + " received");
}
if (GUILayout.Button ("Inspect GUIClip"))
{
InspectType ("UnityEngine", "UnityEngine.GUIClip");
}
if (GUILayout.Button ("Start GUIClip.getTopRect complete test"))
{
performTest = !performTest;
checkedTypes = new List<EventType> ();
}
try
{
if (performTest && !checkedTypes.Contains (Event.current.type))
{
checkedTypes.Add (Event.current.type);
Rect topRect = GUIScaleUtility.getTopRect;
Debug.Log ("Test in " + Event.current.type.ToString () + " suceeded! topRect " + topRect.ToString () + " received");
}
}
catch (Exception e)
{
Debug.LogError ("Test in " + Event.current.type.ToString () + " failed! Error:" + e.ToString ());
}
}
public static void InspectType (string assemblyName, string typeName)
{
Assembly UnityEngine = Assembly.Load (assemblyName);
Type type = UnityEngine.GetType (typeName);
foreach (MemberInfo member in type.GetMembers ())
{
Debug.Log (member.MemberType.ToString () + ": " + member.ToString ());
}
}
} Edit: Fixed checking events multiple times |
All failed: Test in used failed! Error:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object Test in Layout failed! Error:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object Test in Repaint failed! Error:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object Test in mouseDrag failed! Error:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object Test in mouseUp failed! Error:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object It doesn't prove anything. Yeah, it's not available in OnGUI, but that's it. |
Not related to Events then, either:( Sad is I can't test it myself, so figuring this out would only go with you and would probably take forever;) I just wrote a version that allows to avoid this. Replace the region ScaleArea inside GUIScaleUtility with the following code: #region Scale Area
/// <summary>
/// Begins a scaled local area.
/// Returns vector to offset GUI controls with to account for zooming to the pivot.
/// Using adjustGUILayout does that automatically for GUILayout rects.
/// </summary>
public static Vector2 BeginScale (ref Rect rect, Vector2 zoomPivot, float zoom, bool adjustGUILayout)
{
//GUIScaleUtility.BeginNoClip ();
//Rect screenRect = GUIScaleUtility.InnerToScreenRect (rect);
GUI.EndGroup ();
Rect screenRect = rect;
#if UNITY_EDITOR
if (!Application.isPlaying)
screenRect.y += 23;
#endif
// The Rect of the new clipping group to draw our nodes in
rect = ScaleRect (screenRect, screenRect.position + zoomPivot, new Vector2 (zoom, zoom));
// Now continue drawing using the new clipping group
GUI.BeginGroup (rect);
rect.position = Vector2.zero; // Adjust because we entered the new group
// Because I currently found no way to actually scale to the center of the window rather than (0, 0),
// I'm going to cheat and just pan it accordingly to let it appear as if it would scroll to the center
// Note, due to that, other controls are still scaled to (0, 0)
Vector2 zoomPosAdjust = rect.center - screenRect.size/2 + zoomPivot;
// For GUILayout, we can make this adjustment here
adjustedGUILayout.Add (adjustGUILayout);
if (adjustGUILayout)
{
GUILayout.BeginHorizontal ();
GUILayout.Space (rect.center.x - screenRect.size.x + zoomPivot.x);
GUILayout.BeginVertical ();
GUILayout.Space (rect.center.y - screenRect.size.y + zoomPivot.y);
}
// Take a matrix backup to restore back later on
GUIMatrices.Add (GUI.matrix);
// Scale GUI.matrix. After that we have the correct clipping group again.
GUIUtility.ScaleAroundPivot (new Vector2 (1/zoom, 1/zoom), zoomPosAdjust);
return zoomPosAdjust;
}
/// <summary>
/// Ends a scale region
/// </summary>
public static void EndScale ()
{
// Set last matrix and clipping group
if (GUIMatrices.Count == 0 || adjustedGUILayout.Count == 0)
throw new UnityException ("GUIScaleutility: You are ending more scales than you are beginning!");
GUI.matrix = GUIMatrices[GUIMatrices.Count-1];
GUIMatrices.RemoveAt (GUIMatrices.Count-1);
// End GUILayout zoomPosAdjustment
if (adjustedGUILayout[adjustedGUILayout.Count-1])
{
GUILayout.EndVertical ();
GUILayout.EndHorizontal ();
}
adjustedGUILayout.RemoveAt (adjustedGUILayout.Count-1);
GUI.EndGroup ();
#if UNITY_EDITOR
if (!Application.isPlaying)
GUI.BeginClip (new Rect (0, 23, Screen.width, Screen.height-23));
else
GUI.BeginClip (new Rect (0, 0, Screen.width, Screen.height));
#else
GUI.BeginClip (new Rect (0, 0, Screen.width, Screen.height));
#endif
// GUIScaleUtility.RestoreClips ();
}
#endregion That should make sure the three functions in Clips Hierarchy region are not called anymore. Note that you no longer can use the NodeEditor canvas in groups, though - that doesn't affect the current Editor Window nor the runtime demo, aslong as there are no top groups, everything is fine. (Runtime does NEED one top group, but no more! Or you have to delete the first EndGroup in BeginScale and the last BeginClip in EndScale). I'll try to automate that fix for anyone getting those errors - I'll leave this issue open! |
Thank you! I'll try using it tomorrow. |
I'll do, after I got the approval of you that it even works :) |
@Seneral |
Great! :) |
I the latest commit I added a compability mode which should automatically be triggered and inform the user about it. |
(Reverting 36ca904 helps)
When trying to open Window -> Node Editor:
NullReferenceException: Object reference not set to an instance of an object
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
GUIScaleUtility.get_getTopRect () (at Assets/Plugins/Node_Editor/Framework/GUIScaleUtility.cs:16)
GUIScaleUtility.BeginNoClip () (at Assets/Plugins/Node_Editor/Framework/GUIScaleUtility.cs:157)
GUIScaleUtility.BeginScale (UnityEngine.Rect& rect, Vector2 zoomPivot, Single zoom, Boolean adjustGUILayout) (at Assets/Plugins/Node_Editor/Framework/GUIScaleUtility.cs:85)
NodeEditorFramework.NodeEditor.DrawSubCanvas (NodeEditorFramework.NodeCanvas nodeCanvas, NodeEditorFramework.NodeEditorState editorState) (at Assets/Plugins/Node_Editor/Framework/NodeEditor.cs:140)
NodeEditorFramework.NodeEditor.DrawCanvas (NodeEditorFramework.NodeCanvas nodeCanvas, NodeEditorFramework.NodeEditorState editorState) (at Assets/Plugins/Node_Editor/Framework/NodeEditor.cs:86)
NodeEditorFramework.NodeEditorWindow.OnGUI () (at Assets/Editor/Node_Editor/NodeEditorWindow.cs:78)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
The text was updated successfully, but these errors were encountered: