【系列文章目录】


文章目录


前言

本篇我们来创建FGUI的窗口管理类


一、显示普通窗口

1.使用PuerTS创建一个FGUI窗口

FGUI文档中有关于窗口系统的描述【FGUI文档——窗口系统】

按照文档中的说法

我们在创建一个高层级的组件的时候

不应该直接将组件放在GRoot下(FGUI的根节点)

而是应该先创建窗口再放置这些组件

首先我们创建一个UI管理器,并为他添加以下方法

public static async ShowWnd(pkg: string,name: string) {//异步加载FGUI包资源await $promise(API.LoadFairyGUIPackage(pkg));//创建窗口let win: FairyGUI.Window = new FairyGUI.Window();//创建窗口内容win.contentPane = FairyGUI.UIPackage.CreateObject(pkg, name).asCom;//全屏显示win.MakeFullScreen();//显示窗口win.Show();
}

使用上面的方法我们就可以创建一个窗口并将组件作为窗口中的内容放在窗口中显示

这样我们通过窗口的API可以更容易的控制界面

2.拓展窗口基类

我们可以使用FGUI的窗口可以作为基类,进行拓展

export interface IGwndController extends IController {//窗口的拓展接口
}export abstract class AbstractGWndController extends FairyGUI.Window implements IGwndController{//窗口的拓展实现
}

这样我们就拓展好了FGUI的窗口

3.创建拓展窗口

在游戏中,我希望每个窗口都有自己的类

而上面的抽象类只作为一个模板存在

export class WndLogin extends AbstractGWndController{//具体窗口的实现
}

这样我们就拥有了实际窗口类,他们与FGUI编辑器中我们所设计的界面一一对应

所以我们需要将他们的对于关系存储起来

先思考一个我们需要一个什么样的结构

  • key:用于创建窗口时索引窗口信息的值,唯一
  • pkgName:组件所在包名
  • itemId:组件名
  • script:窗口类
  • windName:窗口名

这样我们就先定义了一个接口类型

export interface IUIInfo {pkgName: stringitemId: stringscript: anywindName: string
}

然后我们建了一个类专门用于管理窗口信息与组件拓展信息

export class UITable {public static UIWindow = {WndGameMain: { pkgName: "GameMain", itemId: "WndGameMain", script: WndGameMain, windName: "WndGameMain" },WndLogin: { pkgName: "Login", itemId: "WndLogin", script: WndLogin, windName: "WndLogin" },}
}

这样我们在需要创建窗口的时候只需要填入窗口名,就可以把窗口创建出来了,修改以下窗口创建函数

public static async ShowWnd(windName: string) {let info: IUIInfo = UITable.UIWindow[windName]//判断是否存在窗口信息if (info != null) {let pkg = info.pkgNamelet name = info.itemIdlet scr = info.scriptlet wndName = info.windName//异步加载FGUI包资源await $promise(API.LoadFairyGUIPackage(pkg))//创建窗口let win: AbstractGWndController = new scr();win.name = wndName;//创建窗口内容win.contentPane = FairyGUI.UIPackage.CreateObject(pkg, name).asCom;win.MakeFullScreen();//绑定子组件(这个方法自行拓展)win.BindChild(win);FairyGUI.GRoot.inst.ShowWindow(win);}else {TSLog.Error("WindowName:【" + windName + "】 does not exist or is misspelled,Please check the spelling");}
}

这样我们就可以通过我们自己的UI管理器创建出一个我们自己拓展的窗口了

二、显示弹出窗口

接下来我们来做弹出窗口即点击空白区域会自动关闭的窗口

首先,不要总想着自己一个人造车,先翻一下FGUI文档吧

于是我在FGUI的文档中找到了【FGUI文档——Popup】的内容

按照文档中的描述,十分的简单

显示普通窗口我们用的是

窗口类中Show()的方法

而显示弹出窗口我们只需要把需要这个效果的窗口作为参数传入
FairyGUI.GRoot.inst.ShowPopup()这个方法就可以了

由于创建窗口的部分与普通窗口时公用的,所以我将它分离出来

//有窗口返回窗口,无窗口创建窗口
private async GetWnd(windName: string): Promise<AbstractGWndController> {let info: IUIInfo = UITable.UIWindow[windName]if (info == null) {TSLog.Error("WindowName:【" + windName + "】 does not exist or is misspelled,Please check the spelling");return null;}try {if (this.HasWnd(windName)) {return this.Map_WndInstance.get(windName);}else {let pkg = info.pkgNamelet name = info.itemIdlet scr = info.scriptlet wndName = info.windName//异步加载FGUI包资源await $promise(API.LoadFairyGUIPackage(pkg))//创建窗口let win: AbstractGWndController = new scr();win.name = wndName;//创建窗口内容win.contentPane = FairyGUI.UIPackage.CreateObject(pkg, name).asCom;win.MakeFullScreen();//绑定代码win.fui = win.contentPane;win.BindAll(win);//存储窗口对象this.Map_WndInstance.set(windName, win);return win;}}catch {TSLog.Error("WindowName:【" + windName + "】 throw error when create");}return null;
}

将显示普通窗口的方法修改一下

public async ShowWnd(windName: string, modal: boolean = true) {let wnd: AbstractGWndController = await this.GetWnd(windName);if (wnd == null) {TSLog.Error("WindowName:【" + windName + "】 can not get this window");}wnd.modal = modal;FairyGUI.GRoot.inst.ShowWindow(wnd);
}

然后接下来只需要写一个弹出窗口的方法就可以了

public async ShowPopWnd(windName: string, modal: boolean = true) {let wnd: AbstractGWndController = await this.GetWnd(windName);if (wnd == null) {TSLog.Error("WindowName:【" + windName + "】 can not get this window");}LinxLog.Log("PopWnd")wnd.modal = modal;FairyGUI.GRoot.inst.ShowPopup(wnd);
}

似乎这样就可以了

然而在测试的时候我发现好像并不能点击空白处关闭窗口
我的组件时这样的

研究了一下发现,我需要把组件属性中的点击穿透开起来才可以

而在这过程中,我还发现了FGUI为我们做好了黑遮的效果

只需要在窗口中将modal这个属性设为true就可以了

这个功能一样要把组件中的点击穿透开启才会生效

这样才一个窗口内的空白区域,会被modal遮挡,阻止穿透到其他的窗口

三、管理窗口的创建、显示、隐藏、销毁

按照上述方式来创建显示窗口

我们会使用一个Map来存储已经存在的窗口

public Map_WndInstance: Map<string, AbstractGWndController> = new Map<string, AbstractGWndController>();

这样我们做隐藏和销毁就很容易了

//隐藏窗口public HideWnd(windName: string) {if (this.HasWnd(windName)) {let wnd = this.Map_WndInstance.get(windName);FairyGUI.GRoot.inst.HideWindow(wnd);}
}//隐藏弹窗
public HidePopWnd(windName: string) {if (this.HasWnd(windName)) {let wnd = this.Map_WndInstance.get(windName);FairyGUI.GRoot.inst.HidePopup(wnd);}
}//销毁窗口
public DisposeWnd(windName: string) {if (this.HasWnd(windName)) {let wnd = this.Map_WndInstance.get(windName);wnd.Dispose();this.Map_WndInstance.delete(windName);}
}

四、在WebGL与微信小游戏中

由于Unity导出的WebGL中是不支持异步的
所以如果有导出WebGL或微信小游戏的计划
那就不要使用异步方法,而是用回调的方式来做

可以参考下面的方式:

    //第一步、外部调用显示窗口public ShowWnd(windName: string, modal: boolean = true): void {//获取配置let info: IUIInfo = UITable.UIWindow[windName]//查询不到配置抛出错误if (info == null) {TSLog.Error("WindowName:【" + windName + "】 does not exist or is misspelled,Please check the spelling");return;}//构造窗口数据let wnddata: UIWndData = { windName: windName, cfg: info, modal: modal }//通往第二步,获取窗口并指定最终步骤this.GetWnd(wnddata, this.DoShowWnd.bind(this));}//内部调用,有窗口返回窗口,无窗口创建窗口private GetWnd(info: UIWndData, call: Function): void {try {//判断是否已存在窗口if (this.HasWnd(info.windName)) {if (call != null) {//窗口已存在通往最终步骤call(info, this.Map_WndInstance.get(info.windName))};}else {let pkg = info.cfg.pkgName//加载FGUI包资源,加载完成通完第三步API.LoadFairyGUIPackage(pkg, this.LoadPackComplete.bind(this, info, call))}}catch (error) {TSLog.Error("WindowName:【" + info.windName + "】 throw error when create");TSLog.Error("error:" + error);}}//第三步、加载完成回调private LoadPackComplete(info: UIWndData, call: Function): void {let pkg = info.cfg.pkgNamelet name = info.cfg.itemIdlet scr = info.cfg.scriptlet wndName = info.windName//创建窗口let win: AbstractGWndController = new scr();win.name = wndName;//创建窗口内容win.contentPane = FairyGUI.UIPackage.CreateObject(pkg, name).asCom;win.MakeFullScreen();//绑定代码win.fui = win.contentPane;win.BindAll(win);//存储窗口对象this.Map_WndInstance.set(info.windName, win);if (call != null) {//通往最终步骤call(info, win)};}//最终步骤、加载完成回调,显示窗口private DoShowWnd(info: UIWndData, wnd: AbstractGWndController) {let wndName = info.windNamelet modal = info.modalif (wnd == null) {TSLog.Error("WindowName:【" + wndName + "】 can not get this window");}wnd.modal = modal;FairyGUI.GRoot.inst.ShowWindow(wnd);}

这样在微信小游戏中就可以正常的运行了
这里之所以不用匿名函数,是因为使用匿名函数会造成GC的问题
所以使用了命名函数,虽然写起来麻烦而且很长
对比之下,异步的方式,真是清爽


用Unity同时开发【微信小游戏】【安卓】【IOS】游戏#5.5.1 窗口管理器相关推荐

  1. Unity开发微信小游戏步骤

    unity开发微信小游戏 https://gitcode.net/mirrors/wechat-miniprogram/minigame-unity-webgl-transform?utm_sourc ...

  2. unity开发微信小游戏(5)- 微信好友排行榜

    效果展示: 如果感觉文章有用的,也烦请大家多多支持(扫描上面二维码n(*≧▽≦*)n)!!❤❤❤ unity开发微信好友排行榜可以说是把我虐的体无完肤,但为了拿下这功能,硬壳了三天,把我所踩过的坑分享 ...

  3. Unity 开发微信小游戏初探

    前言 最近因项目需要开始研究Unity开发微信小游戏相关的知识.期间遇到各种坑,网上查阅的资料基本类似,无法解决自己遇到的问题.特用本文记录下过程,方便其他人遇到同样的问题时能够参考. 开发环境 Un ...

  4. 微信小游戏申请注册流程+开发微信小游戏类目需要具备条件

    微信小游戏申请注册流程+开发微信小游戏类目需要具备条件 在这里先讲一下,小程序和小游戏前面的注册流程都是一样的,在注册完毕登录小程序后台后选择类目时需要注意一下,我下面讲解的是已经通过认证的服务号进行 ...

  5. 如何在Unity上开发Nintendo(任天堂)Switch平台游戏时让游戏patch包大小尽量小

    如何在Unity上开发Nintendo(任天堂)Switch平台游戏时让游戏patch包大小尽量小 众所周知,Nintendo Switch有一条guidline-0123来限制游戏的patch包大小 ...

  6. webpack + typescript 开发微信小游戏实践

    源码地址 微信小游戏版本技术选型使用typescript开发 但是微信小游戏原生不支持 typescript 开发,于是探索一下使用ts开发微信小游戏 1. 创建小游戏 使用测试号,创建一个使用官方示 ...

  7. 如何使用egret开发微信小游戏(一)Hello World

    如何使用egret开发微信小游戏(一)Hello World 微信小游戏上线以来,凭借微信海量的用户,取得了巨大的成功,从跳一跳到大家一起来滑水,从2d游戏到3d游戏,许多游戏开发者都赚的盆满钵满,我 ...

  8. 解决uniapp开发微信小程序预览pdf文件ios\安卓兼容问题

    问题 项目需要用uniapp来开发微信小程序,其中,有一个功能是预览pdf, 后台以链接形式返回pdf地址,一开始使用web-view做链接跳转,但是出现ios文件可以正常打开,android打不开的 ...

  9. Unity 之 转微信小游戏本地数据存储方法分享

    Unity 之 转微信小游戏本地数据存储 问题背景 微信小游戏读写本地文件 WebGL平台的一些限制 报错查看方法分享 问题背景 近期在将Unity转换为小游戏的时候发现在读写本地文件的时候,使用Ap ...

  10. 利用Phaser开发微信小游戏(排行榜小结)

                                                                利用Phaser开发微信小游戏(排行榜小结) 小游戏中的开放数据域可用来保存游戏 ...

最新文章

  1. 【ACM】杭电OJ 2044 2045
  2. 【组合数学】生成函数 ( 求和性质 )
  3. Linux下计划任务:crontab 命令的权限说明
  4. mysql utf 8bm4 没用_不要在 MySQL 中使用“utf8”,請使用“utf8mb4”
  5. Apple 企业开发者账号邓白氏码申请记录 ----转
  6. 通向架构师的道路(第十四天)Axis2 Web Service安全之rampart
  7. 23andme、gsa、wegene各染色体位点统计
  8. 2021 年电工杯 A 题(第一题、第二题、第四题)
  9. 紫金桥组态软件使用DF1协议与AB PLC通讯
  10. DX9b 与 DX9c 在x文件解析方面带来的麻烦
  11. Android连接mumu模拟器
  12. 倍福--实现和西门子的profinet
  13. 用阿里云香港云服务器时需要注意的方面
  14. NSIS教程(4): 调用Windows API
  15. 无线路由器破解之cdlinux
  16. 面试了一个 37 岁程序员,让我有所触动,35岁以上的程序员该何去何从?
  17. jadx 1.4.5反编译包不全
  18. Win7如何搜索文件内容
  19. 传统研发团队的敏捷转型实践之路
  20. 软考中级之系统集成项目管理工程师备考

热门文章

  1. MongoDB实战(MongoDB开发者现身说法)
  2. (七)HyperledgerFarbic1.4- Fabric的SDK使用
  3. 网络爬虫(基于python的网络爬虫批量爬取图片)
  4. JAVA生成随机昵称
  5. 一文了解开集输出结构open_drain
  6. Drain算法:日志解析
  7. video标签和source标签
  8. [BZOJ]4198 [NOI2015] 荷马史诗 哈夫曼树
  9. 方法(Method)
  10. Windows Server 2012R2 虚拟专用网络技术