/// <summary>
        /// In a second pass, we update the referenced data. This is so states dependent on other components
        /// is correctly applied.
        /// </summary>
        /// <param name="prefabLookup">A dictionary with lower-case names as key, and created prefabs as values.</param>
        private Dictionary <string, IMainComponent> UpdateGameItems(Dictionary <string, IVpxPrefab> prefabLookup)
        {
            var componentLookup = prefabLookup.ToDictionary(x => x.Key, x => x.Value.MainComponent);

            try {
                // pause asset database refreshing
                AssetDatabase.StartAssetEditing();

                // thanks unity for not letting me pass the options to ModelExporter.ExportObject().
                var modelExporter     = typeof(ModelExporter);
                var optionsProp       = modelExporter.GetProperty("DefaultOptions", BindingFlags.Static | BindingFlags.NonPublic);
                var optionsValue      = optionsProp !.GetValue(null, null);
                var optionsType       = optionsValue.GetType();
                var exportFormatField = optionsType.BaseType !.GetField("exportFormat", BindingFlags.Instance | BindingFlags.NonPublic);
                exportFormatField !.SetValue(optionsValue, 1);                // set to binary
                var exportObject = modelExporter.GetMethod("ExportObjects", BindingFlags.NonPublic | BindingFlags.Static);

                // first loop: write fbx files
                foreach (var prefab in prefabLookup.Values)
                {
                    prefab.SetReferencedData(_sourceTable, this, this, componentLookup);
                    prefab.FreeBinaryData();

                    if (prefab.ExtractMesh)
                    {
                        var meshFilename = $"{prefab.GameObject.name.ToFilename()}.fbx";
                        var meshPath     = Path.Combine(_assetsMeshes, meshFilename);
                        if (_options.SkipExistingMeshes && File.Exists(meshPath))
                        {
                            continue;
                        }
                        if (File.Exists(meshPath))
                        {
                            AssetDatabase.DeleteAsset(meshPath);
                        }

                        // export via reflection, because we need binary.
                        exportObject !.Invoke(null, new[] { meshPath, new UnityEngine.Object[] { prefab.GameObject }, optionsValue, null });
                    }
                }
            } finally {
                // resume asset database refreshing
                AssetDatabase.StopAssetEditing();
                AssetDatabase.Refresh();
            }

            // second loop: assign them to the game object.
            foreach (var prefab in prefabLookup.Values)
            {
                if (prefab.ExtractMesh)
                {
                    var meshFilename = $"{prefab.GameObject.name.ToFilename()}.fbx";
                    var meshPath     = Path.Combine(_assetsMeshes, meshFilename);
                    var mf           = prefab.GameObject.GetComponent <MeshFilter>();
                    mf.sharedMesh = AssetDatabase.LoadAssetAtPath <Mesh>(meshPath);
                }

                // patch
                if (_applyPatch)
                {
                    _patcher?.ApplyPatches(prefab.GameObject, _tableGo);
                    if (prefab.GameObject)                       // only if not destroyed..
                    {
                        prefab.UpdateTransforms();
                    }
                }

                // persist changes
                if (prefab.GameObject)                   // only if not destroyed..
                {
                    prefab.PersistData();
                }
            }

            return(componentLookup);
        }