UG4L21——窗口

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Window                                //窗口类,该类可以继承,以封装窗口的逻辑
window.Show() //显示窗口
window.contentPane //设置窗口对应的组件
window.Hide() //隐藏窗口
window.isShowing //窗口是否在显示
window.modal //设置窗口是否为模态窗口
window.ShowModalWait() //锁定窗口
window.CloseModalWait() //解除窗口的锁定
OnInit() //窗口对象被实例化出来时执行的方法
​OnShown()​ //窗口显示时执行的方法
​OnHide()​ //窗口隐藏时执行的方法
DoShowAnimation() //播放显示动画
DoHideAnimation() //播放隐藏动画
GRoot.inst.BringToFront() //把窗口提到所有窗口最前面
GRoot.inst.CloseAllWindows() //隐藏所有窗口
GRoot.inst.CloseAllExceptModals() //隐藏所有非模态窗口
GRoot.inst.GetTopWindow() //返回当前显示在最上面的窗口
GRoot.inst.hasModalWindow //当前是否有模态窗口在显示
UIConfig.bringWindowToFrontOnClick //是否开启窗口自动排序功能,该属性可以决定是否在点到某个窗口时就让某个窗口显示在最前

窗口

窗口是组件的一种特殊拓展,窗口可以设置任意组件作为它的显示内容
窗口 = 内容组件 + 窗口管理API

如何制作窗口内容组件

  1. 窗口内容组件需放置一个名称为 frame 的组件,一般作为窗口的背景

    image

  2. 窗口内容组件 frame 组件中可以有的内容

    1. closeButton — 名为 closeButton 的按钮,作为关闭按钮

      image

    2. dragArea — 名为 dragArea 的空白图形,作为可拖动窗口的拖动区域

      image

    3. contentArea — 名为 contentArea 的空白图形,作为窗口主要内容显示区域

      这个区域只用于API ShowModalWait​,当调用ShowModalWait​时,窗口会被锁定
      如果设定了contentArea​,则只锁定contentArea​指定的区域,否则锁定整个窗口
      如果你希望窗口在modalWait​状态下依然能够拖动和关闭,那么就不要让contentArea覆盖标题栏区域

      image

这些内容皆为可选,不是必须,
意思是 是否有名为frame的组件,或者该组件中是否有closeButton、dragArea、contentArea都是可选项
这些内容主要是帮助我们使用FairyGUI自带的API来调整窗口
没有这些组件只是不能使用FairyGUI提供给我们的窗口自带功能而已

Unity中使用窗口

窗口类相关API

  1. 显示窗口

    显示窗口和之前的显示面板不一样,在加载出窗口组件后,
    创建窗口类,直接将组件与contentPane​相关联,然后直接使用Show()​方法即可显示,而不需要添加到GRoot下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //设置分辨率自适应
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    //加载包以及依赖包
    UIPackage package = UIPackage.AddPackage("UI/teach");
    foreach (var item in package.dependencies)
    {
    UIPackage.AddPackage(item["name"]);
    }
    //创建窗口类,将窗口组件加载出来后,与contentPane相关联,然后直接使用Show方法即可显示
    Window window = new Window();
    window.contentPane = UIPackage.CreateObject("teach", "WindowTest").asCom;
    window.Show();

    显示效果:​image

    如果之前添加了frame组件,并且在frame上面添加了closeButton和dragArea,那么这个窗口是可拖曳可关闭的

  2. 隐藏窗口

    使用Window.Hide()​方法即可直接隐藏

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //设置分辨率自适应
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    //加载包(跳过依赖包加载)
    UIPackage package = UIPackage.AddPackage("UI/teach");
    //创建窗口类,将窗口组件加载出来后,与contentPane相关联,然后直接使用Show方法即可显示
    Window window = new Window();
    window.contentPane = UIPackage.CreateObject("teach", "WindowTest").asCom;
    window.Show();
    window.Hide();
  3. 获取窗口是否显示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //设置分辨率自适应
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    //加载包(跳过依赖包加载)
    UIPackage package = UIPackage.AddPackage("UI/teach");
    //创建窗口类,将窗口组件加载出来后,与contentPane相关联,然后直接使用Show方法即可显示
    Window window = new Window();
    window.contentPane = UIPackage.CreateObject("teach", "WindowTest").asCom;
    window.contentPane.MakeFullScreen(); //设置分辨率自适应
    window.Show();
    if (window.isShowing)
    {
    print("窗口显示着");
    }

    输出:image

  4. 窗口设置为模态

    何为模态窗口,可参考GUI.ModalWindow()​,简单来说模态窗口可以让该窗口以外的其他可见控件不再可以被点击到

    通过modal​属性设置是否为模态窗口,如果要设置为模态,一定是Show()​之前就要设置
    在显示模态窗口前,可以通过UIConfig.modalLayerColor​来设置模态窗口背后的遮罩颜色

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //设置分辨率自适应
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    //加载包(跳过依赖包加载)
    UIPackage package = UIPackage.AddPackage("UI/teach");
    //设置模态窗口的背景颜色
    UIConfig.modalLayerColor = new Color(0, 0, 0, 0.5f);
    //创建窗口类,将窗口组件加载出来后,与contentPane相关联,然后直接使用Show方法即可显示
    Window window = new Window();
    window.contentPane = UIPackage.CreateObject("teach", "WindowTest").asCom;
    window.contentPane.MakeFullScreen(); //设置分辨率自适应
    window.modal = true; //设置为模态窗口
    window.Show();

    显示效果:image

  5. 锁定窗口

    跳过ShowModalWait()​可以锁定窗口防止误操作窗口

    比如充值面板 点击重置过后 可能会和服务器进行通讯 需要等待
    可以通过UIConfig.windowModalWaiting​ 设定锁定窗口时的提示资源,避免玩家不知道被锁定了,这个提示可以给它一些反馈

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //设置分辨率自适应
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    //加载包(跳过依赖包加载)
    UIPackage package = UIPackage.AddPackage("UI/teach");
    //设置模态窗口的背景颜色
    UIConfig.modalLayerColor = new Color(0, 0, 0, 0.5f);
    //创建窗口类,将窗口组件加载出来后,与contentPane相关联,然后直接使用Show方法即可显示
    Window window = new Window();
    window.contentPane = UIPackage.CreateObject("teach", "WindowTest").asCom;
    window.contentPane.MakeFullScreen(); //设置分辨率自适应
    window.modal = true;
    window.Show();
    window.ShowModalWait();

    显示效果(被设置的锁定资源显示在窗口上,覆盖位置与大小取决于contentArea的参数(不包括锚点参数)):
    image

    要注意,如果在FairyGUI的编辑器中没有为窗口添加frame的contentArea,则整个窗口都会被锁住
    这就会让窗口的closeButton和dragArea失效,设置不遮挡closeButton和dragArea可以防止窗口的拖曳和关闭也失效

  6. 取消窗口锁定

    使用window.CloseModalWait()​即可关闭窗口的锁定

    1
    window.CloseModalWait();

窗口的高级使用

继承窗口类

之前我们是通过创建一个窗口类然后关联窗口组件,最后显示的方法来显示窗口

1
2
3
4
5
6
void Start()
{
Window window = new Window();
window.contentPane = UIPackage.CreateObject("teach", "TeachPanel").asCom;
window.Show();
}

但是这种方法并不够面向对象,因为我们创建的整个窗口并不是指定的某一个窗口,每次创建一个窗口都需要在外部的类中手动关联,比较麻烦
因此可声明一个继承窗口的类,将某种窗口的行为封装到对应的继承的窗口的类中,外部只需要调用这些方法

继承窗口类后,有以下的关键方法可以重写:

  1. 初始化

    初始化方法是OnInit()​,实例化时窗口对象时就会调用这里的方法,
    该方法内可以关联要显示的组件,设置分辨率自适应,添加监听函数等等

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class TeachWindow : Window
    {
    protected override void OnInit()
    {
    base.OnInit();
    UIPackage.AddPackage("UI/teach");
    this.contentPane = UIPackage.CreateObject("teach", "TeachPanel").asCom;
    this.contentPane.MakeFullScreen();
    this.contentPane.GetChild("btnTest").asButton.onClick.Add(() =>
    {
    Debug.Log("点击按钮");
    });
    }
    }

    外部想要显示窗口时,创建了继承窗口的类对象之后,直接使用Show()​方法即可打开窗口

    1
    2
    3
    4
    5
    6
    void Start()
    {
    GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
    TeachWindow teachWindow = new TeachWindow();
    teachWindow.Show();
    }

    显示效果:image

  2. 显示自己

    OnShown()​ 是窗口显示时 会自动调用的函数,我们可以在这里面处理一些 窗口显示时 想要处理的逻辑

    注意!如果重写了DoShowAnimation()​,且其中不调用父类的DoShowAnimation()​,
    就需要自己在DoShowAnimation()​内在恰当的时机调用OnShown()​!!!

    1
    2
    3
    4
    5
    protected override void OnShown()
    {
    base.OnShown();
    Debug.Log("显示自己时");
    }
  3. 隐藏自己

    OnHide()​ 当窗口隐藏时 会自动调用的函数,我们可以在这里面处理一些 窗口隐藏时 想要处理的逻辑

    注意!如果重写了DoHideAnimation()​,且其中不调用父类的DoHideAnimation()​,
    就需要自己在DoHideAnimation()​内在恰当的时机调用OnHide()​!!!

    1
    2
    3
    4
    5
    protected override void OnHide()
    {
    base.OnHide();
    Debug.Log("隐藏自己时");
    }
  4. 播放显示动画

    显示时,DoShowAnimation()​可以处理显示播放动画重写, 可以在这里面自己处理一些动效内容,
    如果不调用base.DoShowAnimation()(父类方法会执行OnShow() 那么需要自己在该方法里调用一次OnShown()​

    动效具体内容:UG4L24——动效

    假设窗口有一个淡入显示动效show​:image

    如果我们要在窗口显示时调用播放该动效,就需要在DoShowAnimation()​内调用该动效的transition.Play()​方法
    我们可以在动画播放完毕后调用OnShown()​或者base.DoShowAnimation()​或者在其他恰当的时机调用

    1
    2
    3
    4
    protected override void DoShowAnimation()
    {
    this.contentPane.GetTransition("show").Play(base.DoShowAnimation);
    }
  5. 播放隐藏动画

    隐藏时,DoHideAnimation()​可以处理播放动画重写, 可以在这里面自己处理一些动效内容,
    如果不调用base.DoHideAnimation()(父类方法会执行OnHide()),那么需要自己在该方法里调用一次OnHide()

    动效具体内容:UG4L24——动效

    假设窗口有一个淡入显示动效hide​:image

    如果我们要在窗口显示时调用播放该动效,就需要在DoHideAnimation()​内调用该动效的transition.Play()​方法
    我们可以在动画播放完毕后调用OnHide()​或者base.DoHideAnimation()​,或者在其他恰当的时机调用

    1
    2
    3
    4
    protected override void DoHideAnimation()
    {
    this.contentPane.GetTransition("hide").Play(base.DoHideAnimation);
    }

窗口管理

  1. 把窗口提到所有窗口最前面

    传入要显示在最前面的窗口类对象

    1
    GRoot.inst.BringToFront(teachWindow);
  2. 隐藏所有窗口

    1
    GRoot.inst.CloseAllWindows();
  3. 隐藏所有非模态窗口

    1
    GRoot.inst.CloseAllExceptModals();
  4. 返回当前显示在最上面的窗口

    1
    GRoot.inst.GetTopWindow();
  5. 当前是否有模态窗口在显示

    1
    2
    3
    4
    if (GRoot.inst.hasModalWindow)
    {
    Debug.Log("有模态窗口显示");
    }
  6. 窗口自动排序功能

    该属性可以决定是否在点到某个窗口时就让某个窗口显示在最前,常用于PC游戏,手机游戏使用较少

    1
    2
    //该属性可以决定是否在点到某个窗口时就让某个窗口显示在最前
    UIConfig.bringWindowToFrontOnClick = false;

使用GRoot显示还是使用Window显示

  • GRoot​中,子对象层级需要我们自己去管理控制
  • Window​中,它帮助我们实现了很多排序相关的功能

一般采用混用的方式:

  • 主界面、战斗界面等全屏面板使用GRoot​添加
  • 背包、人物、商城等弹出面板用Window​添加