如何在Unity3D中自定义脚本图标而不使用"Assets/Gizmos"目录

9

我知道这个问题可能已经被问了很多次,但是很多时候回答都是错误的。

我想要的是:

在检查器中为特定的组件/脚本(例如图2和图3)以及项目视图(例如图1)使用自定义图标 alt text

我到目前为止所做的:

对于每个需要有图标的组件/类,我在文件夹中有一个相应的图标文件。

Assets/Gizmos/<Path>/<To>/<Namespace>/<ClassName> icon

在“导入设置”中,将“TextureType”设置为“Editor GUI和Legacy GUI”

这很好用...直到现在我能够实现它(考虑下面的部分“我绝对不想要什么”)。


但是

然而,我想知道是否真的没有更好的方法来为每个脚本设置唯一的图标文件。这使得项目/UnityPackage变得不必要地巨大。而且如果我重命名一个类,我总是需要重新命名相应的图标文件…这似乎不太合适!

大多数Unity内置的Behaviours和Components都有一个独特的图标。但是来自新的PackageManager的外部Packages也有内置的图标,有时还有一个文件夹,但它并没有遵循上述命名规则…所以显然它们的图标是以其他方式配置的。

因此我的问题是:
是否有更好的方法来为脚本/组件设置这些图标?

最好是通过脚本编写,并重用一个单一的图标文件,而不是在多个不同命名的文件中使用相同的图标。

或者那些来自PackageManager的脚本的图标是如何定义的?


!注意! 我绝对不想要的内容:

在所有已附加这些组件的GameObjects中(例如图4),也在SceneView中显示图标。这是通过通过检查器选择该脚本的图标(如图5中始终建议的那样,例如在this posthere中,甚至通过Unity - Assign Icons)或使用OnDrawGizmosDrawGizmo引起的。 使用我当前使用的Gizmos文件夹的方法不会发生这种情况!

alt text

更新

因为这是在此答案中建议的:我也知道我可以通过场景视图的Gizmos设置来关闭它们。 但是想象一下,我有大约25个不同的模块和各种不同的图标。我不想每个项目都需要逐个禁用它们在SceneView设置中的Gizmos!即使提供的脚本看起来像是一个巨大的hackaround。反射将是我最后采取的选择。此外,我更喜欢根本不要让这些图标出现为可能的Gizmos,而不是全部禁用它们。

2个回答

3
您可以使用图5设置图标,然后从gizmos下拉菜单中关闭该图标的小工具。 编辑: 结合上面的步骤,您可以尝试使用从这里提取的脚本,它使用反射查找负责关闭gizmos和图标的类。每当您的脚本重新编译时,此脚本都会执行以保持那些图标关闭,或者如果您添加了任何新的自动隐藏图标文件,则也会执行。 注意:对于内置组件(例如Camera, AudoSource),scriptClass将是一个空字符串。
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 });
                }
            }
        }
    }
}
  1. 在检查器中用gizmo显示

  2. 从gizmos下拉菜单中隐藏图标

  3. 图标仍然出现在检查器和项目视图中,但在场景中不显示


感谢您的回答..当然我已经考虑过这个问题..但是我有大约30个不同的模块,每个模块都有各种不同的图标,如果按照这种方式关闭它们,那么在每个项目中都需要一个一个地关闭它们..所以与当前解决方案相比,这不是我的选择。正如我所说,当前的解决方案基本上可以正常工作。 - derHugo
我找到了一种方法,可以使用脚本来自动隐藏您不想看到的图标,以补充我的答案。 - BrightenedLight
我有53个 scriptClass = "",你应该也差不多。另外,我添加了一个检查,一旦检测到没有名称的 scriptClass 就跳过它。 - BrightenedLight
嘿,再次感谢你的回答。我又测试了一下,基本上是可以工作的,所以你完全值得这个奖励。不过出于某种原因,我还没有完全信服,但这并不否定你提供的一个坚实的替代方案比我目前所做的更好 :) - derHugo
是的,我完全同意你的看法。这应该更容易一些,也许在未来Unity会将此API公开。 - BrightenedLight
显示剩余3条评论

1
所以,我更深入地研究了内置类型以及来自包管理器和资源商店的软件包。任何外部的东西(packagemanager或assetstore)如果它有一个脚本和检查器的自定义图标,它将始终在场景视图中具有gizmo。正如您在图5示例中所设置的图标一样,在调试检查器的屏幕截图中可以看到。

此外,如果您想使用脚本设置图标或隐藏它,当前反射是您唯一的选择,因为这些API不可公开访问。

我的脚本显示其脚本的调试检查器

来自packagemanager的PixelPerfect软件包脚本在调试检查器中

PixelPerfect图标在场景中显示

我希望将此作为对您原始问题的评论添加,但还没有足够的声望。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接