UG4L10——组件拓展类

组件类拓展

FairyGUI提供了绑定一个类为组件的扩展类的功能,让我们可以更加面向对象的进行编程
回顾目前显示面板,处理面板逻辑的方式,目前我们的面板并没有声明一个类与之对应专门处理该面板的逻辑
这样的写法显然是不够面向对象的

通过view面板获取它的子对象 然后处理子对象 对应逻辑 初始化 或者 事件监听
组件类拓展就可以将某一个面板的逻辑封装到指定类当中

实现组件类拓展

  1. 创建自定义类继承 GComponent

    1
    2
    3
    using FairyGUI;

    public class MyPanel : GComponent { }
  2. 重写 ConstructFromXML​ 方法,在其中初始化面板相关控件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    using FairyGUI;
    using FairyGUI.Utils;
    using UnityEngine;

    public class MyPanel : GComponent
    {
    public GTextInput inputTxt;
    public GButton btnTest;

    public override void ConstructFromXML(XML xml)
    {
    base.ConstructFromXML(xml);
    //在这里初始化面板相关内容
    inputTxt = this.GetChild("inputTxt").asTextInput;
    btnTest = this.GetChild("btnTest").asButton;

    btnTest.onClick.Add(() =>
    {
    Debug.Log("按钮点击");
    });
    }
    }
  3. 在该类中处理面板逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    using FairyGUI;
    using FairyGUI.Utils;
    using UnityEngine;

    public class MyPanel : GComponent
    {
    public GTextInput inputTxt;
    public GButton btnTest;

    public override void ConstructFromXML(XML xml)
    {
    base.ConstructFromXML(xml);
    //在这里初始化面板相关内容
    inputTxt = this.GetChild("inputTxt").asTextInput;
    btnTest = this.GetChild("btnTest").asButton;

    btnTest.onClick.Add(() =>
    {
    Debug.Log("按钮点击");
    });
    }

    public void ShowInfo(string info)
    {
    inputTxt.text = info;
    }
    }
  4. 将自定义类和对应组件进行注册关联UIObjectFactory.SetPackageItemExtension("组件URL地址", typeof(自定义类));
    这一步要在创建面板前执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class Lesson35 : MonoBehaviour
    {
    // Start is called before the first frame update
    void Start()
    {
    //设置适配相关
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    //加载包及其依赖包
    UIPackage package = UIPackage.AddPackage("UI/teach");
    foreach (var item in package.dependencies)
    {
    UIPackage.AddPackage(item["name"]);
    }

    //进行面板和自定义类关系的注册
    UIObjectFactory.SetPackageItemExtension("ui://teach/TeachPanel", typeof(MyPanel));
    //由于我们注册了,所以我们在创建面板时,他会自动和自定义类进行关联,因此我们可以用自定义去装载它
    MyPanel panel = (MyPanel)UIPackage.CreateObject("teach", "TeachPanel").asCom;
    //最后将创建出来的面板放到GRoot对象上,显示面板
    GRoot.inst.AddChild(panel);

    //调用面板类的方法
    panel.ShowInfo("唐老狮的课");
    }
    }

调用面板类的方法,显示效果如下:

image

点击左上角的按钮输出:image

FairyGUI编辑器导出代码功能

如果每多一个面板,就要多拓展一个组件类作为面板类显然是较为麻烦的,不过FairyGUI提供了自动生成代码的功能,它在发布设置内

image

  • 不生成使用默认名称的成员

    对于那些没有修改过名字的n开头的控件,我们往往不需要去获取它
    因此该选项可以默认勾选

  • 使用名称获取成员对象

    如果不勾选,则生成的代码将会是通过索引去获取控件

全局设置设置了之后,还需要到包设置内勾选为本包生成代码

image

最后点击发布,就会自动生成C#脚本

image

  • 生成的脚本分为两种

  • 一种是包名+Binder​绑定类,一个包只有一个

    这种类包括:

    • BindAll​ 方法

      该方法实现了所有生成的组件拓展类脚本注册

  • 另一种组件名前缀+组件名​组件拓展类,所有被导出的组件都会生成一个

    这种类包括:

    • 组件内所有的控件的成员变量

    • 该组件的url地址常量

    • CreateInstance​方法

      从包内创建一个组件对象返回出去

    • ConstructFromXML​方法

      找到组件下的控件并赋值到对应的成员变量上

如何使用生成的代码:

在加载了包之后,调用 包名+Binder​ 绑定类的 BindAll​ 方法完成注册,
然后调用 组件名前缀+组件名​ 组件拓展类的 CreateInstance​ 方法,
最后将 CreateInstance​ 方法返回的组件拓展类对象添加到 GRoot​ 对象下,即可完成组件的显示

如果要为诸如按钮,下拉框等组件下的控件添加监听方法,可以在外部的类中添加,
也可以生成的组件拓展类的ConstructFromXML方法添加(不要这样做)
组件的逻辑可以在外部的类中实现,也可以在生成的组件拓展类中实现(不要这样做),但是要注意:

  1. 要避免生成的代码 把现有的关键逻辑覆盖了,不要将组件逻辑写在生成的组件拓展类中!!!
  2. 要注意生成的代码 控件名变化了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/** This is an automatically generated class by FairyGUI. Please do not modify it. **/

using FairyGUI;
using FairyGUI.Utils;
using UnityEngine;

namespace teach
{
public partial class TeachPanel : GComponent
{
// ..忽略其他控件
public GTextInput m_inputTxt;
public GButton m_btnTest;
public const string URL = "ui://16zntd2ykeur21";

public static TeachPanel CreateInstance()
{
return (TeachPanel)UIPackage.CreateObject("teach", "TeachPanel");
}

public override void ConstructFromXML(XML xml)
{
base.ConstructFromXML(xml);
// ..忽略其他控件
m_inputTxt = (GTextInput)GetChildAt(14);
m_btnTest = (GButton)GetChildAt(18);
}
}
}

值得一提的是,虽然我们不能在生成的组件拓展类脚本内实现逻辑,但由于FairyGUI编辑器生成的组件拓展类声明采用的是 分部类 partial

因此,我们完全可以额外创建一个脚本,再使用分部类 partial​ 关键字声明组件拓展类的另一部分,
在组件拓展类另一部分实现面板逻辑,我们将实现面板逻辑的那部分脚本,保存在非生成脚本的路径下,
这样即使FairyGUI编辑器重新生成了脚本,另一部分的实现面板逻辑的脚本也不会被覆盖

不过,我们还是要注意生成的代码 是否会控件名变化的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using FairyGUI;
using UnityEngine;

namespace teach
{
public partial class TeachPanel : GComponent
{
public void AddListener()
{
m_btnTest.onClick.Add(() =>
{
Debug.Log("点击按钮");
});
}

public void ShowInfo(string str)
{
m_inputTxt.text = str;
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//设置适配相关
GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
//加载包及其依赖包
UIPackage package = UIPackage.AddPackage("UI/teach");
foreach (var item in package.dependencies)
{
UIPackage.AddPackage(item["name"]);
}

teachBinder.BindAll();
TeachPanel panel = TeachPanel.CreateInstance();
GRoot.inst.AddChild(panel);
panel.AddListener()
panel.ShowInfo("唐老狮123");

显示效果:image

点击左上角的按钮输出:image