关于如何在 Unity 的 UI 菜单中默认创建出的控件 Raycast Target 属性默认为 false

关于如何在 Unity 的 UI 菜单中默认创建出的控件 Raycast Target 属性默认为 false

我们在 Unity 中通过 UI 菜单创建的各种控件,比如 Text, Image 等,它们的 Raycast Target 属性默认都是勾选的,这意味着他们会响应点击等时间,Unity 会将其加入到事件的响应队列,所以 UI 中这种控件数量很多时,是很影响性能的,确定不需要响应时间的都可以将改选项的勾选去掉。但是默认创建的都是全部勾选的,不过想要修改下这里面的细节又不破坏整体的使用习惯也是可行的。

UGUI 的源码打开找到 MenuOptions.cs 这里面就是实现 UI 菜单创建控件的代码。不过直接修改这部分的源码或者拷贝到项目里去修改,并且添加一系列新的 UI 菜单并不是我们希望的,我们希望直接接入原有 UI 菜单的创建过程,并且这部分源码并不是所有接口都在外部可访问,所以直接拷贝到项目也不一定可行,所以利用反射是一个好办法。

我们可以看到 UGUI 的源码中定义了各个菜单的位置,例如:[MenuItem("GameObject/UI/Text", false, 2000)],我们可以在自己的项目中重载此菜单的位置,也就是说如果我们在项目中定义了同样的 MenuItem,那么最终响应菜单点击事件的将是我们定义的函数。例如 我们在项目中创建 Editor 文件夹,创建一个 C# 文件,添加一个函数:

[MenuItem("GameObject/UI/Text", false, 2000)]
static public void AddText(MenuCommand menuCommand)
{
    Debug.Log("This is an overrided AddText.");
}

编译完成后,点击菜单 GameObject/UI/Text 来创建一个 Text,会发现除了输出以上的 Log,什么也没创建,说明重载成功,接下来只需要利用反射,按照已有的 UGUI 源码按需求修改即可。例如如何重载创建一个 Raycast Target 为 false 的 Text 控件:

// Add by yaukey(https://github.com/yaukeywang) at 2017-10-11.
// Extend default ui menu.

using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Reflection;

[InitializeOnLoad]
static internal class UIMenuOptionsExtend
{
    // The reflected dafault methods.
    private static MethodInfo m_miGetDefaultResource = null;
    private static MethodInfo m_miPlaceUIElementRoot = null;

    static UIMenuOptionsExtend()
    {
        Initialize();
    }

    private static void Initialize()
    {
        // Get all loaded assemblies.
        Assembly[] allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
        Assembly uiEditorAssembly = null;
        foreach (Assembly assembly in allAssemblies)
        {
            AssemblyName assemblyName = assembly.GetName();
            if ("UnityEditor.UI" == assemblyName.Name)
            {
                uiEditorAssembly = assembly;
                break;
            }
        }

        // Check if we find ui assembly.
        if (null == uiEditorAssembly)
        {
            Debug.LogError("Can not find assembly: UnityEditor.UI.dll");
            return;
        }

        // Get things we need.
        Type menuOptionType = uiEditorAssembly.GetType("UnityEditor.UI.MenuOptions");
        m_miGetDefaultResource = menuOptionType.GetMethod("GetStandardResources", BindingFlags.NonPublic | BindingFlags.Static);
        m_miPlaceUIElementRoot = menuOptionType.GetMethod("PlaceUIElementRoot", BindingFlags.NonPublic | BindingFlags.Static);
    }

    [MenuItem("GameObject/UI/Text", false, 2000)]
    static public void AddText(MenuCommand menuCommand)
    {
        GameObject go = DefaultControls.CreateText((DefaultControls.Resources)m_miGetDefaultResource.Invoke(null, null));
        m_miPlaceUIElementRoot.Invoke(null, new object[] { go, menuCommand });

        // Remove raycast target.
        Text text = go.GetComponent<Text>();
        text.raycastTarget = false;
    }
}

此时点击菜单 GameObject/UI/Text 创建出的 Text,属性 Raycast Target 即为 false。这样就可以几乎无缝修改引擎自定义的行为,同时保留原有的使用习惯。

以上源码完整版下载地址:http://pan.baidu.com/s/1nvA6R0H,提取码:setx

posted @ 2017-10-11 12:29  yaukey  阅读(1897)  评论(0编辑  收藏  举报