微信小游戏的限制与解决办法:以大天使之剑 H5为例

2024-07-17
来源:网络整理

介绍:

有材料,示例分析压缩和优化代码方案。

随着渠道平台的发展和演进,我们的产品往往要在各种平台上推出,微信小游戏就是其中之一。

微信小游戏是微信小程序的一个类别,它是点击播放的,无需下载安装,体验轻巧,可以在微信中与朋友一起玩,比如PK、围观等。

但是,如果你想让你的游戏登录微信小游戏,往往会有一些限制。以下是三奇互娱旗下研发公司极光网络客户端老板程晨策在上周举办的首届“极光休息室”活动上分享的技术干货,将《大天使之剑H5》项目的主要局限性及解决方案登陆微信小游戏进行案例分析。

大天使之剑H5受微信小游戏的主要限制

1、所有分包合同规模不超过8M:分包是指微信开发工具上传的所有资源,包括JS代码和资源,不得大于8M;

2、单个包大小不得大于4M:上传文件中不能有大于4M的文件;

3.JS 必须放在包中才能运行,加载的 JS 文件只会被视为文本:加载的 JS 文本无法转换为可执行脚本

在《大天使之剑H5》登陆微信小游戏之前,整个项目的规模在400M左右,光是JS代码部分就10M左右。除了逻辑代码之外的其他资源(图像、声音、配置等)都可以在游戏运行时加载,开发工具中不需要上传,但需要上传大约 10M 的 JS 代码。因此,《大天使之剑H5》要想登陆微信小游戏,就必须把JS代码的大小减小。

介绍现有压缩工具的一些功能

这

AS3 部分项目在引擎中优化生成 JS,而这个功能应该基于实现。主要优化内容有:

1.从代码中删除无效的空格字符

2. 从代码中删除注释

如图

3. 缩短方法中局部变量的名称

如图

4.代码格式优化(将代码更改为更节省脚本的编写方式)。

如图

5. 压缩属性名称(默认不启用)。

我们先看一下这个例子,这是一个类,当工具默认不启用属性名称的压缩时,工具只会按例子中的橙色 X 和 Y,因为这是一个参数,也就是刚才提到的方法中定义的变量,this.x、this.y 没有按, 因为这是属性名称。如果按下类名、方法名、属性名 X、Y,则必须将其他使用位置一起更改,如果代码使用反射来调用,则无法调用。因此,压缩这些名称是有风险的,这就是为什么该工具默认不压缩的原因。这个功能不是没用吗?不对,该工具还提供了大量的参数供你设置未压缩名称列表,还允许你为压缩名称等定义正则表达式,其实你还是可以使用的,但是你还是要先为自己的项目做一个名称数据列表,并将未压缩的名称设置为与代码同步维护, 所以会比较困难,所以“大天使剑H5”项目不使用这个功能。

总结:

“大天使之剑 H5”项目现有的 AS3 代码代码在生成 JS 代码时已默认优化:

但是,生成的JS代码大约是10M,还没有满足微信小游戏的要求,所以为了减少代码量,我们需要对AS3代码做更多的优化,以减少代码量。

减少程序代码

这

减少代码量最直接的方法是减少代码中的字符数,这部分所做的优化是我们项目的 AS3 代码部分所做的优化,这些优化包括以下内容:

1.更改要从外部加载的界面布局数据

编辑UI编辑器后,会生成对应的UI类文件,其内容如下图所示

这里的主要内容是UI的布局数据,可以在不涉及逻辑的情况下提取。将其保存为文本文件,并在其对应的界面初始化时加载,我们可以在其中通过修改UI模式进行调整

随意创建一个 UI 来执行测试,如图所示:

我们可以看到,当我们创建一个新接口时,使用嵌入模式生成的 .as 文件总共有 3283 个字节,而使用分离模式生成的文件只有 579 个字节。图右侧的绿色部分显示了已经挖掘的代码,比UI布局相关的代码小了80%左右。

在《大天使之剑H5》中,目前有931个UI布局文件,帮助我们减少了1.8M的代码。

2. 删除类中未使用的导入

在开发时,我们错误地输入了一些项目未使用且需要删除的类。

例如,2D 游戏不需要与 3D 相关的东西,也不需要导入

3. 在方法中将其替换为局部变量

当我们的 AS3 代码转换为 JS 时,类中的属性名称将在方法中以此开头。我们可以在这里减少这种情况吗?如下图所示:

在上述方法中有几个。如果将其替换为局部变量,则如下所示。这里的局部变量是单字符变量,因为最后我们的项目将用于按下,方法中定义的所有变量,只要不超过 54 个,都是单字符变量。在我们看优化之前,有四个,它们占用了 16 个字符。优化后,4个 this 变成 4 个 n,也就是 4 个字符,还有一个额外的赋值语句,中间有一个空格,手背有一个分号,总共 11 个字符,4 个 n 是 15 个字符,比优化前少了一个字符。如果我再给这个方法加一个this,那么优化前的代码会加4个字符,优化后的代码只需要加1个字符,所以方法中这个越多,可以减小的大小就越大。因此:

综上所述,只要方法中有3个以上的这个关键词,就可以保存字符数。而且越多,您节省的就越多。我在编译好的JS代码中搜索了一下,这个有将近18个,可以节省很多。但是,需要注意的是,这种优化都是一个作用域,并且每个作用域中对 this 的引用是不同的,因此在每个不同的作用域中应该单独计算,也就是说,如果方法中有一个函数,那么在计算方法中 this 的数量时,函数中的 this 不应该被计算出来。二是有方法已经写好了内部变量赋值是这样的,那么就可以用这个现有的变量来进一步减少字符数了。此优化最终节省了 0.3M。这种优化不仅优化了代码的大小,因为在JS中,局部变量的调用效率比这更高,所以这也可以加快游戏的运行效率。

4. 压缩包名、类名、方法名、属性名

我们在这一步中要做的就是把默认的名字放到不按下,我们用自己的方式压制他

(1)将相同名称按入同一短名,将代码中的相同名称按入同一短名称

(2) obj.abc 与 obj[“abc”] 的处理方式不同。

默认压缩规则:obj.abc 的属性名会被压缩,obj[“abc”] 的字符串部分不会被压缩。

这样想,主要是因为也考虑到一些属性名压缩后可能无法访问,做法是提供一个没有按下的属性名的配置列表,但这只是一个配置列表,我们无法通过这个列表找到这些属性名在代码中使用的位置, 并且有一定的局限性,因此,通过obj.abc和obj[“abc”]的区别,我们可以用不同的方式告诉编译器在写代码的时候,这里属性名是要按还是不按。

有些人可能想知道 obj[“abc”] 是否会比 obj.abc 多写三个字符。不用担心,因为在压缩结束时,[] 语法将转换为 .语法。

(3) 自定义标签 /*[ZIP-JSON]*/

为了不打破程序员的编程习惯,我们不得不以字符串的形式进行

微信小程序注释代码_微信小程序开发界面怎么注释_微信小程序开发工具注释快捷键

访问属性时,想到了以下解决方案:在字符串前面加上 /*[ZIP-JSON]*/

如:

在我们的通用缓动类中,上图中的“x”和“y”是属性名称,我们默认不压缩字符串。在这种情况下,我们可以在代码中添加 /*[ZIP-JSON]*/ 标签,例如:

这样,“x”和“y”就会被浓缩成它们对应的名称。

通过这些过程,我们的代码将按以下方式编写:

表单 1:此属性名称不会被压缩,它将使用其原始名称进行访问

表单 2:此属性名称在定义时被压缩,可以通过传递进行压缩。要访问的语法

表单 3:此属性名称在定义和访问时都会压缩

当然,/*[ZIP-JSON]*/ 是作为注释块的,当 AS3 最后转换为 JS 时,会帮助我们清除注释块,这样我们就不用担心添加注释块了,代码会很大。

(4) 特殊处理

方法如 ,

和方法

在方法中传递的字符串实际上是属性名称。由于默认属性名称是压缩的,而字符串不是压缩的,因此默认情况下,我们会压缩这些方法中的名称。但是要把它浓缩成什么样的名字呢?

我们上面讲的就是要按哪些名字,按的时候要注意一些要点,那么这些名字到底怎么样呢?当然,印刷机越小越好,那么最低限度是多少?一个角色是最好的。让我们先看一下如何处理名称的限制。名称可以由字母组成,字母区分大小写,也可以使用数字,有下划线,还有不太常用的$符号,需要注意的是,名称的第一个字符不能是数字。

如果我们在一个字符中使用所有名称,我们可以有多少个名称? 26个小写字母,26个大写字母,10个数字没有用,加上两个符号,就是54。至于两个字符的名字,有3,456个,三个字符是220,000。当然,可以在这里使用的会更少,为什么?因为比如as、is、if、for等名称,也是两个字三个字,但是都是关键词,名字不能和关键词一样,但是这样的关键词不多,不超过10个。三个角色可以有 220,000 个名字,这对我们来说足够了吗?

上图是《大天使剑H5》中名字中使用的字数分布图,一共有4万个名字,这两个字3000多个肯定不够用,三个字的22万个完全可以满足。而如果我们看一下这些名字的长度,从表中可以看出,95%以上的名字大于三个字符,所以有更大的优化空间。最后,我们的项目压缩了所有名称后,总共减少了 1.9M。在压缩名称中,大部分工作都是用编辑工具完成的,其中有些是修改源码的,还编写了一个工具来处理它,尽量用工具来完成,否则就要手动修改了,工作量会变得不堪重负。

针对《大天使之剑H5》优化了以上五点后,结果如图所示:

“大天使之剑H5”的代码从大约10M缩小到大约5.1M大小

(5) 《天使长之剑》H5中尚未实现的一些理想改进

四。使用分包

经过以上优化,《大天使之剑H5》的主码还是有5.1M的,这5.1M还是需要拆分的,其中5.1M,带游戏引擎的部分占0.7M,其他小文件占0.2M,剩下的主程序有4.2M,剩下的4.2M可以通过分包处理。如何分包,我们可以在腾讯和的官方网站上找到详细的教程。

以下是分包方式的简要介绍:

在项目的根目录下,创建一个 .def 文件,这是一个文本文件,内容如下,编译后可以生成两个文件,主文件的 JS 和模块.js。如果要将其划分为多个模块,可以编写多个结构,并定义模块名称和模块对应代码所在的文件夹。

看起来不是很简单吗?但是,如果我们随机指定一个文件夹下的代码编译成一个模块并且是独立的,那么它在运行时会在上图的红色部分出现错误。

出现此错误的原因是主文件会先运行,主文件引用了模块中的 XXX,在这里运行时,模块还没有加载,所以没有定义 xxx,所以报错。

因此,在做好模块划分工作之前,需要对项目进行解耦。如果要解耦,就要知道我们给模块分配了什么功能,如果在这个功能中需要和主程序交互,就需要设计相应的中继机制来解耦。

如果项目是新项目,我们可以在游戏设计之初就把这部分内容做好,在函数开发的时候,我们就会知道函数是一个要分离的模块,开发它应该采用什么样的开发规则,这样我们才能解耦再分割模块。

但是我们的游戏已经上线快一年了,如果现在加上这样的机制,就相当于把需要放到模块里的函数重构了,工作量很大,而且函数还要重新测试,开发周期是开放的,很容易出现bug。后来,我想出了一种在不解耦的情况下划分模块的方法。

在说我们的方法之前,我想解释一下,我的方法只是解决小游戏中分包小于4M的问题,这与子模块的设计思路不同。这些模块的目的是什么?就是把还没用到的函数放到模块里,再在需要用的时候加载对应的模块。我的方法是,在进入游戏之前,你需要加载所有的模块,不管是否需要模块的功能,也不管模块里有什么功能。

为了说明这一点,让我们看一下 JS 类。JS 类定义中是否有优先权?请看一下这段代码,其中定义了一个父类,然后定义了一个子类。我们可以编写和定义一个子类,然后再定义一个父类吗?如果先编写子类的定义,则父类定义是相同的,并且在父类定义中调用该属性时会报错。所以父类必须写在子类的前面。更换组件模块后会发生什么?

假设我们现在有两个文件,首先加载的文件称为模块 A,稍后加载的文件称为模块 B。模块 A 中有子类的定义,模块 B 中有其他类的定义,模块 A 中有子类的父类的定义。加载模块 A 后,当它运行到子类的定义时,它会调用其父类,因为模块 B 尚未加载,因此它必须报告错误。我们如何避免这里的报告错误?这很简单,把父类的定义放在模块A中,这样你就不会出错了。如果父类仍然有一个父类,并且也在模块 B 中,请记住将其父类也带到模块 A 中。

我们如何将父类放入模块 A 中?我们需要做的就是在调用 Laya 的编译器之前,将父类的 as 文件放入模块 A 的文件夹中。父类中的包名不需要修改。要知道,虽然包名和AS中存储的路径匹配,但是在用laya编译的时候,并不能检测到包名是否匹配,最终生成成JS的就是写在文件中的包名,路径只是作为放到哪个模块的依据。

我们刚刚谈到了在另一个模块的情况下由父类引起的错误。除此之外还有别的吗?是的,例如,我们刚才在模块 A 中的类,在未解耦逻辑中,必须有一个调用模块 B 的类。但是,在初始化过程中,它应该不会运行到业务逻辑中,那么为什么会报错呢?

让我们看一下模块 A 中的代码。模块 A 的前几行通常如下所示,第二行是一个变量,其短名称定义了 Laya 引擎中的一些公共方法,在逻辑中很容易调用。从第三行开始,为本模块中引用的类分配了类名,以便在使用时方便编写包含包名的类名。也就是说,我们直接用 AS 编写的代码可以变成可运行的 JS,而无需太多修改。

请注意,这些代码行在初始化 JS 文件时运行。注意,在第四行,我们有一个类,假设这个类被调用了,这个类是在模块 B 中定义的,那么这个赋值语句会因为模块 B 没有加载而找不到定义,然后会报错。而这个类之所以在这里,是因为它被用于模块的一个类中。

这里我们了解到,用类的方法编写的代码在初始化时不会运行,因此模块 B 中定义的类在初始化时不会出错,导入的类会写到模块的最开头,在初始化时运行时会报错。所以让我们这样处理它,模块 A 中的所有类,如果类是模块 B 中的类,那么删除它。并写入使用此函数调用的字符串的类名的所有位置,包括包名。

看来这样改的话,需要改的地方会比较多,生成的代码中会有多个长名字,我改成这个,给类加一个静态变量,让他等于这个函数,那么代码就不需要修改了, 实际上,在使用类名的地方,它被称为此定义的静态变量。而编译成JS之后,静态变量的定义就变成了一个get函数来获取这个值,也就是在用到的地方调用,而不是在初始化的时候调用。这解决了在模块A的代码中调用模块B类导致初始化过程中出错的问题。

你刚才的两个地方吃完了吗?让我们回想一下,在这两种情况下,它们都是模块 A 中的类,如果引用了模块 B 中的类,那么找到一种方法来删除引用并让他在第一次运行时调用它。也就是说,在编译成JS的时候,模块A中的类被认为是没有引用模块B中的类,所以如果模块B中的类,比方说,只有一个引用是模块A中的类引用,现在模块A中的引用被删除了,那么就没有类引用了它, 也就是说,在编译时,这个类不会被编译成JS。当您运行它时,您将收到错误,因为您找不到定义。所以需要添加一个强制编译标签,这是一个提供的标签,当有这个标签时,即使没有被引用,类也会被编译成JS。

最终结果,如图所示:

4.2M的主程序文件拆分为1.2M和3M,小的和引擎代码等一堆小文件打包成一个包,一共2.1M,3M文件是一个包。程序运行时,进入游戏时会先加载 2.1M 包,完成后立即加载 3M 包。这两个包在准备好进入游戏之前都不会加载。

我正在寻找游戏陀螺仪:

商务合作/访谈/投稿:

西瓜(微信)。

刘伟(微信号)。

温静(微信)。

行业突发新闻:猫与海(微信号)。

投稿邮件:

分享