作Unity工具的时候,功能虽然很重要,但是美观也很重要。所以,用Unity内置自带的图标,会感觉更好看一点。
那么问题来了,你怎么得到Unity的内置图标呢?
雨松MOMO写过个博客,他反编译了一下editor的dll,用正则把图标信息给提取了出来。可是没看过反编译怎么办?【雨松MOMO:他的图标】
那其实也还有其他的方法。我们可以直接用 Resources 的 FindObjectsOfTypeAll 先看看。
/*
* 查看所有 Textures
*
*
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class UnityIconsWindow : EditorWindow
{
[MenuItem(("JJJ/Unity Textures Window"))]
static void Init()
{
UnityIconsWindow window = EditorWindow.GetWindow<UnityIconsWindow>("Unity Textures Window");
//加载所有Texture2D
window.textures = Resources.FindObjectsOfTypeAll<Texture2D>();
window.minSize = new Vector2(200, 400);
//用于GUI
window.fullRect = new Rect();
foreach (var texture in window.textures)
{
window.fullRect.height += texture.height + 15 + 5 + 10;
}
}
Vector2 scrollPos;
Texture2D[] textures;
Rect fullRect;
void OnGUI()
{
Rect scrollrect = new Rect();
scrollrect.width = position.width;
scrollrect.height = position.height;
scrollPos = GUI.BeginScrollView(scrollrect, scrollPos, fullRect);
Rect r = new Rect();
r.x = 10;
Rect box = new Rect();
box.x = 7;
box.width = position.width - 30;
foreach (Texture2D texture in textures)
{
box.y = r.y;
box.height = 15 + 5 + texture.height + 2;
GUI.Box(box, "");
r.height = 15;
r.width = position.width;
//绘制名字
GUI.Label(r, texture.name);
r.y += r.height;
r.y += 5;
r.height = texture.height;
r.width = texture.width;
//绘制图标
GUI.DrawTexture(r, texture);
r.y += texture.height;
r.y += 10;
}
GUI.EndScrollView();
}
}
接下来,我们就可以看到很多见过的图标。
最好是在新建一个空项目里面,因为项目自己本身的Texture也会加载进来。
但是其中我发现了一些问题,有一些Texture 的 name字段是空?
这也行吗?但是没关系,问题不大,我们不用它们。
那现在我们看到了这些图片,怎么在我们的工具里用它们呢?这你总不能每次用它都加载,然后遍历,取名字一样的吧?
其实,Unity是有API通过名字获得具体的Icon,
public static GUIContent IconContent (string name, string text= null);
//name 所需图标的名称。
//text 悬停在图标上的工具提示。
//从具有给定名称的 Unity 内置资源中获取 GUIContent。
//EditorGUIUtility.IconContent 用于为 GUI 元素创建 GUIContent。
//只会加载图标.通常情况下,将使用第一个参数获取 Assets/Editor Default Resources/Icons 中的图标。
//只需要图标的名称,而不需要 png 扩展名。 \ 第二个参数为悬停工具提示提供文本。
//此字符串 需要以竖线“|”字符开头以将其标记为工具提示。
//注意:目前无法悬停定位在工具提示上方。
要创建 GUIContent 就直接这个API就好了,那如果只是要 Texture 呢?那也很简单,
Texture texture = EditorGUIUtility.IconContent("IconName").image;
但实际上并不是所有的Icon都可以通过这个函数取出来,这个函数能取出来的只有在 Assets/Editor Default Resoureces/Icons 里的图标。
我们改一下上面的脚本:
/*
* 查看所有 Textures
*
*
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class UnityIconsWindow : EditorWindow
{
[MenuItem(("JJJ/Unity Textures Window"))]
static void Init()
{
UnityIconsWindow window = EditorWindow.GetWindow<UnityIconsWindow>("Unity Textures Window");
//加载所有Texture2D
window.textures = Resources.FindObjectsOfTypeAll<Texture2D>();
window.minSize = new Vector2(200, 400);
//可见
window.textures2 = new Texture2D[window.textures.Length];
for (int i = 0; i < window.textures2.Length; i++)
{
window.textures2[i] = EditorGUIUtility.IconContent(window.textures[i].name).image as Texture2D;
}
//用于GUI
window.fullRect = new Rect();
//foreach (var texture in window.textures)
//{
// window.fullRect.height += texture.height + 15 + 5 + 10;
//}
for (int i = 0; i < window.textures2.Length; i++)
{
if (window.textures2[i] != null)
{
window.fullRect.height += window.textures2[i].height + 15 + 5 + 10;
}
}
}
Vector2 scrollPos;
Texture2D[] textures;
Texture2D[] textures2;
Rect fullRect;
void OnGUI()
{
Rect scrollrect = new Rect();
scrollrect.width = position.width;
scrollrect.height = position.height;
scrollPos = GUI.BeginScrollView(scrollrect, scrollPos, fullRect);
Rect r = new Rect();
r.x = 10;
Rect box = new Rect();
box.x = 7;
box.width = position.width - 30;
foreach (Texture2D texture in textures2)
{
if (texture == null) continue;
box.y = r.y;
box.height = 15 + 5 + texture.height + 2;
GUI.Box(box, "");
r.height = 15;
r.width = position.width;
//绘制名字
GUI.Label(r, texture.name);
r.y += r.height;
r.y += 5;
r.height = texture.height;
r.width = texture.width;
//绘制图标
GUI.DrawTexture(r, texture);
r.y += texture.height;
r.y += 10;
}
GUI.EndScrollView();
}
private void OnDisable()
{
textures = null;
}
}
打开窗口:
从报错来看就显而易见了,要么你给个该图片的项目完整路径(包括拓展名),要么,它就必须是 Assets/Editor Default Resoureces/Icons 里的图标名字(不用拓展名)。
那我们先把报错藏起来,再试一下给它个完整项目路径试试:
/*
* 查看所有 Textures
*
*
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class UnityIconsWindow : EditorWindow
{
[MenuItem(("JJJ/Unity Textures Window"))]
static void Init()
{
UnityIconsWindow window = EditorWindow.GetWindow<UnityIconsWindow>("Unity Textures Window");
//加载所有Texture2D
window.textures = Resources.FindObjectsOfTypeAll<Texture2D>();
window.minSize = new Vector2(200, 400);
//可见
window.textures2 = new Texture2D[window.textures.Length];
Debug.unityLogger.logEnabled = false;//关掉那个报错,不用管它
for (int i = 0; i < window.textures2.Length; i++)
{
if (window.textures[i].name == "微信图片_20210808203939")//这样写很愚蠢,只是为了作为一个例子才这样写
window.textures2[i] = EditorGUIUtility.IconContent(AssetDatabase.GetAssetPath(window.textures[i])).image as Texture2D;
else
window.textures2[i] = EditorGUIUtility.IconContent(window.textures[i].name).image as Texture2D;
}
Debug.unityLogger.logEnabled = true;
//用于GUI
window.fullRect = new Rect();
//foreach (var texture in window.textures)
//{
// window.fullRect.height += texture.height + 15 + 5 + 10;
//}
for (int i = 0; i < window.textures2.Length; i++)
{
if (window.textures2[i] != null)
{
window.fullRect.height += window.textures2[i].height + 15 + 5 + 10;
}
}
}
Vector2 scrollPos;
Texture2D[] textures;
Texture2D[] textures2;
Rect fullRect;
void OnGUI()
{
Rect scrollrect = new Rect();
scrollrect.width = position.width;
scrollrect.height = position.height;
scrollPos = GUI.BeginScrollView(scrollrect, scrollPos, fullRect);
Rect r = new Rect();
r.x = 10;
Rect box = new Rect();
box.x = 7;
box.width = position.width - 30;
foreach (Texture2D texture in textures2)
{
if (texture == null) continue;
box.y = r.y;
box.height = 15 + 5 + texture.height + 2;
GUI.Box(box, "");
r.height = 15;
r.width = position.width;
//绘制名字
GUI.Label(r, texture.name);
r.y += r.height;
r.y += 5;
r.height = texture.height;
r.width = texture.width;
//绘制图标
GUI.DrawTexture(r, texture);
r.y += texture.height;
r.y += 10;
}
GUI.EndScrollView();
}
private void OnDisable()
{
textures = null;
}
}
再打开窗口:
完美,可以看到第一个就是了。
那我们就可以考虑有这样一个工具类,当我们需要Icon时,只需要通过这个脚本就可以。
using UnityEngine;
using UnityEditor;
public static class JIconUtility
{
//比如需要一个文件夹图标,就可以这样写
static Texture2D directoryIcon;
public static Texture2D DirectoryIcon {
get {
if (directoryIcon == null) directoryIcon = EditorGUIUtility.IconContent("Folder Icon").image as Texture2D; return directoryIcon; } }
//其他的你自定义的icon其实也可以放在这里,只不过不是用 EditorGUIUtility.IconContent() ,而是要直接 Resources.Load 加载
static Texture2D myIcon;
public static Texture2D MyIcon {
get {
if (myIcon == null) myIcon = Resources.Load<Texture2D>("MyIcon"/*自定义icon路径*/); return myIcon; } }
}
或者你也可以用 EditorGUIUtility.Load() 或者 EditorGUIUtility.LoadRequired() 来加载内置资源。