prefabInstanceRoot | 将替换其预制件资源的预制件实例根。 |
prefabAssetRoot | 用于预制件实例的新预制件资源。 |
mode | 使用的交互模式。 |
settings | 用于控制替换详细程度的设置。 |
替换存在于场景中或嵌套在另一个预制件内的预制件实例的预制件资源。
此函数将保留场景中预制件实例根的位置、旋转和缩放,但在合并新预制件资源的内容时,默认情况下将通过基于名称的匹配保留尽可能多的覆盖和引用。请注意,无论ObjectMatchMode如何,根游戏对象及其组件总是会重用这些对象,因此对这些对象的引用总是会替换。如果游戏对象和组件使用其完整的游戏对象层级路径进行匹配,则可以使用ObjectMatchMode.ByHierarchy保留引用,从而确保所有同级元素都有惟一的名称。使用ObjectMatchMode.ByName时,仅当名称匹配是惟一名称时才执行对象匹配。因此,建议预制件实例和预制件资源在游戏对象的层级中只有惟一名称。无法对具有重复名称的游戏对象进行匹配。
不会从预制实例的序列化状态中删除任何属性覆盖,因此在不同的预制资产之间反复替换可保证属性覆盖的无损操作。在决定最终的预制实例后,可以从“Hierarchy”或“Overrides”窗口中清除任何未使用的覆盖。如果名称匹配,则会保留已添加的组件,否则将删除已添加的组件。如果未找到其父级游戏对象的名称匹配项,则会通过将已添加的游戏对象添加到新实例的根目录来保留这些游戏对象。由于已添加的游戏对象可能具有完整的子级层次结构,因此我们任您决定是否在它在新实例中证明多余后删除该对象。可以从“Hierarchy”或“Overrides”窗口执行此操作。若要明确控制应清除哪些覆盖,请使用 PrefabReplacingSettings.prefabOverridesOptions。标志位于 PrefabReplacingSettings 中。
其他资源:ReplacePrefabAssetOfPrefabInstances,ConvertToPrefabInstance。
using System.Collections.Generic; using UnityEditor; using UnityEngine;
class PrefabReplacing { [MenuItem("Assets/Replace Scene Selection with Prefab Asset", false, 32)] static void ReplaceSelectedWithPrefabInstance(MenuCommand menuCommand) { GameObject prefabAsset = null; var listOfInstanceRoots = new List<GameObject>(); var listOfPlainGameObjects = new List<GameObject>(); foreach (var go in Selection.gameObjects) { if (AssetDatabase.Contains(go)) prefabAsset = go; else if (PrefabUtility.IsOutermostPrefabInstanceRoot(go)) listOfInstanceRoots.Add(go); else if (!PrefabUtility.IsPartOfNonAssetPrefabInstance(go)) listOfPlainGameObjects.Add(go); }
if (prefabAsset == null || (listOfInstanceRoots.Count == 0 && listOfPlainGameObjects.Count == 0)) { ShowHelpDialog(prefabAsset); return; }
if (listOfInstanceRoots.Count > 0) { var settings = new PrefabReplacingSettings { logInfo = true, objectMatchMode = ObjectMatchMode.ByHierarchy, prefabOverridesOptions = PrefabOverridesOptions.ClearAllNonDefaultOverrides }; PrefabUtility.ReplacePrefabAssetOfPrefabInstances(listOfInstanceRoots.ToArray(), prefabAsset, settings, InteractionMode.UserAction); }
if (listOfPlainGameObjects.Count > 0) { var settings = new ConvertToPrefabInstanceSettings { logInfo = true, objectMatchMode = ObjectMatchMode.ByHierarchy, }; PrefabUtility.ConvertToPrefabInstances(listOfPlainGameObjects.ToArray(), prefabAsset, settings, InteractionMode.UserAction); } }
[MenuItem("Assets/Replace Scene Selection with Prefab Asset", true, 32)] static bool ValidateReplaceSelectedWithPrefabInstance(MenuCommand menuCommand) { foreach (var go in Selection.gameObjects) { if (AssetDatabase.Contains(go)) return true; }
return false; }
static void ShowHelpDialog(GameObject prefabAsset) { var helptext = "Please make a multiselection with at least one Prefab instance root or plain GameObject in the Scene and one Prefab Asset from the Project Browser. \n\nUse Ctrl/Cmd + Click."; EditorUtility.DisplayDialog("Replace Prefab Asset of Prefab instance", (prefabAsset == null ? "Prefab Asset missing.\n\n" : "Prefab instance missing.\n\n") + helptext, "OK"); } }