UEDL13——PrefabUtility公共类

本章代码关键字

1
2
3
4
5
6
PrefabUtility                            //提供用于处理 Prefab(预制体或称预设体)的方法的公共类
PrefabUtility.SaveAsPrefabAsset() //动态创建预设体文件
PrefabUtility.LoadPrefabContents() //加载预设体到内存内,可以用于深度修改预设体,如添加移除游戏对象或脚本,或者修改父子关系,使用完毕必须释放
PrefabUtility.UnloadPrefabContents() //卸载加载到内存的预设体,LoadPrefabContents()调用后必须调用该方法
PrefabUtility.SavePrefabAsset() //保存对预设体文件的修改,局限性较大
PrefabUtility.InstantiatePrefab() //将预设体文件对象实例化到场景后上

PrefabUtility公共类

它是 Unity 编辑器中的一个公共类,提供了一些用于处理 Prefab(预制体或称预设体)的方法
主要功能包括 实例化预制体、创建预制体、修改预制体 等等

只要你有对预制体操作的相关需求,它可以在编辑器开发的任何地方对其进行使用

关于PrefabUtility相关的更多内容:

常用API

  1. PrefabUtility.SaveAsPrefabAsset()​ 动态创建预设体文件 路径从 Assets/...​ 开始

    • 参数一:要保存为本地预设体文件的游戏对象的数据(GameObject​类型数据)
    • 参数二:保存路径(需要加上.prefab​后缀名),该路径是基于工程所在的路径的,路径从 Assets/...​ 开始

    注意:需要加上.prefab​后缀名

    1
    2
    3
    4
    5
    6
    7
    8
    if (GUILayout.Button("动态创建预设体"))
    {
    GameObject obj = new GameObject();
    obj.AddComponent<Rigidbody>();
    obj.AddComponent<BoxCollider>();
    PrefabUtility.SaveAsPrefabAsset(obj, "Assets/Resources/TestObj.prefab");
    DestroyImmediate(obj); //立刻删除,因为Destory只能在运行模式下的下一帧删除,在编辑器模式下表现就是无法删除并报错
    }

    效果如下:image

  2. PrefabUtility.LoadPrefabContents()​ 加载预制体对象到内存中,路径从 Assets/...​ 开始
    (不能用于实例化创建游戏对象,一般只用于修改,会把预设体加载到内存中)

    这里的加载,本质上其实已经把预设体进行实例化了,因此这里加载的预设体不能用于创建游戏对象
    只不过该实例化对象并不是在传统的Scene窗口中(是在一个看不见的独立的场景中,它类似于在编辑器窗口直接打开预设体)
    由于这个加载是将预设体实例化了,
    因此通过该方法修改预设体,我们可以修改预设体内的游戏对象相关的内容,例如添加对象,创建或修改父子关系等,还可以移除脚本

    • 参数:要加载的预制体文件路径,该路径是基于工程所在的路径的,路径从 Assets/...​ 开始

    PrefabUtility.UnloadPrefabContents()​ 释放加载的预设体对象

    • 参数:要释放的从预制体文件内加载出来的游戏对象

    注意:这两个方法需要配对使用,加载了就要在使用完毕后调用释放方法,否则该预设体将一直占用内存!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (GUILayout.Button("加载预设体对象"))
    {
    //加载 到内存中 不能用来实例化 一般加载出来是进行修改预设体的
    GameObject testObj = PrefabUtility.LoadPrefabContents("Assets/Resources/TestObj.prefab");
    //修改
    testObj.AddComponent<MeshRenderer>();
    GameObject obj = new GameObject("新建子对象");
    obj.transform.parent = testObj.transform;
    //将修改保存到本地
    PrefabUtility.SaveAsPrefabAsset(testObj, "Assets/Resources/TestObj.prefab");
    //释放 一定要配合使用
    PrefabUtility.UnloadPrefabContents(testObj);
    }

    效果如下:
    imageimage
    imageimage

  3. PrefabUtility.SavePrefabAsset()​修改已有预设体文件,配合AssetDatabase.LoadAssetAtPath​使用

    注意!不可使用 PrefabUtility.LoadPrefabContents()加载预制体,因为它加载的预设体会是实例化到另一个不可见场景内的预设体对象
    如果PrefabUtility.LoadPrefabContents() ​,保存将会报错,它会提示不可对实例化的预设体进行修改

    1
    2
    3
    4
    5
    6
    7
    if (GUILayout.Button("修改已有预设体"))
    {
    GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
    testObj.AddComponent<BoxCollider>();
    PrefabUtility.SavePrefabAsset(testObj, out bool isSuccess);
    Debug.Log(isSuccess);
    }

    值得一提的是,上面的方法修改的预设体限于添加脚本,不能修改预设体内游戏对象相关,也不能移除脚本,以及一些需要实例化对象才能完成的操作

    效果如下:image

  4. PrefabUtility.InstantiatePrefab()​ 实例化预设体

    • 参数一:从预设体文件对象实例化一个游戏对象到场景上,配合AssetDatabase.LoadAssetAtPath​使用
    • 参数二:(可选)设置实例化出来的对象的父对象
    1
    2
    3
    4
    5
    if (GUILayout.Button("实例化预设体"))
    {
    GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
    PrefabUtility.InstantiatePrefab(testObj);
    }

    效果如下:image