45.PrefabUtility

45.PrefabUtility


45.1 知识点

PrefabUtility公共类是什么

它是 Unity 编辑器中的一个公共类,提供了一些用于处理 Prefab(预制体或称预设体)的方法。主要功能包括实例化预制体、创建预制体、修改预制体等等。只要你有对预制体操作的相关需求,它可以在编辑器开发的任何地方对其进行使用。

创建自定义面板用于进行知识讲解

using UnityEditor;
using UnityEngine;

public class MyPrefabUtilityLearnWindow : EditorWindow
{
    [MenuItem("编辑器拓展教程/MyPrefabUtilityLearnWindow")]
    private static void OpenMyPrefabUtilityLearnWindow()
    {
        MyPrefabUtilityLearnWindow win = EditorWindow.GetWindow<MyPrefabUtilityLearnWindow>("PrefabUtility知识学习");
        win.Show();
    }

    private void OnGUI()
    {
        
    }
}

常用API

动态创建预设体

private void OnGUI()
{
    // 动态创建预设体 路径从Assets/...开始
    // PrefabUtility.SaveAsPrefabAsset(GameObject对象, 路径);
    if (GUILayout.Button("动态创建预设体"))
    {
        GameObject obj = new GameObject();//场景上也会出现预制体
        obj.AddComponent<Rigidbody>();
        obj.AddComponent<BoxCollider>();
        PrefabUtility.SaveAsPrefabAsset(obj, "Assets/Resources/TestObj.prefab");
        DestroyImmediate(obj);//不想场景上也出现预制体就立即删除
    }
}

加载预制体对象(不能用于创建,一般用于修改,会把预设体加载到内存中)

private void OnGUI()
{
    // 加载预制体对象(不能用于创建,一般用于修改,会把预设体加载到内存中)
    // 路径从Assets/...开始
    // PrefabUtility.LoadPrefabContents(路径)
    // 释放加载的预设体对象
    // PrefabUtility.UnloadPrefabContents(GameObject对象)
    // 注意:这两个方法需要配对使用,加载了就要释放

    // 这里的加载 本质上其实已经把预设体进行了实例化了 只不过该实例化对象并不是在传统的Scene窗口中(是在一个看不见的独立的场景中)
    if (GUILayout.Button("加载预制体对象"))
    {
        // 加载 到内存中 不能用来实例化 一般加载出来是进行修改的  比如给预制体添加组件
        GameObject testObj = PrefabUtility.LoadPrefabContents("Assets/Resources/TestObj.prefab");
        testObj.AddComponent<MeshRenderer>();

        // 拓展:
        // 这种加载方式 是可以进行脚本移除 子对象创建的
        DestroyImmediate(testObj.GetComponent<MeshRenderer>());
        GameObject obj = new GameObject("新建子对象");
        obj.transform.parent = testObj.transform;

        // 覆盖了原先的预制体
        PrefabUtility.SaveAsPrefabAsset(testObj, "Assets/Resources/TestObj.prefab");
        // 释放 一定要配合使用
        PrefabUtility.UnloadPrefabContents(testObj);
    }

}


修改已有预设体

private void OnGUI()
{
    // 修改已有预设体 
    // PrefabUtility.SavePrefabAsset(预设体对象, out bool 是否保存成功);
    // 可以配合AssetDatabase.LoadAssetAtPath使用
    if (GUILayout.Button("修改已有预设体 "))
    {
        GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
        testObj.AddComponent<Camera>();
        // 这个方法不能存储实例化后的内容 只能存储对应的预设体对象
        PrefabUtility.SavePrefabAsset(testObj);
    }
}

实例化预设体

private void OnGUI()
{
    // 实例化预设体
    // PrefabUtility.InstantiatePrefab(Object对象)
    if (GUILayout.Button("实例化预设体"))
    {
        GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
        PrefabUtility.InstantiatePrefab(testObj);
    }
}

更多内容

官方文档:PrefabUtility


45.2 知识点代码

Lesson45_PrefabUtility

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson45_PrefabUtility : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 PrefabUtility公共类是什么

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

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

        #endregion

        #region 知识点二 创建自定义面板用于进行知识讲解

        #endregion

        #region 知识点三 常用API

        //1.动态创建预设体 路径从Assets/...开始
        //  PrefabUtility.SaveAsPrefabAsset(GameObject对象, 路径);

        //2.加载预制体对象(不能用于创建,一般用于修改,会把预设体加载到内存中)
        //  路径从Assets/...开始
        //  PrefabUtility.LoadPrefabContents(路径)
        //  释放加载的预设体对象
        //  PrefabUtility.UnloadPrefabContents(GameObject对象)
        //  注意:这两个方法需要配对使用,加载了就要写在

        //3.修改已有预设体 
        //  PrefabUtility.SavePrefabAsset(预设体对象, out bool 是否保存成功);
        //  可以配合AssetDatabase.LoadAssetAtPath使用

        //4.实例化预设体
        //  PrefabUtility.InstantiatePrefab(Object对象)

        #endregion

        #region 知识点四 更多内容

        //官方文档:https://docs.unity3d.com/2022.3/Documentation/ScriptReference/PrefabUtility.html

        #endregion
    }
}

MyPrefabUtilityLearnWindow

using System;
using UnityEditor;
using UnityEngine;

public class MyPrefabUtilityLearnWindow : EditorWindow
{
    [MenuItem("编辑器拓展教程/MyPrefabUtilityLearnWindow")]
    private static void OpenMyPrefabUtilityLearnWindow()
    {
        MyPrefabUtilityLearnWindow win = EditorWindow.GetWindow<MyPrefabUtilityLearnWindow>("PrefabUtility知识学习");
        win.Show();
    }

    private void OnGUI()
    {
        //1.动态创建预设体 路径从Assets/...开始
        //  PrefabUtility.SaveAsPrefabAsset(GameObject对象, 路径);
        if (GUILayout.Button("动态创建预设体"))
        {
            GameObject obj = new GameObject();//场景上也会出现预制体
            obj.AddComponent<Rigidbody>();
            obj.AddComponent<BoxCollider>();
            PrefabUtility.SaveAsPrefabAsset(obj, "Assets/Resources/TestObj.prefab");
            DestroyImmediate(obj);//不想场景上也出现预制体就立即删除
        }

        
        //2.加载预制体对象(不能用于创建,一般用于修改,会把预设体加载到内存中)
        //  路径从Assets/...开始
        //  PrefabUtility.LoadPrefabContents(路径)
        //  释放加载的预设体对象
        //  PrefabUtility.UnloadPrefabContents(GameObject对象)
        //  注意:这两个方法需要配对使用,加载了就要释放

        //这里的加载 本质上其实已经把预设体进行了实例化了 只不过该实例化对象并不是在传统的Scene窗口中(是在一个看不见的独立的场景中)
        if (GUILayout.Button("加载预制体对象"))
        {
            //加载 到内存中 不能用来实例化 一般加载出来是进行修改的  比如给预制体添加组件
            GameObject testObj = PrefabUtility.LoadPrefabContents("Assets/Resources/TestObj.prefab");
            testObj.AddComponent<MeshRenderer>();
            
            //拓展:
            //这种加载方式 是可以进行脚本移除 子对象创建的
            DestroyImmediate(testObj.GetComponent<MeshRenderer>());
            GameObject obj = new GameObject("新建子对象");
            obj.transform.parent = testObj.transform;
            
            
            //覆盖了原先的预制体
            PrefabUtility.SaveAsPrefabAsset(testObj, "Assets/Resources/TestObj.prefab");
            //释放 一定要配合使用
            PrefabUtility.UnloadPrefabContents(testObj);
        }

        
        //3.修改已有预设体 
        //  PrefabUtility.SavePrefabAsset(预设体对象, out bool 是否保存成功);
        //  可以配合AssetDatabase.LoadAssetAtPath使用
        if (GUILayout.Button("修改已有预设体 "))
        {
            GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
            testObj.AddComponent<Camera>();
            //这个方法不能存储实例化后的内容 只能存储对应的预设体对象
            PrefabUtility.SavePrefabAsset(testObj);
        }

        
        //4.实例化预设体
        //  PrefabUtility.InstantiatePrefab(Object对象)
        if (GUILayout.Button("实例化预设体"))
        {
            GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
            PrefabUtility.InstantiatePrefab(testObj);
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏