//---------------------------------------------------------------------------------------------------------------------- internal static void ChangeSceneCacheFile(SceneCachePlayer cachePlayer, string sceneCacheFilePath) { string prefabPath = null; GameObject go = cachePlayer.gameObject; //Check if it's possible to reuse the old assetsFolder string assetsFolder = cachePlayer.GetAssetsFolder(); if (string.IsNullOrEmpty(assetsFolder)) { MeshSyncProjectSettings projectSettings = MeshSyncProjectSettings.GetOrCreateSettings(); string scOutputPath = projectSettings.GetSceneCacheOutputPath(); assetsFolder = Path.Combine(scOutputPath, Path.GetFileNameWithoutExtension(sceneCacheFilePath)); } bool isPrefabInstance = cachePlayer.gameObject.IsPrefabInstance(); //We are directly modifying a prefab if (!isPrefabInstance && go.IsPrefab()) { prefabPath = AssetDatabase.GetAssetPath(go); CreateSceneCachePlayerAndPrefab(sceneCacheFilePath, prefabPath, assetsFolder, out SceneCachePlayer player, out GameObject newPrefab); Object.DestroyImmediate(player.gameObject); return; } if (isPrefabInstance) { GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(cachePlayer.gameObject); //GetCorrespondingObjectFromSource() may return the ".sc" GameObject instead of the prefab //due to the SceneCacheImporter string assetPath = AssetDatabase.GetAssetPath(prefab); if (Path.GetExtension(assetPath).ToLower() == ".prefab") { prefabPath = assetPath; } else { isPrefabInstance = false; } } cachePlayer.CloseCache(); //[TODO-sin: 2020-9-28] Find out if it is possible to do undo properly Undo.RegisterFullObjectHierarchyUndo(cachePlayer.gameObject, "SceneCachePlayer"); Dictionary<string,EntityRecord> prevRecords = new Dictionary<string, EntityRecord>(cachePlayer.GetClientObjects()); GameObject tempGO = null; Dictionary<Transform, Transform> nonPrefabTrans = new Dictionary<Transform, Transform>(); //nonPrefab -> origParent if (isPrefabInstance) { //Move non-prefab transforms tempGO = new GameObject("Temp"); FindNonPrefabChildren(cachePlayer.transform, ref nonPrefabTrans); nonPrefabTrans.Keys.SetParent(tempGO.transform); PrefabUtility.UnpackPrefabInstance(cachePlayer.gameObject, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); } //remove irrelevant components of the GameObject if the entity type is different void ChangeEntityTypeCB(GameObject updatedGo, TransformData data) { string dataPath = data.path; if (!prevRecords.ContainsKey(dataPath)) return; EntityRecord prevRecord = prevRecords[dataPath]; if (data.entityType == prevRecord.dataType) return; DestroyIrrelevantComponents(updatedGo, data.entityType); } cachePlayer.onUpdateEntity += ChangeEntityTypeCB; cachePlayer.Init(assetsFolder); cachePlayer.OpenCacheInEditor(sceneCacheFilePath); cachePlayer.onUpdateEntity -= ChangeEntityTypeCB; IDictionary<string,EntityRecord> curRecords = cachePlayer.GetClientObjects(); DeleteInvalidRecordedGameObjects(prevRecords, curRecords); if (!isPrefabInstance) { return; } cachePlayer.gameObject.SaveAsPrefab(prefabPath); //Save as prefab if it was originally a prefab instance //Move nonPrefab transforms back foreach (KeyValuePair<Transform, Transform> kv in nonPrefabTrans) { Transform origParent = kv.Value; Transform t = kv.Key; if (null == origParent) { ObjectUtility.Destroy(t.gameObject); } else { t.SetParent(origParent); } } ObjectUtility.Destroy(tempGO); }