static bool InstantiateInMemoryScene(SceneTemplateAsset sceneTemplate, string sourceScenePath, ref string newSceneOutputPath, out string rootFolder, out bool isTempMemory) { isTempMemory = false; if (string.IsNullOrEmpty(newSceneOutputPath)) { if (!registeredTempFolder) { RegisterInMemoryTempFolder(); } var instanceName = "Untitled.unity"; var instancePath = $"{k_MountPoint}/{k_InMemoryTempFolder}/{Guid.NewGuid():N}/{instanceName}"; newSceneOutputPath = instancePath; isTempMemory = true; } if (Path.IsPathRooted(newSceneOutputPath)) { newSceneOutputPath = FileUtil.GetProjectRelativePath(newSceneOutputPath); } rootFolder = Path.GetDirectoryName(newSceneOutputPath); if (rootFolder != null && !Directory.Exists(rootFolder)) { Directory.CreateDirectory(rootFolder); } if (!AssetDatabase.CopyAsset(sourceScenePath, newSceneOutputPath)) { Debug.LogError($"Could not copy scene \"{sourceScenePath}\" to \"{newSceneOutputPath}\""); return(false); } return(true); }
public SceneTemplateCreationEvent(SceneTemplateAsset template, TemplateCreationType templateCreationType) { this.templateCreationType = Enum.GetName(typeof(TemplateCreationType), templateCreationType); sceneName = AssetDatabase.GetAssetPath(template.templateScene); hasCloneableDependencies = FillAnalyticDepInfos(template, dependencyInfos); numberOfTemplatesInProject = SceneTemplateUtils.GetSceneTemplates().Count(); }
public SceneInstantiationEvent(SceneTemplateAsset template, SceneInstantiationType instantiationType) { this.instantiationType = Enum.GetName(typeof(SceneInstantiationType), instantiationType); sceneName = AssetDatabase.GetAssetPath(template.templateScene); hasCloneableDependencies = FillAnalyticDepInfos(template, dependencyInfos); m_StartTime = DateTime.Now; }
public override void AfterTemplateInstantiation(SceneTemplateAsset sceneTemplateAsset, Scene scene, bool isAdditive, string sceneName) { if (sceneTemplateAsset) { Debug.Log($"AfterTemplateInstantiation {sceneTemplateAsset.name} scene: {scene} isAdditive: {isAdditive} sceneName: {sceneName}"); } afterHit = true; }
public override void BeforeTemplateInstantiation(SceneTemplateAsset sceneTemplateAsset, bool isAdditive, string sceneName) { if (sceneTemplateAsset) { Debug.Log($"BeforeTemplateInstantiation {sceneTemplateAsset.name} isAdditive: {isAdditive} sceneName: {sceneName}"); } beforeHit = true; }
internal static bool FillAnalyticDepInfos(SceneTemplateAsset template, List <AnalyticDepInfo> infos) { if (template.dependencies == null) { return(false); } var hasCloneableDependencies = false; var tempDepInfos = new Dictionary <string, List <AnalyticDepInfo> >(); if (template.dependencies != null) { foreach (var dep in template.dependencies) { if (dep.instantiationMode == TemplateInstantiationMode.Clone) { hasCloneableDependencies = true; } if (!dep.dependency || dep.dependency == null) { continue; } var typeName = dep.dependency.GetType().FullName; if (tempDepInfos.TryGetValue(typeName, out var infosPerType)) { var foundInfo = infosPerType.Find(info => info._instantiationMode == dep.instantiationMode); if (foundInfo != null) { foundInfo.count++; } else { infosPerType.Add(new AnalyticDepInfo(dep)); } } else { infosPerType = new List <AnalyticDepInfo>(); infosPerType.Add(new AnalyticDepInfo(dep)); tempDepInfos.Add(typeName, infosPerType); } } } foreach (var kvp in tempDepInfos) { foreach (var depInfo in kvp.Value) { infos.Add(depInfo); } } return(hasCloneableDependencies); }
private static List <Object> CopyCloneableDependencies(SceneTemplateAsset sceneTemplate, string newSceneOutputPath, ref Dictionary <string, string> refPathMap) { var clonedAssets = new List <Object>(); var outputSceneFileName = Path.GetFileNameWithoutExtension(newSceneOutputPath); var outputSceneDirectory = Path.GetDirectoryName(newSceneOutputPath); var dependencyFolder = Path.Combine(outputSceneDirectory, outputSceneFileName); if (!Directory.Exists(dependencyFolder)) { Directory.CreateDirectory(dependencyFolder); } try { AssetDatabase.StartAssetEditing(); foreach (var dependency in sceneTemplate.dependencies) { if (dependency.instantiationMode != TemplateInstantiationMode.Clone) { continue; } var dependencyPath = AssetDatabase.GetAssetPath(dependency.dependency); if (String.IsNullOrEmpty(dependencyPath)) { Debug.LogError("Cannot find dependency path for: " + dependency.dependency, dependency.dependency); continue; } var clonedDepName = Path.GetFileName(dependencyPath); var clonedDepPath = Path.Combine(dependencyFolder, clonedDepName).Replace("\\", "/"); // FYI: CopyAsset already does Import and Refresh AssetDatabase.CopyAsset(dependencyPath, clonedDepPath); refPathMap.Add(dependencyPath, clonedDepPath); } } finally { AssetDatabase.StopAssetEditing(); AssetDatabase.Refresh(); } foreach (var clonedDepPath in refPathMap.Values) { var clonedDependency = AssetDatabase.LoadMainAssetAtPath(clonedDepPath); if (clonedDependency == null || !clonedDependency) { Debug.LogError("Cannot load cloned dependency path at: " + clonedDepPath); continue; } clonedAssets.Add(clonedDependency); } return(clonedAssets); }
private void OnSceneTemplateAssetModified(SceneTemplateAsset asset) { m_SceneTemplateInfos = SceneTemplateUtils.GetSceneTemplateInfos(); var lastSelectedTemplateIndex = m_SceneTemplateInfos.IndexOf(m_LastSelectedTemplate); if (lastSelectedTemplateIndex == -1) { SetLastSelectedTemplate(GetDefaultSceneTemplateInfo()); } else { SetLastSelectedTemplate(m_SceneTemplateInfos[lastSelectedTemplateIndex]); } RefreshTemplateGridView(); UpdateTemplateDescriptionUI(m_LastSelectedTemplate); }
private static bool InstantiateScene(SceneTemplateAsset sceneTemplate, string sourceScenePath, ref string newSceneOutputPath) { if (String.IsNullOrEmpty(newSceneOutputPath)) { newSceneOutputPath = SceneTemplateUtils.SaveFilePanelUniqueName( $"Save scene instantiated from template ({sceneTemplate.name})", SceneTemplateUtils.GetLastFolder("unity"), Path.GetFileNameWithoutExtension(sourceScenePath), "unity"); if (string.IsNullOrEmpty(newSceneOutputPath)) { return(false); } } if (Path.IsPathRooted(newSceneOutputPath)) { newSceneOutputPath = FileUtil.GetProjectRelativePath(newSceneOutputPath); } if (sourceScenePath == newSceneOutputPath) { Debug.LogError($"Cannot instantiate over template scene: {newSceneOutputPath}"); return(false); } var destinationDir = Path.GetDirectoryName(newSceneOutputPath); if (destinationDir != null && !Directory.Exists(destinationDir)) { Directory.CreateDirectory(destinationDir); } AssetDatabase.CopyAsset(sourceScenePath, newSceneOutputPath); return(true); }
public override VisualElement CreateInspectorGUI() { var root = Root = new VisualElement(); root.AddToClassList("scene-template-asset-inspector"); root.AddToClassList(Styles.unityThemeVariables); root.AddToClassList(Styles.sceneTemplateThemeVariables); root.AddStyleSheetPath(Styles.k_CommonStyleSheetPath); root.AddStyleSheetPath(Styles.variableStyleSheet); root.style.flexDirection = FlexDirection.Column; var detailElement = new VisualElement(); // Template scene var templateSceneProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplateScenePropertyName); var templatePropertyField = new PropertyField(templateSceneProperty, L10n.Tr("Template Scene")); templatePropertyField.tooltip = L10n.Tr("Scene to instantiate."); templatePropertyField.RegisterCallback <ChangeEvent <Object> >(e => { RebuildDependencies(root); TriggerSceneTemplateModified(); }); detailElement.Add(templatePropertyField); // Scene title var templateTitleProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplateTitlePropertyName); var titlePropertyField = new PropertyField(templateTitleProperty, L10n.Tr("Title")); titlePropertyField.tooltip = L10n.Tr("Scene template display name. Shown in New Scene Dialog."); titlePropertyField.RegisterCallback <ChangeEvent <string> >(e => TriggerSceneTemplateModified()); titlePropertyField.RegisterCallback <SerializedPropertyBindEvent>(e => { EditorApplication.delayCall += () => { if (!titlePropertyField.Children().Any()) { return; } if (titlePropertyField.Children().First() is TextField titlePropertyFieldTextField) { titlePropertyFieldTextField.maxLength = 1024; m_TitleTextFieldReady = true; } }; }); detailElement.Add(titlePropertyField); // Scene description var templateDescriptionProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplateDescriptionPropertyName); var description = new PropertyField(templateDescriptionProperty, L10n.Tr("Description")); description.tooltip = L10n.Tr("Scene template description. Shown in New Scene Dialog."); description.RegisterCallback <ChangeEvent <string> >(e => TriggerSceneTemplateModified()); description.RegisterCallback <SerializedPropertyBindEvent>(e => { EditorApplication.delayCall += () => { if (!description.Children().Any()) { return; } var descriptionTextField = description.Children().First() as TextField; if (descriptionTextField != null) { descriptionTextField.AddToClassList(Styles.classWrappingText); descriptionTextField.multiline = true; descriptionTextField.maxLength = 1024; m_DescriptionTextFieldReady = true; } }; }); detailElement.Add(description); var templateAddToDefaultsProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplateAddToDefaultsPropertyName); var defaultTemplateField = new VisualElement(); defaultTemplateField.style.flexDirection = FlexDirection.Row; var addToDefaultsPropertyField = new PropertyField(templateAddToDefaultsProperty, " "); addToDefaultsPropertyField.RegisterCallback <ChangeEvent <bool> >(e => TriggerSceneTemplateModified()); addToDefaultsPropertyField.style.flexShrink = 0; defaultTemplateField.Add(addToDefaultsPropertyField); var label = new Label(L10n.Tr("Pin in New Scene Dialog")); label.tooltip = L10n.Tr("Pin in New Scene Dialog. Ensuring this template is shown before unpinned template in the list."); label.style.unityTextAlign = TextAnchor.MiddleLeft; label.style.overflow = Overflow.Hidden; label.style.textOverflow = TextOverflow.Ellipsis; label.style.flexShrink = 1; defaultTemplateField.Add(label); detailElement.Add(defaultTemplateField); root.Add(CreateFoldoutInspector(detailElement, L10n.Tr("Details"), "SceneTemplateInspectorDetailsFoldout")); // Template thumbnail var templateThumbnailProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplateThumbnailPropertyName); var templateThumbnailBadgeProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplateThumbnailBadgePropertyName); var thumbnailField = MakeThumbnailField(templateThumbnailProperty, templateThumbnailBadgeProperty); root.Add(CreateFoldoutInspector(thumbnailField, L10n.Tr("Thumbnail"), "SceneTemplateInspectorThumbnailFoldout")); // SceneTemplatePipeline var sceneTemplatePipeline = new VisualElement(); var pipelineProperty = serializedObject.FindProperty(SceneTemplateUtils.TemplatePipelineName); var pipelineField = new PropertyField(pipelineProperty, L10n.Tr("Scene Template Pipeline")); pipelineField.tooltip = k_SceneTemplateInfo; pipelineField.RegisterCallback <ChangeEvent <Object> >(e => { if (e.newValue != null && !SceneTemplateAsset.IsValidPipeline(e.newValue as MonoScript)) { Debug.LogWarning(k_SceneTemplateInfo); pipelineProperty.objectReferenceValue = null; serializedObject.ApplyModifiedProperties(); } }); sceneTemplatePipeline.Add(pipelineField); var buttonRow = CreateEmptyLabelRow(L10n.Tr("Scene Template Pipeline"), Styles.classUnityPropertyFieldLabel); // Use a hidden label instead of an empty element for proper alignment var createPipelineButton = new Button(OnCreateSceneTemplatePipeline) { text = k_CreatePipelineButtonLabel, tooltip = k_CreatePipelineTooltip }; createPipelineButton.AddToClassList(Styles.classUnityBaseFieldInput); buttonRow.Add(createPipelineButton); sceneTemplatePipeline.Add(buttonRow); root.Add(CreateFoldoutInspectorWithHelp(sceneTemplatePipeline, L10n.Tr("Scene Template Pipeline"), "SceneTemplatePipelineFoldout", k_PipelineHelpUrl)); // Dependencies root.Add(CreateFoldoutInspector(BuildDependencyRows(), L10n.Tr("Dependencies"), "SceneTemplateDependenciesFoldout")); return(root); }
public override VisualElement CreateInspectorGUI() { var styleSheetLoader = new StyleSheetLoader(); styleSheetLoader.LoadStyleSheets(); var root = Root = new VisualElement(); root.AddToClassList("scene-template-asset-inspector"); root.AddToClassList(StyleSheetLoader.Styles.unityThemeVariables); root.AddToClassList(StyleSheetLoader.Styles.sceneTemplateThemeVariables); root.styleSheets.Add(styleSheetLoader.CommonStyleSheet); root.styleSheets.Add(styleSheetLoader.VariableStyleSheet); root.style.flexDirection = FlexDirection.Column; var detailElement = new VisualElement(); // Template scene var templateSceneProperty = serializedObject.FindProperty(k_TemplateScenePropertyName); var templatePropertyField = new PropertyField(templateSceneProperty, "Template Scene"); templatePropertyField.RegisterCallback <ChangeEvent <Object> >(e => { RebuildDependencies(root); TriggerSceneTemplateModified(); }); detailElement.Add(templatePropertyField); // Scene title var templateTitleProperty = serializedObject.FindProperty(k_TemplateTitlePropertyName); var titlePropertyField = new PropertyField(templateTitleProperty, "Title"); titlePropertyField.RegisterCallback <ChangeEvent <string> >(e => TriggerSceneTemplateModified()); detailElement.Add(titlePropertyField); // Scene description var templateDescriptionProperty = serializedObject.FindProperty(k_TemplateDescriptionPropertyName); var descriptionTextField = new TextField("Description", -1, true, false, '*') { name = k_DescriptionTextFieldName, value = templateDescriptionProperty.stringValue }; descriptionTextField.AddToClassList(StyleSheetLoader.Styles.classWrappingText); descriptionTextField.RegisterValueChangedCallback(e => { serializedObject.UpdateIfRequiredOrScript(); templateDescriptionProperty.stringValue = e.newValue; serializedObject.ApplyModifiedProperties(); TriggerSceneTemplateModified(); }); detailElement.Add(descriptionTextField); var templateAddToDefaultsProperty = serializedObject.FindProperty(k_TemplateAddToDefaultsPropertyName); var defaultTemplateField = new VisualElement(); defaultTemplateField.style.flexDirection = FlexDirection.Row; var addToDefaultsPropertyField = new PropertyField(templateAddToDefaultsProperty, " "); addToDefaultsPropertyField.RegisterCallback <ChangeEvent <bool> >(e => TriggerSceneTemplateModified()); addToDefaultsPropertyField.style.flexShrink = 0; defaultTemplateField.Add(addToDefaultsPropertyField); var label = new Label("Pin in New Scene Dialog"); label.style.unityTextAlign = TextAnchor.MiddleLeft; label.style.overflow = Overflow.Hidden; label.style.textOverflow = TextOverflow.Ellipsis; label.style.flexShrink = 1; defaultTemplateField.Add(label); detailElement.Add(defaultTemplateField); root.Add(CreateFoldoutInspector(detailElement, "Details", "SceneTemplateInspectorDetailsFoldout")); // Template thumbnail var templateThumbnailProperty = serializedObject.FindProperty(k_TemplateThumbnailPropertyName); var thumbnailField = MakeThumbnailField(templateThumbnailProperty, "Texture"); root.Add(CreateFoldoutInspector(thumbnailField, "Thumbnail", "SceneTemplateInspectorThumbnailFoldout")); // SceneTemplatePipeline var sceneTemplatePipeline = new VisualElement(); sceneTemplatePipeline.Add(new HelpBox(k_ScenteTemplateInfo, HelpBoxMessageType.Info)); var pipelineProperty = serializedObject.FindProperty(k_TemplatePipelineName); var pipelineField = new PropertyField(pipelineProperty, "Scene Template Pipeline") { name = k_SceneTemplatePipelineName }; pipelineField.RegisterCallback <ChangeEvent <Object> >(e => { if (e.newValue != null && !SceneTemplateAsset.IsValidPipeline(e.newValue as MonoScript)) { Debug.LogWarning(k_ScenteTemplateInfo); pipelineProperty.objectReferenceValue = null; serializedObject.ApplyModifiedProperties(); } }); sceneTemplatePipeline.Add(pipelineField); root.Add(CreateFoldoutInspector(sceneTemplatePipeline, "Scene Template Pipeline", "SceneTemplatePipelineFoldout")); // Dependencies root.Add(CreateFoldoutInspector(BuildDependencyRows(), "Dependencies", "SceneTemplateDependenciesFoldout")); root.Bind(serializedObject); return(root); }
public static InstantiationResult Instantiate(SceneTemplateAsset sceneTemplate, bool loadAdditively, string newSceneOutputPath = null) { return(Instantiate(sceneTemplate, loadAdditively, newSceneOutputPath, SceneTemplateAnalytics.SceneInstantiationType.Scripting)); }
public virtual bool IsValidTemplateForInstantiation(SceneTemplateAsset sceneTemplateAsset) { return(true); }
public virtual void BeforeTemplateInstantiation(SceneTemplateAsset sceneTemplateAsset, bool isAdditive, string sceneName) { }
internal static InstantiationResult Instantiate(SceneTemplateAsset sceneTemplate, bool loadAdditively, string newSceneOutputPath, SceneTemplateAnalytics.SceneInstantiationType instantiationType) { if (!sceneTemplate.isValid) { throw new Exception("templateScene is empty"); } if (EditorApplication.isUpdating) { Debug.LogFormat(LogType.Warning, LogOption.None, null, "Cannot instantiate a new scene while updating the editor is disallowed."); return(null); } // If we are loading additively, we cannot add a new Untitled scene if another unsaved Untitled scene is already opened if (loadAdditively && SceneTemplateUtils.HasSceneUntitled()) { Debug.LogFormat(LogType.Warning, LogOption.None, null, "Cannot instantiate a new scene additively while an unsaved Untitled scene already exists."); return(null); } var sourceScenePath = AssetDatabase.GetAssetPath(sceneTemplate.templateScene); if (String.IsNullOrEmpty(sourceScenePath)) { throw new Exception("Cannot find path for sceneTemplate: " + sceneTemplate.ToString()); } if (!Application.isBatchMode && !loadAdditively && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(null); } var instantiateEvent = new SceneTemplateAnalytics.SceneInstantiationEvent(sceneTemplate, instantiationType) { additive = loadAdditively }; sceneTemplate.UpdateDependencies(); var hasAnyCloneableDependencies = sceneTemplate.hasCloneableDependencies; SceneAsset newSceneAsset = null; Scene newScene; var templatePipeline = sceneTemplate.CreatePipeline(); if (!InstantiateInMemoryScene(sceneTemplate, sourceScenePath, ref newSceneOutputPath, out var rootFolder, out var isTempMemory)) { instantiateEvent.isCancelled = true; SceneTemplateAnalytics.SendSceneInstantiationEvent(instantiateEvent); return(null); } templatePipeline?.BeforeTemplateInstantiation(sceneTemplate, loadAdditively, isTempMemory ? null : newSceneOutputPath); newSceneTemplateInstantiating?.Invoke(sceneTemplate, isTempMemory ? null : newSceneOutputPath, loadAdditively); newSceneAsset = AssetDatabase.LoadAssetAtPath <SceneAsset>(newSceneOutputPath); var refPathMap = new Dictionary <string, string>(); var idMap = new Dictionary <int, int>(); if (hasAnyCloneableDependencies) { var clonedAssets = CopyCloneableDependencies(sceneTemplate, newSceneOutputPath, ref refPathMap); idMap.Add(sceneTemplate.templateScene.GetInstanceID(), newSceneAsset.GetInstanceID()); ReferenceUtils.RemapAssetReferences(refPathMap, idMap); foreach (var clone in clonedAssets) { if (clone) { EditorUtility.SetDirty(clone); } } AssetDatabase.SaveAssets(); } newScene = EditorSceneManager.OpenScene(newSceneOutputPath, loadAdditively ? OpenSceneMode.Additive : OpenSceneMode.Single); if (hasAnyCloneableDependencies) { EditorSceneManager.RemapAssetReferencesInScene(newScene, refPathMap, idMap); } EditorSceneManager.SaveScene(newScene, newSceneOutputPath); if (isTempMemory) { newSceneAsset = null; newScene.SetPathAndGuid("", newScene.guid); s_CurrentInMemorySceneState.guid = newScene.guid; s_CurrentInMemorySceneState.rootFolder = rootFolder; s_CurrentInMemorySceneState.hasCloneableDependencies = hasAnyCloneableDependencies; s_CurrentInMemorySceneState.dependencyFolderName = Path.GetFileNameWithoutExtension(newSceneOutputPath); } SceneTemplateAnalytics.SendSceneInstantiationEvent(instantiateEvent); templatePipeline?.AfterTemplateInstantiation(sceneTemplate, newScene, loadAdditively, newSceneOutputPath); newSceneTemplateInstantiated?.Invoke(sceneTemplate, newScene, newSceneAsset, loadAdditively); SceneTemplateUtils.SetLastFolder(newSceneOutputPath); return(new InstantiationResult(newScene, newSceneAsset)); }
public override bool IsValidTemplateForInstantiation(SceneTemplateAsset sceneTemplateAsset) { return(false); }
public virtual void AfterTemplateInstantiation(SceneTemplateAsset sceneTemplateAsset, Scene scene, bool isAdditive, string sceneName) { }
private void TemplateInstantiating(SceneTemplateAsset sceneTemplate, string newSceneOuputPath, bool loadAdditive) { SceneTemplateService.newSceneTemplateInstantiating -= TemplateInstantiating; Close(); }
internal static System.Tuple <Scene, SceneAsset> Instantiate(SceneTemplateAsset sceneTemplate, bool loadAdditively, string newSceneOutputPath, SceneTemplateAnalytics.SceneInstantiationType instantiationType) { if (!sceneTemplate.IsValid) { throw new Exception("templateScene is empty"); } var sourceScenePath = AssetDatabase.GetAssetPath(sceneTemplate.templateScene); if (String.IsNullOrEmpty(sourceScenePath)) { throw new Exception("Cannot find path for sceneTemplate: " + sceneTemplate.ToString()); } if (!Application.isBatchMode && !loadAdditively && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(null); } var instantiateEvent = new SceneTemplateAnalytics.SceneInstantiationEvent(sceneTemplate, instantiationType) { additive = loadAdditively }; sceneTemplate.UpdateDependencies(); var hasAnyCloneableDependencies = sceneTemplate.dependencies.Any(dep => dep.instantiationMode == TemplateInstantiationMode.Clone); SceneAsset newSceneAsset = null; Scene newScene; var templatePipeline = sceneTemplate.CreatePipeline(); if (hasAnyCloneableDependencies) { if (!InstantiateScene(sceneTemplate, sourceScenePath, ref newSceneOutputPath)) { instantiateEvent.isCancelled = true; SceneTemplateAnalytics.SendSceneInstantiationEvent(instantiateEvent); return(null); } templatePipeline?.BeforeTemplateInstantiation(sceneTemplate, loadAdditively, newSceneOutputPath); newSceneTemplateInstantiating?.Invoke(sceneTemplate, newSceneOutputPath, loadAdditively); var refPathMap = new Dictionary <string, string>(); var refMap = CopyCloneableDependencies(sceneTemplate, newSceneOutputPath, ref refPathMap); newScene = EditorSceneManager.OpenScene(newSceneOutputPath, loadAdditively ? OpenSceneMode.Additive : OpenSceneMode.Single); newSceneAsset = AssetDatabase.LoadAssetAtPath <SceneAsset>(newSceneOutputPath); var idMap = new Dictionary <int, int>(); idMap.Add(sceneTemplate.templateScene.GetInstanceID(), newSceneAsset.GetInstanceID()); EditorSceneManager.RemapAssetReferencesInScene(newScene, refPathMap, idMap); EditorSceneManager.SaveScene(newScene, newSceneOutputPath); foreach (var clone in refMap.Values) { if (clone) { EditorUtility.SetDirty(clone); } } AssetDatabase.SaveAssets(); } else { templatePipeline?.BeforeTemplateInstantiation(sceneTemplate, loadAdditively, newSceneOutputPath); newSceneTemplateInstantiating?.Invoke(sceneTemplate, newSceneOutputPath, loadAdditively); if (loadAdditively) { newScene = EditorSceneManager.OpenScene(sourceScenePath, OpenSceneMode.Additive); } else { newScene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); var sourceScene = EditorSceneManager.OpenScene(sourceScenePath, OpenSceneMode.Additive); SceneManager.MergeScenes(sourceScene, newScene); } } SceneTemplateAnalytics.SendSceneInstantiationEvent(instantiateEvent); templatePipeline?.AfterTemplateInstantiation(sceneTemplate, newScene, loadAdditively, newSceneOutputPath); newSceneTemplateInstantiated?.Invoke(sceneTemplate, newScene, newSceneAsset, loadAdditively); SceneTemplateUtils.SetLastFolder(newSceneOutputPath); return(new System.Tuple <Scene, SceneAsset>(newScene, newSceneAsset)); }