Search Issue Tracker

By Design

Votes

0

Found in

2020.3

2020.3.12f1

Issue ID

1358996

Regression

No

Unexpected null references during prefab import after upgrading a project from 2019.4 to 2020.3

Scene Management

-

Reproduction steps:
1. Open the attached "Project" project
2. Observe the Console

Expected result: No BUILD SYSTEM NULL POINTER errors and the Scene view isn't gray
Actual result: Many BUILD SYSTEM NULL POINTER errors and the Scene view is gray

Reproducible with: 2020.3.23f1
Could not test with: 2019.4.32f1 (reproduction project is already upgraded to 2020.3, downgrading causes other errors but the Scene view remains gray), 2021.2.3f1 (other errors but the Scene view remains gray), 2022.1.0a16 (other errors, often crashes when selecting an asset/object/action, the Scene view remains gray)

  1. Resolution Note:

    Non dependent Prefabs (Prefabs that are not nested nor Variants) are imported in a nondeterministic order. In this case OnValidate is called while a Prefab is imported and it checks if a Prefab that is referenced by a script from the current Prefab is non null, which depending on the importing order might hold or not.

    To check if a script referenced Prefab is valid we have https://docs.unity3d.com/2022.1/Documentation/ScriptReference/AssetPostprocessor.OnPostprocessAllAssets.html which gets called after all Prefabs are imported.

    Following is an example of a similar validation:

    ItemBlueprint.cs:
    using System.Collections.Generic;
    using UnityEngine;

    public class ItemBlueprint : MonoBehaviour
    {
    public List<GameObject> referencedPrefabs = new List<GameObject>();

    public void ValidateReferencedPrefabs(string caller)
    {
    foreach(var referencedPrefab in referencedPrefabs)
    {
    if(referencedPrefab == null)
    {
    Debug.LogError(caller + ": - Referenced prefab is null");
    }
    }
    }

    public void OnValidate()
    {
    ValidateReferencedPrefabs("OnValidate");
    }
    }

    PrefabValidator.cs:
    using UnityEditor;
    using UnityEngine;

    public class PrefabValidator : AssetPostprocessor
    {
    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
    foreach(var importedAsset in importedAssets)
    {
    if(importedAsset.EndsWith(".prefab", System.StringComparison.OrdinalIgnoreCase))
    {
    var prefabRoot = AssetDatabase.LoadMainAssetAtPath(importedAsset) as GameObject;
    var itemBlueprints = prefabRoot.GetComponentsInChildren<ItemBlueprint>();
    foreach(var itemBlueprint in itemBlueprints)
    {
    itemBlueprint.ValidateReferencedPrefabs("OnPostprocessAllAssets");
    }
    }
    }
    }
    }

    In this case the calls to ValidateReferencedPrefabs from OnPostprocessAllAssets will log errors only for missing referenced Prefabs and the calls from OnValidate will log errors for all missing referenced Prefabs and for non missing referenced Prefabs at random.

    Please note that this approach won't validate Prefabs that are already imported - they are not in string[] importedAssets. This also applies to OnValidate - if a referenced Prefab gets deleted OnValidate won't be called on the Prefab that references the deleted Prefab until it gets loaded (it's selected, imported, etc)

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.