9

我知道这可能被问了很多次......但它经常被错误地回答。

我想要的是:

在 Inspector(例如图 2 和图 3)和 ProjectView(例如图 1)中为特定组件/脚本使用自定义图标 替代文字

到目前为止我所做的:

对于每个应具有图标的组件/类,我在文件夹中有一个 accroding Icon 文件

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

并在Import Settigns集合TextureTypeEditor GUI and Legacy GUI

这工作正常.. 直到现在我才能实现这一目标的唯一方法(记住下面的部分我绝对不想要的)。


但是,我想知道是否真的没有更好的方法让每个脚本都有一个唯一的图标文件。这使得项目/UnityPackage 变得不必要地庞大。此外,如果我重命名一个类,我总是必须重命名相应的图标文件......这意味着感觉不对!

大多数 Unity 内置行为和组件都有一个独特的图标。但来自新 PackageManager 的外部包也有内置图标,有时还有一个Gizmos文件夹,但它不遵循上述命名规则......所以显然这个图标是为他们配置的。

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

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

和/或还有哪里/如何为来自 PackageManager 的脚本定义这些图标?


!笔记!我绝对不想要的:

还在 SceneView 中显示所有GameObjects附加了这些组件的图标(例如图 4)。这是由于通过 Inspector 选择此脚本的图标,如图 5 所示(如本文此处,甚至Unity-Assign Icons所建议的那样)或使用OnDrawGizmosDrawGizmo使用我当前对文件夹使用的方法不会发生这种情况Gizmos

替代文字

更新

因为这是在这个答案中建议的:我也知道我可以这样做并通过GizmosSceneView 的设置将它们关闭。但是想象一下,我有 25 个不同的模块和每个不同的图标。我不想在每个项目的基础上一个一个地在 SceneView 设置中禁用他们的 Gizmo!甚至提供的脚本似乎也是一个巨大的hackaround。反思将是我最后的手段。此外,我宁愿根本不让这些图标显示为可能的 Gizmo,而不是全部禁用它们。

4

2 回答 2

3

您可以使用图 5 设置图标,然后从 gizmos 下拉菜单中关闭该图标的 gizmos。

编辑:使用上述步骤的禁令,您可以尝试从这里派生的这个脚本,它使用反射来查找负责关闭小工具和图标的类。这将在您的脚本重新编译以保持这些图标关闭或您将任何新图标添加到自动隐藏图标文件时执行。注意:对于内置组件,scriptClass 将是一个空字符串,例如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 });
                }
            }
        }
    }
}
  1. 在检查器中显示带有 Gizmo

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

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

于 2019-03-13T19:23:49.377 回答
1

因此,我对内置类型以及来自包管理器和资产商店的包进行了更多研究。任何外部的(包管理器或资产存储),如果它具有脚本和检查器的自定义图标,它将始终在场景视图中有一个小工具。因为它使用您的图 5 示例设置了图标,如调试检查器的屏幕截图所示。

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

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

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

场景中显示的 PixelPerfect 图标

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

于 2019-03-18T19:06:21.670 回答