如何在 Unity3D 中使用 "Assets/Gizmos" 以外的自定义脚本图标
How to have custom script icons other than using "Assets/Gizmos" in Unity3D
我知道这个问题可能被问过很多次了..但经常回答错误。
我想要的是:
在 Inspector(例如图 2 和图 3)和 ProjectView(例如图 1)中为特定 components/scripts 使用自定义图标
到目前为止我做了什么:
对于每个应该有图标的 component/class 我在文件夹中有一个相应的图标文件
Assets/Gizmos/<Path>/<To>/<Namespace>/<ClassName> icon
并在 Import Settigns
中将 TextureType
设置为 Editor GUI and Legacy GUI
这工作正常.. 直到现在,这是我实现它的唯一方法(考虑到下面的部分我绝对不想要的)。
但是
但是,我想知道是否真的没有更好的方法让每个脚本都有一个唯一的图标文件。这使得 project/UnityPackage 不必要地巨大。此外,如果我重命名 class,我总是必须重命名相应的图标文件......这意味着感觉不对!
大多数 Unity 内置行为和组件都有一个独特的图标。但来自新 PackageManager 的外部包也有内置图标,有时还有一个 Gizmos
文件夹,但它不遵循上述命名规则......所以显然图标是以其他方式为它们配置的。
因此我的问题:
有没有更好的方法让 scripts/components 使用这些图标?
最好编写脚本并重复使用一个图标文件,而不是在多个不同名称的文件中使用相同的图标。
And/or 还有 Where/How 这些图标是为来自 PackageManager 的脚本定义的吗?
!注意!我绝对不想要的:
在 SceneView 中也显示所有 GameObjects
附加了这些组件的图标(例如图 4)。这是通过如图 5 中的检查器选择此脚本的图标引起的(如 this post or here and even by Unity - Assign Icons ) or using OnDrawGizmos or DrawGizmo 中一直建议的那样)。使用我目前使用的方法并没有发生这种情况 Gizmos
文件夹!
更新
因为 中建议这样做:我也知道我可以这样做并通过 SceneView 的 Gizmos
设置关闭它们。 但是 想象一下我有 25 个不同的模块和各种不同的图标。我不想在每个项目的基础上一个一个地禁用 SceneView 设置中的 Gizmo!即使是提供的脚本看起来也像是一个巨大的 hackaround。反思将是我最后采取的手段。此外,我宁愿根本不让这些图标显示为可能的 Gizmo,而不是将它们全部禁用。
您可以使用图 5 设置图标,然后从小工具下拉菜单中关闭该图标的小工具。
编辑: 上面步骤的指令你可以试试这个派生自 here 的脚本,它使用反射找到负责关闭的 class小发明和图标。这将在您的脚本重新编译以保留这些图标的任何时候执行,或者如果您将任何新图标添加到自动隐藏图标文件中。 注意: scriptClass 对于内置组件 eg.Camera、AudoSource
将是一个空字符串
using UnityEditor;
using System;
using System.Reflection;
public class DisableAllGizmos
{
[UnityEditor.Callbacks.DidReloadScripts]
private static void OnScriptsReloaded()
{
var Annotation = Type.GetType("UnityEditor.Annotation, UnityEditor");
var ClassId = Annotation.GetField("classID");
var ScriptClass = Annotation.GetField("scriptClass");
var Flags = Annotation.GetField("flags");
var IconEnabled = Annotation.GetField("iconEnabled");
Type AnnotationUtility = Type.GetType("UnityEditor.AnnotationUtility, UnityEditor");
var GetAnnotations = AnnotationUtility.GetMethod("GetAnnotations", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
var SetIconEnabled = AnnotationUtility.GetMethod("SetIconEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Array annotations = (Array)GetAnnotations.Invoke(null, null);
foreach (var a in annotations)
{
int classId = (int)ClassId.GetValue(a);
string scriptClass = (string)ScriptClass.GetValue(a);
int flags = (int)Flags.GetValue(a);
int iconEnabled = (int)IconEnabled.GetValue(a);
// this is done to ignore any built in types
if (string.IsNullOrEmpty(scriptClass))
{
continue;
}
// load a json or text file with class names
const int HasIcon = 1;
bool hasIconFlag = (flags & HasIcon) == HasIcon;
// Added for refrence
//const int HasGizmo = 2;
//bool hasGizmoFlag = (flags & HasGizmo) == HasGizmo;
if (/*Compare class names in file to scriptClass == true*/)
{
if (hasIconFlag && (iconEnabled != 0))
{
UnityEngine.Debug.LogWarning(string.Format("Script:'{0}' is not ment to show its icon in the scene view and will auto hide now. " +
"Icon auto hide is checked on script recompile, if you'd like to change this please remove it from the config",scriptClass));
SetIconEnabled.Invoke(null, new object[] { classId, scriptClass, 0 });
}
}
}
}
}
在检查器中显示了一个 gizmo
从小工具下拉菜单中隐藏图标
图标仍然出现在检查器和项目视图中,但不在场景中
所以我对内置类型以及来自包管理器和资产商店的包进行了更多研究。任何外部的东西(packagemanager 或 assetstore),如果它有脚本和检查器的自定义图标,它将 Always 在场景视图中有一个 gizmo。因为它使用图 5 示例设置了图标,如调试检查器的屏幕截图所示。
此外,如果您想使用脚本设置图标或隐藏它,目前反射是您的唯一选项,因为这些 API 不可公开访问。
My Script showing the debug inspector for its script
PixelPerfect package script from the packagemanager in the debug inspector
PixelPerfect Icon showing in the scene
我希望将此添加为对您的原始问题的评论,但还没有足够的代表。
我知道这个问题可能被问过很多次了..但经常回答错误。
我想要的是:
在 Inspector(例如图 2 和图 3)和 ProjectView(例如图 1)中为特定 components/scripts 使用自定义图标
到目前为止我做了什么:
对于每个应该有图标的 component/class 我在文件夹中有一个相应的图标文件
Assets/Gizmos/<Path>/<To>/<Namespace>/<ClassName> icon
并在 Import Settigns
中将 TextureType
设置为 Editor GUI and Legacy GUI
这工作正常.. 直到现在,这是我实现它的唯一方法(考虑到下面的部分我绝对不想要的)。
但是
但是,我想知道是否真的没有更好的方法让每个脚本都有一个唯一的图标文件。这使得 project/UnityPackage 不必要地巨大。此外,如果我重命名 class,我总是必须重命名相应的图标文件......这意味着感觉不对!
大多数 Unity 内置行为和组件都有一个独特的图标。但来自新 PackageManager 的外部包也有内置图标,有时还有一个 Gizmos
文件夹,但它不遵循上述命名规则......所以显然图标是以其他方式为它们配置的。
因此我的问题:
有没有更好的方法让 scripts/components 使用这些图标?
最好编写脚本并重复使用一个图标文件,而不是在多个不同名称的文件中使用相同的图标。
And/or 还有 Where/How 这些图标是为来自 PackageManager 的脚本定义的吗?
!注意!我绝对不想要的:
在 SceneView 中也显示所有 GameObjects
附加了这些组件的图标(例如图 4)。这是通过如图 5 中的检查器选择此脚本的图标引起的(如 this post or here and even by Unity - Assign Icons ) or using OnDrawGizmos or DrawGizmo 中一直建议的那样)。使用我目前使用的方法并没有发生这种情况 Gizmos
文件夹!
更新
因为 Gizmos
设置关闭它们。 但是 想象一下我有 25 个不同的模块和各种不同的图标。我不想在每个项目的基础上一个一个地禁用 SceneView 设置中的 Gizmo!即使是提供的脚本看起来也像是一个巨大的 hackaround。反思将是我最后采取的手段。此外,我宁愿根本不让这些图标显示为可能的 Gizmo,而不是将它们全部禁用。
您可以使用图 5 设置图标,然后从小工具下拉菜单中关闭该图标的小工具。
编辑: 上面步骤的指令你可以试试这个派生自 here 的脚本,它使用反射找到负责关闭的 class小发明和图标。这将在您的脚本重新编译以保留这些图标的任何时候执行,或者如果您将任何新图标添加到自动隐藏图标文件中。 注意: scriptClass 对于内置组件 eg.Camera、AudoSource
将是一个空字符串using UnityEditor;
using System;
using System.Reflection;
public class DisableAllGizmos
{
[UnityEditor.Callbacks.DidReloadScripts]
private static void OnScriptsReloaded()
{
var Annotation = Type.GetType("UnityEditor.Annotation, UnityEditor");
var ClassId = Annotation.GetField("classID");
var ScriptClass = Annotation.GetField("scriptClass");
var Flags = Annotation.GetField("flags");
var IconEnabled = Annotation.GetField("iconEnabled");
Type AnnotationUtility = Type.GetType("UnityEditor.AnnotationUtility, UnityEditor");
var GetAnnotations = AnnotationUtility.GetMethod("GetAnnotations", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
var SetIconEnabled = AnnotationUtility.GetMethod("SetIconEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Array annotations = (Array)GetAnnotations.Invoke(null, null);
foreach (var a in annotations)
{
int classId = (int)ClassId.GetValue(a);
string scriptClass = (string)ScriptClass.GetValue(a);
int flags = (int)Flags.GetValue(a);
int iconEnabled = (int)IconEnabled.GetValue(a);
// this is done to ignore any built in types
if (string.IsNullOrEmpty(scriptClass))
{
continue;
}
// load a json or text file with class names
const int HasIcon = 1;
bool hasIconFlag = (flags & HasIcon) == HasIcon;
// Added for refrence
//const int HasGizmo = 2;
//bool hasGizmoFlag = (flags & HasGizmo) == HasGizmo;
if (/*Compare class names in file to scriptClass == true*/)
{
if (hasIconFlag && (iconEnabled != 0))
{
UnityEngine.Debug.LogWarning(string.Format("Script:'{0}' is not ment to show its icon in the scene view and will auto hide now. " +
"Icon auto hide is checked on script recompile, if you'd like to change this please remove it from the config",scriptClass));
SetIconEnabled.Invoke(null, new object[] { classId, scriptClass, 0 });
}
}
}
}
}
在检查器中显示了一个 gizmo
从小工具下拉菜单中隐藏图标
图标仍然出现在检查器和项目视图中,但不在场景中
所以我对内置类型以及来自包管理器和资产商店的包进行了更多研究。任何外部的东西(packagemanager 或 assetstore),如果它有脚本和检查器的自定义图标,它将 Always 在场景视图中有一个 gizmo。因为它使用图 5 示例设置了图标,如调试检查器的屏幕截图所示。
此外,如果您想使用脚本设置图标或隐藏它,目前反射是您的唯一选项,因为这些 API 不可公开访问。
My Script showing the debug inspector for its script
PixelPerfect package script from the packagemanager in the debug inspector
PixelPerfect Icon showing in the scene
我希望将此添加为对您的原始问题的评论,但还没有足够的代表。