Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Detecting missing nested prefab?

Discussion in 'Prefabs' started by fatswallowBesides, Jun 19, 2019.

  1. fatswallowBesides

    fatswallowBesides

    Joined:
    Jul 18, 2018
    Posts:
    12
    In 2018.4 LTS, I'm trying to detect Missing nested prefab from my project and I'm out of luck.it looks like there's no way to detect B is missing in script.

    for example,
    let B is missing prefab nested in A.

    A - B(missing)

    Then
    PrefabUtility.IsPrefabAssetMissing(B)
    PrefabUtility.IsDisconnectedFromPrefabAsset(B)
    PrefabUtility.IsAnyPrefabInstanceRoot(B)

    all these functions returns false. it looks like missing prefab object does not treated as prefab.

    In big project it is virtually impossible to detect which prefab contains missing prefab. And there's 100% crash issue(https://fogbugz.unity3d.com/default.asp?1156778_6ipq7le01fvqp89f) with missing prefab, one missing prefab can completely block project. Anyone has some answer? :(
     
  2. fatswallowBesides

    fatswallowBesides

    Joined:
    Jul 18, 2018
    Posts:
    12
    I got it covered somehow. on prefab reimport, missing prefab's object name will changed to (Missing Prefab). after reimporting all prefabs, you can check every gameobject's name contains "Missing Prefab".

    I know its kinda crude, but it works anyway.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6.  
    7. public class MissingPrefabDetector
    8. {
    9.     [MenuItem("Util/Find Missing Prefab")]
    10.     static void Init()
    11.     {
    12.         string[] allPrefabs = GetAllPrefabs();
    13.  
    14.         int count = 0;
    15.         EditorUtility.DisplayProgressBar("Processing...", "Begin Job", 0);
    16.  
    17.         foreach (string prefab in allPrefabs)
    18.         {
    19.             UnityEngine.Object o = AssetDatabase.LoadMainAssetAtPath(prefab);
    20.  
    21.             if (o == null)
    22.             {
    23.                 Debug.Log("prefab " + prefab + " null?");
    24.                 continue;
    25.             }
    26.  
    27.             GameObject go;
    28.             try
    29.             {
    30.                 go = (GameObject)PrefabUtility.InstantiatePrefab(o);
    31.                 EditorUtility.DisplayProgressBar("Processing...", go.name, ++count / (float)allPrefabs.Length);
    32.                 FindMissingPrefabInGO(go, prefab, true);
    33.  
    34.                 GameObject.DestroyImmediate(go);
    35.  
    36.             }
    37.             catch
    38.             {
    39.                 Debug.Log("For some reason, prefab " + prefab + " won't cast to GameObject");
    40.  
    41.             }
    42.         }
    43.         EditorUtility.ClearProgressBar();
    44.     }
    45.  
    46.  
    47.     static void FindMissingPrefabInGO(GameObject g, string prefabName, bool isRoot)
    48.     {
    49.         if (g.name.Contains("Missing Prefab"))
    50.         {
    51.             Debug.LogError($"{prefabName} has missing prefab {g.name}");
    52.             return;
    53.  
    54.         }
    55.  
    56.         if (PrefabUtility.IsPrefabAssetMissing(g))
    57.         {
    58.             Debug.LogError($"{prefabName} has missing prefab {g.name}");
    59.             return;
    60.         }
    61.  
    62.         if (PrefabUtility.IsDisconnectedFromPrefabAsset(g))
    63.         {
    64.             Debug.LogError($"{prefabName} has missing prefab {g.name}");
    65.             return;
    66.         }
    67.  
    68.         if (!isRoot)
    69.         {
    70.             if (PrefabUtility.IsAnyPrefabInstanceRoot(g))
    71.             {
    72.                 return;
    73.             }
    74.             GameObject root = PrefabUtility.GetNearestPrefabInstanceRoot(g);
    75.             if (root == g)
    76.             {
    77.                 return;
    78.             }
    79.         }
    80.  
    81.  
    82.         // Now recurse through each child GO (if there are any):
    83.         foreach (Transform childT in g.transform)
    84.         {
    85.             //Debug.Log("Searching " + childT.name  + " " );
    86.             FindMissingPrefabInGO(childT.gameObject, prefabName, false);
    87.         }
    88.     }
    89.  
    90.     public static string[] GetAllPrefabs()
    91.     {
    92.         string[] temp = AssetDatabase.GetAllAssetPaths();
    93.         List<string> result = new List<string>();
    94.         foreach (string s in temp)
    95.         {
    96.             if (s.Contains(".prefab")) result.Add(s);
    97.         }
    98.         return result.ToArray();
    99.     }
    100.  
    101.  
    102. }
    103.  
     
  3. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    Functionality like this really should be built in to Unity. I thought it was strange to get a warning message in my log with no prefab name, and clicking on it did not highlight the item containing the missing prefab in the project hierarchy.
     
    rbitard and IanSherman like this.
  4. Patheagames

    Patheagames

    Joined:
    Jul 19, 2011
    Posts:
    27
    use GameObject obj = PrefabUtility.LoadPrefabContents(path); open you prefab,not AssetDatabase.LoadAssetAtPath.
     
  5. rbitard

    rbitard

    Joined:
    Jan 11, 2022
    Posts:
    189
    is there something available built-in ? Or some code ?
    I found this dunno what it's worth
    https://github.com/edcasillas/unity-missing-references-finder
     
  6. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    A surprising place you can find this type of functionality is in the Asset Store Tools. If you install them and run the Asset Store Validator, it will run a whole pile of checks, including a missing references check. It also gives you a clickable list of prefabs that have missing references.
     
    rbitard likes this.
  7. rbitard

    rbitard

    Joined:
    Jan 11, 2022
    Posts:
    189
  8. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    rbitard likes this.
  9. rbitard

    rbitard

    Joined:
    Jan 11, 2022
    Posts:
    189
    Tried it a bit it's quite nice !! My only problem is that it doesn't check missing references.
    You know when you rename a public or serializeField reference and unity delete it from the script kind of errors.
    If anyone got a tips to handle that I'd be delighted