一:在项目中创建一个名为 Editor 的文件夹(如果还没有)。
二:在该文件夹下新建一个 C# 脚本, UnpackAllPrefabsInScene.cs。复制粘贴以下代码。
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public class UnpackAllPrefabsInScene
{
[MenuItem("Tools/Unpack All Prefabs in Scene Completely")]
static void UnpackAllPrefabsCompletely()
{
if (!EditorApplication.isPlaying)
{
GameObject[] allRootObjects = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
List<GameObject> prefabInstances = new List<GameObject>();
// 收集所有根对象及其子对象中属于预制体实例的对象
foreach (GameObject root in allRootObjects)
{
prefabInstances.AddRange(GetAllPrefabInstances(root));
}
if (prefabInstances.Count == 0)
{
Debug.Log("当前场景中没有预制体实例。");
return;
}
// 开始 Undo 批量操作(可撤销)
Undo.RecordObjects(prefabInstances.ToArray(), "Unpack All Prefabs Completely");
int count = 0;
foreach (GameObject instance in prefabInstances)
{
if (PrefabUtility.IsPartOfAnyPrefab(instance))
{
PrefabUtility.UnpackPrefabInstance(instance, PrefabUnpackMode.Completely, InteractionMode.UserAction);
count++;
}
}
Debug.Log($"成功完全解包 {count} 个预制体实例。");
}
else
{
Debug.LogWarning("请在编辑模式下运行此操作。");
}
}
// 递归获取 GameObject 及其所有子对象中属于预制体实例的对象
static List<GameObject> GetAllPrefabInstances(GameObject root)
{
List<GameObject> result = new List<GameObject>();
if (PrefabUtility.IsPartOfAnyPrefab(root))
{
result.Add(root);
}
foreach (Transform child in root.transform)
{
result.AddRange(GetAllPrefabInstances(child.gameObject));
}
return result;
}
}
三:打开你的场景。点击顶部菜单栏:Tools → Unpack All Prefabs in Scene Completely。Unity 会自动遍历整个场景层级,对所有预制体实例执行 完全解包(Unpack Completely)。操作完成后,控制台会显示解包数量。
四:注意事项
- 此操作不完全可逆,可以使用ctrl+z撤回,但复杂嵌套结构可能无法完美还原。
- 仅在编辑模式下有效,运行时不会执行。
- 解包后,对象将不再与原始 .prefab 文件关联,修改原预制体不会影响这些对象。
- 如果你只想解包选中的对象,也可以稍作修改,配合 Selection.activeTransform 使用。
Comments NOTHING