为Unity的新版ugui的Prefab生成预览图

2018.3版本的unity有新的嵌套预制体功能,现在预览图很不方便。可以生成一个。

 

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;

[CustomPreview(typeof(GameObject))]
public class UIPreview : ObjectPreview
{
    Texture preview;

    const string cachePreviewPath = "CachePreviews";

    public override bool HasPreviewGUI()
    {
        return true;
    }


    public override void OnPreviewGUI(Rect r, GUIStyle background)
    {
        base.OnPreviewGUI(r, background);
        if (target == null)
            return;

        var targetGameObject = target as GameObject;

        if (targetGameObject == null)
            return;


        GUI.Label(r, target.name + " is being previewed");
        preview = AssetPreview.GetAssetPreview(target);

        
        if (preview == null)
        {
            string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(targetGameObject));

            string pathname = Path.Combine(cachePreviewPath, guid + ".png");
            preview = AssetDatabase.LoadAssetAtPath<Texture2D>(Path.Combine("Assets",pathname));
            if (preview == null)
            {
                preview = GetAssetPreview(targetGameObject);

                if (SaveTexture2D(preview as Texture2D, Path.Combine(Application.dataPath, pathname)))
                {
                    AssetDatabase.ImportAsset(pathname);
                    AssetDatabase.Refresh();
                    Debug.Log("SaveTextureToPNG " + pathname);
                }
            }
        }

        GUI.DrawTexture(r, preview);
    }

    public static Texture GetAssetPreview(GameObject obj)
    {
        GameObject canvas_obj = null;
        GameObject clone = GameObject.Instantiate(obj);
        Transform cloneTransform = clone.transform;

        GameObject cameraObj = new GameObject("render camera");
        Camera renderCamera = cameraObj.AddComponent<Camera>();
        renderCamera.backgroundColor = new Color(0.8f, 0.8f, 0.8f, 1f);
        renderCamera.clearFlags = CameraClearFlags.Color;
        renderCamera.cameraType = CameraType.SceneView;
        renderCamera.cullingMask = 1 << 21;
        renderCamera.nearClipPlane = -100;
        renderCamera.farClipPlane = 100;

        bool isUINode = false;
        if (cloneTransform is RectTransform)
        {
            //如果是UGUI节点的话就要把它们放在Canvas下了
            canvas_obj = new GameObject("render canvas", typeof(Canvas));
            Canvas canvas = canvas_obj.GetComponent<Canvas>();
            cloneTransform.parent = canvas_obj.transform;
            cloneTransform.localPosition = Vector3.zero;
            //canvas_obj.transform.position = new Vector3(-1000, -1000, -1000);
            canvas_obj.layer = 21;//放在21层,摄像机也只渲染此层的,避免混入了奇怪的东西
            canvas.renderMode = RenderMode.ScreenSpaceCamera;
            canvas.worldCamera = renderCamera;
            
            isUINode = true;
        }
        else
            cloneTransform.position = new Vector3(-1000, -1000, -1000);

        Transform[] all = clone.GetComponentsInChildren<Transform>();
        foreach (Transform trans in all)
        {
            trans.gameObject.layer = 21;
        }

        Bounds bounds = GetBounds(clone);
        Vector3 Min = bounds.min;
        Vector3 Max = bounds.max;



        if (isUINode)
        {
            cameraObj.transform.position = new Vector3(0, 0, -10);
            //Vector3 center = new Vector3(cloneTransform.position.x, (Max.y + Min.y) / 2f, cloneTransform.position.z);
            cameraObj.transform.LookAt(Vector3.zero);

            renderCamera.orthographic = true;
            float width = Max.x - Min.x;
            float height = Max.y - Min.y;
            float max_camera_size = width > height ? width : height;
            renderCamera.orthographicSize = max_camera_size / 2;//预览图要尽量少点空白
        }
        else
        {
            cameraObj.transform.position = new Vector3((Max.x + Min.x) / 2f, (Max.y + Min.y) / 2f, Max.z + (Max.z - Min.z));
            Vector3 center = new Vector3(cloneTransform.position.x, (Max.y + Min.y) / 2f, cloneTransform.position.z);
            cameraObj.transform.LookAt(center);

            int angle = (int)(Mathf.Atan2((Max.y - Min.y) / 2, (Max.z - Min.z)) * 180 / 3.1415f * 2);
            renderCamera.fieldOfView = angle;
        }
        RenderTexture texture = new RenderTexture(128, 128, 0, RenderTextureFormat.Default);
        renderCamera.targetTexture = texture;

        var tex = RTImage(renderCamera);

        Object.DestroyImmediate(canvas_obj);
        Object.DestroyImmediate(cameraObj);


        return tex;
    }

    static Texture2D RTImage(Camera camera)
    {
        // The Render Texture in RenderTexture.active is the one
        // that will be read by ReadPixels.
        var currentRT = RenderTexture.active;
        RenderTexture.active = camera.targetTexture;

        // Render the camera's view.
        //camera.Render();

        camera.Render();
        // Make a new texture and read the active Render Texture into it.
        Texture2D image = new Texture2D(camera.targetTexture.width, camera.targetTexture.height);
        image.ReadPixels(new Rect(0, 0, camera.targetTexture.width, camera.targetTexture.height), 0, 0);
        image.Apply();

        // Replace the original active Render Texture.
        RenderTexture.active = currentRT;
        return image;
    }

    public static Bounds GetBounds(GameObject obj)
    {
        Vector3 Min = new Vector3(99999, 99999, 99999);
        Vector3 Max = new Vector3(-99999, -99999, -99999);
        MeshRenderer[] renders = obj.GetComponentsInChildren<MeshRenderer>();
        if (renders.Length > 0)
        {
            for (int i = 0; i < renders.Length; i++)
            {
                if (renders[i].bounds.min.x < Min.x)
                    Min.x = renders[i].bounds.min.x;
                if (renders[i].bounds.min.y < Min.y)
                    Min.y = renders[i].bounds.min.y;
                if (renders[i].bounds.min.z < Min.z)
                    Min.z = renders[i].bounds.min.z;

                if (renders[i].bounds.max.x > Max.x)
                    Max.x = renders[i].bounds.max.x;
                if (renders[i].bounds.max.y > Max.y)
                    Max.y = renders[i].bounds.max.y;
                if (renders[i].bounds.max.z > Max.z)
                    Max.z = renders[i].bounds.max.z;
            }
        }
        else
        {
            RectTransform[] rectTrans = obj.GetComponentsInChildren<RectTransform>();
            Vector3[] corner = new Vector3[4];
            for (int i = 0; i < rectTrans.Length; i++)
            {
                //获取节点的四个角的世界坐标,分别按顺序为左下左上,右上右下
                rectTrans[i].GetWorldCorners(corner);
                if (corner[0].x < Min.x)
                    Min.x = corner[0].x;
                if (corner[0].y < Min.y)
                    Min.y = corner[0].y;
                if (corner[0].z < Min.z)
                    Min.z = corner[0].z;

                if (corner[2].x > Max.x)
                    Max.x = corner[2].x;
                if (corner[2].y > Max.y)
                    Max.y = corner[2].y;
                if (corner[2].z > Max.z)
                    Max.z = corner[2].z;
            }
        }

        Vector3 center = (Min + Max) / 2;
        Vector3 size = new Vector3(Max.x - Min.x, Max.y - Min.y, Max.z - Min.z);
        return new Bounds(center, size);
    }

    public static bool SaveTextureToPNG(Texture inputTex, string save_file_name)
    {
        RenderTexture temp = RenderTexture.GetTemporary(inputTex.width, inputTex.height, 0, RenderTextureFormat.ARGB32);
        Graphics.Blit(inputTex, temp);
        bool ret = SaveRenderTextureToPNG(temp, save_file_name);
        RenderTexture.ReleaseTemporary(temp);
        return ret;
    }

    public static bool SaveTexture2D(Texture2D png, string save_file_name)
    {
        byte[] bytes = png.EncodeToPNG();
        string directory = Path.GetDirectoryName(save_file_name);
        if (!Directory.Exists(directory))
            Directory.CreateDirectory(directory);
        FileStream file = File.Open(save_file_name, FileMode.Create);
        BinaryWriter writer = new BinaryWriter(file);
        writer.Write(bytes);
        file.Close();

        return true;
    }

    //将RenderTexture保存成一张png图片  
    public static bool SaveRenderTextureToPNG(RenderTexture rt, string save_file_name)
    {
        RenderTexture prev = RenderTexture.active;
        RenderTexture.active = rt;
        Texture2D png = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
        png.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        byte[] bytes = png.EncodeToPNG();
        string directory = Path.GetDirectoryName(save_file_name);
        if (!Directory.Exists(directory))
            Directory.CreateDirectory(directory);
        FileStream file = File.Open(save_file_name, FileMode.Create);
        BinaryWriter writer = new BinaryWriter(file);
        writer.Write(bytes);
        file.Close();
        Texture2D.DestroyImmediate(png);
        png = null;
        RenderTexture.active = prev;
        return true;
    }


}

 

参考:https://blog.csdn.net/yudianxia/article/details/79639292

可以预览缩略图的功能:https://blog.csdn.net/x_studying/article/details/89102314

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity 中,可以使用以下 C# 代码自动生成 UGUI 预制体: ```csharp using UnityEditor; using UnityEngine; using UnityEngine.UI; public static class PrefabGenerator { [MenuItem("GameObject/Create UGUI Prefab")] public static void CreateUIPrefab() { // 获取当前选择的 GameObject GameObject selectedObject = Selection.activeGameObject; // 创建一个新的 GameObject 作为存储 Prefab 的容器 GameObject prefabContainer = new GameObject(selectedObject.name + "Prefab"); // 将当前选择的 GameObject 的所有子物体复制到新的容器中 foreach (Transform child in selectedObject.transform) { GameObject childObject = Object.Instantiate(child.gameObject); childObject.transform.SetParent(prefabContainer.transform); } // 添加 Canvas 组件和 Graphic Raycaster 组件 Canvas canvas = prefabContainer.AddComponent<Canvas>(); prefabContainer.AddComponent<GraphicRaycaster>(); // 设置 Canvas 属性 canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.sortingOrder = 0; // 保存 Prefab string path = "Assets/" + selectedObject.name + ".prefab"; Object prefab = PrefabUtility.SaveAsPrefabAsset(prefabContainer, path); // 销毁容器 GameObject 和子物体 Object.DestroyImmediate(prefabContainer); // 在 Project 视中选中新创建的 Prefab Selection.activeObject = prefab; } } ``` 这段代码的作用是创建一个菜单项,可以通过在 Unity 编辑器中点击菜单栏的 GameObject -> Create UGUI Prefab 来自动生成 UGUI 预制体。在创建 Prefab 时,会将当前选择的 GameObject 的所有子物体复制到新的容器中,添加 Canvas 和 Graphic Raycaster 组件,并保存为 Prefab

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值