Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feedback Please indicate in the Hierarchy if a GameObject contains unassigned variables

Discussion in 'General Discussion' started by spatialfree, Apr 20, 2019.

  1. spatialfree

    spatialfree

    Joined:
    Jan 25, 2017
    Posts:
    5
    Nothing worse than going to test your code only to be blue balled by a NullReferenceException. Diligence only getting you so far, and contributing unnecessary friction to your workflow.

    Since Unity is essentially an over-featured GUI ref injector. We should expect its core service to be its best. As with all big projects, we/they must of gone blind to how big of an oversight this is.

    Where in the case its not feasible, at least make it more noticeable in the inspector.



    Unity got me back into development, so I owe it my honesty.
    thank you!
     
    pcg and Socrates like this.
  2. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    In the meantime you can create a editor tool for it.
     
  3. spatialfree

    spatialfree

    Joined:
    Jan 25, 2017
    Posts:
    5
    I made a simple method, that performs the check.

    Code (CSharp):
    1. GameObject[] objects = GameObject.FindObjectsOfType<GameObject>();
    2. foreach (GameObject obj in objects)
    3. {
    4.   Component[] comps = obj.GetComponents(typeof(MonoBehaviour));
    5.  
    6.   foreach (Component comp in comps)
    7.   {
    8.     FieldInfo[] fields = comp.GetType().GetFields();
    9.     foreach (FieldInfo field in fields)
    10.     {
    11.       object value = field.GetValue(comp);
    12.       if (value == null || value.Equals(null))
    13.       {
    14.         Debug.Log(obj.name + ": " + field.Name);
    15.       }
    16.     }
    17.   }
    18. }
     
    Last edited: Apr 22, 2019
  4. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,364
    There are a LOT of references on components which are optional though. I can't imagine wading through all the false positives.
     
    ihgyug, dadude123, xVergilx and 2 others like this.
  5. Socrates

    Socrates

    Joined:
    Mar 29, 2011
    Posts:
    787
    I may be doing it a brute force way, but if my code is expecting that a value in the inspector is already set, I check for a valid value, usually in Start. If there is no value, I log it to the console. In some cases, I might stick in an empty game object or other default value to keep later code from crashing while I'm working.

    Some sort of marker on the hierarchy would be nice, though, just to help when wiring things up in the first place.
     
    Joe-Censored, halley and spatialfree like this.
  6. spatialfree

    spatialfree

    Joined:
    Jan 25, 2017
    Posts:
    5
    I made a small change to my code to now only get MonoBehaviour components. Which took care of all of the false positives in my current project.
     
  7. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    .OnValidate is a better place for those checks, as it won't be called in builds, saving some precious performance on loading scripts.
     
  8. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    This only checks in current scene. You can also check all prefabs doing

    Code (CSharp):
    1.     [MenuItem("MDA Digital/Misc/Output prefabs with unassgined members")]
    2.     public static void OutputPrefabsWithUnassignedMembers()
    3.     {
    4.         var unassigned =
    5.             AssetDatabase.FindAssets("t:Prefab")
    6.                 .Select(guid => AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(guid)))
    7.                 .Select(go => new { go, unassigned = go?.GetComponentsInChildren<MonoBehaviour>()?.SelectMany(mono => mono?
    8.                         .GetType()
    9.                         .GetFields()
    10.                         .Where(f => (f.IsPublic || f.GetCustomAttributes(typeof(SerializeField), true).Any()) && f.GetValue(mono) == null))})
    11.                 .Where(info => info.unassigned != null && info.unassigned.Any())
    12.                 .ToList();
    13.  
    14.         foreach (var info in unassigned)
    15.                 Debug.LogWarning($"Prefab: {info.go.name} has these unnasigned members: {string.Join("; ", info.unassigned.Select(u => u.Name))}");
    16.     }
     
    spatialfree likes this.
  9. newjerseyrunner

    newjerseyrunner

    Joined:
    Jul 20, 2017
    Posts:
    966
    I use assertions in the Start method to detect when things that shouldn't be null are. You should use conditional methods to do debugging checks like that in all your code, it'll save you a lot of headaches down the line. Code behaving funny?
    -define:DEBUG
     
  10. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,956
    spatialfree likes this.
  11. Socrates

    Socrates

    Joined:
    Mar 29, 2011
    Posts:
    787
    Thank you. I used that once in a tutorial to check number values or something, but I hadn't even thought about using it for value existence. I will have to start doing that.