Unity ugui非常不友好!自定义控件创建流程。
[TOC]
刚接触unity ugui,觉得以下几点非常不友好
- 好的工具软件都有顺手的快捷键,为有如此编辑过程才能高效生产。然而!!!万万没想到!Unity居然没有创建控件的快捷键。目前都要从Hierarchy窗口右键->UI,或者菜单GameObject->UI创建控件。
- 很多控件不需要勾选raycastTarget。但创建的控件默认勾选raycastTarget。而选了raycastTarget的控件,会额外参与摄像机的UI事件计算。所以为了避免不必要的消耗,我们在每次创建控件后,都要手动关闭该选项。
- 各个游戏项目可能使用了各自的非默认字库。但Text默认使用了Arial.ttf字库。所以每次创建后,都要重新选择字库。
有如下几个方法解决上面问题
- 查看UnityEditor.UI是否允许设置自定义控件的创建过程
- 修改ugui源码。使用它满足我们项目的要求
- 覆盖创建控件的菜单命令
创建控件的代码在ui/UnityEditor.UI/UI/MenuOptions.cs1,我详细看了一下,未发现有可以委托创建控件的设定,即方法1不可行。修改源码的做法不够通用,实在办法时再来考虑方法2。而方法3比较容易实现.
定义菜单命令,需要用到UnityEditor.MenuItem特性,举个简单的例子为静态方法添加特性[MenuItem(“Menu1/item1”)],重新编译代码后,会在顶部菜单出现菜单项如下图
再添加字符#&t
即可为Menu1/item1
菜单命令绑定快捷键shift+alt+t,如[MenuItem("Menu1/item1 #&t")]
。如果是#&a
,即绑定为shift+alt+a。关于UnityEditor.MenuItem详细说明见官方文档2。
英文字符 | win按键 | mac按键 |
---|---|---|
% | CTRL | CMD |
# | Shift | Shift |
& | alt | alt |
以下是简单创建Image控件示例,它覆盖了Unity原有的菜单命令GameObject/UI/Image
并且绑定了快捷键shift+alt+i
[MenuItem("GameObject/UI/Image #&i")]
public static void CreateImage(MenuCommand menuCommand)
{
GameObject go = new GameObject("Image", typeof(Image));
go.GetComponent<Image>().raycastTarget = false;
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
Selection.activeObject = go;
}
以下是另外一个做法。它复用了UGUI创建控件的原有代码,内部接口会将新创建的控件缓存在全局变量Selection.activeGameObject
。当内部方法调用结束后,对Selection.activeGameObject
对象稍加调整即可。由于内部接口声明为internal,以下用到了反射进行调用。
private static System.Type type = null;
public static System.Type GetMenuOptionsClass()
{
if (type == null)
{
type = System.Type.GetType("UnityEditor.UI.MenuOptions,UnityEditor.UI");
}
return type;
}
private static Dictionary<string, System.Reflection.MethodInfo> dict = null;
public static GameObject Invoke(string funcName, MenuCommand menuCommand)
{
if (string.IsNullOrEmpty(funcName))
{
return null;
}
if (!dict.ContainsKey(funcName))
{
System.Type type = System.Type.GetType("UnityEditor.UI.MenuOptions,UnityEditor.UI");
System.Reflection.MethodInfo func = type.GetMethod(funcName);
if (func != null)
{
dict.Add(funcName, func);
}
else
{
Debug.LogError("找不到方法: " + funcName);
return null;
}
}
dict[funcName].Invoke(null, new System.Object[] { menuCommand });
return Selection.activeGameObject;
}
/// <summary>
/// 重写CreateImage,不勾选raycastTarget
/// </summary>
[MenuItem("GameObject/UI/Image")]
public static void CreateImage(MenuCommand menuCommand)
{
GameObject go = Invoke("AddImage", menuCommand);
if (go != null)
{
go.GetComponent<Image>().raycastTarget = false;
}
}
原文:
https://lizijie.github.io/2019/05/23/ugui%E9%9D%9E%E5%B8%B8%E4%B8%8D%E5%8F%8B%E5%A5%BD-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%A7%E4%BB%B6%E5%88%9B%E5%BB%BA%E6%B5%81%E7%A8%8B.html
作者github:
https://github.com/lizijie