【问题标题】:How to have custom script icons other than using "Assets/Gizmos" in Unity3D除了在 Unity3D 中使用“Assets/Gizmos”之外,如何使用自定义脚本图标
【发布时间】:2018-07-18 08:41:01
【问题描述】:

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

我想要的是:

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

到目前为止我做了什么:

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

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

并在Import Settigns 中将TextureType 设置为Editor GUI and Legacy GUI

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


但是

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

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

因此我的问题是:
有没有更好的方法让这些图标用于脚本/组件?

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

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


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

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

更新

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

【问题讨论】:

    标签: unity3d customization unity3d-editor unity-editor


    【解决方案1】:

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

    编辑: 使用上述步骤的禁令,您可以尝试从here 派生的这个脚本,它使用反射来查找负责关闭小工具和图标的类。这将在您的脚本重新编译以保持这些图标关闭或您将任何新图标添加到自动隐藏图标文件时执行。 注意: 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. 从小工具下拉菜单中隐藏图标

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

    【讨论】:

    • 感谢您的回答..当然我已经想到了..但是我有 30 个不同的模块,每个模块都有不同的图标..我不想一个接一个地关闭它们在每个项目的基础上一个......所以与目前的解决方案相比,正如所说的基本上可以按预期工作,这对我来说不是一个选择。
    • 我找到了一种方法来用脚本来补充我的答案,以自动隐藏你不想看到的图标
    • 刚刚测试过...scriptClass = "" 用于所有条目,所以它不起作用。另外......这对我来说似乎是一个巨大的解决方法。主要有两个原因:1. 对任何事情使用反射.. 是我最后的手段.. 2. 我知道这听起来可能是一个模糊的论点,但只要让它出现在 Gizmos 中就可以给出一个用户感觉他可以启用和禁用某些东西..总是重新禁用它似乎是“意外”行为。不要误会我的意思,你的回答很好,并且证明了一些更深层次的背景知识,但我觉得这还不是 解决方案:)
    • 我 100% 同意你应该只在没有其他选项的情况下使用反射,并且因为 unity 不会公开这个 api,反射是唯一的方法,或者你可以使用当前的解决方案和相应的文件夹到命名空间和类名。还有 scriptClass = "" 内置类型,如相机和音频源,但如果你的项目中有 textmeshpro,你应该看到它们的 scriptClass 名称。您使用的是哪个 Unity/OS 版本?
    • v 2018.3.4f1 .. 它没有禁用我的图标,这就是我开始调试的原因,但老实说,在我看到前 20 个带有 scriptClass = "" 的条目后,我停止了调试,所以我会尝试稍后再试一次;)我用if(string.Equals(scriptClass, typeof(My class).Name)))试了一下,也许那里也出了问题
    【解决方案2】:

    所以我对内置类型以及来自包管理器和资产商店的包进行了更多研究。任何外部的东西(packagemanager 或 assetsstore),如果它具有脚本和检查器的自定义图标,它将始终在场景视图中具有 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

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

    【讨论】:

      猜你喜欢
      • 2012-08-29
      • 1970-01-01
      • 2020-09-06
      • 1970-01-01
      • 2021-02-05
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      • 1970-01-01
      相关资源
      最近更新 更多