diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..2269bf46 --- /dev/null +++ b/404.html @@ -0,0 +1,21 @@ + + + + + + 404 | 微信小游戏Unity/团结快适配 + + + + + + + + + + +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/CHANGELOG.html b/CHANGELOG.html new file mode 100644 index 00000000..d0928919 --- /dev/null +++ b/CHANGELOG.html @@ -0,0 +1,25 @@ + + + + + + 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

SDK安装指引:微信小游戏Unity、团结引擎转换插件WXSDK

稳定版本

  1. UnityPackage:下载地址
  2. PackageManager(git URL): https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git

2024-10-18 【预发布】

PackageManager(git URL): https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git#pre-v0.1.22

Feature

  • 普通: WXSDK代码简化
  • 普通: 增强JsonMapper报错信息

Fixed

  • 普通: WX.Cloud.Init() 自定义环境报错

2024-10-8 【重要更新】

Feature

  • 普通: UDPSocket.write适配
  • 普通: 部分JS API接口更新
  • 普通: 云开发/云托管支持

Fixed

  • 普通: 修复.net8 OnApplicationFocus/Pause适配
  • 普通: 修复插件自动调节dpr后,获取不到实际dpr
  • 普通: 修复音频设置timeSamples不生效
  • 重要: 修复iOS18微信系统字体丢失
  • 重要: 修复iOS17.5以上音频退后台无法恢复
  • 重要: 修复音频PC端异常循环播放
  • 重要: 修复游戏圈文案默认显示'打开游戏圈'的问题

2024-8-13 【重要更新】

Feature

  • 普通: 横竖屏切换,PC窗口大小自动适配
  • 普通: PC分辨率模糊,自动调节dpr属性

Fixed

  • 严重:修复多点触控产生的异常
  • 普通:适配2021,去_JS_Focus_Window
  • 普通:修复多线程压缩的扩展名判定

2024-7-09 【普通更新】

Feature

  • 普通:兼容2022新增的音频API
  • 普通:更快的转换打包速度
  • 普通:Unity侧添加设置分辨率接口

Fixed

  • 普通:临时兼容wk 17.5暂停音频无法恢复的bug
  • 普通:Touch id在特定情况丢失
  • 普通:使用微信压缩纹理工具sprite atlas版本被修改

2024-5-17 【普通更新】

Fixed

  • 普通:修复WXAssetBundle与预下载冲突问题

2024-5-15 【普通更新】

Feature

  • 普通:支持JS构建模板,请查阅模板文档
  • 普通:调整启动封面表现,默认进度动画加速
  • 普通:writeFile/unlink操作文件时同步更新启动插件维护的缓存信息
  • 普通:支持自定义微信系统字体字符集
  • 普通:网络接口如UnityWebRequest支持通过添加特殊请求头request.SetRequestHeader("wechatminigame-preload", "1")做预下载,缓存到用户目录但不增加unity内存。当需要使用时不增加请求头重新请求即可从用户目录读取缓存使用。
  • 普通:网络接口如UnityWebRequest支持通过添加特殊请求头request.SetRequestHeader("wechatminigame-skipclean", "1")不做旧缓存淘汰。
  • 普通:适配插件版本升级到1.2.50

2024-4-26 【普通更新】

Fixed

  • 普通:修复Unity2018/2019的兼容
  • 普通:兼容Windows 1.0.4版本template问题
  • 普通:修复Android平台导出时的

2024-4-17 【普通更新】

Feature

  • 普通:编译参数增加ERROR_ON_UNDEFINED_SYMBOLS
  • 适配插件版本升级到1.2.45

Fixed

  • 普通:修复团结版dotnet wasm加载报错
  • 普通:修复音频的长度为负数时的异常stop
  • 普通:修复配置文件重置bug

2024-4-3 【重要更新】

包含重要bugfix、特性支持

Fixed

  • 重要:修复UDP接口处理buffer
  • 重要:修复unity-namespace.js部分环境变量丢失问题

2024-3-28 【普通更新】

  • 普通:优化对团结版的导出支持

Fixed

  • 普通:兼容PlayDelayed播放
  • 普通:兼容FMOD2.02版本
  • 普通:修复FState偶现报错

2024-3-5 【普通更新】

  • 普通:WXAssetBundle支持切换CDN
  • 普通:优化VideoPlayer组件
  • 普通:更新小游戏模板捕获全局错误
  • 普通:高性能+模式下,WebGL2.0不再限制需要iOS>=15.0

Fixed

  • 普通:修复wx.onBluetoothDeviceFound
  • 普通:修复wx.onUserCaptureScreen
  • 普通:修复wx.getAppAuthorizeSetting
  • 普通:修复fs.stat
  • 普通:修复截屏回调
  • 普通:unity21.3网络超时时间设置

2024-1-18 【普通更新】

  • 普通:更新适配插件版本到1.2.38

Fixed

  • 普通:不支持WebGL2的旧Android微信版本提供升级指引

2024-1-15 【普通更新】

Feature

  • 重要:增加iOS高性能+(iOSPerformancePlus)选项,请查阅高性能+模式,有助于提升渲染兼容性、降低WebContent进程内存
  • 普通:陀螺仪去json性能优化

Fixed

  • 普通:修复蓝牙数据传输问题
  • 普通:修复广告低版本微信ReportshareBehavior上报问题
  • 普通:修复2021.3.33 ContextMenu适配
  • 普通:修复开放域排行榜触控

2024-1-2 【重要更新】

包含重要bugfix、特性支持

Feature

  • 普通:陀螺仪去json性能优化
  • 普通:启动剧情新增Hash 、版本号兼容验证逻辑
  • 普通:转换配置新增iOS dpr选项
  • 普通:C# SDK支持文档注释

Fixed

  • 重要:修复Android系统代码分包Patch功能不生效的问题(需同时升级分包工具插件至1.1.12)
  • 普通:修复压缩纹理工具在一些特殊字符转义失败的bug

2023-12-18 【重要更新】

包含重要bugfix、特性支持

Feature

  • 普通:TouchStart/TouchEnd去json性能优化

Fixed

  • 重要:修复TCP接口arraybuffer处理

2023-12-12 【重要更新】

包含重要bugfix、特性支持

Feature

  • 重要:优化TCP接口能力,使用请查阅网络通信适配
  • 重要:优化UDP接口能力
  • 普通:优化启动剧情能力(Beta)
  • 普通:增加接口WX.CanIUse

2023-12-08 【重要更新】

包含重要bugfix、特性支持

Feature

  • 重要:新增启动剧情能力(Beta)
  • 重要:新增TCP接口能力
  • 普通:更新适配插件版本到1.2.34

Fixed

  • 严重:修复TouchMove在<iOS 15.0系统BigUnit64Array兼容性问题
  • 严重:修复适配插件处理代码分包时序导致的一定概率启动失败

2023-11-29 【普通更新】

Fixed

  • 普通:修复TouchMove优化在2020之前版本产生的导出错误

2023-11-28

【重要更新】包含重要bugfix、特性支持

Feature

  • 普通:FileSystem Stat支持isDirectory和isFile
  • 普通:优化胶水层代码,删减多余代码
  • 重要:TouchMove触摸性能优化
  • 重要:优化微信字体所占用的MonoHeap临时内存

Fixed

  • 普通:修复IOS音频被打断无法重新播放
  • 普通:修复2022导出Video的BUG

2023-11-10

【普通更新】

Feature

  • 普通:支持2022 Input Field组件适配微信输入法
  • 普通:PC端和开发者工具支持Unity VideoPlayer组件

2023-11-02

【普通更新】

Fixed

  • 修复部分首资源包压缩异常问题

2023-10-20

【普通更新】

Feature

  • 重要:Unity2022 development build的导出支持
  • 普通:更新小游戏云测试profile获取的性能数据

Fixed

  • 普通:修复微信压缩纹理工具对音频ab包的处理bug问题
  • 普通:修复微信压缩纹理工具在 MacOS M1系列芯片执行异常问题

2023-10-11【普通更新】

Feature

  • 适配Video Player, 安卓3.0.0基础库/IOS 3.1.1基础库且只支持播放一个视频

2023-9-26

【重要更新】包含重要bugfix、特性支持

Feature

  • 适配Application.targetFramerate,无需再调用小游戏的帧率设置API

Fixed

  • 重要:修复wasm分包patch未生效的问题
  • 重要:修复WXAssetBundle在异常时上报错误
  • 更新适配插件版本到1.2.31

2023-09-20

Feature

  • API协议更新至3.0.1版本,增加模糊地理位置获取接口
  • 更新适配插件版本到1.2.29

2023-09-01

Feature

  • 微信压缩纹理工具Unity全版本支持

Fixed

  • 修复WXAssetBundle WXUnload后再次Load同个AssetBundle可能出现的异常
  • 优化WXAssetBundle当UnityWebRequest异常时DownloadHandlerWXAssetBundle.assetBundle返回null,不再直接崩溃
  • 更新适配插件版本到1.2.26

2023-08-24

Feature

  • 适配AudioClip.GetData
  • 更新适配插件版本到1.2.25

Fixed

  • 修复旧版本安卓使用系统字体报错'SC Font not found in TTC File'
  • 资源优化工具支持ASTC6*6格式

2023-08-18

Feature

  • 增加downloadfile(优化构建,支持创建类时传入success等会回调)
  • 重构fs.readFile和fs.readFileSync,支持position和length参数
  • 增加onMouseDown等PC点击事件
  • 支持通过 minigame/unity-namespace.js 中函数 isReportableHttpError 忽略非重要网络异常上报,如心跳、数据分析接口

Fixed

  • 修复使用 WXAssetBundle 且请求了不同版本的资源时报错'readFileSync:fail no such file or directory'
  • pc下载资源出现'still downloading xxx'弹框时用户可尝试重启小游戏
  • 修复最佳实践检测工具首资源包是否压缩判断

2023-08-10

Feature

  • 增加隐私信息授权API(requirePrivacyAuthorize等)
  • 增加API-requestSubscribeLiveActivity
  • WXAssetBundle兼容WebGL浏览器环境(回退至UnityWebRequestAssetBundle模式运行)

2023-08-3

Feature

更新内容:

  • 首资源包压缩后在pc上运行的基础库版本限制调整,CDN加载(>=2.32.3),小游戏分包加载(2.29.2)
  • 完善FileSystemManager
  • Video支持修改属性
  • development模式下,增加渲染性能检测日志
  • 启动卡住时补充上报dependency
  • 更新适配插件为1.2.23

Fixed

  • 修复微信系统字体加载时报错'SC Font not found in TTC File'
  • 忽略unity分析的网络失败上报
  • 修正网络个数和HTTP2.0检测
  • 修复wx.onCompassChange

2023-07-27

Feature

  • 转换插件添加启动并行下载配置
  • 详细缓存日志不写入日志管理器
  • pc增加是否支持brotli压缩条件判断

Fixed

  • 修复系统字体未正常预下载
  • PC微信因loadSubPackage无回调的容错处理
  • 修复最佳实践检测工具首资源包brotli压缩后仍提示未gzip/br压缩
  • 修复AudioSource修改pitch失效
  • 修复PC端OnKeyDown回调报错

2023-07-20

Feature

  • 补充启动阶段关键日志
  • 新增米大师接口RequestMidasPaymentGameItem
  • 更新适配插件1.2.19

Fixed

  • 首资源包校验兼容微信纹理压缩工具
  • 移除不用的纹理下载API

2023-07-12

Feature

  • 增加选项Il2CppCodeGeneration,默认为Il2CppCodeGeneration.OptimizeSize
  • 启动期间校验首资源包大小
  • 更新适配插件1.2.18

2023-07-05

Feature

  • iOS高性能模式自动GC策略(默认10s GC),可通过MiniGameConfig.asset-CompileOption-iOSAutoGCInterval调整间隔
  • 支持对首资源包进行brotli压缩

Fixed

  • 性能面板数值显示优化

2023-06-29

Feature

  • 最佳实践预下载及网络下载检测项调整
  • 增加OpenCustomerServiceChat
  • 优化WXTouchInputOverride,在touchend时触发点击事件

Fixed

  • 修复微信系统字体在iOS上部分字符缺失
  • 修复微信系统字体在安卓上字形异常
  • 修复导出webgl的兼容逻辑

2023-06-16

Fixed

  • 修复Unity压缩选项导致出包错误
  • 调整默认打开窗口宽度
  • 修复打包后分包插件提示: '当前项目模板过旧,请使用新版unity导出插件重新导出项目

2023-06-14

Feature

  • 移除对Node.js依赖;
  • 优化面板,提供Instant Game AutoStreaming自动配置与上传。
  • 增加API getlogmanager/getrealtimelogmanager

Fixed

  • iOS高性能最低支持版本调整
  • 微信系统字体预载bug修复
  • 音频FMOD导出适配

2023-06-12

Fixed

  • plugins目录增加link.xml, 避免动态创建的类型被裁剪(如litjson解析)

2023-06-7

Feature

  • UnityWebRequest支持timeout属性
  • 二次启动最佳实践检测逻辑调整

Fixed

  • 修复Unity 2022引擎版本导出Web版本的模板
  • dev版本不处理symbols数据
  • 修复微信系统字体多行重写的问题
  • 修复微信系统字体在iOS系统部分缺失符号

2023-06-1

Feature

  • 支持Unity 2022引擎版本导出微信小游戏
  • 优化framework胶水层获取Canvas与宽高属性的性能损耗
  • ProfileStats性能面板增加FrameTime
  • 支持WASM生成external symbols优化,无需Node支持
  • 增加API CreateFeedbackButton
  • 广告API customAd增加onHide
  • 更新适配插件1.2.11

Fixed

  • 修复Android首次退出小游戏后会继续播放的问题
  • DoExport增加返回值方便第三方工具集成
  • innerAudio onError增加回调信息

2023-05-24

Feature

  • 更新适配插件1.2.5
  • 优化开发版、体验版小游戏支持最佳实践检测工具

Fixed

  • TextureEditor插件目录不参与编译

2023-05-22

Feature

  • 支持使用微信字体,使用WX.GetWXFont获取使用系统字体
  • 支持WXAssetBundle,替换Unity AssetBundle以减少内存使用,请参阅文档使用AssetBundle其中WXAssetBundle部分
  • 开发版、体验版小游戏支持最佳实践检测,请参阅最佳实践检测工具
  • WX-WASM-SDK-V2** 版本使用新的目录结构为WX-WASM-SDK-V2,更新需手动删除Assets/WX-WASM-SDK (如有二次修改请备份)。若新版本出现异常,可使用旧版本备份包 SDKv1 Unity插件 版本包进行回退
  • 适配插件版本号更新为1.2.3

Fixed

  OnKeyboardInputCallbackResult -> OnKeyboardInputListenerResult
  • 修正调用参数类名的大小写,例如:
  getGameClubDataOption -> GetGameClubDataOption
+  openPageOption -> OpenPageOption

2023-04-26

Changed

  • 更新启动插件1.1.19

2023-03-31

Feature

  • 优化启动插件内存占用

2023-02-22

Feature

  • 支持开通高性能模式的游戏禁止回退成普通模式运行,通过disableHighPerformanceFallback修改

2023-02-15

Fixed

  • 微信压缩纹理工具修复自定义路径导出
  • 微信压缩纹理工具优化增量逻辑
  • fmod转换适配develop build

2023-02-9

Feature

  • 微信压缩纹理新增API可供开发者调用接入自定义自动转化能力
  • 微信压缩纹理工具内核优化
  • 微信压缩纹理工具对WebGL2.0 Gamma Linear模式兼容(Beta)

Fixed

  • WebGL2.0模式下,修复Android的内存异常上涨

2023-01-17

Fixed

  • iOS高性能模式下,touch identifier始终返回正整数

2023-01-17

Feature

  • 适配Unity 2020版本导出的_JS_Sound_IsStopped
  • 适配插件版本升级到1.1.12

Fixed

  • WebGL2.0模式下,修复iOS普通模式的渲染异常
  • WebGL2.0模式下,修复iOS高性能模式进程内存过大的问题
  • 修复fmod相关的适配问题
  • 修复微信压缩纹理DXT占位符当初修复eslint引发的无法替换问题

2023-01-04

Feature

Fixed

  • 修复偶现读取空文件的bug

2022-12-28

Feature

  • 增加ProfilingMemory功能,使用请阅读相关文档
  • C# SDK支持API chooseMedia
  • Snapshot支持,Unity 2021编译参数增加_emscripten_stack_get_base,_emscripten_stack_get_end
  • iOS高性能模式2.29.1支持BufferURL

Fixed

  • InnerAudio播放音频中文文件名修复
  • 兼容iOS 8.0.31普通模式UnityAudio短音频适配问题

2022-12-22

Fixed

  • 修复UnityPlugin v1.1.5导致特性开关和分包patch逻辑失效

2022-12-21

Feature

  • 排行榜能力优化
  • 视频透明时全局清理标记
  • 移除markdown插件
  • 微信压缩纹理增加支持ASTC6*6格式
  • 适配插件版本升级到1.1.5

2022-12-7

Feature

  • 支持指定Node路径,MiniGameConfig.asset-CompileOption-CustomNodePath指定自定义node安装目录
  • 编译选项增加CleanBuild(仅支持2021以上版本)
  • 适配插件版本升级到1.1.3

Fixed

  • 修复UnityAudio适配InnerAudio时,静音状态对长音频在切换场景后无效的问题

2022-11-30

Feature

  • 微信压缩纹理支持WebGL2.0
  • 微信压缩纹理对.svn .git目录忽略

2022-11-23

Feature

  • 导出增加sbrk函数,2021无需profiling-memory查看DynamicMemory

Fixed

  • UDPClient使用connect+write, 修复send接口性能问题

2022-11-17

Feature

  • 微信压缩纹理优化,支持ASTC使用非4倍数尺寸
  • 新增录屏接口功能

2022-11-9

Feature

  • Unity Audio压缩纹理,支持小游戏InnerAudio
  • 适配插件版本升级到1.1.2

Fixed

  • 修复png资源Windows系统下缓存异常

2022-10-27

Feature

压缩纹理回退使用png时也支持缓存逻辑

Fixed

使用node命令时同时查找默认安装路径 修复Win7下使用Unity2021生成symbols时导致的卡死问题

2022-10-20

Feature

  • 高性能模式HTTP网络切换为小游戏接口
  • 适配插件版本升级到1.0.97

2022-10-12

Feature

  • 微信压缩纹理工具支持ASTC文件读取,并支持不同的块大小(需Unity2021版本)
  • 适配插件版本升级到1.0.95

Fixed

  • 文件缓存清理逻辑优化

2022-9-28

Feature

  • InnerAudio支持持久化文件存储(当音频路径加入到缓存目录时)
  • 适配插件版本升级到1.0.94

Fixed

  • 修复Unity2021下使用微信压缩纹理工具,在iOS普通模式无法正常渲染的问题
  • 修复WebGL2导出时的胶水层异常

2022-9-21

Feature

  • 增加游戏圈接口openPageOption, getGameClubData
  • FileSystemManager增加stat接口

Fixed

  • FileSystemManager异步读取文件,填写encoding时没有返回数据

2022-9-13

Feature

  • 微信压缩纹理工具支持bundle级别修改压缩纹理等级
  • Unity2021 IL2CPP默认选项更改为SIZE减少代码包体

2022-9-8

Fixed

  • 启动封面拉伸
  • pc小游戏下载路径处理

Feature

  • 增加动态修改DATA_CDN的C#接口SetDataCDN,以及js接口GameGlobal.manager.setDataCDN
  • 增加动态修改预下载列表的C#接口SetPreloadList,以及js接口GameGlobal.manager.setPreloadList

2022-9-7

Fixed

  • 修复PlayerPref在Unity Editor中的兼容
  • 修复WXWriteBinFileSync返回值的处理

2022-8-31

Fixed

  • 调整WXTouchOverride更新逻辑为LateUpdate, 补充TouchCancel事件
  • 修复资源量较大时,压缩纹理工具替换过程的卡死问题

2022-8-26

Feature

  • HTTP下载时,文件缓存与规则判定效率优化
  • 压缩纹理对于不支持的引擎版本增加提示
  • 插件特性动态开关

2022-8-17

Feature

  • WASM代码未发生变化时不在进行压缩,加快转换速度
  • 压缩纹理支持剔除功能, 增加详细日志输出
  • 微信开发者工具支持提示插件审核指引

2022-8-11

Fixed

  • 启动视频样式错误

2022-8-10

Feature

  • 支持自定义启动封面样式
  • pc微信支持启动封面

Fixed

  • 安卓8.0.25启动异常
  • 写缓存时未删除同名旧缓存
  • 使用Date.now替换performence.now以提升性能
  • 压缩纹理工具支持特殊字符资源

2022-7-28

Feature

  • 增加UDP接口能力

2022-7-20

Feature

  • 增加重启小游戏的API支持

Fixed

  • 纹理压缩并行下载完成未正常显示

Feature

  • 设置启动时是否自动检查小游戏版本更新

2022-7-14

Fixed

  • 转换面板的最大内存提示与指引优化
  • WebGL导出失败时不进行小游戏转换
  • 非playing状态调用WX接口的告警提示

2022-7-1

Fixed

  • 开发阶段没显示耗时弹框
  • 21.3unity服务器错误且无跨域头导致报错

2022-6-30

Fixed

  • 压缩纹理工具逻辑异常,增加进度条
  • 完善限帧率接口SetPreferredFramesPerSecond

2022-6-28

Feature

  • 导出插件的brotli压缩不依赖python环境

Fixed

  • 压缩纹理工具独立命名,避免有NuGet产生dll冲突

2022-6-18

Fixed

  • 小游戏模板错误

2022-6-16

Feature

  • 支持自定义可缓存文件及可清理文件
  • 优化缓存目录统计

Fixed

  • 21.3unity在iOS上网络报错

2022-6-13

Fixed

  • RemoveFile参数转字符串
  • 8.0.16安卓worker写文件报错

2022-6-8

Feature

  • 提供Loader启动数据

Fixed

  • 修复是否需要下载代码包上报
  • 21.3版本Unity webrequest设置请求头;注册进度事件

2022-6-7

Feature

  • 增加MemoryProfiler,开发阶段分析内存

2022-6-1

Feature

  • 使用worker做文件写入临时绕过安卓文件写入多时造成卡顿

2022-5-31

Feature

  • 暴露插件进度事件

2022-5-30

Fixed

  • pc小游戏首包资源通过分包加载时读取失败

2022-5-26

Changed

  • 默认关闭纹理缓存,影响安卓帧率

Fixed

  • 修复21.3替换规则

2022-5-24

Feature

  • 增加对21.3版本unity支持
  • MiniGameConfig.asset增加不常用配置入口

2022-4-29

Fixed

  • 通过分包加载资源时读取bug

2022-4-26

Fixed

  • dataFileSubPrefix时iOS首包资源下载bug

Feature

  • 游戏异常时增加重启游戏按钮
  • 检查是否32位微信导致无法进入游戏
  • 修正URL中非法路径

2022-4-24

Fixed

更新独立域插件版本1.0.60

  • 达缓存上限时未正常清理旧缓存
  • 1.0.58版本插件iOS报错

2022-4-22

Fixed

更新独立域插件版本1.0.58

  • 预下载问题路径bug
  • 不支持webgl2时提示

Feature

  • 增加清理指定文件接口RemoveFile
  • 是否缓存纹理开关

2022-4-18

Feature

  • 修改文件删除接口使用方法CleanFileCache,CleanAllFileCache

2022-4-14

Feature

  • 增加清除文件缓存接口CleanFileCache

2022-4-11

Changed

  • 2021版本调整为需要手动分离symbols,由于Unity自身产生的symbols存在缺失问题
  • 增加CleaStreamingAssets选项,控制是否清理webgl/StreamingAssets

2022-3-29

Changed

  • 更新插件版本为1.0.53
  • streamingUrlSubPath支持传自定义拼接到streamingcdn后面的路径
  • iOS不支持webgl2时提示

2022-3-22

Changed

  • 更新压缩纹理工具使用方式

2022-3-7

Changed

  • 更新独立域插件版本为1.0.51
  • 预载列表按照填写顺序生成
  • Unity2021不再提示分离symbols,2021.2.11以后版本已支持
  • Pointer_stringify导致的浏览器告警

2022-3-7

Changed

  • 更新独立域插件版本为1.0.50

2022-2-17

Changed

  • 更新独立域插件版本
  • 增加日志输出
  • 限帧时禁用后台执行Loop

2022-2-15

Fixed

  • UnityAudio循环播放修复
  • 2021版本修改为默认使用External Symbols(需升级Unity到2021.2.11以上)
  • PlayerSettings默认去除"Run In Background"

2022-2-14

Feature

  • 支持PC端DXT5压缩纹理

2022-2-11

Feature

  • 调整部分API
  • 支持webgl2.0的压缩纹理

2022-1-26

Feature

  • 新增API
  • 修复API中不确定类型的数据可能导致类型转换失败的问题

2022-1-25

Fixed

  • 修复Login方法,默认不传timeout,默认超时为1000ms,容易失败的问题

2022-1-24

Feature

  • 兼容浏览器环境,修复部分API问题

2022-1-21

Feature

  • 新增WXCleanAllFileCache接口,用于清理所有文件缓存

Changed

  • 独立域插件版本更新到1.0.46,包含以下修改
  1. 自动清理存量旧文件
  2. 达到缓存上限时清理更多空间,具体值可通过minigame/unity-namespace.js中releaseMemorySize修改
  3. 上报unity版本和转换插件版本
  4. 支持以文件名全匹配的方式忽略缓存
  5. 插件错误报实时日志
  6. pc小游戏兼容

2022-1-20

Feature

  • 新增API,旧API批量重命名,用法保持不变

2022-1-17

Fixed

  • 同名文件缓存未清理

Changed

  • 版本限制条件更新

2022-1-13

Fixed

  • Unity Audio能力适配, 不支持设备兼容处理; 退后台暂停播放音频; 性能提升

2022-1-7

Fixed

  • Unity Audio能力适配
  • Unity Input Touch能力适配

2021-12-31

Fixed

  • 调整为默认不打开性能面板,单独提供WX.OpenProfileStats

2021-12-30

Fixed

  • 修复引擎初始化失败后依然回调calledMainCb导致统计问题
  • 修复2021版本abort时执行WXUncaughtException
  • 补充小程序框架异常时上报实时日志

2021-12-20

Fixed

  • 2021 dev 运行报错(randomDevices替换)
  • 跳转小游戏接口错误
  • 缓存大小为0,AssetBundle重试失败问题

2021-12-16

Feature

  • 开发、体验版本增加性能面板

2021-12-10

Fixed

  • 修复独立域插件未编译子包bug

2021-12-06

Feature

  • WebGL2.0 增加适配,该特性处于测试阶段
  • 2021增加embedded symbols分离
  • 增加error日志回调

Fixed

  • 2021 dev 运行报错

2021-12-02

Fixed

  • dev build报错
  • 设备方向无法选中"LandscapeLeft", "LandscapeRight"

2021-11-30

Changed

  • 导出配置调整:统一资源CDN路径配置;配置顺序调整。

Fixed

  • 低版本C#导致markdownviewer报错'interpolated strings' cannot be used.

2021-11-19

Fixed

  • 更新小游戏模板

2021-11-18

Feature

增加bundle相关导出配置

  • 自定义bundle名中hash长度:用于缓存控制,默认32
  • 自定义需缓存的路径标识符:下载路径命中标识符时会自动缓存本次下载文件。
  • 忽略路径下指定类型文件:路径命中标识符时,过滤不需缓存的文件类型。

Fixed

  • markdownviewer可能出现guiskin引用丢失

Changed

  • 更新小游戏模板

2021-10-26

Feature

  • 增加部分文件操作API
  • 压缩纹理替换优化,提升转换速度

2021-10-09

Feature

  • 增加Unity2020、2021版本支持

2021-09-23

Fixed

  • 程序crash时触发用户反馈入口

2021-09-22

Feature

  • 支持短音频的播放API(WX.ShortAudioPlayer),更接近Unity的API调用方式

Feature

  • 当禁用异常时,程序即将crash之前弹出用户反馈入口,并自动提交用户反馈日志、JS Error与实时日志

Feature

  • 编译选项增加"Profiling Funcs", 仅调试问题时勾选此选项时,编译代码将含有函数名,代码体积变大

2021-09-14

Feature

  • 支持PlayerPrefs优化,支持配置key

Fixed

  • 修复排行榜内存增长问题

2021-09-06

Feature

  • 支持导出时配置封面图

2021-8-20

Feature

  • 支持创建视频

2021-8-12

Feature

  • 修复IOS下音频被系统打断后的恢复问题
  • 支持客服消息

2021-8-10

Changed

  • 小游戏项目模板更新
  • 独立域插件更新为1.0.27。优化文件删除;修复资源预载bug

2021-08-05

Feature

  • 音频支持获取播放状态
  • 非POT图也支持延迟加载

2021-08-04

Fixed

  • 独立域插件版本更新为1.0.24,修复若干问题

2021-08-02

Fixed

  • 独立域插件更新1.0.20,修复首包资源下载异常
  • 更新小游戏项目模板

2021-08-01

Changed

  • 小游戏项目模板更新

2021-07-31

Feature

  • 增加预下载并发数控制接口WX.SetConcurrent

Changed

  • 小游戏项目模板变更

2021-07-26

Feature

  • 增加预下载猎豹配置,自动从导出目录webgl/StreamingAssets查找资源并填充到game.js的Preload列表

2021-07-26

Feature

  • 支持文件二进制读写(同步和异步)
  • 压缩纹理替换速度优化

2021-07-20

Fixed

  • 独立域插件版本升级为1.0.16,修复初始上报时机

2021-07-19

Changed

  • 优化插件更新提示

2021-07-13

Fixed

  • 独立域插件版本升级为1.0.14,修复了一些bug

Changed

  • 导出插件只提示更新,不自动下载

2021-07-09

Fixed

  • 独立域插件版本升级为1.0.13,修复了一些bug

2021-07-02

Fixed

  • 微信版本或基础库版本过低时WXWebAssembly未定义,未弹框提示更新客户端

2021-06-30

Fixed

  • 压缩纹理兼容flare

Feature

  • 支持游戏恢复到前台后自动播放,默认开启分享

2021-06-29

Fixed

  • 云测试设置UI框架导致editor运行错误

Feature

Removed

  • 移除转换小游戏面板中游戏内存大小字段: 从Unity 2019开始已不支持设置PlayerSettings.WebGL.memorySize

Changed

  • 资源优化工具代码添加namespace, 避免与游戏代码冲突

Others

独立域插件更新为(1.0.11)

  • .untiy3d拓展名文件视为bundle文件,可做缓存。
  • 根据是否调试模式控制日志输出,规则为: 若为开发版, enableDebugLog=false且为调试模式时输出详细日志;其他版本, 开启调试模式则输出详细日志

2021-06-10

Fixed

  • 独立域插件更新(1.0.10): 修复安卓分片读取包内资源内存越界

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/AndroidProfile.html b/Design/AndroidProfile.html new file mode 100644 index 00000000..0db7fddd --- /dev/null +++ b/Design/AndroidProfile.html @@ -0,0 +1,29 @@ + + + + + + 使用Android CPU Profiler性能调优 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用Android CPU Profiler性能调优

  1. 转换导出插件勾选"Profiling-funcs", 请勿使用Development(该模式将极大降低性能)。 发布上线版本请务必关闭该选项!

  2. 在Android微信小游戏打开调试进行录制

  3. 停止性能数据录制

    与步骤1相似,在相同的菜单中选择Stop CPU Profile

  4. 传输录制文件到PC

    录制结束后,Android会生成一份xxx.cpuprofile,该文件格式可以使用chrome进行解析。 因此我们需要将录制后的文件传输到PC使用chrome进行分析。 文件路径通常为:Android/data/com.tencent.mm/MicroMsg/appbrand/trace

  5. 利用PC(Windows/Mac)的Edge/Chrome加载数据

    以Edge为例:浏览器菜单打开"更多工具-开发人员工具-右上角...-更多工具-JavaScript探测器",然后点击加载前面导出的cpuprofile文件即可。

    视图有多种方式,可选择"图表"(Chart)分析每一帧游戏函数耗时情况

  6. 使用JavaScriptProfile进行数据分析

注意:

  1. 编译版本仅当导出勾选Profiling-funcs(推荐)或Development时才能在函数堆栈中看到可读函数名。
  2. 特殊情况下,如果游戏勾选Profiling-funcs会导致代码包过大,那么不要使用此选项。此时得到的Profile中函数为数字ID,有两种做法进行解读:
    • 2.1 通过webgl导出目录下的symbols文件对照映射
    • 2.2 通过替换脚本对cpuprofile进行自动映射到真实函数。使用方式:python update_v8_wasm_profile.py $cpuprofile $symbol
  3. 如希望能从游戏启动立即抓取profile,请在game.js末尾代码稍作修改:
    js
    const gl = GameGlobal.canvas.getContext('webgl') 
    +    gl.clear(gl.COLOR_BUFFER_BIT);
    +    setTimeout(() => {
    +    gameManager.startGame();
    +    GameGlobal.manager = gameManager;
    + }, 10000);
    修改后,游戏启动将会有10s黑屏,可在此期间打开调试。
  4. 最新版本Chrome/Edge已经将Javascript Profiler默认隐藏,你可以使用微信开发者工具查看.cpuprofiler,或是通过以下方式将它在浏览器显示出来: image

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/AssetDescription.html b/Design/AssetDescription.html new file mode 100644 index 00000000..3731d5d3 --- /dev/null +++ b/Design/AssetDescription.html @@ -0,0 +1,24 @@ + + + + + + MiniGameConfig.asset 配置文件说明 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

MiniGameConfig.asset 配置文件说明

位于 Assets/WX-WASM-SDK-V2/Editor/MiniGameConfig.asset 即为 WXSDK 的导出配置文件,其中部分配置可在微信小游戏导出面板中可视化配置,本节将对配置文件中各项字段进行说明,开发者可直接修改其配置内容。

ProjectConfig:

字段类型说明
projectNamestring项目名称。
Appidstring微信小游戏Appid,前往 https://mp.weixin.qq.com/ 注册获得。
CDNstring游戏CDN前缀。
assetLoadTypeint首资源包加载方式,0: CDN加载;1: 小游戏包内加载。
compressDataPackagebool将首包资源Brotli压缩, 降低资源大小. 注意: 首次启动耗时可能会增加200ms, 仅推荐使用小游戏分包加载时节省包体大小使用。
VideoUrlstring加载阶段视频URL,可缺省。
DSTstring导出路径。
StreamCDNstring已废弃。
bundleHashLengthint自定义Bundle文件名中hash部分长度,默认值32,用于缓存控制。
bundlePathIdentifierstring路径中包含特定标识符开始下载bundle,将被自动缓存。半角分号分隔。
bundleExcludeExtensionsstring排除路径下指定类型文件不缓存。半角分号分隔。
AssetsUrlstring已废弃。
MemorySize: 256int游戏内存大小(MB)。
HideAfterCallMainboolcallmain完成后是否立即隐藏加载封面。
preloadFilesstring预下载列表。半角分号分隔。
Orientationint设备方向,0:Portrait; 1:Landscape; 2:LandscapeLeft; 3:LandscapeRight。
bgImageSrcstring启动背景图。
dataFileSubPrefixstring拼接在DATA_CDN和首包资源文件名的路径,用于首包资源没放到DATA_CDN根目录的情况。
maxStorageint最大缓存容量,单位MB,设置后若接近容量阈值将自动回收。
defaultReleaseSizeint清理缓存时默认额外清理的大小,单位Bytes,默认值30MB。
texturesHashLengthint微信压缩纹理工具处理的尾部hash长度,用于识别缓存。
texturesPathstring微信压缩纹理工具处理的纹理CDN拼接路径。
needCacheTexturesbool是否缓存微信压缩纹理工具处理的贴图资源。
loadingBarWidthint加载进度条的宽度,默认240。
needCheckUpdatebool是否需要启动时自动检查小游戏是否有新版本。
disableHighPerformanceFallbackbool是否禁止开启高性能模式后在不支持的iOS设备上回退为普通模式,注意:不要随意修改,只有开通高性能模式后并确认不回退才修改。
IOSDevicePixelRatiofloatIOS限制固定的分辨率,以减少内存,但是会降低游戏画面品质。

SDKOptions:

字段类型说明
UseFriendRelationbool是否使用好友关系链。
UseCompressedTexturebool已废弃。
UseMiniGameChatbool是否使用社交组件。
PreloadWXFontbool是否使用预载系统字体。

CompileOptions:

字段类型说明
DevelopBuildboolDevelopment Build.
AutoProfileboolAutoconnect Profiler.
ScriptOnlyboolScripts Only Build.
Il2CppOptimizeSizebool对应于Il2CppCodeGeneration选项,勾选时使用OptimizeSize(默认推荐),生成代码小15%左右,取消勾选则使用OptimizeSpeed。游戏中大量泛型集合的高频访问建议OptimizeSpeed,在使用HybridCLR等第三方组件时只能用OptimizeSpeed。(Dotnet Runtime模式下该选项无效)。
profilingFuncsboolProfiling Funcs.
Webgl2boolWebGL2.0
fbslimbool导出时自动清理UnityEditor默认打包但游戏项目从未使用的资源,瘦身首包资源体积。(团结引擎已无需开启该能力)。
DeleteStreamingAssetsboolClear Streaming Assets.
ProfilingMemoryboolProfiling Memory.
CleanBuildboolClean WebGL Build.
CustomNodePathstring已废弃。
showMonitorSuggestModalbool是否显示最佳实践检测弹框。
enableProfileStatsbool是否显示性能面板。
enableRenderAnalysisbool是否显示渲染分析日志(develop build才生效)。
iOSAutoGCIntervalintiOS高性能模式自动GC间隔(毫秒)。
enableIOSPerformancePlusbool是否使用iOS高性能Plus。
brotliMT: 1bool是否使用brotli多线程压缩
autoAdaptScreenbool是否使用自适应屏幕尺寸变化

CompressTexture:

以下是微信压缩纹理工具涉及配置,如未使用微信压缩纹理工具可以不予设置。

字段类型说明
halfSizebool已废弃。
useDXT5bool是否开启 PC 压缩纹理。
bundleSuffixstring已废弃。
parallelWithBundleint已废弃。
bundleDirstring自定义 AB 包目录路径。
dstMinDirstring压缩纹理产物输出目录。
debugModebool是否开启仅 ASTC 模式。
forcebool是否强制重新执行。

PlayerPrefsKeys:

使用PlayerPref接口时传入的key,此处设置将预先加载。

FontOptions:

字体相关配置。请阅读 WXFont章节

字段类型说明
CJK_Unified_Ideographsbool-
C0_Controls_and_Basic_Latinbool-
CJK_Symbols_and_Punctuationbool-
General_Punctuationbool-
Enclosed_CJK_Letters_and_Monthsbool-
Vertical_Formsbool-
CJK_Compatibility_Formsbool-
Miscellaneous_Symbolsbool-
CJK_Compatibilitybool-
Halfwidth_and_Fullwidth_Formsbool-
Dingbatsbool-
Letterlike_Symbolsbool-
Enclosed_Alphanumericsbool-
Number_Formsbool-
Currency_Symbolsbool-
Arrowsbool-
Geometric_Shapesbool-
Mathematical_Operatorsbool-
CustomUnicodebool-

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/AssetOptimization.html b/Design/AssetOptimization.html new file mode 100644 index 00000000..f2e89c12 --- /dev/null +++ b/Design/AssetOptimization.html @@ -0,0 +1,24 @@ + + + + + + 资源优化 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

资源优化

可通过转换工具配套提供的资源优化工具,将游戏内纹理资源针对webgl导出做优化。

工具入口

菜单栏-微信小游戏-资源优化工具

入口

工具介绍

Texture

资源处理工具面板

  1. 区域1: 选中目录,以设定规则扫描目录下文件。 搜索规则
  • 已开启MipMap: 搜索已开启了MipMap的纹理
  • NPOT: 搜索非POT图片
  • isReadable: 搜索已开启readable纹理
  • MaxSize大于512: 搜素MaxSize大于512纹理
  1. 区域2: 以设定规则修复列表中选中的资源 注意: 每次修复时将当前所要修复资源的importer覆盖写入到Library/AssetImporterbak; 还原时,从Library/AssetImporterbak读取选中资源的importer设置并还原后,会删除Library/AssetImporterbak,并不是undo/redo逻辑
  • 禁用readable:关闭readable
  • 禁用mipmap:关闭mipmap
  • 优化maxsize:勾选后,可选择优化maxsize的方式

maxsize

其中,自动减半根据当前纹理尺寸,将maxsize设置为纹理宽高最大值的一半。

  • change texture format: 勾选后可修改纹理压缩格式

textureformat

  1. 区域3: 筛选列表展示结果
  2. 区域4: 列表总览
  3. 区域5: 资源列表 支持一键全选、按资源名搜索
  4. 区域6: 引用查找 选中一个资源,查找资源被引用关系

优化建议

  • 小游戏平台下不需要太大的纹理,合理设置纹理maxsize可以减小纹理资源大小,最大不要超过1024。
  • MipMap: UI不需要开启mipmap,开启会增大1/3内存。
  • read/write enabled: 一般不需要访问纹理像素, 并且unity也是默认关闭。开启后会占用GPU显存和CPU内存。
  • NPOT纹理无法使用压缩纹理,注意修改纹理尺寸。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/AudioAndVideo.html b/Design/AudioAndVideo.html new file mode 100644 index 00000000..9f1b4c9c --- /dev/null +++ b/Design/AudioAndVideo.html @@ -0,0 +1,24 @@ + + + + + + 音视频适配 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

音视频适配

音频

目前 UnityAudio 已自动适配微信小游戏,优先建议使用 UnityAudio 来播放音频,也支持 FMOD 插件

兼容原理

UnityAudio 原理:

  • 长音频播放使用的是InnerAudio
  • 短音频播放使用的是WebAudio
  • Unity 插件会根据音频文件大小自动适配使用不同的播放方式

FMOD 原理:

  • 全部使用WebAudio,因此不推荐背景音乐等大文件使用 FMOD 播放,会占用很大内存

QA

  1. 在 IOS 17.5 以上的版本,小游戏退后台后返回音效无法继续播放了
  • 可以尝试更新最新的插件版本,可以避免一些出现的情况,我们正在尝试兼容 IOS 的更新
  1. IOS 偶现音频报错 operateAudio:fail jsapi has no permission
  • 音频播放时小游戏退后台就有可能出现,没有实际影响,可以忽略
  1. 音频播放时游戏卡顿
  • 如果同时播放的音频数量过多,是有可能造成游戏延迟卡顿的,建议限制同时播放的音频数量
  1. 部分音频文件在安卓无法循环播放
  • 已知问题,8.0.51 客户端版本修复
  1. 音频在 PC 端无法循环播放完整音频
  • 已知问题,更新最新的 Unity 导出插件
  1. 推荐使用什么音频格式
  • 推荐 mp3 或者 aac 格式,在双端有较好的兼容
  1. FMOD returns error code 36
  • 旧版本引擎已知问题,推荐使用已修复的 Unity 引擎版本,参考Unity 社区回答

视频

在微信小游戏中有两种播放视频的方式,目前 VideoPlayer 组件已自动适配微信小游戏,只有全屏视频的场景也可以选择使用WXVideo API

VideoPlayer 支持版本

不同客户端的支持情况不同,以下为最低支持版本:

参数版本
IOS 高性能+暂不支持
IOS 高性能8.0.41
安卓8.0.40
PC基础库 3.2.1
开发者工具基础库 3.2.1 + 1.06.2310312

QA

  1. VideoPlayer 视频在 IOS 无法播放,在其他平台都可以播放?
  1. VideoPlayer 视频在 IOS 播放有声音没画面?
  • 开启了高性能+,先临时关闭高性能+
  1. VideoPlayer 为什么在 IOS 高性能模式只能同时播放一个视频?
  • IOS 的播放策略,只能从逻辑上兼容
  1. 应该使用 VideoPlayer 还是 WXVideo?
  1. WXVideo 真机播放正常,开发者工具无法播放?
  • 开发者工具暂时有异常,先主动切换到3.4.10版本基础库查看
  1. WXVideo 在 IOS 设置 underGameView 之后黑屏,有声音没画面?
  • 需要开启高性能模式

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/BackendServiceStartup.html b/Design/BackendServiceStartup.html new file mode 100644 index 00000000..0998f488 --- /dev/null +++ b/Design/BackendServiceStartup.html @@ -0,0 +1,76 @@ + + + + + + 后端服务指引 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

后端服务指引

后端服务模式

微信小游戏对后端服务无任何限制,可以根据自身需求选择,比如:

  1. 自建后端:支持 websocket、HTTP 通信
  2. 云开发:云开发可以降低运维、研发成本,详见云开发-指引
  3. 1、2 混合的模式

自建后端服务

登录态参考登录态管理 通过 websocket 或者 HTTP 通信,理论上 App 和微信小游戏大部分后端服务可以直接复用

云开发

以实现一个服务端校验内容安全的云函数为例对云开发流程进行简单介绍,更多文档和示例请参考云函数文档

注意:此示例仅供参考云函数使用流程,正常情况下对内容进行安全校验的逻辑应该是内容校验通过+内容存储到后端在同一个云函数中实现,避免直接调用存储接口绕开校验的情况出现。

  1. 新建一个云函数的空工程 云函数可以和前端的游戏逻辑独立创建为不同的项目。当然也可以在同一个项目中(project.config.json 中指定 cloudfunctionRoot,避免云函数代码被业务逻辑代码一同打包发布到外网),以下示例为独立项目的模式

  2. 该小游戏首次使用云开发需要先开通云开发

    云开发有一个基本的免费套餐,请求量达到一定上限后需要配额调整申请代金券后更换配额套餐

  3. 实现一个云函数 以“内容安全检查”云函数(msgSecCheck)为例,复制示例中 login 文件夹,重命名为 msgSecCheck,修改 index.js 中的内容实现服务端逻辑:

Javascript
/*
+ *  // msgSecCheck
+ *  message Request {
+ *      string content;
+ *  }
+ *  message Response {
+ *      int code; // 返回码, 0:内容正常; 1:参数非法; 87014: 内容含有违法违规内容
+ *  }
+ */
+
+const cloud = require('wx-server-sdk')
+
+cloud.init({
+    env: cloud.DYNAMIC_CURRENT_ENV
+})
+
+function Response(code) {
+    return {
+        code,
+    }
+}
+
+exports.main = async (event, context) => {
+    if (!event.content) return Response(1);
+    try {
+		// https://developers.weixin.qq.com/minigame/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
+        await cloud.openapi.security.msgSecCheck({
+            content: event.content,
+        });
+        return Response(0);
+    } catch (e) {
+        return Response(e.errorCode);
+    }
+}

修改 config.json,增加对 openapi.security.msgSecCheck 的声明,如没有用到 openapi 则无需修改 config.json:

json
  "permissions": {
+    "openapi": [
+        "security.msgSecCheck"
+    ]
+  }

openapi 更多使用细节参考云调用文档

  1. 部署云函数
  • 云函数可以同时存在多个环境(可自定义,如测试环境、生产环境。本示例为"product"),选中需要部署的云函数环境:
  • 选中需要部署的云函数(本示例为"msgSecCheck"),点击“创建并部署:云端安装依赖”(本云函数仅依赖了 wx-server-sdk 模块,选云端安装依赖即可;若使用了其他第三方 node 模块,则需要选“创建并部署:所有文件”)
  • 等云函数部署完成(看工具的提示),Console 可以输入调用云函数代码进行简单测试,或者右键云函数-开启云函数本地调试
Javascript
wx.cloud.init({env:"product"})
+
+wx.cloud.callFunction({
+  name: 'msgSecCheck',
+  data: {
+    content: "hello cf"
+  },
+  success:function(res) {
+  	console.log("call success", res);
+	const isContentOk = (res.result && res.result && res.result.code === 0);
+	console.log("IsContentOk", isContentOk)
+  },
+  fail: function(res){
+	console.log("call fail", res);
+  }
+})

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/BuildTemplate.html b/Design/BuildTemplate.html new file mode 100644 index 00000000..7801aa24 --- /dev/null +++ b/Design/BuildTemplate.html @@ -0,0 +1,122 @@ + + + + + + 配置构建模板 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

配置构建模板

简介

Unity/团结快适配项目最终导出 minigame 目录即为微信小游戏代码包,使用微信开发者工具打开并上传。该部分主要由 JavaScript、JSON、WASM及图片资源构成。在实际的游戏开发中,开发者存在需要对 minigame 目录中产物做一些定制化的修改,这些修改同时也要跟随项目内容一起进行代码托管。为此微信提供配置构建模板的能力。

结构说明

  • 在Package Manager导入WXSDK模式下的目录 Packages/com.qq.weixin.minigame/Runtime/wechat-default
  • 以及在Assets导入资源模式下的目录 Assets/WX-WASM-SDK-V2/Runtime/wechat-default

两个目录中的 wechat-default 是项目的基础模板,基础模板不建议开发者进行编辑,因为随着新的SDK的更新覆盖也将失去其修改内容。

开发者需要手动创建 Assets/WX-WASM-SDK-V2/Editor/template 目录,在 template/minigame 目录中的资源内容将会按照完整的层级结构覆盖到最终的 minigame 的导出目录中。

直观的结构:

# 游戏工程目录
+Assets
+├─ WX-WASM-SDK-V2
+│  ├─ Editor
+│  │  ├─ template      # 自行创建该目录内容
+│  │  │  ├─ minigame
+│  │  │  │  └─ ...     # 需要被覆盖的资源文件
+│  │  │  └─ plugin.cs  # 可缺省创建,请阅读「构建模板前后不同时机的钩子」小节
+│  │  └─ ...
+│  └─ ...
+└─ ...
+
+# WXSDK目录
+Packages/com.qq.weixin.minigame 或 Assets/WX-WASM-SDK-V2
+├─ Runtime
+│  ├─ wechat-default   # 基础模板
+│  └─ ...
+└─ ...
+
+# 导出资源目录(转换微信小游戏产物)
+wechat
+├─ minigame      # 基础模板 + template(合并结果)
+│  └─ ...
+└─ webgl

值得注意的是,基础模板(wechat-default)并不是一个可以运行的标准JavaScript代码包,因为其中包含了大量的占位符将在导出时根据项目不同的实际情况作出替换,因此开发者在 template/minigame 创建用于覆盖的脚本时,应该以 wechat-defalut 中的脚本为修改基准,而不是导出的资源目录 wechat/minigame 中的资源作为参考。如此一来你自定义模板也将适应占位符的内容作出最终的结果变更。

新版本SDK引起的冲突提醒

随着WXSDK的更新,如果你覆盖过 wechat-defalut 中的关键脚本,那么在新版本WXSDK导入后可能会引起部分功能表现异常,因此WXSDK将识别到关键脚本发生更新且被开发者自定义覆盖的情况下作出警告。(只会检查 .js .json 文件冲突,图片文件不会检查)

  • 在WXSDK初始化时(引擎启动、或导入新的WXSDK时)作出检查

    检查异常时将在Unity控制台中给出详细的冲突信息;

  • 在导出微信小游戏时作出检查

    检查异常时将终止导出,并在Unity控制台中给出详细的冲突信息。

消除冲突提醒

观察到异常提醒后开发者需要根据提醒前往对比冲突的脚本内容自行适配,当冲突的自定义模板文件较冲突前发生变化后提醒也将自动消除。

JSON配置合并

时常开发者需要对 game.jsonproject.config.json 配置文件内容的做针对性的修改,当然使用后面小节提及的钩子能力可以很万能的做出内容修改,但这毕竟需要开发者进行一定的代码编写。构建模板能力为开发者提供了一个JSON配置合并能力,只需要自定义模板目录放置JSON,并且只填写你关注的字段,构建模板能够自动帮你完成相同JSON文件的字段合并。

支持合并的文件为:

  • game.json
  • project.config.json

合并规则:Key-Value 字段将在末位节点新增或覆盖,Array 将整节点新增或覆盖。

例如:

自定义模板 .../Editor/template/minigame/game.json

js
{
+  "test": "abc123",           // 最终模板将新增该字段与值
+  "plugins": {
+    "UnityPlugin": {
+      "version": "1.2.52"     // 最终模板仅变更该版本号
+    }
+  },
+  "subpackages": [            // 最终模板会因该字段为数组类型,将整节点替换
+    "..."
+  ]
+}

构建模板前后不同时机的钩子

有时候简单的覆盖可能并不能满足开发者复杂的修改需要,在构建时提供的不同时机钩子允许开发者使用C#代码来替换或变更是更灵活自由的方案,我们提供了 BuildTemplateHelper 工具类来便捷的获得三个目录的绝对路径。

钩子介绍

在构建模板中通常需要以下几个阶段的钩子:

使用钩子

为了统一约定,推荐开发者创建位于 Assets/WX-WASM-SDK-V2/Editor/template/plugin.cs 脚本来执行构建模板相关的设计。

# 游戏工程目录
+Assets
+├─ WX-WASM-SDK-V2
+│  ├─ Editor
+│  │  ├─ template
+│  │  │  ├─ minigame
+│  │  │  │  └─ ...
+│  │  │  └─ plugin.cs  # 请创建该文件并编写钩子逻辑
+│  │  └─ ...
+│  └─ ...
+└─ ...

样例:

c#
// plugin.cs
+using System.IO;
+using UnityEngine;
+using WeChatWASM;
+
+/// <summary>
+/// 构建生命周期回调钩子
+/// 注意事项:
+///     请创建脚本在 Editor (子)目录下;
+///     回调钩子请使用 public 声明成员函数
+/// </summary>
+public class PluginDemo : LifeCycleBase
+{
+
+    public override void afterCopyDefault()
+    {
+        // code...
+        Debug.Log("afterCopyDefault");
+    }
+
+    public override void beforeCopyDefault()
+    {
+        // 可使用 Exception 阻止继续构建导出
+        throw new System.Exception("Build Failed.");
+    }
+
+    public override void beforeCoverTemplate()
+    {
+        // 读取你的自定义模板目录并对其中的资源做动态修改
+        var tmp = BuildTemplateHelper.CustomTemplateDir;
+        using (
+          FileStream file = new FileStream(
+            Path.Combine(tmp, "newFile.js"),
+            FileMode.Create, FileAccess.Write))
+        {
+            using (StreamWriter writer = new StreamWriter(file))
+            {
+                writer.WriteLineAsync("Your Code Content.");
+            }
+        }
+        // 尽管你在导出期间动态的创建/修改了自定义模板中的资源
+        // 在导出结束后WXSDK会自动恢复你的修改
+    }
+}

BuildTemplateHelper介绍

BuildTemplateHelper 为你便捷的提供了各个目录的绝对路径:

c#
// wechat-default(标准模板)
+// 位于 WXSDK 目录下标准模板绝对路径
+string baseDir = BuildTemplateHelper.BaseDir;
+
+
+// template(自定义模板)
+// 游戏工程中 Assets/WX-WASM-SDK-V2/Editor/template/minigame 绝对路径
+string templateDir = BuildTemplateHelper.CustomTemplateDir;
+
+
+// wechat/minigame(导出产物)
+// 开发者在导出面板配置的导出路径的微信开发者工具打开的 minigame(默认) 绝对路径
+string outDir = BuildTemplateHelper.DstMinigameDir;

搭配钩子介绍小节中的不同阶段,可以任意的对你的 wechat-default(标准模板)template(自定义模板)wechat/minigame(导出产物) 中进行新的脚本创建、已有脚本中局部代码的文本替换(例如使用正则替换)甚至是图片等资源的变更。

在导出期间修改你的自定义模板,在结束导出后不会真实的影响你的游戏工程内容,WXSDK已经为你还原,这对于你托管项目代码很便捷。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/CompressedTexture.html b/Design/CompressedTexture.html new file mode 100644 index 00000000..dee7a154 --- /dev/null +++ b/Design/CompressedTexture.html @@ -0,0 +1,39 @@ + + + + + + 微信小游戏压缩纹理工具2.0(Beta) | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

微信小游戏压缩纹理工具2.0(Beta)

概述

​ 早期 Unity(2018-2020) 不支持对 ASTC 纹理格式进行导出,因此在移动端中无法充分利用 GPU 完成硬件的解码渲染。为弥补这一缺陷,微信 Unity SDK 提供压缩纹理按需加载的能力工具。使用该工具将对项目获得如下增益:

  • 降低 bundle 体积,资源按需加载,加快游戏运行进度

​ 压缩纹理工具将纹理资源从 Bundle 中分离单独托管,因此 Bundle 体积将变小,这有助于加快游戏运行进度。对于被分离的纹理资源将在游戏实际的使用过程中按渲染需要动态加载。

  • 有效降低内存,提升渲染效率

​ 使用压缩后的纹理本身将节约更多的内存空间,这对于内存吃紧的游戏至关重要。微信压缩纹理工具将对同一个纹理资源生成多种不同格式的压缩纹理(如ASTC、DXT……),在游戏运行中如需按需加载,根据实际运行设备 GPU 下载可被识别的压缩纹理。对于资源体积而言将更小,由 GPU 实现硬件解码,效率更高。

使用建议

Unity引擎自带压缩纹理:

​ 更统一的工作流;ASTC能支持最近3-4年大部分机型;但PC端不支持ASTC依然需要解压。

微信小游戏压缩纹理工具:

​ 支持不同平台的自适应(ETC2,ASTC,DXT);同时纹理从ab中剥离出来,使得ab占用内存更小。

建议:

​ 如引擎版本高于2021, 可使用引擎自身的ASTC压缩格式(移动端覆盖率较广,PC微信、微信开发者工具将软解为RGAB32)。对于重度游戏(如MMO、SLG等)内存压力大时,可结合使用WXAssetBundle减少ab体积造成的文件内存

​ 低版本引擎(2018-2020)应使用 微信UnitySDK压缩纹理工具 进行处理。

Unity 版本支持问题

​ 压缩纹理工具对于 Unity 2019、2020、2021 的部分版本有支持,目前已知一些版本无法使用(如 2021.3.x 、 2020.3.36 等不可用)。为了确保压缩纹理工具的顺利进行,建议开发者根据 年份大版本 的基础上选用我们已经验证可行的 Unity 版本:2019.4.28f1c1 、2020.3.10f1c1、2021.2.18f1c1,使用新的 Unity 版本后需要重新构建 Bundle 。

Unity引擎自带压缩纹理微信小游戏压缩纹理工具
版本支持Unity 2019支持部分;Unity 2020支持部分格式;Unity 2021支持2019、2020、2021均有版本支持
格式支持Unity 2019支持DXT等;Unity 2020支持DXT、ETC,但不支持ASTC;Unity 2021支持多数DXT、ASTC、ETC均支持
按设备加载不支持支持

使用说明

请务必确保使用压缩纹理工具时,导出的游戏工程来自 同版本微信 Unity SDK

主要的执行过程如下图所示:

compressedTexture02.png

1.安装 Node.js

下载并安装 Node.JS 并检查环境变量是否生效。

​ 新版本已不再依赖 Node.js。

2.构建 Bundle 文件

​ 项目中若使用 bundle 文件,需先构建 AB包。请勿开启 crc 对 bundle 进行校验。

构建前的纹理格式配置说明:

​ 纹理资源的 WebGL SettingsFormat 配置项支持列表:

Format支持情况
R 8 / R 16 bit支持
RGBA Crunched DXT5|BC3不支持
RGB Crunched DXT1|BC1不支持
RGBA Compressed DXT5|BC3支持
RGB Compressed DXT1|BC1支持
Alpha 8支持
RGBA Compressed ETC2 8 bits不支持
RGB Compressed ETC2 4 bits支持
RGB Compressed ETC 4 bits请勿使用资源占位符专用,全游戏工程请勿使用!
ASTC 请参考配置说明--
RGB(A) Compressed BC7支持
RGBA 32 bit支持

ASTC格式配置说明:

​ ASTC 是多数移动设备中游戏运行的主要支持的纹理格式,因此也是微信小游戏环境下主要使用到的压缩的纹理资源。

​ 在 2021版本 Unity 纹理资源的 WebGL SettingsFormat 配置项中,工具支持识别 RGB(A) Compressed ASTC 8x8、6x6、5x5、4x4 block 这三种压缩格式,其余格式请勿设置,并且不支持 ASTC HDR 系列的格式。

​ 若以上述4种格式配置后,最终生成的多份格式资源中,ASTC 资源将保持对应的 Block Size。值得注意的是,默认推荐使用 Block Size 8x8 格式,4x4 最清晰内存占用也会升高,开发者应根据实际调试后运行效果按需配置。

3.导出游戏

​ 点击微信小游戏 - 转换小游戏 - 导出WEBGL并转化为小游戏 导出游戏工程。请注意!任何时候当 微信Unity SDK 更新后,均需要重新执行该步骤(导出游戏工程)再使用同版本的压缩纹理工具完成后续操作,不可混版本使用

4.执行压缩纹理

​ 点击 微信小游戏 - 包体瘦身--压缩纹理 ,可点击 打开bundle配置面板 查看识别情况,并按需忽略部分不希望执行压缩纹理的bundle资源,点击 处理资源 开始处理。

调试模式 将只生成 ASTC 格式(开发者工具中使用PNG资源,移动设备使用 ASTC格式资源),调试结束后可再次选用全量模式(默认采用增量逻辑不会额外增加处理时间)

​ 该步骤根据项目实际情况不同,处理时间也会有差异,执行完成后请留意控制台提示信息,不可存在多个警告消息。

avatar

5.上传CDN

​ 执行完上述步骤后,将 webgl-min 目录中的资源上传至 CDN 服务器中,如 Assets 目录、StreamingAssets目录、xxx.webgl.data.unityweb.bin.txt 等文件。

WebGL2.0 支持说明(Beta)

​ 微信纹理压缩目前已支持WebGL2.0模式下的Gamma与Linear颜色空间渲染,但仅支持2019、2020、2021 3个年限中部分版本,其中2019必须使用Unity与微信合作的Instant Game版本,其余年限跟随微信纹理压缩支持版本进行选择。该能力仍在兼容一些特殊的应用场景,开发者使用后需要进行详细的真机测试。

忽略配置说明

​ 对于微信压缩纹理工具处理后部分资源渲染效果较差、甚至无法处理的情况,开发者使用忽略处理能力完成对资源的保留在AB包内,从 微信压缩纹理 - 打开配置面板 进入配置页,默认情况下配置页面中将扫描当前项目所有可被处理的AB包资源,对于AB包的忽略直接在右侧 忽略 勾选项选中后保存即可。 ​ 有时忽略整个AB包并不是一种好的策略,仅仅是AB包内部分纹理资源渲染不佳,此时若已经执行过微信压缩纹理能力时,扫描的资源将包含AB包内的单个纹理资源信息,可通过右上角搜索栏检索快速查找对应的纹理资源进行忽略设置,保存后只需再次执行即可。若此前从未执行过微信压缩纹理,需要点击 解包纹理 按钮,等待完全解包后可进行纹理的配置操作,该过程等同执行微信压缩纹理的「阶段一」,大型工程可能花费一些时间。

首资源包优化说明

​ 位于 微信小游戏转换工具面板 - 首资源包优化 能力隶属于微信压缩纹理工具的扩展范畴。该功能能够将首资源包中 Unity Editor 默认打包的资源(但游戏从未使用过)进行剔除,从而再次降低首资源包体积,该功能可以在不开启微信压缩纹理工具的情况下使用。 ​ 默认情况下无需开发者进行手动的配置(工具已经能够识别多数Unity Editor的无用资源),但该能力仍然允许开发者进行手动的进行资源选择,来自定义剔除。请注意当开发者手动配置时需要自行判断资源是否是游戏中的必要资源,不慎剔除将导致游戏的渲染异常。

新版本异常回退说明

​ 微信纹理压缩升级了全新的内核程序,尽管发布前进行了多数Unity年限版本与常见机型的测试,目前仍处于初期测试使用,若使用期间存在异常影响正常的游戏发布可前往issues提出问题,并使用上一代稳定版微信纹理压缩包(旧)导入工程后采用旧版本完成游戏发布。旧版本使用指引请参阅:微信压缩纹理使用说明(旧)

原理解释

​ 微信纹理压缩工具底层原理是将bundle内纹理资源分离,将资源指针替换至原bundle内,分离出的资源将被处理成多种不同GPU所支持的纹理格式托管至CDN中,游戏实际运行时将劫持渲染时根据资源指针以及当前设备GPU所支持的纹理格式进行远程加载,成功加载立即上传GPU后将从系统内存释放。这样的工作原理即做到了不同硬件所支持的纹理格式按需加载,又相比于bundle全部加载至内存时占用过多的系统内存。经过微信小游戏团队测试,该工具能够降低游戏的运行时内存情况,不同的游戏之间使用的场景、纹理差异降低值是不相同的。

Q&A

1.生成的纹理太大

​ PC端上预览的时候展示的是PNG图片会比较大,手机上用的是带txt后缀的,如astc.txt, 这些文件压缩率很高,注意正式环境CDN一定要开启Brotli或者Gzip,这样加载的时候纹理就会很小。速度快很多。建议优先使用Brotli。

2.资源上传至CDN的注意事项

​ 上传至CDN时,请注意要按二进制传输,强制storebinary,如果按文本传输也会出现加载回来的图片成黑色。

3.非4倍数的资源处理底层逻辑

​ 移动设备中大多数使用 ASTC 作为主要的纹理资源格式,ASTC 是不受纹理资源高宽影响的,因此非 4 倍数底层逻辑处理并不会对移动设备上的表现有差异。而对于 DXT 格式是 PC 小游戏中主要的纹理资源格式,该格式是要求高宽必须为 4 的倍数,微信纹理压缩工具在资源处理的过程中识别了资源能否正确的被压缩处理,并在渲染期间做了兜底的渲染策略,在 PC 的表现上,若资源支持以 DXT 格式,则将采用 DXT 渲染,否则遵循兜底策略,其格式优先级为: ASTC、ETC2、DXT、PNG,最差的情况将使用 PNG 格式渲染。

4.Node.js异常处理

​ 压缩纹理工具执行需要依赖 Node.js 解释器,若执行前已安装 Node.js 但执行时提示未找到则需手动填入本机 Node.js 路径。请将 Node.js 的绝对路径填写至 Assets/WX-WASM-SDK/Editor/TextureEditor/WXAssetsTextTools.cs 文件的 NODE_PATH 变量中。若开发者使用API调用执行,可对该变量进行直接赋值。

5.分离纹理后各自单独下载是否会增加下载开销?

​ 不会。标准的CDN服务会支持http2协议,因此看似多条的请求背后系统仅会创建1条TCP/IP链路,所以并不会增加额外的请求开销。宏观来说你开启了CDN压缩情况下,游戏所需资源下载的总量没变、链接次数没变,却享受了不同设备按需使用纹理格式的能力。

6.MacOS系统执行报错 “'System.Drawing.GDIPlus' threw an exception”

​ 因为 Unity 自带 Mono 配置错误 libgdiplus.dylib 文件路径。有两种解决方案选择其一即可。

解决方案一:

​ 本地安装官方 Mono 后,代码配置微信压缩纹理工具用于执行的 Mono 解释器完整路径。

c#
// 在合理的时机进行路径配置:
+#if UNITY_EDITOR_OSX
+  WXAssetsTextTools.MONO_PATH = "/usr/bin/mono";     // 本机安装的 Mono 解释器完整路径
+#endif

解决方案二:

​ 先下载 libgdiplus.dylib 文件后,将其放在 UnityEditor /Applications/Unity/Hub/Editor/{$Unity_Editor_Version}/Unity.app/Contents/MonoBleedingEdge/lib/libgdiplus.dylib 路径下,并编辑 /Applications/Unity/Hub/Editor/{$Unity_Editor_Version}/Unity.app/Contents/MonoBleedingEdge/etc/mono/config 文件,将 target= .../libgdiplus.dylib 路径内容均变更为下载文件的存放完整路径,重启 Unity Editor 即可。

微信压缩纹理API介绍

​ 为方便开发者构建个性化的工程导出能力,微信压缩纹理工具提供了相应的 API 调用接口,开发者可以在游戏内自助构建游戏导出脚本,完成发布上传前的自动化操作。

提示:为简化调用,忽略ab、工程路径等数据均来自面板配置此处不提供相应参数传入,面板配置后将被存盘记录无需每次执行前进行配置。

WXAssetsTextTools.CompressText( ... )

​ void WXAssetsTextTools.CompressText(Action<bool, string> complete = null, string bundleDir = null, string outBundleDir = null, bool debug = false, bool force = false)

说明

​ 执行微信压缩纹理流程,该函数为异步函数。该方法对应【包体瘦身--压缩纹理】面板中「处理资源」按钮的执行,其中小游戏工程导出目录路径来自【转换小游戏】面板中配置。

参数

参数类型说明
completeAction执行结束的回调函数,形参1(bool) 返回执行是否成功,形参2(string)返回执行错误时的错误提示信息。
bundleDirstring可缺省,若存在独立的AB包目录,则此处填写目录的绝对路径。
outBundleDirstring可缺省,若填写bundleDir则不可省略,独立AB包处理后的输出目录。
debugbool可缺省,默认全量生成(false),true时仅生成ASTC格式纹理。
forcebool可缺省,默认遵循增量逻辑(false),true时将强制生成(已生成资源仍然生成并覆盖)。

例子:

c#
WXAssetsTextTools.CompressText((result, msg) =>
+  {
+    if (result)
+    {
+      Debug.Log("微信压缩纹理转换完成!");
+    }else{
+      Debug.LogError(msg);
+    }
+  }, 
+  null, 
+  null, 
+  false,
+  false);

WXAssetsTextTools.GetAssetBundles( ... )

​ void WXAssetsTextTools.GetAssetBundles(Action<string[]> callback = null, string bundleDir = null)

说明

​ 获取微信压缩纹理工具所能扫描到的符合条件的AB包路径数组。相同参数情况下,所扫描到的资源列表则为实际可被执行处理的资源。

参数

参数类型说明
callbackAction扫描结束的回调函数,形参(string[]) 返回扫描到的ab包资源绝对路径。
bundleDirstring可缺省,若存在独立的AB包目录,则此处填写目录的绝对路径。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/CustomLoading.html b/Design/CustomLoading.html new file mode 100644 index 00000000..38d09192 --- /dev/null +++ b/Design/CustomLoading.html @@ -0,0 +1,127 @@ + + + + + + 启动封面 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

启动封面

由于Unity WebGL启动加载需要一定时间,因此需要使用视频或图片等内容作为过渡以留住玩家。Unity Loader默认使用图片+进度信息,铺满全屏呈现。

开发者可自定义以下内容

  • 替换加载图片/视频
  • 加载文案及样式
  • 进度条样式
  • 封面自动隐藏时机

完整配置

转换插件配置

bgImageSrc: 启动封面图;-- $BACKGROUND_IMAGE
+VideoUrl: 启动视频;-- $LOADING_VIDEO_URL
+HideAfterCallMain: 是否callmain完成后立即隐藏封面;-- $HIDE_AFTER_CALLMAIN

game.js配置

样式配置未提供对应的转换插件配置入口,需要修改unity工程中,小游戏模板wechat-default/game.js

js
hideAfterCallmain: $HIDE_AFTER_CALLMAIN,// 是否需要callmain结束后立即隐藏封面视频
+// 加载页配置项
+loadingPageConfig: {
+  totalLaunchTime: 15000, // 默认总启动耗时,即加载动画默认播放时间,可根据游戏实际情况进行调整
+  /**
+   * !!注意:修改设计宽高和缩放模式后,需要修改文字和进度条样式。默认设计尺寸为667*375
+   */
+  designWidth: 0, // 设计宽度,单位px
+  designHeight: 0, // 设计高度,单位px
+  scaleMode: '', // 缩放模式, 取值和效果参考,https://github.com/egret-labs/egret-docs/blob/master/Engine2D/screenAdaptation/zoomMode/README.md
+  // 以下配置的样式,尺寸相对设计宽高
+  textConfig: {
+    firstStartText: '首次加载请耐心等待', // 首次启动时提示文案
+    downloadingText: ['正在加载资源'], // 加载阶段循环展示的文案
+    compilingText: '编译中', // 编译阶段文案
+    initText: '初始化中', // 初始化阶段文案
+    completeText: '开始游戏', // 初始化完成
+    textDuration: 1500, // 当downloadingText有多个文案时,每个文案展示时间
+    // 文字样式
+    style: {
+      bottom: 64,
+      height: 24,
+      width: 240,
+      lineHeight: 24,
+      color: '#ffffff',
+      fontSize: 12,
+    }
+  },
+  // 进度条样式
+  barConfig: {
+    style: {
+      width: 240,
+      height: 24,
+      padding: 2,
+      bottom: 64,
+      backgroundColor: '#07C160',
+    }
+  },
+  // 一般不修改,控制icon样式
+  iconConfig: {
+    visible: true, // 是否显示icon
+    style: {
+      width: 64,
+      height: 23,
+      bottom: 20,
+    }
+  },
+  // 加载页的素材配置
+  materialConfig: {
+    // 背景图或背景视频,两者都填时,先展示背景图,视频可播放后,播放视频
+    backgroundImage: '$BACKGROUND_IMAGE', // 背景图片,推荐使用小游戏包内图片;当有视频时,可作为视频加载时的封面
+    backgroundVideo: '$LOADING_VIDEO_URL', // 加载视频,网络url
+    iconImage: 'images/unity_logo.png', // icon图片,一般不更换
+  }
+},

下面根据配置介绍两种加载效果的实现

默认效果

实现默认效果很简单,开发者只需在导出时配置启动素材即可

所需配置项

js
bgImageSrc: 启动封面图;-- $BACKGROUND_IMAGE
+VideoUrl: 启动视频;-- $LOADING_VIDEO_URL
+HideAfterCallMain: 是否callmain完成后立即隐藏封面;-- $HIDE_AFTER_CALLMAIN
+loadingBarWidth: 加载进度条宽度;-- $LOADING_BAR_WIDTH

定制效果

启动loader提供的默认加载界面为了契合不同游戏,做得相对通用,但游戏可能会存在定制启动loading的需求,以达到和游戏更贴近的体验。

  • 小游戏表现

  • 设计稿 设计尺寸:1600*720

  • 小游戏配置
js
loadingPageConfig: {
+  totalLaunchTime: 15000, // 默认总启动耗时,即加载动画默认播放时间,可根据游戏实际情况进行调整
+  designWidth: 1600,
+  designHeight: 720,
+  scaleMode: scaleMode.fixedHeight,
+  textConfig: {
+    firstStartText: '', // 首次启动时提示文案
+    downloadingText: ['红中在手,天下我有'], // 加载阶段循环展示的文案
+    compilingText: '牌从门前过,不如摸一个', // 编译阶段文案
+    initText: '牌从门前过,不如摸一个', // 初始化阶段文案
+    completeText: '牌从门前过,不如摸一个', // 初始化完成
+    textDuration: 1500, // 当downloadingText有多个文案时,每个文案展示时间
+    style: {
+      bottom: 115,
+      height: 45,
+      width: 1045,
+      lineHeight: 45,
+      color: '#ffffff',
+      fontSize: 28,
+    }
+  },
+  barConfig: {
+    style: {
+      width: 1045,
+      height: 15,
+      padding: 2,
+      bottom: 78,
+      backgroundColor: '#66b71f'
+    }
+  },
+  materialConfig: {
+    // 背景图或背景视频,两者都填时,先展示背景图,视频可播放后,播放视频
+    backgroundImage: 'images/background.jpg',
+    iconImage:'images/unity_logo.png'
+  }
+}
  • scaleMode取值
js
// https://github.com/egret-labs/egret-docs/blob/master/Engine2D/screenAdaptation/zoomMode/README.md
+export const scaleMode = {
+  noBorder: 'NO_BORDER', // 常用之一,不留黑边
+  exactFit: 'EXACT_FIT',
+  fixedHeight: 'FIXED_HEIGHT', // 常用之一,高度适配
+  fixedWidth: 'FIXED_WIDTH', // 常用之一,宽度适配
+  showAll: 'SHOW_ALL',
+  fixedNarrow: 'FIXED_NARROW',
+  fixedWide: 'FIXED_WIDE',
+}

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/CustomSDK.html b/Design/CustomSDK.html new file mode 100644 index 00000000..c9e79cba --- /dev/null +++ b/Design/CustomSDK.html @@ -0,0 +1,41 @@ + + + + + + 自定义SDK调用 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

自定义SDK调用

​ 微信SDK提供了WX.CallJSFunctionWX.CallJSFunctionWithReturn接口实现了简单的第三方SDK调用,支持可序列化为JSON的任意数量的参数返回值

​ 其中,JS侧的实际调用逻辑为GameGlobal.sdkName.functionName(args),所以在调用之前需要保证SDK位于GameGlobal下且SDK中含有该名称的function。

​ 在WX.CallJSFunctionWithReturn中,会将函数返回值转换为JSON后传回,若无返回值则传回""

​ 如需更加复杂的调用,可参考WebGL:与浏览器脚本交互进行自定义定制。

版本要求

转换插件 >= 202406062127

代码示例

​ 示例中的"sdk"、"testFunction"、TestFunctionOption仅作为演示,实际使用中请自行更改。

csharp
WeChatWASM.WX.CallJSFunction("sdk", "testFunction", new TestFunctionOption
+{
+    type = "text",
+    text = "反馈",
+    style = new OptionStyle()
+    {
+        left = 10,
+        top = 10,
+        width = 100,
+        height = 100,
+        backgroundColor = "#ff0000",
+        color = "#ffffff",
+        textAlign = "center",
+        fontSize = 20,
+        borderRadius = 10,
+        lineHeight = 100,
+    }
+});

另外,在js侧代码中合适位置添加以下代码,可配合构建模版能力使用。

js
  GameGlobal["sdk"] = sdk;

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/CustomURP.html b/Design/CustomURP.html new file mode 100644 index 00000000..49b4ac48 --- /dev/null +++ b/Design/CustomURP.html @@ -0,0 +1,44 @@ + + + + + + 定制微信小游戏的 URP 管线 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

定制微信小游戏的 URP 管线

  • 本文档主要说明如何在 Unity 官方 URP 管线基础上,定制适合微信小游戏的 URP 管线。
  • URP 是 Unity 通用渲染管线,支持移动端、PC、WebGL 平台的游戏开发,它包含的功能很全面也很强大。
  • 但对于大部分微信小游戏,有些功能可能是用不上,诸如延迟渲染、XR、多光源管理等。直接用官方 URP 管线,那些用不到的功能在运行时可能也会有性能开销,因此,将那些游戏用不到的功能在编译期就去掉,对运行时性能会有提升。
  • 定制 URP 管线除了具备 C# 和 Shader 相关的编程知识,还要对渲染管线有一定了解。
  • 首先需要 本地化 URP 包

本地化 URP 包

  • 首先将官方的 URP 包本地化,本地化后我们可以自由地定制化 URP,Unity 也支持从本地加载 URP 相关的 Package 包
  • 这里假设 Unity 游戏项目工程已经安装好 URP,并且已经切换到 WebGL 平台,使用官方 URP 版本进行游戏开发
  • 打开 Unity Editor 后,点开 Window 菜单,并选中 Package Manager 打开 Package Manager 窗口
  • 选择 Packages:In Project,在 Packages - Unity 一栏显示的是 当前项目安装的 官方 Packages
    • 安装 URP后,列表会有 Universal RP项,选中,面板右测会显示 URP版本信息,右小角有 Remove 按钮
  • 除了 Universal RP包,URP 还会安装其他依赖包,主要有 Core RP LibraryShader Graph
    • Core RP Library 是 URP 依赖的基础代码包
    • Universal RP 是 URP 本身的代码包
    • Shader Graph 是 Shader 可视化编辑器的包
  • 选择 Packages:Unity Registry,才会看到 Core RP LibraryShader Graph 等包的情况
  • 定制 URP 主要需要修改 Universal RPCore RP Library 这两个包
  • 这里需要将 Universal RPCore RP Library 这两个包从项目工程的缓存目录里拷贝出来
    • 找到 项目工程的 Library/PackageCache/ 文件夹
    • 找到 com.unity.render-pipelines.universal@12.1.10com.unity.render-pipelines.core@12.1.10 两个子文件夹
      • 这里以 URP 12.1.10 版本 (配套Unity 2021.3.19),其他 URP版本的路径是差不多的,就是 @ 带的版本号不一样
    • 将这两个子文件夹拷贝到工程目录外的一个本地文件夹 (这里是放 D:/custom_packages/,路径随意,只要不要放到工程目录下即可)
  • Package Manager 窗口找到 Universal RP 选中,然后点击面板右下角的 Remove 按钮,移除掉官方的 URP版本
    • 除了 Universal RP包,Core RP LibraryShader Graph包也会同时被移除
  • 稍等一会,官方 URP 包就会被移除,此时 Unity Game 和 Scene 视图可能显示粉红色的渲染异常,这是正常现象,不用担心
  • 导入本地的 Core RP Library
    • 在 Package Manager 窗口,点击左上角 + 号按钮,在弹出列表选择 Add package from disk
    • 在弹出的 Select package on disk 窗口,选择 D:/custom_packages/com.unity.render-pipelines.core@12.1.10/package.json文件打开
  • 导入本地的 Universal RP包 再次点击 左上角 + 号按钮,选择 D:/custom_packages/com.unity.render-pipelines.universal@12.1.10/package.json文件打开
  • 注意 需要先导入本地的 Core RP Library,然后再导入Universal RP. 顺序不能反! (否则会自动引入官方的Core RP Library包)
  • 当导入完成后,Unity Game 和 Scene 视图得渲染应该会恢复正常的
  • 此时在 Package Manager 窗口 选择 Packages:In Project, 在 Packages - Other 一栏会看到Core RP LibraryUniversal RP本地化
  • 此时本地化 URP 包已经完成了,下一步可以在本地的包定制 URP
  • 如果此时 Unity Editor 有些 warning 甚至 error 的日志,可能和替换 URP 包有关系,一般重启一下 Editor 就好了
  • 接下来需要准备条件编译宏

准备条件编译宏

  • 为什么要用条件编译宏来定制代码 ?
    • 其实不用宏也可以定制本地化的 URP 包,但这样定制会影响到所有平台,而加了 WebGL 平台相关的宏,那么只会影响到 WebGL 平台
    • 有了编译宏可以保留 原来的 URP 的代码,也方便知道自己修改了哪些内容
  • 需要分别对 C# 脚本 和 Shader HLSL 代码 增加 微信小游戏专用宏 WX_PERFORMANCE_MODE
  • 在 C# 脚本增加宏定义WX_PERFORMANCE_MODE
    • 首先打开 Unity,在 Edit 菜单选择 Project Settings 打开该窗口
    • 然后在Project Settings 窗口选择 Player项,在 Player页选择 WebGL settings 标签页
      • 在该标签页下找到 Other Settings 的 Scripting Define Symbols
      • 点击+号,添加宏WX_PERFORMANCE_MODE,然后点击Apply 让其生效
      • 那么在 C# 脚本环境就会有宏WX_PERFORMANCE_MODE 的定义
  • 在 Shader HLSL 代码增加宏定义WX_PERFORMANCE_MODE
    • 这里采用了一种取巧的方式来定义(Unity 2021.3 没有定义 Shader HLSL 全局宏的接口,如果后面版本有相关的接口,那会方便很多)
      • com.unity.render-pipelins.core@12.1.10/ShaderLibrary/Common.hlslcom.unity.render-pipeline.universal@12.1.10/ShaderLibrary/Input.hlsl 这两个文件的开头新增以下代码:
c
#ifndef WX_PERFORMANCE_MODE
+    #if (defined(SHADER_API_GLES) || defined(SHADER_API_GLES30) || defined(SHADER_API_GLES3)) 
+        #define WX_PERFORMANCE_MODE 1
+    #else 
+        #define WX_PERFORMANCE_MODE 0
+    #endif 
+    #ifndef SHADER_API_MOBILE
+        #define SHADER_API_MOBILE WX_PERFORMANCE_MODE
+    #else 
+        #if !SHADER_API_MOBILE && WX_PERFORMANCE_MODE
+            #undef SHADER_API_MOBILE
+            #define SHADER_API_MOBILE WX_PERFORMANCE_MODE
+        #endif 
+    #endif 
+#endif
  • 这样,就可以在 C# 代码 和 Shader HLSL 代码 通过宏WX_PERFORMANCE_MODE来定制代码
c
#if WX_PERFORMANCE_MODE // 表示 微信 WebGL 平台
+...
+#endif
+
+#if !WX_PERFORMANCE_MODE // 表示 非微信 WebGL 平台
+...
+#endif
  • 注意 1:Shader HLSL 的 WX_PERFORMANCE_MODE 不是 WebGL 平台特有的,而是通过 SHADER_API_GLES* 宏来开启的,除了 WebGL 平台会启用 SHADER_API_GLES* 宏,还有 安卓 GLES 平台也会启用这个宏
  • 注意 2:Unity Editor 默认用渲染图形 API 是 DirectX,而不是 GLES,因此在 Editor 下,HLSL 的宏 WX_PERFORMANCE_MODE 是不生效的,而 C# 的是生效的
  • 注意 3:上述的代码除了启用了 WX_PERFORMANCE_MODE宏,还会启用SHADER_API_MOBILE
    • SHADER_API_MOBILE 宏是 Unity 对移动平台的一个优化项,在 WebGL 平台是没有开启这一项优化,这里顺带把它开启了
  • 接下来,可以定制本地化 URP 管线

定制本地化 URP 管线

  • 定制 URP 管线一般而言,是具体项目具体分析的,对于微信平台的小游戏,有一些共同点是可以参考的
  • 这里列举一些微信小游戏可考虑优化的功能:
    • Deferred 延迟渲染 和 GBuffer 相关Pass
    • 后处理,例如 FilmGrain(胶片颗粒)、PaniniProjection(圆柱状投影)、ChromaticAberration(颜色偏移后处理)等
    • XR 相关功能 (有相关 XR 宏,也可以再用 WX_PERFORMANCE_MODE 宏关闭)
    • Additional Lights 额外的光源 (基本一个主方向光就够了)
    • Clustered Rendering 光照分簇渲染 (多光源分簇渲染,基本上不上)
    • Reflection Probe 反射探头 (可以简化)
    • Light Probe 光照探头 (可以简化)
    • 材质 UnityPerMaterial 属性 (用不到的属性可以剔除掉)
    • Lightmap 光照贴图 (可以简化)
    • Shader 优化 (多余的 Uniform 变量、半精度、简化计算等)
    • 简化阴影 Shadow Cascades (可以简化)
    • Light Cookie (根据项目需要,看是否去掉)
    • ScreenSpaceShadows、ScreenSpaceOcclusion (屏幕空间阴影、遮蔽,根据项目需要,看是否去掉)
    • Motion Vector 相关 (根据项目需要,看是否去掉)
    • Decal 贴花 (根据项目需要,看是否去掉)
    • Fog 雾效 (根据项目需要,看是否去掉)
    • ColorGradingLutPass (根据项目需要,看是否去掉)
    • UseOptimizedStoreActions 设置
    • NormalReconstruction (根据项目需要,看是否去掉)
    • Debug 代码 DebugHandler、DebugDisplaySettingsUI、DrawGizmos、DrawWireOverlay (Debug代码,去调)
  • 除了上面列举的功能,还可以根据项目类型或项目需要简化或去掉 URP 一些功能
  • 下面是一个 [供参考的 URP 定制版本](#供参考的 URP 定制版本)

供参考的 URP 定制版本

  • 开发者请联系 小游戏客服助手 获取微信定制版的 URP 源码
  • 这是基于 Unity 2021.3.19 的 URP 12.1.10 版本定制的渲染管线,主要是用来参考如何定制 URP 管线,
  • 这个 URP 版本是基于大部分微信小游戏的渲染需要来定制的,主要修改有以下这些:
    • 不影响 GPU Instancing 和 SRP Batcher
    • 只支持一盏实时方向光,裁剪 Additional Light 额外的光照
      • 裁剪 _MainLightOcclusionProbes
      • 裁剪 _MainLightLayerMask, 默认使用 DEFAULT_LIGHT_LAYERS
    • 只支持最基础的 Lightmap,裁剪支持 Directional Lightmap 和 Dynamic Lightmap
    • 简化级联阴影 CSM
      • 修改 MainLightShadowCasterPass.cs
        • 去掉 SetEmptyMainLightCascadeShadowmap 额外开销
      • 半透明物体投射阴影,会被当作不透明物体
      • CSM 最多支持 2 级 (默认是 4 级的)
      • 裁剪软阴影
      • 裁剪 _ShadowBias 设置阴影偏移
      • 裁剪 ShadowFade
      • 裁剪 MixRealtimeAndBakedShadows
      • 裁剪 BEYOND_SHADOW_FAR
      • 裁剪 _MainLightShadowParams
    • 简化了 UnityPerMaterial 材质 (包括 UnlitInput、SimpleLitInput、LitInput、BakedLitInput 的)
    • TransformObjectToWorldNormal 和 TransformWorldToObjectNormal 使用 UNITY_ASSUME_UNIFORM_SCALING 版本
    • 只支持 unity_SpecCube0,裁剪 unity_SpecCube1,unity_SpecCube0_HDR 和 unity_SpecCube1_HDR,
      • 裁剪 ReflectionProbe Bleed 和 BoxProjection
    • 裁剪 _GlossyEnvironmentColor、_GlossyEnvironmentCubeMap 和 _GlossyEnvironmentCubeMap_HDR
    • 裁剪 unity_ProbesOcclusion ( 去掉了 Shader HLSL 对应的 uniform 变量 )
    • 裁剪 Alpha Test 镂空 (自己写的 Shader 可以支持镂空,这里是指 URP 自带的 Shader 裁剪了 镂空功能)
    • 裁剪 Fog 雾效
    • 裁剪 Deferred 延迟渲染 和 GBuffer 相关Pass
    • 裁剪 Decal 贴花
    • 裁剪 _DETAIL 细节纹理
    • 裁剪 Light Cookie
    • 裁剪 clearCoatMask 和 clearCoatSmoothness 清漆效果
    • 裁剪 ColorGradingLutPass
    • 裁剪 ClusteredRendering
    • 裁剪 XR
    • 裁剪 RenderGraph(代码用 WX_PERFORMANCE_MODE 屏蔽了)
    • 裁剪 MotionVector 运动向量或运动模糊
    • 裁剪 NormalReconstruction 法线重建
    • 禁用了部分不常用的后处理(FilmGrain、DepthOfField、CameraMotionBlur、PaniniProjection 等),只保留 Bloom 等少数后处理 (后处理慎用)
    • 裁剪 ScreenSpaceShadows、ScreenSpaceOcclusion
    • 裁剪 _Surface 设置表面的类型 (是否不透明)
    • 裁剪 unity_RenderingLayer
    • 裁剪 unity_LODFade
    • 裁剪 _AmbientOcclusionParam
    • 裁剪 _GlobalMipBias
    • 裁剪 _ScaledScreenParams
    • 裁剪 unity_WorldTransformParams
    • 裁剪 unity_OrthoParams(正交投影相机需要注意)
    • 裁剪 Camera renderScale (相机缩放会引入额外的 Pass)
    • 裁剪 UseOptimizedStoreActions 设置
    • SpeedTree7Passes 和 SpeedTree8Passes
      • 裁剪 dithering LOD transition
    • Shader HLSL 部分变量全精度改为半精度 (例如 normalWS 类型从 float3 改为 half3 )
    • Shader HLSL 其他的一些修改
      • 用 LinearToGamma22 替代 LinearToSRGB
      • 简化了 ReflectivitySpecular 函数
      • 简化了 DirectBRDFSpecular 函数
      • 简化了 VFXCalcPixelOutputForward 函数
      • 简化 SubtractDirectMainLightFromLightmap 函数
        • 去掉 _SubtractiveShadowColor 影响
    • 裁剪 DEBUG_DISPLAY、 DebugHandler、DebugDisplaySettingsUI、DrawGizmos、DrawWireOverlay
  • 所有 C# 和 Shader HLSL 代码改动 都有 WX_PERFORMANCE_MODE 来做条件编译,改动详情可参考源代码

微信 URP 定制版本的性能数据对比

    1. 使用 URP SimpleLit Shader 的测试场景,静置如下图: Case1
  • Perfog 统计的数据 (设备 iPhone X) ,定制版本的 GPU利用率从 50%下降到 38.2%,降幅达到 23%,且 Shader半精度的利用率也有所提高
版本FPSGPU 利用率%半精度利用率%全精度利用率%Total CPU 利用率%
官方URP59.85011.9235.2423
定制URP59.938.28.8745.523.1
    1. 使用 URP Lit Shader 的测试场景,静置如下图: Case2
  • Perfog 统计的数据 (设备 iPhone X) ,定制版本的 GPU利用率从 70.8%下降到 51.1%,降幅达到 27.8%,且 Shader半精度的利用率也有所提高
版本FPSGPU 利用率%半精度利用率%全精度利用率%Total CPU 利用率%
官方URP59.870.85.8843.7222.9
定制URP59.951.18.5935.3923.2

注意事项

  • 开发者使用的 Unity 版本 和 URP 版本可能不一样,不能拿微信定制的 URP 直接用的,但是
  • 即使开发者用的 URP 版本和微信定制的 URP版本一致,有需要根据项目实际情况,来决定是否直接使用微信定制的版本
  • 微信定制的 URP 版本目前没有对 Shader 变体做剔除的,因为 .shader 文件非 HLSL部分 不能用WX_PERFORMANCE_MODE宏来控制,因此 Shader 变体这部分开发者可以在定制的过程中剔除掉不需要的功能
    • 例如 fog雾效不会用到,可以手动在 .shader 将相关的 pragma指令删除
  • 使用了定制的 URP 版本后 ,可以切回官方的 URP 包吗 ?
    • 可以,先把本地的 URP包移除掉,然后通过 Package Manager 窗口的 Add package by name,输入com.unity.render-pipelines.universal 即可
  • 微信定制的 URP 12.1.10 版本对应 Unity 2021.3.19,其他 Unity 版本可以直接拿来用吗
    • 如果是 Unity 2021.3.19 ~ 23,URP 版本是很接近的,如果这里给出的参考版本满足开发者需要,可以拿来用
    • 其他 Unity 版本不一样 或者 不满足渲染需要,建议基于当前 Unity版本 的 URP 进行定制,可以借鉴里面定制的方法或思路
  • 上述定制的 URP 版本 是否适用于 App 移动端 平台 ?
    • 不能直接用,但定制的做法或思路可以借鉴
  • 定制版本的 URP 版本和 官方 URP 的渲染结果是否一致 ?
    • 如果使用的功能是定制 URP 支持的,那么渲染结果基本一致的,如果渲染差异比较大,那么应该是使用了定制 URP 裁剪掉的功能

参考

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/DataCDN.html b/Design/DataCDN.html new file mode 100644 index 00000000..c523c7a4 --- /dev/null +++ b/Design/DataCDN.html @@ -0,0 +1,45 @@ + + + + + + 资源部署与缓存 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

资源部署与缓存

在转换完成后,会在导出路径下生成如下目录

bash
.
+├── minigame
+└── webgl
  • webgl目录为游戏对应的webgl版本。
  • minigame目录为转化后的小游戏代码。

其中webgl目录结构如下:

bash
.
+├── 01367b188873c923.webgl.data.unityweb.bin.txt
+├── Assets
+│   ├── 15032.wav
+│   ├── Audio
+│   └── Textures
+├── Build
+│   ├── UnityLoader.js
+│   ├── webgl.data.unityweb
+│   ├── webgl.json
+│   ├── webgl.wasm.code.unityweb
+│   ├── webgl.wasm.framework.unityweb
+│   └── webgl.wasm.symbols.unityweb
+├── StreamingAssets
+│   └── AssetBundles
+├── index.html
+└── texture-config.js

资源部署

导出目录中,webgl目录如下三个文件和目录是可能需要远程部署的资源:

bash
.
+├── 01367b188873c923.webgl.data.unityweb.bin.txt
+├── Assets
+├── StreamingAssets

首资源包

首资源包即01367b188873c923.webgl.data.unityweb.bin.txt,包含Unity builtin + 勾选的导出场景 + Resources资源。 注意:加载方式取决于导出选项中的首包资源加载方式。同时由于小游戏总包体不能超过20MB,实际首包资源加载方式会根据包体决定,更多信息可查看UnityLoader-首包资源加载方式

  • 小游戏分包:因需要统计总包体大小,当导出时wasm代码brotli压缩正常的前提下,如果wasm代码+首包资源小于20MB,可使用"小游戏包内"加载,此时不需要将首包资源部署到服务器
  • CDN:当不使用小游戏分包时,需要部署到服务器。

Assets

如果有用到纹理压缩,导出插件自动生成。将此目录部署到服务器即可

StreamingAssets

AssetBundle和Addressables资源目录。 如果是用的AA,构建时默认打包到StreamingAssets目录下。但如果是用的AB,或者自定义了bundle的生成目录,需要将bundle移动到StreamingAssets目录

资源服务器注意事项

  1. 针对txt文件进行开启Brotli或gzip压缩,首资源包有非常高的压缩率
  2. 小游戏资源下载并发数为10,超过时底层自动排队
  3. 单个请求文件最大不超过100MB,超时默认为60s(理论最大值,实际游戏永远不要让单个文件这么大,考虑到玩家平均下载带宽,建议单文件2~5MB以内)
  4. 网络安全域名、跨域、SSL等问题请参考文档网络通信适配

资源更新说明

请注意!!! bundle的配置文件,比如aa的setting.jsoncatalog.json,以及AssetBundles打包生成的配置文件通常没有带上hash,为了避免新版本发布时由于cdn缓存导致加载到旧版本资源,需要避免这些文件使用缓存。通常有以下两种方式避免。

  1. 每次发新版本更换cdn路径,比如version1/xxxx,version2/xxxx
  2. 不希望被缓存的文件,源站或者cdn加上不允许缓存的HTTP头,如no-cache,请自行查询对应cdn服务商文档进行设置

同时,由于通过HTTP请求的资源会自动缓存,不希望被缓存的文件请添加到缓存忽略目录,具体可阅读后续资源缓存规则文档

除非了解小程序更新机制,请勿删除旧版本资源,否则可能导致旧版本游戏的用户运行报错,具体请移步版本更新

资源缓存

这里主要讲UnityLoader的资源缓存策略。

资源缓存规则

请阅读资源缓存

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/DebugAndException.html b/Design/DebugAndException.html new file mode 100644 index 00000000..fb31fd25 --- /dev/null +++ b/Design/DebugAndException.html @@ -0,0 +1,37 @@ + + + + + + 错误调试与异常排查 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

错误调试与异常排查

本文阐述开发者在遇到转换后的游戏在开发者工具或真机遇到异常时,如何找到对应堆栈并解决问题。

如何排查程序中出现的异常

如何查看日志

小游戏出现异常或错误时,通过以下方式打开 console:

  • 开发者工具:调试器->Console

  • 真机:

    步骤1(打开调试模式):右上角菜单->打开调试->出现vconsole 或者 game.js增加代码"wx.setEnableDebug({enableDebug: true})"

    步骤2(打开vconsole):点击vconsole打开日志面板(启动阶段点三次封面视频下方Unity Logo出现 vconsole)

注意:在WASM代码分包情况下,应该使用jxxx的数字作为函数id

默认情况下,函数堆栈是不可读的函数id,那么可通过以下两种方法之一来获得可读函数名

如何通过错误堆栈查找源代码问题

使用Profiling-funcs

转换面板勾选profiling-funcs, 导出的代码包中将包含可读函数名。 正式上线版本请务必关闭profiling-funcs,或使用代码分包(可自动剔除函数名)。

使用symbols文件可读函数名

以文本方式打开导出目录/webgl/Build/xxx.symbols 文件

通过日志的函数id找到对应的原始函数名,分析调用堆栈。

这里有个小工具可以帮助替换日志(在WASM代码分包情况下,需要自行稍做修改)

影响异常错误的导出选项

推荐配置(转换插件默认设置)

  • Enable Exceptions: Explicitly Thrown Exceptions Only
  • Debug Symbols: Yes
  • Development Build: No

Enable Exceptions

BuildSettings->Player Settings->Publish Settings->Enable Exceptions 选项表示 Unity 引擎捕捉哪种级别的异常

什么是异常级别? 简单来说,就是确定哪些异常由引擎捕捉,未被捕捉的异常将抛给 WASM 虚拟机,最终会导致 VM 结束。

以代码为例

C#
        // 程序捕捉异常
+        try
+        {
+            GameObject go = null;
+            Debug.Log(go.name);
+        }
+        catch (Exception ex)
+        {
+            Debug.Log(ex);
+        }
+
+        // 程序未捕捉异常
+        GameObject go2 = null;
+        Debug.Log(go2.name);

这段代码有两处异常: 1. 程序捕捉的异常, 2.程序未捕捉异常(通常是问题所在)

None

异常捕捉:不捕捉任何异常,引擎或业务代码导致的异常都会抛出到 WASM,并导致程序 Crash。 该选项性能最高,但必须保证游戏不使用任何异常,try catch 也无法捕捉任何异常。从下图看到程序在第 1 个 Exception 产生时已终止,代码是无法 catch 该异常的。

异常信息:取决于虚拟机,在开发者工具有出现详细堆栈函数 ID,在真机环境则无。

Explicitly Thrown Exceptions Only

异常捕捉: 游戏代码的异常将被捕捉,如果非致命异常(不在关键路径上),逻辑代码可以继续。try catch 有效。

异常信息:Debug.Log 等函数等与程序未捕捉异常可输出简要的异常信息,无堆栈信息。

Full Without Stacktrace

异常捕捉: 同"Explicitly Thrown Exceptions Only", 且引擎还会增加额外的底层异常检查,比如”Null References Out of Bounds Array accesses“。

异常信息: Debug.Log 等函数与程序未捕捉异常都只有输出简要的异常信息,无堆栈信息。

Full With Stacktrace

异常捕捉: 同"Full Without Stacktrace"

异常信息: Debug.Log 等函数得到完整的堆栈,程序未捕捉异常有最浅层堆栈函数名。

注意:

None 性能最高,但此模式必须保证游戏代码(包括第三方插件)不使用异常,一旦命中异常即使 catch 也无效,会直接导致程序终止。Explicitly Thrown Exceptions Only 是几种选择中鲁棒性和信息提示较为均衡的,推荐发布使用。Full With Stacktrace 会严重影响性能,切忌在发布版本中使用。

Debug Symbols

BuildSettings->Player Settings->Publish Settings->DebugSymbols

Debug Symbols将产生函数id与函数名之间的映射关系,使用文本方式打开即可。 通常我们从异常log中找到函数id,此时可通过该文件找到C#源代码中的函数名。

Development Build

Development Build会在异常产生时直接附带完整的函数名,与"Full With Stacktrace"类似,且程序未捕捉异常也有详细堆栈。该选项产生的代码体积较大,且对性能有较大影响。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/DevelopmentQAList.html b/Design/DevelopmentQAList.html new file mode 100644 index 00000000..c726f1c6 --- /dev/null +++ b/Design/DevelopmentQAList.html @@ -0,0 +1,43 @@ + + + + + + 技术常见问题QA | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

技术常见问题QA

工具使用

1.微信开发者工具打开时提示“app.json未找到”

2.微信开发者工具打开时提示“找不到game.json或读取错误”

  • 打开导出目录/minigame文件夹而不是导出的根目录

3.如何在真机上预览游戏

  • 请使用微信开发者工具-预览-二维码/自动预览
  • 切勿使用微信开发者工具的"真机调试"功能

4.如何在真机上进行调试和错误日志排查

  • 方式1:game.js增加代码"wx.setEnableDebug({enableDebug: true})"
  • 方式2:真机环境中,右上角"..."-打开调试-重启小游戏-vconsole
  • 上述方法之后,若启动封面无法打开vconsole, 请点三次下方的"unity logo"
  • 错误日志中的业务代码堆栈分析可参考文档 开发错误调试与排查

5.Unity PlayerSettings导出选项中使用"brotli"或"gzip", 使用微信开发者工具无法启动游戏

  • 请勿修改PlayerSettings的压缩选项,保持为不压缩
  • 转换工具对代码包自动进行br压缩
  • 资源包请使用CDN gzip/br, 传输大小与zip压缩后体积相当

6.使用代码分包的情况下,启动游戏出现“首次拉取代码分包”提示

  • 原因是收集函数不够完备,查看分包工具是否有新收集函数,重新生成一轮即可
  • 该提示仅在开发版本提示,代表在“引擎+业务首场景”初始化时遇到了缺失函数

7.微信开发者工具提示"资源下载失败"

  • 请将首资源包放CDN或HTTP服务器,并正确设置导出面板的“游戏资源CDN“

8.微信开发者工具能正常打开游戏,但Android卡在首屏,资源下载失败

  • 请参考文档网络通信适配,尤其关注安全域名、跨域与SSL证书等问题

9.开发者工具提示“插件申请成功,待审核确认”

10.内网开发时,微信开发者工具服务异常

11.开发者工具提示pluginid: wx7a727ff7d940bb3f, permission deny字样错误

Q:

A: 新版导出插件使用小游戏插件来渲染关系链数据,因此需要添加插件。可通过微信开发者工具控制台-添加插件的报错信息添加插件,即可正常使用。同时需要注意实际未使用关系链数据时请删掉game.json中plugins.Layout配置。如果开发者工具控制台没有添加插件的入口请手动在MP端添加插件或者升级至最新版本的开发者工具。

12.小游戏包中的webgl.wasm.symbols.unityweb不会被上传,是做什么用的

13.如何自定义接入构建流程

  • 除在微信小游戏转换工具面板配置导出外,微信SDK工具支持开发者自行实现构建,基于 WXConvertCore.cs 脚本提供的 DoExport() 方法实现导出,参考代码如下:
CSharp
if (WXConvertCore.DoExport() == WXConvertCore.WXExportError.SUCCEED) {
+  Debug.Log("成功");
+  //... 后续操作
+} else {
+  Debug.LogError("失败");
+}

Unity WebGL

1.能否使用System.Net命名空间下的接口

2.小游戏启动出现"Unable to load DLL ...."

  • WebGL模式不允许加载非源码编译的插件,需游戏自行排查
  • 典型地,如System.Net、lua外部模块、某些依赖平台的第三方插件

3.能否使用System.File相关接口做文件存储

  • 如果是资源(比如AssetBundle)需要进行缓存, 适配插件已自动完成,注意bundle命名规则和缓存策略即可,请参考文档资源部署与缓存
  • 如果是玩家存档,可使用C# SDK中的小游戏存储接口。此外,更建议使用服务器或云开发进行定期存储,因为微信用户更容易删除小程序,文件存储将随之被删除。

4.如何接入第三方的js sdk, 能写js脚本和C#进行交互吗?

5.小游戏的中文字体不显示,但Editor没问题

  • WebGL环境下的中文显示需要自定义字体,打包在首资源包或Bundle;请尽量使用2~3MB以内的精简字体以免影响游戏启动速度

6.游戏逻辑是否能使用lua

  • 可以,但具体性能需自己实际评测,请参照Demo示例。
  • lua可使用AssetBundle方式整体打包,require时使用bundle.LoadAsset同步接口获取脚本

7.Touch事件丢失或错误,导致多点触控不正确

  • 请将WXTouchInputOverride.cs附加到EventSystem对象上,已测试EasyTouch、UGUI、FairGUI可正常工作

8.显示黑屏,运行提示大量shader编译错误

  • 默认导出未webgl1, 请确认游戏是否依赖webgl2(opengles3.0)
  • 导出选项勾选webgl2实验能力

9.Unity FMOD音频插件是否支持?

  • 支持,目前微信小游戏已支持fmod转换的小游戏

10.Mac 系统下 Unity 构建 WebGL 项目报Failed running "../il2cppcore/il2cppcore.dll"错误解决办法

  • 报错原因:Unity 2020及以前(如2019)版本构建 WebGL 仍然需要 Python2 ,而Mac OS 12.3版本起已经不再内置 Python2。

  • 一种解决办法:

    (1)前往 python 官网下载对应的 python2.7.dmg 安装包直接进行安装;

    (2)在 Unity 工程目录任意位置创建 .cs 脚本文件,内容如下:

    c#
    #if UNITY_EDITOR
    +using UnityEditor;
    +using UnityEditor.Build;
    +using UnityEditor.Build.Reporting;
    +using UnityEngine;
    +
    +public class PreBuildProcessing : IPreprocessBuildWithReport
    +{
    +    public int callbackOrder => 1;
    +    public void OnPreprocessBuild(BuildReport report)
    +    {
    +        System.Environment.SetEnvironmentVariable("EMSDK_PYTHON", "/Library/Frameworks/Python.framework/Versions/2.7/bin/python");
    +    }
    +}
    +#endif

    其中 Python 路径请自行检查,若由步骤(1)方式安装的一般无需改动,至此问题解决。

11.引擎代码裁剪级别(Managed Striping Level)应该如何设置?

  • 建议勾选并设置为High, 如果发现部分代码被错误裁剪,请参考托管代码剥离

12.使用xlua等方案在WebGL平台报“ArgumentException: Destination array was not long enough”?

平台适配

1.文本输入框点击无法输入,没有弹出输入法

  • 请参考小游戏输入法API进行适配,示例API Demo

2.高性能模式下iOS无法加载,但Android和微信开发者工具没问题

3.Android运行达到满帧较为流畅,iOS性能差

4.小游戏中能插入超链接跳转网页吗?

  • 不行,不提供内嵌webview或跳转的能力

5.小游戏是否支持Unity VideoPlayer

6.小游戏应该使用哪个接口进行限制帧率?

  • Application.targetFrameRate
  • 使用导出插件的“性能面板”(ProfileStats)可以看到帧耗时、限帧与当前FPS
  • 使用Perfdog查看帧率并不总是准确,因为30/15等帧率是微信使用raf分帧处理,Perfdog统计的是raf触发帧率而不是分帧后的帧率。

7.Unity Audio音频是否需要使用小游戏音频适配

  • 转换方案已通过WebAudio支持Unity音频,通常无需替换

8.PlayerPref或用户数据存储失效

  • 使用小程序云开发或自建服务器进行云端存储(推荐,因本地存储的话,由于微信环境下玩家非常容易删除本地小游戏而导致存档丢失)
  • 使用WX C# SDK提供的PlayerPref进行存储,可以替代已有Unity的PlayerPref。但需要注意该部分数据使用小游戏Storage,有10MB存储上限。 由于接口是同步调用(阻塞游戏线程),不建议频率过高的调用。“存储“请参考https://developers.weixin.qq.com/minigame/dev/guide/base-ability/storage.html
  • 使用WX C# SDK的文件API进行自行本地存储,他会与游戏资源缓存共用“文件系统”区域,有200MB存储上限,建议使用异步接口以不影响主线程帧率。“文件系统”请参考https://developers.weixin.qq.com/minigame/dev/guide/base-ability/file-system.html
  • 总体而言,尽量使用云端存储。对于少量数据可以采用后两种方式,缺点是用户删除本地小游戏则记录丢失,同时要注意避免频繁的同步接口调用。

9.微信接口提示“fail require user interaction (only in touchend event)”

  • 个别微信接口(比如订阅消息WX.RequestSubscribeMessage)需要在Touch回调才能被使用,而Unity大部分的UI解决方案都是延迟到下一帧才执行UI事件回调。因此需要开发者手动调用OnTouch监听,在回调内使用这类API。

10. 团结引擎导出的小游戏卡在Loading界面并提示“MONO_WASM: Failed to load config file ./blazor.boot.json”

  • 查看Player Setting中的Scripting Backend选项,将其设置为IL2CPP后重试。

11. 使用 WebGL2 URP管线导出小游戏时提示 shader 编译报错 “Hidden/Universal/CoreBlit: invalid pass index 1 in DrawProcedural”

  • 有部分官方 URP 自带的 shader 存在这个问题,在微信开发者工具上可能渲染会异常,一般真机上渲染是正常的
  • 解决这个报错,可以尝试这两种方法:
    • 第一种方法:升级 URP 版本(有些 URP 版本和 Unity 版本是绑定的,此时可能需要升级 Unity 版本)
    • 第二种方法:可以把工程 Library/PackageCache 目录下的 unity.rendercom.-pipelines.universal@xxx 包拷贝到本地路径,通过 file 的方式引入 unity.rendercom.-pipelines.universal@xxx 包,然后找到 Shaders/Utils/CoreBlit.shader 并修改它,只保留第一个 Pass (注意:此方法需要确保项目中只使用第一个 Pass)

12. PC端输入框无法输入,移动端正常

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/DevtoolsDomain.html b/Design/DevtoolsDomain.html new file mode 100644 index 00000000..ef0aad9a --- /dev/null +++ b/Design/DevtoolsDomain.html @@ -0,0 +1,56 @@ + + + + + + 微信开发者工具域名列表 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

微信开发者工具域名列表

内网使用微信开发者工具时需要放开这些域名的限制方可正常使用

参考 https://developers.weixin.qq.com/community/develop/article/doc/000e426d34c788ac39ad82e1756813

https://mp.weixin.qq.com
+
+https://open.weixin.qq.com
+
+https://long.open.weixin.qq.com
+
+https://lp.open.weixin.qq.com
+
+https://servicewechat.com
+
+https://dldir1.qq.com
+
+https://res.wx.qq.com
+
+https://tcb.cloud.tencent.com
+
+https://scf.tencentcloudapi.com
+
+https://flexdb.tencentcloudapi.com
+
+https://tcb.tencentcloudapi.com
+
+wss://wxagame.weixin.qq.com
+
+https://long.wxagame.weixin.qq.com
+
+https://cube.weixinbridge.com
+
+https://repot.url.cn
+
+https://fuwu.weixin.qq.com
+
+https://res.servicewechat.com

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Evaluation.html b/Design/Evaluation.html new file mode 100644 index 00000000..0e656478 --- /dev/null +++ b/Design/Evaluation.html @@ -0,0 +1,24 @@ + + + + + + 方案评估 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

方案评估

1. 游戏类目

考虑到游戏体积与逻辑复杂度,目前建议中轻度2D/3D游戏进行转换,游戏类目包括:

  • 休闲:消除,答题,模拟经营,塔防,益智等
  • 动作:跑酷,飞行设计,轻度IO
  • 棋牌:棋类,牌类
  • 角色:卡牌,回合,策略

对重度游戏如MMO/FPS等游戏需根据实际情况评估

2. 引擎版本

版本建议:

Unity版本支持从2018到最新的2022版本

建议使用LTS版本,尽量使用2022(更快编译和更小体积、压缩纹理、压缩音频等支持)

3. 能力支持

能力是否支持解决方案
Unity基础模块支持支持动画、物理、AI、UI等基础模块
渲染管线支持支持标准渲染管线、URP
资源加载支持Addressable、AssetBundle网络异步加载
Lua脚本支持支持标准Lua与常见binding(如xlua, tolua等), 不支持Luajit。需根据实际游戏在真机验证性能
PureTS支持iOS系统需14.5以上, 支持JIT
Unity音频支持UnityAudio基本能力支持,支持fmod插件(长音频请使用UnityAudio), 但不支持wwise。
第三方插件部分支持支持大部分插件,C#插件与非平台相关的C原生插件
网络系统需调整HTTP使用UnityWebRequest,TCP使用WX SDK适配或WebSocket通信替代(如开源的UnityWebSocket插件),UDP使用WX SDK适配
渲染接口支持仅支持WebGL1.0(相当于OpenGLES2.0),2.0支持处于Beta测试阶段
多线程不支持删除多线程用法,使用异步等其他替代方式
文件API需调整不支持System.File接口,但可使用微信小游戏WX SDK实现文件存储,大小限制为200MB(最高可开通1GB)。玩家存档请使用服务器或云开发;AssetsBundle缓存适配插件已自动支持

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/FileCache.html b/Design/FileCache.html new file mode 100644 index 00000000..1b068145 --- /dev/null +++ b/Design/FileCache.html @@ -0,0 +1,82 @@ + + + + + + 资源缓存 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

资源缓存

介绍

小游戏主要存在三种类型的资源:

  1. wasm代码,即wasm.code.unityweb文件
  2. 首资源包,即webgl.data.unityweb文件
  3. 业务bundle资源

其中,wasm代码和首资源包框架会强制缓存,开发者无需关心。本篇重点介绍业务资源的缓存规则。

与APP游戏不同,在小游戏中推荐将资源包拆分成为一个个小文件加载。结合启动Loader有以下优势:

  1. 通过细粒度的资源拆分,提高下载成功率。
  2. 文件粒度缓存,降低版本更新时的流量消耗。
  3. 框架自动做缓存控制,开发者无需感知本地是否存在缓存。

大致流程如图:

一、什么情况触发资源缓存

当使用以下API发起网络请求时会检查是否需要缓存,以及是否命中缓存。

  • UnityWebRequest
  • WWW
  • UnityWebRequestAssetBundle
  • Addressables

游戏业务侧无需关心资源是否有缓存,按照本地没有缓存来使用,正常调用API即可,当有缓存时,Loader插件会构造正常响应返回给游戏

二、哪些资源会自动缓存?

  • 配置到预下载列表的文件
  • 用unity网络接口发起请求,且URL包含自动缓存路径标识符的文件
  • 使用微信压缩纹理工具,且开启纹理缓存后,纹理资源

三、缓存规则

相关配置

Assets/WX-WASM-SDK/Editor/MiniGameConfig.asset 中以下配置与缓存相关

// 业务资源相关
+bundlePathIdentifier: 需要缓存的路径,用 `;`分隔 eg: StreamingAssets;bundles;
+excludeFileExtensions: 当路径中包含字符时不需要缓存,用 `;`分隔 eg: .json;.hash
+bundleHashLength: bundle中hash占多少长度
+// 纹理相关
+needCacheTextures: 是否缓存纹理
+texturesPath: 纹理存放路径
+texturesHashLength: 纹理中hash长度
+// 缓存淘汰相关
+defaultReleaseSize: 清理缓存时默认额外清理的大小,单位Bytes,默认值30MB
+maxStorage: 最大缓存容量,单位MB,默认值200MB

其中部分配置可通过转换插件面板快速修改:

  • bundleExcludeExtensions 对应 不自动缓存文件类型 配置
  • bundleHashLength 对应 Bundle名中Hash长度 配置

是否缓存规则

存在业务的bundle资源和使用微信压缩纹理工具后的纹理资源,不同资源的缓存细节略有不同。

是否缓存业务资源

默认URL中包含StreamingAssets的请求会被识别为资源文件被自动缓存,可修改 bundlePathIdentifier 为你期望的值

并非所有文件都适合持久化缓存,因此缓存规则也支持忽略某些文件,默认包含 .json 的文件不会被自动缓存,可修改 bundleExcludeExtensions。等同于修改导出插件面板不自动缓存文件类型配置

对应 js 代码,minigame/unity-namespace.js

ts
// 判断是否需要自动缓存的文件,返回true自动缓存;false不自动缓存
+unityNamespace.isCacheableFile = function (path) {
+  // 判定为下载bundle的路径标识符,此路径下的下载,会自动缓存
+  const cacheableFileIdentifier = ["StreamingAssets"];
+  // 命中路径标识符的情况下,并不是所有文件都有必要缓存,过滤下不需要缓存的文件
+  const excludeFileIdentifier = [".json"];
+  if (
+    cacheableFileIdentifier.some(identifier => path.includes(identifier)
+        && excludeFileIdentifier.every(excludeIdentifier => !path.includes(excludeIdentifier)))
+  ) {
+    return true;
+  }
+  return false;
+};
是否缓存纹理

默认会缓存纹理,修改needCacheTextures可控制是否缓存纹理资源。

通过texturesPath可让Loader识别一条请求是否为纹理,默认为Assets/Textures

资源淘汰规则

如开篇的流程图所示,当需要自动缓存的文件在写入本地之前,若本地已经有此文件的旧缓存,则先清理旧缓存,再执行写入,那么需要一个手段来区分资源版本。

识别业务资源版本

框架不会做额外计算来验证资源版本,通过文件名中带资源hash,可以在资源更新时,识别不同版本的资源。

Addressables为例,打包参数加上BuildAssetBundleOptions.AppendHashToAssetBundleName,会携带32位长度的hash拼接到文件名末尾。

默认hash长度为32,可通过bundleHashLength修改。等同于修改导出插件面板Bundle名中Hash长度

以下几种命名都能识别到版本号8d265a9dfd6cb7669cdb8b726f0afb1e eg1: font_8d265a9dfd6cb7669cdb8b726f0afb1e eg2: font-8d265a9dfd6cb7669cdb8b726f0afb1e eg3: font_8d265a9dfd6cb7669cdb8b726f0afb1e.ttf

识别纹理资源版本

因纹理打包规则不一致,hash长度也不一样,默认hash长度为8,可通过texturesHashLength配置。

缓存清理规则

随着游戏进度的推进,累计资源体积可能会超过允许的最大值。

注意!!!此最大值通过maxStorage修改,未前往mp后台-能力地图-生产提效包-空间提升开通空间提升的游戏,请勿设置超过200MB的值

达到缓存上限后,一些游戏前期的资源已经不需要再被使用。 此时Loader会按照LRU规则,清理出所需大小,并且为了避免频繁触发清理,会默认多清理30MB的空间,可通过defaultReleaseSize修改。

同时,在清理时也支持忽略一些文件,永不被自动清理,只可通过fs接口主动删除。

通过导出的小游戏minigame/untiy-namespace.jsisErasableFilejavascript函数自行控制

js
// 清理缓存时是否可被自动清理;返回true可自动清理;返回false不可自动清理
+unityNamespace.isErasableFile = function (info) {
+  // 用于特定AssetBundle的缓存保持
+  if (unityNamespace.WXAssetBundles.has(info.path)) {
+    return false;
+  }
+  // 达到缓存上限时,不会被自动清理的文件
+  // 例如,font文件不希望自动清理
+  const inErasableIdentifier = ['font_8d265a9dfd6cb7669cdb8b726f0afb1e.ttf'];
+  if (inErasableIdentifier.some(identifier => info.path.includes(identifier))) {
+    return false;
+  }
+  return true;
+};

示例

假设有以下配置

1. DATA_CDN: https://weixin.qq.com/webgl
+2. bundlePathIdentifier: ['StreamingAssets']
+3. bundleHashLength: 32

在写入缓存前需要经过三步

  1. 根据URL生成缓存路径 URL剔除掉DATA_CDN部分后作为缓存路径 例如:

那么:

  • 则缓存路径=${wx.env.USER_DATA_PATH}StreamingAssets/textures_8d265a9dfd6cb7669cdb8b726f0afb1e
  • 资源唯一标识=StreamingAssets/textures
  • 资源版本=8d265a9dfd6cb7669cdb8b726f0afb1e

注意:资源实际部署的CDN前缀必须与转换面板填写的CDN地址一致,否则无法按照前文的缓存规则获得资源的唯一标识。导致缓存失败

  1. 清理掉同名旧文件 通过文件名中的hash区分同名文件的不同版本 继续上面的例子,假如本地已经有StreamingAssets/textures_cdb8b726f0afb1e8d265a9dfd6cb7669 在写入缓存前,插件认为已经本地已经有同名文件StreamingAssets/textures,但hash与本次写入的文件不一致,则需要删除StreamingAssets/textures_cdb8b726f0afb1e8d265a9dfd6cb7669

支持的bundle命名:需以-_分割,当以其他符号分割时,无法正确处理版本信息,故无法正确删除旧版本资源

  • textures_8d265a9dfd6cb7669cdb8b726f0afb1e
  • textures-8d265a9dfd6cb7669cdb8b726f0afb1e

转换插件相关配置

bundleHashLength: bundle中hash的长度
  1. 检查存储空间是否足够,是否需要清理 当已有缓存+待写入缓存超过允许的上限时,按照LRU清理出所需大小

转换插件相关配置

defaultReleaseSize: 清理时,默认额外清理的大小,单位Bytes,1MB = 1024KB = 1024*1024Bytes
+maxStorage: 最大缓存容量,修改此值需要联系研发助手开通权限,否则无效

四、查看缓存日志

查看插件调试日志

判断是否走缓存

  1. 自动缓存 出现以下两种日志,都可认为需要自动缓存
  • [PLUGIN LOG 10:32.52.915] CacheXMLHttpRequest_onload: shadowreceiverdepth_9551162e.bundle, 耗时:222ms,无缓存,执行缓存逻辑
  • [PLUGIN LOG 10:32.53.073] 缓存 shadowreceiverdepth_9551162e.bundle成功;size: 1.78KB,耗时: 79ms
  1. 命中本地缓存: [PLUGIN LOG 20:18.38.275] CacheXMLHttpRequest_onload: scene999_tw_5b9ef7d7.bundle使用缓存, 耗时:37ms

其他缓存日志

  1. 删除 xxx 旧缓存:清理同名文件旧缓存
  2. 需要释放xxMB存储空间:达到缓存上限,需要释放的空间大小
  3. 缓存文件数=xxx, 总文件大小=xxx:当前缓存目录总文件数和总文件大小(单位 bytes)
  4. 删除文件: xx, md5:xx, size:xx, 耗时: xx:清理旧缓存或达到缓存上限时删除文件

对外接口

public string WX.PluginCachePath

获取自动缓存的文件存储路径,返回值:${wx.env.USER_DATA_PATH}/__GAME_FILE_CACHE

  • javascript接口

GameGlobal.manager.PLUGIN_CACHE_PATH

public string WX.GetCachePath(string url)

传入URL或文件相对路径,若本地有文件缓存,返回缓存路径,否则返回空字符串

  • javascript接口

GameGlobal.manager.getCachePath

public void CleanAllFileCache(Action<bool> action)

清理所有自动缓存的文件

  • javascript接口

Promise<boolean> GameGlobal.manager.cleanAllCache()

public void CleanFileCache(int fileSize, Action<ReleaseResult> action)

从自动缓存目录中释放指定大小的文件缓存

  • javascript接口

Promise<ReleaseResult> GameGlobal.manager.cleanCache(fileSize)

cs
/// <summary>
+/// 清理文件缓存的结果
+/// </summary>
+public enum ReleaseResult
+{
+    /// <summary>
+    /// 无需清理,空间足够
+    /// </summary>
+    noNeedRelease = 1,
+
+    /// <summary>
+    /// 超过最大存储容量,不清理
+    /// </summary>
+    exceedMax,
+
+    /// <summary>
+    /// 清理成功
+    /// </summary>
+    releaseSuccess,
+}

public void RemoveFile(string path, Action<bool> action)

从自动缓存目录中删除指定文件

  • javascript接口

Promise<void> GameGlobal.manager.removeFile(path)

五、注意项

  1. 文件名需要带上hash BuildAssetBundleOptions.AppendHashToAssetBundleName,以便清理掉该文件的旧缓存。默认32位长度,可通过导出选项中Bundle名中Hash长度来自定义。比如游戏自己计算了crc,可将Bundle名中Hash长度设置为crc长度。
  2. 配置到不自动缓存文件类型中的文件,不会自动缓存,默认值是json,比如addressable打包后生成StreamingAssets/aa/WebGL/catalog.json,这个文件不会自动缓存。
  3. 缓存目录
  • 开发者工具上可以打开文件系统查看缓存文件 缓存文件在usr目录下
  • 真机安卓缓存目录:data/com.tencent.mm/MicroMsg/wxanewfiles/随机ID(根据最近使用时间判断是哪个目录)
  • windows缓存目录:微信-设置-文件管理-打开文件夹;打开文件管理后进入Applet\${appid}\${appState}\usr\
  1. 当文件没有正常缓存时,着重检查 缓存规则 中 资源下载URLDATA_CDN、和 bundlePathIdentifier,当资源下载URL中不包含DATA_CDN时,不会走缓存逻辑。

  2. 真机安卓缓存目录:data/com.tencent.mm/MicroMsg/wxanewfiles/随机ID(根据最近使用时间判断是哪个目录)

  3. 未开通mp后台-能力地图-生产提效包-空间提升的游戏,修改maxStorage超过200MB会导致出现写缓存失败。

QA

1. PC上配置为不自动缓存的文件,仍然没有走网络下载

PC上使用了Chromium的网络模块,存在HTTP缓存,可通过请求添加时间戳、服务器返回不缓存的头

2. 同一个文件,日志提示执行缓存逻辑,下次运行时仍然从网络下载

可能有两种情况:

  1. 请求同名资源的不同版本 可能预下载列表中配置的资源版本和UnityWebRequest请求的版本不一致,由于缓存清理逻辑:
  • 先下载版本A,若本地有版本B,版本B被清理后写入版本A的缓存
  • 再下载版本B,此时版本A缓存被清理,写入版本B缓存
  • 下次启动游戏再次下载版本A,此时本地有版本B,清理后写入版本A

如何检查:从缓存日志中搜索不带hash的资源名,出现两个版本的下载日志。

  1. 缓存写满之后的自动清理逻辑 当出现以下日志,可认为资源被自动清理,可查阅本篇「缓存清理规则」
  • 需要释放xxMB存储空间
  • 删除文件: xx, md5:xx, size:xx, 耗时: xx

3. 已经有无缓存,执行缓存逻辑的日志,缓存仍不生效,下次访问资源仍从网络下载

资源下载URL中不包含DATA_CDN部分,可能是运行期间修改了CDN,但并没有同步修改资源下载URL。

如何检查:

  • 启动插件版本>=1.2.41,会在开发阶段输出错误日志缓存路径不合法 请检查DATA_CDN配置和请求URL是否匹配,提示出错的资源信息
  • 启动插件版本<=1.2.41,开发者工具通过Network面板查看资源下载URL,确认是否和DATA_CDN不一致;真机可通过抓包工具查看下载URL;

4. 如何切换备用CDN地址

参考Unity Loader - 资源下载

5. 一些配置文件不希望被自动清理,由业务控制何时清理

参考本篇「缓存清理规则」将这些文件添加到inErasableIdentifier中。

注意:业务侧注意在适当时机清理文件,否则文件将会一直在缓存目录中。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/FirstSceneOptimization.html b/Design/FirstSceneOptimization.html new file mode 100644 index 00000000..8c48a82e --- /dev/null +++ b/Design/FirstSceneOptimization.html @@ -0,0 +1,31 @@ + + + + + + 首场景启动优化 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

首场景启动优化

提升Unity WebGL游戏启动速度章节我们提到过:

在timelog中呈现的首场景耗时即为引擎初始化与开发者首帧逻辑,关于该阶段耗时,开发者需要注意的是:

  1. MonoBehaviour脚本的首帧Start/Awake应足够少逻辑,优先将画面呈现
  2. 初始场景不宜过大,通常呈现Splash场景即可
  3. 初始场景中需要后续主场景或配置加载时可采取分帧策略,切勿在Start/Awake阻塞

下面介绍如何通过在小游戏下通过Profile的方式对小游戏首场景耗时进行针对性优化。

小游戏Profile

微信小游戏在安卓平台提供了CPU Profile能力,使用姿势为: 1.采集Profile: 点击右上角菜单 -> 开发调试 -> Start CPU Profile -> Stop CPU Profile; 2.导出Profile文件 当点击Stop CPU Profile之后,会弹出浮窗告知profile文件的存储路径,通过USB链接电脑或者第三方文件管理器即可将Profile文件传输至电脑。

3.Chrome导入Profile文件 打开Chrome浏览器,右键审查元素或者按F12即可打开控制台界面。选中JavaScript Profile tab(如果默认没有,可能在右上角的三个点展开菜单->More tools里面),点击load导入步骤2的profile文件,Profile文件的使用可以参考Google的开发文档: https://developers.google.com/web/tools/chrome-devtools/rendering-tools/js-execution

Unity CallMain

参考文档小游戏启动流程中提到的,当游戏代码包下载编译完成和首包资源下载完成后会运行游戏逻辑,最开始执行的逻辑是CallMain主函数。 在WebGL模式下,CallMain的主要是initWebGLPlayer调用,主要分成两部分调用:

  • Unity引擎初始化:主要分成:InitializeIl2CppFromMain、RuntimeInitialize、PlayerInitEngineNoGraphics和PlayerInitEngineGraphics等函数调用;
  • 首场景初始化:PlayerLoadFirstScene函数调用;

下表为针对Unity Benchmark项目在不同设备上的callmain耗时分析,Benchmark项目链接:https://github.com/Unity-Technologies/Benchmark

下面实验均采用Unity 2018.4.24f1版本,Development模式会对性能有一定影响,下表数据均为Development模式下数据。

initWebGLPlayer主要函数安卓魅族6sOPPO A37m安卓小米10开发者工具
InitializeIl2CppFromMain525ms954ms113ms39.90ms
RuntimeInitialize139ms649ms50.2ms2.33ms
PlayerInitEngineNoGraphics463.8ms1.24s154ms10.46ms
PlayerInitEngineGraphics1.4s2.94s403ms126ms
PlayerLoadFirstScene815ms2.12s213ms70.75ms

目前为止,开发者可以操作的主要是PlayerLoadFirstScene函数的调用,参照Unity的Benchmark项目,要尽可能将PlayerLoadFirstScene的耗时控制在整个CallMain耗时的左右,如果CallMain耗时过大,可以借助上面提到的Profile工具进行优化,下面简单分析流程。

CallMain Profile分析

1.改造小游戏代码 因为安卓采集Profile文件需要手动控制,而CallMain会在码包下载编译完成和首包资源下载完成后就执行,为了录制启动阶段完整的Profile,需要保证Profile的录制开始之后才真正执行游戏开始逻辑,找到项目的game.js文件,改造最后几行即可:

js
// gameManager.startGame();
+
+wx.onTouchStart((result) => {
+  console.log('真正执行开始游戏逻辑');
+  gameManager.startGame();
+})
+
+GameGlobal.manager = gameManager;

通过上面的改造,在进入小游戏后,可以按照这个流程采集Profile:Start CPU Profile -> 点击屏幕触发真正的开始游戏逻辑 -> 看到游戏界面后Stop Profile。

2.导入步骤1的启动过程Profile文件

导入文件后,我们只需要关注CallMain调用的PlayerLoadFirstScene函数,如果PlayerLoadFirstScene耗时占比过高,大多是因为在首场景执行了不必要的操作,比如大量反序列化操作、配置解析操作,按需剔除后再次Profile即可验证效果。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Guide.html b/Design/Guide.html new file mode 100644 index 00000000..c172db43 --- /dev/null +++ b/Design/Guide.html @@ -0,0 +1,24 @@ + + + + + + Unity 游戏接入微信小游戏指南 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Unity 游戏接入微信小游戏指南

​ 下图中介绍了新游戏接入微信小游戏平台的主要转换流程,下文将介绍每一个阶段的工作:

Unity快适配调优指南

  • 【阶段一】兼容性评估:初步确认技术方案是否符合游戏项目
  • 【阶段二】项目转换:可体验的WebGL、小游戏项目
  • 【阶段三】微信平台能力接入:接入更多平台能力
  • 【阶段四】体验调优:达到可上线标准的小游戏体验
  • 【阶段五】发布上线与现网监控:上线后的问题排查与分析

【阶段一】兼容性评估

相关手册:兼容性评估推荐引擎版本更多小游戏成功转换案例技术常见问题QA

​ 新计划接入游戏的开发者应阅读本节相关手册内容,参考已转化的案例游戏并结合自身游戏情况评估转化的可行性。

【阶段二】项目转换

​ 本节内容将指引开发者如何让自己的游戏工程在微信小游戏平台成功运行。

快速开始——转换工具导出微信小游戏

相关下载: 微信 Unity 插件下载

相关手册:快速开始:转换工具导出微信小游戏

​ 阅读 快速开始:转换工具导出微信小游戏 快速熟悉工具的使用并完成一次简单的转化工作!

资源按需加载

相关手册:资源按需加载概述AA(Addressable) 进行资源按需加载AB(AssetBundle)进行资源按需加载Instant Game 实践指南

​ 区别于原生 APP 游戏很少考虑场景内的资源规划问题,开发时通常将资源在游戏启动时全加载到内存中,而小游戏需要做到“即点即玩”,影响游戏的呈现速度因素中如首资源包的下载往往占比较大,因此需要根据场景中的主次内容进行资源上的优化分包处理。有关分包策略可参阅 资源按需加载概述 选择符合当前游戏的方案,具体实施可阅读具体指引文档。

后端/网络通信适配

相关手册:后端服务指引网络通信适配

​ 区别于原生环境,WebGL模式(JavaScript环境)是不支持使用原生套接字(Socket)实现网络通信。对于游戏中使用到网络请求的操作,需要进行相应的适配。将 HTTP 请求使用 UnityWebRequest 类实现,全双工通信改用 WebSocket 协议实现,可参考手册案例完成适配。

资源服务器部署配置

相关手册:资源部署与缓存资源缓存iOS高性能模式

​ 游戏导出小游戏包(/minigame)将使用微信开发者工具打开,而资源目录(/webgl 或 /webgl-min)需要上传至开发者的 CDN 服务器中,并前往 MP 后台配置安全域名白名单,对于进一步提升 iOS 下的游戏运行效率可前往 MP 申请 iOS 高性能模式,请阅读相关手册完成相应的部署。

开发阶段的错误排查

相关手册:开发错误调试与排查

小游戏存在开发者工具、真机(Android/iOS/PC Windows),当游戏出现异常时可通过日志进行错误堆栈分析。

【阶段三】微信平台能力接入

接入微信API

相关手册:WX SDK 平台能力适配屏幕适配输入法适配排行榜与微信关系数据

​ Unity 游戏接入微信小游戏平台将获得微信提供的 API 以及开放能力,开发者根据需要进行按需接入。微信 API 支持的能力包括登录、设备(存储、震动)、开放数据、广告等等。

启动留存数据上报统计

相关手册:启动留存数据上报统计

​ 在小游戏中玩家对启动时长与体验十分敏感(尤其从“广告”等买量场景进入的玩家),因此需要在必要的位置进行相关的数据上报,Unity Loader 插件为游戏提供了一些基础上报数据,但游戏内部关键帧位置仍需要开发者自行上报,可参阅相关手册完成上报配置。

【阶段四】体验调优

​ 截止本阶段,开发者的 Unity 游戏将在微信小游戏平台成功启动运行,但为了能够达到更佳的游戏体验开发者应继续进行对游戏工程的调优工作,本节将介绍目前微信小游戏平台为开发者提供的调优能力完成上线前的最后优化工作。

首场景启动优化——首帧逻辑优化

相关手册:提升Unity WebGL游戏启动速度启动流程与时时序首场景启动优化

​ 根据统计数据反应,小游戏玩家对于游戏的启动时长是较为敏感的,过长的启动时间会导致用户的显著流失,因此如何快速呈现游戏场景是 Unity 原生 APP 游戏接入微信小游戏平台的一个重点优化的工作。首场景启动优化的并不是一个简单的步骤就可以完全优化,在初始 Unity 工程时开发者应主要对游戏代码如首帧逻辑进行修改,具体可参阅首场景启动优化手册。

资源预下载

相关手册:使用预下载功能

​ 在 UnityLoader 加载过程中是存在CPU处理密集而 网络空闲 的情况,因此可以充分利用该时机进行一些必要的资源下载可有助于提升游戏场景等资源的载入速度。

运行性能及调优

相关手册:优化Unity WebGL的运行性能使用 Android CPU Profiler 性能调优使用 Unity Profiler 性能调优优化 Unity WebGL 内存

​ 游戏转化完成后仍需要对各项的性能指标进行量化测试。

压缩纹理资源

相关手册: 压缩纹理优化

​ 压缩纹理工具是微信SDK提供的一种能够根据不同的游戏运行平台而按需加载压缩后纹理资源的能力。它的优点是:

  • 增快游戏运行进度:纹理资源从 bundle 内分离后按渲染需要进行后续加载,有效减少 bundle 体积,增快游戏的运行进度;
  • 减少内存占用,GPU硬解纹理渲染更快: 分离的资源被压缩成多种格式的纹理资源在 CDN 中存储,客户端根据硬件 GPU 支持的格式按需下载渲染,体积更小,渲染速度更快。

​ 纹理压缩对于 提升运行速度减少内存 的优化方面均有不错的表现效果,对于重度游戏而言,均建议进行该优化。

WASM代码分包

相关手册:使用代码分包工具

​ Unity 导出小游戏项目后代码将存储在 wasm 文件中,而游戏启动时需要完整的 wasm 文件才可以运行,于是微信小游戏提供了WASM代码分包能力,将原本的 wasm 文件根据游戏逻辑的主次内容分为 2 个 wasm 文件,一个用于启动加载另一个将被延迟加载,这样就允许先加载较小的首包快速进入主场景。该能力可以有效降低内存的使用,以及减少脚本编译的时间

封面图配置

相关手册:启动封面

​ 由于 Unity WebGL 的启动加载需要一定的时间,微信小游戏支持通过配置封面图/视频等内容作为加载期间的过渡来留住玩家,微信小游戏支持如下自定义配置项:

  • 封面图/视频内容
  • 加载文案及样式
  • 进度条样式
  • 封面自动隐藏时机

【阶段五】发布上线与现网监控

​ 审核发布可参考 MP 文档 小游戏接入指南 自助完成,游戏相关运行数据请前往 微信公众平台

现网错误日志上报与排查

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/InputAdaptation.html b/Design/InputAdaptation.html new file mode 100644 index 00000000..9165489a --- /dev/null +++ b/Design/InputAdaptation.html @@ -0,0 +1,111 @@ + + + + + + 输入法适配 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

输入法适配

支持2022和团结引擎的 Input Field 组件自动适配,低版本或者其他组件暂不支持自动适配

低版本兼容:

在小游戏中Unity游戏唤不起输入法,需要使用WX_SDK中提供的方法来唤起输入法,并做简单的逻辑修改来适配。

详细示例请参考API Demo

以UGUI的Input组件为例,需要给Input 绑定以下脚本:

csharp
using UnityEngine;
+using WeChatWASM;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+
+// 添加 InputField 组件的依赖
+[RequireComponent(typeof(InputField))]
+public class WXInputFieldAdapter : MonoBehaviour, IPointerClickHandler, IPointerExitHandler
+{
+    private InputField _inputField;
+    private bool _isShowKeyboard = false;
+
+    private void Start()
+    {
+        _inputField = GetComponent<InputField>();
+    }
+
+    public void OnPointerClick(PointerEventData eventData)
+    {
+        Debug.Log("OnPointerClick");
+        ShowKeyboard();
+    }
+
+    public void OnPointerExit(PointerEventData eventData)
+    {
+        Debug.Log("OnPointerExit");
+        if (!_inputField.isFocused)
+        {
+            HideKeyboard();
+        }
+    }
+
+    private void OnInput(OnKeyboardInputListenerResult v)
+    {
+        Debug.Log("onInput");
+        Debug.Log(v.value);
+        if (_inputField.isFocused)
+        {
+            _inputField.text = v.value;
+        }
+    }
+
+    private void OnConfirm(OnKeyboardInputListenerResult v)
+    {
+        // 输入法confirm回调
+        Debug.Log("onConfirm");
+        Debug.Log(v.value);
+        HideKeyboard();
+    }
+
+    private void OnComplete(OnKeyboardInputListenerResult v)
+    {
+        // 输入法complete回调
+        Debug.Log("OnComplete");
+        Debug.Log(v.value);
+        HideKeyboard();
+    }
+
+    private void ShowKeyboard()
+    {
+        if (_isShowKeyboard) return;
+        
+        WX.ShowKeyboard(new ShowKeyboardOption()
+        {
+            defaultValue = "xxx",
+            maxLength = 20,
+            confirmType = "go"
+        });
+
+        //绑定回调
+        WX.OnKeyboardConfirm(this.OnConfirm);
+        WX.OnKeyboardComplete(this.OnComplete);
+        WX.OnKeyboardInput(this.OnInput);
+        _isShowKeyboard = true;
+    }
+
+    private void HideKeyboard()
+    {
+        if (!_isShowKeyboard) return;
+        
+        WX.HideKeyboard(new HideKeyboardOption());
+        //删除掉相关事件监听
+        WX.OffKeyboardInput(this.OnInput);
+        WX.OffKeyboardConfirm(this.OnConfirm);
+        WX.OffKeyboardComplete(this.OnComplete);
+        _isShowKeyboard = false;
+    }
+}

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/InstantGameGuide.html b/Design/InstantGameGuide.html new file mode 100644 index 00000000..491053e9 --- /dev/null +++ b/Design/InstantGameGuide.html @@ -0,0 +1,24 @@ + + + + + + 使用 AutoStreaming 进行资源按需加载 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用 AutoStreaming 进行资源按需加载

​ 除常规使用 AA/AB 分包方案外,Unity 官方也提供了 AutoStreaming 转换工具可以实现 Unity 游戏转化至微信小游戏平台的能力。开发者可阅读本文自行选择转换方案。

方案选择建议

​ Instant Game 能够快速有效的将原生 APP 游戏工程在较少的代码修改的情况下完成微信小游戏平台的运行,这得益于 Unity 引擎基于底层实现对游戏资源的异步加载能力,并将这些资源托管至 CCD 服务中。对于开发者而言,若游戏为休闲关卡类等小型游戏,使用 Instant Game 能够减少游戏的转化工时。适用于 Instant Game 转化的游戏一般具备:

  • 需要快速转化上线
  • 原生 APP 游戏工程没有使用 AA/AB 实现资源的管理
  • 中小型游戏,对设备性能如计算、内存等要求并不是特别吃紧的游戏

​ Instant Game 对于极小的休闲类游戏将具备更快更小修改代价将游戏迁移至微信小游戏环境内运行,若追求较好的游戏品质,无论哪一种方案都需要开发者专项的适配。在部署方面 Instant Game 需要使用平台提供的 CDN 服务,不支持开发者自建。

实践指南

​ 请前往 Unity微信小游戏专区 (https://unity.cn/instantgame/docs/WechatMinigame/Demo) 阅读转换指引。

Q&A

1.游戏在微信开发者工具中运行缺失资源?

​ 经过 AutoStreaming 转换后开发者应在微信开发者工具检查控制台中Network面板资源是否加载正常,若存在404时,需要查看资源是否正确上传、读取路径是否正确等。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/IssueAndContact.html b/Design/IssueAndContact.html new file mode 100644 index 00000000..f35563de --- /dev/null +++ b/Design/IssueAndContact.html @@ -0,0 +1,24 @@ + + + + + + 问题反馈与联系我们 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

问题反馈与联系我们

开发者使用转换方案时,如果遇到问题可以随时反馈给我们。目前可通过Git Issue和“小游戏客服助手”微信客服两种方式。

Git Issue

开发者遇到BUG或者希望新增特性优先使用Git Issue,因为这里可以更好进行问题沉淀、讨论与跟踪。

问题复现尽可能详细,包括以下内容:

  • 操作步骤
  • 重现条件
  • 最好有截图/数据报告
  • 最好能提供非业务相关的可复现代码片段

小游戏客服助手

开发者也可以通过客服助手直接与小游戏团队进行技术交流

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/IssueForProduction.html b/Design/IssueForProduction.html new file mode 100644 index 00000000..ac646d23 --- /dev/null +++ b/Design/IssueForProduction.html @@ -0,0 +1,24 @@ + + + + + + 现网错误日志上报与排查 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

现网错误日志上报与排查

当游戏发布到现网时,开发者需要收集玩家遇到的错误、异常等问题并进行排查原因,本文阐述在微信小游戏环境的最佳实践。 开发者可通过三种途径收集到游戏异常数据:

  • 用户反馈日志
  • 小游戏实时日志
  • JS Error错误日志

用户反馈日志

数据入口:MP平台-用户反馈

当玩家游戏中出现问题时,进行功能反馈将会提交“用户反馈日志“,开发者可以在后台下载到对应数据:

该功能需要两个必要条件:

  1. 玩家提交反馈

    • 默认情况下,玩家可通过游戏右上方"..."-反馈与投诉-功能异常打开反馈入口。
    • 除此外,开发者也可通过使用wx.createFeedbackButton主动创建反馈入口。
  2. 开发者埋点打印日志

    • 默认情况下,适配插件将自动埋点游戏启动与特殊异常日志
    • 除此外,开发者看通过C# SDK的LogManagerxxx系列函数进行埋点上报 建议: 开发者埋点上报购买物品、打开广告、进入关卡等关键信息 开发者埋点上报异常捕捉的信息

小游戏实时日志

数据入口:MP平台-开发管理-实时日志

实时日志为帮助小程序开发者快捷地排查小程序漏洞、定位问题.

相对于用户反馈日志,小游戏实时日志**不需要用户反馈行为**。

但需要开发者上报游戏关键节点信息与异常日志。

JS Error错误日志

数据入口:MP平台-开发管理-错误日志

微信小游戏框架会在顶层监控到任何未捕捉的JS异常

使用Unity WebGL转换方案的游戏通常会有这几种错误会产生:

  • 导出选项中禁用异常,当触发异常时将走到js abort相关逻辑,此处将产生异常。
  • 适配插件自身脚本错误
  • 其他JS层未捕获异常

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/LaunchOpera.html b/Design/LaunchOpera.html new file mode 100644 index 00000000..2a6cee0c --- /dev/null +++ b/Design/LaunchOpera.html @@ -0,0 +1,124 @@ + + + + + + 启动剧情(Beta) | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

启动剧情(Beta)

Unity微信小游戏首次启动会花费较长的加载时间,这段等待期间游戏与玩家之间没有更多的交互,这是新用户的留存率影响的重要因素,微信小游戏希望能够提供一些更早的交互行为来提升这段等待空窗期的用户访问体验,为游戏的主逻辑争取更多的下载、加载时间。由此推出「启动剧情」能力,对于希望进一步提升游戏启动留存的开发者可以基于该能力精心设计用于“迎新”的剧情内容,进而提升玩家的代入感与游戏的顺畅体验。

剧情效果

演示视频及演示工程源码

演示工程源码

优秀作品

首次访问将直接进入剧情模式(不会显示Unity游戏通用Loading界面),二次访问通常删除本地微信小游戏包再次访问游戏可体验剧情内容(部分游戏使用异步模式,若已经注册游戏角色可能会改变剧情内容,需使用新微信账号访问体验)。

魔魔打勇士飞翔之光镜花异闻录

欢迎更多游戏接入成为优秀案例。

能力特性

  • 比WASM(C#)更早的运行时机
  • 独立线程
  • 支持区分新老用户不同的播放内容
  • 以视频、插图等形式展现

推荐内容

  • 前置新人、赛季CG动画短片
  • 游戏世界观、故事背景的介绍
  • 游戏厂家启动Logo、防沉迷等信息披露

接入方式

由于启动剧情为Unity启动加载耗时过久而推出的能力,因此主要配置由 JavaScript 脚本实现(早于WASM初始化)。

步骤一:设计剧情

剧本设计请阅读 启动剧情剧本自助设计工具及文档 完成设计与调试;

由工具构建(npm run build)生成剧本产物:资源目录 launchOperaPlay

步骤二:配置启动剧情

  1. 使用代码编辑工具打开Unity工程中 Assets/WX-WASM-SDK-V2/Runtime/wechat-default 目录;
  2. 步骤一launchOperaPlay 资源放到 wechat-default 目录中;
  3. 打开 wechat-default/game.js 文件,该文件是 JavaScript 运行的入口文件,在文件底部增加启动剧情初始化配置。
js
// game.js
+
+...   // 原有的代码
+
+// 底部增加启动剧情配置
+// launchOperaInit 是用于初始化剧情的回调事件
+// 配置工作需要在该回调中使用「同步」方式完成,请勿使用异步函数
+GameGlobal.events.on("launchOperaInit", (operaHandler) => {
+
+  // 如需读取本地缓存请使用 getStorageSync 读取,请勿使用异步方式
+  // 如需异步请查阅「基于异步干预剧情发展」
+  let play = true;
+  try {
+    var value = wx.getStorageSync('launchOperaLocalDataXXX'); // 自行管理的本地缓存 Key-Value
+    if (value) {    // 本地有特定缓存标识意味已经不是首次访问可以不播放
+      play = false;
+    }
+  } catch (e) { }
+
+  // 合理位置标记为非新用户,也可以在 C# 侧完成标记
+  wx.setStorageSync('launchOperaLocalDataXXX', { anydata: 0 });
+
+  // 开始配置启动剧情
+  operaHandler.config = { // 配置本地剧本路径,若 playPath 文件不存在或读取失败则自动放弃启动剧情
+    playPath: play ? '/launchOperaPlay/operaPlay.obj' : null,
+  }
+
+  // 注册一些其他的启动剧情事件回调
+  operaHandler.onEnd((logger) => {
+    console.log('剧情播放结束');
+  })
+
+  operaHandler.onErr((err) => {
+    console.log('发生异常');
+    operaHandler.end();       // 发生异常时强制结束,避免用户无法退出剧情插件模式
+  })
+
+  // 弱网处理
+  operaHandler.onWeakNetwork((info) => {
+    // code...
+  })
+
+});
  1. 导出面板进行导出微信小游戏即可。

基于异步干预剧情发展

初始化期间可以同步读取本地资源简单判断是否需要播放剧情,但对于有网络存档的游戏而言,显然不是可靠的判断新用户的方案(用户新设备或本地缓存丢失时也将判定为新用户),这将涉及到异步方式来干预启动剧情插件的工作。异步由于存在不确定的结果返回时间,游戏的启动自然不能始终等待这段空隙,因此在异步结果返回前,我们应让启动剧情插件正常启动,并在后续合理的时机完成故事线的切换。下图给出一种推荐的做法:

我们可以看到,默认的剧情将固定播放一段大约3~5秒钟的启动动画(可以是游戏厂家Logo、防沉迷提醒等),在3~5秒期间 JavaScript 脚本尝试用一些途径来确定后续的剧情发展(可以通过网络交互、本地读取等),当确认后,启动剧情插件允许配置相关变量进而干预剧情发展。 值得注意的是,异步的获取时间明显是不可控的,因此是有可能在5秒的启动动画结束后,仍未得到期望的结果,因此推荐的设计是默认情况下仅播放5秒的启动动画,后续剧情不播放,当5秒内明确了后续播与不播放的选择时,按结果配置,若仍未得到结果,可以按照老用户立即结束剧情即可。具体如何抉择,开发者可以自行设计。

异步干预剧情需要使用到 全局变量 能力,Beta期间请联系研发助手设计剧情期间咨询异步干预能力。

自定义上报分析

启动剧情是一个持续较长时间的业务内容,这段时间中任何时刻均会有用户离开,因此上报剧情期间用户不同阶段的行为对于分析剧情内容与留存率是非常重要的。启动剧情的“剧本”由开发者定义,因此开发者更清楚一个剧情的不同阶段的时间点,所以需要开发者自行对不同阶段剧情进行上报打点。开发者配置上报后,MP管理后台提供了漏斗图的数据可视化看板,将方便开发者进行数据分析。 有关自定义上报详细内容请参考 启动场景上报分析

外显进度条接入

启动剧情能力工作期间,仍然提供了加载进度外显能力,这有助于在剧情播放期间通过截图方式反馈一些加载进度信息,默认情况下位于小游戏底部区域,如图所示:

启动剧情外显进度条默认为用户开启,并且进度条前70%固定为Unity小游戏封面启动进度,开发者可以自行补充后30%进度的显示,若开发者未定义后30%显示进度则启动剧情插件将在首资源包与WASM初始化完成后以平滑动画完成100%进度显示。

关闭/样式调整

如需关闭/样式调整外显进度条,如下配置:

js
GameGlobal.event.on("launchOperaInit", (operaHandler) => {
+
+  // other codes...
+
+  // 配置外显进度条
+  operaHandler.config = {
+    progressStyle: {   // 外显进度条配置,所有配置项均可缺省,以下为默认值
+      position: 1,                  // 0 顶部 1 底部
+      hidden: false,                // 是否隐藏
+      color: '#FFFFFF',             // 进度条颜色
+      backgroundColor: '#000000',   // 进度条背景颜色
+      height: 3,                    // 进度条高度
+    },
+    useCustomProgress: true,       // 声明控制后30%显示,默认不控制将以动画自动补间
+  }
+
+});

如开启 useCustomProgress 则可在游戏侧完成控制

c#
launchOpera.percentage = 0.6;     // 开发者输入 .0~1.0 浮点数,对应控制剩余 30%

弱网处理

启动剧情通常以视频内容呈现为主,网络流畅度对用户体验是存在直接关系,除了开发者需要确保使用可靠的CDN服务托管视频资源确保足够的输出带宽,用户的实际网络也是影响的重要因素。微信小游戏启动剧情对可能影响用户体验的弱网情况做了相应的回调事件,也对网络情况做了三个级别的分级,请开发者对弱网的反馈同样做出合理的处理提升用户体验。

弱网级别:

  • 0级:视频、音频数据流畅(不会产生onWeakNetwork回调)
  • 1级:存在稍微卡顿但可及时恢复播放。可适当给出Loading动画提醒网络加载,或使用全局变量控制剧情显示退出/跳过按钮由用户主动放弃剧情。
  • 2级:严重卡顿,长时间等待视频数据缓冲。可主动提前结束启动剧情,进入原本的Unity loading模式。

请参阅 .onWeakNetwork API描述。

API执行环境说明

启动剧情的运行环境主要以 JavaScript 为主,当然我们也提供了部分 C# 侧需要用到的访问接口。JavaScript 侧指的是导出目录中 minigame 文件夹中的脚本,这是微信开发者工具打开的脚本目录,minigame/game.js 是整个游戏客户端启动的入口,我们通常也是从该入口进行能力迭代。不过值得注意的是,minigame 目录是导出产物,在重新导出游戏时将会被覆盖,所以正确的修改目录应该位于 Assets/WX-WASM-SDK-V2/Runtime/wechat-default 目录中,这里是导出 minigame 的模板文件,并且能够跟随项目Git等代码版本托管迭代。

C# 侧指的是游戏在 Unity 环境中的函数调用,区别于 JavaScript 他的时机将更晚,因为 C# 侧需要等待 WASM 准备充分(首场景加载完成)后才能够进行一系列的函数调用,因此配置性的操作是不能此完成(请在 JavaScript 完成),当剧情启动并给到充分的 WASM 启动后,C# 将得到一些信息反馈,如:何时结束剧情、外显进度条的进度设置等。

API(JavaScript侧)

在 JavaScript 中除了 launchOperaInit 回调函数参数中可获得句柄外, 全局变量 GameGlobal.launchOpera 可以让开发者在任意位置访问到控制句柄;

.running

只读属性,获得当前剧情插件运行状态,true 代表正在播放剧情,false 为未运行或已播放结束资源已完成析构。

js
console.log(GameGlobal.launchOpera.running);    // true or false

.config

在初始化期间对启动剧情组件进行相关配置。

js
GameGlobal.launchOpera.config = {
+  playPath: '',   // 可选,剧本文件路径,填写该项则意味开启启动剧情
+  progressStyle: {   // 外显进度条配置,所有配置项均可缺省,以下为默认值
+    position: 1,                  // 0 顶部 1 底部
+    hidden: false,                // 是否隐藏
+    color: '#FFFFFF',             // 进度条颜色
+    backgroundColor: '#000000',   // 进度条背景颜色
+    height: 3,                    // 进度条高度
+  },
+  useCustomProgress: false,       // 是否接入自定义外显进度条
+}

.end()

提前结束启动剧情。

.onEnd(callback: Function)

注册当剧情结束时的回调事件。

当产生该回调时意味着启动剧情组件资源已经完全析构,同时自动释放注册的事件(如 .onErr 、.onEnd),无需开发手动释放。

.offEnd(callback: Function)

注销当剧情结束时配置的回调事件。

.onErr(callback: Function)

注册当发生异常时的回调事件。

引发异常的可能是:剧本文件读取失败、剧本与启动剧情插件版本不兼容、插件环境异常、CDN视频资源播放失败等。

为避免发生异常时用户无法退出启动剧情插件,推荐开发者在 onErr 强制结束启动剧情。

js
launchOpera.onErr((err) => {
+  launchOpera.end();    // 强制结束
+});

.offErr(callback: Function)

注销当发生异常时的回调事件。

.onWeakNetwork(callback: Function)

当发生1-2级弱网情况时发生的回调事件。

一种推荐的配置:

js
launchOpera.onWeakNetwork((info) => {
+  /**
+   * info 结构:
+   *  interface info {
+   *    level: number;  // 弱网级别
+   *    url: string;  // 产生本次回调的远程资源url
+   *  }
+  */
+  if (info.level == 1) {
+    wx.showToast({
+      title: '网络较弱正在缓冲...',
+      icon: 'none',
+    });
+    // 使用 GlobalVar 显示跳过/退出按钮
+    // code...
+  } else { // 不是 level 1 则为 level 2
+    wx.showToast({
+      title: '网络较差,已为您跳过剧情',
+      icon: 'none',
+    });
+    launchOpera.end();    // 强制结束
+  }
+});

.offWeakNetwork(callback: Function)

注销当发生弱网情况时的回调事件。

.setGlobalVar(globalName: string, value: string)

设置启动剧情全局变量值。

.getGlobalVar(globalName: string): string | null

读取启动剧情全局变量值。

.onGlobalVarChange(globalName: string, callback: Function)

当启动剧情全局变量变化时回调。

.offGlobalVarChange(globalName: string, callback: Function)

注销启动剧情全局变量变化时回调。

API(C#侧)

获得交互句柄

c#
var launchOperaHandler = WX.GetLaunchOperaHandler();

void SetPercentage(double value)

当开启自定义外显进度条时(useCustomProgress)可控制进度条进度,value 接受 .0 ~ 1.0 区间浮点数,对应外显进度条的 70% ~ 100% 进度。

bool GetRunning()

获得当前剧情插件运行状态,true 代表正在播放剧情,false 为未运行或已播放结束资源析构。

void End()

提前结束启动剧情。

void onEnd(Action<bool> callback)

注册当剧情结束时的回调事件。

由于 C# 代码启动较晚,如果在开发者注册时剧情已经结束,则在注册该方法时会立即产生回调,注册的回调只会产生1次。

c#
// On LaunchOpera End
+WX.GetLaunchOperaHandler().onEnd((status) =>
+{
+    WX.ShowToast(new ShowToastOption()
+    {
+        title = "C#(WASM) received the ending callback event!",
+        icon = "none",
+    });
+});

void offEnd(Action<bool> callback)

注销当剧情结束时配置的回调事件。

void SetGlobalVar(string key, string value)

设置启动剧情全局变量值。

string GetGlobalVar(string key)

读取启动剧情全局变量值。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/LaunchOperaDocument.html b/Design/LaunchOperaDocument.html new file mode 100644 index 00000000..a763a7b9 --- /dev/null +++ b/Design/LaunchOperaDocument.html @@ -0,0 +1,291 @@ + + + + + + 启动剧情剧本自助设计工具及文档 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

启动剧情剧本自助设计工具及文档

1.文档说明

启动剧情能力上线初期微信小游戏团队希望更多开发者能够一定程度上自助接入该能力设计剧本,来减少人工协助带来的额外时间消耗,为此提供本指南及工具,游戏开发者通常可通过阅读指南与使用本工具自行完成剧本的设计并上线能力。

2.准备工作

3.快速入门

如果你还没接触 Cli 开发模式,请跟随本教程直至你能在 微信开发者工具 中随意的预览你创作的剧情设计。

Step1 安装启动剧情Cli工具

确保正确安装Node.js与npm包管理器时,只需在你的PC命令行中输入:

sh
npm install launch-opera-cli -g

有时可能需要以管理员身份运行该命令。

Step2 创建剧情工程

在合适的目录下创建你的剧情编辑工程,PC命令行中输入:

sh
lacop create

按照提示创建,如名为 lac-opera-test 的剧情工程,等待片刻创建成功后请进入该目录。

Step3 启动开发模式

创建成功后进入 lac-opera-test (本案例名)目录中执行:

sh
lacop watch

等待片刻提示 Starting compilation in watch mode... 代表启动成功,此时将自动生成 /minigame 文件夹。 注意在调试期间请勿关闭该命令行,应使其始终保持活跃,直到结束剧本设计

Step4 预览默认剧情

使用 微信开发者工具 打开 /minigame 目录,AppID 请切换成当前登录用户有开发权限的小游戏AppID,如果AppID是首次打开后会要求添加用于调试的小游戏插件,按照提示申请权限,若一切正常,你将在工具完全载入资源后看到默认的启动剧情内容。

Step5 对剧本修改

可能与平时开发小程序/小游戏直接在 微信开发者工具 修改剧本不同的是,你无需修改 /minigame 目录中的任何资源,因为这是一个动态构建的产物,他会随着 /src 目录中的资源变化被不断覆盖。所以你真正需要修改的是 /src 中的代码资源。

接下来请你使用 JavaScript 代码编辑器打开当前工程目录(如 VSCode 打开),找到 /src/launchOperaPlay/index.ts 脚本。

请修改脚本中大约第 51 行的 skipButton 的 setParams 参数为:

js
skipButton.setParams({
+  // right: 30,   // 修改前
+  left: 30,   // 修改后
+  bottom: 60,
+  width: 173 / 1.5,
+  height: 64 / 1.5,
+  url: 'launchOperaPlay/skip.png',
+  visible: true,
+});

此时保存这个文件,如果你的 Step3 中启动的开发模式还在工作,那么 /minigame 目录资源也将被实时更新,此时 微信开发者工具 通常也将重新加载游戏内容,你会看到被你刚刚修改的按钮贴图位置从右下角变成左下角。

以此类推,你可以快速修改你看到的很多属性内容,比如位置信息、URL地址从而改变剧情的内容。

Step6 导出剧本

当你对剧情设计完成,需要导出剧本给正式的游戏工程使用时,请回到 Step3 中你开启的命令行窗口,Windows系统下使用 Ctrl + C MacOS 系统下使用 control + C 结束开发模式。

再次执行:

sh
lacop build

等待程序执行结束后,你将在根目录看到 /release 目录,此时你可以将 release 目录内资源放到你的正式游戏工程导出的 minigame 目录下使用。

有关图片资源路径问题请阅读 常见Q&A 中说明。

至此你已经完成了一次很小变动的剧本导出工作。

Step7 尝试更多的模板

启动剧情能够设计很复杂的交互剧情内容,但是这对于初次使用的开发者还需要阅读本文更多的内容,后续请查阅 进阶指南。如果你想快速应用场景,类似 Step5 中这样仅修改属性值就可以替换成自己的游戏素材还是十分便捷。我们提供了多种模板可供选择,只需要在命令行中输入 lacop template 可以快速切换提供的多种模板效果拿来使用。

实际上你可以直接执行 lacop 而无需带后面的参数进行能力的自主选择

4.进阶指南

如果模板还不能满足你的需要,请仔细阅读本节,你将学会设计复杂的剧情内容。

4.1 了解构建工具

本构建工具已经为开发者配置好了相关类型声明,如果你使用例如 VScode 等具备 JavaScript/TypeScript 解析的 IDE 工具将可以享受到函数名联想及参数注释能力。

在使用前请了解本工具的一些行为约束:

  • src 目录中资源将根据层级结构覆盖构建至 minigame 目录中,因此你可以将图片资源放置在本目录中以供引用,其中 .ts 结尾的脚本不会覆盖;
  • src/launchOperaPlay 是固定的启动剧情资源目录,请勿修改名称;
  • src/launchOperaPlay/index.ts 是固定的剧情撰写文件,请勿修改名称;
  • 视频、音频资源均需要存放至 CDN 中,贴图资源只能放置 src 目录中;
  • operaData 是整个剧情的编辑句柄,剧情的设计将由操作它开始。

4.2 基本概念

在启动剧情中由两个剧本元素组成,分别是 关键动作帧(Frame)故事线(StoryLine),关键动作帧更像是一个“函数”,核心思想在于执行到该帧时会引发某种动作,而故事线则是将多个独立的关键动作帧串联有序执行。

4.2.1 关键动作帧

有关关键动作帧的种类,请查阅 API速查 。每个关键动作帧均有两个必要的组成部分:属性、事件。

4.2.1.1 属性

属性是从关键动作帧激活的那一刻起被赋予其特定的值,属性决定了该帧的真实视图表现。例如:

js
// 创建了一个 Image,并赋予了他一些初始化的属性
+const skipButton = operaData.createFrame(FrameType.createImage, {
+  url: `launchOpera/skip_button.png`,
+  right: 25,
+  bottom: 25,
+  width: 100,
+  height: 100,
+});
+
+// 也可以创建后再修改其属性,与上面的写法实际效果完全一样
+const skipButton = operaData.createFrame(FrameType.createImage);
+
+skipButton.setParams({
+  url: `launchOpera/skip_button.png`,
+  right: 25,
+  bottom: 25,
+  width: 100,
+  height: 100,
+});
+
+// 注意设置属性是一个最终态的表现,也就意味着如下设置只有最后一个是生效的
+skipButton.setParams({
+  height: 100,  // 会因下面设置会覆盖,因此该设置无效
+});
+skipButton.setParams({
+  height: 101,  // 会因下面设置会覆盖,因此该设置无效
+});
+skipButton.setParams({
+  height: 102, // 因最后赋值则有效,skipButton 的 height 初始值则为 102
+});
4.2.1.2 事件

事件是对于不同关键动作帧存在不同的事件从而可以引发新的故事线的能力。比如 图片 可以存在被点击(onClick)的事件,视频组件存在开始播放(onPlay)、播放到第n秒时(onPlayTimeAt)、播放结束时(onEnded)等事件,当发生某种事件自然也就可以触发新的故事线内容。

其中,播放到第n秒时(onPlayTimeAt),n 是一个可变系数,因此事件也是支持配置参数的。

例子:

js
const video1 = operaData.createFrame(FrameType.createVideo, { ... });
+// 设置多个不同的事件
+// ①
+video1.setEvents({
+  event: 'onPlayTimeAt',
+  params: {
+    sec: 9,
+  },
+  bind: nextStoryLine,
+});
+// ②
+video1.setEvents({
+  event: 'onPlayTimeAt',
+  params: {
+    sec: 2,
+  },
+  keep: true,
+  bind: [ skipButton ],
+});
+// ③
+skipButton.setEvents({
+  event: 'onClick',
+  bind: [ operaData.EndFrame ]
+});

上面的例子展示了实际应用的多种可能,首先是不同于 属性 的后设置的值将覆盖前设置特点,同名事件是支持创建多个并同时生效(对照① ②中均是 pnPlayTimeAt 事件,但都是独立生效)。② 中使用了一个 keep 字段告诉剧情引擎该事件是反复有效,意味着实际运行时多次达到该事件条件都会引发该事件,而 ① ③ 没有设置 keep 发生一次事件后再达成条件也不会再次引发该事件。

再次观察 ① ② 的 bind,可以发现发生事件后执行的新的故事线其实可以存在多种表达方式,① 中是上下文中开发者自行创建的名为 nextStoryLine 故事线,有关故事线创建请阅读 故事线 小节,而 ② 中是放了一个由 关键动作帧 组成的数组,这其实是一种匿名故事线。

最后 ③ 中的 operaData.EndFrame 实际上最特殊的关键动作帧,当执行到该帧后,启动剧情将立即结束。

4.2.2 故事线

故事线是将一个或多个关键动作帧有序打包的容器,比较特殊的是,启动剧情需要存在一个主故事线作为启动入口。

4.2.2.1 创建及添加关键动作帧

创建故事线以及添加关键动作帧很简单,使用 operaData 句柄执行:

js
// 创建
+const storyLine = operaData.createStoryLine();
+
+// 创建一系列的动作帧...
+
+// 如需添加动作帧
+storyLine.add(var_GC_GUIDE_STEP, startImg, video1, ... );
4.2.2.2 主故事线

主故事线是启动剧情启动后最先执行的内容,当你第一次创建故事线时,那条线也就是主故事线了。

主故事线有一些很常见的用途,比如挂载一些全局变量放到主故事线上就很合理,这样你可以在任何时候对全局变量进行使用,对于全局变量的详细介绍请阅读 全局变量 小节。

5.API速查

了解基本概念后,你也就知道驱动整个剧情发展无非3点。

  • 合适的时机执行需要的关键动作帧;
  • 用故事线串联一系列动作帧让他们有序执行;
  • 关键动作帧可以达成某种事件从而产生新的一条故事线。

故事线的理解比较简单,重点是了解微信小游戏为开发者们提供了哪些关键动作帧,你可以略读 FrameType速查表 大概知道有哪些能力,并可以具体查看每一个 FrameType 的使用说明,来完成剧情的自主设计。

FrameType速查表

点击名称可快速查阅说明

FrameType释义
createVideo创建视频组件
pauseVide将某个视频组件进行暂停
playVideo将某个视频组件进行继续播放
createAudio创建音频组件
pauseAudio将某个音频组件进行暂停
playAudio将某个音频组件进行继续播放
createImage创建贴图
createRect创建矩形区域(可透明、填充纯色、用于区域点击识别)
setParam设置某个关键动作帧的属性
setParamSizeAndPosition同时设置组件的Size、Position属性
setTimeout创建延迟执行
createAnimationFunction创建动画函数
var创建全局变量
if条件判断
report创建上报节点

类型约定

类型主要包括以下几种:

类型名说明
String字符串
Boolean布尔值
Number数值
None可缺省值
Percent百分比字符串,如 30%
Frame关键动作帧句柄,如 Frame.var 只接受 FrameType 为 var 的句柄

空间描述约定

在描述组件的空间位置时,提供了几种简单的描述几乎可以满足大部分的使用需要。

空间描述主要涉及:left、right、top、bottom、width、height 5个属性,这5个属性均支持缺省(None),实际上描述一个组件在屏幕中的位置有时不需要将5个属性完全设置,比如当你规定了 left=0、right=0 时,也就意味着 width=屏幕宽度(width=100%),同理当你 left=0、width=100%,自然right也就=0。

在处理相对位置的时候有时 Number 与 Percent 可能都不能满足你的需要,比如:left=50% 代表屏幕中间,但是你希望屏幕中间再靠左10像素,就无法直接使用 Percent 实现,因为不同用户的设备宽度是不相同的,此时用到 calc 表达式方式,比如刚刚的案例中你可以这样描述: left=calc(50%-10) 就可以了。

视频相关

FrameType.createVideo

创建视频组件。

属性
属性名类型介绍
topNumber/Percent顶端。可参阅空间描述约定
bottomNumber/Percent底端
leftNumber/Percent左端
rightNumber/Percent右端
visibleBoolean可视
widthNumber/Percent宽度
heightNumber/Percent高度
urlString/Frame.var视频资源CDN地址
autoPlayBoolean是否自动播放
playingBoolean是否播放中
objectFitString/Frame.var视频的缩放模式,可选值:fill(填充拉伸)、contain(包含,可能有黑边)、cover(覆盖,可能有部分内容溢出屏幕)
seekNumber/String/Frame.var视频跳转到特定秒数,如果 < 0 则不跳转
loopBoolean是否循环播放
事件
事件名参数介绍
onPlayTimeAtsec:Number当播放到第sec秒数时(sec单位:秒)
onEnded-视频播放结束时
onPlay-视频开始播放时
案例
js
const video = operaData.createFrame(FrameType.createVideo);
+
+video.setParams({
+  // 全屏视频
+  left: 0,
+  right: 0,
+  top: 0,
+  bottom: 0,
+  // 视频完整呈现,可能存在黑边
+  objectFit: 'contain',
+  // 视频CDN
+  url: 'http://abc.com/xx.mp4',
+  autoPlay: true,
+});
+
+// 播放 1.5s 时触发新的关键动作帧
+video.setEvent({
+  event: 'onPlayTimeAt',
+  param: {
+    sec: 1.5,
+  },
+  bind: [ xxxx ] // 新的关键动作帧/故事线
+});
+
+// 可以创建多个事件,互相独立
+video.setEvent({
+  event: 'onPlayTimeAt',
+  ...
+});
seek 的使用案例

seek 需要配合 Frame.SetParam 使用,意味其他事件触发 Frame.SetParam 后为 video 关键动作帧赋值 seek 则产生视频跳转,如需了解 SetParam 请移步特定章节阅读,此处给出 seek 案例:

js
const video = ... // 创建video
+
+// 创建一个 setParam ,对 video 的 seek 属性设置为 10
+// 意味着当触发 seek0 时,video 组件视频将从10秒的位置开始播放
+const seek0 = operaData.createFrame(FrameType.setParam, {
+  frame: video,
+  param: 'seek',
+  value: '10'
+});
+
+... // 在特定条件下触发 seek0

FrameType.pauseVideo

暂停视频。

属性
属性名类型介绍
videoFrame.createVideo需要暂停的视频的关键动作帧句柄
案例
js
const video = ... // 创建video
+
+const playVideo0 = operaData.createFrame(FrameType.playVideo, {
+  video: video,
+});
+
+... // 在特定条件下触发 playVideo0

FrameType.playVideo

(继续)播放视频。

属性
属性名类型介绍
videoFrame.createVideo需要(继续)播放的视频的关键动作帧句柄
案例

FrameType.pauseVideo 使用。

音频相关

FrameType.createAudio

创建音频组件。

属性
属性名类型介绍
urlString/Frame.var音频资源CDN地址
autoPlayBoolean是否自动播放
playingBoolean是否播放中
seekNumber/String/Frame.var视频跳转到特定秒数,如果 < 0 则不跳转
loopBoolean是否循环播放
volumeNumber音量,0~1之间的数值,默认为1
事件
事件名参数介绍
onPlayTimeAtsec:Number当播放到第sec秒数时(sec单位:秒)
onEnded-音频播放结束时
onPlay-音频开始播放时
案例
js
const audio = operaData.createFrame(FrameType.createAudio);
+
+audio.setParams({
+  // 视频CDN
+  url: 'http://abc.com/xx.mp3',
+  autoPlay: true,
+});
+
+// 播放 1.5s 时触发新的关键动作帧
+audio.setEvent({
+  event: 'onPlayTimeAt',
+  param: {
+    sec: 1.5,
+  },
+  bind: [ xxxx ] // 新的关键动作帧/故事线
+});
+
+// 可以创建多个事件,互相独立
+audio.setEvent({
+  event: 'onPlayTimeAt',
+  ...
+})

FrameType.pauseAudio

暂停音频。

属性
属性名类型介绍
audioFrame.createAudio需要暂停的音频的关键动作帧句柄
案例

FrameType.pauseVideo 使用。

FrameType.playAudio

(继续)播放音频。

属性
属性名类型介绍
audioFrame.createAudio需要(继续)播放的音频的关键动作帧句柄
案例

FrameType.pauseVideo 使用。

贴图相关

FrameType.createImage

创建贴图组件。

贴图只能加载小游戏包内图片资源,并且需要主动设置高宽(不会自动读取贴图资源尺寸)。

属性
属性名类型介绍
topNumber/Percent顶端。可参阅空间描述约定
bottomNumber/Percent底端
leftNumber/Percent左端
rightNumber/Percent右端
visibleBoolean可视
widthNumber/Percent宽度
heightNumber/Percent高度
opacityNumber透明度 0~1
urlString/Frame.var图片资源本地路径
scaleWidthNumber宽度放缩系数
scaleHeightNumber高度放缩系数
事件
事件名参数介绍
onClick-当贴图被点击
案例
js
const image = operaData.createFrame(FrameType.createImage);
+
+// 右下角跳过贴图
+image.setParams({
+  bottom: 10,
+  right: 10,
+  width: 100,
+  height: 30,
+  url: 'launchOperaPlay/skip.png',
+});
+
+// 点击事件
+image.setEvent({
+  event: 'onClick',
+  bind: [ ... ],
+  keep: true,   // 事件始终有效
+});

FrameType.createRect

创建透明、纯色矩形区域,通常用于透明点击区域、背景色。

属性
属性名类型介绍
topNumber/Percent顶端。可参阅空间描述约定
bottomNumber/Percent底端
leftNumber/Percent左端
rightNumber/Percent右端
visibleBoolean可视
widthNumber/Percent宽度
heightNumber/Percent高度
colorString十六进制颜色描述字符串(如:#FFFFFF00)
事件
事件名参数介绍
onClick-当贴图被点击
案例
js
const rect = operaData.createFrame(FrameType.createRect);
+
+// 一个全屏的透明区域,可以用于点击事件透明遮罩
+rect.setParams({
+  top: 0,
+  left: 0,
+  bottom: 0,
+  right: 0,
+  color: '#FFFFFF00'
+});
+
+// 点击事件
+rect.setEvent({
+  event: 'onClick',
+  bind: [ ... ],
+})

属性修改

FrameType.setParam

设置单个属性。

属性
属性名类型介绍
frameFrame需要修改的 frame 句柄
paramString属性名
valueString/Frame.var/Number/Boolean新的值
案例

参阅 seek的使用案例 案例

FrameType.setParamSizeAndPosition

同时设置 Size 或 Position 相关属性。相比较于 FrameType.setParam 每次只能设置1个属性,对于常见的位置属性可以使用 FrameType.setParamSizeAndPosition 一次性设置。

属性

类型中 None 代表可缺省,即不设置该属性。

属性名类型介绍
frameFrame需要修改的 frame 句柄
topNumber/Percent/None顶端
bottomNumber/Percent/None底端
leftNumber/Percent/None左端
rightNumber/Percent/None右端
visibleBoolean/None可视
widthNumber/Percent/None宽度
heightNumber/Percent/None高度
opacityNumber/None透明度 0~1
scaleWidthNumber/None宽度放缩系数
scaleHeightNumber/None高度放缩系数
案例
js
const image = ... // 创建image
+
+// 调整Image位置
+const setPositon = operaData.createFrame(FrameType.setParamSizeAndPosition, {
+  frame: image,
+  top: 0,
+  right: '10%',
+  opacity: 0.5
+});
+
+... // 在特定条件下触发 setPositon

延迟执行

FrameType.setTimeout

类似 JavaScript setTimeout 的延迟执行。

属性
属性名类型介绍
timeoutString/Number/Frame.var延迟时长,单位 ms
cancelBoolean取消状态,运行时赋值false可提前终止延迟执行
事件
事件名参数介绍
onEnded-当延迟结束后
onCancel-当主动取消时
案例
js
const delay1000 = operaData.createFrame(FrameType.setTimeout, {
+  timeout: 1000,  // 1000ms
+});
+
+delay1000.setEvent({
+  event: 'onEnded',
+  bind: [ ... ] // 1000ms 后执行的关键动作帧/故事线
+});

动画相关

FrameType.createAnimationFunction

创建动画函数,使得视图组件的某(几)个属性能够按照持续时间完成渐变。无需考虑卸载动画函数,当动画函数被作用的关键动作帧句柄不可视状态时,动画函数将自动结束。

动画在微信开发者工具(模拟器)中表现异常,以真机表现为准。

属性
属性名类型介绍
frameFrame动画被作用的关键动作帧句柄
durationString/Frame.var持续时长
easingString/Frame.var曲率函数,如 ease-out
topNumber/Percent/None顶端
bottomNumber/Percent/None底端
leftNumber/Percent/None左端
rightNumber/Percent/None右端
visibleBoolean/None可视
widthNumber/Percent/None宽度
heightNumber/Percent/None高度
opacityNumber/None透明度 0~1
scaleWidthNumber/None宽度放缩系数
scaleHeightNumber/None高度放缩系数
事件
事件名参数介绍
onEnded-当动画结束后
案例

使用动画实现贴图按钮“点击继续”的「呼吸态」是最常见的实用应用,本演示将提供呼吸态按钮的实现:

js
// 一个位于底部居中的 点击继续 按钮
+const button = operaData.createFrame(FrameType.createImage, {
+  bottom: 20,
+  left: '50%',
+  width: 100,
+  height: 25,
+  url: 'launchOperaPlay/click_go_on.png'
+});
+
+// 创建一个淡出的动画(透明度从 1->0.2)
+const goonButtonAnimationFadeOut = operaData.createFrame(
+  FrameType.createAnimationFunction,
+  {
+    opacity: 0.2,
+    duration: 1000,
+    easing: 'ease-out',
+    frame: button,
+  },
+);
+// 再创建一个淡入的动画(透明度从 0.2->1)
+const goonButtonAnimationFadeIn = operaData.createFrame(
+  FrameType.createAnimationFunction,
+  {
+    opacity: 1,
+    duration: 1000,
+    easing: 'ease-out',
+    frame: button,
+  },
+);
+
+// 需要两个 Animation 结束后互相调用,即 淡入->结束->淡出->结束->... 循环之
+goonButtonAnimationFadeOut.setEvent({
+  event: 'onEnded',
+  bind: goonButtonAnimationFadeIn,
+  keep: true,    // keep = true 很关键,因为该事件将被反复执行
+});
+goonButtonAnimationFadeIn.setEvent({
+  event: 'onEnded',
+  bind: goonButtonAnimationFadeOut,
+  keep: true,
+});
+
+// 挂载一个适合的故事线中触发后则实现「呼吸态」
+storyLineX.add(button, goonButtonAnimationFadeOut);

全局变量

全局变量是外界脚本(C#、JavaScript)与剧情内部“沟通”的桥梁,外界可以修改全局变量使得剧情内部完成基于条件判断实现的不同逻辑分支,外界也可以通过监听某个全局变量值来实时监控剧情内部通过属性修改产生的一些消息反馈。

有关外界对全局变量的赋值与监听请阅读API使用文档,本节仅介绍全局变量在剧情编辑时的创建及属性介绍。

FrameType.var

全局变量目前以字符串类型进行内容存储,为方便使用一般在剧情最早的时候进行创建并挂载到主故事线中。

属性
属性名类型介绍
valueString变量值
globalNameString/None全局变量名,设置后可供外界访问。缺省则为剧情内部全局变量,外界无法访问。
事件
事件名参数介绍
onChange-当变量被赋值时触发的事件,重复赋相同值也会发生事件
onChanged-当变量被赋值且值发生变化时触发的事件
案例
js
const var_Level0 = operaData.createFrame(FrameType.var, {
+  value: '1',
+  globalName: 'level0',   // 外界可根据此名称读取/监听该全局变量
+});
+
+storyLine.add(var_Level0); // 及时挂载到主故事线使其生效

条件判断

FrameType.if

可以对某(两)个全局变量进行判断的关键动作帧。

属性
属性名类型介绍
valueAString/Frame.var需要对比的变量值或全局变量句柄
valueBString/Frame.var需要对比的变量值或全局变量句柄
事件
事件名参数介绍
isTrue-当 valueA == valueB 时
isFalse-当 valueA != valueB 时
案例
js
// 创建变量
+const var_Level0 = operaData.createFrame(FrameType.var, {
+  value: '1',
+  globalName: 'level0',   // 外界可根据此名称读取/监听该全局变量
+});
+
+storyLine.add(var_Level0); // 及时挂载到主故事线使其生效
+
+const if_go_on = operaData.createFrame(FrameType.if, {
+  valueA: var_Level0,
+  valueB: '1',          // 判断 var_Level0 是否 == '1'
+}, [
+  {
+    event: 'isTrue',
+    bind: [ ... ],      // 成立时执行的故事线
+  },
+  {
+    event: 'isFalse',
+    bind: [ ... ],      // 不成立时执行的故事线
+  }
+]);

上报

上报模块有助于帮助开发者量化启动剧情不同阶段的用户曝光情况分析用户体验,因此建议游戏开发者合理接入该能力。

FrameType.Report

该上报本质使用的是 启动场景上报分析 能力,因此使用前应阅读该能力文档。

注意:启动上报每个sceneId在一次启动过程中最多只能上报1次,因此在接入故事线打点时请务必确保路径只会执行1次同sceneId的上报。

属性
属性名类型介绍
sceneIdString/Frame.var自定义上报场景ID
dimensionString/Frame.var/None自定义上报维度JSON字符串,请阅读上报说明填写
metricString/Frame.var/None自定义上报指标JSON字符串,请阅读上报说明填写
案例
js
// 创建好多个 report
+const report_1001 = operaData.createFrame(FrameType.report, {
+  sceneId: '1001',
+});
+const report_1002 = operaData.createFrame(FrameType.report, {
+  sceneId: '1002',
+});
+
+// 合理的位置进行上报
+video0.setEvent({
+  event: 'onEnded',
+  bind: [ report_1001 ],
+});
+
+...
+
+// 合理的位置进行上报
+video1.setEvent({
+  event: 'onEnded',
+  bind: [ report_1002 ],
+});

6.常见Q&A

6.1 图片资源可以使用网络图片吗?

目前图片资源只能存放于小游戏 minigame 目录中,不可使用网络图片。

6.2 为什么要放首帧图片(firstFramePic)

图片资源是跟随微信小游戏包上传至微信服务器,所以在小游戏主逻辑运行时,图片资源也处于就绪状态可以同步加载,因此玩家打开游戏时首帧将看到具体的游戏画面。而视频是存放在CDN的远程资源,不可避免的存在加载延迟问题,所以配置好首帧图片后,在视频可播放后再隐藏图片资源。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/OpenData.html b/Design/OpenData.html new file mode 100644 index 00000000..5eef51dd --- /dev/null +++ b/Design/OpenData.html @@ -0,0 +1,110 @@ + + + + + + Unity中如何展示排行榜这类微信关系数据 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Unity中如何展示排行榜这类微信关系数据

背景和原理介绍

小游戏提供了一系列接口获取好友关系链数据,为了安全,绝大部分接口都只能在开放数据域内调用。

avatar

开放数据域虽然乍一看有点复杂,但只需要核心理解几个点即可:

  1. 开放数据域所有逻辑都在一个独立的文件夹内完成,它核心处理两件事:调用关系链接口拉好友数据和将数据绘制到 sharedCanvas;
  2. 开放数据域接触到的 sharedCanvas 是一个离屏的 canvas,它完全不理解自己最终是怎么被绘制到屏幕上的;
  3. 主域(其实就是开放数据域文件夹外的业务代码)同样能接触 sharedCanvas,一般是通过 sharedCanvas 创建精灵添加到游戏场景;
  4. 数据的通信一定是单向的,只能从主域流向开放数据域,主域无法感知到开放数据域发生了什么;
  5. 鉴于第4点,主域要更新 sharedCanvas 只能定期刷新纹理来实现同步开放数据域的变化;

Unity 里面要实现 sharedCanvas 的绘制,核心在于 hook Unity 的渲染,完整的原理为:

  1. Unity 侧有个占位的纹理;
  2. Unity WebGL 模式下这个占位纹理会对应有一个 WebGLObject,Unity 会调用 drawElements API 绘制到 canvas;
  3. 在需要绘制排行榜的时候,将原本要绘制的 WebGLObject 替换成通过 sharedCanvas 创建而来的 WebGLObject;
  4. 在关闭排行榜的时候,停止步骤 3 的 hook;

详细步骤

1、设置占位纹理

在游戏需要展示的地方创建一个 RawImage,其中 Texture 属性自己选择透明的图片即可,后续展示时会被动态替换。因为unity纹理与 Web 的绘制存在倒立的差异,请将先将 rotation的x 设置为180,即让 UI控件延X轴旋转180度 再调整到游戏中合适的位置,如下图

avatar

2、调用SDK的API

2.1 在需要展示的地方调用,WX.ShowOpenData

CSharp
WX.ShowOpenData(rawImage.texture, x, y, width, height);

其中 :

  • x : 占位区域对应屏幕左上角横坐标
  • y : 占位区域对应屏幕左上角纵坐标,注意左上角为(0,0)
  • width : 占位区域对应的宽度
  • height : 占位区域对应的高度

WX.ShowOpenData 最终会调用 minigame/unity-sdk/open-data.js 内的 WXShowOpenData 方法,核心是三个作用:

  1. 调用 wx.getOpenDataContext,这会触发开放数据域的初始化,也就是 open-data 文件夹下的代码在开放数据域初始化之后才能够执行;
  2. 给开放数据域侧抛一个事件,告知开放域去执行数据拉取和渲染操作,对于 WXRender 的处理没有任何要求,开放数据域甚至可以忽略这个事件;
js
openDataContext.postMessage({
+    type: "WXRender",
+    x: x,
+    y: y,
+    width: width,
+    height: height,
+    devicePixelRatio: window.devicePixelRatio,
+});
  1. 开始 hook Unity 的渲染,原本的 RawImage 就会被替换成 sharedCanvas 的纹理。

2.2 需要关闭时则调用,WX.HideOpenData

这一步非常重要,如果仅仅在 Unity 侧隐藏了 RawImage 而没有调用 WX.HideOpenData,很可能导致排行榜关闭之后文理错乱,比如有些地方的纹理变成了排行榜对应的纹理。

2.3 通过 PostMessage 向开放数据域传递消息

如果需要在 Unity 中向开放域页面传递数据,可以调用WX.GetOpenDataContext,如下代码:

CSharp
[System.Serializable]
+public class OpenDataMessage
+{
+    // type 用于表明时间类型
+    public string type;
+}
+
+OpenDataMessage msgData = new OpenDataMessage();
+msgData.type = "showFriendsRank";
+string msg = JsonUtility.ToJson(msgData);
+WX.GetOpenDataContext().PostMessage(msg);

开放域JS代码可以通过:

js
wx.onMessage(data => {
+  console.log("[WX OpenData] onMessage", data);
+
+  if (typeof data === "string") {
+    try {
+      data = JSON.parse(data);
+    } catch (e) {
+      console.error("[WX OpenData] onMessage data is not a object");
+      return;
+    }
+  }
+
+  if (data.type === 'showFriendsRank') {
+    // 执行好友排行榜渲染
+  }
+});

3、导出选项勾选使用好友关系链

这一步会做两个事情:

  1. game.json 会声明使用开放数据域;
  2. 将插件内置的 open-data 示例拷贝至 minigame 目录,请注意做好文件备份;

avatar

4、用JS开发排行榜这类微信关系逻辑

开放数据域的开发和普通小游戏并无区别,暂时只能通过 js 来开发,对技术选型并无要求,可以不依赖任何引擎调用 Canvas2D API 执行渲染,但如果需要事件点击、滚动列表等处理,就会显得很麻烦;也可以选择完整的 JS 游戏引擎比如 Cocos,但这会使得代码包明显增大进而影响启动速度。

因此插件内置的示例采用的是微信自研的轻量级渲染引擎,压缩后只有几十k,这需要你掌握一些简单的 Web 开发知识,包括 Flex布局CSS,参照示例修修改改很快能够上手。

5、示例DEMO

可以参考Demo/Ranking下面的Unity工程。插件导出的 open-data 已经是一个比较功能完备的工程,进行简单的魔改就能够满足需求。

5.1 好友排行榜

  1. 展示 RawImage 的时候调用 SDK API
CSharp
void ShowOpenData()
+{
+  RankMask.SetActive(true);
+  RankingBox.SetActive(true);
+  // 
+  // 注意这里传x,y,width,height是为了点击区域能正确点击,x,y 是距离屏幕左上角的距离,宽度传 (int)RankBody.rectTransform.rect.width是在canvas的UI Scale Mode为 Constant Pixel Size的情况下设置的。
+  /**
+    * 如果父元素占满整个窗口的话,pivot 设置为(0,0),rotation设置为180,则左上角就是离屏幕的距离
+    * 注意这里传x,y,width,height是为了点击区域能正确点击,因为开放数据域并不是使用 Unity 进行渲染而是可以选择任意第三方渲染引擎
+    * 所以开放数据域名要正确处理好事件处理,就需要明确告诉开放数据域,排行榜所在的纹理绘制在屏幕中的物理坐标系
+    * 比如 iPhone Xs Max 的物理尺寸是 414 * 896,如果排行榜被绘制在屏幕中央且物理尺寸为 200 * 200,那么这里的 x,y,width,height应当是 107,348,200,200
+    * x,y 是距离屏幕左上角的距离,宽度传 (int)RankBody.rectTransform.rect.width是在canvas的UI Scale Mode为 Constant Pixel Size的情况下设置的
+    * 如果是Scale With Screen Size,且设置为以宽度作为缩放,则要这要做一下换算,比如canavs宽度为960,rawImage设置为200 则需要根据 referenceResolution 做一些换算
+    * 不过不管是什么屏幕适配模式,这里的目的就是为了算出 RawImage 在屏幕中绝对的位置和尺寸
+    */
+
+  CanvasScaler scaler = gameObject.GetComponent<CanvasScaler>();
+  var referenceResolution = scaler.referenceResolution;
+  var p = RankBody.transform.position;
+
+  WX.ShowOpenData(RankBody.texture, (int)p.x, Screen.height - (int)p.y, (int)((Screen.width / referenceResolution.x) * RankBody.rectTransform.rect.width), (int)((Screen.width / referenceResolution.x) * RankBody.rectTransform.rect.height));
+}
  1. 发送事件给开放数据域,要求展示好友排行榜
Csharp
OpenDataMessage msgData = new OpenDataMessage();
+msgData.type = "showFriendsRank";
+
+string msg = JsonUtility.ToJson(msgData);
+WX.GetOpenDataContext().PostMessage(msg);
  1. 开放数据域监听相应事件,展示群排行,详见 open-data。

整体流程示意:

5.2 群好友排行榜

  1. 为了使用群排行榜,需要调用 WX.UpdateShareMenu 设置分享菜单
CSharp
/**
+  * 使用群排行功能需要特殊设置分享功能,详情可见链接
+  * https://developers.weixin.qq.com/minigame/dev/guide/open-ability/share/share.html
+  */
+WX.UpdateShareMenu(new UpdateShareMenuOption()
+{
+    withShareTicket = true,
+    isPrivateMessage = true,
+});
  1. 在分享时,带上相关query
CSharp
WX.ShareAppMessage(new ShareAppMessageOption()
+{
+    title = "最强战力排行榜!谁是第一?",
+    query = "minigame_action=show_group_list",
+    imageUrl = "https://mmgame.qpic.cn/image/5f9144af9f0e32d50fb878e5256d669fa1ae6fdec77550849bfee137be995d18/0",
+});
  1. 监听 WX.OnShow 回调,给开放数据域发消息要求展示群排行
CSharp
WX.OnShow((OnShowCallbackResult res) =>
+{
+    string shareTicket = res.shareTicket;
+    Dictionary<string, string> query = res.query;
+
+    if (!string.IsNullOrEmpty(shareTicket) && query != null && query["minigame_action"] == "show_group_list")
+    {
+        OpenDataMessage msgData = new OpenDataMessage();
+        msgData.type = "showGroupFriendsRank";
+        msgData.shareTicket = shareTicket;
+
+        string msg = JsonUtility.ToJson(msgData);
+
+        ShowOpenData();
+        WX.GetOpenDataContext().PostMessage(msg);
+    }
+});
  1. 开放数据域监听相应事件,展示群排行,详见 open-data。

整体流程示意:

常见问题QA

Q1. 为什么第一次调用 WX.ShowOpenData 之后画面先黑一下再展示排行榜?

A1. WX.ShowOpenData 在 openDataContext.postMessage WXRender 的事件之后立马就会开始 hook Unity 的渲染,如果开放数据域在监听到 WXRender 事件之后没有任何渲染行为,那么 sharedCanvas 纹理就还没有准备好,Unity 侧就可能出现黑一下的情况,解决办法是保证监听到 WXRender 事件之后有个同步的渲染行为,比如绘制个文案”好友数据加载中..."。

Q2. 为什么我关闭排行榜之后界面上有些问题错乱了?

A2. 基本上只可能是没调用 WX.HideOpenData,建议 WX.HideOpenData 打些日志来辅佐排查。

Q3. 为什么开放数据域滚动事件不生效?

A4. WX.ShowOpenData(rawImage.texture, x, y, width, height)的后面四个参数,核心目的是告诉开放数据域 sharedCanvas 最终被绘制在了屏幕的位置和尺寸,开放数据域才能够正确处理事件监听,遇到事件不生效的问题,首先排查传进来的参数是否符合预期,比如 x / y 不应该是负数。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/OptimizationMemory.html b/Design/OptimizationMemory.html new file mode 100644 index 00000000..1616c5f5 --- /dev/null +++ b/Design/OptimizationMemory.html @@ -0,0 +1,24 @@ + + + + + + 优化Unity WebGL的内存 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

优化Unity WebGL的内存

一、内存与OOM

Unity WebGL游戏通常比普通H5(JS)游戏占用更大的内存,在操作系统的控制策略下超出阈值时非常容易被OOM。

为了提高游戏在中低端机型的稳定性,内存优化极为重要。那么,多大的内存是合理的呢? 我们建议内存峰值控制在以下范围(性能评估标准):

  1. Android: 低档机 < 1.2G, 中高档机 < 1.5G
  2. iOS: 低档机 < 1G, 中高档机 < 1.4G

相对而言,Android机型的内存更为宽松。

iOS低档机为iPhone 6sp/7/8等RAM 2G机型为主,中高档机为iPhone 7P/8P/iPhoneX/iPhone11等RAM 3G或以上机型。

二、Unity WebGL适配小游戏的内存结构

Unity WebGL内存结构可先参考:

Unity博客:了解 Unity WebGL 中的内存 (Understanding Memory in Unity WebGL)

Unity博客:Unity WebGL 内存:Unity 堆 (Unity WebGL Memory: The Unity Heap)

Unity WebGL是以WebAssembly+WebGL技术为基础的应用,运行在浏览器环境,因此游戏内存的分配也是完全托管在这个环境中。

适配在小游戏后,小游戏进程也就成为了“容器”,虽然不再是标准的浏览器,但内存组成结构与上图基本一致,典型游戏的内存占用如下图所示:

  • 基础库+Canvas:在小游戏环境中并不存在DOM,但依然会存在一些基本消耗,比如小游戏公共库,Canvas画布等。典型地,小游戏公共库约占用内存100~150MB,Canvas 画布与设备物理分辨率相关,比如iPhone 11 Promax占用约80MB。

  • Unity Heap: 托管堆、本机堆与原生插件底层内存。举例,游戏逻辑分配的C#对象等托管内存、Unity管理的AssetBundle和场景结构等本机内存、第三方原生插件(如lua)调用的malloc分配。

  • WASM编译: 代码编译与运行时指令优化产生的内存,在Android v8、iOS JavascriptCore中还需要大量内存进行JIT优化

  • GPU内存:纹理或模型Upload GPU之后的显存占用, 由于Unity2021之前不支持压缩纹理,纹理内存会造成明显膨胀。

  • 音频:Unity将音频传递给容器(浏览器或小游戏)后,播放音频时将占用的内存。目前UnityAudio将自动适配微信小游戏,特别地请避免使用fmod播放长音频

  • 其他:

    • Emscripten使用文件系统模拟Linux/POSIX接口,代价是占用与文件同等大小的内存。 请勿使用首资源包、Addressable Cache机制、WWW.LoadFromCacheOrDownload等Cache API***
    • 网络请求造成的浏览器端JS临时内存、垃圾回收

三、内存查看工具

我们从大到小各个角度去监控和分析游戏的内存情况:

进程级别: Perfdog、Android Studio、 Mac Xcode Instrument

UnityHeap(CPU主内存): 性能面板、ProfilingMemory、JavaScript Heap

引擎与资源:UnityProfiler

3.1 进程总内存

查看总内存时,我们需要先确定监控的小游戏进程名称:

  • Android:WeChat AppBrand1/2
  • iOS:普通模式WeChat、高性能模式(WebContent)

Instruments in Xcode(iOS)

使用“Activity Monitor”,选择对应的设备-all processes-捕捉,即可看到所有进程的CPU与内存情况.

Perfdog(Android or iOS)

使用Perfdog选择对应的设置-进程名,即可看到相关性能数据,iOS设备应以紫色的XcodeMemory为准。

3.2 UnityHeap

UnityHeap非常关键,典型由以下几部分组成:

  • 托管堆, C#对象托管对象、游戏状态
  • 本机堆, Unity Native产生,引擎内部对象
  • 原生内存,第三方插件(如lua)直接调用malloc产生

分析手段:

  1. 勾选转换面板"ProfilingMemory"
  2. 导出面板勾选“显示性能面板”或unity-namespace.js中enableProfileStats变量打开性能面板(注意:提审版本请勿显示). 游戏左上角显示Performence Stats性能面板

每项指标有三个数值:当前帧、最小值、最大值。

通常而言:MonoHeap + NativeReserverd + 原生插件内存 = DynamicMemory, 因此开发者需要关注这几部分内存。

Unity引擎视角:

  • MonoHeapReserved: 托管堆的内存预留内存

  • MonoHeap:托管堆(如C#业务逻辑)当前的内存使用量

  • NativeReserverd:本机堆(Native)内存分配峰值

  • NativeUnused:本机堆(Native)空闲内存值

  • NativeAllocated:本机堆(Native)当前的内存使用量

    注意:第三方原生插件(如lua)分配内存并未呈现,需开发者自行分析。

底层分配器视角:

  • TotalHeapMemory: UnityHeap总预分配内存大小
  • DynamicMemory:UnityHeap使用上限
  • UsedHeapMemory:UnityHeap真实使用量
  • UnAllocatedMemory:UnityHeap预留量

底层分配器:

  • 绿色为空闲内存或碎片,底层分配器会尽量复用
  • 白色为预留部分,可被使用
  • 其他颜色,已被业务使用

3.3 ProfilingMemory

ProfilingMemory可以分析UnityHeap底层分配器的分配细节,任何分配都会产生记录,因此我们可以通过该能力分析更详细具体的分配行为。

关于该能力的使用请查阅使用ProfilingMemory分析内存

3.4 Unity Profiler

当发现UnityHeap(尤其是Native)占用比较高时,可通过UnityProfiler进一步分析问题所在。关于该工具在微信小游戏的使用请查阅使用 Unity Profiler 性能调优,推荐使用Unity InstantGame版本增强的Profiler功能,下载地址请查阅推荐引擎版本

3.5 JavaScript Heap

由于Unity WebGL是托管在浏览器环境中,因此JavaScript Heap包含了大部分(并非全部)我们关注的内存, 通常我们可以使用浏览器自带的内存工具。 但需要注意的是JavaScript Heap通常无法看出具体内存使用,发现该部分内存明显大于我们预留的UnityHeap,应检查是否有使用Unity Cache进行文件缓存,务必避免这样使用。

微信开发者工具

FireFox Memory(PC)

iOS Safari Timeline(PC or iOS)

四、内存优化方案

计算公式: 小游戏基础库 + Cavnas + 编译内存 + UnityHeap + Gfx显存 + 音频 + JavaScript内存。 UnityHeap = max(托管/Mono内存) + max(Native/Reserved内存 + C原生代码内存)

以iOS高性能模式为例,一款代码(导出目录/webgl/Build/xxx.code.unityweb或code.wasm)大小为30MB的游戏占用内存为: 小游戏基础库(130MB) + Cavnas(70MB) + 编译内存(300MB) + UnityHeap + Gfx显存 + 音频 + JavaScript(通常<100MB)。

假如游戏需要支持低档机型,将内存控制到1G以内,业务侧(UnityHeap, Gfx显存,音频,JavaScript)需控制在500MB左右。我们此处给出转换游戏中最容易遇到的内存问题与解决方案,如果开发者遇到内存问题时请逐个排查优化。

4.1 WASM代码编译内存

  • 问题原因:Unity WebGL将所有代码(引擎、业务代码、第三方插件)编译为跨平台的WebAssembly二进制代码,运行时需进行编译执行。编译所占用内存占用非常大(如在iOS系统,30MB未压缩代码需300MB运行时编译内存)。
  • 解决办法:
      1. 使用代码分包工具能降低原编译代码内存50%以上。
      1. 手动删除多余插件,减少不必要的Unity模块引入(如物理、Unity数据统计等)

4.2 GPU内存

  • 问题原因:Unity 2021才开始支持移动平台的压缩纹理,使用RGBA、DXT等纹理格式将导致巨大的内存开销与运行时解压消耗。
  • 解决办法:
      1. 压缩纹理优化能最大程度地减少内存与解压开销。
      1. 升级引擎至2021使用ASTC压缩纹理
      1. 关闭HDR,标准渲染管线在"GraphicsSetting-tier2"(WebGL使用tier2)取消勾选"Use HDR";URP管线通过renderer配置取消
      1. 使用高性能+模式将显著降低GPU内存

4.3 UnityHeap

  • 问题原因:UnityHeap是用于存储所有状态、托管的对象和本机对象,往往由于场景过大或由于业务原因造成瞬间内存峰值。由于Unity WebGL在单首帧内无法GC,单帧内瞬间的内存使用非常容易造成crash。同时,Heap是只增不减且存在内存碎片的。
  • 解决办法:
      1. 转换面板设置合理的“UnityHeap预留内存”,切忌超出使用
      1. 避免场景过大导致瞬间峰值
      1. 避免过大的AssetBundle导致瞬间峰值
      1. 避免单帧内分配过多的对象, 切忌产生跳跃峰值
  • 如何设置“UnityHeap预留内存”?该值仅表示UnityHeap的峰值进行预留,避免内存不足时导致扩容产生的尖刺;
      1. 导出面板勾选“显示性能面板”或unity-namespace.js中enableProfileStats变量打开性能面板
      1. 将游戏运行一段时间,观察DynamicMemory的峰值
      1. UnityHeap=DynamicMemory+少量静态内存(通常<10MB),因此转换面板的“UnityHeap预留内存”设置为略大于DynamicMemory峰值(可多预留50-100MB,以实际游戏为准)。建议值:超休闲游戏256,中度游戏(模拟经营、卡牌成长)496,重度游戏(SLG,MMO)768。
      1. UnityHeap不宜过大,当UnityHeap>=1024MB时,大部分设备将启动失败;UnityHeap>=500MB时,32位微信(约5%用户)与iOS普通模式大概率启动失败,建议中轻度游戏不超过该值。

4.4 首资源包与AssetBundle内存

  • 问题原因:首资源包永远占用内存且无法释放;首资源包和AssetBundle自带的cache机制都会使用Emscripten使用文件系统,应避免使用。
  • 解决办法:
      1. 减少首资源包大小,此部分始终占用内存无法释放, 使用AssetBundle;
      1. AssetBundle按需加载,及时释放以节省内存;
      1. AssetBundle使用时被解压占用Unity Native内存,应减少AssetBundle大小;
      1. 避免使用Unity自带的文件缓存机制, 首资源包和AssetBundle都不应使用文件Cache

4.5 音频内存

  • 问题原因:音频将占用小游戏环境的内存
  • 解决办法:
      1. 不要使用fmod播放长音频,如游戏BGM
      1. 控制音效数量,同时存在的音频数不应该超过20个
      1. 尽量强制使用单声道音频,双声道会产生2倍内存消耗

4.6 其他常见优化手段

五、QA

  1. Q: 如何解决iOS高性能模式出现内存过大导致游戏关闭,常见优化步骤如何?

    • iOS测试内存务必不要开启development、profilingmem等模式
    • iOS测试内存务必使用代码分包、压缩纹理(2021以上可使用引擎ASTC,低版本使用微信压缩纹理)
    • 请使用Perfdog或mac Instrument查看WebContent进程内存是否在安全范围(安全内存峰值是1.2-1.3G左右)
    • 进程内存离1.5G上限还有较大差距就突然崩溃,请检查“UnityHeap预留内存“是否足够
    • 打开性能面板查看DynamicMemory,峰值不要超过500M(结合profilingmem、memoryprofiler分析)
    • 使用Perfdog查看Android版本的GL、GFX显存,对于GPU显存压力大的游戏,使用高性能+模式
    • 如果以上步骤完成还有问题,请提供详细数据联系平台侧进一步分析
  2. Q: 在Unity Profiler看到内存才200MB+,是否代表游戏内存无问题

    • 不是。游戏占用内存必须以真机环境为准,使用Perfdog(Android or iOS)或 Instruments in Xcode(iOS)测试对应进程的内存占用。
    • Unity Profiler仅能看到“引擎可监控内存”,并不包含小游戏公共库、Cavas、WebAssembly编译以及容器其他内存。
    • 建议使用2022或团结版的memoryprofiler、profiling-mem更精确分析内存,对于分析CPU/GPU内存有较大帮助
  3. Q: 转换面板设置内存值多少合适?

    • 请看前文关于UnityHeap预留内存的说明

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/OptimizationPerformence.html b/Design/OptimizationPerformence.html new file mode 100644 index 00000000..fe0f7b06 --- /dev/null +++ b/Design/OptimizationPerformence.html @@ -0,0 +1,29 @@ + + + + + + 优化Unity WebGL的运行性能 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

优化Unity WebGL的运行性能

一、运行性能概述

Unity WebGL是以WebAssebly(WASM)+WebGL为核心的技术方案,运行性能会极大影响可承载的游戏内容玩法。

本文主要介绍Unity WebGL与基于JS引擎的普通H5游戏、原生APP手游之间技术栈导致的性能差异,以及不同系统平台(Android、iOS、Windows PC)之间的性能差异。其次阐述在微信小游戏环境下最佳的性能优化工具与常见优化手段。

Unity WebGL VS APP的运行性能差异

  • CPU性能差异

    • Unity WebGL是以WASM虚拟机的形式运行在类浏览器环境中,因此CPU算力会受限于虚拟机的执行效率。
    • Unity WebGL目前不支持多线程,导致部分模块比如AI、动画、渲染无法得到多线程的加速。

    这是导致了Unity WebGL与APP存在性能差距的最主要因素。通常而言,Unity WebGL是APP手游性能的1/3,开发者应该特别注意CPU侧的性能瓶颈。

    可通过Benchmarking Unity performance in WebGL了解Unity不同模块与手游APP的性能差异。

  • GPU性能差异

    • Unity是以WebGL API进行渲染,其中WebGL1.0相当于OpenGLES2.0, WebGL2.0相当于OpenGLES3.0。
    • WebGL在原生的渲染API进行封装存在少量负荷带来的开销,但基本的渲染能力与原生APP接近。
    • 渲染特性如GPU Instantcing、SRP Batcher需要WebGL2.0。 (需要注意的是,当APP手游使用了这些特性时,在小游戏未开启WebGL2.0时则会进一步拉大差距)

WASM VS JS的运行差异

  • WASM是强类型语言,这将使得JIT优化能更准确预判运行期类型,因此相对于JS能更快达到JIT指令优化后的峰值。通常而言,WASM~=1.5 * JS, 即JS运行效率的150%以上。
  • Unity引擎目前没有很好地针对浏览器环境优化(比如WASM与宿主接口互调频次、不必要的代码路径裁)会比较臃肿,一些应用场景反而不如JS轻量。

因此,两者在实际使用时并不能简单以语言算力对比,需要以实测游戏为准。

系统平台之间的性能差异

  • Android与Windows PC使用V8作为WASM虚拟机内核,支持JIT,在相同算力条件下两者性能是接近的。但要注意移动平台散热更差,因此对性能更苛刻。
  • iOS默认为普通模式,不支持JIT,可用于超休闲游戏;中重度游戏建议开启iOS高性能模式以支持JIT,但该模式需要更多精力进行调优,特别是启动发烫与内存方面。

二、优化目标

由于Unity WebGL的性能无法完全达到原生APP的性能水平,开发者需要根据不同品类的游戏建立不同的最低机型要求和流畅度标准。 建议:

  • 轻度休闲游戏应保证低档机型30fps以上,需特别注意机型兼容性(可使用小游戏云测获取兼容性报告),以达到买量用户覆盖度。
  • 中重度游戏应保证中高档机不限帧时达到40fps以上,实际运行可限帧30以保持长时间挂机运行的发热量。

详细的基准机型与性能要求可参考性能评估标准微信小游戏平台对上线无严格的性能要求,需要开发者根据自身游戏商业化要求制定。

三、常用优化工具

3.1 小游戏Android CPU Profiler(推荐)

微信小游戏请使用 Android CPU Profiler 性能调优,在勾选Profile-funcs选项后,使用工具在真机上获取Profile数据以分析热点函数和性能瓶颈,非常建议开发者熟练使用,无论是启动耗时或运行时流畅分析都非常有用。

  • 工具本身不会造成大幅度的性能降低
  • 精确获取每帧性能瓶颈,也支持时间段内的汇总信息
  • 支持真机获取,能准确反映游戏实际运行情况

3.2 Unity Profiler

Unity Profiler的运行原理是在Unity Editor监听固定端口,Unity WebGL游戏运行时以WebSocket连接并定期发送性能数据。

  • 工具需要开启development模式,对性能有较大影响
  • 可获取函数热点、内存与模块上报数据(比如物理、动画等)
  • 不是很稳定,部分版本会出现无法连接的情况
  • 内存数据不准确,并不能反应真实使用情况,内存工具请查阅优化Unity WebGL的内存

3.3 小游戏云测

小游戏云测是使用大量真实的移动设备测试游戏的功能、性能、兼容性。

  • 重点关注兼容性问题,比如黑屏、无法启动问题
  • 启动与运行性能由于网络和设备条件稳定性问题不一定准确,建议以性能评估标准实测为准
  • 运行环境以CR识别+随机点击,开发者也可以通过WX.cs的接口判定当前云测环境让游戏自动运行特定逻辑

三、常见优化手段

1. 配置加载与协议解析

不用使用XML、JSON解析大文件,尤其是在游戏启动阶段,字符串类型解析器将耗费大量CPU算力与产生GC。比如大型游戏在使用Addressable时catalog文件往往会超过10MB,导致解析过慢而影响启动速度,此时应使用其他资源管理比如AssetBundle来减少资源索引文件大小。同样地,在游戏过程中也尽量避免这类CPU消耗。

2. LUA性能

Unity WebGL环境的lua不支持JIT,因此需要避免用于重度逻辑。可使用 Android CPU Profiler 性能调优查看LUA的耗时占比。

3. 物理性能

请参考文档优化物理性能,适当调整Fixed Timestep与 Maximum Allowed Timestep降低计算频率。

4. 实例化

由于Unity WebGL是单线程模型,因此耗时长的CPU运算会影响帧率。较为普遍的是AssetBundle加载与Prefab实例化,通过优化逻辑分帧加载可大幅度提升游戏体验。

5. 限制帧率

限制帧率有利于降低设备发热量与提升游戏时长,对帧率不敏感游戏建议使用, 可使用Application.targetFramerate限帧,当帧率为15/30/60使用raf分片处理,其余值使用timer控制。

6. 限制分辨率

限制分辨率以一定的画质牺牲来降低对设备消耗,在小游戏平台请勿使用Unity的SetResulution等接口修改分辨率,应使用DevicePixelRatio来控制(仅支持ios、android)。设备默认DevicePixelRatio(最后一列dpi)如下:

如需强制设置iOS的设备分辨率可以在【导出面板-更多配置项-Project Conf】中修改配置 IOS Device Pixel Ratio 为 2:

  • 可降低渲染压力可明显降低设备发热量
  • 减少内存使用,降低分辨率后可降低50-100MB内存
  • 需开发者自行评估DevicePixelRatio降低后的品质变化

7. 使用压缩纹理

在压缩纹理不支持的情况下,纹理会由于需要在CPU中软解为RGB/RGBA32造成巨大的CPU和内存消耗,运行中的这种行为会造成明显的帧率卡顿问题,建议使用压缩纹理优化

8. WebGL2.0说明

请查阅WebGL2.0渲染支持说明

9. 减少Drawcall

大量DC会造成非常大的CPU压力,当场景渲染物件过多时应该采取适当的措施减少Drawcall

  • 标准渲染管线,适当使用Static Batch以减少DC
  • 可开启WebGL2.0时使用GPU Instantcing
  • 尽可能地设置LOD、可见范围以降低渲染物件

10. 使用SRP Batcher

Uinty WebGL的SRP Batcher需要两个先决条件:Unity 2021以上 + WebGL2.0

11. 如何获取设备硬件信息

  • 使用wx.getDeviceInfo获取硬件信息, 该接口使用前需自行判断是否满足基础库版本要求。新版本已新增memorySize 和 CPUType获取设备内存、CPU型号
  • 使用JS代码获取GPU信息
      const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
    +  const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
    +  const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
    +  console.log(vendor);
    +  console.log(renderer);

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/PerfMeasure.html b/Design/PerfMeasure.html new file mode 100644 index 00000000..9c130219 --- /dev/null +++ b/Design/PerfMeasure.html @@ -0,0 +1,24 @@ + + + + + + Unity WebGL小游戏适配方案性能标准 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Unity WebGL小游戏适配方案性能标准

为什么需要性能评测标准?

Unity性能评测标准用于开发者优化游戏性能数据,提升用户体验。评测标准根据小游戏整体的性能数据表现,结合操作系统、机型分档等多种维度建立。

评测标准细则

性能基线

评测小游戏性能首先需要确定性能基线, 即先确定机型设备条件,开发者可通过机型档位映射获取机型档位的参考机型。

游戏类型说明

分类定义
重度玩法较复杂,通常包含较多游戏场景或支持多人在线游戏(eg: MMO、SLG品类等)
中度包含一定养成玩法、内置内购商城等(eg: 模拟经营、卡牌等)
轻度仅包含简单操作、无养成体系、无内购,以休闲娱乐为主(eg: 棋牌等)

指标与测量方法

Unity小游戏的启动可参考启动流程与时序

定义测量方法
首资源包游戏首个data资源文件位于导出目录/webgl/md5.webgl.data.unityweb.bin.txt, CDN使用gzip压缩
WASM代码游戏代码压缩包位于导出目录/minigame/wasmcode/md5.webgl.wasm.code.unityweb.wasm.br, CDN使用gzip压缩
核心资源除首资源包外进入游戏核心玩法所需的资源量业务自定下载,通常为AssetBundle
CALLMAIN引擎和首场景(Loading)初始化通过timelog,或日志查看“CALLMAIN耗时”
游戏初始化完成引擎和首场景完成,出现首个业务场景通过timelog, 或日志查看“游戏启动耗时”
游戏可交互完成游戏核心场景完成通常定义为用户可交互的时机,可通过启动留存上报能力上报统计。eg:休闲游戏为核心玩法,RPG游戏为创角
内存峰值内存峰值进程内存峰值,测量方法请参考优化Unity WebGL的内存
内存异常退出运行时长由于内存不足而使小游戏发生Crash时,当前游戏的运行时长,表示游戏的稳定运行时长开发者可通过 小游戏数据助手(数据-性能分析)或 MP-研发工具箱-性能数据 获取游戏的现网玩家的性能采集数据 通过小游戏数据助手查看(仅包含线上用户数据)
帧率核心玩法的平均帧率测量5分钟以上游戏核心玩法帧率,取平均值
卡顿率核心玩法的平均卡顿率测量5分钟以上游戏核心玩法卡顿率,取平均值

开发者需要关注哪些性能指标

阶段重点关注指标
启动1. 游戏初始化完成耗时 2. 游戏可交互耗时
运行1. 内存峰值 2. FPS均值 3. 卡顿率 4. 内存异常退出率(iOS) 5. 内存异常退出运行时长(iOS)
兼容性问题1. 逻辑异常 2. 黑/白屏 3. JS Error

代码与资源体积

能力下载量
首资源包(gzip压缩后)<5MB
WASM代码(br压缩后)<5MB
核心玩法资源<30MB

评测标准

评测标准更新时间:2024-08-13(历史现网标准请查阅历史评测标准

评测标准依赖于 现网真实玩家上报的性能数据云测试批量测试数据 统计得出。

注意:

  • FPS均值为大盘游戏数据计算所得,由于游戏可能会存在限帧逻辑,数据仅供参考,建议游戏依据自身游戏特性,合理控制游戏帧率表现。
  • 设备平台的内存统计口径参考社区公告《小游戏内存口径》
  • 红色指标值表示指标标准下降,未标注颜色指标值则表示当前指标项标准提升(与历史评测标准相比)或 与原有标准一致。

iOS性能评测标准

启动性能

运行性能

重点关注:内存峰值运行10mins内存峰值内存异常退出率内存异常退出运行时长

Android性能评测标准

启动性能

运行性能

评测工具

现网阶段

性能报告

为了能够帮助开发者快速了解游戏整体的性能情况,平台通过对评测标准和游戏性能数据的整合,面向开发者提供一个较为全面的大盘性能监控系统,详细可通过 性能监控系统 进行了解和使用。

性能数据

开发者可通过 小游戏数据助手(数据-性能分析)或 MP-研发工具箱-性能数据 获取游戏的现网玩家的性能采集数据。

开发阶段

使用网络模拟工具1MB/s条件

小游戏云测试

云测试服务是一套完整易用的在线测试服务,以帮助开发者更高效、更全面地进行自动化游戏性能测试、兼容性测试。更多详情可查阅小游戏云测试

性能诊断工具

微信小游戏性能诊断工具用于查看 开发版/体验版 运行时的网络和接口调用、运行性能以及启动耗时等信息,协助开发者更精确地定位问题并提供优化建议,详情可查阅性能诊断工具

Perfdog

使用PerfDog测试,PerfDog记录性能数据并上传,取平均值,每种机型测试3组数据再取平均,内存峰值取最大值。

历史评测标准

更新日期文档
2024.08.13当前标准
2023.05.17评测标准文档

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/PerfOptimization.html b/Design/PerfOptimization.html new file mode 100644 index 00000000..f440897d --- /dev/null +++ b/Design/PerfOptimization.html @@ -0,0 +1,24 @@ + + + + + + 性能优化总览 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

性能优化总览

一、为何需要进行性能优化?

Unity WebGL导出形式相对于原生APP应用,需要开发者更关注性能与体验调优。有以下几点原因:

  1. 小游戏天生为"即开即用",在小游戏生态下玩家对启动耗时更敏感。
  2. Unity WebGL底层基于WebAssembly,算力不及原生APP。
  3. Unity并未对WebGL平台做特别裁剪,启动较慢。

因此,相对于原生APP,无论从启动还是运行上我们都需要做进一步性能优化。

二、优化目标

根据平台在不同游戏类型/机型下的评测,我们给出Unity WebGL小游戏可以参照的的性能评估标准,开发者依此对游戏的启动与运行性能进行调优。

三、最佳实践

3.1 加快游戏启动速度

  • 编译选项中仅勾选首场景
  • CDN必须开启Brotli或gzip压缩
  • 精简首场景物件,尽快渲染让玩家看到游戏首画面
  • 减少初始化与首帧逻辑,首场景Awake/Start/首次Update不要包含过重逻辑
  • 减少代码包体, 剔除不必要的插件
  • 使用代码分包工具缩减WebAssembly首次下载包体

更多信息请参考:

3.2 资源按需加载

  • 尽量避免在各级Resource包含资源,该目录将被直接打包在首资源包
  • 使用AssetsBundle/Addressable进行资源加载
  • 单个包体最好不超过2MB
  • 资源请求并发数不超过20个

更多信息请阅读:

3.3 资源处理建议

  • 贴图maxsize尽量不超过1024,小游戏环境适当降低画质
  • 贴图尽量不生成Mipmap
  • 贴图尽量不使用可写属性
  • 字体文件压缩前最大不超过4MB

更多信息请阅读:

3.4 降低小游戏内存使用

  • 不要初始化所有未使用的资源
  • 释放不使用的资源
  • 发布前使用压缩纹理工具进行优化
  • 音频资源尽可能勾选强制单声道
  • iOS开启高性能+模式

更多信息请阅读:

3.5 降低CPU消耗

  • iOS使用高性能模式
  • 尽量使用Android CPU Profiler在小游戏真机环境Profie计算瓶颈
  • 提前在Unity环境使用Unity Profiler发现问题
  • 物理计算较重的游戏使用Fixed Timestep控制计算频率
  • 在中低端机型限制帧率以减轻设备发烫

更多信息请阅读:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/PerformanceMonitor.html b/Design/PerformanceMonitor.html new file mode 100644 index 00000000..8208ab87 --- /dev/null +++ b/Design/PerformanceMonitor.html @@ -0,0 +1,102 @@ + + + + + + 最佳实践检测工具 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

最佳实践检测工具

作用

为了使游戏达到比较好的性能表现,仍需要开发者结合游戏实际情况进行优化。平台针对启动和运行输出了大量优化手段,使用最佳实践检测,可帮助开发者在开发阶段针对问题进行优化

如何使用

版本要求:转换插件版本 > 202305230000

导出小游戏默认在开发版和体验版开启检测,可通过minigame/unity-namespace.js修改

js
// 最佳实践检测配置
+unityNamespace.monitorConfig = {
+  enableMonitor: true, // 是否开启检测(只影响开发版/体验版,线上版本不会检测)
+  fps: 10, // 帧率低于此值的帧会被记录,用于分析长耗时帧,做了限帧的游戏应该适当调低
+  showResultAfterLaunch: true, // 是否一直检测到游戏可交互完成
+  monitorDuration: 30000, // 仅当showResultAfterLaunch=false时有效, 在引擎初始化完成(即callmain)后多长时间停止检测
+}

默认检测条件如上。插件并不知道什么时候检测截止,可选择可交互上报后或在引擎初始化完成(callmain)后多少ms截止,根据游戏实际情况修改。

  1. 有上报游戏可交互WX.ReportGameStart()的游戏 应该设置showResultAfterLaunch=true,同时会忽略monitorDuration的值

  2. 未上报游戏可交互上报的游戏 应设置showResultAfterLaunch=false,此时根据monitorDuration的值截止检测

检测示意

优化建议通过弹框提示,详细内容通过vconsole打印

  1. 弹框提醒优化建议
  1. console打印详细信息
  1. console打印检测报告,可着重关注网络和卡帧的数据

检测指标解释

启动检测

检查框架启动阶段的耗时和资源大小

监控指标

{
+  assetLoadCost: number; // 首资源包下载耗时,单位ms
+  assetContentLength: number; // 首资源包大小(未压缩原始大小),单位bytes
+  useContentEncoding: boolean; // 首资源包是否开启服务器压缩
+  wasmLoadCost: number; // wasm包下载耗时,ms
+  wasmContentLength: number; // 启动下载的wasm包大小,单位bytes
+  useCodeSplit: boolean; // 是否使用了wasm代码分包
+  callmainCost: number; // 引擎初始化耗时,ms
+}

优化建议概览

当提示优化建议时,可采用对应的优化手段

  1. 未使用wasm代码分包
  1. 首资源包较大
  1. 首资源包未开启服务器压缩
  1. callmain耗时较长,请用安卓cpuprofile分析热点函数

预下载检测

检查预下载列表使用情况,分为引擎初始化完成(callmain)和检测完成时两个结果

vconsole输出如下:预下载基本信息: xxx , callmain完成时预下载信息: xxx。其中xxx为js对象

监控指标

{
+  loadedCount: number; // 已预下载完成数量
+  loadingCount: number; // 正在预下载数量
+  loadedSizeStr: string; // 已预下载完成大小字符串表示, eg: 10.1MB
+  loadedSize: number; // 已预下载完成大小,bytes
+  hitCacheCount: number; // 命中CDN缓存的数量
+  useH2: boolean; // 是否启用HTTP2
+  useContentEncoding: boolean; // 是否开启了服务器压缩
+  preloadListLength: number; // 预下载资源个数
+}

优化建议概览

  1. 未使用预下载能力
  1. 已发起预下载,但未完成,请检查预下载资源是否过大,或是否下载过慢
  • 条件: 引擎初始化完成时,loadingCount != 0loadedCount = 0; 表示预下载已发起但未完成
  • 优化手段: 使用预下载功能-注意事项第五点,预下载文件体积不应过大,将优先需要使用的资源放到列表头部
  1. 预下载资源较小,请将大资源调整到预下载列表顶部
  • 条件: 引擎初始化完成时 loadedSize < 1 * 1024 * 1024 (1MB) 或停止检测时 loadedSize < 5 * 1024 * 1024 (5MB)
  • 优化手段: 适当增加预下载资源大小
  1. 预下载资源个数较多
  • 条件: preloadListLength > 15;即预下载列表数大于15
  • 优化手段: 减小预下载个数
  1. 预下载资源量较大
  • 条件: loadedSize > 20 * 1024 * 1024 (20MB);即总预下载大小超过20MB
  • 优化手段: 减小预下载资源量,过大的资源下载会造成带宽抢占,推荐由游戏自行控制加载时机

wasm分包检测

使用wasm代码分包后,检查wasm分包代码的加载时机,加载分包造成的卡顿时长,用来分析分包收集是否合理。若加载时机过早、阻塞时间过长,则需要优化。

tips: 在新包做wasm分包期间可能会频繁提示优化建议

监控指标

{
+  loadSubWasmPackageStartTime: number; // 开始下载wasm子包的时间,ms
+  loadSubWasmPackageCostTime: number; // (仅安卓)加载子包耗时,ms
+  loadDurationCallmain: boolean; // 是否在引擎初始化期间加载子包
+  maxFetchPendingTime: number; // (仅iOS高性能)最大阻塞时间,ms。iOS高性能加载子包代码时会卡顿
+  costTimeAfterCallmain: number; // 引擎初始化完成后多长时间开始加载子包,ms
+}

优化建议概览

  1. wasm子包在callmain期间加载,请使用分包工具继续收集
  • 条件: loadDurationCallmain=true
  • 优化手段: 分包收集不足,使用分包工具继续迭代
  1. wasm子包加载时机过早,请使用分包工具继续收集
  • 条件: costTimeAfterCallmain < 30000 (30s)
  • 优化手段: 游戏前期不应加载子包,当前期出现子包加载,则需要继续迭代
  1. 缺失函数过多,请使用分包工具继续收集

网络信息检测

检查可缓存资源配置、CDN配置、并发数数、请求量、资源量

监控指标

{
+  useH2: boolean, // 是否开启HTTP2.0
+  useContentEncoding: boolean, // 是否开启服务器压缩
+  cacheSettings: boolean, // settings.json是否自动缓存
+  cacheCatalog: boolean, // catalog.json是否自动缓存
+  appendHashToCatalog: boolean, // catalog.json是否带上了hash或其他用于区分版本的信息
+  requestCataHash: boolean, // 是否请求了catalog.hash文件用于资源热更新
+  requestBundleSettings: boolean, // 是否请求了settings.json
+  requestBundleCatalog: boolean, // 是否请求了catalog.json
+  loadCount: number, // 已发起请求数
+  loadedCount: number, // 已完成请求数
+  loadedSizeStr: string, // 请求回包总大小的字符串表示,eg: 10.1MB
+  loadedSize: number, // 请求回包总大小,bytes
+  hitCacheCount: number, // 命中CDN缓存个数
+  cacheableCount: number, // 可自动缓存个数
+  loadFromCacheCount: number, // 使用本地缓存的个数
+  startTime: number, // 首个请求开始时间
+  duration: number, // 监控时长
+  networkTime: number, // 有网络请求的总时长
+  maxLoadingCount: number, // 最大并发数,基于业务侧统计,会大于10个,表示有请求会排队
+  avgLoadingCount: number, // 平均并发数
+  loadedTasks: IBaseRequestInfo[], // 已下载完成请求详细信息
+}
+
+// 请求详细信息如下
+interface IBaseRequestInfo {
+  url: string; // 请求URL
+  startTime: number; // 请求开始时间
+  statusCode?: number; // 服务器状态码
+  enableContentEncoding?: boolean; // 是否开启了服务器压缩
+  endTime?: number; // 请求介绍时间
+  duration?: number; // 请求耗时
+  protocol?: string; // 网络协议,h2或http1.1
+  receivedBytedCount?: number; // 回包大小,bytes
+  hitCache?: boolean; // 是否命中CDN缓存
+  isReadFromCache?: boolean; // 是否使用本地缓存
+  cacheable?: boolean; // 是否自动缓存的资源
+}

优化建议概览

  1. 未开启http2
  • 条件: useH2=false
  • 优化手段: 服务器开启HTTP2.0,通过多路复用和头部压缩的特性,能提升细碎文件的下载效率
  1. 未命中CDN缓存
  • 条件: hitCacheCount=0
  • 优化手段: 发布新版本时,建议进行CDN预热,避免直接从源站拉取资源
  1. 请勿缓存settings.json
  • 条件: requestBundleSettings=truecacheSettings=true
  • 优化手段: Addressables的settings.json文件用来记录打包配置,不应该缓存到本地。取消此文件的自动缓存,哪些资源会自动缓存
  1. 可将catalog.json配置为可缓存文件
  • 条件: requestBundleCatalog=truecacheCatalog=false
  • 优化手段: Addressables的catalog.json记录了所有资源文件的描述信息和依赖关系,一般大小较大,推荐缓存到本地,哪些资源会自动缓存
  1. catalog.json被缓存且无hash/版本信息, 会导致无法更新
  • 条件: requestBundleCatalog=truecacheCatalog=trueappendHashToCatalog=false
  • 优化手段: catalog.json缓存到本地若无版本标识,会导致无法更新到最新版本, 缓存规则
  1. 请勿请求catalog.hash来做资源热更新,小游戏平台不支持
  • 条件: requestCataHash=true
  • 优化手段: catalog.hash记录了catalog.json的hash,用来热更新资源,但小游戏平台不支持,推荐使用catalog.json文件名带hash的方式来管理catalog版本,参见建议第五点
  1. 可缓存文件过少,检查缓存配置
  • 条件: cacheableCount < loadCount / 2,可缓存资源小于总请求数的一半
  • 优化手段: 检查缓存配置,是否资源文件大部分未缓存。提高可缓存数量
  1. 网络并发数过少
  • 条件: avgLoadingCount < 5,平均并发数小于5
  • 优化手段: 并发数较少可能导致细碎文件较多时网络利用率不高,业务侧提高请求并发数
  1. 网络未充分利用
  • 条件: networkTime / duration < 0.7, 网络时间占监控时长占比不足70%
  • 优化建议: 可能由于游戏业务初始化逻辑较重,cpu繁忙,在cpu繁忙时未充分利用网络空闲;建议:在开始长耗时逻辑前,发起资源下载任务,充分利用网络。可使用微信开发者工具辅助分析

帧率检测

检查是否有大长帧,标记大长帧出现的位置,辅助定位是cpu耗时还是网络耗时导致启动慢

监控指标

{
+  frames: string[]; // 长耗时的帧
+  frameCount: number; // 长耗时帧的个数
+  longestFrame: { // 最长帧信息
+      frame: string; // 帧数
+      frameCost: number; // 单帧耗时, ms
+      runtime: number; // 游戏运行时长, ms
+  };
+  frameInfo: IWrongFrame; // 长耗时帧信息
+  totalJankTime: number; // 总卡帧时长, ms
+  currentRuntime: number; // 当前游戏运行时长, ms
+  jankRate: number; // 卡顿率
+}

优化建议概览

卡帧问题,均需要使用cpuprofile定位。使用Android CPU Profiler性能调优使用Unity Profiler性能调优

  1. 存在长耗时帧cost=xxxms,runtime=xxxms
  • 条件: longestFrame.frameCost > 1000 (1s)
  1. 总卡顿时长xxxms
  • 条件: totalJankTime > 5000 (5s)
  1. 卡顿时长占比xx%
  • 条件: jankRate > 0.3

优化分析工具

微信开发者工具

  • step1: 点击调试器-performance
  • step2: 点击录制按钮
  • step3: 分析网络并发和网络耗时
  • step4: 查看每帧耗时,与此帧网络并发

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Profile.html b/Design/Profile.html new file mode 100644 index 00000000..c089d923 --- /dev/null +++ b/Design/Profile.html @@ -0,0 +1,25 @@ + + + + + + 使用Unity Profiler性能调优 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

使用Unity Profiler性能调优

  1. 导出选项时勾选"Development Build"与"Autoconnection Profiler"

  2. 打开Unity-Window-Analysis-Profile窗口

Unity将自启动监听端口34999等待调试链接,对于WebGL版本会启动websockify.js(用于websocket转发)。 此时,导出的WebGL游戏在浏览器时能自动连接到Unity Profiler。

  1. 微信开发者工具小游戏Profile 使用转换脚本导出微信小游戏包并启动小游戏,微信小游戏将自动连接到Unity Profiler

  2. 真机调试 Android或iOS启动之后将使用"ws://ip:port"自动连接到“Unity Profiler”, 如果无法连接请关注vConsole输出的IP:Port是否可达。 如果需要手工调整端口可通过修改以下代码:

一般来说,保持端口为54998,如修改端口需重启websocketfy.js: windows: "$UNITY_PATH/Editor/Data/Tools/nodejs/node.exe" "$UNITY_PATH/Editor/Data/PlaybackEngines/WebGLSupport/BuildTools/websockify/websockify.js" 0.0.0.0:port localhost:34999 mac: /Applications/Unity/Hub/Editor/$Verson/Unity.app/Contents/Tools/nodejs/bin/node /Applications/Unity/Hub/Editor/$Verson/PlaybackEngines/WebGLSupport/BuildTools/websockify/websockify.js 0.0.0.0:port localhost:34999 -vv

附录:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/RenderOptimization.html b/Design/RenderOptimization.html new file mode 100644 index 00000000..671bb66b --- /dev/null +++ b/Design/RenderOptimization.html @@ -0,0 +1,25 @@ + + + + + + RenderOptimization | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

RenderOptimization

  • 本文档主要关于 Unity WebGL 游戏在微信手机平台的渲染性能优化一些建议

WebGL1.0 还是 WebGL2.0

  • WebGL2.0 基本兼容 WebGL1.0,但并不是完全向后兼容 WebGL1.0
  • WebGL2.0 对系统有要求,用户占比和兼容性不如 1.0,可参考 WebGL2.0渲染支持说明
  • 对 Unity 而言,WebGL1.0 和 WebGL2.0 生成的 Shader 是不一样,各有优缺点
    • WebGL2.0 是用了 Uniform Buffer 来管理UnityPerDraw 和 UnityPerMaterial 属性,Unity内置Shader 有大量可能游戏用不上的冗余属性
    • WebGL1.0 用不到的材质属性会剔除掉
  • 如果游戏内容不多,材质比较简单,游戏不依赖 GPU Instancing 等 WebGL2.0 的特性,那么 WebGL1.0 也足够
  • 如果游戏需要依赖 GPU Instancing等 WebGL2.0 的特性,那么必须要用 WebGL2.0
  • 并非用 WebGL2.0 的性能就一定比 WebGL1.0 的好,不一定,有条件的建议分别打对应的包,对比一下性能

选择哪种渲染管线

  • 微信小游戏 推荐引擎版本 都支持 SRP管线
  • 现有的游戏原来是什么管线就什么管线,这里主要针对新开发的小游戏
  • Unity 2019.3开始支持 URP 管线
  • 如果是新开发的游戏,Unity 内置管线、SRP、URP、HDRP 到底怎么选 ?
    • 内置管线,适用于小游戏
      • 优点:默认选项,拿来即用,功能全面
      • 缺点:固定,不灵活,面向全平台,不够精简
    • SRP (Scriptable RP),适用于小游戏
      • 优点:灵活,完全通过 C# 脚本定制渲染管线,冗余功能很少
      • 缺点:不能直接拿来用,需要通过 C#脚本开发渲染管线,对开发者要求高
    • URP (Universal RP) 基于 SRP 的通用渲染管线,适用于小游戏
      • 优点:拿来即用,简单配置即可,
      • 缺点:通用,冗余功能较多,不够精简
    • HDRP 高清渲染管线,适用于主机平台,不适用于小游戏
  • 对于大多数开发者,建议使用 URP,当然 URP复杂的特性尽量少用,因为小游戏对性能要求还是比较高,
    • 对于用不到的特性,可以在 URP的基础上定制
  • 对于对性能要求高且熟悉渲染的开发者,可以使用 SRP定制管线

线性颜色空间 还是 Gamma 颜色空间

  • 目前 Unity 只有在 WebGL2.0 才支持 线性颜色空间,如果是选择 WebGL1.0 必然是 Gamma 颜色空间
  • 那么选择了 WebGL2.0,到底用线性还是Gamma 颜色空间呢?
  • 光照计算尤其是 PBR需要在线性颜色空间进行,如果是 PBR渲染,线性颜色空间比较方便
  • 但线性颜色空间,Unity会多一个全屏 Gamma矫正的 Pass,对性能会有比较明显的影响
    • 这个问题已经反馈给 Unity了,至少 Unity2021.3.23 的版本还是存在这个问题
  • 因此,除非是 PBR光照,其余的都建议选择 Gamma 颜色空间

渲染性能优化的一些建议

光照和阴影

  • 如果没有光照和阴影的需要,确认游戏的光照(包括环境光)和阴影都是关闭的
    • 能不用光照,尽量不用,材质可参考 URP 的 Unlit shader
  • 如果需要光照和阴影的,那么尽量用烘焙 Lightmap,避免用实时光照
  • 需要用到实时光的,一般建议只用一盏方向光,不要用额外的实时光
    • 额外的光照信息可以烘焙到 Lightmap
    • 光照材质尽量简单,避免使用 PBR光照,可参考 URP 的 SimpleLit Shader
    • Unity 的阴影默认使用 Cascade Shadow Map的 方案
      • 阴影生效的距离(离摄像机的)尽量设置小一些,远处物体不用阴影也难观察出来,这样阴影贴图可以小一点
      • 阴影贴图的大小越小越好,建议从256尝试是否合适,逐渐调大,最好不要超过1024
      • Cascade 级联数也是建议 1~2 级,1级能满足要求是最好的
      • 投射阴影 和 接受阴影的物体要区分开,有需要投射或接受阴影的物体才去设置
    • 如果地表是平的,那么用投射平面阴影的方式来表现阴影,不用 Unity的阴影方案,这样性能更好
  • 烘焙 Lightmap 的时候可能会生成环境反射立体贴图,已经有 Lightmap,尽量不要再用环境反射立体贴图

材质和Shader

  • 避免使用 Unity默认的材质,当Inspector窗口的材质缺失,Unity会自动使用内置的默认材质
    • 可以通过 Unity 官网下载对应版本的 builtin_shaders 源码
    • 看下默认材质Shader 是什么,复制一份并尽可能简化,用来新建材质替代默认的材质
    • 好处是:默认的材质一般会有些冗余的设置,简化过的材质对性能更好,而且方便修改
  • 避免使用 Mask 材质 (像 Unity Mask 和 RectMask2D 组件)
    • 常见的头像用圆来做一个Mask 遮罩
    • 通常 Mask 可能会打断 UI系统的合批,或者对硬件优化不友好
    • 这种可以用网格化一个圆作为替代方案,在移动端性能更好
  • 材质Shader 可能有 Stencil 蒙版的设置,一般是为了实现遮罩等效果用的,如果不需要建议在 Shader中注释掉 Stencil 相关代码,否则可能会有额外的API 调用开销
    • 在 iOS 15.4 系统,使用 Stencil 可能会导致一些渲染异常问题
  • 避免使用 if、for 这种结构化语句
    • if 语句 可以尝试使用 step 内置函数替代,如果实在代替不了,而且 if语句比较短小,那也可以用,但如果if 语句很复杂的就不建议使用
  • 如果用了 Shader Graph,建议检查一下最终生成的 shader代码,避免上述的 if、for 这种语句
  • 注意浮点精度的使用,如果能用半精度 half 尽量用半精度,一般涉及到坐标值、uv 的定义或计算可能需要全精度的,其他的像颜色、法线等一般半精度就够了
  • 减少不必要的材质变体
    • 检查 shader代码的#pragma multi_compile#pragma multi_compile_local#pragma shader_featureshader_feature_local 语句,如果有用不到的关键字要记得删除掉
    • 详情可参考Unity 着色器变体和关键字说明

纹理设置

  • 建议材质引用的纹理数尽量控制在 5 张以内
  • 纹理的大小当然越小越好,对于单图,尽量不要超过 512;对于图集来说尽量不要超过1024
  • 尽量使用压缩纹理,建议用 astc压缩,它有多种压缩格式,在满足画质情况下,尽量选择压缩比大的
    • 例如 astc88 比 astc44 压缩比更大,而且满足画质要求,那么就选择 astc8*8
  • UI 一般考虑效果,不用压缩纹理,但有些 UI纹理的精细度可能要求不高,是可以尝试用压缩纹理,这样对内存、游戏加载速度都会有提升
  • 对于图标等小图片,尽量合并成 Atlas 图集
  • 如果启用 WebGL2.0,对于相同尺寸的纹理,可以考虑合并成 Texture2D Array

网格和蒙皮

  • 如果游戏场景比较复杂,总面数比较高,比如超过 50万面,这时候要留意下顶点着色会不会成为瓶颈
    • 可以打个 App包,如果是 iOS包,那么可以通过 XCode抓帧工具,分析场景帧 Vertex Shading 和 Pixel Shading 的耗时,一般都是 Pixel Shading 占大头,如果 Vertex Shading 的时间和 Pixel Shading 差不多,意味着 Veretx Shading 有优化空间,可以尝试优化 顶点 Shader 或 降低总面数
  • 如果有顶点蒙皮,像 Unity WebGL 目前还不支持 GPU skin,也不支持 CPU 多线程,如果顶点过多或骨骼数过多,很容易导致 CPU skin 成为瓶颈
    • 避免瓶颈的手段有: 减少模型面数(可以使用Mesh LOD)、减少骨骼数量、或者减少顶点的受影响的骨骼权重数
    • 后续的 Unity版本 可能会支持 GPU skin 或 多线程,但仍然是需要注意 skin 的开销

DrawCall 相关

  • Draw Call 的数量建议控制在 200个以内,对于大型游戏可以适当放宽一点,但尽量不要超过250个
  • Unity 的统计里有 SetPass Call的概念,它与 Draw Call 是不同的概念,SetPass Call指的切换渲染状态的次数,SetPass Call 应当明显小于 Draw Call 数,这样表示材质复用的概率高
  • 如果使用 WebGL2.0,尽量使用 GPU Instancing 实例化来合并 Draw Call
  • 如果使用 WebGL2.0,URP 默认是开启 SRP Batcher,它并不能减少 Draw Call的数量,它的目的是减少渲染状态的切换。如果渲染状态比较多,那么 SRP Batcher 收益应该会比较明显,建议开发者具体测试一下 SRP Batcher的收益情况 (对比帧率、CPU利用率和内存使用).

摄像机 Camera

  • 避免同时启用多于 2个的Camera,一般就主 Camera,至多额外加一个 UI Camera
    • 如果只用一个 Camera 绘制主场景和UI,那是最好,能够减少渲染的开销

渲染分辨率

  • 如果手机发烫比较严重,可以适当调小一点渲染分辨率,看发烫是否有改善
    • 以 iOS为例,如果dpr(Device Pixel Ratio)默认是3.0,那么可以尝试设置 [2.0 ~ 2.5]
    • 这个方法可能会牺牲一点画质效果,需要画质和性能之前取一个平衡
    • 如需强制设置iOS的设备分辨率可以在【导出面板-更多配置项-Project Conf】中修改配置 IOS Device Pixel Ratio 为 2:

后处理

  • 后处理的销不小,加上 WebGL 游戏在可用内存和性能对比 App 有差距
  • 不建议在微信小游戏使用后处理,除非后处理对画质很关键或游戏性能能支撑起后处理的开销

特效

  • 避免大量的大屏幕的半透明特效重叠导致的 Overdraw,尤其是战斗释放技能时候,容易出现这种情形,需要留意

参考文档

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/ReportStartupStat.html b/Design/ReportStartupStat.html new file mode 100644 index 00000000..fed4d559 --- /dev/null +++ b/Design/ReportStartupStat.html @@ -0,0 +1,93 @@ + + + + + + 启动留存数据上报统计 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

启动留存数据上报统计

一、概述

在小游戏环境下,玩家对启动时长与体验非常敏感(尤其从“广告”等买量场景进入的玩家)。开发者往往需要分析玩家从点击到进入游戏核心玩法的整个过程流失率。 Unity Loader的数据统计功能如下:

  1. Unity Loader插件自动统计了代码包、首包资源、代码编译、引擎与首场景初始化,无需手动上报
  2. 通过C# SDK接口让开发者上报自定义启动阶段,分析每个环节可能存在的流失

二、上报广告信息

为了帮助开发者分析广告渠道的留存数据,达到最好的买量效果,Loader提供了上报广告参数的能力,用于区分不同广告位/广告类型/素材类型的数据。

如何上报?

广告买量时,带上广告相关自定义参数,Loader自动上报 eg: adSpaceType=1&adType=1&materialType=1

  • adSpaceType: 广告位类型;一个广告位可以投放不同类型的广告
  • adType: 广告类型;一个广告类型可以投放不同素材
  • materialType: 素材类型

取值范围:1-200; 默认为0

三、上报自定义阶段

为了详细统计玩家的流失情况以便开发者进行优化,我们拆分了三个部分。 其中自动上报为Unity Loader自动完成开发者无需关注,但自定义阶段启动加载完成需开发者主动调用接口进行上报。详细接口可参考C# SDK中的WX.cs,文档可查看启动场景上报分析wx.reportScene

1. 游戏完成所有加载时上报

当游戏完成所有加载阶段,进入核心玩法时(如进入新手引导或大厅)调用

C#
      WX.ReportGameStart()

2. 上报当前自定义阶段错误信息

C#
      WX.ReportGameSceneError(int sceneId, int errorType, string errStr, string extJsonStr)

sceneId同启动场景上报分析

errorType取值:[0,10000]

示例:

C#
      // 假设Loading场景中A资源完成为1001, 需要知道完成的留存率
+      WX.ReportScene(new ReportSceneParams()
+      {
+            sceneId = 1001,
+            costTime = 100,
+            metric = new Dictionary<string, string>()
+            {
+                  { "testkey1", "1" },
+                  { "testkey2", "2" }
+            },
+            dimension = new Dictionary<string, string>()
+            {
+                  { "testkey1", "testvalue1" },
+                  { "testkey2", "testvalue2" }
+            },
+            complete = (res) =>
+            {
+                  Debug.Log("ReportScene complete" + res);
+            },
+            success = (res) =>
+            {
+                  Debug.Log("ReportScene success: " + res);
+            },
+            fail = (res) =>
+            {
+                  Debug.Log("ReportScene fail: " + res);
+            }
+      });
+      
+      // 所有加载完成,玩家可以交互(如休闲游戏已进入核心玩法、MMO游戏进入创角时), 需要知道留存率
+      WX.ReportGameStart();

四、获取Loader启动阶段

从启动时序可以知道Loader启动阶段分为以下五个阶段

  • wasm代码包下载
  • wasm编译
  • 首包资源下载
  • 首包资源读取
  • 引擎初始化(callmain)

当业务侧需要使用Loader启动数据时,可以使用Loader暴露的进度事件上报到自己的系统

tips: 目前只支持js调用

js
gameManager.onLaunchProgress = (e) => {
+      // e: LaunchEvent
+      // interface LaunchEvent {
+      //   type: LaunchEventType;
+      //   data: {
+      //     costTimeMs: number; // 阶段耗时
+      //     runTimeMs: number; // 总耗时
+      //     loadDataPackageFromSubpackage: boolean; // 首包资源是否通过小游戏分包加载
+      //     isVisible: boolean; // 当前是否处于前台,onShow/onHide
+      //     useCodeSplit: boolean; // 是否使用代码分包
+      //     isHighPerformance: boolean; // 是否iOS高性能模式
+      //   };
+      // }
+      if (e.type === launchEventType.launchPlugin) {
+
+      }
+      if (e.type === launchEventType.loadWasm) {
+
+      }
+      if (e.type === launchEventType.compileWasm) {
+
+      }
+      if (e.type === launchEventType.loadAssets) {
+
+      }
+      if (e.type === launchEventType.readAssets) {
+
+      }
+      if (e.type === launchEventType.prepareGame) {
+
+      }
+}

类型枚举

js
export const launchEventType = {
+  launchPlugin: 0, // 插件启动
+  loadWasm: 1, // 下载wasm代码
+  compileWasm: 2, // wasm代码编译
+  loadAssets: 3, // 下载首资源包
+  unzipAssets: 4, // 解压首资源包
+  readAssets: 5, // 读取首资源包
+  prepareGame: 6, // 引擎初始化
+};

五、获取数据统计

请注意!需前往【公众平台 - 能力地图 - 生产提效包 - 快适配 】开通后,方可查看数据

数据报表包含Unity Loader自动上报与开发者自定义阶段。关注总体流失漏斗以确定需要优化的方向,同时分阶段的耗时分布有利于帮助我们分析该阶段的对应耗时的用户占比。

数据报表统计分析请参考文档启动场景上报分析-数据分析 进行查看。

注:

  1. 若使用的 转换插件版本<202211101011(对应Unity Loader版本<1.1.2),数据统计报表需要联系我们获取。
  2. 数据报表数据未来会开放到《小游戏数据助手》。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/ResourcesLoading.html b/Design/ResourcesLoading.html new file mode 100644 index 00000000..bf96211e --- /dev/null +++ b/Design/ResourcesLoading.html @@ -0,0 +1,24 @@ + + + + + + 资源按需加载概述 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

资源按需加载概述

​ 区别于原生 APP 游戏通常安装与启动时将资源都下载完成,小游戏需要做到“即点即玩”,启动仅能加载少量资源,其余部分都必须放CDN进行延迟加载,如何合理与高效地进行资源按需加载是非常重要的事情。

​ 目前分包将基于 AA/AB 包的按需加载,以及 Unity Instant Game 三种方案。值得注意的是,微信小游戏环境中不支持对本地的 Bundle 进行加载,因此无论哪种方案最终都采用上传 CDN 方式在游戏运行时异步按需下载。

AA包、AB包、Instant Game 方案选择说明

相关手册:AA(Addressable) 进行资源按需加载AB(AssetBundle)进行资源按需加载Instant Game 实践指南

​ AA/AB 包是常规的分包解决方案,关于他们的选择对于轻度游戏来说两者没有特别要求,倒是功能强大的 AA包 使用门槛更低一些,而对于重度游戏,平台目前所反馈到的结论是使用 AB包 的性能要比 AA包 更好,AA包较大项目时生成的未压缩的 catalog 较大,加载效率低,改用 AB包后,效果提升明显。

​ Instant Game 是由 Unity 官方提供的自动加载方案,有关 Instant Game 详细内容可查阅 Instant Game 实践指南,本节说明三种方案的差异:

常规资源加载方案(AA/AB包)Instant Game 工具
技术原理基于 AA/AB 包的异步资源管理Unity引擎底层资源异步加载策略
引擎版本不限制目前需指定版本 2021.2.5
转化人力适中较少/适中
懒加载资源类型常见纹理资源纹理、模型、骨骼动画、音频资源
自选CDN支持不支持(需使用腾讯云CDN服务)
必要的代码修改通常需要适配较少/达到最佳仍需要
首资源包处理通常需要适配默认不需要/达到最佳仍需要

选择建议:

  • 游戏工程本身已采用完善的 AA/AB 资源管理,建议继续沿用常规资源加载方案,且有助于后续压缩纹理等优化工作的进行有效提升游戏运行性能;
  • 原生 APP 版本游戏完全没有做资源的拆包,希望减少游戏的转化周期,使用 Instant Game 方案可以快速完成转化工作。

各类型游戏的资源优化建议

​ 不同的游戏所需要的性能不尽相同,转化过程中的复杂度以及关注的侧重点自然也是不同的。游戏开发者可以根据自己游戏的类型进行不同的优化策略来提升实际的游戏体验,本节总结的列举开发者对不同类型的游戏应重点关注的优化内容。

原生 APP 手游已使用 AB/AA 包等资源按需加载的游戏**

特点:游戏原本发布原生 APP 平台,将游戏资源以 AA/AB 包方式存放于磁盘本地,在游戏运行时适宜的位置进行加载/卸载。

优化建议:

  • 将 AA/AB 资源包使用CDN远程加载,及时卸载不再使用的资源包释放内存,同时结合压缩纹理优化减少包体积。
  • 当APP异步方式使用AB时(如AssetBundle.LoadAssetAsync),调整为从UnityWebRequest下载创建AB即可,具体请参考使用 AssetBundle 进行资源按需加载
  • 当APP同步方式使用AB时(如AssetBundle.LoadFromFile, AssetBundle.LoadAssetAsync),调整为UnityWebRequest异步接口创建AB,并使用LoadAssetAsync等异步接口。异步接口修改可能需要涉及到业务逻辑改造,工作量极大时也可结合使用 Unity Instant Game 进行资源按需加载将部分资源自动剥离。
  • AssetBundle无需再使用本地文件系统缓存和版本更新,小游戏适配插件已自动进行缓存,请参考资源缓存
  • 大型游戏不建议使用Addressable,因为当key达到几千个之后构建的资源索引文件(catalog)往往会非常大,对下载和解析造成较大压力。

原生 APP 手游未使用 资源按需加载 的轻度游戏

特点:游戏总包体积较小,“关卡”休闲类小游戏等。

优化建议:

原生 APP 手游未使用 资源按需加载 的中重度游戏

特点:游戏较大,但未使用 AA/AB 包方式进行分包管理,或较少使用,场景中必须与非及时资源在启动时一并加载。

优化建议:

  • 该类游戏需要耐心调优,需将游戏内资源逐一拆分,推荐使用 AB包 方式进行按需加载与及时资源释放,对多 Scene 时对后续场景使用 AA/AB分包方式载入。
  • 做好资源加载过程中的UI上的进度条反馈。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/SDKInstaller.html b/Design/SDKInstaller.html new file mode 100644 index 00000000..07e0fdd4 --- /dev/null +++ b/Design/SDKInstaller.html @@ -0,0 +1,25 @@ + + + + + + 微信SDK安装 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

微信SDK安装

为兼容历史团结/Unity版本的使用,微信小游戏团队将SDK分为如下两种模式安装使用。

方法一(推荐):Package 方式安装

目前团结引擎、Unity 2019及以后版本推荐使用 Package 方式安装WXSDK。

安装指南

打开游戏工程 -> Unity/团结引擎 Editor 菜单栏 -> Package Manager -> 右上方 “+” -> Add package from git URL URL地址为:

https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git

或国内Gitee镜像:

https://gitee.com/wechat-minigame/minigame-tuanjie-transform-sdk.git

即可完成SDK导入。

方法二:资源包方式安装

对于 Unity 2018 版本引擎使用资源包方式可安装 WXSDK

安装指南

如果当前版本暂不支持 PackageManager 导入,请 下载UnitySDK 后导入游戏工程中。

目录结构说明

我们希望SDK与工程代码解耦,如此一来也更方便开发者的代码版本维护。因此 PackageManager 模式下,微信SDK内容将不再存放在游戏工程的Assets目录中。为兼容需要,仍然会自动在 Assets 目录下创建 WX-WASM-SDK-V2 数据目录,如需保持相关的应用配置应始终保留该目录内容。

常见问题

1.游戏工程可以导出但在微信开发者工具运行提示报错:

常见的情况是发生在如空项目或游戏代码中从未使用WXSDK的任何Runtime能力时,引擎导出项目将微信Runtime包裁剪,解决办法是在游戏合理位置增加对WXSDK的使用即可。 如:

c#
// 无直接的API能力调用可使用读取系统信息等API
+WX.GetSystemInfo(new GetSystemInfoOption());  // 读取SystemInfo

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Salon.html b/Design/Salon.html new file mode 100644 index 00000000..5e7129a1 --- /dev/null +++ b/Design/Salon.html @@ -0,0 +1,24 @@ + + + + + + 技术沙龙 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/ShowCase.html b/Design/ShowCase.html new file mode 100644 index 00000000..76162db9 --- /dev/null +++ b/Design/ShowCase.html @@ -0,0 +1,25 @@ + + + + + + 转换案例 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

转换案例

文档为使用Unity WebGL适配小游戏方案的部分上线游戏。

转换案例目的是分享学习,若作者认为不适合分享,请联系联系我们删除。 如开发者希望分享案例,也可通过联系我们添加。

无尽冬日

SLG品类,探索冻土,重建家园

九梦仙域

重度MMO品类,仙侠为题材,主要讲述在仙域大陆上,玩家扮演一个攀星阁学艺有成,不断提升自身,立志阻挡魔族入侵的游戏。

地铁跑酷

超好玩的3D跑酷手游!简单的上手操作,丰富的游戏画面,众多的城市场景,让你爱不释手!

谜题大陆

一款独具创新的魔幻三消策略小游戏,神奇的消除战争之旅!带你探索不一样的魔幻体验!

三国吧兄弟

鱼吃鱼

剑心吟

重度MMO品类

巨兽战场

重度SLG品类, 3D恐龙自由捕捉

小小蚁国

2023年度热门休闲小程序《小小蚁国》,建立你的地下王国!

翡翠大师

模拟经营游戏,玩家将体验到富有风险的翡翠原石选石过程,通过切石,设计,抛光的流程获得精美的翡翠雕刻成品,让自己的翡翠珍宝展馆发展壮大,熠熠生辉;在得到成就感的同时收获相关的翡翠知识。

超能世界

大侠不哭

喜欢武侠世界,曾梦想惩恶扬善、和志同道合的伙伴携手闯仗剑走天涯!

我叫MT2

由乐动卓越研发的精美3D手游,延续了传统《我叫MT》的经典特色。钓鱼挖矿,外域探险玩法都将为您呈现独一无二的掌中魔幻世界!

葫芦娃大作战

大圣顶住

银河战舰

守护球球

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Startup.html b/Design/Startup.html new file mode 100644 index 00000000..11c9fe00 --- /dev/null +++ b/Design/Startup.html @@ -0,0 +1,24 @@ + + + + + + 小游戏启动流程与时序 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

小游戏启动流程与时序

启动加载时序

Unity WebGL转换的小游戏主要依靠Unity Loader进行初始化,典型的流程如下图所示:

Unity Loader工作流程

关键过程:

  1. 启动准备阶段有两个处理分支:资源与代码分包处理,两者并行。
  2. 资源(data)处理:下载、解压并保持在内存,资源包括:构建场景及依赖、Resource目录所有资源、Unity默认内建资源
  3. 代码分包(wasm.code.br)处理:下载代码分包,解压到内存、编译与实例化
  4. 完成准备阶段后进入Unity引擎初始化与首场景加载

QA:

  1. 有哪些文件需要放CDN服务器? 首资源包:webgl/ProjectName.data.unityweb.bin.txt 资源分包:Adressable/AssetsBundle生成的文件

  2. 资源(data)或资源包是否需每次下载? 为加快二次启动,默认loader再次启动时资源(首包资源或资源分包)将直接使用本地缓存。如需手动删除缓存可在真机中小游戏下拉历史栏将小游戏删除。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/StartupOptimization.html b/Design/StartupOptimization.html new file mode 100644 index 00000000..61c81292 --- /dev/null +++ b/Design/StartupOptimization.html @@ -0,0 +1,24 @@ + + + + + + 提升Unity WebGL游戏启动速度 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

提升Unity WebGL游戏启动速度

一、 为什么要做启动优化

1.1 小游戏与手游APP的启动差异

微信小游戏具有“即开即用“的特性,手游APP则往往需要较长时间的下载。小游戏玩家对于启动时长更为敏感,因此过长的启动时间将导致用户显著流失。

1.2 优化的目标与标准

目前普通小游戏普遍启动时间为7~10s,而如果不经优化的Unity WebGL游戏启动会是该时间的2-3倍以上。我们建议开发者将启动优化作为上线前最为重要的事项。

二、分析小游戏启动速度

2.1. 查看启动耗时

通过修改unity-namespace.js中hideTimeLogModal为false,显示timelog开发者可以看到小游戏目前的启动首屏时长:

要知道各个阶段的含义,我们必要理解启动流程

小游戏启动主要由三部分影响:

  1. 首包资源下载
  2. WASM代码下载和编译
  3. 引擎初始化与开发者首帧逻辑

建议首屏启动时间控制在5~10s甚至更短

2.2 分阶段耗时

2.2.1 首资源包下载与体积

首包资源(webgl/Build目录下的data文件)主要有以下组成:

  • unity default resources文件,引擎默认资源,如Arial字体,默认mesh,纹理等
  • il2cppmetadata, C#代码使用il2Cpp生成cpp代码时,生成的类,方法等信息
  • unity builtin_extra, always include的shader
  • BuildSettings中所有active的场景
  • Resources文件夹中的资源,以及其中的资源引用到的其他资源
  • 全局设置及引用到的资源,如splash图片等

可使用AssetStudio查看文件内的所有资源。

首次下载或更新首资源包时,需要在小游戏的启动前期下载,因此文件大小极为影响游戏的启动速度。

  1. 网络条件绝大部分为wifi或4G(另,微信广告可指定网络条件)
  2. 玩家平均下载速度约2MB/s
  3. 微信用户存在不少<300KB/s的低网速玩家
  4. 务必对首资源包压缩: 转换面板勾选“压缩首资源包” 或 CDN管理后端针对首资源包(后缀.txt)“开启gzip/br压缩“
  5. 中文显示需要自定义字体,打包在首资源包或Bundle;请尽量使用2~3MB以内的精简字体以免影响游戏启动速度

建议: 务必对首资源包进行压缩传输,使用微信开发者工具的network标签确认传输量,网络传输大小应控制在3~5MB

2.2.2 WASM代码下载和编译

WASM分包的大小会直接影响代码下载时长以及程序初始化编译的时间,关于WASM代码对启动速度的影响,开发者需要注意:

  1. 转换工具会将Unity WebGL包自动进行br压缩(压缩至原code包的20%)
  2. WASM代码下载与首包资源并行下载,因此占用下载带宽
  3. WASM编译需要CPU资源,对于低端机来说时间依然可观

我们建议原始代码包(webgl/Build目录下的code文件)不超过30MB, 建议开发者勾选"Strip Engine Code"并设置"Managed Stripping Level"为High。同时,强烈建议开发者可以使用代码分包工具将代码包减少到原始尺寸的到1/3。如果使用Unity2021以上版本,可更改PlayerSettings面板IL2CPP选项为更小尺寸(SIZE)以减少函数量。

2.2.3 引擎初始化与开发者首帧逻辑

在timelog中呈现的首场景耗时即为引擎初始化与开发者首帧逻辑,关于该阶段耗时,开发者需要注意的是:

  1. MonoBehaviour脚本的首帧Start/Awake应足够少逻辑,优先将画面呈现
  2. 初始场景不宜过大,通常呈现Splah场景即可
  3. 初始场景中需要后续主场景或配置加载时可采取分帧策略,切勿在Start/Awake阻塞。
  4. 对于计算耗时 请使用Android CPU Profiler性能调优分析每一帧的耗时部分。

我们建议开发者使用预下载功能,该功能可以利用此阶段的网络空闲期进行资源下载。

2.2.4 游戏内资源按需加载

前面我们提到开发者需要将资源从首包分离以较少首屏加载时间,同理,而对于其余的资源开发者最好使用按需加载的方式进行加载,减少玩家进行核心玩法的等待时间。 优化可参考 使用Addressable Assets SystemAssetBundle进行资源按需加载。

2.3 优化总览

我们总结下启动时序以及开发者、平台提升启动性能的优化事项:

三、常用启动优化技巧

当分析出小游戏需要进行启动优化时,请继续阅读:

四、常用启动优化工具

4.1. AssetStudio(推荐)

https://github.com/Perfare/AssetStudio

一款开源的资源查看工具,可以检查data首包以及AssetsBundle(或新Addressable)的资源内容,对于分析打包的资源正确性和冗余具有很好的帮助。

4.2 BuildReportTool(推荐)

https://assetstore.unity.com/packages/tools/utilities/build-report-tool-8162?locale=zh-CN

很好的前端用于查看Unity编译信息,BRT显示了编译时包括的每个资源占用的存储空间以及未使用资源情况。

4.3 Asset Hunter

https://assetstore.unity.com/packages/tools/utilities/asset-hunter-pro-135296

资源清理插件,可将项目中无用资源清理

4.4 Unity Addressable Assets System

https://docs.unity3d.com/Packages/com.unity.addressables@1.16/manual/index.html Unity全新资源管理流程

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Summary.html b/Design/Summary.html new file mode 100644 index 00000000..21e8c275 --- /dev/null +++ b/Design/Summary.html @@ -0,0 +1,24 @@ + + + + + + Unity WebGL小游戏适配方案概述 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Unity WebGL小游戏适配方案概述

一、技术原理

Unity的BuildTarget支持WebGL平台,WebGL导出包是基于WebAssembly技术运行在浏览器环境。 为了能让导出包运行在微信小游戏环境,我们提供了以下支持:

  • 开发阶段:提供平台能力的C# SDK帮助开发者快速对接平台能力
  • 导出阶段:转换打包工具,进行Unity WebGL胶水层适配,直接转换成小游戏包
  • 运行阶段,提供WebAssembly基础能力,微信底层接口支持

二、接入流程

接入流程请参考文档Unity WebGL微信小游戏转换指南

三、参考资料

  1. https://emscripten.org/
  2. https://docs.unity3d.com/Manual/webgl-gettingstarted.html
  3. https://forum.unity.com/forums/webgl.84/
  4. http://webassembly.org.cn/getting-started/developers-guide/
  5. https://developer.mozilla.org/zh-CN/docs/WebAssembly/C_to_wasm

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Symbol.html b/Design/Symbol.html new file mode 100644 index 00000000..18ac01da --- /dev/null +++ b/Design/Symbol.html @@ -0,0 +1,28 @@ + + + + + + Symbol 相关 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Symbol 相关

Tool

开发者工具或者线上打印出来的堆栈,一般都是 wasm 函数 id,需要通过 symbol 映射到函数名,才能用于定位问题

这里提供了一个小工具用来替换函数 id,用法如下:

比如以下这段堆栈

at Object.WXUncaughtException (https://usr/game.js:108:1264)
+    at abort (https://usr/game.js:593:247583)
+    at j88421 (wasm-function[67190]:0x13a062b)
+    at j88421 (wasm-function[44572]:0x801bd1)
+    at j23511 (wasm-function[9866]:0x432503)

将这段内容保存到文件,和 symbol 文件一起传给工具处理

node tools/rewrite_exception_symbol.js exception.txt webgl.wasm.symbols.unityweb

symbol 文件一般会自动生成在 minigame 目录

Unity 2021 的引擎暂时还不支持导出 symbol,因此需要手动跑工具生成,导出插件导出到 webgl 时的 console 信息有说明要如何操作

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Transform.html b/Design/Transform.html new file mode 100644 index 00000000..8050ebab --- /dev/null +++ b/Design/Transform.html @@ -0,0 +1,60 @@ + + + + + + 转换工具导出微信小游戏 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

转换工具导出微信小游戏

一、Unity导出WebGL

添加需要导出的scene

建议仅勾选Loading场景,后续场景使用AssetsBundle/Addressable进行按需加载。

二、适配小游戏

2.1 转换小游戏

顶部菜单栏 点击 微信小游戏 -> 转换小游戏, 填写相应参数,点击生成并转换按钮 ,等待转换完成。

其中:

  1. 必须
  • 游戏appid:小游戏的appid(勿用测试appid, 注册开通小游戏请查阅快速上手 )
  • 游戏资源CDN:首资源所在HTTP或CDN地址;运行时Application.streamingAssetPath="CDN/StreamingAssets"
  • 导出路径:转换后文件目录
  1. 可选
  • 小游戏项目名:开发者工具中展示的小游戏项目名
  • 首包资源加载方式:CDN-使用CDN下载首包资源;小游戏包内-首资源放在小游戏代码包内(总上限为20MB)
  • 加载阶段视频URL:启动需要一定耗时,在启动加载时会循环播放这段视频,视频格式请参考视频规范
  • 启动背景/视频封面图:启动阶段背景图片;如果配置了加载阶段视频URL,则作为视频封面。
  • 游戏方向:游戏是横屏还是竖屏,可选值参考deviceOrientation
  • 不自动缓存文件类型:游戏资源CDN下不自动缓存的文件类型,具体参见AssetBundle缓存
  • Bundle名中Hash长度:自定义AssetBundle名中Hash长度用于缓存控制,具体参见AssetBundle缓存
  • 预下载列表:网络空闲时预下载的资源,使用预下载
  • SDK功能选项:好友关系链
  • 调试编译选项

2.2 了解转换后目录结构

在转换完成后,会在导出路径下生成如下目录

bash
.
+├── minigame
+└── webgl
  • minigame为小游戏项目
  • webgl为unity导出为webgl后的资源和代码目录

2.3 资源部署

转换完成后,参照小游戏资源部署章节进行资源部署,并了解启动Loader在加载资源时的缓存逻辑。

2.4 小游戏预览

  1. 下载小游戏开发者工具 微信开发者工具

需要下载,稳定版 Stable Build,非小游戏版!

  1. 导入项目 参考小游戏快速开始

导入转换后的minigame目录

  1. 工具预览

注意:

项目使用了小游戏Unity适配插件,若小游戏是第一次使用本插件,在开发者工具会报错提示插件未授权

请前往mp后台-能力地图-生产提效包-快适配,开通使用

  1. 真机预览 点击预览,扫码二维码预览即可。

请不要使用真机调试!! 请不要使用真机调试!! 请不要使用真机调试!!

三、使用脚本集成到自己的构建系统

如果你希望将导出插件集成到自己的发布流程,想脚本调用的话,可修改 Assets/WX-WASM-SDK/Editor/MiniGameConfig.asset配置,然后调用WXEditorWindow 的 DoExport方法导出小游戏

var win = new WXEditorWindow();
+win.DoExport();

MiniGameConfig.asset支持的配置

与转换面板配置有对应关系的配置项

// 基本设置
+Appid -- 小游戏appid
+CDN -- 游戏资源CDN
+projectName -- 小游戏项目名
+Orientation -- 游戏方向
+maxStorage -- 最大内存,修改此值需要联系研发助手开通权限,否则无效
+DST -- 导出路径
+// 启动Loader设置
+bgImageSrc -- 背景图/封面图
+VideoUrl -- 加载阶段视频URL
+assetLoadType -- 首包资源加载方式
+bundleExcludeExtensions -- 不自动缓存文件类型
+bundleHashLength -- bundle名中hash长度
+// 预下载
+preloadFiles -- 预下载文件列表,用;分隔
+// SDK功能
+UseFriendRelation -- 使用好友关系链
+// 调试编译选项
+DevelopBuild -- Development Build
+AutoProfile -- Autoconnect Profiler
+ScriptOnly -- Scripts Only Build
+profilingFuncs -- Profiling Funcs
+Webgl2 -- WebGL2.0
+DeleteStreamingAssets -- DeleteStreamingAssets

不常用配置

使用说明参考Loader配置

// 资源加载与缓存
+dataFileSubPrefix: 配置首包资源加载路径
+bundlePathIdentifier: URL中包含特定标识符时需要自动缓存,用;分隔
+defaultReleaseSize: 达到缓存上限时默认额外清理的存储大小,用;分隔
+needCacheTextures: 是否开启纹理缓存
+texturesPath: 纹理存储路径
+texturesHashLength: 纹理中hash长度
+// 启动界面
+loadingBarWidth: 加载进度条宽度
+HideAfterCallMain: 是否初始化完成立即隐藏封面

四、常见问题

请查阅技术常见问题QA

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UnityProfiler.html b/Design/UnityProfiler.html new file mode 100644 index 00000000..2257abdc --- /dev/null +++ b/Design/UnityProfiler.html @@ -0,0 +1,30 @@ + + + + + + 使用Unity Profiler性能调优 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

使用Unity Profiler性能调优

  1. 导出选项时勾选"Development Build"与"Autoconnect Profiler"
  1. 打开Unity-Window-Analysis-Profile窗口

Unity将自启动监听端口34999等待调试链接,对于WebGL版本会启动websockify.js(用于websocket转发)。 此时,导出的WebGL游戏在浏览器时能自动连接到Unity Profiler。

  1. 微信开发者工具小游戏Profile 使用转换脚本导出微信小游戏包并启动小游戏,微信小游戏将自动连接到Unity Profiler

  2. 调整UnityProfiler IP/端口

网页WebGL/小游戏启动后将通过"ws://ip:port"自动连接到“Unity Profiler”, 此地址默认为编译机器的。如果无法连接请查看微信开发者工具Network页签对应的ws链接是否正常可达。 如需手工调整IP、端口可通修改webgl.wasm.framework.unityweb.js

     if(port == 54998) 
+     {
+        url = "ws://127.0.0.1:54998"
+     }
+     ws = new WebSocketConstructor(url, opts);
+     ws.binaryType = "arraybuffer";

重启UnityProfiler监听,可通过在命令行执行引擎自带Node启动websocketfy.js:

  • windows: "$UNITY_PATH/Editor/Data/Tools/nodejs/node.exe" "$UNITY_PATH/Editor/Data/PlaybackEngines/WebGLSupport/BuildTools/websockify/websockify.js" 0.0.0.0:port localhost:34999
  • mac: /Applications/Unity/Hub/Editor/$Verson/PlaybackEngines/WebGLSupport/BuildTools/Emscripten/node/node /Applications/Unity/Hub/Editor/$Verson/PlaybackEngines/WebGLSupport/BuildTools/websockify/websockify.js 0.0.0.0:port localhost:34999 -vv

(其中$UNITY_PATH为对应Unity版本的安装目录)

  1. 注意事项
  • 并非每个Unity版本UnityProfiler都稳定,如果发现无法正常的情况请尝试更换小版本
  • Unity2021建议使用InstantGame版本,支持增强的Profiler数据,下载地址请查阅 推荐引擎版本
  • 当小游戏无法连接UnityProfile时,请检查UnityProfiler是否已启动监听,且IP/端口可达。通常使用"BuildSetting"-"Build And Run"打开浏览器时,UnityProfiler会默认启动监听; 否则请参考前文手动“重启UnityProfiler监听”。

附录:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UnityVersion.html b/Design/UnityVersion.html new file mode 100644 index 00000000..437c666e --- /dev/null +++ b/Design/UnityVersion.html @@ -0,0 +1,24 @@ + + + + + + 推荐引擎版本 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

推荐引擎版本

版本兼容性

Unity WebGL微信小游戏适配方案是以WebAssembly为基础,具有非常宽泛的兼容性,转换插件理论上支持的Unity版本涵盖:2018、2019、2020、2021、2022等

但并非每个小版本我们都有足够的验证,我们会根据验证情况以及大量转换游戏反馈的情况给出引擎版本建议。

推荐版本

引擎版本压缩纹理/音频编译体积已验证小版本其他
2018仅DXT,不支持ETC2/ASTC100%2018.4.25~2018.4.34不支持设置dpr分辨率
2019仅DXT,不支持ETC2/ASTC100%2019.4.28~2019.4.35---
2019 InstantGame全支持DXT/ETC2/ASTC100%2019.4.29增加WebGL移动端压缩纹理、AutoStreaming等支持
2020DXT/ETC2,不支持ASTC100%2020.3.1~2020.3.36---
2021全支持DXT/ETC2/ASTC80%2021.2.11~2021.3.33---
2021 InstantGame全支持DXT/ETC2/ASTC80%2021.2.5增强运行时性能、UnityProfiler以及更小的包体
2022(推荐)全支持DXT/ETC2/ASTC80%2022.3.1~2022.3.14---
团结引擎(推荐)全支持DXT/ETC2/ASTC60~80%---基于2022.3.2, 但包体、内存更多优化,支持FrameDebugger调试

备注:

  • Unity引擎在早期版本如5.x已提供WebGL平台导出模式,但我们并不推荐使用早期版本,因为存在较多BUG
  • 小游戏平台的压缩纹理支持:PC端DXT,移动端Android ETC2/ASTC, iOS ASTC
  • Unity2018~2020在WebGL上没有明显的性能差异,但2018缺少部分功能(如不支持设置WebGL分辨率),老项目请尽量选择2019以上版本
  • Unity2021~2022开始支持更多特性,如更全的压缩纹理、压缩音频、更快的编译速度与更小的体积,强烈建议2022.3
  • 引擎(如2018-2020)不支持移动端压缩纹理(ETC2/ASTC)时,请务必使用压缩纹理优化进行优化;
  • Unity2022支持新的memoryprofiler Package, 有助于更好地分析WebGL内存使用
  • Unity InstantGame版本目前是在2019.4.29/2021.2.5基础上,由Unity中国区特殊优化,提供更强的Unity Profier内存分析AutoStreaming等功能,如有条件尽可能使用
  • 团结引擎基于2022.3.2,但引擎针对小游戏/WebGL环境有更多的优化,比如内存更低,包体更小,也支持更多的调试工具。可查阅官网了解详细信息

Unity InstantGame/团结引擎获取

中国特供版下载地址

QA

  1. 项目使用2017/Unity5等早期版本,应该使用哪个引擎版本转换?
  • 转换工具最低需要引擎版本为2018, 建议直接升级到2022支持压缩纹理、更小的编译体积
  1. 项目在使用2018-2020版本,是否可以直接使用?
  • 前期建议继续使用当前版本,这些版本需要用微信压缩纹理以优化内存,2018版本不支持修改dpr(修改分辨率);有人力情况下强烈建议升级2022, 编译速度都更快利于版本迭代,编译体积更小利于启动速度和运行内存
  1. Unity InstantGame/团结引擎相对于普通版本有特别之处?
  • Unity InstantGame是对特定正式版本的增强,2019 InstantGame增加了压缩纹理、音频支持;2021 InstantGame增强了Unity Profiler内存分析能力,提供AutoStreaming资源自动化处理
  • 团结引擎基于2022.3.2,但引擎针对小游戏/WebGL环境有更多的优化,比如内存更低,包体更小,也支持更多的调试工具。可查阅官网了解详细信息
  1. 版本是越新越好吗?
  • 不是. 虽然适配方案有较为广泛的兼容性,但新版本(特别是小版本)实现变更可能会导致适配问题,所以建议尽量使用表格中有实际游戏验证的版本

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/Update.html b/Design/Update.html new file mode 100644 index 00000000..5c76b8fb --- /dev/null +++ b/Design/Update.html @@ -0,0 +1,24 @@ + + + + + + 版本更新 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

版本更新

代码更新

请阅读文档,了解小游戏的更新机制

更新策略:

1. 静默更新(默认方式)

这种形式和APP版本类似,比如应用市场自动更新。游戏发新版本后,在打开小游戏前,会静默更新到最新版本。 但小游戏包体的更新机制和APP不同,开发者在管理后台发布新版本的小游戏之后,无法立刻影响到所有现网用户,如果某个用户本地有小程序的历史版本,此时打开的可能还是旧版本,最差情况下,也在发布之后 24 小时之内下发新版本信息到用户

缺点:更新不及时,依然可能体验到旧版本内容,需要注意保证旧版本资源可访问。

适合于对版本一致性要求不高的游戏使用

2. 强制更新

2.1 实时检测更新(UpdateManager)

戏运行期间检查是否有新版本,当新版本可用后,提示用户重启更新

转换插件有提供配置来自动使用这项能力,通过勾选【导出面板-更多配置项-Project Conf】中的配置needCheckUpdate

缺点:由于重启后,可能涉及资源下载,可能导致用户流失。

2.2 设置最低可用版本

  • 如果希望用户始终打开最新版本,可通过mp后台-设置-基本设置-小程序最低可用版本,修改为最新版本

资源更新

请查看资源部署-资源更新说明

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UsingAddressable.html b/Design/UsingAddressable.html new file mode 100644 index 00000000..232d4c26 --- /dev/null +++ b/Design/UsingAddressable.html @@ -0,0 +1,97 @@ + + + + + + 使用Addressable Assets System进行资源按需加载 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用Addressable Assets System进行资源按需加载

一、概述

对于Unity WebGL转换的小游戏启动耗时,资源下载通常是贡献最大的部分。这是由于手游APP往往很少针对首包资源进行特殊优化。 那么,接下来的问题是:小游戏中多大的首包资源合适? 剩余的游戏资源如何加载? 在此,我们建议得优化原则是:

  1. 首包资源量不超过5M
  2. 资源按需延迟加载,拆分得尽量细

本文介绍如何使用Unity新的资源管理流程Addressable Assets System进行资源的按需加载。

附可参考的项目: https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/tree/main/Demo/Addressable

二、Addressable在小游戏中的应用

2.1 什么是Addressable Assets System

Unity在2018版本中推出了Addressable Assets System(以下简称Addressable)的预览版本,并在2019的版本中已经成为正式版本,可以用于生产(仅表示发布时间,实际上大部分Unity版本都可正常使用)。 Addressable提供了以下能力:

低使用门槛:使用Addressable在开发前期就进入快速开发的阶段,使用任何你喜欢的资源管理技术,你都能快速的切换来Addressable系统中,几乎不需要修改代码。

依赖管理:Addressable系统不仅仅会帮你管理、加载你指定的内容,同时它会自动管理并加载好该内容的全部依赖。在所有的依赖加载完成,你的内容彻底可用时,它才会告诉你加载完成。

内存管理:Addressable不仅仅能记载资源,同时也能卸载资源。系统自动启用引用计数,并且有一个完善的Profiler帮助你指出潜在的内存问题。

内容打包:Addressable系统自动管理了所有复杂的依赖连接,所以即使资源移动了或是重新命名了,系统依然能够高效地找到准确的依赖进行打包。当你需要将打包的资源从本地移到服务器上面,Addressable系统也能轻松做到,几乎不需要任何代价。

2.2 相对于AssetsBundles的优势

Unity中资源按需加载也可以使用老的AssetBundle,然而使用AB需要做不少的工作:标识Asset、组织Bundle、编译、Load/Unload、依赖关系以及后期维护的复杂工作。新一代的Addressable正是对这些痛点做了不少改进,开发者只需要将Asset设置为addressable然后加载即可,[功能强大并且学习曲线变得平滑] (https://docs.google.com/document/d/1hPLNLdrF0qAvjEJTpKf-cuO_d4FCV0H2cqBeP1Zo6mA/edit)。

2.3 在小游戏中使用Addressable Assets System

无论是Addressable还是AssetBundle在微信小游戏底层都使用XHR进行远程资源访问,并使用微信小游戏文件存储系统进行缓存。对于已有的游戏资源,如果我们需要尽量少的工作量去做到像H5游戏按需加载,使用Addressable是最佳做法。

2.4 使用WXAssetBundleProvider节省内存

WXAssetBundle可以减轻iOS的内存压力,对于使用Addressable的项目,需要替换Provider来使用WXAssetBundle。

  1. 下载WXAssetBundleProvider.cs,放到WX-WASM-SDK-V2/Runtime/目录下

  2. 导入插件后会有WXAssetBundleProvider.cs缺依赖的报错,需要给WX-WASM-SDK-V2/Runtime 增加 Unity.ResourceManager 的引用

  3. 进入AA的组设置修改Provider如下

  4. 重新导出 AA包 和 小游戏

三、启动优化与资源优化实战

3.1 从首包开始

首包资源应该只包含首屏所需资源,比如Splash界面以及对应文案。 首屏资源需要注意:

  1. 导出场景不要勾选任何其他场景
  2. 不要打包字体文件,字体往往压缩率很低。
  3. 通过Addressable检查Bultin分组,特别注意不要随意放置资源到Resources目录,该目录将无条件被打包到首包中。

通常,Unity首资源包的压缩率是比较高的,因为大多数Unity built资源是以文本形式存在。开发者应尽量减少首资源包压缩后大小,以zip压缩后体积为准,3M左右最佳,不应超过5M。

部署首资源包需要注意:

  1. 使用“小游戏分包”时,小游戏底层会自动进行压缩减少网络传输。
  2. 使用“CDN”时,务必在服务器对txt后缀开启“Brotli或gzip”。

3.2 资源按需加载

3.2.1 场景动态加载

如前所述,我们构建时仅选择了splash/loading场景,那么主场景(如大厅/战斗等)该如何加载?此时我们可以将每个场景单独作为Addressable分组,在用到的时候才下载该场景包。

使用Addressables.LoadSceneAsync可以动态加载场景与获取加载进度:

    IEnumerator LoadMain()
+    {
+        var handle = Addressables.LoadSceneAsync("Assets/RPGPP_LT/Scene/rpgpp_lt_scene_1.0.unity", LoadSceneMode.Single, true);
+        handle.Completed  += (obj) =>
+        {
+            Debug.LogWarning($"Load async scene complete{obj.Status}");
+        };
+
+        while (!handle.IsDone)
+        {
+            // 在此可使用handle.PercentComplete进行进度展示
+            yield return null;
+         }
+    }

选择分组,设置分组属性如下:

如果我们仅将场景作为分组,其中静态摆放的物件不单独设置为Addressable也会一并打包到场景所在bundle。那么,这是会产生一个问题:两个场景都使用同样资源是否产生冗余?答案是肯定的!! 那么,如何消除冗余呢?当我们Adressable面板的Tools-->Analyze进行分析时,可看到以下内容:

此时,我们应将这些冗余的内容单独进行设置为Addressable。而更为简单的做法是:选中“Check Duplicate Bundle Dependencies”,点击“Fixed Selected Rules”,工具会自动将冗余项逐个设置为Addressable。

3.2.2 物件动态加载

除了静态场景外,我们还会经常动态实例化(Instantiate)或在内存中创建资源对象。比如:

C#
public class LoadAssetScript : MonoBehaviour
+{
+    public GameObject somePrefab;
+    private void Start()
+    {
+        Instantiate(somePrefab);
+    }
+}

然而,这样做有个非常严重的问题:Prefab本身以及依赖的所有资源需要在场景加载前完成。在小游戏环境,这意味着即使还没调用Instantiate,这部分资源就必须准备好,这会极大影响场景初始化速度

那么,如果我们希望把somePrefab以及它的依赖资源打包在Addressable分组进行按需下载应该如何做呢?答案是AssetReference。上述代码改写成:

public class LoadAssetScript : MonoBehaviour
+{
+    public AssetReference somePrefab;
+    private void Start()
+    {
+        somePrefab.InstantiateAsync().Completed += (obj) =>
+        {
+           // 加载完成回调
+        };
+    }
+}

或协程写法:

public class LoadAssetScript : MonoBehaviour
+{
+    public AssetReference somePrefab;
+    private IEnumerator spawnSomathing()
+    {
+        var hanle = somePrefab.InstantiateAsync();
+        while(!handle.IsDone) {yield return null;}
+         // 加载完成回调
+        var gameObject = hanle.Result;
+    }
+}

同时,对应的Prefab在editor中需设置为Addressable,并重新为somePrefab赋值。

3.3 小结

Unity WebGL转换的小游戏普遍存在首包资源较大的情况,而新Address提供了非常好的资源管理流程。我们建议开发者:

  1. 精简首场景,首包资源中确保只包含轻量的首屏以及依赖资源
  2. 延迟加载,避免业务逻辑需要全量资源的情况,设计上尽量按需加载
  3. 资源拆分,利用Addressable进行更灵活和细粒度的拆解
  4. 预加载,根据优先级设置需要预加载的分包,利用网络空闲期

四、如何优雅地异步加载

4.1 最基本的异步回调

C#
private void TextureHandle_Completed(AsyncOperationHandle<Texture2D> handle) {
+    if (handle.Status == AsyncOperationStatus.Succeeded) {
+        Texture2D result = handle.Result;
+        // The texture is ready for use.
+    }
+}
+
+void Start() {
+    AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAsset<Texture2D>("mytexture");
+    textureHandle.Completed += TextureHandle_Completed;
+}

4.2 使用协程

C#
public IEnumerator Start() {
+    AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
+
+    //if the handle is done, the yield return will still wait a frame, but we can skip that with an IsDone check
+    if(!handle.IsDone)
+        yield return handle;
+
+    if (handle.Status == AsyncOperationStatus.Succeeded) {
+        Texture2D texture = handle.Result;
+        // The texture is ready for use.
+        // ...
+    // Release the asset after its use:
+        Addressables.Release(handle);
+    }
+}

4.3 使用await

C#
public async Start() {
+    AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
+    await handle.Task;
+    // The task is complete. Be sure to check the Status is successful before storing the Result.
+}

五、旧系统资源改造

资源系统迁移可参考Unity官方文档Upgrading to the Addressables system

5.1 Resource改造

使用这种方式加载资源,通常需要再Asset或其子目录下创建Resources的文件夹,然后使用类似这种方式加载:

C#
       TextAsset text = Resources.Load<TextAsset>("MyConfig");

然而,Resources目录的内容都会被打包进首包资源,对于小游戏来说是不推荐使用的方式。 开发者在Addressable的default中能看到所有这些资源,我们需要将这些资源设置为“Addressable”,Unity将自动移动到“Resources_Moved”目录。 加载代码改写成:

C#
        var handle = Addressables.LoadAssetAsync<TextAsset>("MyConfig");
+        if(!handle.IsDone) yield return handle;
+         // 加载完成回调
+         if (handle.Status == AsyncOperationStatus.Succeeded) {
+            var gameObject = hanle.Result;
+         }

5.2 AssetsBundle迁移

当打开Addressables Groups时,Unity提供了将所有AssetsBundle迁移到Addressable Asset Groups的功能。

六、部署

6.1 Addressable编译与部署

默认情况下,当编译Addressable资源时会输出到Library/com.unity.addressables/,项目发布为WebGL或转换为小游戏时Unity会自动拷贝Bundle文件到最终的生成目录下。我们只需要将对应的StreammingAssets上传到对应的CDN服务器即可。

6.2 资源预下载

为了充分利用网络带宽,在网络空闲时可预下载游戏需要用到的AB包。详细配置请参考使用预下载功能

五、参考资料

  1. Addressable Asset System for Unity (Overview) https://docs.google.com/document/d/1hPLNLdrF0qAvjEJTpKf-cuO_d4FCV0H2cqBeP1Zo6mA/edit

  2. 官方Demo https://github.com/Unity-Technologies/Addressables-Sample

  3. 视频范例 https://drive.google.com/file/d/1w-Lh_jsD2VSHNvkzexJLSc6bA3gUQC8d/view

  4. uwa关于Addressable的介绍 https://blog.uwa4d.com/archives/USparkle_Addressable4.html

  5. Addressable与AssetBundle的对比 https://www.jianshu.com/p/8009c16fcab3

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UsingAssetBundle.html b/Design/UsingAssetBundle.html new file mode 100644 index 00000000..e2f6ed6c --- /dev/null +++ b/Design/UsingAssetBundle.html @@ -0,0 +1,69 @@ + + + + + + 使用 AssetBundle 进行资源按需加载 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用 AssetBundle 进行资源按需加载

阐述如何在小游戏环境对AssetBundle进行打包、加载和内存优化,同时推荐使用WXAssetBundle更自动化地节省内存。

一、AssetBundle使用

注意:小游戏环境不支持assetbundle本地加载

1.1 AssetBundle打包参数建议

c#
public static void Build()
+{
+    string dst = Application.streamingAssetsPath + "/AssetBundles";
+    if (!Directory.Exists(dst))
+    {
+        Directory.CreateDirectory(dst);
+    }
+    BuildPipeline.BuildAssetBundles(dst, BuildAssetBundleOptions.AppendHashToAssetBundleName | BuildAssetBundleOptions.ChunkBasedCompression | UnityEditor.BuildAssetBundleOptions.DisableWriteTypeTree | BuildAssetBundleOptions.None, BuildTarget.WebGL);
+}

打包bundle时,请使用如下参数

  • 【重要】BuildAssetBundleOptions.AppendHashToAssetBundleName:bundle带上hash。在小游戏底层对bundle做缓存及缓存淘汰时,hash是重要依据,请查阅小游戏资源缓存
  • BuildAssetBundleOptions.ChunkBasedCompression:LZ4压缩方式,加载速度和包体大小更均衡。
  • 如非需要新老Unity引擎版本兼容,请使用DisableWriteTypeTree提升加载速度与降低内存。

1.2 AssetBundle下载

从服务器下载bundle的方式主要以下两种:

  • UnityWebRequestAssetBundle.GetAssetBundle

    c#
    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uriPath);
    +yield return request.SendWebRequest();
    +if (request.isHttpError)
    +{
    +    Debug.LogError(GetType() + "/ERROR/" + request.error);
    +}
    +else
    +{
    +    AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
    +    // ab.LoadAsset
    +    ab.Unload(false);
    +}
    +request.Dispose();
  • UnityWebRequest

    c#
    UnityWebRequest www = new UnityWebRequest(uriPath);
    +DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.uri.ToString(), 0);
    +www.downloadHandler = handler;
    +yield return www.Send();
    +if (www.isHttpError)
    +{
    +    Debug.LogError(GetType() + "/ERROR/" + www.error);
    +} else
    +{
    +    AssetBundle ab = handler.assetBundle
    +    // ab.LoadAsset
    +    ab.Unload(false);
    +}
    +www.Dispose();

    特别地, 切忌使用WWW.LoadFromCacheOrDownload或WWW等带cache接口,WebGL模式下将会使用JS模拟文件系统带来额外内存消耗!

二、小游戏与APP的AssetBundle缓存更新流程差异

小游戏因其平台特殊性,需要保证加载速度,因此我们在底层对bundle文件做了缓存,开发者无须自己实现缓存。

游戏逻辑还是按照未缓存需要从网络下载去编写,插件底层会判断是否已有缓存。若未缓存则缓存此bundle;若已缓存,则返回缓存文件,实际不会发起网络请求。

可参见资源缓存与淘汰

资源缓存与更新的不同,会导致APP与小游戏不同的加载流程

  • 常见APP AssetBundle使用方式:

检查更新-->下载更新全量资源-->写入文件系统-->运行时LoadFromFile

  • 微信小游戏 AssetBundle使用方式

打包ab时文件名带hash-->UnityWebRequest按需下载并使用资源

在业务侧看来:总是使用异步接口从远程下载并使用,底层资源的缓存与更新已由适配层自动完成,游戏不再直接读写文件系统。

三、更节省内存的WXAssetBundle

  • 简介与原理

    Unity的 AssetBundle.LoadFromFile() 原本是打开一个文件流,LoadAsset通过文件描述符fd去读实际的目标对象。因此不需要存储完整的AssetBundle(只需存储包头、查找表),可节省内存。

    而由于WebGL的文件系统是在JS内存中维护的,不会实际读写到磁盘,无法使用LoadFromFile()达到节约内存的目的。

    为此,我们在微信小游戏环境将文件系统接口桥接到了微信的文件系统接口,使其可以读写到小游戏缓存目录。同时提供了包装好的Unity SDK以便开发者使用。

  • 使用说明

    Addressable也可使用,可参考使用WXAssetBundleProvider节省内存 修改Provider。

    AssetBundle目前只支持异步加载。参考示例如下:

    C#
    // 【推荐】原本使用WebRequest的话可按如下修改
    +using WeChatWasm;
    +UnityWebRequest bundleReq = WXAssetBundle.GetAssetBundle(url); // UnityWebRequestAssetBundle => WXAssetBundle
    +yield return bundleReq.SendWebRequest();
    +if (bundleReq.isHttpError)
    +{
    +    Debug.LogError(GetType() + "/ERROR/" + bundleReq.error);
    +}
    +else
    +{
    +    AssetBundle bundle = (bundleReq.downloadHandler as DownloadHandlerWXAssetBundle).assetBundle; // DownloadHandlerAssetBundle => DownloadHandlerWXAssetBundle
    +    bundle.WXUnload(false); //bundle还是AssetBundle类型,但需要调用扩展方法WXUnload()才可真正卸载
    +}
  • 注意事项

    此套接口只可在微信小游戏环境下使用!需要同时导出WebGL版本的,建议自行在修改接口时候加编译宏方便控制导出版本。

    频繁读写磁盘损耗性能,于是我们仍旧在JS内存中维护了完整bundle的缓存,只有使用到已被清理的bundle时才会一次性从磁盘完整读进内存,而高频读取资源时通过缓存完成请求。默认情况下5秒未使用的bundle会被从内存中清理。

    读磁盘必定影响性能,所以我们只推荐对内存要求高的重度游戏使用。

四、AssetBundle内存分析

4.1 切勿使用带Cache能力的线管接口

加载的bundle文件大小为5403162字节

bash
-rw-r--r--  1  Users  5403162  6 22 16:07 image1_751427a66d22b184c95342d556354150

通过加载前后snapshot来对比总内存变化

  • UnityWebRequestAssetBundle.GetAssetBundle/UnityWebRequest/WWW 这三种加载方式加载前后内存无变化

  • WWW.LoadFromCacheOrDownload 加载bundle后内存增加了5403162字节,增加了bundle大小的内存,是因为WWW.LoadFromCacheOrDownload除了会将文件存入IndexDB外,还会存入内存中的UnityCache

因此需要注意业务中不要使用已淘汰的WWW类,尤其WWW.LoadFromCacheOrDownload,当bundle数量多时,会浪费不少内存。

4.2 尽可能使用Unload

  • 当bundle从资源服务器下载并使用,会经历多次内存分配: 浏览器HTTP对象-->拷贝到WASM临时内存-->Unity ab内存文件(略大于ab本身体积, 相对于APP常用的LoadFromFile,WebGL这部分开销是额外的)
  • 当HTTP对象dispose之后,Unity ab内存文件
  • 当ab.Unload时,Unity ab内存文件释放

因此,最佳实践是业务应该尽可能早地使用ab.Unload(false),自行维护Asset的引用计数管理资源。

四、参考资料

  1. Introduction to Asset Bundles https://learn.unity.com/tutorial/introduction-to-asset-bundles#6028bab6edbc2a750bf5b8a7
  2. Unity WebGL Memory Optimization: Part Deux https://blog.kongregate.com/unity-webgl-memory-optimization-part-deux/
  3. Understanding Memory in Unity WebGL https://blog.unity.com/technology/understanding-memory-in-unity-webgl
  4. AssetBundle API https://docs.unity3d.com/2019.4/Documentation/ScriptReference/AssetBundle.html

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UsingLoader.html b/Design/UsingLoader.html new file mode 100644 index 00000000..26f2c123 --- /dev/null +++ b/Design/UsingLoader.html @@ -0,0 +1,55 @@ + + + + + + 使用Loader进行游游戏加载 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用Loader进行游游戏加载

一、什么是Unity Loader?

Unity Loader是在微信小游戏环境加载Unity WebGL游戏的加载与适配器,使用微信小游戏插件技术开发,功能包括:

  • WebAssembly代码分包加载与编译
  • 资源加载与编译
  • 启动进度显示
  • 缓存策略
  • 数据上报

二、如何使用Unity Loader插件

生成微信小游戏项目时,转换工具会在game.json中声明:

json
"plugins": {
+    "UnityPlugin": {
+        "version": "major.minor.patch", // 可切换版本号
+        "provider": "wxe5a48f1ed5f544b7",
+        "contexts": [
+            {
+                "type": "isolatedContext"
+            }
+        ]
+    }
+}

这部分配置表示使用Unity Loader插件进行游戏加载,开发者无需手动修改

三、配置Unity Loader功能

3.1 资源下载

声明CDN地址

转换插件相关配置

CDN: cdn地址
+dataFileSubPrefix: 首包资源相对cdn地址的存放目录,默认首包资源放在cdn一级目录

通过接口修改

游戏存在备用CDN地址,可通过C#接口 WX.SetDataCDN 或js接口 GameGlobal.manager.setDataCDN 修改DATA_CDN配置

3.2 启动界面

由于Unity WebGL启动加载需要一定时间,因此需要使用视频或图片等内容作为过渡以留住玩家。Unity Loader默认使用视频+进度信息呈现,开发者可以自定义封面/视频,可参考启动Loader视频规范进行配置。

转换插件相关配置

bgImageSrc: 启动封面图;-- $BACKGROUND_IMAGE
+VideoUrl: 启动视频;-- $LOADING_VIDEO_URL
+HideAfterCallMain: 是否callmain完成后立即隐藏封面;-- $HIDE_AFTER_CALLMAIN
+loadingBarWidth: 加载进度条宽度;-- $LOADING_BAR_WIDTH

game.js配置

js
loadingPageConfig: {
+  // 背景图或背景视频,两者都填时,先展示背景图,视频可播放后,播放视频
+  backgroundImage: '$BACKGROUND_IMAGE', // 默认的背景图,可自行替换,支持本地图片和网络图片
+  backgroundVideo: '$LOADING_VIDEO_URL', // 视频url,需要开发者提供,只支持网络url
+  // 以下是默认值
+  barWidth: $LOADING_BAR_WIDTH, // 加载进度条宽度,默认240,加载文案过长时可设置
+  totalLaunchTime: 15000, // 默认总启动耗时,即加载动画默认播放时间,可根据游戏实际情况进行调整
+  textDuration: 1500, // 当downloadingText有多个文案时,每个文案展示时间
+  firstStartText: '首次加载请耐心等待', // 首次启动时提示文案
+  downloadingText: ['正在加载资源'], // 加载阶段循环展示的文案
+  compilingText: '编译中', // 编译阶段文案
+  initText: '初始化中', // 初始化阶段文案
+  completeText: '开始游戏', // 初始化完成
+},
+hideAfterCallmain: $HIDE_AFTER_CALLMAIN, // 是否callmain完成立即隐藏封面

backgroundImage需要注意图片宽高不可超过2048,否则无法显示 使用coverview需要基础库版本>=2.16.1,插件已做兼容,若不支持,降级为使用离屏canvas渲染进度的方式 hideAfterCallmain: 游戏业务Awake逻辑耗时较高时可能导致出现短暂黑屏,改为false可盖住黑屏,等游戏第一帧渲染时隐藏

更多信息请参考定制启动封面

3.3 首包资源加载方式

加载方式在转换工具导出时就确定好了,开发者一般不需要修改游戏资源量比较少时,可选择将首包资源作为小游戏分包加载,了解小游戏分包 wasm代码已是通过代码分包加载,当wasm代码+首包资源>20M时,资源包不可再使用小游戏分包加载。 当首包资源通过小游戏代码分包下载时,会将首包资源存放在minigame/data-package这个分包下

转换插件相关配置

assetLoadType: -- $LOAD_DATA_FROM_SUBPACKAGE

game.js配置

js
let managerConfig = {
+  /* 省略其他配置 */
+  loadDataPackageFromSubpackage: $LOAD_DATA_FROM_SUBPACKAGE, // 转换工具自动替换
+}
  • 若手动将loadDataPackageFromSubpackage改为false,需要将webgl目录下的资源包上传到CDN,并将CDN地址填写到game.jsDATA_CDN字段
  • 同样的,若手动将loadDataPackageFromSubpackage改为true,需要将webgl目录下的资源包copy到minigame/data-package下

3.4 预加载资源

为了充分利用网络带宽,在网络空闲时可预下载游戏需要用到的AB包。详细配置请参考使用预下载功能

3.5 资源缓存与淘汰策略

loader会自动按一定规则做文件缓存,加快二次启动速度 详情参考资源缓存

3.6 插件调试日志

  1. 通过修改minigame/unity-namespace.jsenableDebugLog=true,可查看插件详细日志,例如预下载发起和命中、文件缓存等。
  2. 打开调试
  • 开发者工具:调试器->Console
  • 真机:
    • 步骤1(打开调试模式):右上角菜单->打开调试->出现vconsole 或者 game.js增加代码
    js
    wx.setEnableDebug({enableDebug: true})
    • 步骤2(打开vconsole):点击vconsole打开日志面板(启动阶段点三次封面视频下方Unity Logo出现 vconsole)

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UsingMemoryProfiler.html b/Design/UsingMemoryProfiler.html new file mode 100644 index 00000000..43669da3 --- /dev/null +++ b/Design/UsingMemoryProfiler.html @@ -0,0 +1,74 @@ + + + + + + 使用ProfilingMemory内存分析 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用ProfilingMemory内存分析

概述

在微信开发者工具运行游戏,利用ProfilingMemory,我们可以分析UnityHeap 或 DynamicMemory(CPU主内存)的详细分配堆栈与统计数值。

  • 该工具仅分析业务与引擎的CPU内存,即性能面板中的DynamicMemory中可被追踪到的内存情况,不包含WASM编译内存、显存、JS临时内存等
  • 建议在微信开发者工具 or Android使用(工具本身会增加不少内存,此时iOS WebContent进程内存压力会很大)
  • 当进行了Lua内存分配器替换操作后(参考常见问题 1),Profiling Memory将无法统计到Lua的内存分配。
  • Profiling Memory无法统计到Mono相关的内存。

步骤

  1. 游戏启动调用WeChatWASM.WX.InitSDK,并勾选导出选项"Profiling Funcs"与"Profiling Memory",请勿同时勾选"Development Build"选项!!!

  2. 在微信开发者工具运行游戏,过程中会自动记录所有内存分配数据

  3. 导出内存堆栈数据

  • 方式1:点击性能面板左上角的"ProfilingMemory Dump" 完成导出(开启性能面板可通过修改unity-namespace.js-enableProfileStats或C#调用OpenProfileStats)
  • 方式2:在微信开发者工具中选择gameContext, 并在Console输入命令: GameGlobal.memprofiler.onDump()。
  1. 微信开发者工具-“游戏缓存目录/usr/alloc_used.csv”(Android位于data/com.tencent.mm/MicroMsg/wxanewfiles/最近使用时间的目录)拖拽并以csv方式导入sqlite数据库, 推荐使用DB Browser for SQLite

  2. 对表格执行格式化换行 update alloc_used set callback=replace(callback, 'at ', x'0a')

数据分析

浏览数据

典型地,我们可以通过size进行排序分析内存最大占用的堆栈情况

其中:

  • callback: 堆栈
  • count: 当前存活的分配次数
  • size: 当前使用内存
  • malloc: 总分配次数
  • free: 总释放次数

SQL统计分析

我们可以在"执行SQL"窗口使用SQL进行数据统计和分析,常见的callback分配堆栈特征:

Unity 2021:

 所有内存: select sum(size) from alloc_used
+
+ AssetBundle Storage Memory: select sum(size) from alloc_used where callback like "%AssetBundle_LoadFromMemory%" or callback like "%OnFinishReceiveData%" or callback like "%AssetBundleLoadFromStream%"
+
+
+ AssetBundle Info:  select sum(size) from alloc_used where callback like "%get_assetBundle%" and callback not like "%AwakeFromLoad%"
+ 
+ AssetBundle TypeTree: select sum(size) from alloc_used where callback like "%TypeTree%" 
+
+ Lua: select sum(size) from alloc_used where callback like "%luaY_parser%" or callback like "%luaH_resize%" or callback like "%luaM_realloc%"
+
+ Shader: select sum(size) from alloc_used where callback like "%ShaderLab%"
+
+ IL2CPP runtime: select sum(size) from alloc_used where callback like "%MetadataCache%"
+
+ 非压缩纹理软解: select sum(size) from alloc_used where callback like "%Mipmap%"
+
+Other: select sum(size) from alloc_used where callback not like "%xxx%" or callback not like "%xxx%"

Unity 2018~2020:

AssetBundle Storage Memory: select sum(size) from alloc_used where callback like "%AssetBundleLoadFromStreamAsyncOperation%" 
+
+AssetBundle Info: select sum(size) from alloc_used where callback like "%get_assetBundle%" and callback not like "%AwakeFromLoad%"
+
+AssetBundle TypeTree: select sum(size) from alloc_used where callback like "%TypeTree%"
+
+Lua: select sum(size) from alloc_used where callback like "%luaY_parser%" or callback like "%luaH_resize%" or callback like "%luaM_realloc%" 
+
+Shader: select sum(size) from alloc_used where callback like "%ShaderFromSerializedShader%"
+
+IL2CPP runtime: select sum(size) from alloc_used where callback like "%MetadataCache%" -19M
+
+动画数据: select  sum(size) from alloc_used where callback like "%AnimationClip%" -7MB
+
+非压缩纹理软解: select sum(size) from alloc_used where callback like "%Mipmap%"
+
+Other: select sum(size) from alloc_used where callback not like "%xxx%" or callback not like "%xxx%"

除了常见的堆栈特征外,我们也可以根据业务自己的使用特点来进行SQL分析。

常见问题

1. 开启ProflingMemory后非常慢,特别是在有Lua逻辑的情况

  • 首先,这是正常情况,因为每次分配内存都会获取堆栈信息导致运行慢
  • Lua会存在大量分配行为,会加重这个问题, 因此我们提供了专门的内存分配器忽略Lua内存,具体做法:
  1. simpledlmalloc.c添加到xLua虚拟机源码目录下参与编译,(和lauxlib.c同一目录)
  2. 参考lauxlib.c,在lua源码目录下的同名文件中增加simple_dlmalloc,并修改LUALIB_API lua_State *luaL_newstate (void) 为如下所示
    C
    #include "simpledlmalloc.c"
    + static void *simple_dlmalloc (void *ud, void *ptr, size_t osize, size_t nsize) {
    +     (void)ud; (void)osize;  /* not used */
    +     if (nsize == 0) {
    +         dlfree(ptr);
    +         return NULL;
    +     }
    +     else
    +         return dlrealloc(ptr, nsize);
    + }
    +
    + // using other_alloc instead of default dlmalloc to avoid print trace of lua
    + LUALIB_API lua_State *luaL_newstate (void) {
    +     // lua_State *L = lua_newstate(l_alloc, NULL);
    +     lua_State *L = lua_newstate(simple_dlmalloc, NULL);
    +     if (L) lua_atpanic(L, &panic);
    +     return L;
    + }

2. ProfilingMemory在真机上更容易出现内存崩溃

  • ProfilingMemory功能需要额外的内存记录堆栈与相关统计,因此JS侧内存压力会更大
  • 理论上UnityHeap(CPU主内存)在不同端上的行为基本是一致的,由于iOS内存更苛刻,建议使用微信开发者工具或Android真机进行内存堆栈导出

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UsingNetworking.html b/Design/UsingNetworking.html new file mode 100644 index 00000000..db8876a6 --- /dev/null +++ b/Design/UsingNetworking.html @@ -0,0 +1,183 @@ + + + + + + 网络通信适配 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

网络通信适配

由于安全性的影响,JavaScript 代码没有直接访问 IP 套接字来实现网络连接。因此,该.NET 网络类(System.Net 命名空间中的一切,特别是System.Net.Sockets)在 WebGL 中不能工作。UnityEngine.Network* 类也是这样,编译 WebGL 时将找不到这些类。

HTTP 通信

Unity 支持在 WebGL 中使用 UnityWebRequest 类。

使用方式

以下为使用协程方式发送 GET、POST 请求到服务器的示例:

C#
 IEnumerator Get()
+    {
+        UnityWebRequest webRequest = UnityWebRequest.Get("https://mysite.com");
+
+        yield return webRequest.SendWebRequest();
+       if (webRequest.isHttpError||webRequest.isNetworkError)
+            Debug.Log(webRequest.error);
+        else
+        {
+            Debug.Log(webRequest.downloadHandler.text);
+        }
+
+    }
+
+    IEnumerator Post()
+    {
+        WWWForm form = new WWWForm();
+        //键值对
+        form.AddField("key", "value");
+        form.AddField("name","mafanwei");
+        form.AddField("blog","qwe25878");
+
+        UnityWebRequest webRequest = UnityWebRequest.Post("https://mysite.com",form);
+
+        yield return webRequest.SendWebRequest();
+        if (webRequest.isHttpError||webRequest.isNetworkError)
+            Debug.Log(webRequest.error);
+        else
+        {
+            Debug.Log(webRequest.downloadHandler.text);
+        }
+    }

特别地,在 Unity WebGL 环境下禁止使用以下代码:

C#
while(!www.isDone) {}

不能阻止线程等待 UnityWebRequest 下载完成,否则您的应用程序将冻结。因为 WebGL 采用单线程机制,并且由于 JavaScript 中的 网络 API 是异步的,所以除非您将控制权交回给浏览器,否则下载永远不会完成。取而代之的做法是使用协程和 yield 语句等待下载完成。

TCP 网络通信

如果游戏使用 TCP 进行网络通信,在 Unity WebGL 中开发者可以使用微信基础库中的TCPSocket(需要微信基础库版本>=3.1.1),也可以使用 Websocket 进行替代。

TCPSocket

注意:出于应用场景考虑,TCPSocket.OnMessage表现与文档不一致。

c#
/// <summary>
+/// [TCPSocket.onMessage(function listener)](https://developers.weixin.qq.com/minigame/dev/api/network/tcp/TCPSocket.onMessage.html)
+/// 监听当接收到数据的时触发该事件
+/// needInfo: 是否需要返回localInfo和remoteInfo,设置为 false 时这两个字段会返回null,设置为 true 会降低性能,请按需使用
+/// 多次使用OnMessage时needInfo以第一个OnMessage为准,OffMessage()移除所有回调后再次OnMessage可重新设置needInfo
+/// </summary>
+public void OnMessage(Action<TCPSocketOnMessageListenerResult> listener, bool needInfo = false)

使用举例:

c#
using System.Text;
+using UnityEngine;
+using WeChatWASM;
+using LitJson;
+
+public class TCPTest : MonoBehaviour
+{
+    void Start()
+    {
+      	// 初始化WXSDK
+         WX.InitSDK((int code) =>
+         {
+             Debug.Log("InitSDK code: " + code);
+             TestTCPSocket();
+         });
+    }
+
+    void TestTCPSocket()
+    {
+        Debug.Log("TestTCPSocket");
+        // 创建TCPSocket
+        WXTCPSocket tcp = WX.CreateTCPSocket();
+      	
+      	// 注册回调
+        tcp.OnConnect(res =>
+        {
+            Debug.Log("tcp 连接成功");
+          	//连接成功时发送数据
+            tcp.Write("TCP Write Test");
+        });
+        tcp.OnError(res =>
+        {
+            Debug.Log("tcp 连接失败" + JsonMapper.ToJson(res));
+            WX.ShowModal(new ShowModalOption()
+            {
+                content = res.errMsg
+            });
+        });
+        // 注意OnMessage参数与文档不同
+        tcp.OnMessage(res =>
+        {
+            Debug.Log("tcp 消息" + JsonMapper.ToJson(res));
+            WX.ShowModal(new ShowModalOption()
+            {
+                content = Encoding.UTF8.GetString(res.message)
+            });
+        }, true);
+				
+      	// 在给定的套接字上启动连接,请按需更改地址与端口
+        tcp.Connect(new TCPSocketConnectOption()
+        {
+            address = "www.example.com",
+            port = 8848
+        });
+    }
+}

WebSocket

客户端

支持 Unity Websocket 的第三方插件比较多,可以从 Github 或 AssetStore 找到。这里以UnityWebSocket为例。

C#
// 命名空间
+using UnityWebSocket;
+
+// 创建实例
+string address = "ws://echo.websocket.org";
+WebSocket socket = new WebSocket(address);
+
+// 注册回调
+socket.OnOpen += OnOpen;
+socket.OnClose += OnClose;
+socket.OnMessage += OnMessage;
+socket.OnError += OnError;
+// 连接
+socket.ConnectAsync();
+// 发送 string 类型数据
+socket.SendAsync(str);
+// 或者 发送 byte[] 类型数据(建议使用)
+socket.SendAsync(bytes);
+// 关闭连接
+socket.CloseAsync();

UnityWebSocket需要对WebSocket.jslib做两处修改(新版本无需修改,感谢@psygames):

  1. instance.ws.onmessage函数将分支"else if (ev.data instanceof Blob)"挪到最后
  2. WebSocketSend函数中"HEAPU8"改为"buffer"

可参考WebSocket Demo

服务端

如果服务端使用 TCP 接入,则需要使用 WSS<-->TCP 的代理层。解决方案也很多:

特别地,在处理WebSocket数据包时,请注意数据的“粘包”问题,需要游戏服务器自行处理。

UDP 网络通信

微信基础库支持UDPSocket类。

注意:出于应用场景考虑,TCPSocket.OnMessage表现与文档不一致。

c#
/// <summary>
+/// [UDPSocket.onMessage(function listener)](https://developers.weixin.qq.com/minigame/dev/api/network/udp/UDPSocket.onMessage.html)
+/// 监听收到消息的事件
+/// needInfo: 是否需要返回localInfo和remoteInfo,设置为 false 时这两个字段会返回null,设置为 true 会降低性能,请按需使用
+/// 多次使用OnMessage时needInfo以第一个OnMessage为准,OffMessage()移除所有回调后再次OnMessage可重新设置needInfo
+/// </summary>
+public void OnMessage(Action<UDPSocketOnMessageListenerResult> listener, bool needInfo = false)

使用举例:

c#
using System.Text;
+using UnityEngine;
+using WeChatWASM;
+using LitJson;
+
+public class UDPTest : MonoBehaviour
+{
+    // Start is called before the first frame update
+    void Start()
+    {
+         Debug.Log("Start");
+         WX.InitSDK((int code) =>
+         {
+             Debug.Log("InitSDK code: " + code);
+             TestUDPSocket();
+         });
+    }
+
+    void TestUDPSocket()
+    {
+        Debug.Log("TestUDPSocket");
+        // 创建UDPSocket
+        var udp = WX.CreateUDPSocket();
+				// 注册回调
+        udp.OnMessage(res => 
+        {
+            Debug.Log("udp 消息" + JsonMapper.ToJson(res));
+            WX.ShowModal(new ShowModalOption()
+            {
+                content = Encoding.UTF8.GetString(res.message)
+            });
+        });
+      	// 绑定端口
+        udp.Bind();
+        // 向指定的 IP 和 port 发送消息,请按需更改地址和端口
+        udp.Send(new UDPSocketSendOption()
+        {
+            address = "www.example.com",
+            port = 8848,
+            message = "UDP Send Test"
+        });
+    }
+}

注意事项

微信小游戏的网络需要提前在MP后台配置安全域名,以及使用带证书的HTTPS、WSS协议。

经常有开发者问道:“为什么开发者工具正常,真机访问异常” 或者 “打开调试时正常,但关闭时异常”,通常是由于安全域名与SSL证书:

  • 微信开发者工具,默认不检验安全域名、SSL证书;通过详情-本地设置-关闭“不检验合法域名、HTTPS证书”进行自查
  • 真机环境下,默认会检查安全域名;开启调试时不检验安全域名

也有开发者问道:“开发阶段还没SSL证书可以跑起来吗?” 、"开发阶段只有内网IP没正式域名,导致MP无法登记安全域名能跑起来吗?" 答案是肯定的:

  • 微信开发者工具 or 使用调试模式的真机环境, 无需登记安全域名,也可以使用HTTP/WS等不带SSL证书的协议
  • 正式上线必须使用HTTPS/WSS等带SSL证书的协议,因为上线后不可能也让玩家打开调试模式

安全域名

  1. 真机预览时,默认检验安全域名,通过手机端小游戏右上角菜单-“开启调试”不检查安全域名
  2. 微信开发者工具,默认不检验安全域名、SSL证书;通过详情-本地设置-关闭“不检验合法域名、HTTPS证书”会强制检查
  3. 上线版本的网络请求必须配置安全域名。在 mp.weixin.qq.com 后台,**开发-开发管理-开发设置-服务器域名**进行设置。如果是 HTTP 请求请设置到 request、download合法域名,Websocket 请求请设置到 socket 合法域名。

SSL证书

访问HTTPS请求时,请检查SSL证书请确认是否过期,使用如通过在线工具检测。

真机预览时,只要用了HTTPS/WSS必然需要SSL证书,无法关闭;如无SSL证书或正式域名,可通过打开调试+HTTP/WS协议进行开发。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/UsingPreload.html b/Design/UsingPreload.html new file mode 100644 index 00000000..6f0575b3 --- /dev/null +++ b/Design/UsingPreload.html @@ -0,0 +1,89 @@ + + + + + + 使用预下载功能 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

使用预下载功能

概述

通过 启动流程与时序我们知道,在UnityLoader加载过程中存在网络空闲的情况。特别是“引擎初始化和首场景准备”,影响该步骤包括:引擎自身模块与数据初始化,游戏首个场景加载以及Awake流程。这个过程是CPU处理密集,但网络空闲的期间,根据机型性能不同,通常平均耗时会在3~6s左右,我们可以在此阶段提前下载资源。

预下载的列表的原理是提前通过网络下载资源并缓存到本地,下次使用时从本地缓存中读取文件,以此提高资源加载速度。

同时,我们认为添加到预下载列表的资源都是需要尽快使用到的资源,因此,资源在预下载完成后,会在内存中持有 60s 后释放,从而降低命中预下载列表时的文件读取耗时。

配置方式

导出预下载列表

MiniGameConfig.asset相关配置

preloadFiles: -- $PRELOAD_LIST

在Unity转换导出插件填写文件列表,生成时工具会自动从webgl/StreamAssets目录找资源并填充到game.js。 运行时UnityLoader将根据列表内容在网络空闲期下载。

手动配置

除了在Unity转换导出插件填写文件列表外,也可以在生成的game.js手动配置:

js
let managerConfig = {
+  /* 省略其他配置 */
+
+  /** 
+   * 假设: AB包打包到 path1/StreamingAssets/WebGL这个目录下; STREAMING_CDN是以path1为根路径上传到服务器的CDN地址
+   */
+  // 需要在网络空闲时预加载的资源,支持如下形式的路径。
+  preloadDataList: [
+    // '$STREAM_CDN/StreamingAssets/WebGL/textures_8d265a9dfd6cb7669cdb8b726f0afb1e',
+    // '/WebGL/sounds_97cd953f8494c3375312e75a29c34fc2'
+    "$PRELOAD_LIST" // 导出时自动替换
+  ],
+}

运行时配置「推荐」

可能存在资源热更,导致配置在预下载列表中的资源是旧版本的资源。支持通过接口在运行时动态修改预下载列表

假设有后台接口 https://api.example.com/preloadlist 返回如下数据:

json
{
+  "list": [
+    "https://cdn.example.com/file1",
+    "https://cdn.example.com/file2",
+    "https://cdn.example.com/file3",
+  ]
+}

在插件启动前修改

在插件启动前,拉取游戏后台获取最新的预下载列表,修改 managerConfig.preloadDataList 或通过js接口 GameGlobal.manager.setPreloadList 修改

伪代码如下:

  • managerConfig.preloadDataList
js
wx.request({
+  url: 'https://api.example.com/preloadlist', // 修改为实际API地址
+  success(res) {
+    if (res.statusCode === 200) {
+      managerConfig.preloadDataList = res.data.list;
+    }
+  },
+  complete() {
+    // 成功与否都开始启动unity
+    GameGlobal.manager.startGame();
+  }
+})
  • GameGlobal.manager.setPreloadList
js
wx.request({
+  url: 'https://api.example.com/preloadlist', // 修改为实际API地址
+  success(res) {
+    if (res.statusCode === 200) {
+      GameGlobal.manager.setPreloadList(res.data.list);
+    }
+  },
+  complete() {
+    // 成功与否都开始启动unity
+    GameGlobal.manager.startGame();
+  }
+})

引擎初始化完成后修改

同样的,拉取游戏后台接口获取最新的预下载列表后,通过C#接口 WX.SetPreloadList 修改

伪代码如下:

csharp
private IEnumerator GetPreloadList()
+{
+    using (UnityWebRequest www = UnityWebRequest.Get("https://api.example.com/preloadlist"))
+    {
+        yield return www.SendWebRequest();
+        if (www.result != UnityWebRequest.Result.Success)
+        {
+            Debug.Log(www.error);
+        }
+        else
+        {
+            string json = www.downloadHandler.text;
+            PreloadListData preloadListData = JsonUtility.FromJson<PreloadListData>(json);
+
+            // 获取URL列表
+            WX.SetPreloadList(preloadListData.list.ToArray());
+        }
+    }
+}
+
+
+[System.Serializable]
+public class PreloadListData
+{
+    public List<string> list;
+}

并发数

在引擎初始化完成前,默认并发10个预下载。已发起但未完成的下载任务,以及列表中尚未发起的任务,会在引擎初始完成后继续进行,但并发数改为1个。可通过Csharp接口 WX.PreloadConcurrent 修改引擎初始化后的预下载并发数,若想修改引擎初始化期间的并发数,需要使用js接口 GameGlobal.manager.setConcurrent

  • 默认值:引擎初始化完成前 10 个;引擎初始化完成后 1 个
  • 最大值:10 个

即使通过 GameGlobal.manager.setConcurrent 修改并发数,在引擎初始化完成后仍会重置为 1 个,需再次修改为你需要的值

路径规范

  • 若填写完成路径,如$STREAM_CDN/StreamingAssets/WebGL/textures_8d265a9dfd6cb7669cdb8b726f0afb1e;实际发起预载请求的URL采用填写的地址
  • 若填写相对路径,如/WebGL/sounds_97cd953f8494c3375312e75a29c34fc2;实际发起请求的URL为DATA_CDN/StreamingAssets/WebGL/sounds_97cd953f8494c3375312e75a29c34fc2

如何验证

查看插件调试日志

  1. 当存在 PreloadManager: 字样日志,即为预下载请求日志。
  2. 当存在 xhr: xx使用预载内容 即为复用内存中已预下载完成的资源,不发起网络请求。
  3. 当存在 xhr: xx 等待预载完成 即为复用未完成的预下载网络链接,等待网络完成。

tips:当预下载完成时间超过 60s 后,内存中的资源会释放。后续请求已预下载的资源没有日志可以区分,可通过 PreloadManager: 验证此资源预下载成功

注意事项

  1. 预下载所有文件总体积应控制在合理范围内,通常可以3~5MB左右的内容。
  2. 文件数量应控制在10个以内,在此阶段最多只能允许10个并发,超过将会排队。
  3. UnityLoader插件已经考虑到业务会重复请求预下载的文件,游戏逻辑依然按未使用预下载的异步加载逻辑,无需做其他处理。如果预下载完成UnityLoader会立即构造网络数据返回,业务无感知。
  4. 添加到预下载列表中的文件,需是插件会自动缓存的文件,否则会导致下载浪费,预下载无效,详见资源缓存
  5. 会按照列表顺序发起预下载,请将优先需要的资源放到列表前面。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/WXFont.html b/Design/WXFont.html new file mode 100644 index 00000000..ec4f4702 --- /dev/null +++ b/Design/WXFont.html @@ -0,0 +1,67 @@ + + + + + + 微信系统字体 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

微信系统字体

游戏基本会使用中文,中文字体大小少则2-3M。

通过微信系统字体,从本地加载中文,可节省启动下载的资源量。再不支持使用微信系统字体时,回退成通过CDN下载后备字体的形式。

版本要求

转换插件 >= 202306292010 提供了 WX.GetWXFont 接口用于加载后备/系统字体

其中,微信客户端满足以下版本要求时,可从本地加载字体,无需网络下载

  • 安卓微信客户端版本 >= 8.0.34
  • iOS微信客户端版本 >= 8.0.39

若不满足客户端版本要求,首次从网络下载;当符合缓存规则时,后续从本地文件缓存加载,因此必须提供 CDN 后备字体。

代码示例

详细示例可参考系统字体demo

csharp
var fallbackFont = "https://www......com/字体文件.ttf";
+WeChatWASM.WX.GetWXFont(fallbackFont, (font) =>
+{
+    text.font = font;
+    tmpText.font = TMP_FontAsset.CreateFontAsset(font);
+});

相关日志

  • 打开插件调试日志
  • 日志中查看以下字样 [PLUGIN LOG xxx][font],例如
    • 使用微信字体:
      • [PLUGIN LOG xxx][font] load font from local
      • [PLUGIN LOG xxx][font]读取字体文件耗时=xxms, 字体大小=xxMB
    • 使用网络字体:
      • [PLUGIN LOG xxx][font] load font from network, url=https://www......com/字体文件.ttf
      • [PLUGIN LOG xxx]xhr_onload: 字体文件.ttf,耗时=xxms,size=xx,无缓存

异常日志:

  • [PLUGIN LOG xxx][font]无中文字体:本地无可用系统字体,常见为安卓系统版本低于7.1
  • [PLUGIN LOG xxx][font]无字体文件内容:读取字体文件失败,未知原因,可提供微信日志给平台侧排查

系统字体字符集

使用GetWXFont加载的字体集合可以在转换面板进行自定义,以减少加载的字体文件大小:

若需要某些特殊Unicode/仅需要部分Unicode,可以直接将需要的字符全部填入自定义Unicode中。

Unicode集合参考:

js
// https://unicode.yunser.com/unicode
+const unicodeRange = [
+  // 基本汉字 https://www.unicode.org/charts/PDF/U4E00.pdf
+  [0x4e00, 0x9fff],
+  // 基本拉丁语(英文大小写、数字、英文标点)https://www.unicode.org/charts/PDF/U0000.pdf
+  [0x0, 0x7f],
+  // 中文标点符号 https://www.unicode.org/charts/PDF/U3000.pdf
+  [0x3000, 0x303f],
+  // 通用标点符号 https://www.unicode.org/charts/PDF/U2000.pdf
+  [0x2000, 0x206f],
+  // CJK字母及月份 http://www.unicode.org/charts/PDF/U3200.pdf
+  [0x3200, 0x32ff],
+  // 中文竖排标点 http://www.unicode.org/charts/PDF/UFE10.pdf
+  [0xfe10, 0xfe1f],
+  // CJK兼容符号 http://www.unicode.org/charts/PDF/UFE30.pdf
+  [0xfe30, 0xfe4f],
+  // 杂项符号 http://www.unicode.org/charts/PDF/U2600.pdf
+  [0x2600, 0x26ff],
+  // CJK特殊符号 http://www.unicode.org/charts/PDF/U3300.pdf
+  [0x3300, 0x33ff],
+  // 全角ASCII、全角中英文标点、半宽片假名、半宽平假名、半宽韩文字母 http://www.unicode.org/charts/PDF/UFF00.pdf
+  [0xff00, 0xffef],
+  // 装饰符号 http://www.unicode.org/charts/PDF/U2700.pdf
+  [0x2700, 0x27bf],
+  // 字母式符号 https://www.unicode.org/charts/PDF/U2100.pdf
+  [0x2100, 0x214f],
+  // 带圈或括号的字母数字 https://www.unicode.org/charts/PDF/U2460.pdf
+  [0x2460, 0x24ff],
+  // 数字形式 https://www.unicode.org/charts/PDF/U2150.pdf
+  [0x2150, 0x218f],
+  // 货币符号 https://www.unicode.org/charts/PDF/U20A0.pdf
+  [0x20a0, 0x20cf],
+  // 箭头 https://www.unicode.org/charts/PDF/U2190.pdf
+  [0x2190, 0x21ff],
+  // 几何图形 https://www.unicode.org/charts/PDF/U25A0.pdf
+  [0x25a0, 0x25ff],
+  // 数学运算符号 https://www.unicode.org/charts/PDF/U2200.pdf
+  [0x2200, 0x22ff],
+];

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/WX_SDK.html b/Design/WX_SDK.html new file mode 100644 index 00000000..a5519ba4 --- /dev/null +++ b/Design/WX_SDK.html @@ -0,0 +1,60 @@ + + + + + + SDK 调用微信 API | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

SDK 调用微信 API

将 WX-WASM-SDK 这个目录拷贝至 unity 工程 Assets 目录下,在主入口初始化,回调后再执行你的主逻辑

WX.InitSDK((int code)=> {
+// 你的主逻辑
+});

API 可以直接看WX.cs这个文件,里面有详细注释说明

本 Unity 的 SDK 的 API 大体与官网 API 文档的 JS 版本 API 类似,使用时可以参考之。 如 JS 版的 banner 广告的调用如下:

js
var bannerAd = wx.createBannerAd({
+    adUnitId: "xxxx",
+    adIntervals: 30,
+    style: {
+        left: 0,
+        top: 0,
+        width: 600,
+        height: 200,
+    },
+});
+bannerAd.onLoad(() => {
+    bannerAd.show();
+});
+bannerAd.onError((res) => {
+    console.log(res);
+});

而对于 Unity 版的调用如下:

csharp
var bannerAd = WX.CreateBannerAd(new WXCreateBannerAdParam()
+{
+    adUnitId = "xxxx",
+    adIntervals = 30,
+    style = new Style()
+    {
+        left = 0,
+        top = 0,
+        width = 600,
+        height = 200
+    }
+});
+bannerAd.OnLoad(()=> {
+    bannerAd.Show();
+});
+bannerAd.OnError((WXADErrorResponse res)=>
+{
+    Debug.Log(res.errCode);
+});

大体是将 JS 版中的wx替换为 Unity 版的WX,然后对应方法名首字母由小写改为大写,如createBannerAd就变为CreateBannerAd

基础库

在 Unity 中兼容低版本基础库

使用WX.CanIUse可以判断当前版本是否支持该 API(仅支持 wx),例如想要判断当前环境WX.ReportScene是否可用,可以用WX.CanIUse("ReportScene")来判断

开发建议

Demo API 示例

使用示例我们会逐渐补充到Demo, 其中 API 项目为常见到使用范例,请优先查阅用法。

联调效率

如果开发者有简单的 JS 代码经验,建议先以 JS 方式直接修改 minigame 的 JS 代码进行调试,完成之后再使用 C# SDK 修改 Unity 工程:

  1. 只保留 game.js 前面 import 部分,其余删除,即不运行游戏逻辑。
  2. 增加以下代码:
js
const gl = GameGlobal.canvas.getContext("webgl");
+gl.clear(gl.COLOR_BUFFER_BIT);
  1. 使用 JS 编写需要调试的 API

注意事项

  1. 广告接口是否需要上线后才能调试
  • 是的,需要上线并累计 UV>1000 才可以开通广告主

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/WasmSplit.html b/Design/WasmSplit.html new file mode 100644 index 00000000..6163a9be --- /dev/null +++ b/Design/WasmSplit.html @@ -0,0 +1,25 @@ + + + + + + 代码分包 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

代码分包

概述

背景

unity 导出小游戏项目后,代码是在一个 wasm 文件里,经过 brotli 压缩后,放在 wasmcode 目录下

一般小游戏的 wasm 大小都为 30M 左右,压缩后为 6M 左右

启动阶段,小游戏需要先下载完 wasmcode 再编译,这里会占用较高的内存和时间

因此我们提供了代码分包工具,将原来的 wasm 拆分为两个,一个用于启动加载(主包),另一个可以延迟加载(子包)

使得小游戏可以先加载较小的首包进入主场景,再异步加载剩下的分包

另外对于iOS高性能模式,子包不会加载,会转为按函数粒度按需加载

作用

分包的作用在于优化启动时间

另外对于 iOS 新的高性能模式,分包还有两个作用:

  1. 减少内存使用,以支持更多 iOS 低端机上运行高性能模式
  2. 减少编译时间,降低了游戏前期的发烫情况

实现原理

目前我们采用了一种 Profile Guided Optimization 的方式,通过运行时收集信息,按函数粒度对小游戏的 wasm 代码包进行拆分

开发者可以在离线测试阶段,通过真机运行小游戏,并尽量覆盖游戏内的场景,特别是启动后最先进入的场景和关卡(比如新手教学,游戏最初的关卡内容)来收集信息

工具上会显示收集到的函数个数,这时候就可以重新分包,将收集到的函数加入首包

因此收集工作非常重要,收集的场景覆盖率越高,命中子包的时机就可以相应延后,使得首包可以满足大部分新玩家前几分钟的游戏进程

我们提供了一个微信开发者工具里的插件来辅助分包过程,依赖的开发者工具版本为 1.05.2104251 RC 及以上,稳定版 1.05.2105100 已支持

插件安装

通过开发者工具的设置-拓展设置-编辑器自定义拓展,安装 wasmCodeSplit 这个插件

插件更新

开发者工具上(如果用的是stable版,非minigame版)的插件一般是自动更新的

手动更新

插件使用

分包插件按小游戏的md5(wasmcode下的wasm文件名里的md5)来区分不同的小游戏包

相同md5的小游戏包会复用同一份分包结果

对于新构建的小游戏包,分包流程如下:

  • 点启用代码分包
  • 输入当前项目版本描述
  • 等待上传代码包
  • 等待预处理
  • 选择是否增量分包,然后下一步
  • 等待第一次分包
  • 进入正式分包阶段,先android收集,然后继续下一步
  • iOS收集,然后继续下一步
  • 选择生成profile或者release包,然后收集,这一步可以重复进行

最后一步这里已经可以随时上传体验版了

具体操作和注意事项如下

启用分包

打开插件开关后,在目录树上的工具栏中,可以看到插件的按钮,如图所示,点击后即可进入插件页:

输入版本描述

等待上传文件

等待预处理

注意:如果出现红框中的提示,说明这里的状态更新已经中断,需要重启开发者工具

这一步一般是分钟级的耗时,如果等待超过10分钟,建议先重启下开发者工具

选择是否增量分包

如果这个游戏之前的包已经有用过代码分包,没有比较大的代码修改的情况下(比如大范围的代码重构,更换引擎),可以使用增量更新,也就是选择之前的某个包作为参考

我们会对比前后两个包的symbol,把之前收集过的函数当做放到首包,即无需重复收集

因此要求前后两个包都必须提供symbol文件

在unity侧使用微信插件导出时,需要开启profiling func,这样打包时就会导出symbol文件

无需担心开启profiling func导致的包体增大,分包工具会优化函数名

等待分包

android收集 + iOS收集

分包的收集,一般需要android和iOS单独收集

收集操作:

  • 点击开发者工具的预览(注意是预览,不是真机调试,在真机上跑游戏,覆盖尽可能多的场景
  • 当插件页显示的收集到增量函数个数相对稳定时,可以点击“我已收集好,继续下一步”

这里主要关注首包函数个数,一般跑完这两个步骤首包函数占整包函数个数的30%以上就差不多了

重复收集与生成

android和iOS收集完,基本就可以测试和发布了

有条件的话,可以尽量覆盖各种机型(主流品牌)再多跑几次收集

每次收集发现新增函数趋于稳定之后,就可以继续点生成profile分包或者生成release分包

每次点生成时,会先跳到前面的等待分包界面,完成后再回来

每次生成会当前的分包version会加1

关闭分包

如果想回退到未分包的版本,点击关闭代码分包即可

注意事项

上线前

  • 生成release版分包
  • 首包函数个数至少要有原始包函数总数的30%
  • 新增收集函数个数清零
  • 关注android或者iOS普通模式的子包是否过早加载(是否有wait for func的日志)
  • 关注iOS高性能是否有fetch js相关的日志

如果有最后两点,那就还要继续收集+生成分包

上线后

  • 小游戏包先不要删掉
  • 新增收集函数个数这个数据非常重要,要尽量保持关注,包括上线后

如果上线后,有玩家遇到新增函数个数,分包插件上也会更新(主要来源是iOS高性能),或者收到小游戏数据助手的相关告警,这个时候要继续生成分包,同时提审发布

FAQ

分包是否是必要的


对于 iOS 高性能模式,由于内存限制,游戏加载完整 wasm 基本就会内存 crash。分包能降低内存占用,同时我们对子包支持按需加载,才让游戏能稳定跑起来

所以如果是使用了 iOS 高性能模式则是必须的

对于 android 和 iOS 普通模式,分包主要目的是优化启动加载,另外这两个 runtime 下由于子包可以全量加载,因此对游戏运行影响最多只有加载子包的一次性影响

我们也会在启动 callmain 后 30s 提前加载子包,在这个时间之后才触发未收集函数的情况也不会有加载子包的影响

收集到什么时候可以结束


按照我们经验,一般首包函数有整包个数的 33%以上的时候就可以接受了,当然能尽量再收集完善刚好,个别游戏可能会接近 50%

这时候不代表没收集的函数都没用了,实际上有些函数可能只是调用比较冷门,后续还是可能会被调到,可以通过分包插件面板的新增收集函数个数来留意线上新增的情况,

如果线上新增较多(超过 50),可以考虑再往下分一次包然后提审发布

游戏内容难以遍历完整怎么办

我们针对这种情况也有线上patch可以进行补漏,但是patch有大小限制

建议新增收集函数个数超过100个的还是要生成新分包+发版本

分包总大小比原始包大


  1. 分包的目的主要是将启动时需要的包减小,一般分包后wasm首包可以控制在原包的1/3到1/2之间
  2. 子包是有延迟加载的,因此耗时上不需要看总的大小,看首包的减少量即可
  3. 一般iOS高性能模式才有内存使用瓶颈,而iOS上子包是按需加载的,可以缓解内存问题 因此,这里不需要关注分包后所有wasm包的总和,主要关注wasm首包(即minigame/wasmcode)的大小即可

新增收集的函数要重新再次提审才会在首包吗


对的,用户下载的代码包只能是提审发布过的

会不会最终跑到所有函数都收集的情况


目前还没出现这种情况,超过整包 50%的都很少

大部分游戏收集 1 小时的函数个数都在 33%到 50%之间

可以等收集函数超过 75%了再来考虑这个问题

iOS 高性能模式收集很卡


iOS 高性能模式由于加载子包的实现不同,刚开始收集时又基本是跑子包函数,所以最开始的收集会比较卡

这个时候可以观察分包插件面板,如果能看到有新增函数个数的变化,一般就是没问题的。如果出现卡顿(并且有新增函数)或者新增函数较多(超过 50),可以先继续往下生成分包,再进行收集。游戏运行会随着收集越来越流畅

iOS 高性能模式代码分包后内存反而变得很高


这种情况一般是太多新增函数(比如几百个),iOS 高性能模式的子包代码也会占用大量内存,可以继续生成分包,将这部分函数放在首包(放首包的内存占用相对小些)

iOS 高性能模式出现 impport section's count is too big


新版的插件已经规避这个问题,更新插件即可

没有看到增量分包的界面


由于增量分包是新增的功能,因此之前的项目不能被用来增量更新。更新分包插件后,第二次导出的版本开始才可以使用

增量分包没生效


请检查指定参考的旧版本以及当前版本是否都有 symbol 文件,以及是否有更换引擎或者其他导致代码变动较大的操作

如何更新分包插件


微信开发者工具会自动更新分包插件,一般不需要手动更新。可前往微信开发者工具-编辑器区域-拓展列表查看插件版本确认是否为最新版本

请勿使用小游戏版微信开发者工具,会出现插件无法正常更新或安装。请前往:适配文档-安装与使用,下载stable版本微信开发者工具。

分包插件安装失败


首先确认是否为stable版本开发者工具。

有两个地方可安装插件:

  1. 编辑器区域-拓展:搜索wasm-code-split,点击安装
  2. 菜单栏-设置-拓展设置,找到wasmcodesplit,点击进入详情页,点击获取

分包插件卡住

遇到流程卡住问题,一般先尝试关闭分包,然后重启开发者工具,再打开分包,大部分时候有奇效

内存优化版本未观察到内存优化


  1. 首先排查项目是否已经是内存优化版本的分包:插件面板当前后台服务版本为3(或者看framework最后的API_VERSION)
  2. 这里的内存优化主要针对iOS高性能模式,主要是减少了编译相关的内存(和函数个数相关,10w+函数的包可以减少约100M),可以通过在callmain或者raf之前暂停来观察
  3. 最终到游戏内有可能会上涨到和原来差不多,但这个是受gc策略和系统进程内存优化的影响,可以点右上角退出小游戏触发强制gc来观察

如何查看分包插件日志

当出现问题时,优先排查是否stable版本的微信开发者工具,能解决大部分问题。 若问题仍无法解决,可联系我们,提供日志排查。 日志获取方式:

菜单栏-微信开发者工具-调试-调试微信开发者工具,搜索关键字:extension host。可右键保存日志文件

Changelog

v1.1.13

Fixed

  • 1.1.12无法安装、更新

v1.1.12

Fixed

  • patch编译后未生效

v1.1.11

Fixed

  • 修复回退为旧分包方案的bug

v1.1.10

Fixed

  • 开发者工具插件偶现下载wk_import包失败错误

v1.1.9

Feature

  • 选择增量更新时可查看首包个数、最后收集时间

v1.1.8

Changed

  • 拉取分包时网络异常弹框提示

v1.1.6

Changed

  • 移除无用代码

v1.1.5

Fixed

  • iOS普通模式无法进入游戏
  • 安卓微信客户端8.0.25无法进入游戏

v1.1.4

Fixed

  • 修复iOS profile版在高性能模式下卡与内存不足的问题
  • 修复android偶现null function or function signature mismatch问题
  • 修复iOS普通模式运行出错的问题

v1.1.2

Changed

  • 插件新旧版本分包兼容

v1.1.0

Added

  • iOS高性能内存优化:
    • 使用条件:转换插件版本高于202212070000重新导出
  • 分包插件交互优化
    • 等待预处理提前到选择是否增量更新的界面,收集时可使用安卓和iOS同时进行
    • 收集界面增加连接状态、appid信息展示

v1.0.2

Added

  • 包体优化&广告买量启动优化
    • 使用条件:转换插件版本高于202212070000导出的包

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/WebGL2.html b/Design/WebGL2.html new file mode 100644 index 00000000..d82a0c5c --- /dev/null +++ b/Design/WebGL2.html @@ -0,0 +1,24 @@ + + + + + + WebGL2.0渲染支持说明 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

WebGL2.0渲染支持说明

适合使用场景

WebGL 是一种用于在 Web 浏览器中渲染图形的 API,基于 OpenGL ES 图形库的功能。WebGL 1.0 大致与 OpenGL ES 2.0 功能相匹配,而 WebGL 2.0 大致与 OpenGL ES 3.0 功能相匹配。 根据游戏项目统计,我们发现相对于WebGL1,更适合以下游戏需求:

  • 线性颜色空间渲染
  • 使用GPU Instancing提高渲染性能
  • 使用SRP Batcher提高渲染性能
  • 使用URP PostProcessing效果提升品质
  • 存在大量依赖OpenGL ES 3.0以上的Shader难以降低

用户占比

Unity WebGL较多渲染优化特性依赖WebGL2.0, 因此这里需要针对该特性在小游戏环境的支持进一步说明。

  • 小游戏Android平台在8.0.24(2022年中版本)已支持WebGL2, 用户占比>85%(2022.12),最新占比请查阅基础库版本分布
  • 小游戏iOS高性能模式需要iOS系统版本>=15.0,用户占比>75%(2022.12)
  • 小游戏高性能+模式可以支持iOS系统版本>=14.0用户使用WebGL2

已知兼容问题

  • iOS高性能使用WebGL2会存在较多问题,平台暂不保证所有能力完善,开发者务必验证游戏所用到的特性支持情况。
  • 对于WebGL2, 高性能+模式有更好的兼容性。

如遇到问题请联系我们详细排查。

iOS高性能模式开启GPU Instance,模型闪烁/消失/不绘制等问题

  • 原因:iOS WebKit对webGL2的支持存在问题,当uniform变量过多时,会出现绘制不正确、不绘制、效率变低等现象;

  • 解决方法

    1. 减少shader中Instance Props的大小;

    2. shader中添加instancing_options选项(可参考Unity官方文档说明)

      • assumeuniformscaling:开启后,默认object缩放为均匀缩放,uniform可以减少sizeof(mat4x4) * instance count的大小
      • forcemaxcount:batchSize:限制每次draw call的instance数量
    3. 根据机型分级,使用GPU instance特性或合批处理(已知iPhone7p及以下机型需要进一步限制instance count)

iOS高性能模式DrawMeshInstanced显示错乱

  • 原因:iOS WebKit对webGL2的支持存在问题,当批次较大时出现显示错误
  • 解决方法: iOS降低DrawMeshInstanced的参数matrices、count为32或更小的值

参考文档

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/fixScreen.html b/Design/fixScreen.html new file mode 100644 index 00000000..878353ff --- /dev/null +++ b/Design/fixScreen.html @@ -0,0 +1,33 @@ + + + + + + 屏幕适配 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

屏幕适配

安全区域适配

小游戏的屏幕适配与 unity 游戏适配常见手机屏幕没有区别。常见的适配方式都可以在小游中使用。区别的是一些屏幕信息的获取。 如安全区域的获取需调用 WX.GetWindowInfo 得到其中的安全区域。 如下是适配刘海屏(这里以竖屏游戏按高度适配为例)的示例:

csharp
var info = WX.GetWindowInfo();
+float py = (float)info.safeArea.top / (float)info.windowHeight;
+// Rootrect初始时设置其Anchor,使其与父节点一样大,也就是屏幕的大小
+// 调整屏幕移到刘海屏下面,
+Rootrect.anchorMin = new Vector2((float)info.safeArea.left / (float)info.windowWidth, -(float)info.safeArea.top / (float)info.windowHeight);
+// 重新计算缩放,让高度占满刘海屏以下的区域
+cs.referenceResolution = new Vector2(cs.referenceResolution.x, cs.referenceResolution.y * (1.0f+py));

安全区域wx.getWindowInfo 中获取的安全区域的数值,需要乘以 pixelRatio 才为 Unity 中的大小,而且手机屏幕左上角为(0,0)

高分辨屏下模糊问题

因为 Unity 2019.3 之前的版本对高分辨屏适配不是很好。会出现画面模糊的情况,所以最好选择Unity 2019.3之后的版本来构建你的游戏。如果游戏不能升级版本,也可以引入SDK,在初始化 SDK 后,SDK 会自动对页面做一个兼容适配,避免模糊的问题。

csharp
//初始化SDK
+WX.InitSDK((int code)=> {
+// 你的主逻辑
+});

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/iOSOptimization.html b/Design/iOSOptimization.html new file mode 100644 index 00000000..f9e88e97 --- /dev/null +++ b/Design/iOSOptimization.html @@ -0,0 +1,25 @@ + + + + + + iOS 高性能与高性能+模式 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

iOS 高性能与高性能+模式

什么是高性能模式

在 iOS 环境下,标准的微信小游戏 WASM 运行模式是无 JIT, 对于计算性能要求较高的游戏会受到比较大的限制。常见情况是:

  1. 中低端机帧率较低,流畅度难以达到上线标准
  2. 对 CPU 计算资源消耗过高,运行一段时间后设备温度持续上升

小游戏环境框架提供了高性能运行模式,该运行模式下 CPU 算力得到明显提升。但该模式也存在更严格的内存与代码包体限制,需要开发者采取合适的手段以达到最优。

什么是高性能+模式

高性能+模式开创新地在保留游戏独立进程的基础上将渲染重新挪回了微信进程,这使得渲染效果和渲染内存消耗都得到了改善。详细文档请查阅高性能+模式。 特别地,建议使用WebGL2、内存压力大的游戏开启此选项。开启后请验证进程内存、渲染兼容性、帧耗时数据是否正常。

性能提升

CPU 消耗

通过多款游戏项目,我们得到实际游戏项目的 CPU 占用如下图所示:

我们得到以下结论:

  • 高性能模式在长期执行过程中 CPU 明显低于普通模式,后者长期处于高 CPU 占用因此长期运行容易越来越烫
  • 游戏启动初始阶段,高性能模式存在 CPU 高峰用于 WebAssembly 编译优化
  • 采用代码分包后,高性能模式能较快回落 CPU 占用并维持正常水平

压力测试

使用 Unity 所提供的 Benchmark Demo 的部分案例进行评测:

  • Instntiate & Destroy
  • Animation & Skinning
  • Physics Cubes
  • AI Agents

测试过程为不断增加运算复杂度,直到帧率下降到特定数值。

分数越高,代表的运行能力越强。

上图分别是 iOS 端普通模式与高性能模式的得分,可以看到在几个压测示例中高性能模式均明显优于普通模式。

经实际游戏测试,游戏帧率都会得到明显改善,虽无法达到 Benchmark 几乎一个数量级的差异。

如何开通

iOS 端小游戏高性能模式适用于遇到 iOS 环境运行性能不足,运行发烫的小游戏。

  • 需要该能力的开发者登录微信公众平台 -> 能力地图 -> 研发能力 -> 生产提效包 -> 点击开通高性能模式。
  • 开通成功后,过配置 game.json 的 iOSHighPerformance 为 true 则可进入高性能模式,通过去掉此开关可以正常回退到普通模式,以便两种模式对比。

高性能模式限制

内存限制

高性能模式下,iOS 低端机(6s/7/8 等)2G RAM 机型的内存限制为 1G,中高端机(7P/8P/iPhoneX/XSAMX/11/12 等)3G 以上内存机型的内存限制为 1.5G(安全内存建议1.2G~1.3G),因此开发者务必保证内存峰值不超过该数值。

建议开发者根据指引优化 Unity WebGL 的内存

代码体积限制

高性能模式下,WASM 代码将被编译并优化,需要占用更多的编译消耗与内存。如果未进行优化前,可以明显感受到启动开始阶段(如启动前 1 分钟内)设备发烫。

上线发布时,特别建议使用WASM 代码分包+压缩纹理+UnityHeap预留这几种优化手段。

QA

1. 如何判别游戏否已经开启了高性能模式?

  • 删除本地小游戏(包括开发版、体验版和正式版),
  • 重新进入小游戏并打开调试,查看 vconsole 日志, 关注"game start"日志中的"render"字段为"h5"则为高性能模式
  • 系统和基础库要求是: iOS>=14.0, 基础库>=2.23.1, 用户占比约为 90%。 对于不满足此要求时回退为普通执行方式。

2. 使用高性能模式下,游戏本身是否需要做修改?

  • 业务代码无需做任何调整,普通模式与高性能模式可以无缝切换。
  • 高性能模式下,请不要服务端设置 Cookie,游戏端内因为跨域问题会读取不到 Cookie
  • Android 下载资源无问题,高性能模式提示资源下载失败等网络问题,请参考文档网络通信适配关于跨域的问题

3. iOS 报错提示未开启 gzip/br 压缩

可通过微信开发者工具查看 Content-Encoding 是否为 gzip 或 br

如果有正确压缩,可忽略这个错误。

问题原因:由于跨域获取不到 Content-Encoding 头

解决办法:增加跨域头部"Access-Control-Expose-Headers": "Content-Length, Content-Encoding",

4. 资源下载提示isTrusted

多半由于跨域问题导致,可通过开发者工具查看对应资源的 Response Header 是否有跨域头, 请参考文档网络通信适配关于跨域的问题

5. 卡在启动封面无法启动

  • 右上角打开调试,重启小游戏,点三次下方的 Unity logo 打开 vconsole
  • 如果出现资源访问失败,但 Android 和开发者工具却可以下载则参考 QA3 关于跨域问题
  • 15.4 系统出现"Not implemented"、"Class::FromIl2CppType",此为 Unity & iOS 15.4 的 BUG,微信提供的 wasm 代码分包(推荐)或 Unity WebGL 官方论坛的临时修复方案
  • 16.7/17.0系统出现"glGetString (GL_EXTENSIONS) - failure", 苹果官方17.1已fix。对于未更新系统的玩家,也可使用高性能+模式处理。详情请查阅: Unity社区讨论iOS浏览器Webkit BUG,

6. 个别游戏 UI 会出现闪烁问题

7. 为什么开启了高性能模式,游戏启动很烫?

  • 请参考本文前面部分,如果未使用代码分包的情况下 JIT 编译优化将耗费大量性能

8. 使用高性能模式下,不优化内存、WASM 代码包体积就发布上线可以吗?

  • 不建议。iOS 高性能模式虽然能提运行算力,但对内存、WASM 包体积有更苛刻的要求,需要更多的精力做优化。如果不做任何优化的情况下,很有可能会遇到超出内存限制而崩溃,启动时发烫现象严重等问题。上线发布时,特别建议使用WASM 代码分包+压缩纹理+UnityHeap预留这几种优化手段。

9. iOS 高性能模式与安卓性能对比如何?

  • 两种系统环境下,WASM 执行都是 JIT 代码。但由于底层虚拟机差异过大以及自身不断迭代,难以横向对比。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/performance-standard/PerfMeasure_20230517.html b/Design/performance-standard/PerfMeasure_20230517.html new file mode 100644 index 00000000..e574da98 --- /dev/null +++ b/Design/performance-standard/PerfMeasure_20230517.html @@ -0,0 +1,24 @@ + + + + + + Unity WebGL小游戏适配方案性能标准 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Unity WebGL小游戏适配方案性能标准

为什么需要性能评测标准?

Unity性能评测标准用于开发者优化游戏性能数据,提升用户体验。评测标准根据小游戏整体的性能数据表现,结合操作系统、机型分档等多种维度建立。

评测标准细则

性能基线

  1. 性能基线机型并非特定,但建议综合CPU、内存、GPU等选取性能相当的机型
  2. 更新时间:2023-05-17
档位Android参考机型iOS参考机型
高档⼩⽶10(⾼通骁⻰865)iPhone13
中档VIVO S7(⾼通骁⻰765G)、红米k30iPhone11
低档OPPO r9s(通骁⻰625)iPhone7/8/X

指标与测量方法

Unity小游戏的启动可参考启动流程与时序

定义测量方法
首资源包游戏首个data资源文件位于导出目录/webgl/md5.webgl.data.unityweb.bin.txt, CDN使用gzip压缩
WASM代码游戏代码压缩包位于导出目录/minigame/wasmcode/md5.webgl.wasm.code.unityweb.wasm.br, CDN使用gzip压缩
核心资源除首资源包外进入游戏核心玩法所需的资源量业务自定下载,通常为AssetBundle
CALLMAIN引擎和首场景(Loading)初始化通过timelog,或日志查看“CALLMAIN耗时”
游戏初始化完成引擎和首场景完成,出现首个业务场景通过timelog, 或日志查看“游戏启动耗时”
游戏可交互完成游戏核心场景完成通常定义为用户可交互的时机,可通过启动留存上报能力上报统计。eg:休闲游戏为核心玩法,RPG游戏为创角
内存峰值内存峰值进程内存峰值,测量方法请参考优化Unity WebGL的内存
内存异常退出运行时长由于内存不足而使小游戏发生Crash时,当前游戏的运行时长,表示游戏的稳定运行时长通过小游戏数据助手查看(仅包含线上用户数据) 数据路径:数据 - 性能分析 - 运行性能 - 内存异常退出分析
帧率核心玩法的平均帧率测量5分钟以上游戏核心玩法帧率,取平均值
卡顿率核心玩法的平均卡顿率测量5分钟以上游戏核心玩法卡顿率,取平均值

代码与资源体积

能力下载量
首资源包(gzip压缩后)<5MB
WASM代码(br压缩后)<5MB
核心玩法资源<30MB

评测工具

启动性能

使用网络模拟工具1MB/s条件,使用Unity适配提供TimeLog窗口、运行日志或小游戏云测试获取性能数据。

运行性能

使用PerfDog测试,PerfDog记录性能数据并上传,取平均值,每种机型测试3组数据再取平均,内存峰值取最大值。

评测标准

评测标准更新时间:2023-05-17(历史现网标准请查阅文档

评测标准依赖于 现网真实玩家上报的性能数据人工批量测试数据 统计得出。

开发者需要关注哪些性能指标

阶段重点关注指标
启动1. 游戏初始化完成耗时 2. 游戏可交互耗时
运行1. 内存峰值 2. FPS均值 3. 卡顿率 4. 内存异常退出率(iOS) 5. 内存异常退出运行时长
兼容性问题1. 逻辑异常 2. 黑/白屏 3. JS Error

游戏类型说明

分类定义
重度玩法较复杂,通常包含较多游戏场景或支持多人在线游戏(eg: MMO、SLG品类等)
中度包含一定养成玩法、内置内购商城等(eg: 模拟经营、卡牌等)
轻度仅包含简单操作、无养成体系、无内购,以休闲娱乐为主(eg: 棋牌等)

iOS性能评测标准

启动性能

运行性能

重点关注:内存峰值GC后内存峰值内存异常退出率内存异常退出运行时长

Android性能评测标准

启动性能

运行性能

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/performance-standard/PerfMeasure_old.html b/Design/performance-standard/PerfMeasure_old.html new file mode 100644 index 00000000..8f541cad --- /dev/null +++ b/Design/performance-standard/PerfMeasure_old.html @@ -0,0 +1,24 @@ + + + + + + Unity WebGL小游戏适配方案性能标准 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

Unity WebGL小游戏适配方案性能标准

为什么需要性能评测标准?

性能评测标准希望能引导开发者优化相关性能数据,提升用户体验。

开发者需要关注哪些性能指标

从小游戏的运行周期来看,主要由启动和运行两个阶段产生性能问题。

启动阶段:启动时长,该数据将显著影响用户打开留存率 运行阶段:内存峰值、流畅度、CPU占用、网络等 其他兼容性问题,包括逻辑异常、黑屏等严重问题

评测标准细则

性能基线

机型档位

能力Android参考机型iOS参考机型
高档⼩⽶10(⾼通骁⻰865)iPhone13
中档VIVO S7(⾼通骁⻰765G) 红米k30iPhone11
低档OPPO r9s(通骁⻰625)iPhone7/8/X

指标与测量方法

Unity小游戏的启动可参考启动流程与时序

定义测量方法
首资源包游戏首个data资源文件位于导出目录/webgl/md5.webgl.data.unityweb.bin.txt, CDN使用gzip压缩
WASM代码游戏代码压缩包位于导出目录/minigame/wasmcode/md5.webgl.wasm.code.unityweb.wasm.br, CDN使用gzip压缩
核心资源除首资源包外进入游戏核心玩法所需的资源量业务自定下载,通常为AssetBundle
callmain引擎和首场景(Loading)初始化通过timelog,或日志查看“callMain耗时”
游戏初始化完成引擎和手场景完成,出现首个业务场景通过timelog, 或日志查看“游戏启动耗时”
游戏可交互完成游戏核心场景完成业务自定义,典型地:休闲游戏为核心玩法,RPG游戏为创角
内存内存峰值进程内存峰值,测量方法请参考优化Unity WebGL的内存
帧率核心玩法的平均帧率测量5分钟以上游戏核心玩法帧率,取平均值

评测工具

启动性能: 使用网络模拟工具1MB/s条件,使用Unity适配提供TimeLog窗口或运行日志获取性能数据。

运行性能: 使用PerfDog测试,PerfDog记录性能数据并上传,取平均值,每种机型测试3组数据再取平均,内存峰值取最大值。

代码与资源体积

能力下载量
首包资源(gzip压缩后)<5M
WASM代码(br压缩后)<5M
核心玩法资源<30MB

Android 评测标准

高档机中档机低档机
首资源包下载<3s<4s<5s
callmain<3s<5s<7s
游戏初始化完成<8s<10s<12s
游戏可交互完成<12s<15s<20s

运行性能

高档机中档机低档机
内存<1.5G<1.2G<1G
帧率>50>40>30

iOS 评测标准

高档机中档机低档机
首资源包下载<3s<4s<5s
callmain<2s<4s<5s
游戏初始化完成<6s<8s<10s
游戏可交互完成<10s<12s<15s

运行性能

高档机中档机低档机
内存<1.4G<1.2G<800MB
帧率>50>40>30

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/video.html b/Design/video.html new file mode 100644 index 00000000..3a5634d5 --- /dev/null +++ b/Design/video.html @@ -0,0 +1,39 @@ + + + + + + 视频设计规范 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + +
Skip to content

视频设计规范

建议启动视频内带有团队宣传logo动画,游戏logo动画,带有吸引力的游戏玩法视频

视频格式参考:

Loading 视频规范:
+横屏视频:16:9(素材分辨率:960 px × 540 px)
+竖屏视频:9:16(视频分辨率:750 px × 1334 px)
+视频尺寸:不超过 10MB
+视频时长:6~15 秒
+支持格式:MP4
+注:视频会在 Loading 期间重复播放
+----
+以下为视频建议参数(仅供参考)
+视频编码:H.264
+FPS:24
+码率:小于 800 kbit/s
+MP4 Profile:Main
+音轨格式:AAC
+音轨Sample Rate:44.1 kHz
+音轨 Datarate:96 kbit/sec

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/Design/wasmWaterMark.html b/Design/wasmWaterMark.html new file mode 100644 index 00000000..7efad66b --- /dev/null +++ b/Design/wasmWaterMark.html @@ -0,0 +1,25 @@ + + + + + + wasm水印插件 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

wasm水印插件

如果同时使用代码分包插件,需要在使用分包插件后,再使用水印插件对分包后的wasm代码打水印

说明:

在平台原有相似度检测基础上,为进一步保障wasm小游戏的代码安全,引入wasm水印机制 已添加水印的wasm游戏,若遭遇恶意人员扒包抄袭,平台可通过水印准确检测出游戏的原作者,并处罚恶意抄袭人员

使用方式:

插件依赖微信开发者工具1.05.2104251 RC 及以上,稳定版 1.05.2105100 及以上

添加插件

部分示意图可能有出入,请升级微信开发者工具版本

打开拓展设置,找到水印工具,添加插件

使用插件

在目录树上方工具栏找到水印工具icon,点击显示水印插件面板

项目首次使用插件默认会启用打水印功能。

插件检测并展示项目中的wasm文件,开发者自行决定是否需要上传并打水印。

点击上传按钮后,插件会自动执行逻辑

正在打水印

下载中

已完成

完成后,即可测试小游戏是否正常运行,若有异常,可点击还原wasm文件到初始状态,重新打水印。

当有两个wasm文件时,操作同理

若不想使用水印功能,点击关闭水印,wasm代码回到初始状态

注意

打水印和下载过程可能会有一定耗时,请耐心等待。

若AppID为测试号,或者是小程序AppID,会出现如下界面,更换正确的AppID后重新检测即可

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/README.html b/README.html new file mode 100644 index 00000000..382b06ea --- /dev/null +++ b/README.html @@ -0,0 +1,25 @@ + + + + + + 微信小游戏Unity/团结引擎适配方案 | 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + +
Skip to content

微信小游戏Unity/团结引擎适配方案

欢迎使用 Unity WebGL 小游戏适配方案(又称Unity/团结引擎快适配),本方案设计目的是降低 Unity 游戏转换到微信小游戏的开发成本。基于WebAssembly技术,无需更换Unity引擎与重写核心代码的情况下将原有游戏项目适配到微信小游戏。

官方文档:https://wechat-miniprogram.github.io/minigame-unity-webgl-transform/

方案特点

  • 保持原引擎工具链与技术栈
  • 无需重写游戏核心逻辑,支持大部分第三方插件
  • 由转换工具与微信小游戏运行环境保证适配兼容,保持较高还原度
  • 微信小游戏平台能力以C# SDK方式提供给开发者,快速对接平台开放能力

转换案例

我叫MT2(回合战斗)旅行串串(休闲)谜题大陆(SLG)热血神剑(MMO)

查阅更多转换案例

安装与使用

PackageManager(git安装URL): https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git

UnityPackage:下载地址

版本更新请查看更新日志,Unity/团结引擎详细安装请查阅SDK安装指引

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/assets/CHANGELOG.md.Jm0i_MoD.js b/assets/CHANGELOG.md.Jm0i_MoD.js new file mode 100644 index 00000000..563e8f69 --- /dev/null +++ b/assets/CHANGELOG.md.Jm0i_MoD.js @@ -0,0 +1,2 @@ +import{_ as a,c as e,o as i,a4 as l}from"./chunks/framework.Br2U662V.js";const x=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"CHANGELOG.md","filePath":"CHANGELOG.md"}'),r={name:"CHANGELOG.md"},t=l(`

SDK安装指引:微信小游戏Unity、团结引擎转换插件WXSDK

稳定版本

  1. UnityPackage:下载地址
  2. PackageManager(git URL): https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git

2024-10-18 【预发布】

PackageManager(git URL): https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git#pre-v0.1.22

Feature

Fixed

2024-10-8 【重要更新】

Feature

Fixed

2024-8-13 【重要更新】

Feature

Fixed

2024-7-09 【普通更新】

Feature

Fixed

2024-5-17 【普通更新】

Fixed

2024-5-15 【普通更新】

Feature

2024-4-26 【普通更新】

Fixed

2024-4-17 【普通更新】

Feature

Fixed

2024-4-3 【重要更新】

包含重要bugfix、特性支持

Fixed

2024-3-28 【普通更新】

Fixed

2024-3-5 【普通更新】

Fixed

2024-1-18 【普通更新】

Fixed

2024-1-15 【普通更新】

Feature

Fixed

2024-1-2 【重要更新】

包含重要bugfix、特性支持

Feature

Fixed

2023-12-18 【重要更新】

包含重要bugfix、特性支持

Feature

Fixed

2023-12-12 【重要更新】

包含重要bugfix、特性支持

Feature

2023-12-08 【重要更新】

包含重要bugfix、特性支持

Feature

Fixed

2023-11-29 【普通更新】

Fixed

2023-11-28

【重要更新】包含重要bugfix、特性支持

Feature

Fixed

2023-11-10

【普通更新】

Feature

2023-11-02

【普通更新】

Fixed

2023-10-20

【普通更新】

Feature

Fixed

2023-10-11【普通更新】

Feature

2023-9-26

【重要更新】包含重要bugfix、特性支持

Feature

Fixed

2023-09-20

Feature

2023-09-01

Feature

Fixed

2023-08-24

Feature

Fixed

2023-08-18

Feature

Fixed

2023-08-10

Feature

2023-08-3

Feature

更新内容:

Fixed

2023-07-27

Feature

Fixed

2023-07-20

Feature

Fixed

2023-07-12

Feature

2023-07-05

Feature

Fixed

2023-06-29

Feature

Fixed

2023-06-16

Fixed

2023-06-14

Feature

Fixed

2023-06-12

Fixed

2023-06-7

Feature

Fixed

2023-06-1

Feature

Fixed

2023-05-24

Feature

Fixed

2023-05-22

Feature

Fixed

  OnKeyboardInputCallbackResult -> OnKeyboardInputListenerResult
  getGameClubDataOption -> GetGameClubDataOption
+  openPageOption -> OpenPageOption

2023-04-26

Changed

2023-03-31

Feature

2023-02-22

Feature

2023-02-15

Fixed

2023-02-9

Feature

Fixed

2023-01-17

Fixed

2023-01-17

Feature

Fixed

2023-01-04

Feature

Fixed

2022-12-28

Feature

Fixed

2022-12-22

Fixed

2022-12-21

Feature

2022-12-7

Feature

Fixed

2022-11-30

Feature

2022-11-23

Feature

Fixed

2022-11-17

Feature

2022-11-9

Feature

Fixed

2022-10-27

Feature

压缩纹理回退使用png时也支持缓存逻辑

Fixed

使用node命令时同时查找默认安装路径 修复Win7下使用Unity2021生成symbols时导致的卡死问题

2022-10-20

Feature

2022-10-12

Feature

Fixed

2022-9-28

Feature

Fixed

2022-9-21

Feature

Fixed

2022-9-13

Feature

2022-9-8

Fixed

Feature

2022-9-7

Fixed

2022-8-31

Fixed

2022-8-26

Feature

2022-8-17

Feature

2022-8-11

Fixed

2022-8-10

Feature

Fixed

2022-7-28

Feature

2022-7-20

Feature

Fixed

Feature

2022-7-14

Fixed

2022-7-1

Fixed

2022-6-30

Fixed

2022-6-28

Feature

Fixed

2022-6-18

Fixed

2022-6-16

Feature

Fixed

2022-6-13

Fixed

2022-6-8

Feature

Fixed

2022-6-7

Feature

2022-6-1

Feature

2022-5-31

Feature

2022-5-30

Fixed

2022-5-26

Changed

Fixed

2022-5-24

Feature

2022-4-29

Fixed

2022-4-26

Fixed

Feature

2022-4-24

Fixed

更新独立域插件版本1.0.60

2022-4-22

Fixed

更新独立域插件版本1.0.58

Feature

2022-4-18

Feature

2022-4-14

Feature

2022-4-11

Changed

2022-3-29

Changed

2022-3-22

Changed

2022-3-7

Changed

2022-3-7

Changed

2022-2-17

Changed

2022-2-15

Fixed

2022-2-14

Feature

2022-2-11

Feature

2022-1-26

Feature

2022-1-25

Fixed

2022-1-24

Feature

2022-1-21

Feature

Changed

  1. 自动清理存量旧文件
  2. 达到缓存上限时清理更多空间,具体值可通过minigame/unity-namespace.js中releaseMemorySize修改
  3. 上报unity版本和转换插件版本
  4. 支持以文件名全匹配的方式忽略缓存
  5. 插件错误报实时日志
  6. pc小游戏兼容

2022-1-20

Feature

2022-1-17

Fixed

Changed

2022-1-13

Fixed

2022-1-7

Fixed

2021-12-31

Fixed

2021-12-30

Fixed

2021-12-20

Fixed

2021-12-16

Feature

2021-12-10

Fixed

2021-12-06

Feature

Fixed

2021-12-02

Fixed

2021-11-30

Changed

Fixed

2021-11-19

Fixed

2021-11-18

Feature

增加bundle相关导出配置

Fixed

Changed

2021-10-26

Feature

2021-10-09

Feature

2021-09-23

Fixed

2021-09-22

Feature

Feature

Feature

2021-09-14

Feature

Fixed

2021-09-06

Feature

2021-8-20

Feature

2021-8-12

Feature

2021-8-10

Changed

2021-08-05

Feature

2021-08-04

Fixed

2021-08-02

Fixed

2021-08-01

Changed

2021-07-31

Feature

Changed

2021-07-26

Feature

2021-07-26

Feature

2021-07-20

Fixed

2021-07-19

Changed

2021-07-13

Fixed

Changed

2021-07-09

Fixed

2021-07-02

Fixed

2021-06-30

Fixed

Feature

2021-06-29

Fixed

Feature

Removed

Changed

Others

独立域插件更新为(1.0.11)

2021-06-10

Fixed

`,582),h=[t];function o(d,u,n,s,c,b){return i(),e("div",null,h)}const q=a(r,[["render",o]]);export{x as __pageData,q as default}; diff --git a/assets/CHANGELOG.md.Jm0i_MoD.lean.js b/assets/CHANGELOG.md.Jm0i_MoD.lean.js new file mode 100644 index 00000000..b77616d8 --- /dev/null +++ b/assets/CHANGELOG.md.Jm0i_MoD.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as l}from"./chunks/framework.Br2U662V.js";const x=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"CHANGELOG.md","filePath":"CHANGELOG.md"}'),r={name:"CHANGELOG.md"},t=l("",582),h=[t];function o(d,u,n,s,c,b){return i(),e("div",null,h)}const q=a(r,[["render",o]]);export{x as __pageData,q as default}; diff --git a/assets/Design_AndroidProfile.md.DdtvteaF.js b/assets/Design_AndroidProfile.md.DdtvteaF.js new file mode 100644 index 00000000..85ad9eed --- /dev/null +++ b/assets/Design_AndroidProfile.md.DdtvteaF.js @@ -0,0 +1,6 @@ +import{_ as i,c as s,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/androidprofile1.CWmGtjYo.png",n="/minigame-unity-webgl-transform/assets/androidprofile2.BV1rYep4.png",l="/minigame-unity-webgl-transform/assets/androidprofile5.v23kq4o6.png",r="/minigame-unity-webgl-transform/assets/androidprofile3.C3xDSI1N.png",p="/minigame-unity-webgl-transform/assets/androidprofile4.D2zXydy3.png",u=JSON.parse('{"title":"使用Android CPU Profiler性能调优","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AndroidProfile.md","filePath":"Design/AndroidProfile.md"}'),o={name:"Design/AndroidProfile.md"},h=e('

使用Android CPU Profiler性能调优

  1. 转换导出插件勾选"Profiling-funcs", 请勿使用Development(该模式将极大降低性能)。 发布上线版本请务必关闭该选项!

  2. 在Android微信小游戏打开调试进行录制

  3. 停止性能数据录制

    与步骤1相似,在相同的菜单中选择Stop CPU Profile

  4. 传输录制文件到PC

    录制结束后,Android会生成一份xxx.cpuprofile,该文件格式可以使用chrome进行解析。 因此我们需要将录制后的文件传输到PC使用chrome进行分析。 文件路径通常为:Android/data/com.tencent.mm/MicroMsg/appbrand/trace

  5. 利用PC(Windows/Mac)的Edge/Chrome加载数据

    以Edge为例:浏览器菜单打开"更多工具-开发人员工具-右上角...-更多工具-JavaScript探测器",然后点击加载前面导出的cpuprofile文件即可。

    视图有多种方式,可选择"图表"(Chart)分析每一帧游戏函数耗时情况

  6. 使用JavaScriptProfile进行数据分析

注意:

  1. 编译版本仅当导出勾选Profiling-funcs(推荐)或Development时才能在函数堆栈中看到可读函数名。
  2. 特殊情况下,如果游戏勾选Profiling-funcs会导致代码包过大,那么不要使用此选项。此时得到的Profile中函数为数字ID,有两种做法进行解读:
  3. 如希望能从游戏启动立即抓取profile,请在game.js末尾代码稍作修改:
    js
    const gl = GameGlobal.canvas.getContext('webgl') 
    +    gl.clear(gl.COLOR_BUFFER_BIT);
    +    setTimeout(() => {
    +    gameManager.startGame();
    +    GameGlobal.manager = gameManager;
    + }, 10000);
    修改后,游戏启动将会有10s黑屏,可在此期间打开调试。
  4. 最新版本Chrome/Edge已经将Javascript Profiler默认隐藏,你可以使用微信开发者工具查看.cpuprofiler,或是通过以下方式将它在浏览器显示出来: image
`,4),d=[h];function g(k,c,m,E,f,_){return a(),s("div",null,d)}const C=i(o,[["render",g]]);export{u as __pageData,C as default}; diff --git a/assets/Design_AndroidProfile.md.DdtvteaF.lean.js b/assets/Design_AndroidProfile.md.DdtvteaF.lean.js new file mode 100644 index 00000000..5a638833 --- /dev/null +++ b/assets/Design_AndroidProfile.md.DdtvteaF.lean.js @@ -0,0 +1 @@ +import{_ as i,c as s,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/androidprofile1.CWmGtjYo.png",n="/minigame-unity-webgl-transform/assets/androidprofile2.BV1rYep4.png",l="/minigame-unity-webgl-transform/assets/androidprofile5.v23kq4o6.png",r="/minigame-unity-webgl-transform/assets/androidprofile3.C3xDSI1N.png",p="/minigame-unity-webgl-transform/assets/androidprofile4.D2zXydy3.png",u=JSON.parse('{"title":"使用Android CPU Profiler性能调优","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AndroidProfile.md","filePath":"Design/AndroidProfile.md"}'),o={name:"Design/AndroidProfile.md"},h=e("",4),d=[h];function g(k,c,m,E,f,_){return a(),s("div",null,d)}const C=i(o,[["render",g]]);export{u as __pageData,C as default}; diff --git a/assets/Design_AssetDescription.md.5qrDTdVw.js b/assets/Design_AssetDescription.md.5qrDTdVw.js new file mode 100644 index 00000000..3a6c3ccc --- /dev/null +++ b/assets/Design_AssetDescription.md.5qrDTdVw.js @@ -0,0 +1 @@ +import{_ as t,c as d,o as r,a4 as e}from"./chunks/framework.Br2U662V.js";const u=JSON.parse('{"title":"MiniGameConfig.asset 配置文件说明","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AssetDescription.md","filePath":"Design/AssetDescription.md"}'),o={name:"Design/AssetDescription.md"},a=e('

MiniGameConfig.asset 配置文件说明

位于 Assets/WX-WASM-SDK-V2/Editor/MiniGameConfig.asset 即为 WXSDK 的导出配置文件,其中部分配置可在微信小游戏导出面板中可视化配置,本节将对配置文件中各项字段进行说明,开发者可直接修改其配置内容。

ProjectConfig:

字段类型说明
projectNamestring项目名称。
Appidstring微信小游戏Appid,前往 https://mp.weixin.qq.com/ 注册获得。
CDNstring游戏CDN前缀。
assetLoadTypeint首资源包加载方式,0: CDN加载;1: 小游戏包内加载。
compressDataPackagebool将首包资源Brotli压缩, 降低资源大小. 注意: 首次启动耗时可能会增加200ms, 仅推荐使用小游戏分包加载时节省包体大小使用。
VideoUrlstring加载阶段视频URL,可缺省。
DSTstring导出路径。
StreamCDNstring已废弃。
bundleHashLengthint自定义Bundle文件名中hash部分长度,默认值32,用于缓存控制。
bundlePathIdentifierstring路径中包含特定标识符开始下载bundle,将被自动缓存。半角分号分隔。
bundleExcludeExtensionsstring排除路径下指定类型文件不缓存。半角分号分隔。
AssetsUrlstring已废弃。
MemorySize: 256int游戏内存大小(MB)。
HideAfterCallMainboolcallmain完成后是否立即隐藏加载封面。
preloadFilesstring预下载列表。半角分号分隔。
Orientationint设备方向,0:Portrait; 1:Landscape; 2:LandscapeLeft; 3:LandscapeRight。
bgImageSrcstring启动背景图。
dataFileSubPrefixstring拼接在DATA_CDN和首包资源文件名的路径,用于首包资源没放到DATA_CDN根目录的情况。
maxStorageint最大缓存容量,单位MB,设置后若接近容量阈值将自动回收。
defaultReleaseSizeint清理缓存时默认额外清理的大小,单位Bytes,默认值30MB。
texturesHashLengthint微信压缩纹理工具处理的尾部hash长度,用于识别缓存。
texturesPathstring微信压缩纹理工具处理的纹理CDN拼接路径。
needCacheTexturesbool是否缓存微信压缩纹理工具处理的贴图资源。
loadingBarWidthint加载进度条的宽度,默认240。
needCheckUpdatebool是否需要启动时自动检查小游戏是否有新版本。
disableHighPerformanceFallbackbool是否禁止开启高性能模式后在不支持的iOS设备上回退为普通模式,注意:不要随意修改,只有开通高性能模式后并确认不回退才修改。
IOSDevicePixelRatiofloatIOS限制固定的分辨率,以减少内存,但是会降低游戏画面品质。

SDKOptions:

字段类型说明
UseFriendRelationbool是否使用好友关系链。
UseCompressedTexturebool已废弃。
UseMiniGameChatbool是否使用社交组件。
PreloadWXFontbool是否使用预载系统字体。

CompileOptions:

字段类型说明
DevelopBuildboolDevelopment Build.
AutoProfileboolAutoconnect Profiler.
ScriptOnlyboolScripts Only Build.
Il2CppOptimizeSizebool对应于Il2CppCodeGeneration选项,勾选时使用OptimizeSize(默认推荐),生成代码小15%左右,取消勾选则使用OptimizeSpeed。游戏中大量泛型集合的高频访问建议OptimizeSpeed,在使用HybridCLR等第三方组件时只能用OptimizeSpeed。(Dotnet Runtime模式下该选项无效)。
profilingFuncsboolProfiling Funcs.
Webgl2boolWebGL2.0
fbslimbool导出时自动清理UnityEditor默认打包但游戏项目从未使用的资源,瘦身首包资源体积。(团结引擎已无需开启该能力)。
DeleteStreamingAssetsboolClear Streaming Assets.
ProfilingMemoryboolProfiling Memory.
CleanBuildboolClean WebGL Build.
CustomNodePathstring已废弃。
showMonitorSuggestModalbool是否显示最佳实践检测弹框。
enableProfileStatsbool是否显示性能面板。
enableRenderAnalysisbool是否显示渲染分析日志(develop build才生效)。
iOSAutoGCIntervalintiOS高性能模式自动GC间隔(毫秒)。
enableIOSPerformancePlusbool是否使用iOS高性能Plus。
brotliMT: 1bool是否使用brotli多线程压缩
autoAdaptScreenbool是否使用自适应屏幕尺寸变化

CompressTexture:

以下是微信压缩纹理工具涉及配置,如未使用微信压缩纹理工具可以不予设置。

字段类型说明
halfSizebool已废弃。
useDXT5bool是否开启 PC 压缩纹理。
bundleSuffixstring已废弃。
parallelWithBundleint已废弃。
bundleDirstring自定义 AB 包目录路径。
dstMinDirstring压缩纹理产物输出目录。
debugModebool是否开启仅 ASTC 模式。
forcebool是否强制重新执行。

PlayerPrefsKeys:

使用PlayerPref接口时传入的key,此处设置将预先加载。

FontOptions:

字体相关配置。请阅读 WXFont章节

字段类型说明
CJK_Unified_Ideographsbool-
C0_Controls_and_Basic_Latinbool-
CJK_Symbols_and_Punctuationbool-
General_Punctuationbool-
Enclosed_CJK_Letters_and_Monthsbool-
Vertical_Formsbool-
CJK_Compatibility_Formsbool-
Miscellaneous_Symbolsbool-
CJK_Compatibilitybool-
Halfwidth_and_Fullwidth_Formsbool-
Dingbatsbool-
Letterlike_Symbolsbool-
Enclosed_Alphanumericsbool-
Number_Formsbool-
Currency_Symbolsbool-
Arrowsbool-
Geometric_Shapesbool-
Mathematical_Operatorsbool-
CustomUnicodebool-
',16),i=[a];function l(n,s,b,h,p,c){return r(),d("div",null,i)}const _=t(o,[["render",l]]);export{u as __pageData,_ as default}; diff --git a/assets/Design_AssetDescription.md.5qrDTdVw.lean.js b/assets/Design_AssetDescription.md.5qrDTdVw.lean.js new file mode 100644 index 00000000..529c9a6c --- /dev/null +++ b/assets/Design_AssetDescription.md.5qrDTdVw.lean.js @@ -0,0 +1 @@ +import{_ as t,c as d,o as r,a4 as e}from"./chunks/framework.Br2U662V.js";const u=JSON.parse('{"title":"MiniGameConfig.asset 配置文件说明","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AssetDescription.md","filePath":"Design/AssetDescription.md"}'),o={name:"Design/AssetDescription.md"},a=e("",16),i=[a];function l(n,s,b,h,p,c){return r(),d("div",null,i)}const _=t(o,[["render",l]]);export{u as __pageData,_ as default}; diff --git a/assets/Design_AssetOptimization.md.DD6FAQCd.js b/assets/Design_AssetOptimization.md.DD6FAQCd.js new file mode 100644 index 00000000..5ebe6249 --- /dev/null +++ b/assets/Design_AssetOptimization.md.DD6FAQCd.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/entrance.3drElOeY.png",l="/minigame-unity-webgl-transform/assets/asset-analysis-window.D04lUzYU.png",s="/minigame-unity-webgl-transform/assets/change-max-size.DDYD-ESI.png",o="/minigame-unity-webgl-transform/assets/change-format.Ceib4V6i.png",f=JSON.parse('{"title":"资源优化","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AssetOptimization.md","filePath":"Design/AssetOptimization.md"}'),n={name:"Design/AssetOptimization.md"},m=t('

资源优化

可通过转换工具配套提供的资源优化工具,将游戏内纹理资源针对webgl导出做优化。

工具入口

菜单栏-微信小游戏-资源优化工具

入口

工具介绍

Texture

资源处理工具面板

  1. 区域1: 选中目录,以设定规则扫描目录下文件。 搜索规则
  1. 区域2: 以设定规则修复列表中选中的资源 注意: 每次修复时将当前所要修复资源的importer覆盖写入到Library/AssetImporterbak; 还原时,从Library/AssetImporterbak读取选中资源的importer设置并还原后,会删除Library/AssetImporterbak,并不是undo/redo逻辑

maxsize

其中,自动减半根据当前纹理尺寸,将maxsize设置为纹理宽高最大值的一半。

textureformat

  1. 区域3: 筛选列表展示结果
  2. 区域4: 列表总览
  3. 区域5: 资源列表 支持一键全选、按资源名搜索
  4. 区域6: 引用查找 选中一个资源,查找资源被引用关系

优化建议

',19),p=[m];function c(d,u,_,h,g,b){return i(),e("div",null,p)}const P=a(n,[["render",c]]);export{f as __pageData,P as default}; diff --git a/assets/Design_AssetOptimization.md.DD6FAQCd.lean.js b/assets/Design_AssetOptimization.md.DD6FAQCd.lean.js new file mode 100644 index 00000000..2517add8 --- /dev/null +++ b/assets/Design_AssetOptimization.md.DD6FAQCd.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/entrance.3drElOeY.png",l="/minigame-unity-webgl-transform/assets/asset-analysis-window.D04lUzYU.png",s="/minigame-unity-webgl-transform/assets/change-max-size.DDYD-ESI.png",o="/minigame-unity-webgl-transform/assets/change-format.Ceib4V6i.png",f=JSON.parse('{"title":"资源优化","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AssetOptimization.md","filePath":"Design/AssetOptimization.md"}'),n={name:"Design/AssetOptimization.md"},m=t("",19),p=[m];function c(d,u,_,h,g,b){return i(),e("div",null,p)}const P=a(n,[["render",c]]);export{f as __pageData,P as default}; diff --git a/assets/Design_AudioAndVideo.md.B1u2EDqx.js b/assets/Design_AudioAndVideo.md.B1u2EDqx.js new file mode 100644 index 00000000..c16b53dd --- /dev/null +++ b/assets/Design_AudioAndVideo.md.B1u2EDqx.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,a4 as l}from"./chunks/framework.Br2U662V.js";const p=JSON.parse('{"title":"音视频适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AudioAndVideo.md","filePath":"Design/AudioAndVideo.md"}'),t={name:"Design/AudioAndVideo.md"},r=l('

音视频适配

音频

目前 UnityAudio 已自动适配微信小游戏,优先建议使用 UnityAudio 来播放音频,也支持 FMOD 插件

兼容原理

UnityAudio 原理:

FMOD 原理:

QA

  1. 在 IOS 17.5 以上的版本,小游戏退后台后返回音效无法继续播放了
  1. IOS 偶现音频报错 operateAudio:fail jsapi has no permission
  1. 音频播放时游戏卡顿
  1. 部分音频文件在安卓无法循环播放
  1. 音频在 PC 端无法循环播放完整音频
  1. 推荐使用什么音频格式
  1. FMOD returns error code 36

视频

在微信小游戏中有两种播放视频的方式,目前 VideoPlayer 组件已自动适配微信小游戏,只有全屏视频的场景也可以选择使用WXVideo API

VideoPlayer 支持版本

不同客户端的支持情况不同,以下为最低支持版本:

参数版本
IOS 高性能+暂不支持
IOS 高性能8.0.41
安卓8.0.40
PC基础库 3.2.1
开发者工具基础库 3.2.1 + 1.06.2310312

QA

  1. VideoPlayer 视频在 IOS 无法播放,在其他平台都可以播放?
  1. VideoPlayer 视频在 IOS 播放有声音没画面?
  1. VideoPlayer 为什么在 IOS 高性能模式只能同时播放一个视频?
  1. 应该使用 VideoPlayer 还是 WXVideo?
  1. WXVideo 真机播放正常,开发者工具无法播放?
  1. WXVideo 在 IOS 设置 underGameView 之后黑屏,有声音没画面?
',41),o=[r];function d(n,s,h,u,c,m){return i(),a("div",null,o)}const b=e(t,[["render",d]]);export{p as __pageData,b as default}; diff --git a/assets/Design_AudioAndVideo.md.B1u2EDqx.lean.js b/assets/Design_AudioAndVideo.md.B1u2EDqx.lean.js new file mode 100644 index 00000000..a9ac46b7 --- /dev/null +++ b/assets/Design_AudioAndVideo.md.B1u2EDqx.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,a4 as l}from"./chunks/framework.Br2U662V.js";const p=JSON.parse('{"title":"音视频适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/AudioAndVideo.md","filePath":"Design/AudioAndVideo.md"}'),t={name:"Design/AudioAndVideo.md"},r=l("",41),o=[r];function d(n,s,h,u,c,m){return i(),a("div",null,o)}const b=e(t,[["render",d]]);export{p as __pageData,b as default}; diff --git a/assets/Design_BackendServiceStartup.md.BfLKGEwG.js b/assets/Design_BackendServiceStartup.md.BfLKGEwG.js new file mode 100644 index 00000000..fef488d0 --- /dev/null +++ b/assets/Design_BackendServiceStartup.md.BfLKGEwG.js @@ -0,0 +1,53 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/init-cf-proj.Cam-RLFc.jpg",t="/minigame-unity-webgl-transform/assets/cf-overview.CV2FOQaP.png",e="/minigame-unity-webgl-transform/assets/open-cf.DLBm5pMO.jpg",p="/minigame-unity-webgl-transform/assets/cf-free.BM2qYFhS.jpg",h="/minigame-unity-webgl-transform/assets/choose-env.Cy4xcKaE.jpg",k="/minigame-unity-webgl-transform/assets/upload-cf.Du3A6DMK.png",A=JSON.parse('{"title":"后端服务指引","description":"","frontmatter":{},"headers":[],"relativePath":"Design/BackendServiceStartup.md","filePath":"Design/BackendServiceStartup.md"}'),r={name:"Design/BackendServiceStartup.md"},E=n('

后端服务指引

后端服务模式

微信小游戏对后端服务无任何限制,可以根据自身需求选择,比如:

  1. 自建后端:支持 websocket、HTTP 通信
  2. 云开发:云开发可以降低运维、研发成本,详见云开发-指引
  3. 1、2 混合的模式

自建后端服务

登录态参考登录态管理 通过 websocket 或者 HTTP 通信,理论上 App 和微信小游戏大部分后端服务可以直接复用

云开发

以实现一个服务端校验内容安全的云函数为例对云开发流程进行简单介绍,更多文档和示例请参考云函数文档

注意:此示例仅供参考云函数使用流程,正常情况下对内容进行安全校验的逻辑应该是内容校验通过+内容存储到后端在同一个云函数中实现,避免直接调用存储接口绕开校验的情况出现。

  1. 新建一个云函数的空工程 云函数可以和前端的游戏逻辑独立创建为不同的项目。当然也可以在同一个项目中(project.config.json 中指定 cloudfunctionRoot,避免云函数代码被业务逻辑代码一同打包发布到外网),以下示例为独立项目的模式

  2. 该小游戏首次使用云开发需要先开通云开发

    云开发有一个基本的免费套餐,请求量达到一定上限后需要配额调整申请代金券后更换配额套餐

  3. 实现一个云函数 以“内容安全检查”云函数(msgSecCheck)为例,复制示例中 login 文件夹,重命名为 msgSecCheck,修改 index.js 中的内容实现服务端逻辑:

Javascript
/*
+ *  // msgSecCheck
+ *  message Request {
+ *      string content;
+ *  }
+ *  message Response {
+ *      int code; // 返回码, 0:内容正常; 1:参数非法; 87014: 内容含有违法违规内容
+ *  }
+ */
+
+const cloud = require('wx-server-sdk')
+
+cloud.init({
+    env: cloud.DYNAMIC_CURRENT_ENV
+})
+
+function Response(code) {
+    return {
+        code,
+    }
+}
+
+exports.main = async (event, context) => {
+    if (!event.content) return Response(1);
+    try {
+		// https://developers.weixin.qq.com/minigame/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
+        await cloud.openapi.security.msgSecCheck({
+            content: event.content,
+        });
+        return Response(0);
+    } catch (e) {
+        return Response(e.errorCode);
+    }
+}

修改 config.json,增加对 openapi.security.msgSecCheck 的声明,如没有用到 openapi 则无需修改 config.json:

json
  "permissions": {
+    "openapi": [
+        "security.msgSecCheck"
+    ]
+  }

openapi 更多使用细节参考云调用文档

  1. 部署云函数
Javascript
wx.cloud.init({env:"product"})
+
+wx.cloud.callFunction({
+  name: 'msgSecCheck',
+  data: {
+    content: "hello cf"
+  },
+  success:function(res) {
+  	console.log("call success", res);
+	const isContentOk = (res.result && res.result && res.result.code === 0);
+	console.log("IsContentOk", isContentOk)
+  },
+  fail: function(res){
+	console.log("call fail", res);
+  }
+})
`,17),d=[E];function c(o,g,y,F,u,m){return a(),i("div",null,d)}const q=s(r,[["render",c]]);export{A as __pageData,q as default}; diff --git a/assets/Design_BackendServiceStartup.md.BfLKGEwG.lean.js b/assets/Design_BackendServiceStartup.md.BfLKGEwG.lean.js new file mode 100644 index 00000000..38975143 --- /dev/null +++ b/assets/Design_BackendServiceStartup.md.BfLKGEwG.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/init-cf-proj.Cam-RLFc.jpg",t="/minigame-unity-webgl-transform/assets/cf-overview.CV2FOQaP.png",e="/minigame-unity-webgl-transform/assets/open-cf.DLBm5pMO.jpg",p="/minigame-unity-webgl-transform/assets/cf-free.BM2qYFhS.jpg",h="/minigame-unity-webgl-transform/assets/choose-env.Cy4xcKaE.jpg",k="/minigame-unity-webgl-transform/assets/upload-cf.Du3A6DMK.png",A=JSON.parse('{"title":"后端服务指引","description":"","frontmatter":{},"headers":[],"relativePath":"Design/BackendServiceStartup.md","filePath":"Design/BackendServiceStartup.md"}'),r={name:"Design/BackendServiceStartup.md"},E=n("",17),d=[E];function c(o,g,y,F,u,m){return a(),i("div",null,d)}const q=s(r,[["render",c]]);export{A as __pageData,q as default}; diff --git a/assets/Design_BuildTemplate.md.BwpsT2kQ.js b/assets/Design_BuildTemplate.md.BwpsT2kQ.js new file mode 100644 index 00000000..61262186 --- /dev/null +++ b/assets/Design_BuildTemplate.md.BwpsT2kQ.js @@ -0,0 +1,99 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const p="/minigame-unity-webgl-transform/assets/buildtemplateprocess.BJDyZOCI.png",y=JSON.parse('{"title":"配置构建模板","description":"","frontmatter":{},"headers":[],"relativePath":"Design/BuildTemplate.md","filePath":"Design/BuildTemplate.md"}'),l={name:"Design/BuildTemplate.md"},e=n(`

配置构建模板

简介

Unity/团结快适配项目最终导出 minigame 目录即为微信小游戏代码包,使用微信开发者工具打开并上传。该部分主要由 JavaScript、JSON、WASM及图片资源构成。在实际的游戏开发中,开发者存在需要对 minigame 目录中产物做一些定制化的修改,这些修改同时也要跟随项目内容一起进行代码托管。为此微信提供配置构建模板的能力。

结构说明

两个目录中的 wechat-default 是项目的基础模板,基础模板不建议开发者进行编辑,因为随着新的SDK的更新覆盖也将失去其修改内容。

开发者需要手动创建 Assets/WX-WASM-SDK-V2/Editor/template 目录,在 template/minigame 目录中的资源内容将会按照完整的层级结构覆盖到最终的 minigame 的导出目录中。

直观的结构:

# 游戏工程目录
+Assets
+├─ WX-WASM-SDK-V2
+│  ├─ Editor
+│  │  ├─ template      # 自行创建该目录内容
+│  │  │  ├─ minigame
+│  │  │  │  └─ ...     # 需要被覆盖的资源文件
+│  │  │  └─ plugin.cs  # 可缺省创建,请阅读「构建模板前后不同时机的钩子」小节
+│  │  └─ ...
+│  └─ ...
+└─ ...
+
+# WXSDK目录
+Packages/com.qq.weixin.minigame 或 Assets/WX-WASM-SDK-V2
+├─ Runtime
+│  ├─ wechat-default   # 基础模板
+│  └─ ...
+└─ ...
+
+# 导出资源目录(转换微信小游戏产物)
+wechat
+├─ minigame      # 基础模板 + template(合并结果)
+│  └─ ...
+└─ webgl

值得注意的是,基础模板(wechat-default)并不是一个可以运行的标准JavaScript代码包,因为其中包含了大量的占位符将在导出时根据项目不同的实际情况作出替换,因此开发者在 template/minigame 创建用于覆盖的脚本时,应该以 wechat-defalut 中的脚本为修改基准,而不是导出的资源目录 wechat/minigame 中的资源作为参考。如此一来你自定义模板也将适应占位符的内容作出最终的结果变更。

新版本SDK引起的冲突提醒

随着WXSDK的更新,如果你覆盖过 wechat-defalut 中的关键脚本,那么在新版本WXSDK导入后可能会引起部分功能表现异常,因此WXSDK将识别到关键脚本发生更新且被开发者自定义覆盖的情况下作出警告。(只会检查 .js .json 文件冲突,图片文件不会检查)

消除冲突提醒

观察到异常提醒后开发者需要根据提醒前往对比冲突的脚本内容自行适配,当冲突的自定义模板文件较冲突前发生变化后提醒也将自动消除。

JSON配置合并

时常开发者需要对 game.jsonproject.config.json 配置文件内容的做针对性的修改,当然使用后面小节提及的钩子能力可以很万能的做出内容修改,但这毕竟需要开发者进行一定的代码编写。构建模板能力为开发者提供了一个JSON配置合并能力,只需要自定义模板目录放置JSON,并且只填写你关注的字段,构建模板能够自动帮你完成相同JSON文件的字段合并。

支持合并的文件为:

合并规则:Key-Value 字段将在末位节点新增或覆盖,Array 将整节点新增或覆盖。

例如:

自定义模板 .../Editor/template/minigame/game.json

js
{
+  "test": "abc123",           // 最终模板将新增该字段与值
+  "plugins": {
+    "UnityPlugin": {
+      "version": "1.2.52"     // 最终模板仅变更该版本号
+    }
+  },
+  "subpackages": [            // 最终模板会因该字段为数组类型,将整节点替换
+    "..."
+  ]
+}

构建模板前后不同时机的钩子

有时候简单的覆盖可能并不能满足开发者复杂的修改需要,在构建时提供的不同时机钩子允许开发者使用C#代码来替换或变更是更灵活自由的方案,我们提供了 BuildTemplateHelper 工具类来便捷的获得三个目录的绝对路径。

钩子介绍

在构建模板中通常需要以下几个阶段的钩子:

使用钩子

为了统一约定,推荐开发者创建位于 Assets/WX-WASM-SDK-V2/Editor/template/plugin.cs 脚本来执行构建模板相关的设计。

# 游戏工程目录
+Assets
+├─ WX-WASM-SDK-V2
+│  ├─ Editor
+│  │  ├─ template
+│  │  │  ├─ minigame
+│  │  │  │  └─ ...
+│  │  │  └─ plugin.cs  # 请创建该文件并编写钩子逻辑
+│  │  └─ ...
+│  └─ ...
+└─ ...

样例:

c#
// plugin.cs
+using System.IO;
+using UnityEngine;
+using WeChatWASM;
+
+/// <summary>
+/// 构建生命周期回调钩子
+/// 注意事项:
+///     请创建脚本在 Editor (子)目录下;
+///     回调钩子请使用 public 声明成员函数
+/// </summary>
+public class PluginDemo : LifeCycleBase
+{
+
+    public override void afterCopyDefault()
+    {
+        // code...
+        Debug.Log("afterCopyDefault");
+    }
+
+    public override void beforeCopyDefault()
+    {
+        // 可使用 Exception 阻止继续构建导出
+        throw new System.Exception("Build Failed.");
+    }
+
+    public override void beforeCoverTemplate()
+    {
+        // 读取你的自定义模板目录并对其中的资源做动态修改
+        var tmp = BuildTemplateHelper.CustomTemplateDir;
+        using (
+          FileStream file = new FileStream(
+            Path.Combine(tmp, "newFile.js"),
+            FileMode.Create, FileAccess.Write))
+        {
+            using (StreamWriter writer = new StreamWriter(file))
+            {
+                writer.WriteLineAsync("Your Code Content.");
+            }
+        }
+        // 尽管你在导出期间动态的创建/修改了自定义模板中的资源
+        // 在导出结束后WXSDK会自动恢复你的修改
+    }
+}

BuildTemplateHelper介绍

BuildTemplateHelper 为你便捷的提供了各个目录的绝对路径:

c#
// wechat-default(标准模板)
+// 位于 WXSDK 目录下标准模板绝对路径
+string baseDir = BuildTemplateHelper.BaseDir;
+
+
+// template(自定义模板)
+// 游戏工程中 Assets/WX-WASM-SDK-V2/Editor/template/minigame 绝对路径
+string templateDir = BuildTemplateHelper.CustomTemplateDir;
+
+
+// wechat/minigame(导出产物)
+// 开发者在导出面板配置的导出路径的微信开发者工具打开的 minigame(默认) 绝对路径
+string outDir = BuildTemplateHelper.DstMinigameDir;

搭配钩子介绍小节中的不同阶段,可以任意的对你的 wechat-default(标准模板)template(自定义模板)wechat/minigame(导出产物) 中进行新的脚本创建、已有脚本中局部代码的文本替换(例如使用正则替换)甚至是图片等资源的变更。

在导出期间修改你的自定义模板,在结束导出后不会真实的影响你的游戏工程内容,WXSDK已经为你还原,这对于你托管项目代码很便捷。

`,38),t=[e];function h(k,r,d,c,g,E){return i(),a("div",null,t)}const u=s(l,[["render",h]]);export{y as __pageData,u as default}; diff --git a/assets/Design_BuildTemplate.md.BwpsT2kQ.lean.js b/assets/Design_BuildTemplate.md.BwpsT2kQ.lean.js new file mode 100644 index 00000000..62356a9f --- /dev/null +++ b/assets/Design_BuildTemplate.md.BwpsT2kQ.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const p="/minigame-unity-webgl-transform/assets/buildtemplateprocess.BJDyZOCI.png",y=JSON.parse('{"title":"配置构建模板","description":"","frontmatter":{},"headers":[],"relativePath":"Design/BuildTemplate.md","filePath":"Design/BuildTemplate.md"}'),l={name:"Design/BuildTemplate.md"},e=n("",38),t=[e];function h(k,r,d,c,g,E){return i(),a("div",null,t)}const u=s(l,[["render",h]]);export{y as __pageData,u as default}; diff --git a/assets/Design_CompressedTexture.md.TGKkGaTi.js b/assets/Design_CompressedTexture.md.TGKkGaTi.js new file mode 100644 index 00000000..be0705f4 --- /dev/null +++ b/assets/Design_CompressedTexture.md.TGKkGaTi.js @@ -0,0 +1,16 @@ +import{_ as t,c as a,o as e,a4 as s}from"./chunks/framework.Br2U662V.js";const i="/minigame-unity-webgl-transform/assets/compressedTexture02.BVxh_oYK.png",n="/minigame-unity-webgl-transform/assets/cm-texture1.Dy62LOjy.png",m=JSON.parse('{"title":"微信小游戏压缩纹理工具2.0(Beta)","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CompressedTexture.md","filePath":"Design/CompressedTexture.md"}'),d={name:"Design/CompressedTexture.md"},r=s('

微信小游戏压缩纹理工具2.0(Beta)

概述

​ 早期 Unity(2018-2020) 不支持对 ASTC 纹理格式进行导出,因此在移动端中无法充分利用 GPU 完成硬件的解码渲染。为弥补这一缺陷,微信 Unity SDK 提供压缩纹理按需加载的能力工具。使用该工具将对项目获得如下增益:

​ 压缩纹理工具将纹理资源从 Bundle 中分离单独托管,因此 Bundle 体积将变小,这有助于加快游戏运行进度。对于被分离的纹理资源将在游戏实际的使用过程中按渲染需要动态加载。

​ 使用压缩后的纹理本身将节约更多的内存空间,这对于内存吃紧的游戏至关重要。微信压缩纹理工具将对同一个纹理资源生成多种不同格式的压缩纹理(如ASTC、DXT……),在游戏运行中如需按需加载,根据实际运行设备 GPU 下载可被识别的压缩纹理。对于资源体积而言将更小,由 GPU 实现硬件解码,效率更高。

使用建议

Unity引擎自带压缩纹理:

​ 更统一的工作流;ASTC能支持最近3-4年大部分机型;但PC端不支持ASTC依然需要解压。

微信小游戏压缩纹理工具:

​ 支持不同平台的自适应(ETC2,ASTC,DXT);同时纹理从ab中剥离出来,使得ab占用内存更小。

建议:

​ 如引擎版本高于2021, 可使用引擎自身的ASTC压缩格式(移动端覆盖率较广,PC微信、微信开发者工具将软解为RGAB32)。对于重度游戏(如MMO、SLG等)内存压力大时,可结合使用WXAssetBundle减少ab体积造成的文件内存

​ 低版本引擎(2018-2020)应使用 微信UnitySDK压缩纹理工具 进行处理。

Unity 版本支持问题

​ 压缩纹理工具对于 Unity 2019、2020、2021 的部分版本有支持,目前已知一些版本无法使用(如 2021.3.x 、 2020.3.36 等不可用)。为了确保压缩纹理工具的顺利进行,建议开发者根据 年份大版本 的基础上选用我们已经验证可行的 Unity 版本:2019.4.28f1c1 、2020.3.10f1c1、2021.2.18f1c1,使用新的 Unity 版本后需要重新构建 Bundle 。

Unity引擎自带压缩纹理微信小游戏压缩纹理工具
版本支持Unity 2019支持部分;Unity 2020支持部分格式;Unity 2021支持2019、2020、2021均有版本支持
格式支持Unity 2019支持DXT等;Unity 2020支持DXT、ETC,但不支持ASTC;Unity 2021支持多数DXT、ASTC、ETC均支持
按设备加载不支持支持

使用说明

请务必确保使用压缩纹理工具时,导出的游戏工程来自 同版本微信 Unity SDK

主要的执行过程如下图所示:

compressedTexture02.png

1.安装 Node.js

下载并安装 Node.JS 并检查环境变量是否生效。

​ 新版本已不再依赖 Node.js。

2.构建 Bundle 文件

​ 项目中若使用 bundle 文件,需先构建 AB包。请勿开启 crc 对 bundle 进行校验。

构建前的纹理格式配置说明:

​ 纹理资源的 WebGL SettingsFormat 配置项支持列表:

Format支持情况
R 8 / R 16 bit支持
RGBA Crunched DXT5|BC3不支持
RGB Crunched DXT1|BC1不支持
RGBA Compressed DXT5|BC3支持
RGB Compressed DXT1|BC1支持
Alpha 8支持
RGBA Compressed ETC2 8 bits不支持
RGB Compressed ETC2 4 bits支持
RGB Compressed ETC 4 bits请勿使用资源占位符专用,全游戏工程请勿使用!
ASTC 请参考配置说明--
RGB(A) Compressed BC7支持
RGBA 32 bit支持

ASTC格式配置说明:

​ ASTC 是多数移动设备中游戏运行的主要支持的纹理格式,因此也是微信小游戏环境下主要使用到的压缩的纹理资源。

​ 在 2021版本 Unity 纹理资源的 WebGL SettingsFormat 配置项中,工具支持识别 RGB(A) Compressed ASTC 8x8、6x6、5x5、4x4 block 这三种压缩格式,其余格式请勿设置,并且不支持 ASTC HDR 系列的格式。

​ 若以上述4种格式配置后,最终生成的多份格式资源中,ASTC 资源将保持对应的 Block Size。值得注意的是,默认推荐使用 Block Size 8x8 格式,4x4 最清晰内存占用也会升高,开发者应根据实际调试后运行效果按需配置。

3.导出游戏

​ 点击微信小游戏 - 转换小游戏 - 导出WEBGL并转化为小游戏 导出游戏工程。请注意!任何时候当 微信Unity SDK 更新后,均需要重新执行该步骤(导出游戏工程)再使用同版本的压缩纹理工具完成后续操作,不可混版本使用

4.执行压缩纹理

​ 点击 微信小游戏 - 包体瘦身--压缩纹理 ,可点击 打开bundle配置面板 查看识别情况,并按需忽略部分不希望执行压缩纹理的bundle资源,点击 处理资源 开始处理。

调试模式 将只生成 ASTC 格式(开发者工具中使用PNG资源,移动设备使用 ASTC格式资源),调试结束后可再次选用全量模式(默认采用增量逻辑不会额外增加处理时间)

​ 该步骤根据项目实际情况不同,处理时间也会有差异,执行完成后请留意控制台提示信息,不可存在多个警告消息。

avatar

5.上传CDN

​ 执行完上述步骤后,将 webgl-min 目录中的资源上传至 CDN 服务器中,如 Assets 目录、StreamingAssets目录、xxx.webgl.data.unityweb.bin.txt 等文件。

WebGL2.0 支持说明(Beta)

​ 微信纹理压缩目前已支持WebGL2.0模式下的Gamma与Linear颜色空间渲染,但仅支持2019、2020、2021 3个年限中部分版本,其中2019必须使用Unity与微信合作的Instant Game版本,其余年限跟随微信纹理压缩支持版本进行选择。该能力仍在兼容一些特殊的应用场景,开发者使用后需要进行详细的真机测试。

忽略配置说明

​ 对于微信压缩纹理工具处理后部分资源渲染效果较差、甚至无法处理的情况,开发者使用忽略处理能力完成对资源的保留在AB包内,从 微信压缩纹理 - 打开配置面板 进入配置页,默认情况下配置页面中将扫描当前项目所有可被处理的AB包资源,对于AB包的忽略直接在右侧 忽略 勾选项选中后保存即可。 ​ 有时忽略整个AB包并不是一种好的策略,仅仅是AB包内部分纹理资源渲染不佳,此时若已经执行过微信压缩纹理能力时,扫描的资源将包含AB包内的单个纹理资源信息,可通过右上角搜索栏检索快速查找对应的纹理资源进行忽略设置,保存后只需再次执行即可。若此前从未执行过微信压缩纹理,需要点击 解包纹理 按钮,等待完全解包后可进行纹理的配置操作,该过程等同执行微信压缩纹理的「阶段一」,大型工程可能花费一些时间。

首资源包优化说明

​ 位于 微信小游戏转换工具面板 - 首资源包优化 能力隶属于微信压缩纹理工具的扩展范畴。该功能能够将首资源包中 Unity Editor 默认打包的资源(但游戏从未使用过)进行剔除,从而再次降低首资源包体积,该功能可以在不开启微信压缩纹理工具的情况下使用。 ​ 默认情况下无需开发者进行手动的配置(工具已经能够识别多数Unity Editor的无用资源),但该能力仍然允许开发者进行手动的进行资源选择,来自定义剔除。请注意当开发者手动配置时需要自行判断资源是否是游戏中的必要资源,不慎剔除将导致游戏的渲染异常。

新版本异常回退说明

​ 微信纹理压缩升级了全新的内核程序,尽管发布前进行了多数Unity年限版本与常见机型的测试,目前仍处于初期测试使用,若使用期间存在异常影响正常的游戏发布可前往issues提出问题,并使用上一代稳定版微信纹理压缩包(旧)导入工程后采用旧版本完成游戏发布。旧版本使用指引请参阅:微信压缩纹理使用说明(旧)

原理解释

​ 微信纹理压缩工具底层原理是将bundle内纹理资源分离,将资源指针替换至原bundle内,分离出的资源将被处理成多种不同GPU所支持的纹理格式托管至CDN中,游戏实际运行时将劫持渲染时根据资源指针以及当前设备GPU所支持的纹理格式进行远程加载,成功加载立即上传GPU后将从系统内存释放。这样的工作原理即做到了不同硬件所支持的纹理格式按需加载,又相比于bundle全部加载至内存时占用过多的系统内存。经过微信小游戏团队测试,该工具能够降低游戏的运行时内存情况,不同的游戏之间使用的场景、纹理差异降低值是不相同的。

Q&A

1.生成的纹理太大

​ PC端上预览的时候展示的是PNG图片会比较大,手机上用的是带txt后缀的,如astc.txt, 这些文件压缩率很高,注意正式环境CDN一定要开启Brotli或者Gzip,这样加载的时候纹理就会很小。速度快很多。建议优先使用Brotli。

2.资源上传至CDN的注意事项

​ 上传至CDN时,请注意要按二进制传输,强制storebinary,如果按文本传输也会出现加载回来的图片成黑色。

3.非4倍数的资源处理底层逻辑

​ 移动设备中大多数使用 ASTC 作为主要的纹理资源格式,ASTC 是不受纹理资源高宽影响的,因此非 4 倍数底层逻辑处理并不会对移动设备上的表现有差异。而对于 DXT 格式是 PC 小游戏中主要的纹理资源格式,该格式是要求高宽必须为 4 的倍数,微信纹理压缩工具在资源处理的过程中识别了资源能否正确的被压缩处理,并在渲染期间做了兜底的渲染策略,在 PC 的表现上,若资源支持以 DXT 格式,则将采用 DXT 渲染,否则遵循兜底策略,其格式优先级为: ASTC、ETC2、DXT、PNG,最差的情况将使用 PNG 格式渲染。

4.Node.js异常处理

​ 压缩纹理工具执行需要依赖 Node.js 解释器,若执行前已安装 Node.js 但执行时提示未找到则需手动填入本机 Node.js 路径。请将 Node.js 的绝对路径填写至 Assets/WX-WASM-SDK/Editor/TextureEditor/WXAssetsTextTools.cs 文件的 NODE_PATH 变量中。若开发者使用API调用执行,可对该变量进行直接赋值。

5.分离纹理后各自单独下载是否会增加下载开销?

​ 不会。标准的CDN服务会支持http2协议,因此看似多条的请求背后系统仅会创建1条TCP/IP链路,所以并不会增加额外的请求开销。宏观来说你开启了CDN压缩情况下,游戏所需资源下载的总量没变、链接次数没变,却享受了不同设备按需使用纹理格式的能力。

6.MacOS系统执行报错 “'System.Drawing.GDIPlus' threw an exception”

​ 因为 Unity 自带 Mono 配置错误 libgdiplus.dylib 文件路径。有两种解决方案选择其一即可。

解决方案一:

​ 本地安装官方 Mono 后,代码配置微信压缩纹理工具用于执行的 Mono 解释器完整路径。

c#
// 在合理的时机进行路径配置:
+#if UNITY_EDITOR_OSX
+  WXAssetsTextTools.MONO_PATH = "/usr/bin/mono";     // 本机安装的 Mono 解释器完整路径
+#endif

解决方案二:

​ 先下载 libgdiplus.dylib 文件后,将其放在 UnityEditor /Applications/Unity/Hub/Editor/{$Unity_Editor_Version}/Unity.app/Contents/MonoBleedingEdge/lib/libgdiplus.dylib 路径下,并编辑 /Applications/Unity/Hub/Editor/{$Unity_Editor_Version}/Unity.app/Contents/MonoBleedingEdge/etc/mono/config 文件,将 target= .../libgdiplus.dylib 路径内容均变更为下载文件的存放完整路径,重启 Unity Editor 即可。

微信压缩纹理API介绍

​ 为方便开发者构建个性化的工程导出能力,微信压缩纹理工具提供了相应的 API 调用接口,开发者可以在游戏内自助构建游戏导出脚本,完成发布上传前的自动化操作。

提示:为简化调用,忽略ab、工程路径等数据均来自面板配置此处不提供相应参数传入,面板配置后将被存盘记录无需每次执行前进行配置。

WXAssetsTextTools.CompressText( ... )

​ void WXAssetsTextTools.CompressText(Action<bool, string> complete = null, string bundleDir = null, string outBundleDir = null, bool debug = false, bool force = false)

说明

​ 执行微信压缩纹理流程,该函数为异步函数。该方法对应【包体瘦身--压缩纹理】面板中「处理资源」按钮的执行,其中小游戏工程导出目录路径来自【转换小游戏】面板中配置。

参数

参数类型说明
completeAction执行结束的回调函数,形参1(bool) 返回执行是否成功,形参2(string)返回执行错误时的错误提示信息。
bundleDirstring可缺省,若存在独立的AB包目录,则此处填写目录的绝对路径。
outBundleDirstring可缺省,若填写bundleDir则不可省略,独立AB包处理后的输出目录。
debugbool可缺省,默认全量生成(false),true时仅生成ASTC格式纹理。
forcebool可缺省,默认遵循增量逻辑(false),true时将强制生成(已生成资源仍然生成并覆盖)。

例子:

c#
WXAssetsTextTools.CompressText((result, msg) =>
+  {
+    if (result)
+    {
+      Debug.Log("微信压缩纹理转换完成!");
+    }else{
+      Debug.LogError(msg);
+    }
+  }, 
+  null, 
+  null, 
+  false,
+  false);

WXAssetsTextTools.GetAssetBundles( ... )

​ void WXAssetsTextTools.GetAssetBundles(Action<string[]> callback = null, string bundleDir = null)

说明

​ 获取微信压缩纹理工具所能扫描到的符合条件的AB包路径数组。相同参数情况下,所扫描到的资源列表则为实际可被执行处理的资源。

参数

参数类型说明
callbackAction扫描结束的回调函数,形参(string[]) 返回扫描到的ab包资源绝对路径。
bundleDirstring可缺省,若存在独立的AB包目录,则此处填写目录的绝对路径。
`,88),l=[r];function o(h,p,c,k,b,u){return e(),a("div",null,l)}const E=t(d,[["render",o]]);export{m as __pageData,E as default}; diff --git a/assets/Design_CompressedTexture.md.TGKkGaTi.lean.js b/assets/Design_CompressedTexture.md.TGKkGaTi.lean.js new file mode 100644 index 00000000..d157c90b --- /dev/null +++ b/assets/Design_CompressedTexture.md.TGKkGaTi.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as e,a4 as s}from"./chunks/framework.Br2U662V.js";const i="/minigame-unity-webgl-transform/assets/compressedTexture02.BVxh_oYK.png",n="/minigame-unity-webgl-transform/assets/cm-texture1.Dy62LOjy.png",m=JSON.parse('{"title":"微信小游戏压缩纹理工具2.0(Beta)","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CompressedTexture.md","filePath":"Design/CompressedTexture.md"}'),d={name:"Design/CompressedTexture.md"},r=s("",88),l=[r];function o(h,p,c,k,b,u){return e(),a("div",null,l)}const E=t(d,[["render",o]]);export{m as __pageData,E as default}; diff --git a/assets/Design_CustomLoading.md.CIt3rPKd.js b/assets/Design_CustomLoading.md.CIt3rPKd.js new file mode 100644 index 00000000..6ee30601 --- /dev/null +++ b/assets/Design_CustomLoading.md.CIt3rPKd.js @@ -0,0 +1,104 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const h="/minigame-unity-webgl-transform/assets/loading_default.CgcqniMh.png",l="/minigame-unity-webgl-transform/assets/loading_demo.BSF4nkPk.jpg",k="/minigame-unity-webgl-transform/assets/loading_design.CFXQxkuH.jpg",C=JSON.parse('{"title":"启动封面","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CustomLoading.md","filePath":"Design/CustomLoading.md"}'),p={name:"Design/CustomLoading.md"},t=n(`

启动封面

由于Unity WebGL启动加载需要一定时间,因此需要使用视频或图片等内容作为过渡以留住玩家。Unity Loader默认使用图片+进度信息,铺满全屏呈现。

开发者可自定义以下内容

完整配置

转换插件配置

bgImageSrc: 启动封面图;-- $BACKGROUND_IMAGE
+VideoUrl: 启动视频;-- $LOADING_VIDEO_URL
+HideAfterCallMain: 是否callmain完成后立即隐藏封面;-- $HIDE_AFTER_CALLMAIN

game.js配置

样式配置未提供对应的转换插件配置入口,需要修改unity工程中,小游戏模板wechat-default/game.js

js
hideAfterCallmain: $HIDE_AFTER_CALLMAIN,// 是否需要callmain结束后立即隐藏封面视频
+// 加载页配置项
+loadingPageConfig: {
+  totalLaunchTime: 15000, // 默认总启动耗时,即加载动画默认播放时间,可根据游戏实际情况进行调整
+  /**
+   * !!注意:修改设计宽高和缩放模式后,需要修改文字和进度条样式。默认设计尺寸为667*375
+   */
+  designWidth: 0, // 设计宽度,单位px
+  designHeight: 0, // 设计高度,单位px
+  scaleMode: '', // 缩放模式, 取值和效果参考,https://github.com/egret-labs/egret-docs/blob/master/Engine2D/screenAdaptation/zoomMode/README.md
+  // 以下配置的样式,尺寸相对设计宽高
+  textConfig: {
+    firstStartText: '首次加载请耐心等待', // 首次启动时提示文案
+    downloadingText: ['正在加载资源'], // 加载阶段循环展示的文案
+    compilingText: '编译中', // 编译阶段文案
+    initText: '初始化中', // 初始化阶段文案
+    completeText: '开始游戏', // 初始化完成
+    textDuration: 1500, // 当downloadingText有多个文案时,每个文案展示时间
+    // 文字样式
+    style: {
+      bottom: 64,
+      height: 24,
+      width: 240,
+      lineHeight: 24,
+      color: '#ffffff',
+      fontSize: 12,
+    }
+  },
+  // 进度条样式
+  barConfig: {
+    style: {
+      width: 240,
+      height: 24,
+      padding: 2,
+      bottom: 64,
+      backgroundColor: '#07C160',
+    }
+  },
+  // 一般不修改,控制icon样式
+  iconConfig: {
+    visible: true, // 是否显示icon
+    style: {
+      width: 64,
+      height: 23,
+      bottom: 20,
+    }
+  },
+  // 加载页的素材配置
+  materialConfig: {
+    // 背景图或背景视频,两者都填时,先展示背景图,视频可播放后,播放视频
+    backgroundImage: '$BACKGROUND_IMAGE', // 背景图片,推荐使用小游戏包内图片;当有视频时,可作为视频加载时的封面
+    backgroundVideo: '$LOADING_VIDEO_URL', // 加载视频,网络url
+    iconImage: 'images/unity_logo.png', // icon图片,一般不更换
+  }
+},

下面根据配置介绍两种加载效果的实现

默认效果

实现默认效果很简单,开发者只需在导出时配置启动素材即可

所需配置项

js
bgImageSrc: 启动封面图;-- $BACKGROUND_IMAGE
+VideoUrl: 启动视频;-- $LOADING_VIDEO_URL
+HideAfterCallMain: 是否callmain完成后立即隐藏封面;-- $HIDE_AFTER_CALLMAIN
+loadingBarWidth: 加载进度条宽度;-- $LOADING_BAR_WIDTH

定制效果

启动loader提供的默认加载界面为了契合不同游戏,做得相对通用,但游戏可能会存在定制启动loading的需求,以达到和游戏更贴近的体验。

js
loadingPageConfig: {
+  totalLaunchTime: 15000, // 默认总启动耗时,即加载动画默认播放时间,可根据游戏实际情况进行调整
+  designWidth: 1600,
+  designHeight: 720,
+  scaleMode: scaleMode.fixedHeight,
+  textConfig: {
+    firstStartText: '', // 首次启动时提示文案
+    downloadingText: ['红中在手,天下我有'], // 加载阶段循环展示的文案
+    compilingText: '牌从门前过,不如摸一个', // 编译阶段文案
+    initText: '牌从门前过,不如摸一个', // 初始化阶段文案
+    completeText: '牌从门前过,不如摸一个', // 初始化完成
+    textDuration: 1500, // 当downloadingText有多个文案时,每个文案展示时间
+    style: {
+      bottom: 115,
+      height: 45,
+      width: 1045,
+      lineHeight: 45,
+      color: '#ffffff',
+      fontSize: 28,
+    }
+  },
+  barConfig: {
+    style: {
+      width: 1045,
+      height: 15,
+      padding: 2,
+      bottom: 78,
+      backgroundColor: '#66b71f'
+    }
+  },
+  materialConfig: {
+    // 背景图或背景视频,两者都填时,先展示背景图,视频可播放后,播放视频
+    backgroundImage: 'images/background.jpg',
+    iconImage:'images/unity_logo.png'
+  }
+}
js
// https://github.com/egret-labs/egret-docs/blob/master/Engine2D/screenAdaptation/zoomMode/README.md
+export const scaleMode = {
+  noBorder: 'NO_BORDER', // 常用之一,不留黑边
+  exactFit: 'EXACT_FIT',
+  fixedHeight: 'FIXED_HEIGHT', // 常用之一,高度适配
+  fixedWidth: 'FIXED_WIDTH', // 常用之一,宽度适配
+  showAll: 'SHOW_ALL',
+  fixedNarrow: 'FIXED_NARROW',
+  fixedWide: 'FIXED_WIDE',
+}
`,24),e=[t];function E(d,g,r,y,F,c){return a(),i("div",null,e)}const B=s(p,[["render",E]]);export{C as __pageData,B as default}; diff --git a/assets/Design_CustomLoading.md.CIt3rPKd.lean.js b/assets/Design_CustomLoading.md.CIt3rPKd.lean.js new file mode 100644 index 00000000..6186450e --- /dev/null +++ b/assets/Design_CustomLoading.md.CIt3rPKd.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const h="/minigame-unity-webgl-transform/assets/loading_default.CgcqniMh.png",l="/minigame-unity-webgl-transform/assets/loading_demo.BSF4nkPk.jpg",k="/minigame-unity-webgl-transform/assets/loading_design.CFXQxkuH.jpg",C=JSON.parse('{"title":"启动封面","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CustomLoading.md","filePath":"Design/CustomLoading.md"}'),p={name:"Design/CustomLoading.md"},t=n("",24),e=[t];function E(d,g,r,y,F,c){return a(),i("div",null,e)}const B=s(p,[["render",E]]);export{C as __pageData,B as default}; diff --git a/assets/Design_CustomSDK.md.BSt-btdV.js b/assets/Design_CustomSDK.md.BSt-btdV.js new file mode 100644 index 00000000..c0066562 --- /dev/null +++ b/assets/Design_CustomSDK.md.BSt-btdV.js @@ -0,0 +1,18 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const c=JSON.parse('{"title":"自定义SDK调用","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CustomSDK.md","filePath":"Design/CustomSDK.md"}'),t={name:"Design/CustomSDK.md"},h=n(`

自定义SDK调用

​ 微信SDK提供了WX.CallJSFunctionWX.CallJSFunctionWithReturn接口实现了简单的第三方SDK调用,支持可序列化为JSON的任意数量的参数返回值

​ 其中,JS侧的实际调用逻辑为GameGlobal.sdkName.functionName(args),所以在调用之前需要保证SDK位于GameGlobal下且SDK中含有该名称的function。

​ 在WX.CallJSFunctionWithReturn中,会将函数返回值转换为JSON后传回,若无返回值则传回""

​ 如需更加复杂的调用,可参考WebGL:与浏览器脚本交互进行自定义定制。

版本要求

转换插件 >= 202406062127

代码示例

​ 示例中的"sdk"、"testFunction"、TestFunctionOption仅作为演示,实际使用中请自行更改。

csharp
WeChatWASM.WX.CallJSFunction("sdk", "testFunction", new TestFunctionOption
+{
+    type = "text",
+    text = "反馈",
+    style = new OptionStyle()
+    {
+        left = 10,
+        top = 10,
+        width = 100,
+        height = 100,
+        backgroundColor = "#ff0000",
+        color = "#ffffff",
+        textAlign = "center",
+        fontSize = 20,
+        borderRadius = 10,
+        lineHeight = 100,
+    }
+});

另外,在js侧代码中合适位置添加以下代码,可配合构建模版能力使用。

js
  GameGlobal["sdk"] = sdk;
`,12),l=[h];function p(k,e,E,r,d,o){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{c as __pageData,y as default}; diff --git a/assets/Design_CustomSDK.md.BSt-btdV.lean.js b/assets/Design_CustomSDK.md.BSt-btdV.lean.js new file mode 100644 index 00000000..3a4f4e94 --- /dev/null +++ b/assets/Design_CustomSDK.md.BSt-btdV.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const c=JSON.parse('{"title":"自定义SDK调用","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CustomSDK.md","filePath":"Design/CustomSDK.md"}'),t={name:"Design/CustomSDK.md"},h=n("",12),l=[h];function p(k,e,E,r,d,o){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{c as __pageData,y as default}; diff --git a/assets/Design_CustomURP.md.DO3qEFih.js b/assets/Design_CustomURP.md.DO3qEFih.js new file mode 100644 index 00000000..8128ede8 --- /dev/null +++ b/assets/Design_CustomURP.md.DO3qEFih.js @@ -0,0 +1,21 @@ +import{_ as i,c as l,o as e,a4 as a}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/custom_urp_pkgs.DenHdfcL.png",s="/minigame-unity-webgl-transform/assets/custom_urp_case1.agZ3pgEK.jpeg",n="/minigame-unity-webgl-transform/assets/custom_urp_case2.DnrjlZiu.jpeg",R=JSON.parse('{"title":"定制微信小游戏的 URP 管线","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CustomURP.md","filePath":"Design/CustomURP.md"}'),r={name:"Design/CustomURP.md"},d=a('

定制微信小游戏的 URP 管线

本地化 URP 包

准备条件编译宏

c
#ifndef WX_PERFORMANCE_MODE
+    #if (defined(SHADER_API_GLES) || defined(SHADER_API_GLES30) || defined(SHADER_API_GLES3)) 
+        #define WX_PERFORMANCE_MODE 1
+    #else 
+        #define WX_PERFORMANCE_MODE 0
+    #endif 
+    #ifndef SHADER_API_MOBILE
+        #define SHADER_API_MOBILE WX_PERFORMANCE_MODE
+    #else 
+        #if !SHADER_API_MOBILE && WX_PERFORMANCE_MODE
+            #undef SHADER_API_MOBILE
+            #define SHADER_API_MOBILE WX_PERFORMANCE_MODE
+        #endif 
+    #endif 
+#endif
c
#if WX_PERFORMANCE_MODE // 表示 微信 WebGL 平台
+...
+#endif
+
+#if !WX_PERFORMANCE_MODE // 表示 非微信 WebGL 平台
+...
+#endif

定制本地化 URP 管线

供参考的 URP 定制版本

微信 URP 定制版本的性能数据对比

版本FPSGPU 利用率%半精度利用率%全精度利用率%Total CPU 利用率%
官方URP59.85011.9235.2423
定制URP59.938.28.8745.523.1
版本FPSGPU 利用率%半精度利用率%全精度利用率%Total CPU 利用率%
官方URP59.870.85.8843.7222.9
定制URP59.951.18.5935.3923.2

注意事项

参考

',23),o=[d];function h(c,p,k,g,u,P){return e(),l("div",null,o)}const E=i(r,[["render",h]]);export{R as __pageData,E as default}; diff --git a/assets/Design_CustomURP.md.DO3qEFih.lean.js b/assets/Design_CustomURP.md.DO3qEFih.lean.js new file mode 100644 index 00000000..d1b5a190 --- /dev/null +++ b/assets/Design_CustomURP.md.DO3qEFih.lean.js @@ -0,0 +1 @@ +import{_ as i,c as l,o as e,a4 as a}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/custom_urp_pkgs.DenHdfcL.png",s="/minigame-unity-webgl-transform/assets/custom_urp_case1.agZ3pgEK.jpeg",n="/minigame-unity-webgl-transform/assets/custom_urp_case2.DnrjlZiu.jpeg",R=JSON.parse('{"title":"定制微信小游戏的 URP 管线","description":"","frontmatter":{},"headers":[],"relativePath":"Design/CustomURP.md","filePath":"Design/CustomURP.md"}'),r={name:"Design/CustomURP.md"},d=a("",23),o=[d];function h(c,p,k,g,u,P){return e(),l("div",null,o)}const E=i(r,[["render",h]]);export{R as __pageData,E as default}; diff --git a/assets/Design_DataCDN.md.CP-7QzjN.js b/assets/Design_DataCDN.md.CP-7QzjN.js new file mode 100644 index 00000000..db9a135c --- /dev/null +++ b/assets/Design_DataCDN.md.CP-7QzjN.js @@ -0,0 +1,22 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const c=JSON.parse('{"title":"资源部署与缓存","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DataCDN.md","filePath":"Design/DataCDN.md"}'),e={name:"Design/DataCDN.md"},t=n(`

资源部署与缓存

在转换完成后,会在导出路径下生成如下目录

bash
.
+├── minigame
+└── webgl

其中webgl目录结构如下:

bash
.
+├── 01367b188873c923.webgl.data.unityweb.bin.txt
+├── Assets
+│   ├── 15032.wav
+│   ├── Audio
+│   └── Textures
+├── Build
+│   ├── UnityLoader.js
+│   ├── webgl.data.unityweb
+│   ├── webgl.json
+│   ├── webgl.wasm.code.unityweb
+│   ├── webgl.wasm.framework.unityweb
+│   └── webgl.wasm.symbols.unityweb
+├── StreamingAssets
+│   └── AssetBundles
+├── index.html
+└── texture-config.js

资源部署

导出目录中,webgl目录如下三个文件和目录是可能需要远程部署的资源:

bash
.
+├── 01367b188873c923.webgl.data.unityweb.bin.txt
+├── Assets
+├── StreamingAssets

首资源包

首资源包即01367b188873c923.webgl.data.unityweb.bin.txt,包含Unity builtin + 勾选的导出场景 + Resources资源。 注意:加载方式取决于导出选项中的首包资源加载方式。同时由于小游戏总包体不能超过20MB,实际首包资源加载方式会根据包体决定,更多信息可查看UnityLoader-首包资源加载方式

Assets

如果有用到纹理压缩,导出插件自动生成。将此目录部署到服务器即可

StreamingAssets

AssetBundle和Addressables资源目录。 如果是用的AA,构建时默认打包到StreamingAssets目录下。但如果是用的AB,或者自定义了bundle的生成目录,需要将bundle移动到StreamingAssets目录

资源服务器注意事项

  1. 针对txt文件进行开启Brotli或gzip压缩,首资源包有非常高的压缩率
  2. 小游戏资源下载并发数为10,超过时底层自动排队
  3. 单个请求文件最大不超过100MB,超时默认为60s(理论最大值,实际游戏永远不要让单个文件这么大,考虑到玩家平均下载带宽,建议单文件2~5MB以内)
  4. 网络安全域名、跨域、SSL等问题请参考文档网络通信适配

资源更新说明

请注意!!! bundle的配置文件,比如aa的setting.jsoncatalog.json,以及AssetBundles打包生成的配置文件通常没有带上hash,为了避免新版本发布时由于cdn缓存导致加载到旧版本资源,需要避免这些文件使用缓存。通常有以下两种方式避免。

  1. 每次发新版本更换cdn路径,比如version1/xxxx,version2/xxxx
  2. 不希望被缓存的文件,源站或者cdn加上不允许缓存的HTTP头,如no-cache,请自行查询对应cdn服务商文档进行设置

同时,由于通过HTTP请求的资源会自动缓存,不希望被缓存的文件请添加到缓存忽略目录,具体可阅读后续资源缓存规则文档

除非了解小程序更新机制,请勿删除旧版本资源,否则可能导致旧版本游戏的用户运行报错,具体请移步版本更新

资源缓存

这里主要讲UnityLoader的资源缓存策略。

资源缓存规则

请阅读资源缓存

`,27),l=[t];function h(p,k,r,d,o,F){return i(),a("div",null,l)}const b=s(e,[["render",h]]);export{c as __pageData,b as default}; diff --git a/assets/Design_DataCDN.md.CP-7QzjN.lean.js b/assets/Design_DataCDN.md.CP-7QzjN.lean.js new file mode 100644 index 00000000..abd0d0a9 --- /dev/null +++ b/assets/Design_DataCDN.md.CP-7QzjN.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const c=JSON.parse('{"title":"资源部署与缓存","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DataCDN.md","filePath":"Design/DataCDN.md"}'),e={name:"Design/DataCDN.md"},t=n("",27),l=[t];function h(p,k,r,d,o,F){return i(),a("div",null,l)}const b=s(e,[["render",h]]);export{c as __pageData,b as default}; diff --git a/assets/Design_DebugAndException.md.B6v48M9a.js b/assets/Design_DebugAndException.md.B6v48M9a.js new file mode 100644 index 00000000..fe0d7622 --- /dev/null +++ b/assets/Design_DebugAndException.md.B6v48M9a.js @@ -0,0 +1,14 @@ +import{_ as e,c as n,a as s,a4 as a,m as i,o as t}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/debugexception4.DSUeoQnT.png",p="/minigame-unity-webgl-transform/assets/debugexception5.CVudNa9e.png",o="/minigame-unity-webgl-transform/assets/debugexception1.BCEW4Vpv.png",h="/minigame-unity-webgl-transform/assets/debugexception9.W-PbBU-g.png",r="/minigame-unity-webgl-transform/assets/debugexception8.c2_HLQJn.png",g="/minigame-unity-webgl-transform/assets/debugexception7.DPXuZd9S.png",c="/minigame-unity-webgl-transform/assets/debugexception6.B1QYPPoJ.png",d="/minigame-unity-webgl-transform/assets/debugexception3.BbzACAPG.png",k="/minigame-unity-webgl-transform/assets/debugexception2.DcBQavmG.png",P=JSON.parse('{"title":"错误调试与异常排查","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DebugAndException.md","filePath":"Design/DebugAndException.md"}'),u={name:"Design/DebugAndException.md"},m=a('

错误调试与异常排查

本文阐述开发者在遇到转换后的游戏在开发者工具或真机遇到异常时,如何找到对应堆栈并解决问题。

如何排查程序中出现的异常

如何查看日志

小游戏出现异常或错误时,通过以下方式打开 console:

注意:在WASM代码分包情况下,应该使用jxxx的数字作为函数id

默认情况下,函数堆栈是不可读的函数id,那么可通过以下两种方法之一来获得可读函数名

如何通过错误堆栈查找源代码问题

使用Profiling-funcs

转换面板勾选profiling-funcs, 导出的代码包中将包含可读函数名。 正式上线版本请务必关闭profiling-funcs,或使用代码分包(可自动剔除函数名)。

使用symbols文件可读函数名

以文本方式打开导出目录/webgl/Build/xxx.symbols 文件

',15),b=a('

这里有个小工具可以帮助替换日志(在WASM代码分包情况下,需要自行稍做修改)

影响异常错误的导出选项

推荐配置(转换插件默认设置)

Enable Exceptions

BuildSettings->Player Settings->Publish Settings->Enable Exceptions 选项表示 Unity 引擎捕捉哪种级别的异常

什么是异常级别? 简单来说,就是确定哪些异常由引擎捕捉,未被捕捉的异常将抛给 WASM 虚拟机,最终会导致 VM 结束。

以代码为例

C#
        // 程序捕捉异常
+        try
+        {
+            GameObject go = null;
+            Debug.Log(go.name);
+        }
+        catch (Exception ex)
+        {
+            Debug.Log(ex);
+        }
+
+        // 程序未捕捉异常
+        GameObject go2 = null;
+        Debug.Log(go2.name);

这段代码有两处异常: 1. 程序捕捉的异常, 2.程序未捕捉异常(通常是问题所在)

None

异常捕捉:不捕捉任何异常,引擎或业务代码导致的异常都会抛出到 WASM,并导致程序 Crash。 该选项性能最高,但必须保证游戏不使用任何异常,try catch 也无法捕捉任何异常。从下图看到程序在第 1 个 Exception 产生时已终止,代码是无法 catch 该异常的。

异常信息:取决于虚拟机,在开发者工具有出现详细堆栈函数 ID,在真机环境则无。

Explicitly Thrown Exceptions Only

异常捕捉: 游戏代码的异常将被捕捉,如果非致命异常(不在关键路径上),逻辑代码可以继续。try catch 有效。

异常信息:Debug.Log 等函数等与程序未捕捉异常可输出简要的异常信息,无堆栈信息。

Full Without Stacktrace

异常捕捉: 同"Explicitly Thrown Exceptions Only", 且引擎还会增加额外的底层异常检查,比如”Null References Out of Bounds Array accesses“。

异常信息: Debug.Log 等函数与程序未捕捉异常都只有输出简要的异常信息,无堆栈信息。

Full With Stacktrace

异常捕捉: 同"Full Without Stacktrace"

异常信息: Debug.Log 等函数得到完整的堆栈,程序未捕捉异常有最浅层堆栈函数名。

注意:

None 性能最高,但此模式必须保证游戏代码(包括第三方插件)不使用异常,一旦命中异常即使 catch 也无效,会直接导致程序终止。Explicitly Thrown Exceptions Only 是几种选择中鲁棒性和信息提示较为均衡的,推荐发布使用。Full With Stacktrace 会严重影响性能,切忌在发布版本中使用。

Debug Symbols

BuildSettings->Player Settings->Publish Settings->DebugSymbols

',27),E=i("h3",{id:"development-build",tabindex:"-1"},[s("Development Build "),i("a",{class:"header-anchor",href:"#development-build","aria-label":'Permalink to "Development Build"'},"​")],-1),y=i("img",{src:k,width:"800"},null,-1);function _(x,f,D,F,S,B){return t(),n("div",null,[m,s(" 通过日志的函数id找到对应的原始函数名,分析调用堆栈。 "),b,s(" Debug Symbols将产生函数id与函数名之间的映射关系,使用文本方式打开即可。 通常我们从异常log中找到函数id,此时可通过该文件找到C#源代码中的函数名。 "),E,y,s(' Development Build会在异常产生时直接附带完整的函数名,与"Full With Stacktrace"类似,且程序未捕捉异常也有详细堆栈。该选项产生的代码体积较大,且对性能有较大影响。 ')])}const q=e(u,[["render",_]]);export{P as __pageData,q as default}; diff --git a/assets/Design_DebugAndException.md.B6v48M9a.lean.js b/assets/Design_DebugAndException.md.B6v48M9a.lean.js new file mode 100644 index 00000000..af684c65 --- /dev/null +++ b/assets/Design_DebugAndException.md.B6v48M9a.lean.js @@ -0,0 +1 @@ +import{_ as e,c as n,a as s,a4 as a,m as i,o as t}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/debugexception4.DSUeoQnT.png",p="/minigame-unity-webgl-transform/assets/debugexception5.CVudNa9e.png",o="/minigame-unity-webgl-transform/assets/debugexception1.BCEW4Vpv.png",h="/minigame-unity-webgl-transform/assets/debugexception9.W-PbBU-g.png",r="/minigame-unity-webgl-transform/assets/debugexception8.c2_HLQJn.png",g="/minigame-unity-webgl-transform/assets/debugexception7.DPXuZd9S.png",c="/minigame-unity-webgl-transform/assets/debugexception6.B1QYPPoJ.png",d="/minigame-unity-webgl-transform/assets/debugexception3.BbzACAPG.png",k="/minigame-unity-webgl-transform/assets/debugexception2.DcBQavmG.png",P=JSON.parse('{"title":"错误调试与异常排查","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DebugAndException.md","filePath":"Design/DebugAndException.md"}'),u={name:"Design/DebugAndException.md"},m=a("",15),b=a("",27),E=i("h3",{id:"development-build",tabindex:"-1"},[s("Development Build "),i("a",{class:"header-anchor",href:"#development-build","aria-label":'Permalink to "Development Build"'},"​")],-1),y=i("img",{src:k,width:"800"},null,-1);function _(x,f,D,F,S,B){return t(),n("div",null,[m,s(" 通过日志的函数id找到对应的原始函数名,分析调用堆栈。 "),b,s(" Debug Symbols将产生函数id与函数名之间的映射关系,使用文本方式打开即可。 通常我们从异常log中找到函数id,此时可通过该文件找到C#源代码中的函数名。 "),E,y,s(' Development Build会在异常产生时直接附带完整的函数名,与"Full With Stacktrace"类似,且程序未捕捉异常也有详细堆栈。该选项产生的代码体积较大,且对性能有较大影响。 ')])}const q=e(u,[["render",_]]);export{P as __pageData,q as default}; diff --git a/assets/Design_DevelopmentQAList.md.DTehlE5h.js b/assets/Design_DevelopmentQAList.md.DTehlE5h.js new file mode 100644 index 00000000..db56bc12 --- /dev/null +++ b/assets/Design_DevelopmentQAList.md.DTehlE5h.js @@ -0,0 +1,20 @@ +import{_ as i,c as a,o as e,a4 as l}from"./chunks/framework.Br2U662V.js";const s="/minigame-unity-webgl-transform/assets/addplugin.DpVfb8Rz.png",b=JSON.parse('{"title":"技术常见问题QA","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DevelopmentQAList.md","filePath":"Design/DevelopmentQAList.md"}'),n={name:"Design/DevelopmentQAList.md"},t=l('

技术常见问题QA

工具使用

1.微信开发者工具打开时提示“app.json未找到”

2.微信开发者工具打开时提示“找不到game.json或读取错误”

3.如何在真机上预览游戏

4.如何在真机上进行调试和错误日志排查

5.Unity PlayerSettings导出选项中使用"brotli"或"gzip", 使用微信开发者工具无法启动游戏

6.使用代码分包的情况下,启动游戏出现“首次拉取代码分包”提示

7.微信开发者工具提示"资源下载失败"

8.微信开发者工具能正常打开游戏,但Android卡在首屏,资源下载失败

9.开发者工具提示“插件申请成功,待审核确认”

10.内网开发时,微信开发者工具服务异常

11.开发者工具提示pluginid: wx7a727ff7d940bb3f, permission deny字样错误

Q:

A: 新版导出插件使用小游戏插件来渲染关系链数据,因此需要添加插件。可通过微信开发者工具控制台-添加插件的报错信息添加插件,即可正常使用。同时需要注意实际未使用关系链数据时请删掉game.json中plugins.Layout配置。如果开发者工具控制台没有添加插件的入口请手动在MP端添加插件或者升级至最新版本的开发者工具。

12.小游戏包中的webgl.wasm.symbols.unityweb不会被上传,是做什么用的

13.如何自定义接入构建流程

CSharp
if (WXConvertCore.DoExport() == WXConvertCore.WXExportError.SUCCEED) {
+  Debug.Log("成功");
+  //... 后续操作
+} else {
+  Debug.LogError("失败");
+}

Unity WebGL

1.能否使用System.Net命名空间下的接口

2.小游戏启动出现"Unable to load DLL ...."

3.能否使用System.File相关接口做文件存储

4.如何接入第三方的js sdk, 能写js脚本和C#进行交互吗?

5.小游戏的中文字体不显示,但Editor没问题

6.游戏逻辑是否能使用lua

7.Touch事件丢失或错误,导致多点触控不正确

8.显示黑屏,运行提示大量shader编译错误

9.Unity FMOD音频插件是否支持?

10.Mac 系统下 Unity 构建 WebGL 项目报Failed running "../il2cppcore/il2cppcore.dll"错误解决办法

11.引擎代码裁剪级别(Managed Striping Level)应该如何设置?

12.使用xlua等方案在WebGL平台报“ArgumentException: Destination array was not long enough”?

平台适配

1.文本输入框点击无法输入,没有弹出输入法

2.高性能模式下iOS无法加载,但Android和微信开发者工具没问题

3.Android运行达到满帧较为流畅,iOS性能差

4.小游戏中能插入超链接跳转网页吗?

5.小游戏是否支持Unity VideoPlayer

6.小游戏应该使用哪个接口进行限制帧率?

7.Unity Audio音频是否需要使用小游戏音频适配

8.PlayerPref或用户数据存储失效

9.微信接口提示“fail require user interaction (only in touchend event)”

10. 团结引擎导出的小游戏卡在Loading界面并提示“MONO_WASM: Failed to load config file ./blazor.boot.json”

11. 使用 WebGL2 URP管线导出小游戏时提示 shader 编译报错 “Hidden/Universal/CoreBlit: invalid pass index 1 in DrawProcedural”

12. PC端输入框无法输入,移动端正常

`,81),r=[t];function h(o,d,p,u,k,c){return e(),a("div",null,r)}const m=i(n,[["render",h]]);export{b as __pageData,m as default}; diff --git a/assets/Design_DevelopmentQAList.md.DTehlE5h.lean.js b/assets/Design_DevelopmentQAList.md.DTehlE5h.lean.js new file mode 100644 index 00000000..c3f7a3a0 --- /dev/null +++ b/assets/Design_DevelopmentQAList.md.DTehlE5h.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as e,a4 as l}from"./chunks/framework.Br2U662V.js";const s="/minigame-unity-webgl-transform/assets/addplugin.DpVfb8Rz.png",b=JSON.parse('{"title":"技术常见问题QA","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DevelopmentQAList.md","filePath":"Design/DevelopmentQAList.md"}'),n={name:"Design/DevelopmentQAList.md"},t=l("",81),r=[t];function h(o,d,p,u,k,c){return e(),a("div",null,r)}const m=i(n,[["render",h]]);export{b as __pageData,m as default}; diff --git a/assets/Design_DevtoolsDomain.md.BZk7ZQVg.js b/assets/Design_DevtoolsDomain.md.BZk7ZQVg.js new file mode 100644 index 00000000..6552ce86 --- /dev/null +++ b/assets/Design_DevtoolsDomain.md.BZk7ZQVg.js @@ -0,0 +1,33 @@ +import{_ as s,c as n,o as a,a4 as p}from"./chunks/framework.Br2U662V.js";const q=JSON.parse('{"title":"微信开发者工具域名列表","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DevtoolsDomain.md","filePath":"Design/DevtoolsDomain.md"}'),e={name:"Design/DevtoolsDomain.md"},l=p(`

微信开发者工具域名列表

内网使用微信开发者工具时需要放开这些域名的限制方可正常使用

参考 https://developers.weixin.qq.com/community/develop/article/doc/000e426d34c788ac39ad82e1756813

https://mp.weixin.qq.com
+
+https://open.weixin.qq.com
+
+https://long.open.weixin.qq.com
+
+https://lp.open.weixin.qq.com
+
+https://servicewechat.com
+
+https://dldir1.qq.com
+
+https://res.wx.qq.com
+
+https://tcb.cloud.tencent.com
+
+https://scf.tencentcloudapi.com
+
+https://flexdb.tencentcloudapi.com
+
+https://tcb.tencentcloudapi.com
+
+wss://wxagame.weixin.qq.com
+
+https://long.wxagame.weixin.qq.com
+
+https://cube.weixinbridge.com
+
+https://repot.url.cn
+
+https://fuwu.weixin.qq.com
+
+https://res.servicewechat.com
`,4),c=[l];function t(i,o,r,d,m,h){return a(),n("div",null,c)}const u=s(e,[["render",t]]);export{q as __pageData,u as default}; diff --git a/assets/Design_DevtoolsDomain.md.BZk7ZQVg.lean.js b/assets/Design_DevtoolsDomain.md.BZk7ZQVg.lean.js new file mode 100644 index 00000000..6fc7b26c --- /dev/null +++ b/assets/Design_DevtoolsDomain.md.BZk7ZQVg.lean.js @@ -0,0 +1 @@ +import{_ as s,c as n,o as a,a4 as p}from"./chunks/framework.Br2U662V.js";const q=JSON.parse('{"title":"微信开发者工具域名列表","description":"","frontmatter":{},"headers":[],"relativePath":"Design/DevtoolsDomain.md","filePath":"Design/DevtoolsDomain.md"}'),e={name:"Design/DevtoolsDomain.md"},l=p("",4),c=[l];function t(i,o,r,d,m,h){return a(),n("div",null,c)}const u=s(e,[["render",t]]);export{q as __pageData,u as default}; diff --git a/assets/Design_Evaluation.md.CSX9uvMD.js b/assets/Design_Evaluation.md.CSX9uvMD.js new file mode 100644 index 00000000..c945457b --- /dev/null +++ b/assets/Design_Evaluation.md.CSX9uvMD.js @@ -0,0 +1 @@ +import{_ as t,c as d,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const b=JSON.parse('{"title":"方案评估","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Evaluation.md","filePath":"Design/Evaluation.md"}'),r={name:"Design/Evaluation.md"},i=e('

方案评估

1. 游戏类目

考虑到游戏体积与逻辑复杂度,目前建议中轻度2D/3D游戏进行转换,游戏类目包括:

对重度游戏如MMO/FPS等游戏需根据实际情况评估

2. 引擎版本

版本建议:

Unity版本支持从2018到最新的2022版本

建议使用LTS版本,尽量使用2022(更快编译和更小体积、压缩纹理、压缩音频等支持)

3. 能力支持

能力是否支持解决方案
Unity基础模块支持支持动画、物理、AI、UI等基础模块
渲染管线支持支持标准渲染管线、URP
资源加载支持Addressable、AssetBundle网络异步加载
Lua脚本支持支持标准Lua与常见binding(如xlua, tolua等), 不支持Luajit。需根据实际游戏在真机验证性能
PureTS支持iOS系统需14.5以上, 支持JIT
Unity音频支持UnityAudio基本能力支持,支持fmod插件(长音频请使用UnityAudio), 但不支持wwise。
第三方插件部分支持支持大部分插件,C#插件与非平台相关的C原生插件
网络系统需调整HTTP使用UnityWebRequest,TCP使用WX SDK适配或WebSocket通信替代(如开源的UnityWebSocket插件),UDP使用WX SDK适配
渲染接口支持仅支持WebGL1.0(相当于OpenGLES2.0),2.0支持处于Beta测试阶段
多线程不支持删除多线程用法,使用异步等其他替代方式
文件API需调整不支持System.File接口,但可使用微信小游戏WX SDK实现文件存储,大小限制为200MB(最高可开通1GB)。玩家存档请使用服务器或云开发;AssetsBundle缓存适配插件已自动支持
',11),o=[i];function l(n,s,h,_,c,u){return a(),d("div",null,o)}const m=t(r,[["render",l]]);export{b as __pageData,m as default}; diff --git a/assets/Design_Evaluation.md.CSX9uvMD.lean.js b/assets/Design_Evaluation.md.CSX9uvMD.lean.js new file mode 100644 index 00000000..8fadb929 --- /dev/null +++ b/assets/Design_Evaluation.md.CSX9uvMD.lean.js @@ -0,0 +1 @@ +import{_ as t,c as d,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const b=JSON.parse('{"title":"方案评估","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Evaluation.md","filePath":"Design/Evaluation.md"}'),r={name:"Design/Evaluation.md"},i=e("",11),o=[i];function l(n,s,h,_,c,u){return a(),d("div",null,o)}const m=t(r,[["render",l]]);export{b as __pageData,m as default}; diff --git a/assets/Design_FileCache.md.DaJotKv1.js b/assets/Design_FileCache.md.DaJotKv1.js new file mode 100644 index 00000000..3c605a49 --- /dev/null +++ b/assets/Design_FileCache.md.DaJotKv1.js @@ -0,0 +1,59 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/file_cache.BSYo5Xk8.png",n="/minigame-unity-webgl-transform/assets/cache_path.DmEqMbAH.png",E=JSON.parse('{"title":"资源缓存","description":"","frontmatter":{},"headers":[],"relativePath":"Design/FileCache.md","filePath":"Design/FileCache.md"}'),t={name:"Design/FileCache.md"},h=e('

资源缓存

介绍

小游戏主要存在三种类型的资源:

  1. wasm代码,即wasm.code.unityweb文件
  2. 首资源包,即webgl.data.unityweb文件
  3. 业务bundle资源

其中,wasm代码和首资源包框架会强制缓存,开发者无需关心。本篇重点介绍业务资源的缓存规则。

与APP游戏不同,在小游戏中推荐将资源包拆分成为一个个小文件加载。结合启动Loader有以下优势:

  1. 通过细粒度的资源拆分,提高下载成功率。
  2. 文件粒度缓存,降低版本更新时的流量消耗。
  3. 框架自动做缓存控制,开发者无需感知本地是否存在缓存。

大致流程如图:

一、什么情况触发资源缓存

当使用以下API发起网络请求时会检查是否需要缓存,以及是否命中缓存。

游戏业务侧无需关心资源是否有缓存,按照本地没有缓存来使用,正常调用API即可,当有缓存时,Loader插件会构造正常响应返回给游戏

二、哪些资源会自动缓存?

三、缓存规则

相关配置

Assets/WX-WASM-SDK/Editor/MiniGameConfig.asset 中以下配置与缓存相关

// 业务资源相关
+bundlePathIdentifier: 需要缓存的路径,用 \`;\`分隔 eg: StreamingAssets;bundles;
+excludeFileExtensions: 当路径中包含字符时不需要缓存,用 \`;\`分隔 eg: .json;.hash
+bundleHashLength: bundle中hash占多少长度
+// 纹理相关
+needCacheTextures: 是否缓存纹理
+texturesPath: 纹理存放路径
+texturesHashLength: 纹理中hash长度
+// 缓存淘汰相关
+defaultReleaseSize: 清理缓存时默认额外清理的大小,单位Bytes,默认值30MB
+maxStorage: 最大缓存容量,单位MB,默认值200MB

其中部分配置可通过转换插件面板快速修改:

是否缓存规则

存在业务的bundle资源和使用微信压缩纹理工具后的纹理资源,不同资源的缓存细节略有不同。

是否缓存业务资源

默认URL中包含StreamingAssets的请求会被识别为资源文件被自动缓存,可修改 bundlePathIdentifier 为你期望的值

并非所有文件都适合持久化缓存,因此缓存规则也支持忽略某些文件,默认包含 .json 的文件不会被自动缓存,可修改 bundleExcludeExtensions。等同于修改导出插件面板不自动缓存文件类型配置

对应 js 代码,minigame/unity-namespace.js

ts
// 判断是否需要自动缓存的文件,返回true自动缓存;false不自动缓存
+unityNamespace.isCacheableFile = function (path) {
+  // 判定为下载bundle的路径标识符,此路径下的下载,会自动缓存
+  const cacheableFileIdentifier = ["StreamingAssets"];
+  // 命中路径标识符的情况下,并不是所有文件都有必要缓存,过滤下不需要缓存的文件
+  const excludeFileIdentifier = [".json"];
+  if (
+    cacheableFileIdentifier.some(identifier => path.includes(identifier)
+        && excludeFileIdentifier.every(excludeIdentifier => !path.includes(excludeIdentifier)))
+  ) {
+    return true;
+  }
+  return false;
+};
是否缓存纹理

默认会缓存纹理,修改needCacheTextures可控制是否缓存纹理资源。

通过texturesPath可让Loader识别一条请求是否为纹理,默认为Assets/Textures

资源淘汰规则

如开篇的流程图所示,当需要自动缓存的文件在写入本地之前,若本地已经有此文件的旧缓存,则先清理旧缓存,再执行写入,那么需要一个手段来区分资源版本。

识别业务资源版本

框架不会做额外计算来验证资源版本,通过文件名中带资源hash,可以在资源更新时,识别不同版本的资源。

Addressables为例,打包参数加上BuildAssetBundleOptions.AppendHashToAssetBundleName,会携带32位长度的hash拼接到文件名末尾。

默认hash长度为32,可通过bundleHashLength修改。等同于修改导出插件面板Bundle名中Hash长度

以下几种命名都能识别到版本号8d265a9dfd6cb7669cdb8b726f0afb1e eg1: font_8d265a9dfd6cb7669cdb8b726f0afb1e eg2: font-8d265a9dfd6cb7669cdb8b726f0afb1e eg3: font_8d265a9dfd6cb7669cdb8b726f0afb1e.ttf

识别纹理资源版本

因纹理打包规则不一致,hash长度也不一样,默认hash长度为8,可通过texturesHashLength配置。

缓存清理规则

随着游戏进度的推进,累计资源体积可能会超过允许的最大值。

注意!!!此最大值通过maxStorage修改,未前往mp后台-能力地图-生产提效包-空间提升开通空间提升的游戏,请勿设置超过200MB的值

达到缓存上限后,一些游戏前期的资源已经不需要再被使用。 此时Loader会按照LRU规则,清理出所需大小,并且为了避免频繁触发清理,会默认多清理30MB的空间,可通过defaultReleaseSize修改。

同时,在清理时也支持忽略一些文件,永不被自动清理,只可通过fs接口主动删除。

通过导出的小游戏minigame/untiy-namespace.jsisErasableFilejavascript函数自行控制

js
// 清理缓存时是否可被自动清理;返回true可自动清理;返回false不可自动清理
+unityNamespace.isErasableFile = function (info) {
+  // 用于特定AssetBundle的缓存保持
+  if (unityNamespace.WXAssetBundles.has(info.path)) {
+    return false;
+  }
+  // 达到缓存上限时,不会被自动清理的文件
+  // 例如,font文件不希望自动清理
+  const inErasableIdentifier = ['font_8d265a9dfd6cb7669cdb8b726f0afb1e.ttf'];
+  if (inErasableIdentifier.some(identifier => info.path.includes(identifier))) {
+    return false;
+  }
+  return true;
+};

示例

假设有以下配置

1. DATA_CDN: https://weixin.qq.com/webgl
+2. bundlePathIdentifier: ['StreamingAssets']
+3. bundleHashLength: 32

在写入缓存前需要经过三步

  1. 根据URL生成缓存路径 URL剔除掉DATA_CDN部分后作为缓存路径 例如:

那么:

注意:资源实际部署的CDN前缀必须与转换面板填写的CDN地址一致,否则无法按照前文的缓存规则获得资源的唯一标识。导致缓存失败

  1. 清理掉同名旧文件 通过文件名中的hash区分同名文件的不同版本 继续上面的例子,假如本地已经有StreamingAssets/textures_cdb8b726f0afb1e8d265a9dfd6cb7669 在写入缓存前,插件认为已经本地已经有同名文件StreamingAssets/textures,但hash与本次写入的文件不一致,则需要删除StreamingAssets/textures_cdb8b726f0afb1e8d265a9dfd6cb7669

支持的bundle命名:需以-_分割,当以其他符号分割时,无法正确处理版本信息,故无法正确删除旧版本资源

转换插件相关配置

bundleHashLength: bundle中hash的长度
  1. 检查存储空间是否足够,是否需要清理 当已有缓存+待写入缓存超过允许的上限时,按照LRU清理出所需大小

转换插件相关配置

defaultReleaseSize: 清理时,默认额外清理的大小,单位Bytes,1MB = 1024KB = 1024*1024Bytes
+maxStorage: 最大缓存容量,修改此值需要联系研发助手开通权限,否则无效

四、查看缓存日志

查看插件调试日志

判断是否走缓存

  1. 自动缓存 出现以下两种日志,都可认为需要自动缓存
  1. 命中本地缓存: [PLUGIN LOG 20:18.38.275] CacheXMLHttpRequest_onload: scene999_tw_5b9ef7d7.bundle使用缓存, 耗时:37ms

其他缓存日志

  1. 删除 xxx 旧缓存:清理同名文件旧缓存
  2. 需要释放xxMB存储空间:达到缓存上限,需要释放的空间大小
  3. 缓存文件数=xxx, 总文件大小=xxx:当前缓存目录总文件数和总文件大小(单位 bytes)
  4. 删除文件: xx, md5:xx, size:xx, 耗时: xx:清理旧缓存或达到缓存上限时删除文件

对外接口

public string WX.PluginCachePath

获取自动缓存的文件存储路径,返回值:\${wx.env.USER_DATA_PATH}/__GAME_FILE_CACHE

GameGlobal.manager.PLUGIN_CACHE_PATH

public string WX.GetCachePath(string url)

传入URL或文件相对路径,若本地有文件缓存,返回缓存路径,否则返回空字符串

GameGlobal.manager.getCachePath

public void CleanAllFileCache(Action<bool> action)

清理所有自动缓存的文件

Promise<boolean> GameGlobal.manager.cleanAllCache()

public void CleanFileCache(int fileSize, Action<ReleaseResult> action)

从自动缓存目录中释放指定大小的文件缓存

Promise<ReleaseResult> GameGlobal.manager.cleanCache(fileSize)

cs
/// <summary>
+/// 清理文件缓存的结果
+/// </summary>
+public enum ReleaseResult
+{
+    /// <summary>
+    /// 无需清理,空间足够
+    /// </summary>
+    noNeedRelease = 1,
+
+    /// <summary>
+    /// 超过最大存储容量,不清理
+    /// </summary>
+    exceedMax,
+
+    /// <summary>
+    /// 清理成功
+    /// </summary>
+    releaseSuccess,
+}

public void RemoveFile(string path, Action<bool> action)

从自动缓存目录中删除指定文件

Promise<void> GameGlobal.manager.removeFile(path)

五、注意项

  1. 文件名需要带上hash BuildAssetBundleOptions.AppendHashToAssetBundleName,以便清理掉该文件的旧缓存。默认32位长度,可通过导出选项中Bundle名中Hash长度来自定义。比如游戏自己计算了crc,可将Bundle名中Hash长度设置为crc长度。
  2. 配置到不自动缓存文件类型中的文件,不会自动缓存,默认值是json,比如addressable打包后生成StreamingAssets/aa/WebGL/catalog.json,这个文件不会自动缓存。
  3. 缓存目录
  1. 当文件没有正常缓存时,着重检查 缓存规则 中 资源下载URLDATA_CDN、和 bundlePathIdentifier,当资源下载URL中不包含DATA_CDN时,不会走缓存逻辑。

  2. 真机安卓缓存目录:data/com.tencent.mm/MicroMsg/wxanewfiles/随机ID(根据最近使用时间判断是哪个目录)

  3. 未开通mp后台-能力地图-生产提效包-空间提升的游戏,修改maxStorage超过200MB会导致出现写缓存失败。

QA

1. PC上配置为不自动缓存的文件,仍然没有走网络下载

PC上使用了Chromium的网络模块,存在HTTP缓存,可通过请求添加时间戳、服务器返回不缓存的头

2. 同一个文件,日志提示执行缓存逻辑,下次运行时仍然从网络下载

可能有两种情况:

  1. 请求同名资源的不同版本 可能预下载列表中配置的资源版本和UnityWebRequest请求的版本不一致,由于缓存清理逻辑:

如何检查:从缓存日志中搜索不带hash的资源名,出现两个版本的下载日志。

  1. 缓存写满之后的自动清理逻辑 当出现以下日志,可认为资源被自动清理,可查阅本篇「缓存清理规则」

3. 已经有无缓存,执行缓存逻辑的日志,缓存仍不生效,下次访问资源仍从网络下载

资源下载URL中不包含DATA_CDN部分,可能是运行期间修改了CDN,但并没有同步修改资源下载URL。

如何检查:

4. 如何切换备用CDN地址

参考Unity Loader - 资源下载

5. 一些配置文件不希望被自动清理,由业务控制何时清理

参考本篇「缓存清理规则」将这些文件添加到inErasableIdentifier中。

注意:业务侧注意在适当时机清理文件,否则文件将会一直在缓存目录中。

',121),p=[h];function d(o,c,r,k,u,g){return i(),s("div",null,p)}const f=a(t,[["render",d]]);export{E as __pageData,f as default}; diff --git a/assets/Design_FileCache.md.DaJotKv1.lean.js b/assets/Design_FileCache.md.DaJotKv1.lean.js new file mode 100644 index 00000000..ec78816f --- /dev/null +++ b/assets/Design_FileCache.md.DaJotKv1.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/file_cache.BSYo5Xk8.png",n="/minigame-unity-webgl-transform/assets/cache_path.DmEqMbAH.png",E=JSON.parse('{"title":"资源缓存","description":"","frontmatter":{},"headers":[],"relativePath":"Design/FileCache.md","filePath":"Design/FileCache.md"}'),t={name:"Design/FileCache.md"},h=e("",121),p=[h];function d(o,c,r,k,u,g){return i(),s("div",null,p)}const f=a(t,[["render",d]]);export{E as __pageData,f as default}; diff --git a/assets/Design_FirstSceneOptimization.md.CcSBIIZy.js b/assets/Design_FirstSceneOptimization.md.CcSBIIZy.js new file mode 100644 index 00000000..e245dc47 --- /dev/null +++ b/assets/Design_FirstSceneOptimization.md.CcSBIIZy.js @@ -0,0 +1,8 @@ +import{_ as e,E as s,c as n,m as l,a as t,J as r,w as o,a4 as i,o as p}from"./chunks/framework.Br2U662V.js";const h="/minigame-unity-webgl-transform/assets/profile.yCnwPQ6L.png",d="/minigame-unity-webgl-transform/assets/stop.CFvG6dL8.png",m="/minigame-unity-webgl-transform/assets/stopprofile.DmPV0U4-.png",c="/minigame-unity-webgl-transform/assets/chromeload.sYqunEFg.png",g="/minigame-unity-webgl-transform/assets/benchmarkprofile.BvHHzfgK.png",v=JSON.parse('{"title":"首场景启动优化","description":"","frontmatter":{},"headers":[],"relativePath":"Design/FirstSceneOptimization.md","filePath":"Design/FirstSceneOptimization.md"}'),k={name:"Design/FirstSceneOptimization.md"},f=i('

首场景启动优化

提升Unity WebGL游戏启动速度章节我们提到过:

在timelog中呈现的首场景耗时即为引擎初始化与开发者首帧逻辑,关于该阶段耗时,开发者需要注意的是:

  1. MonoBehaviour脚本的首帧Start/Awake应足够少逻辑,优先将画面呈现
  2. 初始场景不宜过大,通常呈现Splash场景即可
  3. 初始场景中需要后续主场景或配置加载时可采取分帧策略,切勿在Start/Awake阻塞

下面介绍如何通过在小游戏下通过Profile的方式对小游戏首场景耗时进行针对性优化。

小游戏Profile

微信小游戏在安卓平台提供了CPU Profile能力,使用姿势为: 1.采集Profile: 点击右上角菜单 -> 开发调试 -> Start CPU Profile -> Stop CPU Profile; 2.导出Profile文件 当点击Stop CPU Profile之后,会弹出浮窗告知profile文件的存储路径,通过USB链接电脑或者第三方文件管理器即可将Profile文件传输至电脑。

3.Chrome导入Profile文件 打开Chrome浏览器,右键审查元素或者按F12即可打开控制台界面。选中JavaScript Profile tab(如果默认没有,可能在右上角的三个点展开菜单->More tools里面),点击load导入步骤2的profile文件,Profile文件的使用可以参考Google的开发文档: https://developers.google.com/web/tools/chrome-devtools/rendering-tools/js-execution

Unity CallMain

参考文档小游戏启动流程中提到的,当游戏代码包下载编译完成和首包资源下载完成后会运行游戏逻辑,最开始执行的逻辑是CallMain主函数。 在WebGL模式下,CallMain的主要是initWebGLPlayer调用,主要分成两部分调用:

下表为针对Unity Benchmark项目在不同设备上的callmain耗时分析,Benchmark项目链接:https://github.com/Unity-Technologies/Benchmark

下面实验均采用Unity 2018.4.24f1版本,Development模式会对性能有一定影响,下表数据均为Development模式下数据。

initWebGLPlayer主要函数安卓魅族6sOPPO A37m安卓小米10开发者工具
InitializeIl2CppFromMain525ms954ms113ms39.90ms
RuntimeInitialize139ms649ms50.2ms2.33ms
PlayerInitEngineNoGraphics463.8ms1.24s154ms10.46ms
PlayerInitEngineGraphics1.4s2.94s403ms126ms
PlayerLoadFirstScene815ms2.12s213ms70.75ms
',13),E=i(`

CallMain Profile分析

1.改造小游戏代码 因为安卓采集Profile文件需要手动控制,而CallMain会在码包下载编译完成和首包资源下载完成后就执行,为了录制启动阶段完整的Profile,需要保证Profile的录制开始之后才真正执行游戏开始逻辑,找到项目的game.js文件,改造最后几行即可:

js
// gameManager.startGame();
+
+wx.onTouchStart((result) => {
+  console.log('真正执行开始游戏逻辑');
+  gameManager.startGame();
+})
+
+GameGlobal.manager = gameManager;

通过上面的改造,在进入小游戏后,可以按照这个流程采集Profile:Start CPU Profile -> 点击屏幕触发真正的开始游戏逻辑 -> 看到游戏界面后Stop Profile。

2.导入步骤1的启动过程Profile文件

导入文件后,我们只需要关注CallMain调用的PlayerLoadFirstScene函数,如果PlayerLoadFirstScene耗时占比过高,大多是因为在首场景执行了不必要的操作,比如大量反序列化操作、配置解析操作,按需剔除后再次Profile即可验证效果。

',6);function P(_,y,u,b,C,S){const a=s("font");return p(),n("div",null,[f,l("p",null,[t("目前为止,开发者可以操作的主要是PlayerLoadFirstScene函数的调用,参照Unity的Benchmark项目,要尽可能将PlayerLoadFirstScene的耗时控制在整个CallMain耗时的"),r(a,{color:"#dd0000"},{default:o(()=>[t("20%")]),_:1}),t("左右,如果CallMain耗时过大,可以借助上面提到的Profile工具进行优化,下面简单分析流程。")]),E])}const w=e(k,[["render",P]]);export{v as __pageData,w as default}; diff --git a/assets/Design_FirstSceneOptimization.md.CcSBIIZy.lean.js b/assets/Design_FirstSceneOptimization.md.CcSBIIZy.lean.js new file mode 100644 index 00000000..e6220055 --- /dev/null +++ b/assets/Design_FirstSceneOptimization.md.CcSBIIZy.lean.js @@ -0,0 +1 @@ +import{_ as e,E as s,c as n,m as l,a as t,J as r,w as o,a4 as i,o as p}from"./chunks/framework.Br2U662V.js";const h="/minigame-unity-webgl-transform/assets/profile.yCnwPQ6L.png",d="/minigame-unity-webgl-transform/assets/stop.CFvG6dL8.png",m="/minigame-unity-webgl-transform/assets/stopprofile.DmPV0U4-.png",c="/minigame-unity-webgl-transform/assets/chromeload.sYqunEFg.png",g="/minigame-unity-webgl-transform/assets/benchmarkprofile.BvHHzfgK.png",v=JSON.parse('{"title":"首场景启动优化","description":"","frontmatter":{},"headers":[],"relativePath":"Design/FirstSceneOptimization.md","filePath":"Design/FirstSceneOptimization.md"}'),k={name:"Design/FirstSceneOptimization.md"},f=i("",13),E=i("",6);function P(_,y,u,b,C,S){const a=s("font");return p(),n("div",null,[f,l("p",null,[t("目前为止,开发者可以操作的主要是PlayerLoadFirstScene函数的调用,参照Unity的Benchmark项目,要尽可能将PlayerLoadFirstScene的耗时控制在整个CallMain耗时的"),r(a,{color:"#dd0000"},{default:o(()=>[t("20%")]),_:1}),t("左右,如果CallMain耗时过大,可以借助上面提到的Profile工具进行优化,下面简单分析流程。")]),E])}const w=e(k,[["render",P]]);export{v as __pageData,w as default}; diff --git a/assets/Design_Guide.md.2Tii1bAr.js b/assets/Design_Guide.md.2Tii1bAr.js new file mode 100644 index 00000000..964050f3 --- /dev/null +++ b/assets/Design_Guide.md.2Tii1bAr.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as r}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/guide1.BFcCfH8z.png",f=JSON.parse('{"title":"Unity 游戏接入微信小游戏指南","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Guide.md","filePath":"Design/Guide.md"}'),i={name:"Design/Guide.md"},l=r('

Unity 游戏接入微信小游戏指南

​ 下图中介绍了新游戏接入微信小游戏平台的主要转换流程,下文将介绍每一个阶段的工作:

Unity快适配调优指南

【阶段一】兼容性评估

相关手册:兼容性评估推荐引擎版本更多小游戏成功转换案例技术常见问题QA

​ 新计划接入游戏的开发者应阅读本节相关手册内容,参考已转化的案例游戏并结合自身游戏情况评估转化的可行性。

【阶段二】项目转换

​ 本节内容将指引开发者如何让自己的游戏工程在微信小游戏平台成功运行。

快速开始——转换工具导出微信小游戏

相关下载: 微信 Unity 插件下载

相关手册:快速开始:转换工具导出微信小游戏

​ 阅读 快速开始:转换工具导出微信小游戏 快速熟悉工具的使用并完成一次简单的转化工作!

资源按需加载

相关手册:资源按需加载概述AA(Addressable) 进行资源按需加载AB(AssetBundle)进行资源按需加载Instant Game 实践指南

​ 区别于原生 APP 游戏很少考虑场景内的资源规划问题,开发时通常将资源在游戏启动时全加载到内存中,而小游戏需要做到“即点即玩”,影响游戏的呈现速度因素中如首资源包的下载往往占比较大,因此需要根据场景中的主次内容进行资源上的优化分包处理。有关分包策略可参阅 资源按需加载概述 选择符合当前游戏的方案,具体实施可阅读具体指引文档。

后端/网络通信适配

相关手册:后端服务指引网络通信适配

​ 区别于原生环境,WebGL模式(JavaScript环境)是不支持使用原生套接字(Socket)实现网络通信。对于游戏中使用到网络请求的操作,需要进行相应的适配。将 HTTP 请求使用 UnityWebRequest 类实现,全双工通信改用 WebSocket 协议实现,可参考手册案例完成适配。

资源服务器部署配置

相关手册:资源部署与缓存资源缓存iOS高性能模式

​ 游戏导出小游戏包(/minigame)将使用微信开发者工具打开,而资源目录(/webgl 或 /webgl-min)需要上传至开发者的 CDN 服务器中,并前往 MP 后台配置安全域名白名单,对于进一步提升 iOS 下的游戏运行效率可前往 MP 申请 iOS 高性能模式,请阅读相关手册完成相应的部署。

开发阶段的错误排查

相关手册:开发错误调试与排查

小游戏存在开发者工具、真机(Android/iOS/PC Windows),当游戏出现异常时可通过日志进行错误堆栈分析。

【阶段三】微信平台能力接入

接入微信API

相关手册:WX SDK 平台能力适配屏幕适配输入法适配排行榜与微信关系数据

​ Unity 游戏接入微信小游戏平台将获得微信提供的 API 以及开放能力,开发者根据需要进行按需接入。微信 API 支持的能力包括登录、设备(存储、震动)、开放数据、广告等等。

启动留存数据上报统计

相关手册:启动留存数据上报统计

​ 在小游戏中玩家对启动时长与体验十分敏感(尤其从“广告”等买量场景进入的玩家),因此需要在必要的位置进行相关的数据上报,Unity Loader 插件为游戏提供了一些基础上报数据,但游戏内部关键帧位置仍需要开发者自行上报,可参阅相关手册完成上报配置。

【阶段四】体验调优

​ 截止本阶段,开发者的 Unity 游戏将在微信小游戏平台成功启动运行,但为了能够达到更佳的游戏体验开发者应继续进行对游戏工程的调优工作,本节将介绍目前微信小游戏平台为开发者提供的调优能力完成上线前的最后优化工作。

首场景启动优化——首帧逻辑优化

相关手册:提升Unity WebGL游戏启动速度启动流程与时时序首场景启动优化

​ 根据统计数据反应,小游戏玩家对于游戏的启动时长是较为敏感的,过长的启动时间会导致用户的显著流失,因此如何快速呈现游戏场景是 Unity 原生 APP 游戏接入微信小游戏平台的一个重点优化的工作。首场景启动优化的并不是一个简单的步骤就可以完全优化,在初始 Unity 工程时开发者应主要对游戏代码如首帧逻辑进行修改,具体可参阅首场景启动优化手册。

资源预下载

相关手册:使用预下载功能

​ 在 UnityLoader 加载过程中是存在CPU处理密集而 网络空闲 的情况,因此可以充分利用该时机进行一些必要的资源下载可有助于提升游戏场景等资源的载入速度。

运行性能及调优

相关手册:优化Unity WebGL的运行性能使用 Android CPU Profiler 性能调优使用 Unity Profiler 性能调优优化 Unity WebGL 内存

​ 游戏转化完成后仍需要对各项的性能指标进行量化测试。

压缩纹理资源

相关手册: 压缩纹理优化

​ 压缩纹理工具是微信SDK提供的一种能够根据不同的游戏运行平台而按需加载压缩后纹理资源的能力。它的优点是:

​ 纹理压缩对于 提升运行速度减少内存 的优化方面均有不错的表现效果,对于重度游戏而言,均建议进行该优化。

WASM代码分包

相关手册:使用代码分包工具

​ Unity 导出小游戏项目后代码将存储在 wasm 文件中,而游戏启动时需要完整的 wasm 文件才可以运行,于是微信小游戏提供了WASM代码分包能力,将原本的 wasm 文件根据游戏逻辑的主次内容分为 2 个 wasm 文件,一个用于启动加载另一个将被延迟加载,这样就允许先加载较小的首包快速进入主场景。该能力可以有效降低内存的使用,以及减少脚本编译的时间

封面图配置

相关手册:启动封面

​ 由于 Unity WebGL 的启动加载需要一定的时间,微信小游戏支持通过配置封面图/视频等内容作为加载期间的过渡来留住玩家,微信小游戏支持如下自定义配置项:

【阶段五】发布上线与现网监控

​ 审核发布可参考 MP 文档 小游戏接入指南 自助完成,游戏相关运行数据请前往 微信公众平台

现网错误日志上报与排查

',57),n=[l];function h(s,p,d,u,c,m){return t(),e("div",null,n)}const q=a(i,[["render",h]]);export{f as __pageData,q as default}; diff --git a/assets/Design_Guide.md.2Tii1bAr.lean.js b/assets/Design_Guide.md.2Tii1bAr.lean.js new file mode 100644 index 00000000..76d7d628 --- /dev/null +++ b/assets/Design_Guide.md.2Tii1bAr.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as r}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/guide1.BFcCfH8z.png",f=JSON.parse('{"title":"Unity 游戏接入微信小游戏指南","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Guide.md","filePath":"Design/Guide.md"}'),i={name:"Design/Guide.md"},l=r("",57),n=[l];function h(s,p,d,u,c,m){return t(),e("div",null,n)}const q=a(i,[["render",h]]);export{f as __pageData,q as default}; diff --git a/assets/Design_InputAdaptation.md.CYV3Uf9j.js b/assets/Design_InputAdaptation.md.CYV3Uf9j.js new file mode 100644 index 00000000..9e3fd793 --- /dev/null +++ b/assets/Design_InputAdaptation.md.CYV3Uf9j.js @@ -0,0 +1,88 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const F=JSON.parse('{"title":"输入法适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/InputAdaptation.md","filePath":"Design/InputAdaptation.md"}'),h={name:"Design/InputAdaptation.md"},p=n(`

输入法适配

支持2022和团结引擎的 Input Field 组件自动适配,低版本或者其他组件暂不支持自动适配

低版本兼容:

在小游戏中Unity游戏唤不起输入法,需要使用WX_SDK中提供的方法来唤起输入法,并做简单的逻辑修改来适配。

详细示例请参考API Demo

以UGUI的Input组件为例,需要给Input 绑定以下脚本:

csharp
using UnityEngine;
+using WeChatWASM;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+
+// 添加 InputField 组件的依赖
+[RequireComponent(typeof(InputField))]
+public class WXInputFieldAdapter : MonoBehaviour, IPointerClickHandler, IPointerExitHandler
+{
+    private InputField _inputField;
+    private bool _isShowKeyboard = false;
+
+    private void Start()
+    {
+        _inputField = GetComponent<InputField>();
+    }
+
+    public void OnPointerClick(PointerEventData eventData)
+    {
+        Debug.Log("OnPointerClick");
+        ShowKeyboard();
+    }
+
+    public void OnPointerExit(PointerEventData eventData)
+    {
+        Debug.Log("OnPointerExit");
+        if (!_inputField.isFocused)
+        {
+            HideKeyboard();
+        }
+    }
+
+    private void OnInput(OnKeyboardInputListenerResult v)
+    {
+        Debug.Log("onInput");
+        Debug.Log(v.value);
+        if (_inputField.isFocused)
+        {
+            _inputField.text = v.value;
+        }
+    }
+
+    private void OnConfirm(OnKeyboardInputListenerResult v)
+    {
+        // 输入法confirm回调
+        Debug.Log("onConfirm");
+        Debug.Log(v.value);
+        HideKeyboard();
+    }
+
+    private void OnComplete(OnKeyboardInputListenerResult v)
+    {
+        // 输入法complete回调
+        Debug.Log("OnComplete");
+        Debug.Log(v.value);
+        HideKeyboard();
+    }
+
+    private void ShowKeyboard()
+    {
+        if (_isShowKeyboard) return;
+        
+        WX.ShowKeyboard(new ShowKeyboardOption()
+        {
+            defaultValue = "xxx",
+            maxLength = 20,
+            confirmType = "go"
+        });
+
+        //绑定回调
+        WX.OnKeyboardConfirm(this.OnConfirm);
+        WX.OnKeyboardComplete(this.OnComplete);
+        WX.OnKeyboardInput(this.OnInput);
+        _isShowKeyboard = true;
+    }
+
+    private void HideKeyboard()
+    {
+        if (!_isShowKeyboard) return;
+        
+        WX.HideKeyboard(new HideKeyboardOption());
+        //删除掉相关事件监听
+        WX.OffKeyboardInput(this.OnInput);
+        WX.OffKeyboardConfirm(this.OnConfirm);
+        WX.OffKeyboardComplete(this.OnComplete);
+        _isShowKeyboard = false;
+    }
+}
`,7),k=[p];function l(t,e,E,r,d,g){return a(),i("div",null,k)}const o=s(h,[["render",l]]);export{F as __pageData,o as default}; diff --git a/assets/Design_InputAdaptation.md.CYV3Uf9j.lean.js b/assets/Design_InputAdaptation.md.CYV3Uf9j.lean.js new file mode 100644 index 00000000..ae8236f9 --- /dev/null +++ b/assets/Design_InputAdaptation.md.CYV3Uf9j.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const F=JSON.parse('{"title":"输入法适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/InputAdaptation.md","filePath":"Design/InputAdaptation.md"}'),h={name:"Design/InputAdaptation.md"},p=n("",7),k=[p];function l(t,e,E,r,d,g){return a(),i("div",null,k)}const o=s(h,[["render",l]]);export{F as __pageData,o as default}; diff --git a/assets/Design_InstantGameGuide.md.5__8NzkS.js b/assets/Design_InstantGameGuide.md.5__8NzkS.js new file mode 100644 index 00000000..12e9a427 --- /dev/null +++ b/assets/Design_InstantGameGuide.md.5__8NzkS.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as e,a4 as n}from"./chunks/framework.Br2U662V.js";const p=JSON.parse('{"title":"使用 AutoStreaming 进行资源按需加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/InstantGameGuide.md","filePath":"Design/InstantGameGuide.md"}'),i={name:"Design/InstantGameGuide.md"},r=n('

使用 AutoStreaming 进行资源按需加载

​ 除常规使用 AA/AB 分包方案外,Unity 官方也提供了 AutoStreaming 转换工具可以实现 Unity 游戏转化至微信小游戏平台的能力。开发者可阅读本文自行选择转换方案。

方案选择建议

​ Instant Game 能够快速有效的将原生 APP 游戏工程在较少的代码修改的情况下完成微信小游戏平台的运行,这得益于 Unity 引擎基于底层实现对游戏资源的异步加载能力,并将这些资源托管至 CCD 服务中。对于开发者而言,若游戏为休闲关卡类等小型游戏,使用 Instant Game 能够减少游戏的转化工时。适用于 Instant Game 转化的游戏一般具备:

​ Instant Game 对于极小的休闲类游戏将具备更快更小修改代价将游戏迁移至微信小游戏环境内运行,若追求较好的游戏品质,无论哪一种方案都需要开发者专项的适配。在部署方面 Instant Game 需要使用平台提供的 CDN 服务,不支持开发者自建。

实践指南

​ 请前往 Unity微信小游戏专区 (https://unity.cn/instantgame/docs/WechatMinigame/Demo) 阅读转换指引。

Q&A

1.游戏在微信开发者工具中运行缺失资源?

​ 经过 AutoStreaming 转换后开发者应在微信开发者工具检查控制台中Network面板资源是否加载正常,若存在404时,需要查看资源是否正确上传、读取路径是否正确等。

',11),o=[r];function s(l,m,h,c,d,u){return e(),t("div",null,o)}const g=a(i,[["render",s]]);export{p as __pageData,g as default}; diff --git a/assets/Design_InstantGameGuide.md.5__8NzkS.lean.js b/assets/Design_InstantGameGuide.md.5__8NzkS.lean.js new file mode 100644 index 00000000..d8811a0a --- /dev/null +++ b/assets/Design_InstantGameGuide.md.5__8NzkS.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as e,a4 as n}from"./chunks/framework.Br2U662V.js";const p=JSON.parse('{"title":"使用 AutoStreaming 进行资源按需加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/InstantGameGuide.md","filePath":"Design/InstantGameGuide.md"}'),i={name:"Design/InstantGameGuide.md"},r=n("",11),o=[r];function s(l,m,h,c,d,u){return e(),t("div",null,o)}const g=a(i,[["render",s]]);export{p as __pageData,g as default}; diff --git a/assets/Design_IssueAndContact.md.nMr6t1S1.js b/assets/Design_IssueAndContact.md.nMr6t1S1.js new file mode 100644 index 00000000..e3b557f5 --- /dev/null +++ b/assets/Design_IssueAndContact.md.nMr6t1S1.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,a4 as s}from"./chunks/framework.Br2U662V.js";const i="/minigame-unity-webgl-transform/assets/issueandcontact1.BeCR63tr.png",r="/minigame-unity-webgl-transform/assets/issueandcontact2.CMeXfzus.png",f=JSON.parse('{"title":"问题反馈与联系我们","description":"","frontmatter":{},"headers":[],"relativePath":"Design/IssueAndContact.md","filePath":"Design/IssueAndContact.md"}'),n={name:"Design/IssueAndContact.md"},o=s('

问题反馈与联系我们

开发者使用转换方案时,如果遇到问题可以随时反馈给我们。目前可通过Git Issue和“小游戏客服助手”微信客服两种方式。

Git Issue

开发者遇到BUG或者希望新增特性优先使用Git Issue,因为这里可以更好进行问题沉淀、讨论与跟踪。

问题复现尽可能详细,包括以下内容:

小游戏客服助手

开发者也可以通过客服助手直接与小游戏团队进行技术交流

',10),c=[o];function l(m,u,_,h,d,p){return a(),t("div",null,c)}const b=e(n,[["render",l]]);export{f as __pageData,b as default}; diff --git a/assets/Design_IssueAndContact.md.nMr6t1S1.lean.js b/assets/Design_IssueAndContact.md.nMr6t1S1.lean.js new file mode 100644 index 00000000..184e6a11 --- /dev/null +++ b/assets/Design_IssueAndContact.md.nMr6t1S1.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,a4 as s}from"./chunks/framework.Br2U662V.js";const i="/minigame-unity-webgl-transform/assets/issueandcontact1.BeCR63tr.png",r="/minigame-unity-webgl-transform/assets/issueandcontact2.CMeXfzus.png",f=JSON.parse('{"title":"问题反馈与联系我们","description":"","frontmatter":{},"headers":[],"relativePath":"Design/IssueAndContact.md","filePath":"Design/IssueAndContact.md"}'),n={name:"Design/IssueAndContact.md"},o=s("",10),c=[o];function l(m,u,_,h,d,p){return a(),t("div",null,c)}const b=e(n,[["render",l]]);export{f as __pageData,b as default}; diff --git a/assets/Design_IssueForProduction.md.DIdpWfBl.js b/assets/Design_IssueForProduction.md.DIdpWfBl.js new file mode 100644 index 00000000..f853e31c --- /dev/null +++ b/assets/Design_IssueForProduction.md.DIdpWfBl.js @@ -0,0 +1 @@ +import{_ as r,c as i,a as t,a4 as e,o as a}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/issueforproduction1.bg6Fx4u1.png",s="/minigame-unity-webgl-transform/assets/issueforproduction2.DBTokemQ.png",n="/minigame-unity-webgl-transform/assets/issueforproduction3.CSZPVLs2.png",l="/minigame-unity-webgl-transform/assets/issueforproduction4.BR2EWzID.png",x=JSON.parse('{"title":"现网错误日志上报与排查","description":"","frontmatter":{},"headers":[],"relativePath":"Design/IssueForProduction.md","filePath":"Design/IssueForProduction.md"}'),p={name:"Design/IssueForProduction.md"},c=e('

现网错误日志上报与排查

当游戏发布到现网时,开发者需要收集玩家遇到的错误、异常等问题并进行排查原因,本文阐述在微信小游戏环境的最佳实践。 开发者可通过三种途径收集到游戏异常数据:

用户反馈日志

数据入口:MP平台-用户反馈

当玩家游戏中出现问题时,进行功能反馈将会提交“用户反馈日志“,开发者可以在后台下载到对应数据:

该功能需要两个必要条件:

  1. 玩家提交反馈

  2. 开发者埋点打印日志

小游戏实时日志

数据入口:MP平台-开发管理-实时日志

实时日志为帮助小程序开发者快捷地排查小程序漏洞、定位问题.

',12),_=e('

但需要开发者上报游戏关键节点信息与异常日志。

JS Error错误日志

数据入口:MP平台-开发管理-错误日志

微信小游戏框架会在顶层监控到任何未捕捉的JS异常

使用Unity WebGL转换方案的游戏通常会有这几种错误会产生:

',6);function u(d,m,h,g,f,b){return a(),i("div",null,[c,t(" 相对于用户反馈日志,小游戏实时日志**不需要用户反馈行为**。 "),_])}const S=r(p,[["render",u]]);export{x as __pageData,S as default}; diff --git a/assets/Design_IssueForProduction.md.DIdpWfBl.lean.js b/assets/Design_IssueForProduction.md.DIdpWfBl.lean.js new file mode 100644 index 00000000..c8be8122 --- /dev/null +++ b/assets/Design_IssueForProduction.md.DIdpWfBl.lean.js @@ -0,0 +1 @@ +import{_ as r,c as i,a as t,a4 as e,o as a}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/issueforproduction1.bg6Fx4u1.png",s="/minigame-unity-webgl-transform/assets/issueforproduction2.DBTokemQ.png",n="/minigame-unity-webgl-transform/assets/issueforproduction3.CSZPVLs2.png",l="/minigame-unity-webgl-transform/assets/issueforproduction4.BR2EWzID.png",x=JSON.parse('{"title":"现网错误日志上报与排查","description":"","frontmatter":{},"headers":[],"relativePath":"Design/IssueForProduction.md","filePath":"Design/IssueForProduction.md"}'),p={name:"Design/IssueForProduction.md"},c=e("",12),_=e("",6);function u(d,m,h,g,f,b){return a(),i("div",null,[c,t(" 相对于用户反馈日志,小游戏实时日志**不需要用户反馈行为**。 "),_])}const S=r(p,[["render",u]]);export{x as __pageData,S as default}; diff --git a/assets/Design_LaunchOpera.md.VmxdpFyu.js b/assets/Design_LaunchOpera.md.VmxdpFyu.js new file mode 100644 index 00000000..d8bc893f --- /dev/null +++ b/assets/Design_LaunchOpera.md.VmxdpFyu.js @@ -0,0 +1,101 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/demo-video.bmM6aW-q.mp4",h="/minigame-unity-webgl-transform/assets/app-mmdys.D2V6c5GV.jpeg",t="/minigame-unity-webgl-transform/assets/app-fxzg.CwsGWMYA.jpeg",e="/minigame-unity-webgl-transform/assets/app-jhywl.4N6roqlx.jpeg",p="/minigame-unity-webgl-transform/assets/image-0.j3jmWdo-.png",k="/minigame-unity-webgl-transform/assets/image-1.BvWojOYk.png",m=JSON.parse('{"title":"启动剧情(Beta)","description":"","frontmatter":{},"headers":[],"relativePath":"Design/LaunchOpera.md","filePath":"Design/LaunchOpera.md"}'),r={name:"Design/LaunchOpera.md"},o=n('

启动剧情(Beta)

Unity微信小游戏首次启动会花费较长的加载时间,这段等待期间游戏与玩家之间没有更多的交互,这是新用户的留存率影响的重要因素,微信小游戏希望能够提供一些更早的交互行为来提升这段等待空窗期的用户访问体验,为游戏的主逻辑争取更多的下载、加载时间。由此推出「启动剧情」能力,对于希望进一步提升游戏启动留存的开发者可以基于该能力精心设计用于“迎新”的剧情内容,进而提升玩家的代入感与游戏的顺畅体验。

剧情效果

演示视频及演示工程源码

演示工程源码

优秀作品

首次访问将直接进入剧情模式(不会显示Unity游戏通用Loading界面),二次访问通常删除本地微信小游戏包再次访问游戏可体验剧情内容(部分游戏使用异步模式,若已经注册游戏角色可能会改变剧情内容,需使用新微信账号访问体验)。

魔魔打勇士飞翔之光镜花异闻录

欢迎更多游戏接入成为优秀案例。

能力特性

推荐内容

接入方式

由于启动剧情为Unity启动加载耗时过久而推出的能力,因此主要配置由 JavaScript 脚本实现(早于WASM初始化)。

步骤一:设计剧情

剧本设计请阅读 启动剧情剧本自助设计工具及文档 完成设计与调试;

由工具构建(npm run build)生成剧本产物:资源目录 launchOperaPlay

步骤二:配置启动剧情

  1. 使用代码编辑工具打开Unity工程中 Assets/WX-WASM-SDK-V2/Runtime/wechat-default 目录;
  2. 步骤一launchOperaPlay 资源放到 wechat-default 目录中;
  3. 打开 wechat-default/game.js 文件,该文件是 JavaScript 运行的入口文件,在文件底部增加启动剧情初始化配置。
js
// game.js
+
+...   // 原有的代码
+
+// 底部增加启动剧情配置
+// launchOperaInit 是用于初始化剧情的回调事件
+// 配置工作需要在该回调中使用「同步」方式完成,请勿使用异步函数
+GameGlobal.events.on("launchOperaInit", (operaHandler) => {
+
+  // 如需读取本地缓存请使用 getStorageSync 读取,请勿使用异步方式
+  // 如需异步请查阅「基于异步干预剧情发展」
+  let play = true;
+  try {
+    var value = wx.getStorageSync('launchOperaLocalDataXXX'); // 自行管理的本地缓存 Key-Value
+    if (value) {    // 本地有特定缓存标识意味已经不是首次访问可以不播放
+      play = false;
+    }
+  } catch (e) { }
+
+  // 合理位置标记为非新用户,也可以在 C# 侧完成标记
+  wx.setStorageSync('launchOperaLocalDataXXX', { anydata: 0 });
+
+  // 开始配置启动剧情
+  operaHandler.config = { // 配置本地剧本路径,若 playPath 文件不存在或读取失败则自动放弃启动剧情
+    playPath: play ? '/launchOperaPlay/operaPlay.obj' : null,
+  }
+
+  // 注册一些其他的启动剧情事件回调
+  operaHandler.onEnd((logger) => {
+    console.log('剧情播放结束');
+  })
+
+  operaHandler.onErr((err) => {
+    console.log('发生异常');
+    operaHandler.end();       // 发生异常时强制结束,避免用户无法退出剧情插件模式
+  })
+
+  // 弱网处理
+  operaHandler.onWeakNetwork((info) => {
+    // code...
+  })
+
+});
  1. 导出面板进行导出微信小游戏即可。

基于异步干预剧情发展

初始化期间可以同步读取本地资源简单判断是否需要播放剧情,但对于有网络存档的游戏而言,显然不是可靠的判断新用户的方案(用户新设备或本地缓存丢失时也将判定为新用户),这将涉及到异步方式来干预启动剧情插件的工作。异步由于存在不确定的结果返回时间,游戏的启动自然不能始终等待这段空隙,因此在异步结果返回前,我们应让启动剧情插件正常启动,并在后续合理的时机完成故事线的切换。下图给出一种推荐的做法:

我们可以看到,默认的剧情将固定播放一段大约3~5秒钟的启动动画(可以是游戏厂家Logo、防沉迷提醒等),在3~5秒期间 JavaScript 脚本尝试用一些途径来确定后续的剧情发展(可以通过网络交互、本地读取等),当确认后,启动剧情插件允许配置相关变量进而干预剧情发展。 值得注意的是,异步的获取时间明显是不可控的,因此是有可能在5秒的启动动画结束后,仍未得到期望的结果,因此推荐的设计是默认情况下仅播放5秒的启动动画,后续剧情不播放,当5秒内明确了后续播与不播放的选择时,按结果配置,若仍未得到结果,可以按照老用户立即结束剧情即可。具体如何抉择,开发者可以自行设计。

异步干预剧情需要使用到 全局变量 能力,Beta期间请联系研发助手设计剧情期间咨询异步干预能力。

自定义上报分析

启动剧情是一个持续较长时间的业务内容,这段时间中任何时刻均会有用户离开,因此上报剧情期间用户不同阶段的行为对于分析剧情内容与留存率是非常重要的。启动剧情的“剧本”由开发者定义,因此开发者更清楚一个剧情的不同阶段的时间点,所以需要开发者自行对不同阶段剧情进行上报打点。开发者配置上报后,MP管理后台提供了漏斗图的数据可视化看板,将方便开发者进行数据分析。 有关自定义上报详细内容请参考 启动场景上报分析

外显进度条接入

启动剧情能力工作期间,仍然提供了加载进度外显能力,这有助于在剧情播放期间通过截图方式反馈一些加载进度信息,默认情况下位于小游戏底部区域,如图所示:

启动剧情外显进度条默认为用户开启,并且进度条前70%固定为Unity小游戏封面启动进度,开发者可以自行补充后30%进度的显示,若开发者未定义后30%显示进度则启动剧情插件将在首资源包与WASM初始化完成后以平滑动画完成100%进度显示。

关闭/样式调整

如需关闭/样式调整外显进度条,如下配置:

js
GameGlobal.event.on("launchOperaInit", (operaHandler) => {
+
+  // other codes...
+
+  // 配置外显进度条
+  operaHandler.config = {
+    progressStyle: {   // 外显进度条配置,所有配置项均可缺省,以下为默认值
+      position: 1,                  // 0 顶部 1 底部
+      hidden: false,                // 是否隐藏
+      color: '#FFFFFF',             // 进度条颜色
+      backgroundColor: '#000000',   // 进度条背景颜色
+      height: 3,                    // 进度条高度
+    },
+    useCustomProgress: true,       // 声明控制后30%显示,默认不控制将以动画自动补间
+  }
+
+});

如开启 useCustomProgress 则可在游戏侧完成控制

c#
launchOpera.percentage = 0.6;     // 开发者输入 .0~1.0 浮点数,对应控制剩余 30%

弱网处理

启动剧情通常以视频内容呈现为主,网络流畅度对用户体验是存在直接关系,除了开发者需要确保使用可靠的CDN服务托管视频资源确保足够的输出带宽,用户的实际网络也是影响的重要因素。微信小游戏启动剧情对可能影响用户体验的弱网情况做了相应的回调事件,也对网络情况做了三个级别的分级,请开发者对弱网的反馈同样做出合理的处理提升用户体验。

弱网级别:

请参阅 .onWeakNetwork API描述。

API执行环境说明

启动剧情的运行环境主要以 JavaScript 为主,当然我们也提供了部分 C# 侧需要用到的访问接口。JavaScript 侧指的是导出目录中 minigame 文件夹中的脚本,这是微信开发者工具打开的脚本目录,minigame/game.js 是整个游戏客户端启动的入口,我们通常也是从该入口进行能力迭代。不过值得注意的是,minigame 目录是导出产物,在重新导出游戏时将会被覆盖,所以正确的修改目录应该位于 Assets/WX-WASM-SDK-V2/Runtime/wechat-default 目录中,这里是导出 minigame 的模板文件,并且能够跟随项目Git等代码版本托管迭代。

C# 侧指的是游戏在 Unity 环境中的函数调用,区别于 JavaScript 他的时机将更晚,因为 C# 侧需要等待 WASM 准备充分(首场景加载完成)后才能够进行一系列的函数调用,因此配置性的操作是不能此完成(请在 JavaScript 完成),当剧情启动并给到充分的 WASM 启动后,C# 将得到一些信息反馈,如:何时结束剧情、外显进度条的进度设置等。

API(JavaScript侧)

在 JavaScript 中除了 launchOperaInit 回调函数参数中可获得句柄外, 全局变量 GameGlobal.launchOpera 可以让开发者在任意位置访问到控制句柄;

.running

只读属性,获得当前剧情插件运行状态,true 代表正在播放剧情,false 为未运行或已播放结束资源已完成析构。

js
console.log(GameGlobal.launchOpera.running);    // true or false

.config

在初始化期间对启动剧情组件进行相关配置。

js
GameGlobal.launchOpera.config = {
+  playPath: '',   // 可选,剧本文件路径,填写该项则意味开启启动剧情
+  progressStyle: {   // 外显进度条配置,所有配置项均可缺省,以下为默认值
+    position: 1,                  // 0 顶部 1 底部
+    hidden: false,                // 是否隐藏
+    color: '#FFFFFF',             // 进度条颜色
+    backgroundColor: '#000000',   // 进度条背景颜色
+    height: 3,                    // 进度条高度
+  },
+  useCustomProgress: false,       // 是否接入自定义外显进度条
+}

.end()

提前结束启动剧情。

.onEnd(callback: Function)

注册当剧情结束时的回调事件。

当产生该回调时意味着启动剧情组件资源已经完全析构,同时自动释放注册的事件(如 .onErr 、.onEnd),无需开发手动释放。

.offEnd(callback: Function)

注销当剧情结束时配置的回调事件。

.onErr(callback: Function)

注册当发生异常时的回调事件。

引发异常的可能是:剧本文件读取失败、剧本与启动剧情插件版本不兼容、插件环境异常、CDN视频资源播放失败等。

为避免发生异常时用户无法退出启动剧情插件,推荐开发者在 onErr 强制结束启动剧情。

js
launchOpera.onErr((err) => {
+  launchOpera.end();    // 强制结束
+});

.offErr(callback: Function)

注销当发生异常时的回调事件。

.onWeakNetwork(callback: Function)

当发生1-2级弱网情况时发生的回调事件。

一种推荐的配置:

js
launchOpera.onWeakNetwork((info) => {
+  /**
+   * info 结构:
+   *  interface info {
+   *    level: number;  // 弱网级别
+   *    url: string;  // 产生本次回调的远程资源url
+   *  }
+  */
+  if (info.level == 1) {
+    wx.showToast({
+      title: '网络较弱正在缓冲...',
+      icon: 'none',
+    });
+    // 使用 GlobalVar 显示跳过/退出按钮
+    // code...
+  } else { // 不是 level 1 则为 level 2
+    wx.showToast({
+      title: '网络较差,已为您跳过剧情',
+      icon: 'none',
+    });
+    launchOpera.end();    // 强制结束
+  }
+});

.offWeakNetwork(callback: Function)

注销当发生弱网情况时的回调事件。

.setGlobalVar(globalName: string, value: string)

设置启动剧情全局变量值。

.getGlobalVar(globalName: string): string | null

读取启动剧情全局变量值。

.onGlobalVarChange(globalName: string, callback: Function)

当启动剧情全局变量变化时回调。

.offGlobalVarChange(globalName: string, callback: Function)

注销启动剧情全局变量变化时回调。

API(C#侧)

获得交互句柄

c#
var launchOperaHandler = WX.GetLaunchOperaHandler();

void SetPercentage(double value)

当开启自定义外显进度条时(useCustomProgress)可控制进度条进度,value 接受 .0 ~ 1.0 区间浮点数,对应外显进度条的 70% ~ 100% 进度。

bool GetRunning()

获得当前剧情插件运行状态,true 代表正在播放剧情,false 为未运行或已播放结束资源析构。

void End()

提前结束启动剧情。

void onEnd(Action<bool> callback)

注册当剧情结束时的回调事件。

由于 C# 代码启动较晚,如果在开发者注册时剧情已经结束,则在注册该方法时会立即产生回调,注册的回调只会产生1次。

c#
// On LaunchOpera End
+WX.GetLaunchOperaHandler().onEnd((status) =>
+{
+    WX.ShowToast(new ShowToastOption()
+    {
+        title = "C#(WASM) received the ending callback event!",
+        icon = "none",
+    });
+});

void offEnd(Action<bool> callback)

注销当剧情结束时配置的回调事件。

void SetGlobalVar(string key, string value)

设置启动剧情全局变量值。

string GetGlobalVar(string key)

读取启动剧情全局变量值。

`,102),E=[o];function d(c,g,y,u,b,F){return i(),a("div",null,E)}const f=s(r,[["render",d]]);export{m as __pageData,f as default}; diff --git a/assets/Design_LaunchOpera.md.VmxdpFyu.lean.js b/assets/Design_LaunchOpera.md.VmxdpFyu.lean.js new file mode 100644 index 00000000..ef68e09b --- /dev/null +++ b/assets/Design_LaunchOpera.md.VmxdpFyu.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/demo-video.bmM6aW-q.mp4",h="/minigame-unity-webgl-transform/assets/app-mmdys.D2V6c5GV.jpeg",t="/minigame-unity-webgl-transform/assets/app-fxzg.CwsGWMYA.jpeg",e="/minigame-unity-webgl-transform/assets/app-jhywl.4N6roqlx.jpeg",p="/minigame-unity-webgl-transform/assets/image-0.j3jmWdo-.png",k="/minigame-unity-webgl-transform/assets/image-1.BvWojOYk.png",m=JSON.parse('{"title":"启动剧情(Beta)","description":"","frontmatter":{},"headers":[],"relativePath":"Design/LaunchOpera.md","filePath":"Design/LaunchOpera.md"}'),r={name:"Design/LaunchOpera.md"},o=n("",102),E=[o];function d(c,g,y,u,b,F){return i(),a("div",null,E)}const f=s(r,[["render",d]]);export{m as __pageData,f as default}; diff --git a/assets/Design_LaunchOperaDocument.md.C4QbbkY9.js b/assets/Design_LaunchOperaDocument.md.C4QbbkY9.js new file mode 100644 index 00000000..acf6f3bb --- /dev/null +++ b/assets/Design_LaunchOperaDocument.md.C4QbbkY9.js @@ -0,0 +1,268 @@ +import{_ as s,c as a,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const y=JSON.parse('{"title":"启动剧情剧本自助设计工具及文档","description":"","frontmatter":{},"headers":[],"relativePath":"Design/LaunchOperaDocument.md","filePath":"Design/LaunchOperaDocument.md"}'),n={name:"Design/LaunchOperaDocument.md"},e=t(`

启动剧情剧本自助设计工具及文档

1.文档说明

启动剧情能力上线初期微信小游戏团队希望更多开发者能够一定程度上自助接入该能力设计剧本,来减少人工协助带来的额外时间消耗,为此提供本指南及工具,游戏开发者通常可通过阅读指南与使用本工具自行完成剧本的设计并上线能力。

2.准备工作

3.快速入门

如果你还没接触 Cli 开发模式,请跟随本教程直至你能在 微信开发者工具 中随意的预览你创作的剧情设计。

Step1 安装启动剧情Cli工具

确保正确安装Node.js与npm包管理器时,只需在你的PC命令行中输入:

sh
npm install launch-opera-cli -g

有时可能需要以管理员身份运行该命令。

Step2 创建剧情工程

在合适的目录下创建你的剧情编辑工程,PC命令行中输入:

sh
lacop create

按照提示创建,如名为 lac-opera-test 的剧情工程,等待片刻创建成功后请进入该目录。

Step3 启动开发模式

创建成功后进入 lac-opera-test (本案例名)目录中执行:

sh
lacop watch

等待片刻提示 Starting compilation in watch mode... 代表启动成功,此时将自动生成 /minigame 文件夹。 注意在调试期间请勿关闭该命令行,应使其始终保持活跃,直到结束剧本设计

Step4 预览默认剧情

使用 微信开发者工具 打开 /minigame 目录,AppID 请切换成当前登录用户有开发权限的小游戏AppID,如果AppID是首次打开后会要求添加用于调试的小游戏插件,按照提示申请权限,若一切正常,你将在工具完全载入资源后看到默认的启动剧情内容。

Step5 对剧本修改

可能与平时开发小程序/小游戏直接在 微信开发者工具 修改剧本不同的是,你无需修改 /minigame 目录中的任何资源,因为这是一个动态构建的产物,他会随着 /src 目录中的资源变化被不断覆盖。所以你真正需要修改的是 /src 中的代码资源。

接下来请你使用 JavaScript 代码编辑器打开当前工程目录(如 VSCode 打开),找到 /src/launchOperaPlay/index.ts 脚本。

请修改脚本中大约第 51 行的 skipButton 的 setParams 参数为:

js
skipButton.setParams({
+  // right: 30,   // 修改前
+  left: 30,   // 修改后
+  bottom: 60,
+  width: 173 / 1.5,
+  height: 64 / 1.5,
+  url: 'launchOperaPlay/skip.png',
+  visible: true,
+});

此时保存这个文件,如果你的 Step3 中启动的开发模式还在工作,那么 /minigame 目录资源也将被实时更新,此时 微信开发者工具 通常也将重新加载游戏内容,你会看到被你刚刚修改的按钮贴图位置从右下角变成左下角。

以此类推,你可以快速修改你看到的很多属性内容,比如位置信息、URL地址从而改变剧情的内容。

Step6 导出剧本

当你对剧情设计完成,需要导出剧本给正式的游戏工程使用时,请回到 Step3 中你开启的命令行窗口,Windows系统下使用 Ctrl + C MacOS 系统下使用 control + C 结束开发模式。

再次执行:

sh
lacop build

等待程序执行结束后,你将在根目录看到 /release 目录,此时你可以将 release 目录内资源放到你的正式游戏工程导出的 minigame 目录下使用。

有关图片资源路径问题请阅读 常见Q&A 中说明。

至此你已经完成了一次很小变动的剧本导出工作。

Step7 尝试更多的模板

启动剧情能够设计很复杂的交互剧情内容,但是这对于初次使用的开发者还需要阅读本文更多的内容,后续请查阅 进阶指南。如果你想快速应用场景,类似 Step5 中这样仅修改属性值就可以替换成自己的游戏素材还是十分便捷。我们提供了多种模板可供选择,只需要在命令行中输入 lacop template 可以快速切换提供的多种模板效果拿来使用。

实际上你可以直接执行 lacop 而无需带后面的参数进行能力的自主选择

4.进阶指南

如果模板还不能满足你的需要,请仔细阅读本节,你将学会设计复杂的剧情内容。

4.1 了解构建工具

本构建工具已经为开发者配置好了相关类型声明,如果你使用例如 VScode 等具备 JavaScript/TypeScript 解析的 IDE 工具将可以享受到函数名联想及参数注释能力。

在使用前请了解本工具的一些行为约束:

4.2 基本概念

在启动剧情中由两个剧本元素组成,分别是 关键动作帧(Frame)故事线(StoryLine),关键动作帧更像是一个“函数”,核心思想在于执行到该帧时会引发某种动作,而故事线则是将多个独立的关键动作帧串联有序执行。

4.2.1 关键动作帧

有关关键动作帧的种类,请查阅 API速查 。每个关键动作帧均有两个必要的组成部分:属性、事件。

4.2.1.1 属性

属性是从关键动作帧激活的那一刻起被赋予其特定的值,属性决定了该帧的真实视图表现。例如:

js
// 创建了一个 Image,并赋予了他一些初始化的属性
+const skipButton = operaData.createFrame(FrameType.createImage, {
+  url: \`launchOpera/skip_button.png\`,
+  right: 25,
+  bottom: 25,
+  width: 100,
+  height: 100,
+});
+
+// 也可以创建后再修改其属性,与上面的写法实际效果完全一样
+const skipButton = operaData.createFrame(FrameType.createImage);
+
+skipButton.setParams({
+  url: \`launchOpera/skip_button.png\`,
+  right: 25,
+  bottom: 25,
+  width: 100,
+  height: 100,
+});
+
+// 注意设置属性是一个最终态的表现,也就意味着如下设置只有最后一个是生效的
+skipButton.setParams({
+  height: 100,  // 会因下面设置会覆盖,因此该设置无效
+});
+skipButton.setParams({
+  height: 101,  // 会因下面设置会覆盖,因此该设置无效
+});
+skipButton.setParams({
+  height: 102, // 因最后赋值则有效,skipButton 的 height 初始值则为 102
+});
4.2.1.2 事件

事件是对于不同关键动作帧存在不同的事件从而可以引发新的故事线的能力。比如 图片 可以存在被点击(onClick)的事件,视频组件存在开始播放(onPlay)、播放到第n秒时(onPlayTimeAt)、播放结束时(onEnded)等事件,当发生某种事件自然也就可以触发新的故事线内容。

其中,播放到第n秒时(onPlayTimeAt),n 是一个可变系数,因此事件也是支持配置参数的。

例子:

js
const video1 = operaData.createFrame(FrameType.createVideo, { ... });
+// 设置多个不同的事件
+// ①
+video1.setEvents({
+  event: 'onPlayTimeAt',
+  params: {
+    sec: 9,
+  },
+  bind: nextStoryLine,
+});
+// ②
+video1.setEvents({
+  event: 'onPlayTimeAt',
+  params: {
+    sec: 2,
+  },
+  keep: true,
+  bind: [ skipButton ],
+});
+// ③
+skipButton.setEvents({
+  event: 'onClick',
+  bind: [ operaData.EndFrame ]
+});

上面的例子展示了实际应用的多种可能,首先是不同于 属性 的后设置的值将覆盖前设置特点,同名事件是支持创建多个并同时生效(对照① ②中均是 pnPlayTimeAt 事件,但都是独立生效)。② 中使用了一个 keep 字段告诉剧情引擎该事件是反复有效,意味着实际运行时多次达到该事件条件都会引发该事件,而 ① ③ 没有设置 keep 发生一次事件后再达成条件也不会再次引发该事件。

再次观察 ① ② 的 bind,可以发现发生事件后执行的新的故事线其实可以存在多种表达方式,① 中是上下文中开发者自行创建的名为 nextStoryLine 故事线,有关故事线创建请阅读 故事线 小节,而 ② 中是放了一个由 关键动作帧 组成的数组,这其实是一种匿名故事线。

最后 ③ 中的 operaData.EndFrame 实际上最特殊的关键动作帧,当执行到该帧后,启动剧情将立即结束。

4.2.2 故事线

故事线是将一个或多个关键动作帧有序打包的容器,比较特殊的是,启动剧情需要存在一个主故事线作为启动入口。

4.2.2.1 创建及添加关键动作帧

创建故事线以及添加关键动作帧很简单,使用 operaData 句柄执行:

js
// 创建
+const storyLine = operaData.createStoryLine();
+
+// 创建一系列的动作帧...
+
+// 如需添加动作帧
+storyLine.add(var_GC_GUIDE_STEP, startImg, video1, ... );
4.2.2.2 主故事线

主故事线是启动剧情启动后最先执行的内容,当你第一次创建故事线时,那条线也就是主故事线了。

主故事线有一些很常见的用途,比如挂载一些全局变量放到主故事线上就很合理,这样你可以在任何时候对全局变量进行使用,对于全局变量的详细介绍请阅读 全局变量 小节。

5.API速查

了解基本概念后,你也就知道驱动整个剧情发展无非3点。

故事线的理解比较简单,重点是了解微信小游戏为开发者们提供了哪些关键动作帧,你可以略读 FrameType速查表 大概知道有哪些能力,并可以具体查看每一个 FrameType 的使用说明,来完成剧情的自主设计。

FrameType速查表

点击名称可快速查阅说明

FrameType释义
createVideo创建视频组件
pauseVide将某个视频组件进行暂停
playVideo将某个视频组件进行继续播放
createAudio创建音频组件
pauseAudio将某个音频组件进行暂停
playAudio将某个音频组件进行继续播放
createImage创建贴图
createRect创建矩形区域(可透明、填充纯色、用于区域点击识别)
setParam设置某个关键动作帧的属性
setParamSizeAndPosition同时设置组件的Size、Position属性
setTimeout创建延迟执行
createAnimationFunction创建动画函数
var创建全局变量
if条件判断
report创建上报节点

类型约定

类型主要包括以下几种:

类型名说明
String字符串
Boolean布尔值
Number数值
None可缺省值
Percent百分比字符串,如 30%
Frame关键动作帧句柄,如 Frame.var 只接受 FrameType 为 var 的句柄

空间描述约定

在描述组件的空间位置时,提供了几种简单的描述几乎可以满足大部分的使用需要。

空间描述主要涉及:left、right、top、bottom、width、height 5个属性,这5个属性均支持缺省(None),实际上描述一个组件在屏幕中的位置有时不需要将5个属性完全设置,比如当你规定了 left=0、right=0 时,也就意味着 width=屏幕宽度(width=100%),同理当你 left=0、width=100%,自然right也就=0。

在处理相对位置的时候有时 Number 与 Percent 可能都不能满足你的需要,比如:left=50% 代表屏幕中间,但是你希望屏幕中间再靠左10像素,就无法直接使用 Percent 实现,因为不同用户的设备宽度是不相同的,此时用到 calc 表达式方式,比如刚刚的案例中你可以这样描述: left=calc(50%-10) 就可以了。

视频相关

FrameType.createVideo

创建视频组件。

属性
属性名类型介绍
topNumber/Percent顶端。可参阅空间描述约定
bottomNumber/Percent底端
leftNumber/Percent左端
rightNumber/Percent右端
visibleBoolean可视
widthNumber/Percent宽度
heightNumber/Percent高度
urlString/Frame.var视频资源CDN地址
autoPlayBoolean是否自动播放
playingBoolean是否播放中
objectFitString/Frame.var视频的缩放模式,可选值:fill(填充拉伸)、contain(包含,可能有黑边)、cover(覆盖,可能有部分内容溢出屏幕)
seekNumber/String/Frame.var视频跳转到特定秒数,如果 < 0 则不跳转
loopBoolean是否循环播放
事件
事件名参数介绍
onPlayTimeAtsec:Number当播放到第sec秒数时(sec单位:秒)
onEnded-视频播放结束时
onPlay-视频开始播放时
案例
js
const video = operaData.createFrame(FrameType.createVideo);
+
+video.setParams({
+  // 全屏视频
+  left: 0,
+  right: 0,
+  top: 0,
+  bottom: 0,
+  // 视频完整呈现,可能存在黑边
+  objectFit: 'contain',
+  // 视频CDN
+  url: 'http://abc.com/xx.mp4',
+  autoPlay: true,
+});
+
+// 播放 1.5s 时触发新的关键动作帧
+video.setEvent({
+  event: 'onPlayTimeAt',
+  param: {
+    sec: 1.5,
+  },
+  bind: [ xxxx ] // 新的关键动作帧/故事线
+});
+
+// 可以创建多个事件,互相独立
+video.setEvent({
+  event: 'onPlayTimeAt',
+  ...
+});
seek 的使用案例

seek 需要配合 Frame.SetParam 使用,意味其他事件触发 Frame.SetParam 后为 video 关键动作帧赋值 seek 则产生视频跳转,如需了解 SetParam 请移步特定章节阅读,此处给出 seek 案例:

js
const video = ... // 创建video
+
+// 创建一个 setParam ,对 video 的 seek 属性设置为 10
+// 意味着当触发 seek0 时,video 组件视频将从10秒的位置开始播放
+const seek0 = operaData.createFrame(FrameType.setParam, {
+  frame: video,
+  param: 'seek',
+  value: '10'
+});
+
+... // 在特定条件下触发 seek0

FrameType.pauseVideo

暂停视频。

属性
属性名类型介绍
videoFrame.createVideo需要暂停的视频的关键动作帧句柄
案例
js
const video = ... // 创建video
+
+const playVideo0 = operaData.createFrame(FrameType.playVideo, {
+  video: video,
+});
+
+... // 在特定条件下触发 playVideo0

FrameType.playVideo

(继续)播放视频。

属性
属性名类型介绍
videoFrame.createVideo需要(继续)播放的视频的关键动作帧句柄
案例

FrameType.pauseVideo 使用。

音频相关

FrameType.createAudio

创建音频组件。

属性
属性名类型介绍
urlString/Frame.var音频资源CDN地址
autoPlayBoolean是否自动播放
playingBoolean是否播放中
seekNumber/String/Frame.var视频跳转到特定秒数,如果 < 0 则不跳转
loopBoolean是否循环播放
volumeNumber音量,0~1之间的数值,默认为1
事件
事件名参数介绍
onPlayTimeAtsec:Number当播放到第sec秒数时(sec单位:秒)
onEnded-音频播放结束时
onPlay-音频开始播放时
案例
js
const audio = operaData.createFrame(FrameType.createAudio);
+
+audio.setParams({
+  // 视频CDN
+  url: 'http://abc.com/xx.mp3',
+  autoPlay: true,
+});
+
+// 播放 1.5s 时触发新的关键动作帧
+audio.setEvent({
+  event: 'onPlayTimeAt',
+  param: {
+    sec: 1.5,
+  },
+  bind: [ xxxx ] // 新的关键动作帧/故事线
+});
+
+// 可以创建多个事件,互相独立
+audio.setEvent({
+  event: 'onPlayTimeAt',
+  ...
+})

FrameType.pauseAudio

暂停音频。

属性
属性名类型介绍
audioFrame.createAudio需要暂停的音频的关键动作帧句柄
案例

FrameType.pauseVideo 使用。

FrameType.playAudio

(继续)播放音频。

属性
属性名类型介绍
audioFrame.createAudio需要(继续)播放的音频的关键动作帧句柄
案例

FrameType.pauseVideo 使用。

贴图相关

FrameType.createImage

创建贴图组件。

贴图只能加载小游戏包内图片资源,并且需要主动设置高宽(不会自动读取贴图资源尺寸)。

属性
属性名类型介绍
topNumber/Percent顶端。可参阅空间描述约定
bottomNumber/Percent底端
leftNumber/Percent左端
rightNumber/Percent右端
visibleBoolean可视
widthNumber/Percent宽度
heightNumber/Percent高度
opacityNumber透明度 0~1
urlString/Frame.var图片资源本地路径
scaleWidthNumber宽度放缩系数
scaleHeightNumber高度放缩系数
事件
事件名参数介绍
onClick-当贴图被点击
案例
js
const image = operaData.createFrame(FrameType.createImage);
+
+// 右下角跳过贴图
+image.setParams({
+  bottom: 10,
+  right: 10,
+  width: 100,
+  height: 30,
+  url: 'launchOperaPlay/skip.png',
+});
+
+// 点击事件
+image.setEvent({
+  event: 'onClick',
+  bind: [ ... ],
+  keep: true,   // 事件始终有效
+});

FrameType.createRect

创建透明、纯色矩形区域,通常用于透明点击区域、背景色。

属性
属性名类型介绍
topNumber/Percent顶端。可参阅空间描述约定
bottomNumber/Percent底端
leftNumber/Percent左端
rightNumber/Percent右端
visibleBoolean可视
widthNumber/Percent宽度
heightNumber/Percent高度
colorString十六进制颜色描述字符串(如:#FFFFFF00)
事件
事件名参数介绍
onClick-当贴图被点击
案例
js
const rect = operaData.createFrame(FrameType.createRect);
+
+// 一个全屏的透明区域,可以用于点击事件透明遮罩
+rect.setParams({
+  top: 0,
+  left: 0,
+  bottom: 0,
+  right: 0,
+  color: '#FFFFFF00'
+});
+
+// 点击事件
+rect.setEvent({
+  event: 'onClick',
+  bind: [ ... ],
+})

属性修改

FrameType.setParam

设置单个属性。

属性
属性名类型介绍
frameFrame需要修改的 frame 句柄
paramString属性名
valueString/Frame.var/Number/Boolean新的值
案例

参阅 seek的使用案例 案例

FrameType.setParamSizeAndPosition

同时设置 Size 或 Position 相关属性。相比较于 FrameType.setParam 每次只能设置1个属性,对于常见的位置属性可以使用 FrameType.setParamSizeAndPosition 一次性设置。

属性

类型中 None 代表可缺省,即不设置该属性。

属性名类型介绍
frameFrame需要修改的 frame 句柄
topNumber/Percent/None顶端
bottomNumber/Percent/None底端
leftNumber/Percent/None左端
rightNumber/Percent/None右端
visibleBoolean/None可视
widthNumber/Percent/None宽度
heightNumber/Percent/None高度
opacityNumber/None透明度 0~1
scaleWidthNumber/None宽度放缩系数
scaleHeightNumber/None高度放缩系数
案例
js
const image = ... // 创建image
+
+// 调整Image位置
+const setPositon = operaData.createFrame(FrameType.setParamSizeAndPosition, {
+  frame: image,
+  top: 0,
+  right: '10%',
+  opacity: 0.5
+});
+
+... // 在特定条件下触发 setPositon

延迟执行

FrameType.setTimeout

类似 JavaScript setTimeout 的延迟执行。

属性
属性名类型介绍
timeoutString/Number/Frame.var延迟时长,单位 ms
cancelBoolean取消状态,运行时赋值false可提前终止延迟执行
事件
事件名参数介绍
onEnded-当延迟结束后
onCancel-当主动取消时
案例
js
const delay1000 = operaData.createFrame(FrameType.setTimeout, {
+  timeout: 1000,  // 1000ms
+});
+
+delay1000.setEvent({
+  event: 'onEnded',
+  bind: [ ... ] // 1000ms 后执行的关键动作帧/故事线
+});

动画相关

FrameType.createAnimationFunction

创建动画函数,使得视图组件的某(几)个属性能够按照持续时间完成渐变。无需考虑卸载动画函数,当动画函数被作用的关键动作帧句柄不可视状态时,动画函数将自动结束。

动画在微信开发者工具(模拟器)中表现异常,以真机表现为准。

属性
属性名类型介绍
frameFrame动画被作用的关键动作帧句柄
durationString/Frame.var持续时长
easingString/Frame.var曲率函数,如 ease-out
topNumber/Percent/None顶端
bottomNumber/Percent/None底端
leftNumber/Percent/None左端
rightNumber/Percent/None右端
visibleBoolean/None可视
widthNumber/Percent/None宽度
heightNumber/Percent/None高度
opacityNumber/None透明度 0~1
scaleWidthNumber/None宽度放缩系数
scaleHeightNumber/None高度放缩系数
事件
事件名参数介绍
onEnded-当动画结束后
案例

使用动画实现贴图按钮“点击继续”的「呼吸态」是最常见的实用应用,本演示将提供呼吸态按钮的实现:

js
// 一个位于底部居中的 点击继续 按钮
+const button = operaData.createFrame(FrameType.createImage, {
+  bottom: 20,
+  left: '50%',
+  width: 100,
+  height: 25,
+  url: 'launchOperaPlay/click_go_on.png'
+});
+
+// 创建一个淡出的动画(透明度从 1->0.2)
+const goonButtonAnimationFadeOut = operaData.createFrame(
+  FrameType.createAnimationFunction,
+  {
+    opacity: 0.2,
+    duration: 1000,
+    easing: 'ease-out',
+    frame: button,
+  },
+);
+// 再创建一个淡入的动画(透明度从 0.2->1)
+const goonButtonAnimationFadeIn = operaData.createFrame(
+  FrameType.createAnimationFunction,
+  {
+    opacity: 1,
+    duration: 1000,
+    easing: 'ease-out',
+    frame: button,
+  },
+);
+
+// 需要两个 Animation 结束后互相调用,即 淡入->结束->淡出->结束->... 循环之
+goonButtonAnimationFadeOut.setEvent({
+  event: 'onEnded',
+  bind: goonButtonAnimationFadeIn,
+  keep: true,    // keep = true 很关键,因为该事件将被反复执行
+});
+goonButtonAnimationFadeIn.setEvent({
+  event: 'onEnded',
+  bind: goonButtonAnimationFadeOut,
+  keep: true,
+});
+
+// 挂载一个适合的故事线中触发后则实现「呼吸态」
+storyLineX.add(button, goonButtonAnimationFadeOut);

全局变量

全局变量是外界脚本(C#、JavaScript)与剧情内部“沟通”的桥梁,外界可以修改全局变量使得剧情内部完成基于条件判断实现的不同逻辑分支,外界也可以通过监听某个全局变量值来实时监控剧情内部通过属性修改产生的一些消息反馈。

有关外界对全局变量的赋值与监听请阅读API使用文档,本节仅介绍全局变量在剧情编辑时的创建及属性介绍。

FrameType.var

全局变量目前以字符串类型进行内容存储,为方便使用一般在剧情最早的时候进行创建并挂载到主故事线中。

属性
属性名类型介绍
valueString变量值
globalNameString/None全局变量名,设置后可供外界访问。缺省则为剧情内部全局变量,外界无法访问。
事件
事件名参数介绍
onChange-当变量被赋值时触发的事件,重复赋相同值也会发生事件
onChanged-当变量被赋值且值发生变化时触发的事件
案例
js
const var_Level0 = operaData.createFrame(FrameType.var, {
+  value: '1',
+  globalName: 'level0',   // 外界可根据此名称读取/监听该全局变量
+});
+
+storyLine.add(var_Level0); // 及时挂载到主故事线使其生效

条件判断

FrameType.if

可以对某(两)个全局变量进行判断的关键动作帧。

属性
属性名类型介绍
valueAString/Frame.var需要对比的变量值或全局变量句柄
valueBString/Frame.var需要对比的变量值或全局变量句柄
事件
事件名参数介绍
isTrue-当 valueA == valueB 时
isFalse-当 valueA != valueB 时
案例
js
// 创建变量
+const var_Level0 = operaData.createFrame(FrameType.var, {
+  value: '1',
+  globalName: 'level0',   // 外界可根据此名称读取/监听该全局变量
+});
+
+storyLine.add(var_Level0); // 及时挂载到主故事线使其生效
+
+const if_go_on = operaData.createFrame(FrameType.if, {
+  valueA: var_Level0,
+  valueB: '1',          // 判断 var_Level0 是否 == '1'
+}, [
+  {
+    event: 'isTrue',
+    bind: [ ... ],      // 成立时执行的故事线
+  },
+  {
+    event: 'isFalse',
+    bind: [ ... ],      // 不成立时执行的故事线
+  }
+]);

上报

上报模块有助于帮助开发者量化启动剧情不同阶段的用户曝光情况分析用户体验,因此建议游戏开发者合理接入该能力。

FrameType.Report

该上报本质使用的是 启动场景上报分析 能力,因此使用前应阅读该能力文档。

注意:启动上报每个sceneId在一次启动过程中最多只能上报1次,因此在接入故事线打点时请务必确保路径只会执行1次同sceneId的上报。

属性
属性名类型介绍
sceneIdString/Frame.var自定义上报场景ID
dimensionString/Frame.var/None自定义上报维度JSON字符串,请阅读上报说明填写
metricString/Frame.var/None自定义上报指标JSON字符串,请阅读上报说明填写
案例
js
// 创建好多个 report
+const report_1001 = operaData.createFrame(FrameType.report, {
+  sceneId: '1001',
+});
+const report_1002 = operaData.createFrame(FrameType.report, {
+  sceneId: '1002',
+});
+
+// 合理的位置进行上报
+video0.setEvent({
+  event: 'onEnded',
+  bind: [ report_1001 ],
+});
+
+...
+
+// 合理的位置进行上报
+video1.setEvent({
+  event: 'onEnded',
+  bind: [ report_1002 ],
+});

6.常见Q&A

6.1 图片资源可以使用网络图片吗?

目前图片资源只能存放于小游戏 minigame 目录中,不可使用网络图片。

6.2 为什么要放首帧图片(firstFramePic)

图片资源是跟随微信小游戏包上传至微信服务器,所以在小游戏主逻辑运行时,图片资源也处于就绪状态可以同步加载,因此玩家打开游戏时首帧将看到具体的游戏画面。而视频是存放在CDN的远程资源,不可避免的存在加载延迟问题,所以配置好首帧图片后,在视频可播放后再隐藏图片资源。

`,212),h=[e];function l(p,k,r,d,E,o){return i(),a("div",null,h)}const g=s(n,[["render",l]]);export{y as __pageData,g as default}; diff --git a/assets/Design_LaunchOperaDocument.md.C4QbbkY9.lean.js b/assets/Design_LaunchOperaDocument.md.C4QbbkY9.lean.js new file mode 100644 index 00000000..f920ae7d --- /dev/null +++ b/assets/Design_LaunchOperaDocument.md.C4QbbkY9.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const y=JSON.parse('{"title":"启动剧情剧本自助设计工具及文档","description":"","frontmatter":{},"headers":[],"relativePath":"Design/LaunchOperaDocument.md","filePath":"Design/LaunchOperaDocument.md"}'),n={name:"Design/LaunchOperaDocument.md"},e=t("",212),h=[e];function l(p,k,r,d,E,o){return i(),a("div",null,h)}const g=s(n,[["render",l]]);export{y as __pageData,g as default}; diff --git a/assets/Design_OpenData.md.LqgzEtQr.js b/assets/Design_OpenData.md.LqgzEtQr.js new file mode 100644 index 00000000..3fd12c39 --- /dev/null +++ b/assets/Design_OpenData.md.LqgzEtQr.js @@ -0,0 +1,87 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/opendataframework.2OxzAkk1.png",h="/minigame-unity-webgl-transform/assets/o2.BiHxPfHa.png",e="/minigame-unity-webgl-transform/assets/opendata.BgWhdjkg.png",l="/minigame-unity-webgl-transform/assets/demo1.BsKsD89o.jpeg",p="/minigame-unity-webgl-transform/assets/demo2.ByJUMFjf.jpeg",k="/minigame-unity-webgl-transform/assets/demo3.Bj8Y-kOy.jpeg",r="/minigame-unity-webgl-transform/assets/demo6.BEnu5duc.jpeg",E="/minigame-unity-webgl-transform/assets/demo7.BJ_h8aov.jpeg",d="/minigame-unity-webgl-transform/assets/demo4.D7PXjFbO.jpeg",g="/minigame-unity-webgl-transform/assets/demo5.jD5F1kVF.jpeg",B=JSON.parse('{"title":"Unity中如何展示排行榜这类微信关系数据","description":"","frontmatter":{},"headers":[],"relativePath":"Design/OpenData.md","filePath":"Design/OpenData.md"}'),o={name:"Design/OpenData.md"},y=n('

Unity中如何展示排行榜这类微信关系数据

背景和原理介绍

小游戏提供了一系列接口获取好友关系链数据,为了安全,绝大部分接口都只能在开放数据域内调用。

avatar

开放数据域虽然乍一看有点复杂,但只需要核心理解几个点即可:

  1. 开放数据域所有逻辑都在一个独立的文件夹内完成,它核心处理两件事:调用关系链接口拉好友数据和将数据绘制到 sharedCanvas;
  2. 开放数据域接触到的 sharedCanvas 是一个离屏的 canvas,它完全不理解自己最终是怎么被绘制到屏幕上的;
  3. 主域(其实就是开放数据域文件夹外的业务代码)同样能接触 sharedCanvas,一般是通过 sharedCanvas 创建精灵添加到游戏场景;
  4. 数据的通信一定是单向的,只能从主域流向开放数据域,主域无法感知到开放数据域发生了什么;
  5. 鉴于第4点,主域要更新 sharedCanvas 只能定期刷新纹理来实现同步开放数据域的变化;

Unity 里面要实现 sharedCanvas 的绘制,核心在于 hook Unity 的渲染,完整的原理为:

  1. Unity 侧有个占位的纹理;
  2. Unity WebGL 模式下这个占位纹理会对应有一个 WebGLObject,Unity 会调用 drawElements API 绘制到 canvas;
  3. 在需要绘制排行榜的时候,将原本要绘制的 WebGLObject 替换成通过 sharedCanvas 创建而来的 WebGLObject;
  4. 在关闭排行榜的时候,停止步骤 3 的 hook;

详细步骤

1、设置占位纹理

在游戏需要展示的地方创建一个 RawImage,其中 Texture 属性自己选择透明的图片即可,后续展示时会被动态替换。因为unity纹理与 Web 的绘制存在倒立的差异,请将先将 rotation的x 设置为180,即让 UI控件延X轴旋转180度 再调整到游戏中合适的位置,如下图

avatar

2、调用SDK的API

2.1 在需要展示的地方调用,WX.ShowOpenData

CSharp
WX.ShowOpenData(rawImage.texture, x, y, width, height);

其中 :

WX.ShowOpenData 最终会调用 minigame/unity-sdk/open-data.js 内的 WXShowOpenData 方法,核心是三个作用:

  1. 调用 wx.getOpenDataContext,这会触发开放数据域的初始化,也就是 open-data 文件夹下的代码在开放数据域初始化之后才能够执行;
  2. 给开放数据域侧抛一个事件,告知开放域去执行数据拉取和渲染操作,对于 WXRender 的处理没有任何要求,开放数据域甚至可以忽略这个事件;
js
openDataContext.postMessage({
+    type: "WXRender",
+    x: x,
+    y: y,
+    width: width,
+    height: height,
+    devicePixelRatio: window.devicePixelRatio,
+});
  1. 开始 hook Unity 的渲染,原本的 RawImage 就会被替换成 sharedCanvas 的纹理。

2.2 需要关闭时则调用,WX.HideOpenData

这一步非常重要,如果仅仅在 Unity 侧隐藏了 RawImage 而没有调用 WX.HideOpenData,很可能导致排行榜关闭之后文理错乱,比如有些地方的纹理变成了排行榜对应的纹理。

2.3 通过 PostMessage 向开放数据域传递消息

如果需要在 Unity 中向开放域页面传递数据,可以调用WX.GetOpenDataContext,如下代码:

CSharp
[System.Serializable]
+public class OpenDataMessage
+{
+    // type 用于表明时间类型
+    public string type;
+}
+
+OpenDataMessage msgData = new OpenDataMessage();
+msgData.type = "showFriendsRank";
+string msg = JsonUtility.ToJson(msgData);
+WX.GetOpenDataContext().PostMessage(msg);

开放域JS代码可以通过:

js
wx.onMessage(data => {
+  console.log("[WX OpenData] onMessage", data);
+
+  if (typeof data === "string") {
+    try {
+      data = JSON.parse(data);
+    } catch (e) {
+      console.error("[WX OpenData] onMessage data is not a object");
+      return;
+    }
+  }
+
+  if (data.type === 'showFriendsRank') {
+    // 执行好友排行榜渲染
+  }
+});

3、导出选项勾选使用好友关系链

这一步会做两个事情:

  1. game.json 会声明使用开放数据域;
  2. 将插件内置的 open-data 示例拷贝至 minigame 目录,请注意做好文件备份;

avatar

4、用JS开发排行榜这类微信关系逻辑

开放数据域的开发和普通小游戏并无区别,暂时只能通过 js 来开发,对技术选型并无要求,可以不依赖任何引擎调用 Canvas2D API 执行渲染,但如果需要事件点击、滚动列表等处理,就会显得很麻烦;也可以选择完整的 JS 游戏引擎比如 Cocos,但这会使得代码包明显增大进而影响启动速度。

因此插件内置的示例采用的是微信自研的轻量级渲染引擎,压缩后只有几十k,这需要你掌握一些简单的 Web 开发知识,包括 Flex布局CSS,参照示例修修改改很快能够上手。

5、示例DEMO

可以参考Demo/Ranking下面的Unity工程。插件导出的 open-data 已经是一个比较功能完备的工程,进行简单的魔改就能够满足需求。

5.1 好友排行榜

  1. 展示 RawImage 的时候调用 SDK API
CSharp
void ShowOpenData()
+{
+  RankMask.SetActive(true);
+  RankingBox.SetActive(true);
+  // 
+  // 注意这里传x,y,width,height是为了点击区域能正确点击,x,y 是距离屏幕左上角的距离,宽度传 (int)RankBody.rectTransform.rect.width是在canvas的UI Scale Mode为 Constant Pixel Size的情况下设置的。
+  /**
+    * 如果父元素占满整个窗口的话,pivot 设置为(0,0),rotation设置为180,则左上角就是离屏幕的距离
+    * 注意这里传x,y,width,height是为了点击区域能正确点击,因为开放数据域并不是使用 Unity 进行渲染而是可以选择任意第三方渲染引擎
+    * 所以开放数据域名要正确处理好事件处理,就需要明确告诉开放数据域,排行榜所在的纹理绘制在屏幕中的物理坐标系
+    * 比如 iPhone Xs Max 的物理尺寸是 414 * 896,如果排行榜被绘制在屏幕中央且物理尺寸为 200 * 200,那么这里的 x,y,width,height应当是 107,348,200,200
+    * x,y 是距离屏幕左上角的距离,宽度传 (int)RankBody.rectTransform.rect.width是在canvas的UI Scale Mode为 Constant Pixel Size的情况下设置的
+    * 如果是Scale With Screen Size,且设置为以宽度作为缩放,则要这要做一下换算,比如canavs宽度为960,rawImage设置为200 则需要根据 referenceResolution 做一些换算
+    * 不过不管是什么屏幕适配模式,这里的目的就是为了算出 RawImage 在屏幕中绝对的位置和尺寸
+    */
+
+  CanvasScaler scaler = gameObject.GetComponent<CanvasScaler>();
+  var referenceResolution = scaler.referenceResolution;
+  var p = RankBody.transform.position;
+
+  WX.ShowOpenData(RankBody.texture, (int)p.x, Screen.height - (int)p.y, (int)((Screen.width / referenceResolution.x) * RankBody.rectTransform.rect.width), (int)((Screen.width / referenceResolution.x) * RankBody.rectTransform.rect.height));
+}
  1. 发送事件给开放数据域,要求展示好友排行榜
Csharp
OpenDataMessage msgData = new OpenDataMessage();
+msgData.type = "showFriendsRank";
+
+string msg = JsonUtility.ToJson(msgData);
+WX.GetOpenDataContext().PostMessage(msg);
  1. 开放数据域监听相应事件,展示群排行,详见 open-data。

整体流程示意:

5.2 群好友排行榜

  1. 为了使用群排行榜,需要调用 WX.UpdateShareMenu 设置分享菜单
CSharp
/**
+  * 使用群排行功能需要特殊设置分享功能,详情可见链接
+  * https://developers.weixin.qq.com/minigame/dev/guide/open-ability/share/share.html
+  */
+WX.UpdateShareMenu(new UpdateShareMenuOption()
+{
+    withShareTicket = true,
+    isPrivateMessage = true,
+});
  1. 在分享时,带上相关query
CSharp
WX.ShareAppMessage(new ShareAppMessageOption()
+{
+    title = "最强战力排行榜!谁是第一?",
+    query = "minigame_action=show_group_list",
+    imageUrl = "https://mmgame.qpic.cn/image/5f9144af9f0e32d50fb878e5256d669fa1ae6fdec77550849bfee137be995d18/0",
+});
  1. 监听 WX.OnShow 回调,给开放数据域发消息要求展示群排行
CSharp
WX.OnShow((OnShowCallbackResult res) =>
+{
+    string shareTicket = res.shareTicket;
+    Dictionary<string, string> query = res.query;
+
+    if (!string.IsNullOrEmpty(shareTicket) && query != null && query["minigame_action"] == "show_group_list")
+    {
+        OpenDataMessage msgData = new OpenDataMessage();
+        msgData.type = "showGroupFriendsRank";
+        msgData.shareTicket = shareTicket;
+
+        string msg = JsonUtility.ToJson(msgData);
+
+        ShowOpenData();
+        WX.GetOpenDataContext().PostMessage(msg);
+    }
+});
  1. 开放数据域监听相应事件,展示群排行,详见 open-data。

整体流程示意:

常见问题QA

Q1. 为什么第一次调用 WX.ShowOpenData 之后画面先黑一下再展示排行榜?

A1. WX.ShowOpenData 在 openDataContext.postMessage WXRender 的事件之后立马就会开始 hook Unity 的渲染,如果开放数据域在监听到 WXRender 事件之后没有任何渲染行为,那么 sharedCanvas 纹理就还没有准备好,Unity 侧就可能出现黑一下的情况,解决办法是保证监听到 WXRender 事件之后有个同步的渲染行为,比如绘制个文案”好友数据加载中..."。

Q2. 为什么我关闭排行榜之后界面上有些问题错乱了?

A2. 基本上只可能是没调用 WX.HideOpenData,建议 WX.HideOpenData 打些日志来辅佐排查。

Q3. 为什么开放数据域滚动事件不生效?

A4. WX.ShowOpenData(rawImage.texture, x, y, width, height)的后面四个参数,核心目的是告诉开放数据域 sharedCanvas 最终被绘制在了屏幕的位置和尺寸,开放数据域才能够正确处理事件监听,遇到事件不生效的问题,首先排查传进来的参数是否符合预期,比如 x / y 不应该是负数。

',62),c=[y];function F(m,D,u,C,A,b){return a(),i("div",null,c)}const v=s(o,[["render",F]]);export{B as __pageData,v as default}; diff --git a/assets/Design_OpenData.md.LqgzEtQr.lean.js b/assets/Design_OpenData.md.LqgzEtQr.lean.js new file mode 100644 index 00000000..2b7657dd --- /dev/null +++ b/assets/Design_OpenData.md.LqgzEtQr.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/opendataframework.2OxzAkk1.png",h="/minigame-unity-webgl-transform/assets/o2.BiHxPfHa.png",e="/minigame-unity-webgl-transform/assets/opendata.BgWhdjkg.png",l="/minigame-unity-webgl-transform/assets/demo1.BsKsD89o.jpeg",p="/minigame-unity-webgl-transform/assets/demo2.ByJUMFjf.jpeg",k="/minigame-unity-webgl-transform/assets/demo3.Bj8Y-kOy.jpeg",r="/minigame-unity-webgl-transform/assets/demo6.BEnu5duc.jpeg",E="/minigame-unity-webgl-transform/assets/demo7.BJ_h8aov.jpeg",d="/minigame-unity-webgl-transform/assets/demo4.D7PXjFbO.jpeg",g="/minigame-unity-webgl-transform/assets/demo5.jD5F1kVF.jpeg",B=JSON.parse('{"title":"Unity中如何展示排行榜这类微信关系数据","description":"","frontmatter":{},"headers":[],"relativePath":"Design/OpenData.md","filePath":"Design/OpenData.md"}'),o={name:"Design/OpenData.md"},y=n("",62),c=[y];function F(m,D,u,C,A,b){return a(),i("div",null,c)}const v=s(o,[["render",F]]);export{B as __pageData,v as default}; diff --git a/assets/Design_OptimizationMemory.md.CqTeDkzA.js b/assets/Design_OptimizationMemory.md.CqTeDkzA.js new file mode 100644 index 00000000..4cf115c9 --- /dev/null +++ b/assets/Design_OptimizationMemory.md.CqTeDkzA.js @@ -0,0 +1 @@ +import{_ as e,c as a,a as l,a4 as i,o as t}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/optimizationMemory1.CpSWLJ8m.png",o="/minigame-unity-webgl-transform/assets/optimizationMemory10.D-SZ1dZe.png",n="/minigame-unity-webgl-transform/assets/optimizationMemory2.aE_-ogAD.png",s="/minigame-unity-webgl-transform/assets/optimizationMemory3.CEtq636B.png",p="/minigame-unity-webgl-transform/assets/optimizationMemory4.ymgsNGzl.png",m="/minigame-unity-webgl-transform/assets/optimizationMemory6.8iXuz3Gb.png",h="/minigame-unity-webgl-transform/assets/optimizationMemory11.BB2iD3xR.png",d="/minigame-unity-webgl-transform/assets/optimizationMemory12.C9Wsxuea.png",u="/minigame-unity-webgl-transform/assets/optimizationMemory5.CzK1696v.png",A=JSON.parse('{"title":"优化Unity WebGL的内存","description":"","frontmatter":{},"headers":[],"relativePath":"Design/OptimizationMemory.md","filePath":"Design/OptimizationMemory.md"}'),y={name:"Design/OptimizationMemory.md"},c=i('

优化Unity WebGL的内存

一、内存与OOM

Unity WebGL游戏通常比普通H5(JS)游戏占用更大的内存,在操作系统的控制策略下超出阈值时非常容易被OOM。

为了提高游戏在中低端机型的稳定性,内存优化极为重要。那么,多大的内存是合理的呢? 我们建议内存峰值控制在以下范围(性能评估标准):

  1. Android: 低档机 < 1.2G, 中高档机 < 1.5G
  2. iOS: 低档机 < 1G, 中高档机 < 1.4G

相对而言,Android机型的内存更为宽松。

iOS低档机为iPhone 6sp/7/8等RAM 2G机型为主,中高档机为iPhone 7P/8P/iPhoneX/iPhone11等RAM 3G或以上机型。

二、Unity WebGL适配小游戏的内存结构

Unity WebGL内存结构可先参考:

Unity博客:了解 Unity WebGL 中的内存 (Understanding Memory in Unity WebGL)

Unity博客:Unity WebGL 内存:Unity 堆 (Unity WebGL Memory: The Unity Heap)

',12),f=i('

适配在小游戏后,小游戏进程也就成为了“容器”,虽然不再是标准的浏览器,但内存组成结构与上图基本一致,典型游戏的内存占用如下图所示:

三、内存查看工具

我们从大到小各个角度去监控和分析游戏的内存情况:

进程级别: Perfdog、Android Studio、 Mac Xcode Instrument

UnityHeap(CPU主内存): 性能面板、ProfilingMemory、JavaScript Heap

引擎与资源:UnityProfiler

3.1 进程总内存

查看总内存时,我们需要先确定监控的小游戏进程名称:

Instruments in Xcode(iOS)

使用“Activity Monitor”,选择对应的设备-all processes-捕捉,即可看到所有进程的CPU与内存情况.

Perfdog(Android or iOS)

使用Perfdog选择对应的设置-进程名,即可看到相关性能数据,iOS设备应以紫色的XcodeMemory为准。

3.2 UnityHeap

UnityHeap非常关键,典型由以下几部分组成:

分析手段:

  1. 勾选转换面板"ProfilingMemory"
  2. 导出面板勾选“显示性能面板”或unity-namespace.js中enableProfileStats变量打开性能面板(注意:提审版本请勿显示). 游戏左上角显示Performence Stats性能面板

每项指标有三个数值:当前帧、最小值、最大值。

通常而言:MonoHeap + NativeReserverd + 原生插件内存 = DynamicMemory, 因此开发者需要关注这几部分内存。

Unity引擎视角:

底层分配器视角:

底层分配器:

3.3 ProfilingMemory

ProfilingMemory可以分析UnityHeap底层分配器的分配细节,任何分配都会产生记录,因此我们可以通过该能力分析更详细具体的分配行为。

关于该能力的使用请查阅使用ProfilingMemory分析内存

3.4 Unity Profiler

当发现UnityHeap(尤其是Native)占用比较高时,可通过UnityProfiler进一步分析问题所在。关于该工具在微信小游戏的使用请查阅使用 Unity Profiler 性能调优,推荐使用Unity InstantGame版本增强的Profiler功能,下载地址请查阅推荐引擎版本

3.5 JavaScript Heap

由于Unity WebGL是托管在浏览器环境中,因此JavaScript Heap包含了大部分(并非全部)我们关注的内存, 通常我们可以使用浏览器自带的内存工具。 但需要注意的是JavaScript Heap通常无法看出具体内存使用,发现该部分内存明显大于我们预留的UnityHeap,应检查是否有使用Unity Cache进行文件缓存,务必避免这样使用。

微信开发者工具

FireFox Memory(PC)

iOS Safari Timeline(PC or iOS)

四、内存优化方案

计算公式: 小游戏基础库 + Cavnas + 编译内存 + UnityHeap + Gfx显存 + 音频 + JavaScript内存。 UnityHeap = max(托管/Mono内存) + max(Native/Reserved内存 + C原生代码内存)

以iOS高性能模式为例,一款代码(导出目录/webgl/Build/xxx.code.unityweb或code.wasm)大小为30MB的游戏占用内存为: 小游戏基础库(130MB) + Cavnas(70MB) + 编译内存(300MB) + UnityHeap + Gfx显存 + 音频 + JavaScript(通常<100MB)。

假如游戏需要支持低档机型,将内存控制到1G以内,业务侧(UnityHeap, Gfx显存,音频,JavaScript)需控制在500MB左右。我们此处给出转换游戏中最容易遇到的内存问题与解决方案,如果开发者遇到内存问题时请逐个排查优化。

4.1 WASM代码编译内存

4.2 GPU内存

4.3 UnityHeap

4.4 首资源包与AssetBundle内存

4.5 音频内存

4.6 其他常见优化手段

五、QA

  1. Q: 如何解决iOS高性能模式出现内存过大导致游戏关闭,常见优化步骤如何?

  2. Q: 在Unity Profiler看到内存才200MB+,是否代表游戏内存无问题

  3. Q: 转换面板设置内存值多少合适?

',61);function g(b,_,U,P,M,q){return t(),a("div",null,[c,l(" Unity WebGL是以WebAssembly+WebGL技术为基础的应用,运行在浏览器环境,因此游戏内存的分配也是完全托管在这个环境中。 "),f])}const x=e(y,[["render",g]]);export{A as __pageData,x as default}; diff --git a/assets/Design_OptimizationMemory.md.CqTeDkzA.lean.js b/assets/Design_OptimizationMemory.md.CqTeDkzA.lean.js new file mode 100644 index 00000000..83da2ed9 --- /dev/null +++ b/assets/Design_OptimizationMemory.md.CqTeDkzA.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,a as l,a4 as i,o as t}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/optimizationMemory1.CpSWLJ8m.png",o="/minigame-unity-webgl-transform/assets/optimizationMemory10.D-SZ1dZe.png",n="/minigame-unity-webgl-transform/assets/optimizationMemory2.aE_-ogAD.png",s="/minigame-unity-webgl-transform/assets/optimizationMemory3.CEtq636B.png",p="/minigame-unity-webgl-transform/assets/optimizationMemory4.ymgsNGzl.png",m="/minigame-unity-webgl-transform/assets/optimizationMemory6.8iXuz3Gb.png",h="/minigame-unity-webgl-transform/assets/optimizationMemory11.BB2iD3xR.png",d="/minigame-unity-webgl-transform/assets/optimizationMemory12.C9Wsxuea.png",u="/minigame-unity-webgl-transform/assets/optimizationMemory5.CzK1696v.png",A=JSON.parse('{"title":"优化Unity WebGL的内存","description":"","frontmatter":{},"headers":[],"relativePath":"Design/OptimizationMemory.md","filePath":"Design/OptimizationMemory.md"}'),y={name:"Design/OptimizationMemory.md"},c=i("",12),f=i("",61);function g(b,_,U,P,M,q){return t(),a("div",null,[c,l(" Unity WebGL是以WebAssembly+WebGL技术为基础的应用,运行在浏览器环境,因此游戏内存的分配也是完全托管在这个环境中。 "),f])}const x=e(y,[["render",g]]);export{A as __pageData,x as default}; diff --git a/assets/Design_OptimizationPerformence.md.CrALocpx.js b/assets/Design_OptimizationPerformence.md.CrALocpx.js new file mode 100644 index 00000000..d843a61d --- /dev/null +++ b/assets/Design_OptimizationPerformence.md.CrALocpx.js @@ -0,0 +1,5 @@ +import{_ as e}from"./chunks/IOSDevicePixelRatio.DHUlmbuM.js";import{_ as a,c as i,o as r,a4 as l}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/optimizationperformence1.CW91_65C.png",n="/minigame-unity-webgl-transform/assets/optimizationperformence2.Bbu1amCi.png",g=JSON.parse('{"title":"优化Unity WebGL的运行性能","description":"","frontmatter":{},"headers":[],"relativePath":"Design/OptimizationPerformence.md","filePath":"Design/OptimizationPerformence.md"}'),o={name:"Design/OptimizationPerformence.md"},s=l('

优化Unity WebGL的运行性能

一、运行性能概述

Unity WebGL是以WebAssebly(WASM)+WebGL为核心的技术方案,运行性能会极大影响可承载的游戏内容玩法。

本文主要介绍Unity WebGL与基于JS引擎的普通H5游戏、原生APP手游之间技术栈导致的性能差异,以及不同系统平台(Android、iOS、Windows PC)之间的性能差异。其次阐述在微信小游戏环境下最佳的性能优化工具与常见优化手段。

Unity WebGL VS APP的运行性能差异

WASM VS JS的运行差异

因此,两者在实际使用时并不能简单以语言算力对比,需要以实测游戏为准。

系统平台之间的性能差异

二、优化目标

由于Unity WebGL的性能无法完全达到原生APP的性能水平,开发者需要根据不同品类的游戏建立不同的最低机型要求和流畅度标准。 建议:

详细的基准机型与性能要求可参考性能评估标准微信小游戏平台对上线无严格的性能要求,需要开发者根据自身游戏商业化要求制定。

三、常用优化工具

3.1 小游戏Android CPU Profiler(推荐)

微信小游戏请使用 Android CPU Profiler 性能调优,在勾选Profile-funcs选项后,使用工具在真机上获取Profile数据以分析热点函数和性能瓶颈,非常建议开发者熟练使用,无论是启动耗时或运行时流畅分析都非常有用。

3.2 Unity Profiler

Unity Profiler的运行原理是在Unity Editor监听固定端口,Unity WebGL游戏运行时以WebSocket连接并定期发送性能数据。

3.3 小游戏云测

小游戏云测是使用大量真实的移动设备测试游戏的功能、性能、兼容性。

三、常见优化手段

1. 配置加载与协议解析

不用使用XML、JSON解析大文件,尤其是在游戏启动阶段,字符串类型解析器将耗费大量CPU算力与产生GC。比如大型游戏在使用Addressable时catalog文件往往会超过10MB,导致解析过慢而影响启动速度,此时应使用其他资源管理比如AssetBundle来减少资源索引文件大小。同样地,在游戏过程中也尽量避免这类CPU消耗。

2. LUA性能

Unity WebGL环境的lua不支持JIT,因此需要避免用于重度逻辑。可使用 Android CPU Profiler 性能调优查看LUA的耗时占比。

3. 物理性能

请参考文档优化物理性能,适当调整Fixed Timestep与 Maximum Allowed Timestep降低计算频率。

4. 实例化

由于Unity WebGL是单线程模型,因此耗时长的CPU运算会影响帧率。较为普遍的是AssetBundle加载与Prefab实例化,通过优化逻辑分帧加载可大幅度提升游戏体验。

5. 限制帧率

限制帧率有利于降低设备发热量与提升游戏时长,对帧率不敏感游戏建议使用, 可使用Application.targetFramerate限帧,当帧率为15/30/60使用raf分片处理,其余值使用timer控制。

6. 限制分辨率

限制分辨率以一定的画质牺牲来降低对设备消耗,在小游戏平台请勿使用Unity的SetResulution等接口修改分辨率,应使用DevicePixelRatio来控制(仅支持ios、android)。设备默认DevicePixelRatio(最后一列dpi)如下:

如需强制设置iOS的设备分辨率可以在【导出面板-更多配置项-Project Conf】中修改配置 IOS Device Pixel Ratio 为 2:

7. 使用压缩纹理

在压缩纹理不支持的情况下,纹理会由于需要在CPU中软解为RGB/RGBA32造成巨大的CPU和内存消耗,运行中的这种行为会造成明显的帧率卡顿问题,建议使用压缩纹理优化

8. WebGL2.0说明

请查阅WebGL2.0渲染支持说明

9. 减少Drawcall

大量DC会造成非常大的CPU压力,当场景渲染物件过多时应该采取适当的措施减少Drawcall

10. 使用SRP Batcher

Uinty WebGL的SRP Batcher需要两个先决条件:Unity 2021以上 + WebGL2.0

11. 如何获取设备硬件信息

`,53),h=[s];function d(p,c,m,u,b,P){return r(),i("div",null,h)}const U=a(o,[["render",d]]);export{g as __pageData,U as default}; diff --git a/assets/Design_OptimizationPerformence.md.CrALocpx.lean.js b/assets/Design_OptimizationPerformence.md.CrALocpx.lean.js new file mode 100644 index 00000000..31e2074f --- /dev/null +++ b/assets/Design_OptimizationPerformence.md.CrALocpx.lean.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/IOSDevicePixelRatio.DHUlmbuM.js";import{_ as a,c as i,o as r,a4 as l}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/optimizationperformence1.CW91_65C.png",n="/minigame-unity-webgl-transform/assets/optimizationperformence2.Bbu1amCi.png",g=JSON.parse('{"title":"优化Unity WebGL的运行性能","description":"","frontmatter":{},"headers":[],"relativePath":"Design/OptimizationPerformence.md","filePath":"Design/OptimizationPerformence.md"}'),o={name:"Design/OptimizationPerformence.md"},s=l("",53),h=[s];function d(p,c,m,u,b,P){return r(),i("div",null,h)}const U=a(o,[["render",d]]);export{g as __pageData,U as default}; diff --git a/assets/Design_PerfMeasure.md.DqQ7Xs1a.js b/assets/Design_PerfMeasure.md.DqQ7Xs1a.js new file mode 100644 index 00000000..6989079d --- /dev/null +++ b/assets/Design_PerfMeasure.md.DqQ7Xs1a.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as a,a4 as r}from"./chunks/framework.Br2U662V.js";const d="/minigame-unity-webgl-transform/assets/ios_start_performance.COdU60g3.png",n="/minigame-unity-webgl-transform/assets/ios_running_performance.BhKw0KAS.png",i="/minigame-unity-webgl-transform/assets/android_start_performance.BEBLnORD.png",o="/minigame-unity-webgl-transform/assets/android_running_performance.DuhaNO5M.png",_=JSON.parse('{"title":"Unity WebGL小游戏适配方案性能标准","description":"","frontmatter":{},"headers":[],"relativePath":"Design/PerfMeasure.md","filePath":"Design/PerfMeasure.md"}'),l={name:"Design/PerfMeasure.md"},s=r('

Unity WebGL小游戏适配方案性能标准

为什么需要性能评测标准?

Unity性能评测标准用于开发者优化游戏性能数据,提升用户体验。评测标准根据小游戏整体的性能数据表现,结合操作系统、机型分档等多种维度建立。

评测标准细则

性能基线

评测小游戏性能首先需要确定性能基线, 即先确定机型设备条件,开发者可通过机型档位映射获取机型档位的参考机型。

游戏类型说明

分类定义
重度玩法较复杂,通常包含较多游戏场景或支持多人在线游戏(eg: MMO、SLG品类等)
中度包含一定养成玩法、内置内购商城等(eg: 模拟经营、卡牌等)
轻度仅包含简单操作、无养成体系、无内购,以休闲娱乐为主(eg: 棋牌等)

指标与测量方法

Unity小游戏的启动可参考启动流程与时序

定义测量方法
首资源包游戏首个data资源文件位于导出目录/webgl/md5.webgl.data.unityweb.bin.txt, CDN使用gzip压缩
WASM代码游戏代码压缩包位于导出目录/minigame/wasmcode/md5.webgl.wasm.code.unityweb.wasm.br, CDN使用gzip压缩
核心资源除首资源包外进入游戏核心玩法所需的资源量业务自定下载,通常为AssetBundle
CALLMAIN引擎和首场景(Loading)初始化通过timelog,或日志查看“CALLMAIN耗时”
游戏初始化完成引擎和首场景完成,出现首个业务场景通过timelog, 或日志查看“游戏启动耗时”
游戏可交互完成游戏核心场景完成通常定义为用户可交互的时机,可通过启动留存上报能力上报统计。eg:休闲游戏为核心玩法,RPG游戏为创角
内存峰值内存峰值进程内存峰值,测量方法请参考优化Unity WebGL的内存
内存异常退出运行时长由于内存不足而使小游戏发生Crash时,当前游戏的运行时长,表示游戏的稳定运行时长开发者可通过 小游戏数据助手(数据-性能分析)或 MP-研发工具箱-性能数据 获取游戏的现网玩家的性能采集数据 通过小游戏数据助手查看(仅包含线上用户数据)
帧率核心玩法的平均帧率测量5分钟以上游戏核心玩法帧率,取平均值
卡顿率核心玩法的平均卡顿率测量5分钟以上游戏核心玩法卡顿率,取平均值

开发者需要关注哪些性能指标

阶段重点关注指标
启动1. 游戏初始化完成耗时 2. 游戏可交互耗时
运行1. 内存峰值 2. FPS均值 3. 卡顿率 4. 内存异常退出率(iOS) 5. 内存异常退出运行时长(iOS)
兼容性问题1. 逻辑异常 2. 黑/白屏 3. JS Error

代码与资源体积

能力下载量
首资源包(gzip压缩后)<5MB
WASM代码(br压缩后)<5MB
核心玩法资源<30MB

评测标准

评测标准更新时间:2024-08-13(历史现网标准请查阅历史评测标准

评测标准依赖于 现网真实玩家上报的性能数据云测试批量测试数据 统计得出。

注意:

iOS性能评测标准

启动性能

运行性能

重点关注:内存峰值运行10mins内存峰值内存异常退出率内存异常退出运行时长

Android性能评测标准

启动性能

运行性能

评测工具

现网阶段

性能报告

为了能够帮助开发者快速了解游戏整体的性能情况,平台通过对评测标准和游戏性能数据的整合,面向开发者提供一个较为全面的大盘性能监控系统,详细可通过 性能监控系统 进行了解和使用。

性能数据

开发者可通过 小游戏数据助手(数据-性能分析)或 MP-研发工具箱-性能数据 获取游戏的现网玩家的性能采集数据。

开发阶段

使用网络模拟工具1MB/s条件

小游戏云测试

云测试服务是一套完整易用的在线测试服务,以帮助开发者更高效、更全面地进行自动化游戏性能测试、兼容性测试。更多详情可查阅小游戏云测试

性能诊断工具

微信小游戏性能诊断工具用于查看 开发版/体验版 运行时的网络和接口调用、运行性能以及启动耗时等信息,协助开发者更精确地定位问题并提供优化建议,详情可查阅性能诊断工具

Perfdog

使用PerfDog测试,PerfDog记录性能数据并上传,取平均值,每种机型测试3组数据再取平均,内存峰值取最大值。

历史评测标准

更新日期文档
2024.08.13当前标准
2023.05.17评测标准文档
',47),h=[s];function m(c,g,p,b,f,u){return a(),e("div",null,h)}const x=t(l,[["render",m]]);export{_ as __pageData,x as default}; diff --git a/assets/Design_PerfMeasure.md.DqQ7Xs1a.lean.js b/assets/Design_PerfMeasure.md.DqQ7Xs1a.lean.js new file mode 100644 index 00000000..5dc18c74 --- /dev/null +++ b/assets/Design_PerfMeasure.md.DqQ7Xs1a.lean.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as a,a4 as r}from"./chunks/framework.Br2U662V.js";const d="/minigame-unity-webgl-transform/assets/ios_start_performance.COdU60g3.png",n="/minigame-unity-webgl-transform/assets/ios_running_performance.BhKw0KAS.png",i="/minigame-unity-webgl-transform/assets/android_start_performance.BEBLnORD.png",o="/minigame-unity-webgl-transform/assets/android_running_performance.DuhaNO5M.png",_=JSON.parse('{"title":"Unity WebGL小游戏适配方案性能标准","description":"","frontmatter":{},"headers":[],"relativePath":"Design/PerfMeasure.md","filePath":"Design/PerfMeasure.md"}'),l={name:"Design/PerfMeasure.md"},s=r("",47),h=[s];function m(c,g,p,b,f,u){return a(),e("div",null,h)}const x=t(l,[["render",m]]);export{_ as __pageData,x as default}; diff --git a/assets/Design_PerfOptimization.md.C-5U97w8.js b/assets/Design_PerfOptimization.md.C-5U97w8.js new file mode 100644 index 00000000..c209dc25 --- /dev/null +++ b/assets/Design_PerfOptimization.md.C-5U97w8.js @@ -0,0 +1 @@ +import{_ as i,c as l,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const c=JSON.parse('{"title":"性能优化总览","description":"","frontmatter":{},"headers":[],"relativePath":"Design/PerfOptimization.md","filePath":"Design/PerfOptimization.md"}'),t={name:"Design/PerfOptimization.md"},r=e('

性能优化总览

一、为何需要进行性能优化?

Unity WebGL导出形式相对于原生APP应用,需要开发者更关注性能与体验调优。有以下几点原因:

  1. 小游戏天生为"即开即用",在小游戏生态下玩家对启动耗时更敏感。
  2. Unity WebGL底层基于WebAssembly,算力不及原生APP。
  3. Unity并未对WebGL平台做特别裁剪,启动较慢。

因此,相对于原生APP,无论从启动还是运行上我们都需要做进一步性能优化。

二、优化目标

根据平台在不同游戏类型/机型下的评测,我们给出Unity WebGL小游戏可以参照的的性能评估标准,开发者依此对游戏的启动与运行性能进行调优。

三、最佳实践

3.1 加快游戏启动速度

更多信息请参考:

3.2 资源按需加载

更多信息请阅读:

3.3 资源处理建议

更多信息请阅读:

3.4 降低小游戏内存使用

更多信息请阅读:

3.5 降低CPU消耗

更多信息请阅读:

',28),o=[r];function n(h,s,d,u,m,p){return a(),l("div",null,o)}const _=i(t,[["render",n]]);export{c as __pageData,_ as default}; diff --git a/assets/Design_PerfOptimization.md.C-5U97w8.lean.js b/assets/Design_PerfOptimization.md.C-5U97w8.lean.js new file mode 100644 index 00000000..b64e4af1 --- /dev/null +++ b/assets/Design_PerfOptimization.md.C-5U97w8.lean.js @@ -0,0 +1 @@ +import{_ as i,c as l,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const c=JSON.parse('{"title":"性能优化总览","description":"","frontmatter":{},"headers":[],"relativePath":"Design/PerfOptimization.md","filePath":"Design/PerfOptimization.md"}'),t={name:"Design/PerfOptimization.md"},r=e("",28),o=[r];function n(h,s,d,u,m,p){return a(),l("div",null,o)}const _=i(t,[["render",n]]);export{c as __pageData,_ as default}; diff --git a/assets/Design_PerformanceMonitor.md.GX3ElIdy.js b/assets/Design_PerformanceMonitor.md.GX3ElIdy.js new file mode 100644 index 00000000..f8839078 --- /dev/null +++ b/assets/Design_PerformanceMonitor.md.GX3ElIdy.js @@ -0,0 +1,79 @@ +import{_ as a,c as s,o as n,a4 as l}from"./chunks/framework.Br2U662V.js";const e="/minigame-unity-webgl-transform/assets/monitor-dialog.DkmXCKiX.png",i="/minigame-unity-webgl-transform/assets/monitor-console.DO12gbRg.png",o="/minigame-unity-webgl-transform/assets/detail-log.DbHrWCWi.png",t="/minigame-unity-webgl-transform/assets/network-profile.D4dnTarY.png",C=JSON.parse('{"title":"最佳实践检测工具","description":"","frontmatter":{},"headers":[],"relativePath":"Design/PerformanceMonitor.md","filePath":"Design/PerformanceMonitor.md"}'),p={name:"Design/PerformanceMonitor.md"},c=l(`

最佳实践检测工具

作用

为了使游戏达到比较好的性能表现,仍需要开发者结合游戏实际情况进行优化。平台针对启动和运行输出了大量优化手段,使用最佳实践检测,可帮助开发者在开发阶段针对问题进行优化

如何使用

版本要求:转换插件版本 > 202305230000

导出小游戏默认在开发版和体验版开启检测,可通过minigame/unity-namespace.js修改

js
// 最佳实践检测配置
+unityNamespace.monitorConfig = {
+  enableMonitor: true, // 是否开启检测(只影响开发版/体验版,线上版本不会检测)
+  fps: 10, // 帧率低于此值的帧会被记录,用于分析长耗时帧,做了限帧的游戏应该适当调低
+  showResultAfterLaunch: true, // 是否一直检测到游戏可交互完成
+  monitorDuration: 30000, // 仅当showResultAfterLaunch=false时有效, 在引擎初始化完成(即callmain)后多长时间停止检测
+}

默认检测条件如上。插件并不知道什么时候检测截止,可选择可交互上报后或在引擎初始化完成(callmain)后多少ms截止,根据游戏实际情况修改。

  1. 有上报游戏可交互WX.ReportGameStart()的游戏 应该设置showResultAfterLaunch=true,同时会忽略monitorDuration的值

  2. 未上报游戏可交互上报的游戏 应设置showResultAfterLaunch=false,此时根据monitorDuration的值截止检测

检测示意

优化建议通过弹框提示,详细内容通过vconsole打印

  1. 弹框提醒优化建议
  1. console打印详细信息
  1. console打印检测报告,可着重关注网络和卡帧的数据

检测指标解释

启动检测

检查框架启动阶段的耗时和资源大小

监控指标

{
+  assetLoadCost: number; // 首资源包下载耗时,单位ms
+  assetContentLength: number; // 首资源包大小(未压缩原始大小),单位bytes
+  useContentEncoding: boolean; // 首资源包是否开启服务器压缩
+  wasmLoadCost: number; // wasm包下载耗时,ms
+  wasmContentLength: number; // 启动下载的wasm包大小,单位bytes
+  useCodeSplit: boolean; // 是否使用了wasm代码分包
+  callmainCost: number; // 引擎初始化耗时,ms
+}

优化建议概览

当提示优化建议时,可采用对应的优化手段

  1. 未使用wasm代码分包
  1. 首资源包较大
  1. 首资源包未开启服务器压缩
  1. callmain耗时较长,请用安卓cpuprofile分析热点函数

预下载检测

检查预下载列表使用情况,分为引擎初始化完成(callmain)和检测完成时两个结果

vconsole输出如下:预下载基本信息: xxx , callmain完成时预下载信息: xxx。其中xxx为js对象

监控指标

{
+  loadedCount: number; // 已预下载完成数量
+  loadingCount: number; // 正在预下载数量
+  loadedSizeStr: string; // 已预下载完成大小字符串表示, eg: 10.1MB
+  loadedSize: number; // 已预下载完成大小,bytes
+  hitCacheCount: number; // 命中CDN缓存的数量
+  useH2: boolean; // 是否启用HTTP2
+  useContentEncoding: boolean; // 是否开启了服务器压缩
+  preloadListLength: number; // 预下载资源个数
+}

优化建议概览

  1. 未使用预下载能力
  1. 已发起预下载,但未完成,请检查预下载资源是否过大,或是否下载过慢
  1. 预下载资源较小,请将大资源调整到预下载列表顶部
  1. 预下载资源个数较多
  1. 预下载资源量较大

wasm分包检测

使用wasm代码分包后,检查wasm分包代码的加载时机,加载分包造成的卡顿时长,用来分析分包收集是否合理。若加载时机过早、阻塞时间过长,则需要优化。

tips: 在新包做wasm分包期间可能会频繁提示优化建议

监控指标

{
+  loadSubWasmPackageStartTime: number; // 开始下载wasm子包的时间,ms
+  loadSubWasmPackageCostTime: number; // (仅安卓)加载子包耗时,ms
+  loadDurationCallmain: boolean; // 是否在引擎初始化期间加载子包
+  maxFetchPendingTime: number; // (仅iOS高性能)最大阻塞时间,ms。iOS高性能加载子包代码时会卡顿
+  costTimeAfterCallmain: number; // 引擎初始化完成后多长时间开始加载子包,ms
+}

优化建议概览

  1. wasm子包在callmain期间加载,请使用分包工具继续收集
  1. wasm子包加载时机过早,请使用分包工具继续收集
  1. 缺失函数过多,请使用分包工具继续收集

网络信息检测

检查可缓存资源配置、CDN配置、并发数数、请求量、资源量

监控指标

{
+  useH2: boolean, // 是否开启HTTP2.0
+  useContentEncoding: boolean, // 是否开启服务器压缩
+  cacheSettings: boolean, // settings.json是否自动缓存
+  cacheCatalog: boolean, // catalog.json是否自动缓存
+  appendHashToCatalog: boolean, // catalog.json是否带上了hash或其他用于区分版本的信息
+  requestCataHash: boolean, // 是否请求了catalog.hash文件用于资源热更新
+  requestBundleSettings: boolean, // 是否请求了settings.json
+  requestBundleCatalog: boolean, // 是否请求了catalog.json
+  loadCount: number, // 已发起请求数
+  loadedCount: number, // 已完成请求数
+  loadedSizeStr: string, // 请求回包总大小的字符串表示,eg: 10.1MB
+  loadedSize: number, // 请求回包总大小,bytes
+  hitCacheCount: number, // 命中CDN缓存个数
+  cacheableCount: number, // 可自动缓存个数
+  loadFromCacheCount: number, // 使用本地缓存的个数
+  startTime: number, // 首个请求开始时间
+  duration: number, // 监控时长
+  networkTime: number, // 有网络请求的总时长
+  maxLoadingCount: number, // 最大并发数,基于业务侧统计,会大于10个,表示有请求会排队
+  avgLoadingCount: number, // 平均并发数
+  loadedTasks: IBaseRequestInfo[], // 已下载完成请求详细信息
+}
+
+// 请求详细信息如下
+interface IBaseRequestInfo {
+  url: string; // 请求URL
+  startTime: number; // 请求开始时间
+  statusCode?: number; // 服务器状态码
+  enableContentEncoding?: boolean; // 是否开启了服务器压缩
+  endTime?: number; // 请求介绍时间
+  duration?: number; // 请求耗时
+  protocol?: string; // 网络协议,h2或http1.1
+  receivedBytedCount?: number; // 回包大小,bytes
+  hitCache?: boolean; // 是否命中CDN缓存
+  isReadFromCache?: boolean; // 是否使用本地缓存
+  cacheable?: boolean; // 是否自动缓存的资源
+}

优化建议概览

  1. 未开启http2
  1. 未命中CDN缓存
  1. 请勿缓存settings.json
  1. 可将catalog.json配置为可缓存文件
  1. catalog.json被缓存且无hash/版本信息, 会导致无法更新
  1. 请勿请求catalog.hash来做资源热更新,小游戏平台不支持
  1. 可缓存文件过少,检查缓存配置
  1. 网络并发数过少
  1. 网络未充分利用

帧率检测

检查是否有大长帧,标记大长帧出现的位置,辅助定位是cpu耗时还是网络耗时导致启动慢

监控指标

{
+  frames: string[]; // 长耗时的帧
+  frameCount: number; // 长耗时帧的个数
+  longestFrame: { // 最长帧信息
+      frame: string; // 帧数
+      frameCost: number; // 单帧耗时, ms
+      runtime: number; // 游戏运行时长, ms
+  };
+  frameInfo: IWrongFrame; // 长耗时帧信息
+  totalJankTime: number; // 总卡帧时长, ms
+  currentRuntime: number; // 当前游戏运行时长, ms
+  jankRate: number; // 卡顿率
+}

优化建议概览

卡帧问题,均需要使用cpuprofile定位。使用Android CPU Profiler性能调优使用Unity Profiler性能调优

  1. 存在长耗时帧cost=xxxms,runtime=xxxms
  1. 总卡顿时长xxxms
  1. 卡顿时长占比xx%

优化分析工具

微信开发者工具

',99),r=[c];function d(h,u,m,g,b,k){return n(),s("div",null,r)}const q=a(p,[["render",d]]);export{C as __pageData,q as default}; diff --git a/assets/Design_PerformanceMonitor.md.GX3ElIdy.lean.js b/assets/Design_PerformanceMonitor.md.GX3ElIdy.lean.js new file mode 100644 index 00000000..fa4a606d --- /dev/null +++ b/assets/Design_PerformanceMonitor.md.GX3ElIdy.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as n,a4 as l}from"./chunks/framework.Br2U662V.js";const e="/minigame-unity-webgl-transform/assets/monitor-dialog.DkmXCKiX.png",i="/minigame-unity-webgl-transform/assets/monitor-console.DO12gbRg.png",o="/minigame-unity-webgl-transform/assets/detail-log.DbHrWCWi.png",t="/minigame-unity-webgl-transform/assets/network-profile.D4dnTarY.png",C=JSON.parse('{"title":"最佳实践检测工具","description":"","frontmatter":{},"headers":[],"relativePath":"Design/PerformanceMonitor.md","filePath":"Design/PerformanceMonitor.md"}'),p={name:"Design/PerformanceMonitor.md"},c=l("",99),r=[c];function d(h,u,m,g,b,k){return n(),s("div",null,r)}const q=a(p,[["render",d]]);export{C as __pageData,q as default}; diff --git a/assets/Design_Profile.md.CWCGA8rU.js b/assets/Design_Profile.md.CWCGA8rU.js new file mode 100644 index 00000000..9e68a050 --- /dev/null +++ b/assets/Design_Profile.md.CWCGA8rU.js @@ -0,0 +1 @@ +import{_ as o,a as t,b as i}from"./chunks/profile3.CffCZqR8.js";import{_ as e,c as r,o as s,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/profile4.CDVkeqdb.png",w=JSON.parse('{"title":"使用Unity Profiler性能调优","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Profile.md","filePath":"Design/Profile.md"}'),a={name:"Design/Profile.md"},p=n('

使用Unity Profiler性能调优

  1. 导出选项时勾选"Development Build"与"Autoconnection Profiler"

  2. 打开Unity-Window-Analysis-Profile窗口

Unity将自启动监听端口34999等待调试链接,对于WebGL版本会启动websockify.js(用于websocket转发)。 此时,导出的WebGL游戏在浏览器时能自动连接到Unity Profiler。

  1. 微信开发者工具小游戏Profile 使用转换脚本导出微信小游戏包并启动小游戏,微信小游戏将自动连接到Unity Profiler

  2. 真机调试 Android或iOS启动之后将使用"ws://ip:port"自动连接到“Unity Profiler”, 如果无法连接请关注vConsole输出的IP:Port是否可达。 如果需要手工调整端口可通过修改以下代码:

一般来说,保持端口为54998,如修改端口需重启websocketfy.js: windows: "$UNITY_PATH/Editor/Data/Tools/nodejs/node.exe" "$UNITY_PATH/Editor/Data/PlaybackEngines/WebGLSupport/BuildTools/websockify/websockify.js" 0.0.0.0:port localhost:34999 mac: /Applications/Unity/Hub/Editor/$Verson/Unity.app/Contents/Tools/nodejs/bin/node /Applications/Unity/Hub/Editor/$Verson/PlaybackEngines/WebGLSupport/BuildTools/websockify/websockify.js 0.0.0.0:port localhost:34999 -vv

附录:

',8),c=[p];function d(_,f,u,m,P,y){return s(),r("div",null,c)}const k=e(a,[["render",d]]);export{w as __pageData,k as default}; diff --git a/assets/Design_Profile.md.CWCGA8rU.lean.js b/assets/Design_Profile.md.CWCGA8rU.lean.js new file mode 100644 index 00000000..f94e7f79 --- /dev/null +++ b/assets/Design_Profile.md.CWCGA8rU.lean.js @@ -0,0 +1 @@ +import{_ as o,a as t,b as i}from"./chunks/profile3.CffCZqR8.js";import{_ as e,c as r,o as s,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/profile4.CDVkeqdb.png",w=JSON.parse('{"title":"使用Unity Profiler性能调优","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Profile.md","filePath":"Design/Profile.md"}'),a={name:"Design/Profile.md"},p=n("",8),c=[p];function d(_,f,u,m,P,y){return s(),r("div",null,c)}const k=e(a,[["render",d]]);export{w as __pageData,k as default}; diff --git a/assets/Design_RenderOptimization.md.D368ru2I.js b/assets/Design_RenderOptimization.md.D368ru2I.js new file mode 100644 index 00000000..ee308ac4 --- /dev/null +++ b/assets/Design_RenderOptimization.md.D368ru2I.js @@ -0,0 +1 @@ +import{_ as l}from"./chunks/IOSDevicePixelRatio.DHUlmbuM.js";import{_ as i,c as e,o as a,a4 as t}from"./chunks/framework.Br2U662V.js";const P=JSON.parse('{"title":"RenderOptimization","description":"","frontmatter":{},"headers":[],"relativePath":"Design/RenderOptimization.md","filePath":"Design/RenderOptimization.md"}'),r={name:"Design/RenderOptimization.md"},o=t('

RenderOptimization

WebGL1.0 还是 WebGL2.0

选择哪种渲染管线

线性颜色空间 还是 Gamma 颜色空间

渲染性能优化的一些建议

光照和阴影

材质和Shader

纹理设置

网格和蒙皮

DrawCall 相关

摄像机 Camera

渲染分辨率

后处理

特效

参考文档

',28),n=[o];function u(c,h,b,s,d,m){return a(),e("div",null,n)}const p=i(r,[["render",u]]);export{P as __pageData,p as default}; diff --git a/assets/Design_RenderOptimization.md.D368ru2I.lean.js b/assets/Design_RenderOptimization.md.D368ru2I.lean.js new file mode 100644 index 00000000..18a294cf --- /dev/null +++ b/assets/Design_RenderOptimization.md.D368ru2I.lean.js @@ -0,0 +1 @@ +import{_ as l}from"./chunks/IOSDevicePixelRatio.DHUlmbuM.js";import{_ as i,c as e,o as a,a4 as t}from"./chunks/framework.Br2U662V.js";const P=JSON.parse('{"title":"RenderOptimization","description":"","frontmatter":{},"headers":[],"relativePath":"Design/RenderOptimization.md","filePath":"Design/RenderOptimization.md"}'),r={name:"Design/RenderOptimization.md"},o=t("",28),n=[o];function u(c,h,b,s,d,m){return a(),e("div",null,n)}const p=i(r,[["render",u]]);export{P as __pageData,p as default}; diff --git a/assets/Design_ReportStartupStat.md.CcswZlo3.js b/assets/Design_ReportStartupStat.md.CcswZlo3.js new file mode 100644 index 00000000..b8c679c5 --- /dev/null +++ b/assets/Design_ReportStartupStat.md.CcswZlo3.js @@ -0,0 +1,70 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/reportstartupstat3.CsotQIbl.png",p="/minigame-unity-webgl-transform/assets/reportstartupstat2.A-XTyuDH.png",l="/minigame-unity-webgl-transform/assets/reportstartupstat1.qEYJSd-a.png",u=JSON.parse('{"title":"启动留存数据上报统计","description":"","frontmatter":{},"headers":[],"relativePath":"Design/ReportStartupStat.md","filePath":"Design/ReportStartupStat.md"}'),h={name:"Design/ReportStartupStat.md"},e=n('

启动留存数据上报统计

一、概述

在小游戏环境下,玩家对启动时长与体验非常敏感(尤其从“广告”等买量场景进入的玩家)。开发者往往需要分析玩家从点击到进入游戏核心玩法的整个过程流失率。 Unity Loader的数据统计功能如下:

  1. Unity Loader插件自动统计了代码包、首包资源、代码编译、引擎与首场景初始化,无需手动上报
  2. 通过C# SDK接口让开发者上报自定义启动阶段,分析每个环节可能存在的流失

二、上报广告信息

为了帮助开发者分析广告渠道的留存数据,达到最好的买量效果,Loader提供了上报广告参数的能力,用于区分不同广告位/广告类型/素材类型的数据。

如何上报?

广告买量时,带上广告相关自定义参数,Loader自动上报 eg: adSpaceType=1&adType=1&materialType=1

取值范围:1-200; 默认为0

三、上报自定义阶段

为了详细统计玩家的流失情况以便开发者进行优化,我们拆分了三个部分。 其中自动上报为Unity Loader自动完成开发者无需关注,但自定义阶段启动加载完成需开发者主动调用接口进行上报。详细接口可参考C# SDK中的WX.cs,文档可查看启动场景上报分析wx.reportScene

1. 游戏完成所有加载时上报

当游戏完成所有加载阶段,进入核心玩法时(如进入新手引导或大厅)调用

C#
      WX.ReportGameStart()

2. 上报当前自定义阶段错误信息

C#
      WX.ReportGameSceneError(int sceneId, int errorType, string errStr, string extJsonStr)

sceneId同启动场景上报分析

errorType取值:[0,10000]

示例:

C#
      // 假设Loading场景中A资源完成为1001, 需要知道完成的留存率
+      WX.ReportScene(new ReportSceneParams()
+      {
+            sceneId = 1001,
+            costTime = 100,
+            metric = new Dictionary<string, string>()
+            {
+                  { "testkey1", "1" },
+                  { "testkey2", "2" }
+            },
+            dimension = new Dictionary<string, string>()
+            {
+                  { "testkey1", "testvalue1" },
+                  { "testkey2", "testvalue2" }
+            },
+            complete = (res) =>
+            {
+                  Debug.Log("ReportScene complete" + res);
+            },
+            success = (res) =>
+            {
+                  Debug.Log("ReportScene success: " + res);
+            },
+            fail = (res) =>
+            {
+                  Debug.Log("ReportScene fail: " + res);
+            }
+      });
+      
+      // 所有加载完成,玩家可以交互(如休闲游戏已进入核心玩法、MMO游戏进入创角时), 需要知道留存率
+      WX.ReportGameStart();

四、获取Loader启动阶段

从启动时序可以知道Loader启动阶段分为以下五个阶段

当业务侧需要使用Loader启动数据时,可以使用Loader暴露的进度事件上报到自己的系统

tips: 目前只支持js调用

js
gameManager.onLaunchProgress = (e) => {
+      // e: LaunchEvent
+      // interface LaunchEvent {
+      //   type: LaunchEventType;
+      //   data: {
+      //     costTimeMs: number; // 阶段耗时
+      //     runTimeMs: number; // 总耗时
+      //     loadDataPackageFromSubpackage: boolean; // 首包资源是否通过小游戏分包加载
+      //     isVisible: boolean; // 当前是否处于前台,onShow/onHide
+      //     useCodeSplit: boolean; // 是否使用代码分包
+      //     isHighPerformance: boolean; // 是否iOS高性能模式
+      //   };
+      // }
+      if (e.type === launchEventType.launchPlugin) {
+
+      }
+      if (e.type === launchEventType.loadWasm) {
+
+      }
+      if (e.type === launchEventType.compileWasm) {
+
+      }
+      if (e.type === launchEventType.loadAssets) {
+
+      }
+      if (e.type === launchEventType.readAssets) {
+
+      }
+      if (e.type === launchEventType.prepareGame) {
+
+      }
+}

类型枚举

js
export const launchEventType = {
+  launchPlugin: 0, // 插件启动
+  loadWasm: 1, // 下载wasm代码
+  compileWasm: 2, // wasm代码编译
+  loadAssets: 3, // 下载首资源包
+  unzipAssets: 4, // 解压首资源包
+  readAssets: 5, // 读取首资源包
+  prepareGame: 6, // 引擎初始化
+};

五、获取数据统计

请注意!需前往【公众平台 - 能力地图 - 生产提效包 - 快适配 】开通后,方可查看数据

数据报表包含Unity Loader自动上报与开发者自定义阶段。关注总体流失漏斗以确定需要优化的方向,同时分阶段的耗时分布有利于帮助我们分析该阶段的对应耗时的用户占比。

数据报表统计分析请参考文档启动场景上报分析-数据分析 进行查看。

注:

  1. 若使用的 转换插件版本<202211101011(对应Unity Loader版本<1.1.2),数据统计报表需要联系我们获取。
  2. 数据报表数据未来会开放到《小游戏数据助手》。
',37),k=[e];function E(r,d,g,y,o,c){return a(),i("div",null,k)}const D=s(h,[["render",E]]);export{u as __pageData,D as default}; diff --git a/assets/Design_ReportStartupStat.md.CcswZlo3.lean.js b/assets/Design_ReportStartupStat.md.CcswZlo3.lean.js new file mode 100644 index 00000000..ba46d024 --- /dev/null +++ b/assets/Design_ReportStartupStat.md.CcswZlo3.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/reportstartupstat3.CsotQIbl.png",p="/minigame-unity-webgl-transform/assets/reportstartupstat2.A-XTyuDH.png",l="/minigame-unity-webgl-transform/assets/reportstartupstat1.qEYJSd-a.png",u=JSON.parse('{"title":"启动留存数据上报统计","description":"","frontmatter":{},"headers":[],"relativePath":"Design/ReportStartupStat.md","filePath":"Design/ReportStartupStat.md"}'),h={name:"Design/ReportStartupStat.md"},e=n("",37),k=[e];function E(r,d,g,y,o,c){return a(),i("div",null,k)}const D=s(h,[["render",E]]);export{u as __pageData,D as default}; diff --git a/assets/Design_ResourcesLoading.md.BKWzKO9M.js b/assets/Design_ResourcesLoading.md.BKWzKO9M.js new file mode 100644 index 00000000..80706aed --- /dev/null +++ b/assets/Design_ResourcesLoading.md.BKWzKO9M.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as e,a4 as n}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"资源按需加载概述","description":"","frontmatter":{},"headers":[],"relativePath":"Design/ResourcesLoading.md","filePath":"Design/ResourcesLoading.md"}'),s={name:"Design/ResourcesLoading.md"},d=n('

资源按需加载概述

​ 区别于原生 APP 游戏通常安装与启动时将资源都下载完成,小游戏需要做到“即点即玩”,启动仅能加载少量资源,其余部分都必须放CDN进行延迟加载,如何合理与高效地进行资源按需加载是非常重要的事情。

​ 目前分包将基于 AA/AB 包的按需加载,以及 Unity Instant Game 三种方案。值得注意的是,微信小游戏环境中不支持对本地的 Bundle 进行加载,因此无论哪种方案最终都采用上传 CDN 方式在游戏运行时异步按需下载。

AA包、AB包、Instant Game 方案选择说明

相关手册:AA(Addressable) 进行资源按需加载AB(AssetBundle)进行资源按需加载Instant Game 实践指南

​ AA/AB 包是常规的分包解决方案,关于他们的选择对于轻度游戏来说两者没有特别要求,倒是功能强大的 AA包 使用门槛更低一些,而对于重度游戏,平台目前所反馈到的结论是使用 AB包 的性能要比 AA包 更好,AA包较大项目时生成的未压缩的 catalog 较大,加载效率低,改用 AB包后,效果提升明显。

​ Instant Game 是由 Unity 官方提供的自动加载方案,有关 Instant Game 详细内容可查阅 Instant Game 实践指南,本节说明三种方案的差异:

常规资源加载方案(AA/AB包)Instant Game 工具
技术原理基于 AA/AB 包的异步资源管理Unity引擎底层资源异步加载策略
引擎版本不限制目前需指定版本 2021.2.5
转化人力适中较少/适中
懒加载资源类型常见纹理资源纹理、模型、骨骼动画、音频资源
自选CDN支持不支持(需使用腾讯云CDN服务)
必要的代码修改通常需要适配较少/达到最佳仍需要
首资源包处理通常需要适配默认不需要/达到最佳仍需要

选择建议:

各类型游戏的资源优化建议

​ 不同的游戏所需要的性能不尽相同,转化过程中的复杂度以及关注的侧重点自然也是不同的。游戏开发者可以根据自己游戏的类型进行不同的优化策略来提升实际的游戏体验,本节总结的列举开发者对不同类型的游戏应重点关注的优化内容。

原生 APP 手游已使用 AB/AA 包等资源按需加载的游戏**

特点:游戏原本发布原生 APP 平台,将游戏资源以 AA/AB 包方式存放于磁盘本地,在游戏运行时适宜的位置进行加载/卸载。

优化建议:

原生 APP 手游未使用 资源按需加载 的轻度游戏

特点:游戏总包体积较小,“关卡”休闲类小游戏等。

优化建议:

原生 APP 手游未使用 资源按需加载 的中重度游戏

特点:游戏较大,但未使用 AA/AB 包方式进行分包管理,或较少使用,场景中必须与非及时资源在启动时一并加载。

优化建议:

',24),l=[d];function r(A,i,o,h,p,u){return e(),a("div",null,l)}const P=t(s,[["render",r]]);export{m as __pageData,P as default}; diff --git a/assets/Design_ResourcesLoading.md.BKWzKO9M.lean.js b/assets/Design_ResourcesLoading.md.BKWzKO9M.lean.js new file mode 100644 index 00000000..defe4e5a --- /dev/null +++ b/assets/Design_ResourcesLoading.md.BKWzKO9M.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as e,a4 as n}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"资源按需加载概述","description":"","frontmatter":{},"headers":[],"relativePath":"Design/ResourcesLoading.md","filePath":"Design/ResourcesLoading.md"}'),s={name:"Design/ResourcesLoading.md"},d=n("",24),l=[d];function r(A,i,o,h,p,u){return e(),a("div",null,l)}const P=t(s,[["render",r]]);export{m as __pageData,P as default}; diff --git a/assets/Design_SDKInstaller.md._y_ScH2A.js b/assets/Design_SDKInstaller.md._y_ScH2A.js new file mode 100644 index 00000000..b6577e8a --- /dev/null +++ b/assets/Design_SDKInstaller.md._y_ScH2A.js @@ -0,0 +1,2 @@ +import{_ as a,c as e,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const k=JSON.parse('{"title":"微信SDK安装","description":"","frontmatter":{},"headers":[],"relativePath":"Design/SDKInstaller.md","filePath":"Design/SDKInstaller.md"}'),s={name:"Design/SDKInstaller.md"},n=t(`

微信SDK安装

为兼容历史团结/Unity版本的使用,微信小游戏团队将SDK分为如下两种模式安装使用。

方法一(推荐):Package 方式安装

目前团结引擎、Unity 2019及以后版本推荐使用 Package 方式安装WXSDK。

安装指南

打开游戏工程 -> Unity/团结引擎 Editor 菜单栏 -> Package Manager -> 右上方 “+” -> Add package from git URL URL地址为:

https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git

或国内Gitee镜像:

https://gitee.com/wechat-minigame/minigame-tuanjie-transform-sdk.git

即可完成SDK导入。

方法二:资源包方式安装

对于 Unity 2018 版本引擎使用资源包方式可安装 WXSDK

安装指南

如果当前版本暂不支持 PackageManager 导入,请 下载UnitySDK 后导入游戏工程中。

目录结构说明

我们希望SDK与工程代码解耦,如此一来也更方便开发者的代码版本维护。因此 PackageManager 模式下,微信SDK内容将不再存放在游戏工程的Assets目录中。为兼容需要,仍然会自动在 Assets 目录下创建 WX-WASM-SDK-V2 数据目录,如需保持相关的应用配置应始终保留该目录内容。

常见问题

1.游戏工程可以导出但在微信开发者工具运行提示报错:

常见的情况是发生在如空项目或游戏代码中从未使用WXSDK的任何Runtime能力时,引擎导出项目将微信Runtime包裁剪,解决办法是在游戏合理位置增加对WXSDK的使用即可。 如:

c#
// 无直接的API能力调用可使用读取系统信息等API
+WX.GetSystemInfo(new GetSystemInfoOption());  // 读取SystemInfo
`,21),r=[n];function l(o,h,p,d,c,g){return i(),e("div",null,r)}const u=a(s,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/Design_SDKInstaller.md._y_ScH2A.lean.js b/assets/Design_SDKInstaller.md._y_ScH2A.lean.js new file mode 100644 index 00000000..78b7ce87 --- /dev/null +++ b/assets/Design_SDKInstaller.md._y_ScH2A.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const k=JSON.parse('{"title":"微信SDK安装","description":"","frontmatter":{},"headers":[],"relativePath":"Design/SDKInstaller.md","filePath":"Design/SDKInstaller.md"}'),s={name:"Design/SDKInstaller.md"},n=t("",21),r=[n];function l(o,h,p,d,c,g){return i(),e("div",null,r)}const u=a(s,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/Design_Salon.md.BzNSLcNw.js b/assets/Design_Salon.md.BzNSLcNw.js new file mode 100644 index 00000000..38150884 --- /dev/null +++ b/assets/Design_Salon.md.BzNSLcNw.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as t,a4 as o}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"技术沙龙","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Salon.md","filePath":"Design/Salon.md"}'),r={name:"Design/Salon.md"},n=o('

技术沙龙

微信小游戏技术沙龙分享材料2023

https://docs.qq.com/pdf/DSVdvRHh6elZRdGZu

',3),s=[n];function _(c,d,l,i,h,p){return t(),a("div",null,s)}const u=e(r,[["render",_]]);export{m as __pageData,u as default}; diff --git a/assets/Design_Salon.md.BzNSLcNw.lean.js b/assets/Design_Salon.md.BzNSLcNw.lean.js new file mode 100644 index 00000000..d83bf527 --- /dev/null +++ b/assets/Design_Salon.md.BzNSLcNw.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as t,a4 as o}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"技术沙龙","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Salon.md","filePath":"Design/Salon.md"}'),r={name:"Design/Salon.md"},n=o("",3),s=[n];function _(c,d,l,i,h,p){return t(),a("div",null,s)}const u=e(r,[["render",_]]);export{m as __pageData,u as default}; diff --git a/assets/Design_ShowCase.md.DonZUX3q.js b/assets/Design_ShowCase.md.DonZUX3q.js new file mode 100644 index 00000000..e91e5982 --- /dev/null +++ b/assets/Design_ShowCase.md.DonZUX3q.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/showcase25.C-ERrYO-.js";import{_ as e,c as t,o as s,a4 as i}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/showcase45.CJUw74WU.png",o="/minigame-unity-webgl-transform/assets/showcase47.DboLTkit.png",n="/minigame-unity-webgl-transform/assets/showcase23.DnIByHA1.png",h="/minigame-unity-webgl-transform/assets/showcase35.zELPKZNw.jpeg",m="/minigame-unity-webgl-transform/assets/showcase41.9V2U7_05.jpeg",c="/minigame-unity-webgl-transform/assets/showcase36.CEaMVzaY.jpeg",l="/minigame-unity-webgl-transform/assets/showcase37.R-rKrZ15.jpeg",d="/minigame-unity-webgl-transform/assets/showcase38.BKdA-XtE.jpeg",g="/minigame-unity-webgl-transform/assets/showcase8.B0rkzu4v.png",p="/minigame-unity-webgl-transform/assets/showcase42.-UTNgrg5.jpeg",u="/minigame-unity-webgl-transform/assets/showcase26.MXwOeujv.png",_="/minigame-unity-webgl-transform/assets/showcase24.CPjVEBLQ.png",b="/minigame-unity-webgl-transform/assets/showcase39.BdJRJUTr.jpeg",w="/minigame-unity-webgl-transform/assets/showcase40.CU3rTbh5.jpeg",f="/minigame-unity-webgl-transform/assets/showcase43.D25VoWLG.jpeg",q="/minigame-unity-webgl-transform/assets/showcase44.O3fT7nY7.jpeg",L=JSON.parse('{"title":"转换案例","description":"","frontmatter":{},"headers":[],"relativePath":"Design/ShowCase.md","filePath":"Design/ShowCase.md"}'),k={name:"Design/ShowCase.md"},P=i('

转换案例

文档为使用Unity WebGL适配小游戏方案的部分上线游戏。

转换案例目的是分享学习,若作者认为不适合分享,请联系联系我们删除。 如开发者希望分享案例,也可通过联系我们添加。

无尽冬日

SLG品类,探索冻土,重建家园

九梦仙域

重度MMO品类,仙侠为题材,主要讲述在仙域大陆上,玩家扮演一个攀星阁学艺有成,不断提升自身,立志阻挡魔族入侵的游戏。

地铁跑酷

超好玩的3D跑酷手游!简单的上手操作,丰富的游戏画面,众多的城市场景,让你爱不释手!

谜题大陆

一款独具创新的魔幻三消策略小游戏,神奇的消除战争之旅!带你探索不一样的魔幻体验!

三国吧兄弟

鱼吃鱼

剑心吟

重度MMO品类

巨兽战场

重度SLG品类, 3D恐龙自由捕捉

小小蚁国

2023年度热门休闲小程序《小小蚁国》,建立你的地下王国!

翡翠大师

模拟经营游戏,玩家将体验到富有风险的翡翠原石选石过程,通过切石,设计,抛光的流程获得精美的翡翠雕刻成品,让自己的翡翠珍宝展馆发展壮大,熠熠生辉;在得到成就感的同时收获相关的翡翠知识。

超能世界

大侠不哭

喜欢武侠世界,曾梦想惩恶扬善、和志同道合的伙伴携手闯仗剑走天涯!

我叫MT2

由乐动卓越研发的精美3D手游,延续了传统《我叫MT》的经典特色。钓鱼挖矿,外域探险玩法都将为您呈现独一无二的掌中魔幻世界!

葫芦娃大作战

大圣顶住

银河战舰

守护球球

',47),x=[P];function y(T,j,C,D,S,M){return s(),t("div",null,x)}const U=e(k,[["render",y]]);export{L as __pageData,U as default}; diff --git a/assets/Design_ShowCase.md.DonZUX3q.lean.js b/assets/Design_ShowCase.md.DonZUX3q.lean.js new file mode 100644 index 00000000..d59c3080 --- /dev/null +++ b/assets/Design_ShowCase.md.DonZUX3q.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/showcase25.C-ERrYO-.js";import{_ as e,c as t,o as s,a4 as i}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/showcase45.CJUw74WU.png",o="/minigame-unity-webgl-transform/assets/showcase47.DboLTkit.png",n="/minigame-unity-webgl-transform/assets/showcase23.DnIByHA1.png",h="/minigame-unity-webgl-transform/assets/showcase35.zELPKZNw.jpeg",m="/minigame-unity-webgl-transform/assets/showcase41.9V2U7_05.jpeg",c="/minigame-unity-webgl-transform/assets/showcase36.CEaMVzaY.jpeg",l="/minigame-unity-webgl-transform/assets/showcase37.R-rKrZ15.jpeg",d="/minigame-unity-webgl-transform/assets/showcase38.BKdA-XtE.jpeg",g="/minigame-unity-webgl-transform/assets/showcase8.B0rkzu4v.png",p="/minigame-unity-webgl-transform/assets/showcase42.-UTNgrg5.jpeg",u="/minigame-unity-webgl-transform/assets/showcase26.MXwOeujv.png",_="/minigame-unity-webgl-transform/assets/showcase24.CPjVEBLQ.png",b="/minigame-unity-webgl-transform/assets/showcase39.BdJRJUTr.jpeg",w="/minigame-unity-webgl-transform/assets/showcase40.CU3rTbh5.jpeg",f="/minigame-unity-webgl-transform/assets/showcase43.D25VoWLG.jpeg",q="/minigame-unity-webgl-transform/assets/showcase44.O3fT7nY7.jpeg",L=JSON.parse('{"title":"转换案例","description":"","frontmatter":{},"headers":[],"relativePath":"Design/ShowCase.md","filePath":"Design/ShowCase.md"}'),k={name:"Design/ShowCase.md"},P=i("",47),x=[P];function y(T,j,C,D,S,M){return s(),t("div",null,x)}const U=e(k,[["render",y]]);export{L as __pageData,U as default}; diff --git a/assets/Design_Startup.md.__rV3b8S.js b/assets/Design_Startup.md.__rV3b8S.js new file mode 100644 index 00000000..cd15d82b --- /dev/null +++ b/assets/Design_Startup.md.__rV3b8S.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as i}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/launch1.eXb8FuyH.png",o="/minigame-unity-webgl-transform/assets/launch.DesekVa-.png",f=JSON.parse('{"title":"小游戏启动流程与时序","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Startup.md","filePath":"Design/Startup.md"}'),n={name:"Design/Startup.md"},s=i('

小游戏启动流程与时序

启动加载时序

Unity WebGL转换的小游戏主要依靠Unity Loader进行初始化,典型的流程如下图所示:

Unity Loader工作流程

关键过程:

  1. 启动准备阶段有两个处理分支:资源与代码分包处理,两者并行。
  2. 资源(data)处理:下载、解压并保持在内存,资源包括:构建场景及依赖、Resource目录所有资源、Unity默认内建资源
  3. 代码分包(wasm.code.br)处理:下载代码分包,解压到内存、编译与实例化
  4. 完成准备阶段后进入Unity引擎初始化与首场景加载

QA:

  1. 有哪些文件需要放CDN服务器? 首资源包:webgl/ProjectName.data.unityweb.bin.txt 资源分包:Adressable/AssetsBundle生成的文件

  2. 资源(data)或资源包是否需每次下载? 为加快二次启动,默认loader再次启动时资源(首包资源或资源分包)将直接使用本地缓存。如需手动删除缓存可在真机中小游戏下拉历史栏将小游戏删除。

',9),l=[s];function d(c,_,h,p,u,m){return t(),e("div",null,l)}const g=a(n,[["render",d]]);export{f as __pageData,g as default}; diff --git a/assets/Design_Startup.md.__rV3b8S.lean.js b/assets/Design_Startup.md.__rV3b8S.lean.js new file mode 100644 index 00000000..83296cc2 --- /dev/null +++ b/assets/Design_Startup.md.__rV3b8S.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as i}from"./chunks/framework.Br2U662V.js";const r="/minigame-unity-webgl-transform/assets/launch1.eXb8FuyH.png",o="/minigame-unity-webgl-transform/assets/launch.DesekVa-.png",f=JSON.parse('{"title":"小游戏启动流程与时序","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Startup.md","filePath":"Design/Startup.md"}'),n={name:"Design/Startup.md"},s=i("",9),l=[s];function d(c,_,h,p,u,m){return t(),e("div",null,l)}const g=a(n,[["render",d]]);export{f as __pageData,g as default}; diff --git a/assets/Design_StartupOptimization.md.DHwW9GTU.js b/assets/Design_StartupOptimization.md.DHwW9GTU.js new file mode 100644 index 00000000..9ea79c7e --- /dev/null +++ b/assets/Design_StartupOptimization.md.DHwW9GTU.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as i}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/startupop1.BD5F2llA.png",r="/minigame-unity-webgl-transform/assets/startupop2.ClyZL3O9.png",f=JSON.parse('{"title":"提升Unity WebGL游戏启动速度","description":"","frontmatter":{},"headers":[],"relativePath":"Design/StartupOptimization.md","filePath":"Design/StartupOptimization.md"}'),s={name:"Design/StartupOptimization.md"},o=i('

提升Unity WebGL游戏启动速度

一、 为什么要做启动优化

1.1 小游戏与手游APP的启动差异

微信小游戏具有“即开即用“的特性,手游APP则往往需要较长时间的下载。小游戏玩家对于启动时长更为敏感,因此过长的启动时间将导致用户显著流失。

1.2 优化的目标与标准

目前普通小游戏普遍启动时间为7~10s,而如果不经优化的Unity WebGL游戏启动会是该时间的2-3倍以上。我们建议开发者将启动优化作为上线前最为重要的事项。

二、分析小游戏启动速度

2.1. 查看启动耗时

通过修改unity-namespace.js中hideTimeLogModal为false,显示timelog开发者可以看到小游戏目前的启动首屏时长:

要知道各个阶段的含义,我们必要理解启动流程

小游戏启动主要由三部分影响:

  1. 首包资源下载
  2. WASM代码下载和编译
  3. 引擎初始化与开发者首帧逻辑

建议首屏启动时间控制在5~10s甚至更短

2.2 分阶段耗时

2.2.1 首资源包下载与体积

首包资源(webgl/Build目录下的data文件)主要有以下组成:

可使用AssetStudio查看文件内的所有资源。

首次下载或更新首资源包时,需要在小游戏的启动前期下载,因此文件大小极为影响游戏的启动速度。

  1. 网络条件绝大部分为wifi或4G(另,微信广告可指定网络条件)
  2. 玩家平均下载速度约2MB/s
  3. 微信用户存在不少<300KB/s的低网速玩家
  4. 务必对首资源包压缩: 转换面板勾选“压缩首资源包” 或 CDN管理后端针对首资源包(后缀.txt)“开启gzip/br压缩“
  5. 中文显示需要自定义字体,打包在首资源包或Bundle;请尽量使用2~3MB以内的精简字体以免影响游戏启动速度

建议: 务必对首资源包进行压缩传输,使用微信开发者工具的network标签确认传输量,网络传输大小应控制在3~5MB

2.2.2 WASM代码下载和编译

WASM分包的大小会直接影响代码下载时长以及程序初始化编译的时间,关于WASM代码对启动速度的影响,开发者需要注意:

  1. 转换工具会将Unity WebGL包自动进行br压缩(压缩至原code包的20%)
  2. WASM代码下载与首包资源并行下载,因此占用下载带宽
  3. WASM编译需要CPU资源,对于低端机来说时间依然可观

我们建议原始代码包(webgl/Build目录下的code文件)不超过30MB, 建议开发者勾选"Strip Engine Code"并设置"Managed Stripping Level"为High。同时,强烈建议开发者可以使用代码分包工具将代码包减少到原始尺寸的到1/3。如果使用Unity2021以上版本,可更改PlayerSettings面板IL2CPP选项为更小尺寸(SIZE)以减少函数量。

2.2.3 引擎初始化与开发者首帧逻辑

在timelog中呈现的首场景耗时即为引擎初始化与开发者首帧逻辑,关于该阶段耗时,开发者需要注意的是:

  1. MonoBehaviour脚本的首帧Start/Awake应足够少逻辑,优先将画面呈现
  2. 初始场景不宜过大,通常呈现Splah场景即可
  3. 初始场景中需要后续主场景或配置加载时可采取分帧策略,切勿在Start/Awake阻塞。
  4. 对于计算耗时 请使用Android CPU Profiler性能调优分析每一帧的耗时部分。

我们建议开发者使用预下载功能,该功能可以利用此阶段的网络空闲期进行资源下载。

2.2.4 游戏内资源按需加载

前面我们提到开发者需要将资源从首包分离以较少首屏加载时间,同理,而对于其余的资源开发者最好使用按需加载的方式进行加载,减少玩家进行核心玩法的等待时间。 优化可参考 使用Addressable Assets SystemAssetBundle进行资源按需加载。

2.3 优化总览

我们总结下启动时序以及开发者、平台提升启动性能的优化事项:

三、常用启动优化技巧

当分析出小游戏需要进行启动优化时,请继续阅读:

四、常用启动优化工具

4.1. AssetStudio(推荐)

https://github.com/Perfare/AssetStudio

一款开源的资源查看工具,可以检查data首包以及AssetsBundle(或新Addressable)的资源内容,对于分析打包的资源正确性和冗余具有很好的帮助。

4.2 BuildReportTool(推荐)

https://assetstore.unity.com/packages/tools/utilities/build-report-tool-8162?locale=zh-CN

很好的前端用于查看Unity编译信息,BRT显示了编译时包括的每个资源占用的存储空间以及未使用资源情况。

4.3 Asset Hunter

https://assetstore.unity.com/packages/tools/utilities/asset-hunter-pro-135296

资源清理插件,可将项目中无用资源清理

4.4 Unity Addressable Assets System

https://docs.unity3d.com/Packages/com.unity.addressables@1.16/manual/index.html Unity全新资源管理流程

',49),n=[o];function h(d,u,p,c,m,b){return t(),e("div",null,n)}const g=a(s,[["render",h]]);export{f as __pageData,g as default}; diff --git a/assets/Design_StartupOptimization.md.DHwW9GTU.lean.js b/assets/Design_StartupOptimization.md.DHwW9GTU.lean.js new file mode 100644 index 00000000..129a5696 --- /dev/null +++ b/assets/Design_StartupOptimization.md.DHwW9GTU.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as i}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/startupop1.BD5F2llA.png",r="/minigame-unity-webgl-transform/assets/startupop2.ClyZL3O9.png",f=JSON.parse('{"title":"提升Unity WebGL游戏启动速度","description":"","frontmatter":{},"headers":[],"relativePath":"Design/StartupOptimization.md","filePath":"Design/StartupOptimization.md"}'),s={name:"Design/StartupOptimization.md"},o=i("",49),n=[o];function h(d,u,p,c,m,b){return t(),e("div",null,n)}const g=a(s,[["render",h]]);export{f as __pageData,g as default}; diff --git a/assets/Design_Summary.md.C5Wmwk6F.js b/assets/Design_Summary.md.C5Wmwk6F.js new file mode 100644 index 00000000..dac63686 --- /dev/null +++ b/assets/Design_Summary.md.C5Wmwk6F.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,a4 as r}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/summary1.B7mzdmu-.png",g=JSON.parse('{"title":"Unity WebGL小游戏适配方案概述","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Summary.md","filePath":"Design/Summary.md"}'),i={name:"Design/Summary.md"},s=r('

Unity WebGL小游戏适配方案概述

一、技术原理

Unity的BuildTarget支持WebGL平台,WebGL导出包是基于WebAssembly技术运行在浏览器环境。 为了能让导出包运行在微信小游戏环境,我们提供了以下支持:

二、接入流程

接入流程请参考文档Unity WebGL微信小游戏转换指南

三、参考资料

  1. https://emscripten.org/
  2. https://docs.unity3d.com/Manual/webgl-gettingstarted.html
  3. https://forum.unity.com/forums/webgl.84/
  4. http://webassembly.org.cn/getting-started/developers-guide/
  5. https://developer.mozilla.org/zh-CN/docs/WebAssembly/C_to_wasm
',9),o=[s];function n(m,h,d,c,b,u){return a(),t("div",null,o)}const p=e(i,[["render",n]]);export{g as __pageData,p as default}; diff --git a/assets/Design_Summary.md.C5Wmwk6F.lean.js b/assets/Design_Summary.md.C5Wmwk6F.lean.js new file mode 100644 index 00000000..2b9a0560 --- /dev/null +++ b/assets/Design_Summary.md.C5Wmwk6F.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,a4 as r}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/summary1.B7mzdmu-.png",g=JSON.parse('{"title":"Unity WebGL小游戏适配方案概述","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Summary.md","filePath":"Design/Summary.md"}'),i={name:"Design/Summary.md"},s=r("",9),o=[s];function n(m,h,d,c,b,u){return a(),t("div",null,o)}const p=e(i,[["render",n]]);export{g as __pageData,p as default}; diff --git a/assets/Design_Symbol.md.DCwyi1Dw.js b/assets/Design_Symbol.md.DCwyi1Dw.js new file mode 100644 index 00000000..50a24064 --- /dev/null +++ b/assets/Design_Symbol.md.DCwyi1Dw.js @@ -0,0 +1,5 @@ +import{_ as a,c as s,o as e,a4 as t}from"./chunks/framework.Br2U662V.js";const _=JSON.parse('{"title":"Symbol 相关","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Symbol.md","filePath":"Design/Symbol.md"}'),n={name:"Design/Symbol.md"},o=t(`

Symbol 相关

Tool

开发者工具或者线上打印出来的堆栈,一般都是 wasm 函数 id,需要通过 symbol 映射到函数名,才能用于定位问题

这里提供了一个小工具用来替换函数 id,用法如下:

比如以下这段堆栈

at Object.WXUncaughtException (https://usr/game.js:108:1264)
+    at abort (https://usr/game.js:593:247583)
+    at j88421 (wasm-function[67190]:0x13a062b)
+    at j88421 (wasm-function[44572]:0x801bd1)
+    at j23511 (wasm-function[9866]:0x432503)

将这段内容保存到文件,和 symbol 文件一起传给工具处理

node tools/rewrite_exception_symbol.js exception.txt webgl.wasm.symbols.unityweb

symbol 文件一般会自动生成在 minigame 目录

Unity 2021 的引擎暂时还不支持导出 symbol,因此需要手动跑工具生成,导出插件导出到 webgl 时的 console 信息有说明要如何操作

`,10),p=[o];function l(i,c,r,d,m,b){return e(),s("div",null,p)}const u=a(n,[["render",l]]);export{_ as __pageData,u as default}; diff --git a/assets/Design_Symbol.md.DCwyi1Dw.lean.js b/assets/Design_Symbol.md.DCwyi1Dw.lean.js new file mode 100644 index 00000000..e9afba2d --- /dev/null +++ b/assets/Design_Symbol.md.DCwyi1Dw.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as e,a4 as t}from"./chunks/framework.Br2U662V.js";const _=JSON.parse('{"title":"Symbol 相关","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Symbol.md","filePath":"Design/Symbol.md"}'),n={name:"Design/Symbol.md"},o=t("",10),p=[o];function l(i,c,r,d,m,b){return e(),s("div",null,p)}const u=a(n,[["render",l]]);export{_ as __pageData,u as default}; diff --git a/assets/Design_Transform.md.x98sGhu_.js b/assets/Design_Transform.md.x98sGhu_.js new file mode 100644 index 00000000..0ebdc1ff --- /dev/null +++ b/assets/Design_Transform.md.x98sGhu_.js @@ -0,0 +1,36 @@ +import{_ as a}from"./chunks/mp_addplugin.pe280tQx.js";import{_ as s,c as n,o as e,a4 as i}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/scene.lhTRWbUv.png",p="/minigame-unity-webgl-transform/assets/export.CQlpBdYZ.png",t="/minigame-unity-webgl-transform/assets/devtools_preview.BlOHG4Jk.png",o="/minigame-unity-webgl-transform/assets/addPlugin.wW8f1Te-.png",r="/minigame-unity-webgl-transform/assets/auth_plugin.DqkcQvPd.png",C=JSON.parse('{"title":"转换工具导出微信小游戏","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Transform.md","filePath":"Design/Transform.md"}'),d={name:"Design/Transform.md"},c=i('

转换工具导出微信小游戏

一、Unity导出WebGL

添加需要导出的scene

建议仅勾选Loading场景,后续场景使用AssetsBundle/Addressable进行按需加载。

二、适配小游戏

2.1 转换小游戏

顶部菜单栏 点击 微信小游戏 -> 转换小游戏, 填写相应参数,点击生成并转换按钮 ,等待转换完成。

其中:

  1. 必须
  1. 可选

2.2 了解转换后目录结构

在转换完成后,会在导出路径下生成如下目录

bash
.
+├── minigame
+└── webgl

2.3 资源部署

转换完成后,参照小游戏资源部署章节进行资源部署,并了解启动Loader在加载资源时的缓存逻辑。

2.4 小游戏预览

  1. 下载小游戏开发者工具 微信开发者工具

需要下载,稳定版 Stable Build,非小游戏版!

  1. 导入项目 参考小游戏快速开始

导入转换后的minigame目录

  1. 工具预览

注意:

项目使用了小游戏Unity适配插件,若小游戏是第一次使用本插件,在开发者工具会报错提示插件未授权

请前往mp后台-能力地图-生产提效包-快适配,开通使用

  1. 真机预览 点击预览,扫码二维码预览即可。

请不要使用真机调试!! 请不要使用真机调试!! 请不要使用真机调试!!

三、使用脚本集成到自己的构建系统

如果你希望将导出插件集成到自己的发布流程,想脚本调用的话,可修改 Assets/WX-WASM-SDK/Editor/MiniGameConfig.asset配置,然后调用WXEditorWindow 的 DoExport方法导出小游戏

var win = new WXEditorWindow();
+win.DoExport();

MiniGameConfig.asset支持的配置

与转换面板配置有对应关系的配置项

// 基本设置
+Appid -- 小游戏appid
+CDN -- 游戏资源CDN
+projectName -- 小游戏项目名
+Orientation -- 游戏方向
+maxStorage -- 最大内存,修改此值需要联系研发助手开通权限,否则无效
+DST -- 导出路径
+// 启动Loader设置
+bgImageSrc -- 背景图/封面图
+VideoUrl -- 加载阶段视频URL
+assetLoadType -- 首包资源加载方式
+bundleExcludeExtensions -- 不自动缓存文件类型
+bundleHashLength -- bundle名中hash长度
+// 预下载
+preloadFiles -- 预下载文件列表,用;分隔
+// SDK功能
+UseFriendRelation -- 使用好友关系链
+// 调试编译选项
+DevelopBuild -- Development Build
+AutoProfile -- Autoconnect Profiler
+ScriptOnly -- Scripts Only Build
+profilingFuncs -- Profiling Funcs
+Webgl2 -- WebGL2.0
+DeleteStreamingAssets -- DeleteStreamingAssets

不常用配置

使用说明参考Loader配置

// 资源加载与缓存
+dataFileSubPrefix: 配置首包资源加载路径
+bundlePathIdentifier: URL中包含特定标识符时需要自动缓存,用;分隔
+defaultReleaseSize: 达到缓存上限时默认额外清理的存储大小,用;分隔
+needCacheTextures: 是否开启纹理缓存
+texturesPath: 纹理存储路径
+texturesHashLength: 纹理中hash长度
+// 启动界面
+loadingBarWidth: 加载进度条宽度
+HideAfterCallMain: 是否初始化完成立即隐藏封面

四、常见问题

请查阅技术常见问题QA

`,45),h=[c];function m(g,u,b,f,_,k){return e(),n("div",null,h)}const x=s(d,[["render",m]]);export{C as __pageData,x as default}; diff --git a/assets/Design_Transform.md.x98sGhu_.lean.js b/assets/Design_Transform.md.x98sGhu_.lean.js new file mode 100644 index 00000000..bea13854 --- /dev/null +++ b/assets/Design_Transform.md.x98sGhu_.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/mp_addplugin.pe280tQx.js";import{_ as s,c as n,o as e,a4 as i}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/scene.lhTRWbUv.png",p="/minigame-unity-webgl-transform/assets/export.CQlpBdYZ.png",t="/minigame-unity-webgl-transform/assets/devtools_preview.BlOHG4Jk.png",o="/minigame-unity-webgl-transform/assets/addPlugin.wW8f1Te-.png",r="/minigame-unity-webgl-transform/assets/auth_plugin.DqkcQvPd.png",C=JSON.parse('{"title":"转换工具导出微信小游戏","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Transform.md","filePath":"Design/Transform.md"}'),d={name:"Design/Transform.md"},c=i("",45),h=[c];function m(g,u,b,f,_,k){return e(),n("div",null,h)}const x=s(d,[["render",m]]);export{C as __pageData,x as default}; diff --git a/assets/Design_UnityProfiler.md.BWh3E1Ho.js b/assets/Design_UnityProfiler.md.BWh3E1Ho.js new file mode 100644 index 00000000..3f31a1ef --- /dev/null +++ b/assets/Design_UnityProfiler.md.BWh3E1Ho.js @@ -0,0 +1,6 @@ +import{_ as i,a as o,b as t}from"./chunks/profile3.CffCZqR8.js";import{_ as e,c as n,o as s,a4 as l}from"./chunks/framework.Br2U662V.js";const h=JSON.parse('{"title":"使用Unity Profiler性能调优","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UnityProfiler.md","filePath":"Design/UnityProfiler.md"}'),r={name:"Design/UnityProfiler.md"},a=l('

使用Unity Profiler性能调优

  1. 导出选项时勾选"Development Build"与"Autoconnect Profiler"
  1. 打开Unity-Window-Analysis-Profile窗口

Unity将自启动监听端口34999等待调试链接,对于WebGL版本会启动websockify.js(用于websocket转发)。 此时,导出的WebGL游戏在浏览器时能自动连接到Unity Profiler。

  1. 微信开发者工具小游戏Profile 使用转换脚本导出微信小游戏包并启动小游戏,微信小游戏将自动连接到Unity Profiler

  2. 调整UnityProfiler IP/端口

网页WebGL/小游戏启动后将通过"ws://ip:port"自动连接到“Unity Profiler”, 此地址默认为编译机器的。如果无法连接请查看微信开发者工具Network页签对应的ws链接是否正常可达。 如需手工调整IP、端口可通修改webgl.wasm.framework.unityweb.js

     if(port == 54998) 
+     {
+        url = "ws://127.0.0.1:54998"
+     }
+     ws = new WebSocketConstructor(url, opts);
+     ws.binaryType = "arraybuffer";

重启UnityProfiler监听,可通过在命令行执行引擎自带Node启动websocketfy.js:

(其中$UNITY_PATH为对应Unity版本的安装目录)

  1. 注意事项

附录:

`,16),p=[a];function c(u,d,f,y,P,_){return s(),n("div",null,p)}const U=e(r,[["render",c]]);export{h as __pageData,U as default}; diff --git a/assets/Design_UnityProfiler.md.BWh3E1Ho.lean.js b/assets/Design_UnityProfiler.md.BWh3E1Ho.lean.js new file mode 100644 index 00000000..4ef2a78c --- /dev/null +++ b/assets/Design_UnityProfiler.md.BWh3E1Ho.lean.js @@ -0,0 +1 @@ +import{_ as i,a as o,b as t}from"./chunks/profile3.CffCZqR8.js";import{_ as e,c as n,o as s,a4 as l}from"./chunks/framework.Br2U662V.js";const h=JSON.parse('{"title":"使用Unity Profiler性能调优","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UnityProfiler.md","filePath":"Design/UnityProfiler.md"}'),r={name:"Design/UnityProfiler.md"},a=l("",16),p=[a];function c(u,d,f,y,P,_){return s(),n("div",null,p)}const U=e(r,[["render",c]]);export{h as __pageData,U as default}; diff --git a/assets/Design_UnityVersion.md.BsPD-TKi.js b/assets/Design_UnityVersion.md.BsPD-TKi.js new file mode 100644 index 00000000..e082eb56 --- /dev/null +++ b/assets/Design_UnityVersion.md.BsPD-TKi.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as e,a4 as d}from"./chunks/framework.Br2U662V.js";const y=JSON.parse('{"title":"推荐引擎版本","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UnityVersion.md","filePath":"Design/UnityVersion.md"}'),i={name:"Design/UnityVersion.md"},r=d('

推荐引擎版本

版本兼容性

Unity WebGL微信小游戏适配方案是以WebAssembly为基础,具有非常宽泛的兼容性,转换插件理论上支持的Unity版本涵盖:2018、2019、2020、2021、2022等

但并非每个小版本我们都有足够的验证,我们会根据验证情况以及大量转换游戏反馈的情况给出引擎版本建议。

推荐版本

引擎版本压缩纹理/音频编译体积已验证小版本其他
2018仅DXT,不支持ETC2/ASTC100%2018.4.25~2018.4.34不支持设置dpr分辨率
2019仅DXT,不支持ETC2/ASTC100%2019.4.28~2019.4.35---
2019 InstantGame全支持DXT/ETC2/ASTC100%2019.4.29增加WebGL移动端压缩纹理、AutoStreaming等支持
2020DXT/ETC2,不支持ASTC100%2020.3.1~2020.3.36---
2021全支持DXT/ETC2/ASTC80%2021.2.11~2021.3.33---
2021 InstantGame全支持DXT/ETC2/ASTC80%2021.2.5增强运行时性能、UnityProfiler以及更小的包体
2022(推荐)全支持DXT/ETC2/ASTC80%2022.3.1~2022.3.14---
团结引擎(推荐)全支持DXT/ETC2/ASTC60~80%---基于2022.3.2, 但包体、内存更多优化,支持FrameDebugger调试

备注:

Unity InstantGame/团结引擎获取

中国特供版下载地址

QA

  1. 项目使用2017/Unity5等早期版本,应该使用哪个引擎版本转换?
  1. 项目在使用2018-2020版本,是否可以直接使用?
  1. Unity InstantGame/团结引擎相对于普通版本有特别之处?
  1. 版本是越新越好吗?
',19),n=[r];function l(o,s,h,m,c,u){return e(),a("div",null,n)}const _=t(i,[["render",l]]);export{y as __pageData,_ as default}; diff --git a/assets/Design_UnityVersion.md.BsPD-TKi.lean.js b/assets/Design_UnityVersion.md.BsPD-TKi.lean.js new file mode 100644 index 00000000..6800ab42 --- /dev/null +++ b/assets/Design_UnityVersion.md.BsPD-TKi.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as e,a4 as d}from"./chunks/framework.Br2U662V.js";const y=JSON.parse('{"title":"推荐引擎版本","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UnityVersion.md","filePath":"Design/UnityVersion.md"}'),i={name:"Design/UnityVersion.md"},r=d("",19),n=[r];function l(o,s,h,m,c,u){return e(),a("div",null,n)}const _=t(i,[["render",l]]);export{y as __pageData,_ as default}; diff --git a/assets/Design_Update.md.gfZSJS5M.js b/assets/Design_Update.md.gfZSJS5M.js new file mode 100644 index 00000000..fce3a2de --- /dev/null +++ b/assets/Design_Update.md.gfZSJS5M.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as r}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/update-dialog.6NED8STH.png",g=JSON.parse('{"title":"版本更新","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Update.md","filePath":"Design/Update.md"}'),n={name:"Design/Update.md"},i=r('

版本更新

代码更新

请阅读文档,了解小游戏的更新机制

更新策略:

1. 静默更新(默认方式)

这种形式和APP版本类似,比如应用市场自动更新。游戏发新版本后,在打开小游戏前,会静默更新到最新版本。 但小游戏包体的更新机制和APP不同,开发者在管理后台发布新版本的小游戏之后,无法立刻影响到所有现网用户,如果某个用户本地有小程序的历史版本,此时打开的可能还是旧版本,最差情况下,也在发布之后 24 小时之内下发新版本信息到用户

缺点:更新不及时,依然可能体验到旧版本内容,需要注意保证旧版本资源可访问。

适合于对版本一致性要求不高的游戏使用

2. 强制更新

2.1 实时检测更新(UpdateManager)

戏运行期间检查是否有新版本,当新版本可用后,提示用户重启更新

转换插件有提供配置来自动使用这项能力,通过勾选【导出面板-更多配置项-Project Conf】中的配置needCheckUpdate

缺点:由于重启后,可能涉及资源下载,可能导致用户流失。

2.2 设置最低可用版本

资源更新

请查看资源部署-资源更新说明

',18),d=[i];function s(l,h,c,p,_,u){return t(),e("div",null,d)}const b=a(n,[["render",s]]);export{g as __pageData,b as default}; diff --git a/assets/Design_Update.md.gfZSJS5M.lean.js b/assets/Design_Update.md.gfZSJS5M.lean.js new file mode 100644 index 00000000..bcd09acb --- /dev/null +++ b/assets/Design_Update.md.gfZSJS5M.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,a4 as r}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/update-dialog.6NED8STH.png",g=JSON.parse('{"title":"版本更新","description":"","frontmatter":{},"headers":[],"relativePath":"Design/Update.md","filePath":"Design/Update.md"}'),n={name:"Design/Update.md"},i=r("",18),d=[i];function s(l,h,c,p,_,u){return t(),e("div",null,d)}const b=a(n,[["render",s]]);export{g as __pageData,b as default}; diff --git a/assets/Design_UsingAddressable.md.758Zr0tY.js b/assets/Design_UsingAddressable.md.758Zr0tY.js new file mode 100644 index 00000000..e3f8b3b0 --- /dev/null +++ b/assets/Design_UsingAddressable.md.758Zr0tY.js @@ -0,0 +1,74 @@ +import{_ as a,c as i,a as e,a4 as s,o as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/addressable7.D5VA3cAj.png",l="/minigame-unity-webgl-transform/assets/wxassetbundleprovider1.BrJzXZd7.png",p="/minigame-unity-webgl-transform/assets/wxassetbundleprovider2.DIWHTi9X.png",h="/minigame-unity-webgl-transform/assets/addressable2.Dk3Ey3UQ.png",r="/minigame-unity-webgl-transform/assets/addressable5.CfIJPhUo.png",d="/minigame-unity-webgl-transform/assets/addressable10.CVteO2U4.png",k="/minigame-unity-webgl-transform/assets/addressable9.BGoeNYVl.png",o="/minigame-unity-webgl-transform/assets/addressable3.D_qvXfAd.png",C=JSON.parse('{"title":"使用Addressable Assets System进行资源按需加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingAddressable.md","filePath":"Design/UsingAddressable.md"}'),c={name:"Design/UsingAddressable.md"},g=s('

使用Addressable Assets System进行资源按需加载

一、概述

对于Unity WebGL转换的小游戏启动耗时,资源下载通常是贡献最大的部分。这是由于手游APP往往很少针对首包资源进行特殊优化。 那么,接下来的问题是:小游戏中多大的首包资源合适? 剩余的游戏资源如何加载? 在此,我们建议得优化原则是:

  1. 首包资源量不超过5M
  2. 资源按需延迟加载,拆分得尽量细

本文介绍如何使用Unity新的资源管理流程Addressable Assets System进行资源的按需加载。

附可参考的项目: https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/tree/main/Demo/Addressable

二、Addressable在小游戏中的应用

2.1 什么是Addressable Assets System

Unity在2018版本中推出了Addressable Assets System(以下简称Addressable)的预览版本,并在2019的版本中已经成为正式版本,可以用于生产(仅表示发布时间,实际上大部分Unity版本都可正常使用)。 Addressable提供了以下能力:

低使用门槛:使用Addressable在开发前期就进入快速开发的阶段,使用任何你喜欢的资源管理技术,你都能快速的切换来Addressable系统中,几乎不需要修改代码。

依赖管理:Addressable系统不仅仅会帮你管理、加载你指定的内容,同时它会自动管理并加载好该内容的全部依赖。在所有的依赖加载完成,你的内容彻底可用时,它才会告诉你加载完成。

内存管理:Addressable不仅仅能记载资源,同时也能卸载资源。系统自动启用引用计数,并且有一个完善的Profiler帮助你指出潜在的内存问题。

内容打包:Addressable系统自动管理了所有复杂的依赖连接,所以即使资源移动了或是重新命名了,系统依然能够高效地找到准确的依赖进行打包。当你需要将打包的资源从本地移到服务器上面,Addressable系统也能轻松做到,几乎不需要任何代价。

2.2 相对于AssetsBundles的优势

Unity中资源按需加载也可以使用老的AssetBundle,然而使用AB需要做不少的工作:标识Asset、组织Bundle、编译、Load/Unload、依赖关系以及后期维护的复杂工作。新一代的Addressable正是对这些痛点做了不少改进,开发者只需要将Asset设置为addressable然后加载即可,[功能强大并且学习曲线变得平滑] (https://docs.google.com/document/d/1hPLNLdrF0qAvjEJTpKf-cuO_d4FCV0H2cqBeP1Zo6mA/edit)。

2.3 在小游戏中使用Addressable Assets System

无论是Addressable还是AssetBundle在微信小游戏底层都使用XHR进行远程资源访问,并使用微信小游戏文件存储系统进行缓存。对于已有的游戏资源,如果我们需要尽量少的工作量去做到像H5游戏按需加载,使用Addressable是最佳做法。

2.4 使用WXAssetBundleProvider节省内存

WXAssetBundle可以减轻iOS的内存压力,对于使用Addressable的项目,需要替换Provider来使用WXAssetBundle。

  1. 下载WXAssetBundleProvider.cs,放到WX-WASM-SDK-V2/Runtime/目录下

  2. 导入插件后会有WXAssetBundleProvider.cs缺依赖的报错,需要给WX-WASM-SDK-V2/Runtime 增加 Unity.ResourceManager 的引用

  3. 进入AA的组设置修改Provider如下

  4. 重新导出 AA包 和 小游戏

三、启动优化与资源优化实战

3.1 从首包开始

首包资源应该只包含首屏所需资源,比如Splash界面以及对应文案。 首屏资源需要注意:

  1. 导出场景不要勾选任何其他场景
  2. 不要打包字体文件,字体往往压缩率很低。
  3. 通过Addressable检查Bultin分组,特别注意不要随意放置资源到Resources目录,该目录将无条件被打包到首包中。

通常,Unity首资源包的压缩率是比较高的,因为大多数Unity built资源是以文本形式存在。开发者应尽量减少首资源包压缩后大小,以zip压缩后体积为准,3M左右最佳,不应超过5M。

部署首资源包需要注意:

  1. 使用“小游戏分包”时,小游戏底层会自动进行压缩减少网络传输。
  2. 使用“CDN”时,务必在服务器对txt后缀开启“Brotli或gzip”。

3.2 资源按需加载

3.2.1 场景动态加载

如前所述,我们构建时仅选择了splash/loading场景,那么主场景(如大厅/战斗等)该如何加载?此时我们可以将每个场景单独作为Addressable分组,在用到的时候才下载该场景包。

使用Addressables.LoadSceneAsync可以动态加载场景与获取加载进度:

    IEnumerator LoadMain()
+    {
+        var handle = Addressables.LoadSceneAsync("Assets/RPGPP_LT/Scene/rpgpp_lt_scene_1.0.unity", LoadSceneMode.Single, true);
+        handle.Completed  += (obj) =>
+        {
+            Debug.LogWarning($"Load async scene complete{obj.Status}");
+        };
+
+        while (!handle.IsDone)
+        {
+            // 在此可使用handle.PercentComplete进行进度展示
+            yield return null;
+         }
+    }

选择分组,设置分组属性如下:

如果我们仅将场景作为分组,其中静态摆放的物件不单独设置为Addressable也会一并打包到场景所在bundle。那么,这是会产生一个问题:两个场景都使用同样资源是否产生冗余?答案是肯定的!! 那么,如何消除冗余呢?当我们Adressable面板的Tools-->Analyze进行分析时,可看到以下内容:

',37),E=s('

3.2.2 物件动态加载

除了静态场景外,我们还会经常动态实例化(Instantiate)或在内存中创建资源对象。比如:

C#
public class LoadAssetScript : MonoBehaviour
+{
+    public GameObject somePrefab;
+    private void Start()
+    {
+        Instantiate(somePrefab);
+    }
+}

然而,这样做有个非常严重的问题:Prefab本身以及依赖的所有资源需要在场景加载前完成。在小游戏环境,这意味着即使还没调用Instantiate,这部分资源就必须准备好,这会极大影响场景初始化速度

那么,如果我们希望把somePrefab以及它的依赖资源打包在Addressable分组进行按需下载应该如何做呢?答案是AssetReference。上述代码改写成:

public class LoadAssetScript : MonoBehaviour
+{
+    public AssetReference somePrefab;
+    private void Start()
+    {
+        somePrefab.InstantiateAsync().Completed += (obj) =>
+        {
+           // 加载完成回调
+        };
+    }
+}

或协程写法:

public class LoadAssetScript : MonoBehaviour
+{
+    public AssetReference somePrefab;
+    private IEnumerator spawnSomathing()
+    {
+        var hanle = somePrefab.InstantiateAsync();
+        while(!handle.IsDone) {yield return null;}
+         // 加载完成回调
+        var gameObject = hanle.Result;
+    }
+}

同时,对应的Prefab在editor中需设置为Addressable,并重新为somePrefab赋值。

3.3 小结

Unity WebGL转换的小游戏普遍存在首包资源较大的情况,而新Address提供了非常好的资源管理流程。我们建议开发者:

  1. 精简首场景,首包资源中确保只包含轻量的首屏以及依赖资源
  2. 延迟加载,避免业务逻辑需要全量资源的情况,设计上尽量按需加载
  3. 资源拆分,利用Addressable进行更灵活和细粒度的拆解
  4. 预加载,根据优先级设置需要预加载的分包,利用网络空闲期

四、如何优雅地异步加载

4.1 最基本的异步回调

C#
private void TextureHandle_Completed(AsyncOperationHandle<Texture2D> handle) {
+    if (handle.Status == AsyncOperationStatus.Succeeded) {
+        Texture2D result = handle.Result;
+        // The texture is ready for use.
+    }
+}
+
+void Start() {
+    AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAsset<Texture2D>("mytexture");
+    textureHandle.Completed += TextureHandle_Completed;
+}

4.2 使用协程

C#
public IEnumerator Start() {
+    AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
+
+    //if the handle is done, the yield return will still wait a frame, but we can skip that with an IsDone check
+    if(!handle.IsDone)
+        yield return handle;
+
+    if (handle.Status == AsyncOperationStatus.Succeeded) {
+        Texture2D texture = handle.Result;
+        // The texture is ready for use.
+        // ...
+    // Release the asset after its use:
+        Addressables.Release(handle);
+    }
+}

4.3 使用await

C#
public async Start() {
+    AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
+    await handle.Task;
+    // The task is complete. Be sure to check the Status is successful before storing the Result.
+}

五、旧系统资源改造

资源系统迁移可参考Unity官方文档Upgrading to the Addressables system

5.1 Resource改造

使用这种方式加载资源,通常需要再Asset或其子目录下创建Resources的文件夹,然后使用类似这种方式加载:

C#
       TextAsset text = Resources.Load<TextAsset>("MyConfig");

然而,Resources目录的内容都会被打包进首包资源,对于小游戏来说是不推荐使用的方式。 开发者在Addressable的default中能看到所有这些资源,我们需要将这些资源设置为“Addressable”,Unity将自动移动到“Resources_Moved”目录。 加载代码改写成:

C#
        var handle = Addressables.LoadAssetAsync<TextAsset>("MyConfig");
+        if(!handle.IsDone) yield return handle;
+         // 加载完成回调
+         if (handle.Status == AsyncOperationStatus.Succeeded) {
+            var gameObject = hanle.Result;
+         }

5.2 AssetsBundle迁移

当打开Addressables Groups时,Unity提供了将所有AssetsBundle迁移到Addressable Asset Groups的功能。

六、部署

6.1 Addressable编译与部署

默认情况下,当编译Addressable资源时会输出到Library/com.unity.addressables/,项目发布为WebGL或转换为小游戏时Unity会自动拷贝Bundle文件到最终的生成目录下。我们只需要将对应的StreammingAssets上传到对应的CDN服务器即可。

6.2 资源预下载

为了充分利用网络带宽,在网络空闲时可预下载游戏需要用到的AB包。详细配置请参考使用预下载功能

五、参考资料

  1. Addressable Asset System for Unity (Overview) https://docs.google.com/document/d/1hPLNLdrF0qAvjEJTpKf-cuO_d4FCV0H2cqBeP1Zo6mA/edit

  2. 官方Demo https://github.com/Unity-Technologies/Addressables-Sample

  3. 视频范例 https://drive.google.com/file/d/1w-Lh_jsD2VSHNvkzexJLSc6bA3gUQC8d/view

  4. uwa关于Addressable的介绍 https://blog.uwa4d.com/archives/USparkle_Addressable4.html

  5. Addressable与AssetBundle的对比 https://www.jianshu.com/p/8009c16fcab3

`,36);function u(b,y,A,m,F,_){return n(),i("div",null,[g,e(" 此时,我们应将这些冗余的内容单独进行设置为Addressable。而更为简单的做法是:选中“Check Duplicate Bundle Dependencies”,点击“Fixed Selected Rules”,工具会自动将冗余项逐个设置为Addressable。 "),E])}const v=a(c,[["render",u]]);export{C as __pageData,v as default}; diff --git a/assets/Design_UsingAddressable.md.758Zr0tY.lean.js b/assets/Design_UsingAddressable.md.758Zr0tY.lean.js new file mode 100644 index 00000000..e3a8562a --- /dev/null +++ b/assets/Design_UsingAddressable.md.758Zr0tY.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,a as e,a4 as s,o as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/addressable7.D5VA3cAj.png",l="/minigame-unity-webgl-transform/assets/wxassetbundleprovider1.BrJzXZd7.png",p="/minigame-unity-webgl-transform/assets/wxassetbundleprovider2.DIWHTi9X.png",h="/minigame-unity-webgl-transform/assets/addressable2.Dk3Ey3UQ.png",r="/minigame-unity-webgl-transform/assets/addressable5.CfIJPhUo.png",d="/minigame-unity-webgl-transform/assets/addressable10.CVteO2U4.png",k="/minigame-unity-webgl-transform/assets/addressable9.BGoeNYVl.png",o="/minigame-unity-webgl-transform/assets/addressable3.D_qvXfAd.png",C=JSON.parse('{"title":"使用Addressable Assets System进行资源按需加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingAddressable.md","filePath":"Design/UsingAddressable.md"}'),c={name:"Design/UsingAddressable.md"},g=s("",37),E=s("",36);function u(b,y,A,m,F,_){return n(),i("div",null,[g,e(" 此时,我们应将这些冗余的内容单独进行设置为Addressable。而更为简单的做法是:选中“Check Duplicate Bundle Dependencies”,点击“Fixed Selected Rules”,工具会自动将冗余项逐个设置为Addressable。 "),E])}const v=a(c,[["render",u]]);export{C as __pageData,v as default}; diff --git a/assets/Design_UsingAssetBundle.md.DHBD80cj.js b/assets/Design_UsingAssetBundle.md.DHBD80cj.js new file mode 100644 index 00000000..50c2237f --- /dev/null +++ b/assets/Design_UsingAssetBundle.md.DHBD80cj.js @@ -0,0 +1,46 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const e="/minigame-unity-webgl-transform/assets/wxassetbundle.DrADi2AS.png",l="/minigame-unity-webgl-transform/assets/normal-assetbundle-memory.Iz7sHvbP.png",t="/minigame-unity-webgl-transform/assets/assetbundle-unnormal-memory.CY0FXhT_.png",F=JSON.parse('{"title":"使用 AssetBundle 进行资源按需加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingAssetBundle.md","filePath":"Design/UsingAssetBundle.md"}'),h={name:"Design/UsingAssetBundle.md"},p=n(`

使用 AssetBundle 进行资源按需加载

阐述如何在小游戏环境对AssetBundle进行打包、加载和内存优化,同时推荐使用WXAssetBundle更自动化地节省内存。

一、AssetBundle使用

注意:小游戏环境不支持assetbundle本地加载

1.1 AssetBundle打包参数建议

c#
public static void Build()
+{
+    string dst = Application.streamingAssetsPath + "/AssetBundles";
+    if (!Directory.Exists(dst))
+    {
+        Directory.CreateDirectory(dst);
+    }
+    BuildPipeline.BuildAssetBundles(dst, BuildAssetBundleOptions.AppendHashToAssetBundleName | BuildAssetBundleOptions.ChunkBasedCompression | UnityEditor.BuildAssetBundleOptions.DisableWriteTypeTree | BuildAssetBundleOptions.None, BuildTarget.WebGL);
+}

打包bundle时,请使用如下参数

1.2 AssetBundle下载

从服务器下载bundle的方式主要以下两种:

二、小游戏与APP的AssetBundle缓存更新流程差异

小游戏因其平台特殊性,需要保证加载速度,因此我们在底层对bundle文件做了缓存,开发者无须自己实现缓存。

游戏逻辑还是按照未缓存需要从网络下载去编写,插件底层会判断是否已有缓存。若未缓存则缓存此bundle;若已缓存,则返回缓存文件,实际不会发起网络请求。

可参见资源缓存与淘汰

资源缓存与更新的不同,会导致APP与小游戏不同的加载流程

检查更新-->下载更新全量资源-->写入文件系统-->运行时LoadFromFile

打包ab时文件名带hash-->UnityWebRequest按需下载并使用资源

在业务侧看来:总是使用异步接口从远程下载并使用,底层资源的缓存与更新已由适配层自动完成,游戏不再直接读写文件系统。

三、更节省内存的WXAssetBundle

四、AssetBundle内存分析

4.1 切勿使用带Cache能力的线管接口

加载的bundle文件大小为5403162字节

bash
-rw-r--r--  1  Users  5403162  6 22 16:07 image1_751427a66d22b184c95342d556354150

通过加载前后snapshot来对比总内存变化

因此需要注意业务中不要使用已淘汰的WWW类,尤其WWW.LoadFromCacheOrDownload,当bundle数量多时,会浪费不少内存。

4.2 尽可能使用Unload

因此,最佳实践是业务应该尽可能早地使用ab.Unload(false),自行维护Asset的引用计数管理资源。

四、参考资料

  1. Introduction to Asset Bundles https://learn.unity.com/tutorial/introduction-to-asset-bundles#6028bab6edbc2a750bf5b8a7
  2. Unity WebGL Memory Optimization: Part Deux https://blog.kongregate.com/unity-webgl-memory-optimization-part-deux/
  3. Understanding Memory in Unity WebGL https://blog.unity.com/technology/understanding-memory-in-unity-webgl
  4. AssetBundle API https://docs.unity3d.com/2019.4/Documentation/ScriptReference/AssetBundle.html
',35),k=[p];function d(r,E,g,o,u,y){return a(),i("div",null,k)}const b=s(h,[["render",d]]);export{F as __pageData,b as default}; diff --git a/assets/Design_UsingAssetBundle.md.DHBD80cj.lean.js b/assets/Design_UsingAssetBundle.md.DHBD80cj.lean.js new file mode 100644 index 00000000..685bb82e --- /dev/null +++ b/assets/Design_UsingAssetBundle.md.DHBD80cj.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const e="/minigame-unity-webgl-transform/assets/wxassetbundle.DrADi2AS.png",l="/minigame-unity-webgl-transform/assets/normal-assetbundle-memory.Iz7sHvbP.png",t="/minigame-unity-webgl-transform/assets/assetbundle-unnormal-memory.CY0FXhT_.png",F=JSON.parse('{"title":"使用 AssetBundle 进行资源按需加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingAssetBundle.md","filePath":"Design/UsingAssetBundle.md"}'),h={name:"Design/UsingAssetBundle.md"},p=n("",35),k=[p];function d(r,E,g,o,u,y){return a(),i("div",null,k)}const b=s(h,[["render",d]]);export{F as __pageData,b as default}; diff --git a/assets/Design_UsingLoader.md.DBMrBC_O.js b/assets/Design_UsingLoader.md.DBMrBC_O.js new file mode 100644 index 00000000..b1c2ffe6 --- /dev/null +++ b/assets/Design_UsingLoader.md.DBMrBC_O.js @@ -0,0 +1,32 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const e="/minigame-unity-webgl-transform/assets/coverview_loading.BiGkOLi_.png",u=JSON.parse('{"title":"使用Loader进行游游戏加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingLoader.md","filePath":"Design/UsingLoader.md"}'),l={name:"Design/UsingLoader.md"},t=n(`

使用Loader进行游游戏加载

一、什么是Unity Loader?

Unity Loader是在微信小游戏环境加载Unity WebGL游戏的加载与适配器,使用微信小游戏插件技术开发,功能包括:

二、如何使用Unity Loader插件

生成微信小游戏项目时,转换工具会在game.json中声明:

json
"plugins": {
+    "UnityPlugin": {
+        "version": "major.minor.patch", // 可切换版本号
+        "provider": "wxe5a48f1ed5f544b7",
+        "contexts": [
+            {
+                "type": "isolatedContext"
+            }
+        ]
+    }
+}

这部分配置表示使用Unity Loader插件进行游戏加载,开发者无需手动修改

三、配置Unity Loader功能

3.1 资源下载

声明CDN地址

转换插件相关配置

CDN: cdn地址
+dataFileSubPrefix: 首包资源相对cdn地址的存放目录,默认首包资源放在cdn一级目录

通过接口修改

游戏存在备用CDN地址,可通过C#接口 WX.SetDataCDN 或js接口 GameGlobal.manager.setDataCDN 修改DATA_CDN配置

3.2 启动界面

由于Unity WebGL启动加载需要一定时间,因此需要使用视频或图片等内容作为过渡以留住玩家。Unity Loader默认使用视频+进度信息呈现,开发者可以自定义封面/视频,可参考启动Loader视频规范进行配置。

转换插件相关配置

bgImageSrc: 启动封面图;-- $BACKGROUND_IMAGE
+VideoUrl: 启动视频;-- $LOADING_VIDEO_URL
+HideAfterCallMain: 是否callmain完成后立即隐藏封面;-- $HIDE_AFTER_CALLMAIN
+loadingBarWidth: 加载进度条宽度;-- $LOADING_BAR_WIDTH

game.js配置

js
loadingPageConfig: {
+  // 背景图或背景视频,两者都填时,先展示背景图,视频可播放后,播放视频
+  backgroundImage: '$BACKGROUND_IMAGE', // 默认的背景图,可自行替换,支持本地图片和网络图片
+  backgroundVideo: '$LOADING_VIDEO_URL', // 视频url,需要开发者提供,只支持网络url
+  // 以下是默认值
+  barWidth: $LOADING_BAR_WIDTH, // 加载进度条宽度,默认240,加载文案过长时可设置
+  totalLaunchTime: 15000, // 默认总启动耗时,即加载动画默认播放时间,可根据游戏实际情况进行调整
+  textDuration: 1500, // 当downloadingText有多个文案时,每个文案展示时间
+  firstStartText: '首次加载请耐心等待', // 首次启动时提示文案
+  downloadingText: ['正在加载资源'], // 加载阶段循环展示的文案
+  compilingText: '编译中', // 编译阶段文案
+  initText: '初始化中', // 初始化阶段文案
+  completeText: '开始游戏', // 初始化完成
+},
+hideAfterCallmain: $HIDE_AFTER_CALLMAIN, // 是否callmain完成立即隐藏封面

backgroundImage需要注意图片宽高不可超过2048,否则无法显示 使用coverview需要基础库版本>=2.16.1,插件已做兼容,若不支持,降级为使用离屏canvas渲染进度的方式 hideAfterCallmain: 游戏业务Awake逻辑耗时较高时可能导致出现短暂黑屏,改为false可盖住黑屏,等游戏第一帧渲染时隐藏

更多信息请参考定制启动封面

3.3 首包资源加载方式

加载方式在转换工具导出时就确定好了,开发者一般不需要修改游戏资源量比较少时,可选择将首包资源作为小游戏分包加载,了解小游戏分包 wasm代码已是通过代码分包加载,当wasm代码+首包资源>20M时,资源包不可再使用小游戏分包加载。 当首包资源通过小游戏代码分包下载时,会将首包资源存放在minigame/data-package这个分包下

转换插件相关配置

assetLoadType: -- $LOAD_DATA_FROM_SUBPACKAGE

game.js配置

js
let managerConfig = {
+  /* 省略其他配置 */
+  loadDataPackageFromSubpackage: $LOAD_DATA_FROM_SUBPACKAGE, // 转换工具自动替换
+}

3.4 预加载资源

为了充分利用网络带宽,在网络空闲时可预下载游戏需要用到的AB包。详细配置请参考使用预下载功能

3.5 资源缓存与淘汰策略

loader会自动按一定规则做文件缓存,加快二次启动速度 详情参考资源缓存

3.6 插件调试日志

  1. 通过修改minigame/unity-namespace.jsenableDebugLog=true,可查看插件详细日志,例如预下载发起和命中、文件缓存等。
  2. 打开调试
`,38),h=[t];function p(k,r,d,o,g,c){return i(),a("div",null,h)}const y=s(l,[["render",p]]);export{u as __pageData,y as default}; diff --git a/assets/Design_UsingLoader.md.DBMrBC_O.lean.js b/assets/Design_UsingLoader.md.DBMrBC_O.lean.js new file mode 100644 index 00000000..ac4e447b --- /dev/null +++ b/assets/Design_UsingLoader.md.DBMrBC_O.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as n}from"./chunks/framework.Br2U662V.js";const e="/minigame-unity-webgl-transform/assets/coverview_loading.BiGkOLi_.png",u=JSON.parse('{"title":"使用Loader进行游游戏加载","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingLoader.md","filePath":"Design/UsingLoader.md"}'),l={name:"Design/UsingLoader.md"},t=n("",38),h=[t];function p(k,r,d,o,g,c){return i(),a("div",null,h)}const y=s(l,[["render",p]]);export{u as __pageData,y as default}; diff --git a/assets/Design_UsingMemoryProfiler.md.Bfk-VwRy.js b/assets/Design_UsingMemoryProfiler.md.Bfk-VwRy.js new file mode 100644 index 00000000..44bc8e61 --- /dev/null +++ b/assets/Design_UsingMemoryProfiler.md.Bfk-VwRy.js @@ -0,0 +1,51 @@ +import{_ as s,c as a,o as i,a4 as l}from"./chunks/framework.Br2U662V.js";const n="/minigame-unity-webgl-transform/assets/memoryprofiler1.DqqM3hJv.png",e="/minigame-unity-webgl-transform/assets/memoryprofiler2.CO1KsCPI.png",t="/minigame-unity-webgl-transform/assets/memoryprofiler3.BHNFw8hn.png",p="/minigame-unity-webgl-transform/assets/memoryprofiler4.fmpW3n4Z.png",o="/minigame-unity-webgl-transform/assets/memoryprofiler5.BQ-2xA41.png",_=JSON.parse('{"title":"使用ProfilingMemory内存分析","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingMemoryProfiler.md","filePath":"Design/UsingMemoryProfiler.md"}'),r={name:"Design/UsingMemoryProfiler.md"},h=l('

使用ProfilingMemory内存分析

概述

在微信开发者工具运行游戏,利用ProfilingMemory,我们可以分析UnityHeap 或 DynamicMemory(CPU主内存)的详细分配堆栈与统计数值。

步骤

  1. 游戏启动调用WeChatWASM.WX.InitSDK,并勾选导出选项"Profiling Funcs"与"Profiling Memory",请勿同时勾选"Development Build"选项!!!

  2. 在微信开发者工具运行游戏,过程中会自动记录所有内存分配数据

  3. 导出内存堆栈数据

  1. 微信开发者工具-“游戏缓存目录/usr/alloc_used.csv”(Android位于data/com.tencent.mm/MicroMsg/wxanewfiles/最近使用时间的目录)拖拽并以csv方式导入sqlite数据库, 推荐使用DB Browser for SQLite

  2. 对表格执行格式化换行 update alloc_used set callback=replace(callback, 'at ', x'0a')

数据分析

浏览数据

典型地,我们可以通过size进行排序分析内存最大占用的堆栈情况

其中:

SQL统计分析

我们可以在"执行SQL"窗口使用SQL进行数据统计和分析,常见的callback分配堆栈特征:

Unity 2021:

 所有内存: select sum(size) from alloc_used
+
+ AssetBundle Storage Memory: select sum(size) from alloc_used where callback like "%AssetBundle_LoadFromMemory%" or callback like "%OnFinishReceiveData%" or callback like "%AssetBundleLoadFromStream%"
+
+
+ AssetBundle Info:  select sum(size) from alloc_used where callback like "%get_assetBundle%" and callback not like "%AwakeFromLoad%"
+ 
+ AssetBundle TypeTree: select sum(size) from alloc_used where callback like "%TypeTree%" 
+
+ Lua: select sum(size) from alloc_used where callback like "%luaY_parser%" or callback like "%luaH_resize%" or callback like "%luaM_realloc%"
+
+ Shader: select sum(size) from alloc_used where callback like "%ShaderLab%"
+
+ IL2CPP runtime: select sum(size) from alloc_used where callback like "%MetadataCache%"
+
+ 非压缩纹理软解: select sum(size) from alloc_used where callback like "%Mipmap%"
+
+Other: select sum(size) from alloc_used where callback not like "%xxx%" or callback not like "%xxx%"

Unity 2018~2020:

AssetBundle Storage Memory: select sum(size) from alloc_used where callback like "%AssetBundleLoadFromStreamAsyncOperation%" 
+
+AssetBundle Info: select sum(size) from alloc_used where callback like "%get_assetBundle%" and callback not like "%AwakeFromLoad%"
+
+AssetBundle TypeTree: select sum(size) from alloc_used where callback like "%TypeTree%"
+
+Lua: select sum(size) from alloc_used where callback like "%luaY_parser%" or callback like "%luaH_resize%" or callback like "%luaM_realloc%" 
+
+Shader: select sum(size) from alloc_used where callback like "%ShaderFromSerializedShader%"
+
+IL2CPP runtime: select sum(size) from alloc_used where callback like "%MetadataCache%" -19M
+
+动画数据: select  sum(size) from alloc_used where callback like "%AnimationClip%" -7MB
+
+非压缩纹理软解: select sum(size) from alloc_used where callback like "%Mipmap%"
+
+Other: select sum(size) from alloc_used where callback not like "%xxx%" or callback not like "%xxx%"

除了常见的堆栈特征外,我们也可以根据业务自己的使用特点来进行SQL分析。

常见问题

1. 开启ProflingMemory后非常慢,特别是在有Lua逻辑的情况

  1. simpledlmalloc.c添加到xLua虚拟机源码目录下参与编译,(和lauxlib.c同一目录)
  2. 参考lauxlib.c,在lua源码目录下的同名文件中增加simple_dlmalloc,并修改LUALIB_API lua_State *luaL_newstate (void) 为如下所示
    C
    #include "simpledlmalloc.c"
    + static void *simple_dlmalloc (void *ud, void *ptr, size_t osize, size_t nsize) {
    +     (void)ud; (void)osize;  /* not used */
    +     if (nsize == 0) {
    +         dlfree(ptr);
    +         return NULL;
    +     }
    +     else
    +         return dlrealloc(ptr, nsize);
    + }
    +
    + // using other_alloc instead of default dlmalloc to avoid print trace of lua
    + LUALIB_API lua_State *luaL_newstate (void) {
    +     // lua_State *L = lua_newstate(l_alloc, NULL);
    +     lua_State *L = lua_newstate(simple_dlmalloc, NULL);
    +     if (L) lua_atpanic(L, &panic);
    +     return L;
    + }

2. ProfilingMemory在真机上更容易出现内存崩溃

`,26),k=[h];function c(u,d,m,g,y,E){return i(),a("div",null,k)}const q=s(r,[["render",c]]);export{_ as __pageData,q as default}; diff --git a/assets/Design_UsingMemoryProfiler.md.Bfk-VwRy.lean.js b/assets/Design_UsingMemoryProfiler.md.Bfk-VwRy.lean.js new file mode 100644 index 00000000..c52d58af --- /dev/null +++ b/assets/Design_UsingMemoryProfiler.md.Bfk-VwRy.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as l}from"./chunks/framework.Br2U662V.js";const n="/minigame-unity-webgl-transform/assets/memoryprofiler1.DqqM3hJv.png",e="/minigame-unity-webgl-transform/assets/memoryprofiler2.CO1KsCPI.png",t="/minigame-unity-webgl-transform/assets/memoryprofiler3.BHNFw8hn.png",p="/minigame-unity-webgl-transform/assets/memoryprofiler4.fmpW3n4Z.png",o="/minigame-unity-webgl-transform/assets/memoryprofiler5.BQ-2xA41.png",_=JSON.parse('{"title":"使用ProfilingMemory内存分析","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingMemoryProfiler.md","filePath":"Design/UsingMemoryProfiler.md"}'),r={name:"Design/UsingMemoryProfiler.md"},h=l("",26),k=[h];function c(u,d,m,g,y,E){return i(),a("div",null,k)}const q=s(r,[["render",c]]);export{_ as __pageData,q as default}; diff --git a/assets/Design_UsingNetworking.md.BwIqduoZ.js b/assets/Design_UsingNetworking.md.BwIqduoZ.js new file mode 100644 index 00000000..27c5082b --- /dev/null +++ b/assets/Design_UsingNetworking.md.BwIqduoZ.js @@ -0,0 +1,160 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const o=JSON.parse('{"title":"网络通信适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingNetworking.md","filePath":"Design/UsingNetworking.md"}'),h={name:"Design/UsingNetworking.md"},k=n(`

网络通信适配

由于安全性的影响,JavaScript 代码没有直接访问 IP 套接字来实现网络连接。因此,该.NET 网络类(System.Net 命名空间中的一切,特别是System.Net.Sockets)在 WebGL 中不能工作。UnityEngine.Network* 类也是这样,编译 WebGL 时将找不到这些类。

HTTP 通信

Unity 支持在 WebGL 中使用 UnityWebRequest 类。

使用方式

以下为使用协程方式发送 GET、POST 请求到服务器的示例:

C#
 IEnumerator Get()
+    {
+        UnityWebRequest webRequest = UnityWebRequest.Get("https://mysite.com");
+
+        yield return webRequest.SendWebRequest();
+       if (webRequest.isHttpError||webRequest.isNetworkError)
+            Debug.Log(webRequest.error);
+        else
+        {
+            Debug.Log(webRequest.downloadHandler.text);
+        }
+
+    }
+
+    IEnumerator Post()
+    {
+        WWWForm form = new WWWForm();
+        //键值对
+        form.AddField("key", "value");
+        form.AddField("name","mafanwei");
+        form.AddField("blog","qwe25878");
+
+        UnityWebRequest webRequest = UnityWebRequest.Post("https://mysite.com",form);
+
+        yield return webRequest.SendWebRequest();
+        if (webRequest.isHttpError||webRequest.isNetworkError)
+            Debug.Log(webRequest.error);
+        else
+        {
+            Debug.Log(webRequest.downloadHandler.text);
+        }
+    }

特别地,在 Unity WebGL 环境下禁止使用以下代码:

C#
while(!www.isDone) {}

不能阻止线程等待 UnityWebRequest 下载完成,否则您的应用程序将冻结。因为 WebGL 采用单线程机制,并且由于 JavaScript 中的 网络 API 是异步的,所以除非您将控制权交回给浏览器,否则下载永远不会完成。取而代之的做法是使用协程和 yield 语句等待下载完成。

TCP 网络通信

如果游戏使用 TCP 进行网络通信,在 Unity WebGL 中开发者可以使用微信基础库中的TCPSocket(需要微信基础库版本>=3.1.1),也可以使用 Websocket 进行替代。

TCPSocket

注意:出于应用场景考虑,TCPSocket.OnMessage表现与文档不一致。

c#
/// <summary>
+/// [TCPSocket.onMessage(function listener)](https://developers.weixin.qq.com/minigame/dev/api/network/tcp/TCPSocket.onMessage.html)
+/// 监听当接收到数据的时触发该事件
+/// needInfo: 是否需要返回localInfo和remoteInfo,设置为 false 时这两个字段会返回null,设置为 true 会降低性能,请按需使用
+/// 多次使用OnMessage时needInfo以第一个OnMessage为准,OffMessage()移除所有回调后再次OnMessage可重新设置needInfo
+/// </summary>
+public void OnMessage(Action<TCPSocketOnMessageListenerResult> listener, bool needInfo = false)

使用举例:

c#
using System.Text;
+using UnityEngine;
+using WeChatWASM;
+using LitJson;
+
+public class TCPTest : MonoBehaviour
+{
+    void Start()
+    {
+      	// 初始化WXSDK
+         WX.InitSDK((int code) =>
+         {
+             Debug.Log("InitSDK code: " + code);
+             TestTCPSocket();
+         });
+    }
+
+    void TestTCPSocket()
+    {
+        Debug.Log("TestTCPSocket");
+        // 创建TCPSocket
+        WXTCPSocket tcp = WX.CreateTCPSocket();
+      	
+      	// 注册回调
+        tcp.OnConnect(res =>
+        {
+            Debug.Log("tcp 连接成功");
+          	//连接成功时发送数据
+            tcp.Write("TCP Write Test");
+        });
+        tcp.OnError(res =>
+        {
+            Debug.Log("tcp 连接失败" + JsonMapper.ToJson(res));
+            WX.ShowModal(new ShowModalOption()
+            {
+                content = res.errMsg
+            });
+        });
+        // 注意OnMessage参数与文档不同
+        tcp.OnMessage(res =>
+        {
+            Debug.Log("tcp 消息" + JsonMapper.ToJson(res));
+            WX.ShowModal(new ShowModalOption()
+            {
+                content = Encoding.UTF8.GetString(res.message)
+            });
+        }, true);
+				
+      	// 在给定的套接字上启动连接,请按需更改地址与端口
+        tcp.Connect(new TCPSocketConnectOption()
+        {
+            address = "www.example.com",
+            port = 8848
+        });
+    }
+}

WebSocket

客户端

支持 Unity Websocket 的第三方插件比较多,可以从 Github 或 AssetStore 找到。这里以UnityWebSocket为例。

C#
// 命名空间
+using UnityWebSocket;
+
+// 创建实例
+string address = "ws://echo.websocket.org";
+WebSocket socket = new WebSocket(address);
+
+// 注册回调
+socket.OnOpen += OnOpen;
+socket.OnClose += OnClose;
+socket.OnMessage += OnMessage;
+socket.OnError += OnError;
+// 连接
+socket.ConnectAsync();
+// 发送 string 类型数据
+socket.SendAsync(str);
+// 或者 发送 byte[] 类型数据(建议使用)
+socket.SendAsync(bytes);
+// 关闭连接
+socket.CloseAsync();

UnityWebSocket需要对WebSocket.jslib做两处修改(新版本无需修改,感谢@psygames):

  1. instance.ws.onmessage函数将分支"else if (ev.data instanceof Blob)"挪到最后
  2. WebSocketSend函数中"HEAPU8"改为"buffer"

可参考WebSocket Demo

服务端

如果服务端使用 TCP 接入,则需要使用 WSS<-->TCP 的代理层。解决方案也很多:

特别地,在处理WebSocket数据包时,请注意数据的“粘包”问题,需要游戏服务器自行处理。

UDP 网络通信

微信基础库支持UDPSocket类。

注意:出于应用场景考虑,TCPSocket.OnMessage表现与文档不一致。

c#
/// <summary>
+/// [UDPSocket.onMessage(function listener)](https://developers.weixin.qq.com/minigame/dev/api/network/udp/UDPSocket.onMessage.html)
+/// 监听收到消息的事件
+/// needInfo: 是否需要返回localInfo和remoteInfo,设置为 false 时这两个字段会返回null,设置为 true 会降低性能,请按需使用
+/// 多次使用OnMessage时needInfo以第一个OnMessage为准,OffMessage()移除所有回调后再次OnMessage可重新设置needInfo
+/// </summary>
+public void OnMessage(Action<UDPSocketOnMessageListenerResult> listener, bool needInfo = false)

使用举例:

c#
using System.Text;
+using UnityEngine;
+using WeChatWASM;
+using LitJson;
+
+public class UDPTest : MonoBehaviour
+{
+    // Start is called before the first frame update
+    void Start()
+    {
+         Debug.Log("Start");
+         WX.InitSDK((int code) =>
+         {
+             Debug.Log("InitSDK code: " + code);
+             TestUDPSocket();
+         });
+    }
+
+    void TestUDPSocket()
+    {
+        Debug.Log("TestUDPSocket");
+        // 创建UDPSocket
+        var udp = WX.CreateUDPSocket();
+				// 注册回调
+        udp.OnMessage(res => 
+        {
+            Debug.Log("udp 消息" + JsonMapper.ToJson(res));
+            WX.ShowModal(new ShowModalOption()
+            {
+                content = Encoding.UTF8.GetString(res.message)
+            });
+        });
+      	// 绑定端口
+        udp.Bind();
+        // 向指定的 IP 和 port 发送消息,请按需更改地址和端口
+        udp.Send(new UDPSocketSendOption()
+        {
+            address = "www.example.com",
+            port = 8848,
+            message = "UDP Send Test"
+        });
+    }
+}

注意事项

微信小游戏的网络需要提前在MP后台配置安全域名,以及使用带证书的HTTPS、WSS协议。

经常有开发者问道:“为什么开发者工具正常,真机访问异常” 或者 “打开调试时正常,但关闭时异常”,通常是由于安全域名与SSL证书:

也有开发者问道:“开发阶段还没SSL证书可以跑起来吗?” 、"开发阶段只有内网IP没正式域名,导致MP无法登记安全域名能跑起来吗?" 答案是肯定的:

安全域名

  1. 真机预览时,默认检验安全域名,通过手机端小游戏右上角菜单-“开启调试”不检查安全域名
  2. 微信开发者工具,默认不检验安全域名、SSL证书;通过详情-本地设置-关闭“不检验合法域名、HTTPS证书”会强制检查
  3. 上线版本的网络请求必须配置安全域名。在 mp.weixin.qq.com 后台,**开发-开发管理-开发设置-服务器域名**进行设置。如果是 HTTP 请求请设置到 request、download合法域名,Websocket 请求请设置到 socket 合法域名。

SSL证书

访问HTTPS请求时,请检查SSL证书请确认是否过期,使用如通过在线工具检测。

真机预览时,只要用了HTTPS/WSS必然需要SSL证书,无法关闭;如无SSL证书或正式域名,可通过打开调试+HTTP/WS协议进行开发。

`,45),l=[k];function t(p,e,E,r,d,g){return a(),i("div",null,l)}const c=s(h,[["render",t]]);export{o as __pageData,c as default}; diff --git a/assets/Design_UsingNetworking.md.BwIqduoZ.lean.js b/assets/Design_UsingNetworking.md.BwIqduoZ.lean.js new file mode 100644 index 00000000..40c033a9 --- /dev/null +++ b/assets/Design_UsingNetworking.md.BwIqduoZ.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const o=JSON.parse('{"title":"网络通信适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingNetworking.md","filePath":"Design/UsingNetworking.md"}'),h={name:"Design/UsingNetworking.md"},k=n("",45),l=[k];function t(p,e,E,r,d,g){return a(),i("div",null,l)}const c=s(h,[["render",t]]);export{o as __pageData,c as default}; diff --git a/assets/Design_UsingPreload.md.YYInpzwD.js b/assets/Design_UsingPreload.md.YYInpzwD.js new file mode 100644 index 00000000..219e6a32 --- /dev/null +++ b/assets/Design_UsingPreload.md.YYInpzwD.js @@ -0,0 +1,66 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/usingpreload1.Ci_fdB50.png",y=JSON.parse('{"title":"使用预下载功能","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingPreload.md","filePath":"Design/UsingPreload.md"}'),e={name:"Design/UsingPreload.md"},t=n('

使用预下载功能

概述

通过 启动流程与时序我们知道,在UnityLoader加载过程中存在网络空闲的情况。特别是“引擎初始化和首场景准备”,影响该步骤包括:引擎自身模块与数据初始化,游戏首个场景加载以及Awake流程。这个过程是CPU处理密集,但网络空闲的期间,根据机型性能不同,通常平均耗时会在3~6s左右,我们可以在此阶段提前下载资源。

预下载的列表的原理是提前通过网络下载资源并缓存到本地,下次使用时从本地缓存中读取文件,以此提高资源加载速度。

同时,我们认为添加到预下载列表的资源都是需要尽快使用到的资源,因此,资源在预下载完成后,会在内存中持有 60s 后释放,从而降低命中预下载列表时的文件读取耗时。

配置方式

导出预下载列表

MiniGameConfig.asset相关配置

preloadFiles: -- $PRELOAD_LIST

在Unity转换导出插件填写文件列表,生成时工具会自动从webgl/StreamAssets目录找资源并填充到game.js。 运行时UnityLoader将根据列表内容在网络空闲期下载。

手动配置

除了在Unity转换导出插件填写文件列表外,也可以在生成的game.js手动配置:

js
let managerConfig = {
+  /* 省略其他配置 */
+
+  /** 
+   * 假设: AB包打包到 path1/StreamingAssets/WebGL这个目录下; STREAMING_CDN是以path1为根路径上传到服务器的CDN地址
+   */
+  // 需要在网络空闲时预加载的资源,支持如下形式的路径。
+  preloadDataList: [
+    // '$STREAM_CDN/StreamingAssets/WebGL/textures_8d265a9dfd6cb7669cdb8b726f0afb1e',
+    // '/WebGL/sounds_97cd953f8494c3375312e75a29c34fc2'
+    "$PRELOAD_LIST" // 导出时自动替换
+  ],
+}

运行时配置「推荐」

可能存在资源热更,导致配置在预下载列表中的资源是旧版本的资源。支持通过接口在运行时动态修改预下载列表

假设有后台接口 https://api.example.com/preloadlist 返回如下数据:

json
{
+  "list": [
+    "https://cdn.example.com/file1",
+    "https://cdn.example.com/file2",
+    "https://cdn.example.com/file3",
+  ]
+}

在插件启动前修改

在插件启动前,拉取游戏后台获取最新的预下载列表,修改 managerConfig.preloadDataList 或通过js接口 GameGlobal.manager.setPreloadList 修改

伪代码如下:

js
wx.request({
+  url: 'https://api.example.com/preloadlist', // 修改为实际API地址
+  success(res) {
+    if (res.statusCode === 200) {
+      managerConfig.preloadDataList = res.data.list;
+    }
+  },
+  complete() {
+    // 成功与否都开始启动unity
+    GameGlobal.manager.startGame();
+  }
+})
js
wx.request({
+  url: 'https://api.example.com/preloadlist', // 修改为实际API地址
+  success(res) {
+    if (res.statusCode === 200) {
+      GameGlobal.manager.setPreloadList(res.data.list);
+    }
+  },
+  complete() {
+    // 成功与否都开始启动unity
+    GameGlobal.manager.startGame();
+  }
+})

引擎初始化完成后修改

同样的,拉取游戏后台接口获取最新的预下载列表后,通过C#接口 WX.SetPreloadList 修改

伪代码如下:

csharp
private IEnumerator GetPreloadList()
+{
+    using (UnityWebRequest www = UnityWebRequest.Get("https://api.example.com/preloadlist"))
+    {
+        yield return www.SendWebRequest();
+        if (www.result != UnityWebRequest.Result.Success)
+        {
+            Debug.Log(www.error);
+        }
+        else
+        {
+            string json = www.downloadHandler.text;
+            PreloadListData preloadListData = JsonUtility.FromJson<PreloadListData>(json);
+
+            // 获取URL列表
+            WX.SetPreloadList(preloadListData.list.ToArray());
+        }
+    }
+}
+
+
+[System.Serializable]
+public class PreloadListData
+{
+    public List<string> list;
+}

并发数

在引擎初始化完成前,默认并发10个预下载。已发起但未完成的下载任务,以及列表中尚未发起的任务,会在引擎初始完成后继续进行,但并发数改为1个。可通过Csharp接口 WX.PreloadConcurrent 修改引擎初始化后的预下载并发数,若想修改引擎初始化期间的并发数,需要使用js接口 GameGlobal.manager.setConcurrent

即使通过 GameGlobal.manager.setConcurrent 修改并发数,在引擎初始化完成后仍会重置为 1 个,需再次修改为你需要的值

路径规范

如何验证

查看插件调试日志

  1. 当存在 PreloadManager: 字样日志,即为预下载请求日志。
  2. 当存在 xhr: xx使用预载内容 即为复用内存中已预下载完成的资源,不发起网络请求。
  3. 当存在 xhr: xx 等待预载完成 即为复用未完成的预下载网络链接,等待网络完成。

tips:当预下载完成时间超过 60s 后,内存中的资源会释放。后续请求已预下载的资源没有日志可以区分,可通过 PreloadManager: 验证此资源预下载成功

注意事项

  1. 预下载所有文件总体积应控制在合理范围内,通常可以3~5MB左右的内容。
  2. 文件数量应控制在10个以内,在此阶段最多只能允许10个并发,超过将会排队。
  3. UnityLoader插件已经考虑到业务会重复请求预下载的文件,游戏逻辑依然按未使用预下载的异步加载逻辑,无需做其他处理。如果预下载完成UnityLoader会立即构造网络数据返回,业务无感知。
  4. 添加到预下载列表中的文件,需是插件会自动缓存的文件,否则会导致下载浪费,预下载无效,详见资源缓存
  5. 会按照列表顺序发起预下载,请将优先需要的资源放到列表前面。
`,41),h=[t];function p(k,r,d,E,o,g){return a(),i("div",null,h)}const u=s(e,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/Design_UsingPreload.md.YYInpzwD.lean.js b/assets/Design_UsingPreload.md.YYInpzwD.lean.js new file mode 100644 index 00000000..a4badd75 --- /dev/null +++ b/assets/Design_UsingPreload.md.YYInpzwD.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/usingpreload1.Ci_fdB50.png",y=JSON.parse('{"title":"使用预下载功能","description":"","frontmatter":{},"headers":[],"relativePath":"Design/UsingPreload.md","filePath":"Design/UsingPreload.md"}'),e={name:"Design/UsingPreload.md"},t=n("",41),h=[t];function p(k,r,d,E,o,g){return a(),i("div",null,h)}const u=s(e,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/Design_WXFont.md.-W-sW9eo.js b/assets/Design_WXFont.md.-W-sW9eo.js new file mode 100644 index 00000000..c65dc14b --- /dev/null +++ b/assets/Design_WXFont.md.-W-sW9eo.js @@ -0,0 +1,44 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const h="/minigame-unity-webgl-transform/assets/WXFont.GXJDQ91G.png",y=JSON.parse('{"title":"微信系统字体","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WXFont.md","filePath":"Design/WXFont.md"}'),t={name:"Design/WXFont.md"},l=n(`

微信系统字体

游戏基本会使用中文,中文字体大小少则2-3M。

通过微信系统字体,从本地加载中文,可节省启动下载的资源量。再不支持使用微信系统字体时,回退成通过CDN下载后备字体的形式。

版本要求

转换插件 >= 202306292010 提供了 WX.GetWXFont 接口用于加载后备/系统字体

其中,微信客户端满足以下版本要求时,可从本地加载字体,无需网络下载

若不满足客户端版本要求,首次从网络下载;当符合缓存规则时,后续从本地文件缓存加载,因此必须提供 CDN 后备字体。

代码示例

详细示例可参考系统字体demo

csharp
var fallbackFont = "https://www......com/字体文件.ttf";
+WeChatWASM.WX.GetWXFont(fallbackFont, (font) =>
+{
+    text.font = font;
+    tmpText.font = TMP_FontAsset.CreateFontAsset(font);
+});

相关日志

异常日志:

系统字体字符集

使用GetWXFont加载的字体集合可以在转换面板进行自定义,以减少加载的字体文件大小:

若需要某些特殊Unicode/仅需要部分Unicode,可以直接将需要的字符全部填入自定义Unicode中。

Unicode集合参考:

js
// https://unicode.yunser.com/unicode
+const unicodeRange = [
+  // 基本汉字 https://www.unicode.org/charts/PDF/U4E00.pdf
+  [0x4e00, 0x9fff],
+  // 基本拉丁语(英文大小写、数字、英文标点)https://www.unicode.org/charts/PDF/U0000.pdf
+  [0x0, 0x7f],
+  // 中文标点符号 https://www.unicode.org/charts/PDF/U3000.pdf
+  [0x3000, 0x303f],
+  // 通用标点符号 https://www.unicode.org/charts/PDF/U2000.pdf
+  [0x2000, 0x206f],
+  // CJK字母及月份 http://www.unicode.org/charts/PDF/U3200.pdf
+  [0x3200, 0x32ff],
+  // 中文竖排标点 http://www.unicode.org/charts/PDF/UFE10.pdf
+  [0xfe10, 0xfe1f],
+  // CJK兼容符号 http://www.unicode.org/charts/PDF/UFE30.pdf
+  [0xfe30, 0xfe4f],
+  // 杂项符号 http://www.unicode.org/charts/PDF/U2600.pdf
+  [0x2600, 0x26ff],
+  // CJK特殊符号 http://www.unicode.org/charts/PDF/U3300.pdf
+  [0x3300, 0x33ff],
+  // 全角ASCII、全角中英文标点、半宽片假名、半宽平假名、半宽韩文字母 http://www.unicode.org/charts/PDF/UFF00.pdf
+  [0xff00, 0xffef],
+  // 装饰符号 http://www.unicode.org/charts/PDF/U2700.pdf
+  [0x2700, 0x27bf],
+  // 字母式符号 https://www.unicode.org/charts/PDF/U2100.pdf
+  [0x2100, 0x214f],
+  // 带圈或括号的字母数字 https://www.unicode.org/charts/PDF/U2460.pdf
+  [0x2460, 0x24ff],
+  // 数字形式 https://www.unicode.org/charts/PDF/U2150.pdf
+  [0x2150, 0x218f],
+  // 货币符号 https://www.unicode.org/charts/PDF/U20A0.pdf
+  [0x20a0, 0x20cf],
+  // 箭头 https://www.unicode.org/charts/PDF/U2190.pdf
+  [0x2190, 0x21ff],
+  // 几何图形 https://www.unicode.org/charts/PDF/U25A0.pdf
+  [0x25a0, 0x25ff],
+  // 数学运算符号 https://www.unicode.org/charts/PDF/U2200.pdf
+  [0x2200, 0x22ff],
+];
`,21),p=[l];function k(e,E,r,d,g,o){return a(),i("div",null,p)}const F=s(t,[["render",k]]);export{y as __pageData,F as default}; diff --git a/assets/Design_WXFont.md.-W-sW9eo.lean.js b/assets/Design_WXFont.md.-W-sW9eo.lean.js new file mode 100644 index 00000000..a719f8c8 --- /dev/null +++ b/assets/Design_WXFont.md.-W-sW9eo.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const h="/minigame-unity-webgl-transform/assets/WXFont.GXJDQ91G.png",y=JSON.parse('{"title":"微信系统字体","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WXFont.md","filePath":"Design/WXFont.md"}'),t={name:"Design/WXFont.md"},l=n("",21),p=[l];function k(e,E,r,d,g,o){return a(),i("div",null,p)}const F=s(t,[["render",k]]);export{y as __pageData,F as default}; diff --git a/assets/Design_WX_SDK.md.CBaKb55h.js b/assets/Design_WX_SDK.md.CBaKb55h.js new file mode 100644 index 00000000..148ba3ab --- /dev/null +++ b/assets/Design_WX_SDK.md.CBaKb55h.js @@ -0,0 +1,37 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const y=JSON.parse('{"title":"SDK 调用微信 API","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WX_SDK.md","filePath":"Design/WX_SDK.md"}'),h={name:"Design/WX_SDK.md"},l=n(`

SDK 调用微信 API

将 WX-WASM-SDK 这个目录拷贝至 unity 工程 Assets 目录下,在主入口初始化,回调后再执行你的主逻辑

WX.InitSDK((int code)=> {
+// 你的主逻辑
+});

API 可以直接看WX.cs这个文件,里面有详细注释说明

本 Unity 的 SDK 的 API 大体与官网 API 文档的 JS 版本 API 类似,使用时可以参考之。 如 JS 版的 banner 广告的调用如下:

js
var bannerAd = wx.createBannerAd({
+    adUnitId: "xxxx",
+    adIntervals: 30,
+    style: {
+        left: 0,
+        top: 0,
+        width: 600,
+        height: 200,
+    },
+});
+bannerAd.onLoad(() => {
+    bannerAd.show();
+});
+bannerAd.onError((res) => {
+    console.log(res);
+});

而对于 Unity 版的调用如下:

csharp
var bannerAd = WX.CreateBannerAd(new WXCreateBannerAdParam()
+{
+    adUnitId = "xxxx",
+    adIntervals = 30,
+    style = new Style()
+    {
+        left = 0,
+        top = 0,
+        width = 600,
+        height = 200
+    }
+});
+bannerAd.OnLoad(()=> {
+    bannerAd.Show();
+});
+bannerAd.OnError((WXADErrorResponse res)=>
+{
+    Debug.Log(res.errCode);
+});

大体是将 JS 版中的wx替换为 Unity 版的WX,然后对应方法名首字母由小写改为大写,如createBannerAd就变为CreateBannerAd

基础库

在 Unity 中兼容低版本基础库

使用WX.CanIUse可以判断当前版本是否支持该 API(仅支持 wx),例如想要判断当前环境WX.ReportScene是否可用,可以用WX.CanIUse("ReportScene")来判断

开发建议

Demo API 示例

使用示例我们会逐渐补充到Demo, 其中 API 项目为常见到使用范例,请优先查阅用法。

联调效率

如果开发者有简单的 JS 代码经验,建议先以 JS 方式直接修改 minigame 的 JS 代码进行调试,完成之后再使用 C# SDK 修改 Unity 工程:

  1. 只保留 game.js 前面 import 部分,其余删除,即不运行游戏逻辑。
  2. 增加以下代码:
js
const gl = GameGlobal.canvas.getContext("webgl");
+gl.clear(gl.COLOR_BUFFER_BIT);
  1. 使用 JS 编写需要调试的 API

注意事项

  1. 广告接口是否需要上线后才能调试
`,24),t=[l];function e(p,k,E,r,d,g){return a(),i("div",null,t)}const c=s(h,[["render",e]]);export{y as __pageData,c as default}; diff --git a/assets/Design_WX_SDK.md.CBaKb55h.lean.js b/assets/Design_WX_SDK.md.CBaKb55h.lean.js new file mode 100644 index 00000000..f4e7c8fe --- /dev/null +++ b/assets/Design_WX_SDK.md.CBaKb55h.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const y=JSON.parse('{"title":"SDK 调用微信 API","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WX_SDK.md","filePath":"Design/WX_SDK.md"}'),h={name:"Design/WX_SDK.md"},l=n("",24),t=[l];function e(p,k,E,r,d,g){return a(),i("div",null,t)}const c=s(h,[["render",e]]);export{y as __pageData,c as default}; diff --git a/assets/Design_WasmSplit.md.WxEMJpKx.js b/assets/Design_WasmSplit.md.WxEMJpKx.js new file mode 100644 index 00000000..9da56bbc --- /dev/null +++ b/assets/Design_WasmSplit.md.WxEMJpKx.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/extension-panel.CY9x27Ol.js";import{_ as i,c as e,o as l,a4 as r}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/update-plugin.QaxP19qF.png",t="/minigame-unity-webgl-transform/assets/enable-plugin-1.hrkbpNFb.png",h="/minigame-unity-webgl-transform/assets/enable-plugin-2.gCjA-u1u.png",n="/minigame-unity-webgl-transform/assets/start-split.Bf36xgxL.png",d="/minigame-unity-webgl-transform/assets/preproc.B1bs5gTC.png",s="/minigame-unity-webgl-transform/assets/increment-update.B83feQqF.png",u="/minigame-unity-webgl-transform/assets/wait-split.DY23j374.png",c="/minigame-unity-webgl-transform/assets/main.CwerfU8n.png",p="/minigame-unity-webgl-transform/assets/check-version.BiswJbE4.png",w=JSON.parse('{"title":"代码分包","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WasmSplit.md","filePath":"Design/WasmSplit.md"}'),f={name:"Design/WasmSplit.md"},m=r('

代码分包

概述

背景

unity 导出小游戏项目后,代码是在一个 wasm 文件里,经过 brotli 压缩后,放在 wasmcode 目录下

一般小游戏的 wasm 大小都为 30M 左右,压缩后为 6M 左右

启动阶段,小游戏需要先下载完 wasmcode 再编译,这里会占用较高的内存和时间

因此我们提供了代码分包工具,将原来的 wasm 拆分为两个,一个用于启动加载(主包),另一个可以延迟加载(子包)

使得小游戏可以先加载较小的首包进入主场景,再异步加载剩下的分包

另外对于iOS高性能模式,子包不会加载,会转为按函数粒度按需加载

作用

分包的作用在于优化启动时间

另外对于 iOS 新的高性能模式,分包还有两个作用:

  1. 减少内存使用,以支持更多 iOS 低端机上运行高性能模式
  2. 减少编译时间,降低了游戏前期的发烫情况

实现原理

目前我们采用了一种 Profile Guided Optimization 的方式,通过运行时收集信息,按函数粒度对小游戏的 wasm 代码包进行拆分

开发者可以在离线测试阶段,通过真机运行小游戏,并尽量覆盖游戏内的场景,特别是启动后最先进入的场景和关卡(比如新手教学,游戏最初的关卡内容)来收集信息

工具上会显示收集到的函数个数,这时候就可以重新分包,将收集到的函数加入首包

因此收集工作非常重要,收集的场景覆盖率越高,命中子包的时机就可以相应延后,使得首包可以满足大部分新玩家前几分钟的游戏进程

我们提供了一个微信开发者工具里的插件来辅助分包过程,依赖的开发者工具版本为 1.05.2104251 RC 及以上,稳定版 1.05.2105100 已支持

插件安装

通过开发者工具的设置-拓展设置-编辑器自定义拓展,安装 wasmCodeSplit 这个插件

插件更新

开发者工具上(如果用的是stable版,非minigame版)的插件一般是自动更新的

手动更新

插件使用

分包插件按小游戏的md5(wasmcode下的wasm文件名里的md5)来区分不同的小游戏包

相同md5的小游戏包会复用同一份分包结果

对于新构建的小游戏包,分包流程如下:

最后一步这里已经可以随时上传体验版了

具体操作和注意事项如下

启用分包

打开插件开关后,在目录树上的工具栏中,可以看到插件的按钮,如图所示,点击后即可进入插件页:

输入版本描述

等待上传文件

等待预处理

注意:如果出现红框中的提示,说明这里的状态更新已经中断,需要重启开发者工具

这一步一般是分钟级的耗时,如果等待超过10分钟,建议先重启下开发者工具

选择是否增量分包

如果这个游戏之前的包已经有用过代码分包,没有比较大的代码修改的情况下(比如大范围的代码重构,更换引擎),可以使用增量更新,也就是选择之前的某个包作为参考

我们会对比前后两个包的symbol,把之前收集过的函数当做放到首包,即无需重复收集

因此要求前后两个包都必须提供symbol文件

在unity侧使用微信插件导出时,需要开启profiling func,这样打包时就会导出symbol文件

无需担心开启profiling func导致的包体增大,分包工具会优化函数名

等待分包

android收集 + iOS收集

分包的收集,一般需要android和iOS单独收集

收集操作:

这里主要关注首包函数个数,一般跑完这两个步骤首包函数占整包函数个数的30%以上就差不多了

重复收集与生成

android和iOS收集完,基本就可以测试和发布了

有条件的话,可以尽量覆盖各种机型(主流品牌)再多跑几次收集

每次收集发现新增函数趋于稳定之后,就可以继续点生成profile分包或者生成release分包

每次点生成时,会先跳到前面的等待分包界面,完成后再回来

每次生成会当前的分包version会加1

关闭分包

如果想回退到未分包的版本,点击关闭代码分包即可

注意事项

上线前

如果有最后两点,那就还要继续收集+生成分包

上线后

如果上线后,有玩家遇到新增函数个数,分包插件上也会更新(主要来源是iOS高性能),或者收到小游戏数据助手的相关告警,这个时候要继续生成分包,同时提审发布

FAQ

分包是否是必要的


对于 iOS 高性能模式,由于内存限制,游戏加载完整 wasm 基本就会内存 crash。分包能降低内存占用,同时我们对子包支持按需加载,才让游戏能稳定跑起来

所以如果是使用了 iOS 高性能模式则是必须的

对于 android 和 iOS 普通模式,分包主要目的是优化启动加载,另外这两个 runtime 下由于子包可以全量加载,因此对游戏运行影响最多只有加载子包的一次性影响

我们也会在启动 callmain 后 30s 提前加载子包,在这个时间之后才触发未收集函数的情况也不会有加载子包的影响

收集到什么时候可以结束


按照我们经验,一般首包函数有整包个数的 33%以上的时候就可以接受了,当然能尽量再收集完善刚好,个别游戏可能会接近 50%

这时候不代表没收集的函数都没用了,实际上有些函数可能只是调用比较冷门,后续还是可能会被调到,可以通过分包插件面板的新增收集函数个数来留意线上新增的情况,

如果线上新增较多(超过 50),可以考虑再往下分一次包然后提审发布

游戏内容难以遍历完整怎么办

我们针对这种情况也有线上patch可以进行补漏,但是patch有大小限制

建议新增收集函数个数超过100个的还是要生成新分包+发版本

分包总大小比原始包大


  1. 分包的目的主要是将启动时需要的包减小,一般分包后wasm首包可以控制在原包的1/3到1/2之间
  2. 子包是有延迟加载的,因此耗时上不需要看总的大小,看首包的减少量即可
  3. 一般iOS高性能模式才有内存使用瓶颈,而iOS上子包是按需加载的,可以缓解内存问题 因此,这里不需要关注分包后所有wasm包的总和,主要关注wasm首包(即minigame/wasmcode)的大小即可

新增收集的函数要重新再次提审才会在首包吗


对的,用户下载的代码包只能是提审发布过的

会不会最终跑到所有函数都收集的情况


目前还没出现这种情况,超过整包 50%的都很少

大部分游戏收集 1 小时的函数个数都在 33%到 50%之间

可以等收集函数超过 75%了再来考虑这个问题

iOS 高性能模式收集很卡


iOS 高性能模式由于加载子包的实现不同,刚开始收集时又基本是跑子包函数,所以最开始的收集会比较卡

这个时候可以观察分包插件面板,如果能看到有新增函数个数的变化,一般就是没问题的。如果出现卡顿(并且有新增函数)或者新增函数较多(超过 50),可以先继续往下生成分包,再进行收集。游戏运行会随着收集越来越流畅

iOS 高性能模式代码分包后内存反而变得很高


这种情况一般是太多新增函数(比如几百个),iOS 高性能模式的子包代码也会占用大量内存,可以继续生成分包,将这部分函数放在首包(放首包的内存占用相对小些)

iOS 高性能模式出现 impport section's count is too big


新版的插件已经规避这个问题,更新插件即可

没有看到增量分包的界面


由于增量分包是新增的功能,因此之前的项目不能被用来增量更新。更新分包插件后,第二次导出的版本开始才可以使用

增量分包没生效


请检查指定参考的旧版本以及当前版本是否都有 symbol 文件,以及是否有更换引擎或者其他导致代码变动较大的操作

如何更新分包插件


微信开发者工具会自动更新分包插件,一般不需要手动更新。可前往微信开发者工具-编辑器区域-拓展列表查看插件版本确认是否为最新版本

请勿使用小游戏版微信开发者工具,会出现插件无法正常更新或安装。请前往:适配文档-安装与使用,下载stable版本微信开发者工具。

分包插件安装失败


首先确认是否为stable版本开发者工具。

有两个地方可安装插件:

  1. 编辑器区域-拓展:搜索wasm-code-split,点击安装
  2. 菜单栏-设置-拓展设置,找到wasmcodesplit,点击进入详情页,点击获取

分包插件卡住

遇到流程卡住问题,一般先尝试关闭分包,然后重启开发者工具,再打开分包,大部分时候有奇效

内存优化版本未观察到内存优化


  1. 首先排查项目是否已经是内存优化版本的分包:插件面板当前后台服务版本为3(或者看framework最后的API_VERSION)
  2. 这里的内存优化主要针对iOS高性能模式,主要是减少了编译相关的内存(和函数个数相关,10w+函数的包可以减少约100M),可以通过在callmain或者raf之前暂停来观察
  3. 最终到游戏内有可能会上涨到和原来差不多,但这个是受gc策略和系统进程内存优化的影响,可以点右上角退出小游戏触发强制gc来观察

如何查看分包插件日志

当出现问题时,优先排查是否stable版本的微信开发者工具,能解决大部分问题。 若问题仍无法解决,可联系我们,提供日志排查。 日志获取方式:

菜单栏-微信开发者工具-调试-调试微信开发者工具,搜索关键字:extension host。可右键保存日志文件

Changelog

v1.1.13

Fixed

v1.1.12

Fixed

v1.1.11

Fixed

v1.1.10

Fixed

v1.1.9

Feature

v1.1.8

Changed

v1.1.6

Changed

v1.1.5

Fixed

v1.1.4

Fixed

v1.1.2

Changed

v1.1.0

Added

v1.0.2

Added

',170),b=[m];function q(g,x,v,k,P,_){return l(),e("div",null,b)}const F=i(f,[["render",q]]);export{w as __pageData,F as default}; diff --git a/assets/Design_WasmSplit.md.WxEMJpKx.lean.js b/assets/Design_WasmSplit.md.WxEMJpKx.lean.js new file mode 100644 index 00000000..8cfd5b23 --- /dev/null +++ b/assets/Design_WasmSplit.md.WxEMJpKx.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/extension-panel.CY9x27Ol.js";import{_ as i,c as e,o as l,a4 as r}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/update-plugin.QaxP19qF.png",t="/minigame-unity-webgl-transform/assets/enable-plugin-1.hrkbpNFb.png",h="/minigame-unity-webgl-transform/assets/enable-plugin-2.gCjA-u1u.png",n="/minigame-unity-webgl-transform/assets/start-split.Bf36xgxL.png",d="/minigame-unity-webgl-transform/assets/preproc.B1bs5gTC.png",s="/minigame-unity-webgl-transform/assets/increment-update.B83feQqF.png",u="/minigame-unity-webgl-transform/assets/wait-split.DY23j374.png",c="/minigame-unity-webgl-transform/assets/main.CwerfU8n.png",p="/minigame-unity-webgl-transform/assets/check-version.BiswJbE4.png",w=JSON.parse('{"title":"代码分包","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WasmSplit.md","filePath":"Design/WasmSplit.md"}'),f={name:"Design/WasmSplit.md"},m=r("",170),b=[m];function q(g,x,v,k,P,_){return l(),e("div",null,b)}const F=i(f,[["render",q]]);export{w as __pageData,F as default}; diff --git a/assets/Design_WebGL2.md.C7mclE2P.js b/assets/Design_WebGL2.md.C7mclE2P.js new file mode 100644 index 00000000..aa7541af --- /dev/null +++ b/assets/Design_WebGL2.md.C7mclE2P.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"WebGL2.0渲染支持说明","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WebGL2.md","filePath":"Design/WebGL2.md"}'),n={name:"Design/WebGL2.md"},r=t('

WebGL2.0渲染支持说明

适合使用场景

WebGL 是一种用于在 Web 浏览器中渲染图形的 API,基于 OpenGL ES 图形库的功能。WebGL 1.0 大致与 OpenGL ES 2.0 功能相匹配,而 WebGL 2.0 大致与 OpenGL ES 3.0 功能相匹配。 根据游戏项目统计,我们发现相对于WebGL1,更适合以下游戏需求:

用户占比

Unity WebGL较多渲染优化特性依赖WebGL2.0, 因此这里需要针对该特性在小游戏环境的支持进一步说明。

已知兼容问题

如遇到问题请联系我们详细排查。

iOS高性能模式开启GPU Instance,模型闪烁/消失/不绘制等问题

iOS高性能模式DrawMeshInstanced显示错乱

参考文档

',16),l=[r];function o(s,c,h,d,u,p){return i(),a("div",null,l)}const g=e(n,[["render",o]]);export{m as __pageData,g as default}; diff --git a/assets/Design_WebGL2.md.C7mclE2P.lean.js b/assets/Design_WebGL2.md.C7mclE2P.lean.js new file mode 100644 index 00000000..bd97a447 --- /dev/null +++ b/assets/Design_WebGL2.md.C7mclE2P.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,a4 as t}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"WebGL2.0渲染支持说明","description":"","frontmatter":{},"headers":[],"relativePath":"Design/WebGL2.md","filePath":"Design/WebGL2.md"}'),n={name:"Design/WebGL2.md"},r=t("",16),l=[r];function o(s,c,h,d,u,p){return i(),a("div",null,l)}const g=e(n,[["render",o]]);export{m as __pageData,g as default}; diff --git a/assets/Design_fixScreen.md.9f3koYcy.js b/assets/Design_fixScreen.md.9f3koYcy.js new file mode 100644 index 00000000..7e33c0f2 --- /dev/null +++ b/assets/Design_fixScreen.md.9f3koYcy.js @@ -0,0 +1,10 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/saveArea.BbgprMYb.png",y=JSON.parse('{"title":"屏幕适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/fixScreen.md","filePath":"Design/fixScreen.md"}'),h={name:"Design/fixScreen.md"},e=n(`

屏幕适配

安全区域适配

小游戏的屏幕适配与 unity 游戏适配常见手机屏幕没有区别。常见的适配方式都可以在小游中使用。区别的是一些屏幕信息的获取。 如安全区域的获取需调用 WX.GetWindowInfo 得到其中的安全区域。 如下是适配刘海屏(这里以竖屏游戏按高度适配为例)的示例:

csharp
var info = WX.GetWindowInfo();
+float py = (float)info.safeArea.top / (float)info.windowHeight;
+// Rootrect初始时设置其Anchor,使其与父节点一样大,也就是屏幕的大小
+// 调整屏幕移到刘海屏下面,
+Rootrect.anchorMin = new Vector2((float)info.safeArea.left / (float)info.windowWidth, -(float)info.safeArea.top / (float)info.windowHeight);
+// 重新计算缩放,让高度占满刘海屏以下的区域
+cs.referenceResolution = new Vector2(cs.referenceResolution.x, cs.referenceResolution.y * (1.0f+py));

安全区域wx.getWindowInfo 中获取的安全区域的数值,需要乘以 pixelRatio 才为 Unity 中的大小,而且手机屏幕左上角为(0,0)

高分辨屏下模糊问题

因为 Unity 2019.3 之前的版本对高分辨屏适配不是很好。会出现画面模糊的情况,所以最好选择Unity 2019.3之后的版本来构建你的游戏。如果游戏不能升级版本,也可以引入SDK,在初始化 SDK 后,SDK 会自动对页面做一个兼容适配,避免模糊的问题。

csharp
//初始化SDK
+WX.InitSDK((int code)=> {
+// 你的主逻辑
+});
`,8),l=[e];function p(k,r,d,o,E,g){return a(),i("div",null,l)}const f=s(h,[["render",p]]);export{y as __pageData,f as default}; diff --git a/assets/Design_fixScreen.md.9f3koYcy.lean.js b/assets/Design_fixScreen.md.9f3koYcy.lean.js new file mode 100644 index 00000000..233a36a0 --- /dev/null +++ b/assets/Design_fixScreen.md.9f3koYcy.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.Br2U662V.js";const t="/minigame-unity-webgl-transform/assets/saveArea.BbgprMYb.png",y=JSON.parse('{"title":"屏幕适配","description":"","frontmatter":{},"headers":[],"relativePath":"Design/fixScreen.md","filePath":"Design/fixScreen.md"}'),h={name:"Design/fixScreen.md"},e=n("",8),l=[e];function p(k,r,d,o,E,g){return a(),i("div",null,l)}const f=s(h,[["render",p]]);export{y as __pageData,f as default}; diff --git a/assets/Design_iOSOptimization.md.CvXFzPXD.js b/assets/Design_iOSOptimization.md.CvXFzPXD.js new file mode 100644 index 00000000..c5ea387f --- /dev/null +++ b/assets/Design_iOSOptimization.md.CvXFzPXD.js @@ -0,0 +1 @@ +import{_ as i}from"./chunks/mp_addplugin.pe280tQx.js";import{_ as a,c as e,o as t,a4 as r}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/iosoptimization3.wOpxID9g.png",o="/minigame-unity-webgl-transform/assets/iosoptimization1.DvZXgGEV.png",n="/minigame-unity-webgl-transform/assets/iosoptimization2.ydVjAkNG.png",s="/minigame-unity-webgl-transform/assets/contentencoding_error.BloxEjqB.png",h="/minigame-unity-webgl-transform/assets/devtools_network.CT_lQr9b.png",m="/minigame-unity-webgl-transform/assets/cors_istrusted.CXIjh3Wr.png",O=JSON.parse('{"title":"iOS 高性能与高性能+模式","description":"","frontmatter":{},"headers":[],"relativePath":"Design/iOSOptimization.md","filePath":"Design/iOSOptimization.md"}'),p={name:"Design/iOSOptimization.md"},d=r('

iOS 高性能与高性能+模式

什么是高性能模式

在 iOS 环境下,标准的微信小游戏 WASM 运行模式是无 JIT, 对于计算性能要求较高的游戏会受到比较大的限制。常见情况是:

  1. 中低端机帧率较低,流畅度难以达到上线标准
  2. 对 CPU 计算资源消耗过高,运行一段时间后设备温度持续上升

小游戏环境框架提供了高性能运行模式,该运行模式下 CPU 算力得到明显提升。但该模式也存在更严格的内存与代码包体限制,需要开发者采取合适的手段以达到最优。

什么是高性能+模式

高性能+模式开创新地在保留游戏独立进程的基础上将渲染重新挪回了微信进程,这使得渲染效果和渲染内存消耗都得到了改善。详细文档请查阅高性能+模式。 特别地,建议使用WebGL2、内存压力大的游戏开启此选项。开启后请验证进程内存、渲染兼容性、帧耗时数据是否正常。

性能提升

CPU 消耗

通过多款游戏项目,我们得到实际游戏项目的 CPU 占用如下图所示:

我们得到以下结论:

压力测试

使用 Unity 所提供的 Benchmark Demo 的部分案例进行评测:

测试过程为不断增加运算复杂度,直到帧率下降到特定数值。

分数越高,代表的运行能力越强。

上图分别是 iOS 端普通模式与高性能模式的得分,可以看到在几个压测示例中高性能模式均明显优于普通模式。

经实际游戏测试,游戏帧率都会得到明显改善,虽无法达到 Benchmark 几乎一个数量级的差异。

如何开通

iOS 端小游戏高性能模式适用于遇到 iOS 环境运行性能不足,运行发烫的小游戏。

高性能模式限制

内存限制

高性能模式下,iOS 低端机(6s/7/8 等)2G RAM 机型的内存限制为 1G,中高端机(7P/8P/iPhoneX/XSAMX/11/12 等)3G 以上内存机型的内存限制为 1.5G(安全内存建议1.2G~1.3G),因此开发者务必保证内存峰值不超过该数值。

建议开发者根据指引优化 Unity WebGL 的内存

代码体积限制

高性能模式下,WASM 代码将被编译并优化,需要占用更多的编译消耗与内存。如果未进行优化前,可以明显感受到启动开始阶段(如启动前 1 分钟内)设备发烫。

上线发布时,特别建议使用WASM 代码分包+压缩纹理+UnityHeap预留这几种优化手段。

QA

1. 如何判别游戏否已经开启了高性能模式?

2. 使用高性能模式下,游戏本身是否需要做修改?

3. iOS 报错提示未开启 gzip/br 压缩

可通过微信开发者工具查看 Content-Encoding 是否为 gzip 或 br

如果有正确压缩,可忽略这个错误。

问题原因:由于跨域获取不到 Content-Encoding 头

解决办法:增加跨域头部"Access-Control-Expose-Headers": "Content-Length, Content-Encoding",

4. 资源下载提示isTrusted

多半由于跨域问题导致,可通过开发者工具查看对应资源的 Response Header 是否有跨域头, 请参考文档网络通信适配关于跨域的问题

5. 卡在启动封面无法启动

6. 个别游戏 UI 会出现闪烁问题

7. 为什么开启了高性能模式,游戏启动很烫?

8. 使用高性能模式下,不优化内存、WASM 代码包体积就发布上线可以吗?

9. iOS 高性能模式与安卓性能对比如何?

',58),u=[d];function c(f,g,q,b,_,S){return t(),e("div",null,u)}const w=a(p,[["render",c]]);export{O as __pageData,w as default}; diff --git a/assets/Design_iOSOptimization.md.CvXFzPXD.lean.js b/assets/Design_iOSOptimization.md.CvXFzPXD.lean.js new file mode 100644 index 00000000..620dc7c9 --- /dev/null +++ b/assets/Design_iOSOptimization.md.CvXFzPXD.lean.js @@ -0,0 +1 @@ +import{_ as i}from"./chunks/mp_addplugin.pe280tQx.js";import{_ as a,c as e,o as t,a4 as r}from"./chunks/framework.Br2U662V.js";const l="/minigame-unity-webgl-transform/assets/iosoptimization3.wOpxID9g.png",o="/minigame-unity-webgl-transform/assets/iosoptimization1.DvZXgGEV.png",n="/minigame-unity-webgl-transform/assets/iosoptimization2.ydVjAkNG.png",s="/minigame-unity-webgl-transform/assets/contentencoding_error.BloxEjqB.png",h="/minigame-unity-webgl-transform/assets/devtools_network.CT_lQr9b.png",m="/minigame-unity-webgl-transform/assets/cors_istrusted.CXIjh3Wr.png",O=JSON.parse('{"title":"iOS 高性能与高性能+模式","description":"","frontmatter":{},"headers":[],"relativePath":"Design/iOSOptimization.md","filePath":"Design/iOSOptimization.md"}'),p={name:"Design/iOSOptimization.md"},d=r("",58),u=[d];function c(f,g,q,b,_,S){return t(),e("div",null,u)}const w=a(p,[["render",c]]);export{O as __pageData,w as default}; diff --git a/assets/Design_performance-standard_PerfMeasure_20230517.md.B5V5KI6R.js b/assets/Design_performance-standard_PerfMeasure_20230517.md.B5V5KI6R.js new file mode 100644 index 00000000..bcfaef61 --- /dev/null +++ b/assets/Design_performance-standard_PerfMeasure_20230517.md.B5V5KI6R.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as a,a4 as r}from"./chunks/framework.Br2U662V.js";const d="/minigame-unity-webgl-transform/assets/ios_start_performance.DKHEzdfl.png",o="/minigame-unity-webgl-transform/assets/ios_running_performance.C2YhXpAi.png",n="/minigame-unity-webgl-transform/assets/android_start_performance.B_mgYBnj.png",i="/minigame-unity-webgl-transform/assets/android_running_performance.0A9W-niz.png",q=JSON.parse('{"title":"Unity WebGL小游戏适配方案性能标准","description":"","frontmatter":{},"headers":[],"relativePath":"Design/performance-standard/PerfMeasure_20230517.md","filePath":"Design/performance-standard/PerfMeasure_20230517.md"}'),s={name:"Design/performance-standard/PerfMeasure_20230517.md"},l=r('

Unity WebGL小游戏适配方案性能标准

为什么需要性能评测标准?

Unity性能评测标准用于开发者优化游戏性能数据,提升用户体验。评测标准根据小游戏整体的性能数据表现,结合操作系统、机型分档等多种维度建立。

评测标准细则

性能基线

  1. 性能基线机型并非特定,但建议综合CPU、内存、GPU等选取性能相当的机型
  2. 更新时间:2023-05-17
档位Android参考机型iOS参考机型
高档⼩⽶10(⾼通骁⻰865)iPhone13
中档VIVO S7(⾼通骁⻰765G)、红米k30iPhone11
低档OPPO r9s(通骁⻰625)iPhone7/8/X

指标与测量方法

Unity小游戏的启动可参考启动流程与时序

定义测量方法
首资源包游戏首个data资源文件位于导出目录/webgl/md5.webgl.data.unityweb.bin.txt, CDN使用gzip压缩
WASM代码游戏代码压缩包位于导出目录/minigame/wasmcode/md5.webgl.wasm.code.unityweb.wasm.br, CDN使用gzip压缩
核心资源除首资源包外进入游戏核心玩法所需的资源量业务自定下载,通常为AssetBundle
CALLMAIN引擎和首场景(Loading)初始化通过timelog,或日志查看“CALLMAIN耗时”
游戏初始化完成引擎和首场景完成,出现首个业务场景通过timelog, 或日志查看“游戏启动耗时”
游戏可交互完成游戏核心场景完成通常定义为用户可交互的时机,可通过启动留存上报能力上报统计。eg:休闲游戏为核心玩法,RPG游戏为创角
内存峰值内存峰值进程内存峰值,测量方法请参考优化Unity WebGL的内存
内存异常退出运行时长由于内存不足而使小游戏发生Crash时,当前游戏的运行时长,表示游戏的稳定运行时长通过小游戏数据助手查看(仅包含线上用户数据) 数据路径:数据 - 性能分析 - 运行性能 - 内存异常退出分析
帧率核心玩法的平均帧率测量5分钟以上游戏核心玩法帧率,取平均值
卡顿率核心玩法的平均卡顿率测量5分钟以上游戏核心玩法卡顿率,取平均值

代码与资源体积

能力下载量
首资源包(gzip压缩后)<5MB
WASM代码(br压缩后)<5MB
核心玩法资源<30MB

评测工具

启动性能

使用网络模拟工具1MB/s条件,使用Unity适配提供TimeLog窗口、运行日志或小游戏云测试获取性能数据。

运行性能

使用PerfDog测试,PerfDog记录性能数据并上传,取平均值,每种机型测试3组数据再取平均,内存峰值取最大值。

评测标准

评测标准更新时间:2023-05-17(历史现网标准请查阅文档

评测标准依赖于 现网真实玩家上报的性能数据人工批量测试数据 统计得出。

开发者需要关注哪些性能指标

阶段重点关注指标
启动1. 游戏初始化完成耗时 2. 游戏可交互耗时
运行1. 内存峰值 2. FPS均值 3. 卡顿率 4. 内存异常退出率(iOS) 5. 内存异常退出运行时长
兼容性问题1. 逻辑异常 2. 黑/白屏 3. JS Error

游戏类型说明

分类定义
重度玩法较复杂,通常包含较多游戏场景或支持多人在线游戏(eg: MMO、SLG品类等)
中度包含一定养成玩法、内置内购商城等(eg: 模拟经营、卡牌等)
轻度仅包含简单操作、无养成体系、无内购,以休闲娱乐为主(eg: 棋牌等)

iOS性能评测标准

启动性能

运行性能

重点关注:内存峰值GC后内存峰值内存异常退出率内存异常退出运行时长

Android性能评测标准

启动性能

运行性能

',35),h=[l];function c(m,b,g,p,u,f){return a(),e("div",null,h)}const y=t(s,[["render",c]]);export{q as __pageData,y as default}; diff --git a/assets/Design_performance-standard_PerfMeasure_20230517.md.B5V5KI6R.lean.js b/assets/Design_performance-standard_PerfMeasure_20230517.md.B5V5KI6R.lean.js new file mode 100644 index 00000000..6938ea3c --- /dev/null +++ b/assets/Design_performance-standard_PerfMeasure_20230517.md.B5V5KI6R.lean.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as a,a4 as r}from"./chunks/framework.Br2U662V.js";const d="/minigame-unity-webgl-transform/assets/ios_start_performance.DKHEzdfl.png",o="/minigame-unity-webgl-transform/assets/ios_running_performance.C2YhXpAi.png",n="/minigame-unity-webgl-transform/assets/android_start_performance.B_mgYBnj.png",i="/minigame-unity-webgl-transform/assets/android_running_performance.0A9W-niz.png",q=JSON.parse('{"title":"Unity WebGL小游戏适配方案性能标准","description":"","frontmatter":{},"headers":[],"relativePath":"Design/performance-standard/PerfMeasure_20230517.md","filePath":"Design/performance-standard/PerfMeasure_20230517.md"}'),s={name:"Design/performance-standard/PerfMeasure_20230517.md"},l=r("",35),h=[l];function c(m,b,g,p,u,f){return a(),e("div",null,h)}const y=t(s,[["render",c]]);export{q as __pageData,y as default}; diff --git a/assets/Design_performance-standard_PerfMeasure_old.md.Beja5Gk0.js b/assets/Design_performance-standard_PerfMeasure_old.md.Beja5Gk0.js new file mode 100644 index 00000000..6a172e2d --- /dev/null +++ b/assets/Design_performance-standard_PerfMeasure_old.md.Beja5Gk0.js @@ -0,0 +1 @@ +import{_ as t,c as d,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const u=JSON.parse('{"title":"Unity WebGL小游戏适配方案性能标准","description":"","frontmatter":{},"headers":[],"relativePath":"Design/performance-standard/PerfMeasure_old.md","filePath":"Design/performance-standard/PerfMeasure_old.md"}'),r={name:"Design/performance-standard/PerfMeasure_old.md"},h=e('

Unity WebGL小游戏适配方案性能标准

为什么需要性能评测标准?

性能评测标准希望能引导开发者优化相关性能数据,提升用户体验。

开发者需要关注哪些性能指标

从小游戏的运行周期来看,主要由启动和运行两个阶段产生性能问题。

启动阶段:启动时长,该数据将显著影响用户打开留存率 运行阶段:内存峰值、流畅度、CPU占用、网络等 其他兼容性问题,包括逻辑异常、黑屏等严重问题

评测标准细则

性能基线

机型档位

能力Android参考机型iOS参考机型
高档⼩⽶10(⾼通骁⻰865)iPhone13
中档VIVO S7(⾼通骁⻰765G) 红米k30iPhone11
低档OPPO r9s(通骁⻰625)iPhone7/8/X

指标与测量方法

Unity小游戏的启动可参考启动流程与时序

定义测量方法
首资源包游戏首个data资源文件位于导出目录/webgl/md5.webgl.data.unityweb.bin.txt, CDN使用gzip压缩
WASM代码游戏代码压缩包位于导出目录/minigame/wasmcode/md5.webgl.wasm.code.unityweb.wasm.br, CDN使用gzip压缩
核心资源除首资源包外进入游戏核心玩法所需的资源量业务自定下载,通常为AssetBundle
callmain引擎和首场景(Loading)初始化通过timelog,或日志查看“callMain耗时”
游戏初始化完成引擎和手场景完成,出现首个业务场景通过timelog, 或日志查看“游戏启动耗时”
游戏可交互完成游戏核心场景完成业务自定义,典型地:休闲游戏为核心玩法,RPG游戏为创角
内存内存峰值进程内存峰值,测量方法请参考优化Unity WebGL的内存
帧率核心玩法的平均帧率测量5分钟以上游戏核心玩法帧率,取平均值

评测工具

启动性能: 使用网络模拟工具1MB/s条件,使用Unity适配提供TimeLog窗口或运行日志获取性能数据。

运行性能: 使用PerfDog测试,PerfDog记录性能数据并上传,取平均值,每种机型测试3组数据再取平均,内存峰值取最大值。

代码与资源体积

能力下载量
首包资源(gzip压缩后)<5M
WASM代码(br压缩后)<5M
核心玩法资源<30MB

Android 评测标准

高档机中档机低档机
首资源包下载<3s<4s<5s
callmain<3s<5s<7s
游戏初始化完成<8s<10s<12s
游戏可交互完成<12s<15s<20s

运行性能

高档机中档机低档机
内存<1.5G<1.2G<1G
帧率>50>40>30

iOS 评测标准

高档机中档机低档机
首资源包下载<3s<4s<5s
callmain<2s<4s<5s
游戏初始化完成<6s<8s<10s
游戏可交互完成<10s<12s<15s

运行性能

高档机中档机低档机
内存<1.4G<1.2G<800MB
帧率>50>40>30
',26),l=[h];function o(i,s,n,b,c,p){return a(),d("div",null,l)}const _=t(r,[["render",o]]);export{u as __pageData,_ as default}; diff --git a/assets/Design_performance-standard_PerfMeasure_old.md.Beja5Gk0.lean.js b/assets/Design_performance-standard_PerfMeasure_old.md.Beja5Gk0.lean.js new file mode 100644 index 00000000..c5ab73b2 --- /dev/null +++ b/assets/Design_performance-standard_PerfMeasure_old.md.Beja5Gk0.lean.js @@ -0,0 +1 @@ +import{_ as t,c as d,o as a,a4 as e}from"./chunks/framework.Br2U662V.js";const u=JSON.parse('{"title":"Unity WebGL小游戏适配方案性能标准","description":"","frontmatter":{},"headers":[],"relativePath":"Design/performance-standard/PerfMeasure_old.md","filePath":"Design/performance-standard/PerfMeasure_old.md"}'),r={name:"Design/performance-standard/PerfMeasure_old.md"},h=e("",26),l=[h];function o(i,s,n,b,c,p){return a(),d("div",null,l)}const _=t(r,[["render",o]]);export{u as __pageData,_ as default}; diff --git a/assets/Design_video.md.DUVWhAg-.js b/assets/Design_video.md.DUVWhAg-.js new file mode 100644 index 00000000..0b1f224d --- /dev/null +++ b/assets/Design_video.md.DUVWhAg-.js @@ -0,0 +1,16 @@ +import{_ as a,c as s,o as n,a4 as p}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"视频设计规范","description":"","frontmatter":{},"headers":[],"relativePath":"Design/video.md","filePath":"Design/video.md"}'),e={name:"Design/video.md"},l=p(`

视频设计规范

建议启动视频内带有团队宣传logo动画,游戏logo动画,带有吸引力的游戏玩法视频

视频格式参考:

Loading 视频规范:
+横屏视频:16:9(素材分辨率:960 px × 540 px)
+竖屏视频:9:16(视频分辨率:750 px × 1334 px)
+视频尺寸:不超过 10MB
+视频时长:6~15 秒
+支持格式:MP4
+注:视频会在 Loading 期间重复播放
+----
+以下为视频建议参数(仅供参考)
+视频编码:H.264
+FPS:24
+码率:小于 800 kbit/s
+MP4 Profile:Main
+音轨格式:AAC
+音轨Sample Rate:44.1 kHz
+音轨 Datarate:96 kbit/sec
`,4),i=[l];function o(t,c,r,d,_,h){return n(),s("div",null,i)}const u=a(e,[["render",o]]);export{m as __pageData,u as default}; diff --git a/assets/Design_video.md.DUVWhAg-.lean.js b/assets/Design_video.md.DUVWhAg-.lean.js new file mode 100644 index 00000000..491a69ab --- /dev/null +++ b/assets/Design_video.md.DUVWhAg-.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as n,a4 as p}from"./chunks/framework.Br2U662V.js";const m=JSON.parse('{"title":"视频设计规范","description":"","frontmatter":{},"headers":[],"relativePath":"Design/video.md","filePath":"Design/video.md"}'),e={name:"Design/video.md"},l=p("",4),i=[l];function o(t,c,r,d,_,h){return n(),s("div",null,i)}const u=a(e,[["render",o]]);export{m as __pageData,u as default}; diff --git a/assets/Design_wasmWaterMark.md.C4-A8aK7.js b/assets/Design_wasmWaterMark.md.C4-A8aK7.js new file mode 100644 index 00000000..8b546316 --- /dev/null +++ b/assets/Design_wasmWaterMark.md.C4-A8aK7.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/extension-panel.CY9x27Ol.js";import{_ as e,c as t,o as r,a4 as s}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/panel.SGItx1qt.png",p="/minigame-unity-webgl-transform/assets/add.CWlt1hFU.png",i="/minigame-unity-webgl-transform/assets/icon.BKg32493.png",k=JSON.parse('{"title":"wasm水印插件","description":"","frontmatter":{},"headers":[],"relativePath":"Design/wasmWaterMark.md","filePath":"Design/wasmWaterMark.md"}'),c={name:"Design/wasmWaterMark.md"},m=s('

wasm水印插件

如果同时使用代码分包插件,需要在使用分包插件后,再使用水印插件对分包后的wasm代码打水印

说明:

在平台原有相似度检测基础上,为进一步保障wasm小游戏的代码安全,引入wasm水印机制 已添加水印的wasm游戏,若遭遇恶意人员扒包抄袭,平台可通过水印准确检测出游戏的原作者,并处罚恶意抄袭人员

使用方式:

插件依赖微信开发者工具1.05.2104251 RC 及以上,稳定版 1.05.2105100 及以上

添加插件

部分示意图可能有出入,请升级微信开发者工具版本

打开拓展设置,找到水印工具,添加插件

使用插件

在目录树上方工具栏找到水印工具icon,点击显示水印插件面板

项目首次使用插件默认会启用打水印功能。

插件检测并展示项目中的wasm文件,开发者自行决定是否需要上传并打水印。

点击上传按钮后,插件会自动执行逻辑

正在打水印

下载中

已完成

完成后,即可测试小游戏是否正常运行,若有异常,可点击还原wasm文件到初始状态,重新打水印。

当有两个wasm文件时,操作同理

若不想使用水印功能,点击关闭水印,wasm代码回到初始状态

注意

打水印和下载过程可能会有一定耗时,请耐心等待。

若AppID为测试号,或者是小程序AppID,会出现如下界面,更换正确的AppID后重新检测即可

',34),n=[m];function d(h,l,w,u,g,_){return r(),t("div",null,n)}const f=e(c,[["render",d]]);export{k as __pageData,f as default}; diff --git a/assets/Design_wasmWaterMark.md.C4-A8aK7.lean.js b/assets/Design_wasmWaterMark.md.C4-A8aK7.lean.js new file mode 100644 index 00000000..836f4485 --- /dev/null +++ b/assets/Design_wasmWaterMark.md.C4-A8aK7.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/extension-panel.CY9x27Ol.js";import{_ as e,c as t,o as r,a4 as s}from"./chunks/framework.Br2U662V.js";const o="/minigame-unity-webgl-transform/assets/panel.SGItx1qt.png",p="/minigame-unity-webgl-transform/assets/add.CWlt1hFU.png",i="/minigame-unity-webgl-transform/assets/icon.BKg32493.png",k=JSON.parse('{"title":"wasm水印插件","description":"","frontmatter":{},"headers":[],"relativePath":"Design/wasmWaterMark.md","filePath":"Design/wasmWaterMark.md"}'),c={name:"Design/wasmWaterMark.md"},m=s("",34),n=[m];function d(h,l,w,u,g,_){return r(),t("div",null,n)}const f=e(c,[["render",d]]);export{k as __pageData,f as default}; diff --git a/assets/IOSDevicePixelRatio.B1RP7CsG.png b/assets/IOSDevicePixelRatio.B1RP7CsG.png new file mode 100644 index 00000000..3e856e22 Binary files /dev/null and b/assets/IOSDevicePixelRatio.B1RP7CsG.png differ diff --git a/assets/README.md.B8Z9A7kF.js b/assets/README.md.B8Z9A7kF.js new file mode 100644 index 00000000..62967b97 --- /dev/null +++ b/assets/README.md.B8Z9A7kF.js @@ -0,0 +1 @@ +import{_ as t}from"./chunks/showcase25.C-ERrYO-.js";import{_ as e,c as a,o as r,a4 as i}from"./chunks/framework.Br2U662V.js";const n="/minigame-unity-webgl-transform/assets/showcase34.B1YJ7Mgk.png",o="/minigame-unity-webgl-transform/assets/showcase32.oc_3wbrg.png",s="/minigame-unity-webgl-transform/assets/showcase33.BLPWsQzS.png",y=JSON.parse('{"title":"微信小游戏Unity/团结引擎适配方案","description":"","frontmatter":{},"headers":[],"relativePath":"README.md","filePath":"README.md"}'),l={name:"README.md"},m=i('

微信小游戏Unity/团结引擎适配方案

欢迎使用 Unity WebGL 小游戏适配方案(又称Unity/团结引擎快适配),本方案设计目的是降低 Unity 游戏转换到微信小游戏的开发成本。基于WebAssembly技术,无需更换Unity引擎与重写核心代码的情况下将原有游戏项目适配到微信小游戏。

官方文档:https://wechat-miniprogram.github.io/minigame-unity-webgl-transform/

方案特点

转换案例

我叫MT2(回合战斗)旅行串串(休闲)谜题大陆(SLG)热血神剑(MMO)

查阅更多转换案例

安装与使用

PackageManager(git安装URL): https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git

UnityPackage:下载地址

版本更新请查看更新日志,Unity/团结引擎详细安装请查阅SDK安装指引

',13),h=[m];function g(p,c,d,b,f,_){return r(),a("div",null,h)}const k=e(l,[["render",g]]);export{y as __pageData,k as default}; diff --git a/assets/README.md.B8Z9A7kF.lean.js b/assets/README.md.B8Z9A7kF.lean.js new file mode 100644 index 00000000..cfae0a26 --- /dev/null +++ b/assets/README.md.B8Z9A7kF.lean.js @@ -0,0 +1 @@ +import{_ as t}from"./chunks/showcase25.C-ERrYO-.js";import{_ as e,c as a,o as r,a4 as i}from"./chunks/framework.Br2U662V.js";const n="/minigame-unity-webgl-transform/assets/showcase34.B1YJ7Mgk.png",o="/minigame-unity-webgl-transform/assets/showcase32.oc_3wbrg.png",s="/minigame-unity-webgl-transform/assets/showcase33.BLPWsQzS.png",y=JSON.parse('{"title":"微信小游戏Unity/团结引擎适配方案","description":"","frontmatter":{},"headers":[],"relativePath":"README.md","filePath":"README.md"}'),l={name:"README.md"},m=i("",13),h=[m];function g(p,c,d,b,f,_){return r(),a("div",null,h)}const k=e(l,[["render",g]]);export{y as __pageData,k as default}; diff --git a/assets/WXFont.GXJDQ91G.png b/assets/WXFont.GXJDQ91G.png new file mode 100644 index 00000000..9abeeb48 Binary files /dev/null and b/assets/WXFont.GXJDQ91G.png differ diff --git a/assets/add.CWlt1hFU.png b/assets/add.CWlt1hFU.png new file mode 100644 index 00000000..3fa9b670 Binary files /dev/null and b/assets/add.CWlt1hFU.png differ diff --git a/assets/addPlugin.wW8f1Te-.png b/assets/addPlugin.wW8f1Te-.png new file mode 100644 index 00000000..f4f84e4e Binary files /dev/null and b/assets/addPlugin.wW8f1Te-.png differ diff --git a/assets/addplugin.DpVfb8Rz.png b/assets/addplugin.DpVfb8Rz.png new file mode 100644 index 00000000..b60c7fe9 Binary files /dev/null and b/assets/addplugin.DpVfb8Rz.png differ diff --git a/assets/addressable10.CVteO2U4.png b/assets/addressable10.CVteO2U4.png new file mode 100644 index 00000000..521288bd Binary files /dev/null and b/assets/addressable10.CVteO2U4.png differ diff --git a/assets/addressable2.Dk3Ey3UQ.png b/assets/addressable2.Dk3Ey3UQ.png new file mode 100644 index 00000000..1ac8197f Binary files /dev/null and b/assets/addressable2.Dk3Ey3UQ.png differ diff --git a/assets/addressable3.D_qvXfAd.png b/assets/addressable3.D_qvXfAd.png new file mode 100644 index 00000000..ed1732ac Binary files /dev/null and b/assets/addressable3.D_qvXfAd.png differ diff --git a/assets/addressable5.CfIJPhUo.png b/assets/addressable5.CfIJPhUo.png new file mode 100644 index 00000000..9600a3b2 Binary files /dev/null and b/assets/addressable5.CfIJPhUo.png differ diff --git a/assets/addressable7.D5VA3cAj.png b/assets/addressable7.D5VA3cAj.png new file mode 100644 index 00000000..2b434f9d Binary files /dev/null and b/assets/addressable7.D5VA3cAj.png differ diff --git a/assets/addressable9.BGoeNYVl.png b/assets/addressable9.BGoeNYVl.png new file mode 100644 index 00000000..f3b32594 Binary files /dev/null and b/assets/addressable9.BGoeNYVl.png differ diff --git a/assets/android_running_performance.0A9W-niz.png b/assets/android_running_performance.0A9W-niz.png new file mode 100644 index 00000000..41bd1126 Binary files /dev/null and b/assets/android_running_performance.0A9W-niz.png differ diff --git a/assets/android_running_performance.DuhaNO5M.png b/assets/android_running_performance.DuhaNO5M.png new file mode 100644 index 00000000..0f498c8f Binary files /dev/null and b/assets/android_running_performance.DuhaNO5M.png differ diff --git a/assets/android_start_performance.BEBLnORD.png b/assets/android_start_performance.BEBLnORD.png new file mode 100644 index 00000000..aa945d2c Binary files /dev/null and b/assets/android_start_performance.BEBLnORD.png differ diff --git a/assets/android_start_performance.B_mgYBnj.png b/assets/android_start_performance.B_mgYBnj.png new file mode 100644 index 00000000..6a6f4f09 Binary files /dev/null and b/assets/android_start_performance.B_mgYBnj.png differ diff --git a/assets/androidprofile1.CWmGtjYo.png b/assets/androidprofile1.CWmGtjYo.png new file mode 100644 index 00000000..5b46c2f9 Binary files /dev/null and b/assets/androidprofile1.CWmGtjYo.png differ diff --git a/assets/androidprofile2.BV1rYep4.png b/assets/androidprofile2.BV1rYep4.png new file mode 100644 index 00000000..b1f17645 Binary files /dev/null and b/assets/androidprofile2.BV1rYep4.png differ diff --git a/assets/androidprofile3.C3xDSI1N.png b/assets/androidprofile3.C3xDSI1N.png new file mode 100644 index 00000000..ba9dc03a Binary files /dev/null and b/assets/androidprofile3.C3xDSI1N.png differ diff --git a/assets/androidprofile4.D2zXydy3.png b/assets/androidprofile4.D2zXydy3.png new file mode 100644 index 00000000..bd9aa822 Binary files /dev/null and b/assets/androidprofile4.D2zXydy3.png differ diff --git a/assets/androidprofile5.v23kq4o6.png b/assets/androidprofile5.v23kq4o6.png new file mode 100644 index 00000000..7c6a7f1f Binary files /dev/null and b/assets/androidprofile5.v23kq4o6.png differ diff --git a/assets/app-fxzg.CwsGWMYA.jpeg b/assets/app-fxzg.CwsGWMYA.jpeg new file mode 100644 index 00000000..74be75fb Binary files /dev/null and b/assets/app-fxzg.CwsGWMYA.jpeg differ diff --git a/assets/app-jhywl.4N6roqlx.jpeg b/assets/app-jhywl.4N6roqlx.jpeg new file mode 100644 index 00000000..3919ac65 Binary files /dev/null and b/assets/app-jhywl.4N6roqlx.jpeg differ diff --git a/assets/app-mmdys.D2V6c5GV.jpeg b/assets/app-mmdys.D2V6c5GV.jpeg new file mode 100644 index 00000000..cd1bd49a Binary files /dev/null and b/assets/app-mmdys.D2V6c5GV.jpeg differ diff --git a/assets/app.q0bjKtWa.js b/assets/app.q0bjKtWa.js new file mode 100644 index 00000000..efa7d9ab --- /dev/null +++ b/assets/app.q0bjKtWa.js @@ -0,0 +1 @@ +import{j as o,a5 as p,a6 as u,a7 as l,a8 as c,a9 as f,aa as d,ab as m,ac as h,ad as g,ae as A,Y as P,d as _,u as v,l as y,z as C,af as E,ag as b,ah as w,ai as R}from"./chunks/framework.Br2U662V.js";import{t as S}from"./chunks/theme.DuJp6K1e.js";function i(e){if(e.extends){const a=i(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=i(S),T=_({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=v();return y(()=>{C(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&E(),b(),w(),s.setup&&s.setup(),()=>R(s.Layout)}});async function D(){globalThis.__VITEPRESS__=!0;const e=L(),a=j();a.provide(u,e);const t=l(e.route);return a.provide(c,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function j(){return h(T)}function L(){let e=o,a;return g(t=>{let n=A(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=P(()=>import(n),[])),o&&(e=!1),r},s.NotFound)}o&&D().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{D as createApp}; diff --git a/assets/asset-analysis-window.D04lUzYU.png b/assets/asset-analysis-window.D04lUzYU.png new file mode 100644 index 00000000..06344481 Binary files /dev/null and b/assets/asset-analysis-window.D04lUzYU.png differ diff --git a/assets/assetbundle-unnormal-memory.CY0FXhT_.png b/assets/assetbundle-unnormal-memory.CY0FXhT_.png new file mode 100644 index 00000000..c61ff3d2 Binary files /dev/null and b/assets/assetbundle-unnormal-memory.CY0FXhT_.png differ diff --git a/assets/auth_plugin.DqkcQvPd.png b/assets/auth_plugin.DqkcQvPd.png new file mode 100644 index 00000000..8b52b4e6 Binary files /dev/null and b/assets/auth_plugin.DqkcQvPd.png differ diff --git a/assets/benchmarkprofile.BvHHzfgK.png b/assets/benchmarkprofile.BvHHzfgK.png new file mode 100644 index 00000000..d6a82b3f Binary files /dev/null and b/assets/benchmarkprofile.BvHHzfgK.png differ diff --git a/assets/buildtemplateprocess.BJDyZOCI.png b/assets/buildtemplateprocess.BJDyZOCI.png new file mode 100644 index 00000000..c0b7fc6f Binary files /dev/null and b/assets/buildtemplateprocess.BJDyZOCI.png differ diff --git a/assets/cache_path.DmEqMbAH.png b/assets/cache_path.DmEqMbAH.png new file mode 100644 index 00000000..3eed4d54 Binary files /dev/null and b/assets/cache_path.DmEqMbAH.png differ diff --git a/assets/cf-free.BM2qYFhS.jpg b/assets/cf-free.BM2qYFhS.jpg new file mode 100644 index 00000000..8bbb545a Binary files /dev/null and b/assets/cf-free.BM2qYFhS.jpg differ diff --git a/assets/cf-overview.CV2FOQaP.png b/assets/cf-overview.CV2FOQaP.png new file mode 100644 index 00000000..d74762d5 Binary files /dev/null and b/assets/cf-overview.CV2FOQaP.png differ diff --git a/assets/change-format.Ceib4V6i.png b/assets/change-format.Ceib4V6i.png new file mode 100644 index 00000000..1b995b82 Binary files /dev/null and b/assets/change-format.Ceib4V6i.png differ diff --git a/assets/change-max-size.DDYD-ESI.png b/assets/change-max-size.DDYD-ESI.png new file mode 100644 index 00000000..93399134 Binary files /dev/null and b/assets/change-max-size.DDYD-ESI.png differ diff --git a/assets/check-version.BiswJbE4.png b/assets/check-version.BiswJbE4.png new file mode 100644 index 00000000..b383fb2b Binary files /dev/null and b/assets/check-version.BiswJbE4.png differ diff --git a/assets/choose-env.Cy4xcKaE.jpg b/assets/choose-env.Cy4xcKaE.jpg new file mode 100644 index 00000000..7a8404a2 Binary files /dev/null and b/assets/choose-env.Cy4xcKaE.jpg differ diff --git a/assets/chromeload.sYqunEFg.png b/assets/chromeload.sYqunEFg.png new file mode 100644 index 00000000..45a72fc8 Binary files /dev/null and b/assets/chromeload.sYqunEFg.png differ diff --git a/assets/chunks/@localSearchIndexroot.DOuO4YaK.js b/assets/chunks/@localSearchIndexroot.DOuO4YaK.js new file mode 100644 index 00000000..2d0671cc --- /dev/null +++ b/assets/chunks/@localSearchIndexroot.DOuO4YaK.js @@ -0,0 +1 @@ +const t=`{"documentCount":1137,"nextId":1137,"documentIds":{"0":"/minigame-unity-webgl-transform/CHANGELOG.html#稳定版本","1":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-10-18-【预发布】","2":"/minigame-unity-webgl-transform/CHANGELOG.html#feature","3":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed","4":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-10-8-【重要更新】","5":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-1","6":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-1","7":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-8-13-【重要更新】","8":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-2","9":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-2","10":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-7-09-【普通更新】","11":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-3","12":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-3","13":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-5-17-【普通更新】","14":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-4","15":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-5-15-【普通更新】","16":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-4","17":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-4-26-【普通更新】","18":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-5","19":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-4-17-【普通更新】","20":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-5","21":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-6","22":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-4-3-【重要更新】","23":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-7","24":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-3-28-【普通更新】","25":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-8","26":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-3-5-【普通更新】","27":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-9","28":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-1-18-【普通更新】","29":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-10","30":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-1-15-【普通更新】","31":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-6","32":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-11","33":"/minigame-unity-webgl-transform/CHANGELOG.html#_2024-1-2-【重要更新】","34":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-7","35":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-12","36":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-12-18-【重要更新】","37":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-8","38":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-13","39":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-12-12-【重要更新】","40":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-9","41":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-12-08-【重要更新】","42":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-10","43":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-14","44":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-11-29-【普通更新】","45":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-15","46":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-11-28","47":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-11","48":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-16","49":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-11-10","50":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-12","51":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-11-02","52":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-17","53":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-10-20","54":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-13","55":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-18","56":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-10-11【普通更新】","57":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-14","58":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-9-26","59":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-15","60":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-19","61":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-09-20","62":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-16","63":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-09-01","64":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-17","65":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-20","66":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-08-24","67":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-18","68":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-21","69":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-08-18","70":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-19","71":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-22","72":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-08-10","73":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-20","74":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-08-3","75":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-21","76":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-23","77":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-07-27","78":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-22","79":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-24","80":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-07-20","81":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-23","82":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-25","83":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-07-12","84":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-24","85":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-07-05","86":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-25","87":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-26","88":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-06-29","89":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-26","90":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-27","91":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-06-16","92":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-28","93":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-06-14","94":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-27","95":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-29","96":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-06-12","97":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-30","98":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-06-7","99":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-28","100":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-31","101":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-06-1","102":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-29","103":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-32","104":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-05-24","105":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-30","106":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-33","107":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-05-22","108":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-31","109":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-34","110":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-04-26","111":"/minigame-unity-webgl-transform/CHANGELOG.html#changed","112":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-03-31","113":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-32","114":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-02-22","115":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-33","116":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-02-15","117":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-35","118":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-02-9","119":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-34","120":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-36","121":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-01-17","122":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-37","123":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-01-17-1","124":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-35","125":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-38","126":"/minigame-unity-webgl-transform/CHANGELOG.html#_2023-01-04","127":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-36","128":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-39","129":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-12-28","130":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-37","131":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-40","132":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-12-22","133":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-41","134":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-12-21","135":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-38","136":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-12-7","137":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-39","138":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-42","139":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-11-30","140":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-40","141":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-11-23","142":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-41","143":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-43","144":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-11-17","145":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-42","146":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-11-9","147":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-43","148":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-44","149":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-10-27","150":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-44","151":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-45","152":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-10-20","153":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-45","154":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-10-12","155":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-46","156":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-46","157":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-9-28","158":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-47","159":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-47","160":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-9-21","161":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-48","162":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-48","163":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-9-13","164":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-49","165":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-9-8","166":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-49","167":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-50","168":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-9-7","169":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-50","170":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-8-31","171":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-51","172":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-8-26","173":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-51","174":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-8-17","175":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-52","176":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-8-11","177":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-52","178":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-8-10","179":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-53","180":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-53","181":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-7-28","182":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-54","183":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-7-20","184":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-55","185":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-54","186":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-56","187":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-7-14","188":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-55","189":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-7-1","190":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-56","191":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-30","192":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-57","193":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-28","194":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-57","195":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-58","196":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-18","197":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-59","198":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-16","199":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-58","200":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-60","201":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-13","202":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-61","203":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-8","204":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-59","205":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-62","206":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-7","207":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-60","208":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-6-1","209":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-61","210":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-5-31","211":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-62","212":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-5-30","213":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-63","214":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-5-26","215":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-1","216":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-64","217":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-5-24","218":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-63","219":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-29","220":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-65","221":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-26","222":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-66","223":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-64","224":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-24","225":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-67","226":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-22","227":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-68","228":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-65","229":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-18","230":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-66","231":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-14","232":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-67","233":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-4-11","234":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-2","235":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-3-29","236":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-3","237":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-3-22","238":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-4","239":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-3-7","240":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-5","241":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-3-7-1","242":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-6","243":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-2-17","244":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-7","245":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-2-15","246":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-69","247":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-2-14","248":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-68","249":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-2-11","250":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-69","251":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-26","252":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-70","253":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-25","254":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-70","255":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-24","256":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-71","257":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-21","258":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-72","259":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-8","260":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-20","261":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-73","262":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-17","263":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-71","264":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-9","265":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-13","266":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-72","267":"/minigame-unity-webgl-transform/CHANGELOG.html#_2022-1-7","268":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-73","269":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-31","270":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-74","271":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-30","272":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-75","273":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-20","274":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-76","275":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-16","276":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-74","277":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-10","278":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-77","279":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-06","280":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-75","281":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-78","282":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-12-02","283":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-79","284":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-11-30","285":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-10","286":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-80","287":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-11-19","288":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-81","289":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-11-18","290":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-76","291":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-82","292":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-11","293":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-10-26","294":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-77","295":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-10-09","296":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-78","297":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-09-23","298":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-83","299":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-09-22","300":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-79","301":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-80","302":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-81","303":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-09-14","304":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-82","305":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-84","306":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-09-06","307":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-83","308":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-8-20","309":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-84","310":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-8-12","311":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-85","312":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-8-10","313":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-12","314":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-08-05","315":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-86","316":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-08-04","317":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-85","318":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-08-02","319":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-86","320":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-08-01","321":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-13","322":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-31","323":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-87","324":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-14","325":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-26","326":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-88","327":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-26-1","328":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-89","329":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-20","330":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-87","331":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-19","332":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-15","333":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-13","334":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-88","335":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-16","336":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-09","337":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-89","338":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-07-02","339":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-90","340":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-06-30","341":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-91","342":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-90","343":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-06-29","344":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-92","345":"/minigame-unity-webgl-transform/CHANGELOG.html#feature-91","346":"/minigame-unity-webgl-transform/CHANGELOG.html#removed","347":"/minigame-unity-webgl-transform/CHANGELOG.html#changed-17","348":"/minigame-unity-webgl-transform/CHANGELOG.html#others","349":"/minigame-unity-webgl-transform/CHANGELOG.html#_2021-06-10","350":"/minigame-unity-webgl-transform/CHANGELOG.html#fixed-93","351":"/minigame-unity-webgl-transform/Design/AndroidProfile.html#使用android-cpu-profiler性能调优","352":"/minigame-unity-webgl-transform/Design/AssetDescription.html#minigameconfig-asset-配置文件说明","353":"/minigame-unity-webgl-transform/Design/AssetDescription.html#projectconfig","354":"/minigame-unity-webgl-transform/Design/AssetDescription.html#sdkoptions","355":"/minigame-unity-webgl-transform/Design/AssetDescription.html#compileoptions","356":"/minigame-unity-webgl-transform/Design/AssetDescription.html#compresstexture","357":"/minigame-unity-webgl-transform/Design/AssetDescription.html#playerprefskeys","358":"/minigame-unity-webgl-transform/Design/AssetDescription.html#fontoptions","359":"/minigame-unity-webgl-transform/Design/AssetOptimization.html#资源优化","360":"/minigame-unity-webgl-transform/Design/AssetOptimization.html#工具入口","361":"/minigame-unity-webgl-transform/Design/AssetOptimization.html#工具介绍","362":"/minigame-unity-webgl-transform/Design/AssetOptimization.html#texture","363":"/minigame-unity-webgl-transform/Design/AssetOptimization.html#优化建议","364":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#音视频适配","365":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#音频","366":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#兼容原理","367":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#qa","368":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#视频","369":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#videoplayer-支持版本","370":"/minigame-unity-webgl-transform/Design/AudioAndVideo.html#qa-1","371":"/minigame-unity-webgl-transform/Design/BackendServiceStartup.html#后端服务指引","372":"/minigame-unity-webgl-transform/Design/BackendServiceStartup.html#后端服务模式","373":"/minigame-unity-webgl-transform/Design/BackendServiceStartup.html#自建后端服务","374":"/minigame-unity-webgl-transform/Design/BackendServiceStartup.html#云开发","375":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#配置构建模板","376":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#简介","377":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#结构说明","378":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#新版本sdk引起的冲突提醒","379":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#消除冲突提醒","380":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#json配置合并","381":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#构建模板前后不同时机的钩子","382":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#钩子介绍","383":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#使用钩子","384":"/minigame-unity-webgl-transform/Design/BuildTemplate.html#buildtemplatehelper介绍","385":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#微信小游戏压缩纹理工具2-0-beta","386":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#概述","387":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#使用建议","388":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#unity-版本支持问题","389":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#使用说明","390":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_1-安装-node-js","391":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_2-构建-bundle-文件","392":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#构建前的纹理格式配置说明","393":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#astc格式配置说明","394":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_3-导出游戏","395":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_4-执行压缩纹理","396":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_5-上传cdn","397":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#webgl2-0-支持说明-beta","398":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#忽略配置说明","399":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#首资源包优化说明","400":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#新版本异常回退说明","401":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#原理解释","402":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#q-a","403":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_1-生成的纹理太大","404":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_2-资源上传至cdn的注意事项","405":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_3-非4倍数的资源处理底层逻辑","406":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_4-node-js异常处理","407":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_5-分离纹理后各自单独下载是否会增加下载开销","408":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#_6-macos系统执行报错-system-drawing-gdiplus-threw-an-exception","409":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#解决方案一","410":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#解决方案二","411":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#微信压缩纹理api介绍","412":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#wxassetstexttools-compresstext","413":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#说明","414":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#参数","415":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#wxassetstexttools-getassetbundles","416":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#说明-1","417":"/minigame-unity-webgl-transform/Design/CompressedTexture.html#参数-1","418":"/minigame-unity-webgl-transform/Design/CustomLoading.html#启动封面","419":"/minigame-unity-webgl-transform/Design/CustomLoading.html#完整配置","420":"/minigame-unity-webgl-transform/Design/CustomLoading.html#转换插件配置","421":"/minigame-unity-webgl-transform/Design/CustomLoading.html#game-js配置","422":"/minigame-unity-webgl-transform/Design/CustomLoading.html#默认效果","423":"/minigame-unity-webgl-transform/Design/CustomLoading.html#定制效果","424":"/minigame-unity-webgl-transform/Design/CustomSDK.html#自定义sdk调用","425":"/minigame-unity-webgl-transform/Design/CustomSDK.html#版本要求","426":"/minigame-unity-webgl-transform/Design/CustomSDK.html#代码示例","427":"/minigame-unity-webgl-transform/Design/CustomURP.html#定制微信小游戏的-urp-管线","428":"/minigame-unity-webgl-transform/Design/CustomURP.html#本地化-urp-包","429":"/minigame-unity-webgl-transform/Design/CustomURP.html#准备条件编译宏","430":"/minigame-unity-webgl-transform/Design/CustomURP.html#定制本地化-urp-管线","431":"/minigame-unity-webgl-transform/Design/CustomURP.html#供参考的-urp-定制版本","432":"/minigame-unity-webgl-transform/Design/CustomURP.html#微信-urp-定制版本的性能数据对比","433":"/minigame-unity-webgl-transform/Design/CustomURP.html#注意事项","434":"/minigame-unity-webgl-transform/Design/CustomURP.html#参考","435":"/minigame-unity-webgl-transform/Design/DataCDN.html#资源部署与缓存","436":"/minigame-unity-webgl-transform/Design/DataCDN.html#资源部署","437":"/minigame-unity-webgl-transform/Design/DataCDN.html#首资源包","438":"/minigame-unity-webgl-transform/Design/DataCDN.html#assets","439":"/minigame-unity-webgl-transform/Design/DataCDN.html#streamingassets","440":"/minigame-unity-webgl-transform/Design/DataCDN.html#资源服务器注意事项","441":"/minigame-unity-webgl-transform/Design/DataCDN.html#资源更新说明","442":"/minigame-unity-webgl-transform/Design/DataCDN.html#资源缓存","443":"/minigame-unity-webgl-transform/Design/DataCDN.html#资源缓存规则","444":"/minigame-unity-webgl-transform/Design/DebugAndException.html#错误调试与异常排查","445":"/minigame-unity-webgl-transform/Design/DebugAndException.html#如何排查程序中出现的异常","446":"/minigame-unity-webgl-transform/Design/DebugAndException.html#如何查看日志","447":"/minigame-unity-webgl-transform/Design/DebugAndException.html#如何通过错误堆栈查找源代码问题","448":"/minigame-unity-webgl-transform/Design/DebugAndException.html#使用profiling-funcs","449":"/minigame-unity-webgl-transform/Design/DebugAndException.html#使用symbols文件可读函数名","450":"/minigame-unity-webgl-transform/Design/DebugAndException.html#影响异常错误的导出选项","451":"/minigame-unity-webgl-transform/Design/DebugAndException.html#enable-exceptions","452":"/minigame-unity-webgl-transform/Design/DebugAndException.html#debug-symbols","453":"/minigame-unity-webgl-transform/Design/DebugAndException.html#development-build","454":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#技术常见问题qa","455":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#工具使用","456":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_1-微信开发者工具打开时提示-app-json未找到","457":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_2-微信开发者工具打开时提示-找不到game-json或读取错误","458":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_3-如何在真机上预览游戏","459":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_4-如何在真机上进行调试和错误日志排查","460":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_5-unity-playersettings导出选项中使用-brotli-或-gzip-使用微信开发者工具无法启动游戏","461":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_6-使用代码分包的情况下-启动游戏出现-首次拉取代码分包-提示","462":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_7-微信开发者工具提示-资源下载失败","463":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_8-微信开发者工具能正常打开游戏-但android卡在首屏-资源下载失败","464":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_9-开发者工具提示-插件申请成功-待审核确认","465":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_10-内网开发时-微信开发者工具服务异常","466":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_11-开发者工具提示pluginid-wx7a727ff7d940bb3f-permission-deny字样错误","467":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_12-小游戏包中的webgl-wasm-symbols-unityweb不会被上传-是做什么用的","468":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_13-如何自定义接入构建流程","469":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#unity-webgl","470":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_1-能否使用system-net命名空间下的接口","471":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_2-小游戏启动出现-unable-to-load-dll","472":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_3-能否使用system-file相关接口做文件存储","473":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_4-如何接入第三方的js-sdk-能写js脚本和c-进行交互吗","474":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_5-小游戏的中文字体不显示-但editor没问题","475":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_6-游戏逻辑是否能使用lua","476":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_7-touch事件丢失或错误-导致多点触控不正确","477":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_8-显示黑屏-运行提示大量shader编译错误","478":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_9-unity-fmod音频插件是否支持","479":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_10-mac-系统下-unity-构建-webgl-项目报failed-running-il2cppcore-il2cppcore-dll-错误解决办法","480":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_11-引擎代码裁剪级别-managed-striping-level-应该如何设置","481":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_12-使用xlua等方案在webgl平台报-argumentexception-destination-array-was-not-long-enough","482":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#平台适配","483":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_1-文本输入框点击无法输入-没有弹出输入法","484":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_2-高性能模式下ios无法加载-但android和微信开发者工具没问题","485":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_3-android运行达到满帧较为流畅-ios性能差","486":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_4-小游戏中能插入超链接跳转网页吗","487":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_5-小游戏是否支持unity-videoplayer","488":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_6-小游戏应该使用哪个接口进行限制帧率","489":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_7-unity-audio音频是否需要使用小游戏音频适配","490":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_8-playerpref或用户数据存储失效","491":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_9-微信接口提示-fail-require-user-interaction-only-in-touchend-event","492":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_10-团结引擎导出的小游戏卡在loading界面并提示-mono-wasm-failed-to-load-config-file-blazor-boot-json","493":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_11-使用-webgl2-urp管线导出小游戏时提示-shader-编译报错-hidden-universal-coreblit-invalid-pass-index-1-in-drawprocedural","494":"/minigame-unity-webgl-transform/Design/DevelopmentQAList.html#_12-pc端输入框无法输入-移动端正常","495":"/minigame-unity-webgl-transform/Design/Evaluation.html#方案评估","496":"/minigame-unity-webgl-transform/Design/Evaluation.html#_1-游戏类目","497":"/minigame-unity-webgl-transform/Design/Evaluation.html#_2-引擎版本","498":"/minigame-unity-webgl-transform/Design/Evaluation.html#_3-能力支持","499":"/minigame-unity-webgl-transform/Design/DevtoolsDomain.html#微信开发者工具域名列表","500":"/minigame-unity-webgl-transform/Design/FileCache.html#资源缓存","501":"/minigame-unity-webgl-transform/Design/FileCache.html#介绍","502":"/minigame-unity-webgl-transform/Design/FileCache.html#一、什么情况触发资源缓存","503":"/minigame-unity-webgl-transform/Design/FileCache.html#二、哪些资源会自动缓存","504":"/minigame-unity-webgl-transform/Design/FileCache.html#三、缓存规则","505":"/minigame-unity-webgl-transform/Design/FileCache.html#相关配置","506":"/minigame-unity-webgl-transform/Design/FileCache.html#是否缓存规则","507":"/minigame-unity-webgl-transform/Design/FileCache.html#是否缓存业务资源","508":"/minigame-unity-webgl-transform/Design/FileCache.html#是否缓存纹理","509":"/minigame-unity-webgl-transform/Design/FileCache.html#资源淘汰规则","510":"/minigame-unity-webgl-transform/Design/FileCache.html#识别业务资源版本","511":"/minigame-unity-webgl-transform/Design/FileCache.html#识别纹理资源版本","512":"/minigame-unity-webgl-transform/Design/FileCache.html#缓存清理规则","513":"/minigame-unity-webgl-transform/Design/FileCache.html#示例","514":"/minigame-unity-webgl-transform/Design/FileCache.html#四、查看缓存日志","515":"/minigame-unity-webgl-transform/Design/FileCache.html#判断是否走缓存","516":"/minigame-unity-webgl-transform/Design/FileCache.html#其他缓存日志","517":"/minigame-unity-webgl-transform/Design/FileCache.html#对外接口","518":"/minigame-unity-webgl-transform/Design/FileCache.html#public-string-wx-plugincachepath","519":"/minigame-unity-webgl-transform/Design/FileCache.html#public-string-wx-getcachepath-string-url","520":"/minigame-unity-webgl-transform/Design/FileCache.html#public-void-cleanallfilecache-action-bool-action","521":"/minigame-unity-webgl-transform/Design/FileCache.html#public-void-cleanfilecache-int-filesize-action-releaseresult-action","522":"/minigame-unity-webgl-transform/Design/FileCache.html#public-void-removefile-string-path-action-bool-action","523":"/minigame-unity-webgl-transform/Design/FileCache.html#五、注意项","524":"/minigame-unity-webgl-transform/Design/FileCache.html#qa","525":"/minigame-unity-webgl-transform/Design/FileCache.html#_1-pc上配置为不自动缓存的文件-仍然没有走网络下载","526":"/minigame-unity-webgl-transform/Design/FileCache.html#_2-同一个文件-日志提示执行缓存逻辑-下次运行时仍然从网络下载","527":"/minigame-unity-webgl-transform/Design/FileCache.html#_3-已经有无缓存-执行缓存逻辑的日志-缓存仍不生效-下次访问资源仍从网络下载","528":"/minigame-unity-webgl-transform/Design/FileCache.html#_4-如何切换备用cdn地址","529":"/minigame-unity-webgl-transform/Design/FileCache.html#_5-一些配置文件不希望被自动清理-由业务控制何时清理","530":"/minigame-unity-webgl-transform/Design/FirstSceneOptimization.html#首场景启动优化","531":"/minigame-unity-webgl-transform/Design/FirstSceneOptimization.html#小游戏profile","532":"/minigame-unity-webgl-transform/Design/FirstSceneOptimization.html#unity-callmain","533":"/minigame-unity-webgl-transform/Design/FirstSceneOptimization.html#callmain-profile分析","534":"/minigame-unity-webgl-transform/Design/Guide.html#unity-游戏接入微信小游戏指南","535":"/minigame-unity-webgl-transform/Design/Guide.html#【阶段一】兼容性评估","536":"/minigame-unity-webgl-transform/Design/Guide.html#【阶段二】项目转换","537":"/minigame-unity-webgl-transform/Design/Guide.html#快速开始——转换工具导出微信小游戏","538":"/minigame-unity-webgl-transform/Design/Guide.html#资源按需加载","539":"/minigame-unity-webgl-transform/Design/Guide.html#后端-网络通信适配","540":"/minigame-unity-webgl-transform/Design/Guide.html#资源服务器部署配置","541":"/minigame-unity-webgl-transform/Design/Guide.html#开发阶段的错误排查","542":"/minigame-unity-webgl-transform/Design/Guide.html#【阶段三】微信平台能力接入","543":"/minigame-unity-webgl-transform/Design/Guide.html#接入微信api","544":"/minigame-unity-webgl-transform/Design/Guide.html#启动留存数据上报统计","545":"/minigame-unity-webgl-transform/Design/Guide.html#【阶段四】体验调优","546":"/minigame-unity-webgl-transform/Design/Guide.html#首场景启动优化——首帧逻辑优化","547":"/minigame-unity-webgl-transform/Design/Guide.html#资源预下载","548":"/minigame-unity-webgl-transform/Design/Guide.html#运行性能及调优","549":"/minigame-unity-webgl-transform/Design/Guide.html#压缩纹理资源","550":"/minigame-unity-webgl-transform/Design/Guide.html#wasm代码分包","551":"/minigame-unity-webgl-transform/Design/Guide.html#封面图配置","552":"/minigame-unity-webgl-transform/Design/Guide.html#【阶段五】发布上线与现网监控","553":"/minigame-unity-webgl-transform/Design/InputAdaptation.html#输入法适配","554":"/minigame-unity-webgl-transform/Design/InputAdaptation.html#支持2022和团结引擎的-input-field-组件自动适配-低版本或者其他组件暂不支持自动适配","555":"/minigame-unity-webgl-transform/Design/InputAdaptation.html#低版本兼容","556":"/minigame-unity-webgl-transform/Design/InstantGameGuide.html#使用-autostreaming-进行资源按需加载","557":"/minigame-unity-webgl-transform/Design/InstantGameGuide.html#方案选择建议","558":"/minigame-unity-webgl-transform/Design/InstantGameGuide.html#实践指南","559":"/minigame-unity-webgl-transform/Design/InstantGameGuide.html#q-a","560":"/minigame-unity-webgl-transform/Design/InstantGameGuide.html#_1-游戏在微信开发者工具中运行缺失资源","561":"/minigame-unity-webgl-transform/Design/IssueAndContact.html#问题反馈与联系我们","562":"/minigame-unity-webgl-transform/Design/IssueAndContact.html#git-issue","563":"/minigame-unity-webgl-transform/Design/IssueAndContact.html#小游戏客服助手","564":"/minigame-unity-webgl-transform/Design/IssueForProduction.html#现网错误日志上报与排查","565":"/minigame-unity-webgl-transform/Design/IssueForProduction.html#用户反馈日志","566":"/minigame-unity-webgl-transform/Design/IssueForProduction.html#小游戏实时日志","567":"/minigame-unity-webgl-transform/Design/IssueForProduction.html#js-error错误日志","568":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#启动剧情-beta","569":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#剧情效果","570":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#演示视频及演示工程源码","571":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#优秀作品","572":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#能力特性","573":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#推荐内容","574":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#接入方式","575":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#步骤一-设计剧情","576":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#步骤二-配置启动剧情","577":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#基于异步干预剧情发展","578":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#自定义上报分析","579":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#外显进度条接入","580":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#关闭-样式调整","581":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#弱网处理","582":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#api执行环境说明","583":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#api-javascript侧","584":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#running","585":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#config","586":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#end","587":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#onend-callback-function","588":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#offend-callback-function","589":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#onerr-callback-function","590":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#offerr-callback-function","591":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#onweaknetwork-callback-function","592":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#offweaknetwork-callback-function","593":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#setglobalvar-globalname-string-value-string","594":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#getglobalvar-globalname-string-string-null","595":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#onglobalvarchange-globalname-string-callback-function","596":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#offglobalvarchange-globalname-string-callback-function","597":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#api-c-侧","598":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#获得交互句柄","599":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#void-setpercentage-double-value","600":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#bool-getrunning","601":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#void-end","602":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#void-onend-action-bool-callback","603":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#void-offend-action-bool-callback","604":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#void-setglobalvar-string-key-string-value","605":"/minigame-unity-webgl-transform/Design/LaunchOpera.html#string-getglobalvar-string-key","606":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#启动剧情剧本自助设计工具及文档","607":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_1-文档说明","608":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_2-准备工作","609":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_3-快速入门","610":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step1-安装启动剧情cli工具","611":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step2-创建剧情工程","612":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step3-启动开发模式","613":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step4-预览默认剧情","614":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step5-对剧本修改","615":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step6-导出剧本","616":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#step7-尝试更多的模板","617":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-进阶指南","618":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-1-了解构建工具","619":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-基本概念","620":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-1-关键动作帧","621":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-1-1-属性","622":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-1-2-事件","623":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-2-故事线","624":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-2-1-创建及添加关键动作帧","625":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_4-2-2-2-主故事线","626":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_5-api速查","627":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype速查表","628":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#类型约定","629":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#空间描述约定","630":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#视频相关","631":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-createvideo","632":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性","633":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件","634":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例","635":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#seek-的使用案例","636":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-pausevideo","637":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-1","638":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-1","639":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-playvideo","640":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-2","641":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-2","642":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#音频相关","643":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-createaudio","644":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-3","645":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-1","646":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-3","647":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-pauseaudio","648":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-4","649":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-4","650":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-playaudio","651":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-5","652":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-5","653":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#贴图相关","654":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-createimage","655":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-6","656":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-2","657":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-6","658":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-createrect","659":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-7","660":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-3","661":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-7","662":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性修改","663":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-setparam","664":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-8","665":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-8","666":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-setparamsizeandposition","667":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-9","668":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-9","669":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#延迟执行","670":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-settimeout","671":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-10","672":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-4","673":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-10","674":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#动画相关","675":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-createanimationfunction","676":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-11","677":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-5","678":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-11","679":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#全局变量","680":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-var","681":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-12","682":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-6","683":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-12","684":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#条件判断","685":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-if","686":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-13","687":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#事件-7","688":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-13","689":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#上报","690":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#frametype-report","691":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#属性-14","692":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#案例-14","693":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_6-常见q-a","694":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_6-1-图片资源可以使用网络图片吗","695":"/minigame-unity-webgl-transform/Design/LaunchOperaDocument.html#_6-2-为什么要放首帧图片-firstframepic","696":"/minigame-unity-webgl-transform/Design/OpenData.html#unity中如何展示排行榜这类微信关系数据","697":"/minigame-unity-webgl-transform/Design/OpenData.html#背景和原理介绍","698":"/minigame-unity-webgl-transform/Design/OpenData.html#详细步骤","699":"/minigame-unity-webgl-transform/Design/OpenData.html#_1、设置占位纹理","700":"/minigame-unity-webgl-transform/Design/OpenData.html#_2、调用sdk的api","701":"/minigame-unity-webgl-transform/Design/OpenData.html#_2-1-在需要展示的地方调用-wx-showopendata","702":"/minigame-unity-webgl-transform/Design/OpenData.html#_2-2-需要关闭时则调用-wx-hideopendata","703":"/minigame-unity-webgl-transform/Design/OpenData.html#_2-3-通过-postmessage-向开放数据域传递消息","704":"/minigame-unity-webgl-transform/Design/OpenData.html#_3、导出选项勾选使用好友关系链","705":"/minigame-unity-webgl-transform/Design/OpenData.html#_4、用js开发排行榜这类微信关系逻辑","706":"/minigame-unity-webgl-transform/Design/OpenData.html#_5、示例demo","707":"/minigame-unity-webgl-transform/Design/OpenData.html#_5-1-好友排行榜","708":"/minigame-unity-webgl-transform/Design/OpenData.html#_5-2-群好友排行榜","709":"/minigame-unity-webgl-transform/Design/OpenData.html#常见问题qa","710":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#优化unity-webgl的内存","711":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#一、内存与oom","712":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#二、unity-webgl适配小游戏的内存结构","713":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#三、内存查看工具","714":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_3-1-进程总内存","715":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#instruments-in-xcode-ios","716":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#perfdog-android-or-ios","717":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_3-2-unityheap","718":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_3-3-profilingmemory","719":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_3-4-unity-profiler","720":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_3-5-javascript-heap","721":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#微信开发者工具","722":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#firefox-memory-pc","723":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#ios-safari-timeline-pc-or-ios","724":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#四、内存优化方案","725":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_4-1-wasm代码编译内存","726":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_4-2-gpu内存","727":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_4-3-unityheap","728":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_4-4-首资源包与assetbundle内存","729":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_4-5-音频内存","730":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#_4-6-其他常见优化手段","731":"/minigame-unity-webgl-transform/Design/OptimizationMemory.html#五、qa","732":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#优化unity-webgl的运行性能","733":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#一、运行性能概述","734":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#unity-webgl-vs-app的运行性能差异","735":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#wasm-vs-js的运行差异","736":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#系统平台之间的性能差异","737":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#二、优化目标","738":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#三、常用优化工具","739":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_3-1-小游戏android-cpu-profiler-推荐","740":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_3-2-unity-profiler","741":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_3-3-小游戏云测","742":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#三、常见优化手段","743":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_1-配置加载与协议解析","744":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_2-lua性能","745":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_3-物理性能","746":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_4-实例化","747":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_5-限制帧率","748":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_6-限制分辨率","749":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_7-使用压缩纹理","750":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_8-webgl2-0说明","751":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_9-减少drawcall","752":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_10-使用srp-batcher","753":"/minigame-unity-webgl-transform/Design/OptimizationPerformence.html#_11-如何获取设备硬件信息","754":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#unity-webgl小游戏适配方案性能标准","755":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#为什么需要性能评测标准","756":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#评测标准细则","757":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#性能基线","758":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#游戏类型说明","759":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#指标与测量方法","760":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#开发者需要关注哪些性能指标","761":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#代码与资源体积","762":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#评测标准","763":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#ios性能评测标准","764":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#android性能评测标准","765":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#评测工具","766":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#现网阶段","767":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#性能报告","768":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#性能数据","769":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#开发阶段","770":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#小游戏云测试","771":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#性能诊断工具","772":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#perfdog","773":"/minigame-unity-webgl-transform/Design/PerfMeasure.html#历史评测标准","774":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#性能优化总览","775":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#一、为何需要进行性能优化","776":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#二、优化目标","777":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#三、最佳实践","778":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#_3-1-加快游戏启动速度","779":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#_3-2-资源按需加载","780":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#_3-3-资源处理建议","781":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#_3-4-降低小游戏内存使用","782":"/minigame-unity-webgl-transform/Design/PerfOptimization.html#_3-5-降低cpu消耗","783":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#最佳实践检测工具","784":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#作用","785":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#如何使用","786":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#检测示意","787":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#检测指标解释","788":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#启动检测","789":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#监控指标","790":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#优化建议概览","791":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#预下载检测","792":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#监控指标-1","793":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#优化建议概览-1","794":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#wasm分包检测","795":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#监控指标-2","796":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#优化建议概览-2","797":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#网络信息检测","798":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#监控指标-3","799":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#优化建议概览-3","800":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#帧率检测","801":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#监控指标-4","802":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#优化建议概览-4","803":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#优化分析工具","804":"/minigame-unity-webgl-transform/Design/PerformanceMonitor.html#微信开发者工具","805":"/minigame-unity-webgl-transform/Design/Profile.html#使用unity-profiler性能调优","806":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#renderoptimization","807":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#webgl1-0-还是-webgl2-0","808":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#选择哪种渲染管线","809":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#线性颜色空间-还是-gamma-颜色空间","810":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#渲染性能优化的一些建议","811":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#光照和阴影","812":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#材质和shader","813":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#纹理设置","814":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#网格和蒙皮","815":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#drawcall-相关","816":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#摄像机-camera","817":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#渲染分辨率","818":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#后处理","819":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#特效","820":"/minigame-unity-webgl-transform/Design/RenderOptimization.html#参考文档","821":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#启动留存数据上报统计","822":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#一、概述","823":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#二、上报广告信息","824":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#如何上报","825":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#三、上报自定义阶段","826":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#四、获取loader启动阶段","827":"/minigame-unity-webgl-transform/Design/ReportStartupStat.html#五、获取数据统计","828":"/minigame-unity-webgl-transform/Design/ResourcesLoading.html#资源按需加载概述","829":"/minigame-unity-webgl-transform/Design/ResourcesLoading.html#aa包、ab包、instant-game-方案选择说明","830":"/minigame-unity-webgl-transform/Design/ResourcesLoading.html#各类型游戏的资源优化建议","831":"/minigame-unity-webgl-transform/Design/ResourcesLoading.html#原生-app-手游已使用-ab-aa-包等资源按需加载的游戏","832":"/minigame-unity-webgl-transform/Design/ResourcesLoading.html#原生-app-手游未使用-资源按需加载-的轻度游戏","833":"/minigame-unity-webgl-transform/Design/ResourcesLoading.html#原生-app-手游未使用-资源按需加载-的中重度游戏","834":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#微信sdk安装","835":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#方法一-推荐-package-方式安装","836":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#安装指南","837":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#方法二-资源包方式安装","838":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#安装指南-1","839":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#目录结构说明","840":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#常见问题","841":"/minigame-unity-webgl-transform/Design/SDKInstaller.html#_1-游戏工程可以导出但在微信开发者工具运行提示报错","842":"/minigame-unity-webgl-transform/Design/Salon.html#技术沙龙","843":"/minigame-unity-webgl-transform/Design/Salon.html#微信小游戏技术沙龙分享材料2023","844":"/minigame-unity-webgl-transform/Design/ShowCase.html#转换案例","845":"/minigame-unity-webgl-transform/Design/ShowCase.html#无尽冬日","846":"/minigame-unity-webgl-transform/Design/ShowCase.html#九梦仙域","847":"/minigame-unity-webgl-transform/Design/ShowCase.html#地铁跑酷","848":"/minigame-unity-webgl-transform/Design/ShowCase.html#谜题大陆","849":"/minigame-unity-webgl-transform/Design/ShowCase.html#三国吧兄弟","850":"/minigame-unity-webgl-transform/Design/ShowCase.html#鱼吃鱼","851":"/minigame-unity-webgl-transform/Design/ShowCase.html#剑心吟","852":"/minigame-unity-webgl-transform/Design/ShowCase.html#巨兽战场","853":"/minigame-unity-webgl-transform/Design/ShowCase.html#小小蚁国","854":"/minigame-unity-webgl-transform/Design/ShowCase.html#翡翠大师","855":"/minigame-unity-webgl-transform/Design/ShowCase.html#超能世界","856":"/minigame-unity-webgl-transform/Design/ShowCase.html#大侠不哭","857":"/minigame-unity-webgl-transform/Design/ShowCase.html#我叫mt2","858":"/minigame-unity-webgl-transform/Design/ShowCase.html#葫芦娃大作战","859":"/minigame-unity-webgl-transform/Design/ShowCase.html#大圣顶住","860":"/minigame-unity-webgl-transform/Design/ShowCase.html#银河战舰","861":"/minigame-unity-webgl-transform/Design/ShowCase.html#守护球球","862":"/minigame-unity-webgl-transform/Design/Startup.html#小游戏启动流程与时序","863":"/minigame-unity-webgl-transform/Design/Startup.html#启动加载时序","864":"/minigame-unity-webgl-transform/Design/Startup.html#unity-loader工作流程","865":"/minigame-unity-webgl-transform/Design/Startup.html#qa","866":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#提升unity-webgl游戏启动速度","867":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#一、-为什么要做启动优化","868":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_1-1-小游戏与手游app的启动差异","869":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_1-2-优化的目标与标准","870":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#二、分析小游戏启动速度","871":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-1-查看启动耗时","872":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-2-分阶段耗时","873":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-2-1-首资源包下载与体积","874":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-2-2-wasm代码下载和编译","875":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-2-3-引擎初始化与开发者首帧逻辑","876":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-2-4-游戏内资源按需加载","877":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_2-3-优化总览","878":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#三、常用启动优化技巧","879":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#四、常用启动优化工具","880":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_4-1-assetstudio-推荐","881":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_4-2-buildreporttool-推荐","882":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_4-3-asset-hunter","883":"/minigame-unity-webgl-transform/Design/StartupOptimization.html#_4-4-unity-addressable-assets-system","884":"/minigame-unity-webgl-transform/Design/Summary.html#unity-webgl小游戏适配方案概述","885":"/minigame-unity-webgl-transform/Design/Summary.html#一、技术原理","886":"/minigame-unity-webgl-transform/Design/Summary.html#二、接入流程","887":"/minigame-unity-webgl-transform/Design/Summary.html#三、参考资料","888":"/minigame-unity-webgl-transform/Design/Symbol.html#symbol-相关","889":"/minigame-unity-webgl-transform/Design/Symbol.html#tool","890":"/minigame-unity-webgl-transform/Design/Transform.html#转换工具导出微信小游戏","891":"/minigame-unity-webgl-transform/Design/Transform.html#一、unity导出webgl","892":"/minigame-unity-webgl-transform/Design/Transform.html#二、适配小游戏","893":"/minigame-unity-webgl-transform/Design/Transform.html#_2-1-转换小游戏","894":"/minigame-unity-webgl-transform/Design/Transform.html#_2-2-了解转换后目录结构","895":"/minigame-unity-webgl-transform/Design/Transform.html#_2-3-资源部署","896":"/minigame-unity-webgl-transform/Design/Transform.html#_2-4-小游戏预览","897":"/minigame-unity-webgl-transform/Design/Transform.html#三、使用脚本集成到自己的构建系统","898":"/minigame-unity-webgl-transform/Design/Transform.html#minigameconfig-asset支持的配置","899":"/minigame-unity-webgl-transform/Design/Transform.html#与转换面板配置有对应关系的配置项","900":"/minigame-unity-webgl-transform/Design/Transform.html#不常用配置","901":"/minigame-unity-webgl-transform/Design/Transform.html#四、常见问题","902":"/minigame-unity-webgl-transform/Design/UnityProfiler.html#使用unity-profiler性能调优","903":"/minigame-unity-webgl-transform/Design/UnityVersion.html#推荐引擎版本","904":"/minigame-unity-webgl-transform/Design/UnityVersion.html#版本兼容性","905":"/minigame-unity-webgl-transform/Design/UnityVersion.html#推荐版本","906":"/minigame-unity-webgl-transform/Design/UnityVersion.html#unity-instantgame-团结引擎获取","907":"/minigame-unity-webgl-transform/Design/UnityVersion.html#qa","908":"/minigame-unity-webgl-transform/Design/Update.html#版本更新","909":"/minigame-unity-webgl-transform/Design/Update.html#代码更新","910":"/minigame-unity-webgl-transform/Design/Update.html#更新策略","911":"/minigame-unity-webgl-transform/Design/Update.html#_1-静默更新-默认方式","912":"/minigame-unity-webgl-transform/Design/Update.html#_2-强制更新","913":"/minigame-unity-webgl-transform/Design/Update.html#_2-1-实时检测更新-updatemanager","914":"/minigame-unity-webgl-transform/Design/Update.html#_2-2-设置最低可用版本","915":"/minigame-unity-webgl-transform/Design/Update.html#资源更新","916":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#使用addressable-assets-system进行资源按需加载","917":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#一、概述","918":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#二、addressable在小游戏中的应用","919":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_2-1-什么是addressable-assets-system","920":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_2-2-相对于assetsbundles的优势","921":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_2-3-在小游戏中使用addressable-assets-system","922":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_2-4-使用wxassetbundleprovider节省内存","923":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#三、启动优化与资源优化实战","924":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_3-1-从首包开始","925":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_3-2-资源按需加载","926":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_3-2-1-场景动态加载","927":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_3-2-2-物件动态加载","928":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_3-3-小结","929":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#四、如何优雅地异步加载","930":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_4-1-最基本的异步回调","931":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_4-2-使用协程","932":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_4-3-使用await","933":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#五、旧系统资源改造","934":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_5-1-resource改造","935":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_5-2-assetsbundle迁移","936":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#六、部署","937":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_6-1-addressable编译与部署","938":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#_6-2-资源预下载","939":"/minigame-unity-webgl-transform/Design/UsingAddressable.html#五、参考资料","940":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#使用-assetbundle-进行资源按需加载","941":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#一、assetbundle使用","942":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#_1-1-assetbundle打包参数建议","943":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#_1-2-assetbundle下载","944":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#二、小游戏与app的assetbundle缓存更新流程差异","945":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#三、更节省内存的wxassetbundle","946":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#四、assetbundle内存分析","947":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#_4-1-切勿使用带cache能力的线管接口","948":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#_4-2-尽可能使用unload","949":"/minigame-unity-webgl-transform/Design/UsingAssetBundle.html#四、参考资料","950":"/minigame-unity-webgl-transform/Design/UsingLoader.html#使用loader进行游游戏加载","951":"/minigame-unity-webgl-transform/Design/UsingLoader.html#一、什么是unity-loader","952":"/minigame-unity-webgl-transform/Design/UsingLoader.html#二、如何使用unity-loader插件","953":"/minigame-unity-webgl-transform/Design/UsingLoader.html#三、配置unity-loader功能","954":"/minigame-unity-webgl-transform/Design/UsingLoader.html#_3-1-资源下载","955":"/minigame-unity-webgl-transform/Design/UsingLoader.html#转换插件相关配置","956":"/minigame-unity-webgl-transform/Design/UsingLoader.html#通过接口修改","957":"/minigame-unity-webgl-transform/Design/UsingLoader.html#_3-2-启动界面","958":"/minigame-unity-webgl-transform/Design/UsingLoader.html#转换插件相关配置-1","959":"/minigame-unity-webgl-transform/Design/UsingLoader.html#game-js配置","960":"/minigame-unity-webgl-transform/Design/UsingLoader.html#_3-3-首包资源加载方式","961":"/minigame-unity-webgl-transform/Design/UsingLoader.html#转换插件相关配置-2","962":"/minigame-unity-webgl-transform/Design/UsingLoader.html#game-js配置-1","963":"/minigame-unity-webgl-transform/Design/UsingLoader.html#_3-4-预加载资源","964":"/minigame-unity-webgl-transform/Design/UsingLoader.html#_3-5-资源缓存与淘汰策略","965":"/minigame-unity-webgl-transform/Design/UsingLoader.html#_3-6-插件调试日志","966":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#使用profilingmemory内存分析","967":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#概述","968":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#步骤","969":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#数据分析","970":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#浏览数据","971":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#sql统计分析","972":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#常见问题","973":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#_1-开启proflingmemory后非常慢-特别是在有lua逻辑的情况","974":"/minigame-unity-webgl-transform/Design/UsingMemoryProfiler.html#_2-profilingmemory在真机上更容易出现内存崩溃","975":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#网络通信适配","976":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#http-通信","977":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#使用方式","978":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#tcp-网络通信","979":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#tcpsocket","980":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#websocket","981":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#客户端","982":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#服务端","983":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#udp-网络通信","984":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#注意事项","985":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#安全域名","986":"/minigame-unity-webgl-transform/Design/UsingNetworking.html#ssl证书","987":"/minigame-unity-webgl-transform/Design/UsingPreload.html#使用预下载功能","988":"/minigame-unity-webgl-transform/Design/UsingPreload.html#概述","989":"/minigame-unity-webgl-transform/Design/UsingPreload.html#配置方式","990":"/minigame-unity-webgl-transform/Design/UsingPreload.html#导出预下载列表","991":"/minigame-unity-webgl-transform/Design/UsingPreload.html#minigameconfig-asset相关配置","992":"/minigame-unity-webgl-transform/Design/UsingPreload.html#手动配置","993":"/minigame-unity-webgl-transform/Design/UsingPreload.html#运行时配置「推荐」","994":"/minigame-unity-webgl-transform/Design/UsingPreload.html#在插件启动前修改","995":"/minigame-unity-webgl-transform/Design/UsingPreload.html#引擎初始化完成后修改","996":"/minigame-unity-webgl-transform/Design/UsingPreload.html#并发数","997":"/minigame-unity-webgl-transform/Design/UsingPreload.html#路径规范","998":"/minigame-unity-webgl-transform/Design/UsingPreload.html#如何验证","999":"/minigame-unity-webgl-transform/Design/UsingPreload.html#注意事项","1000":"/minigame-unity-webgl-transform/Design/WXFont.html#微信系统字体","1001":"/minigame-unity-webgl-transform/Design/WXFont.html#版本要求","1002":"/minigame-unity-webgl-transform/Design/WXFont.html#代码示例","1003":"/minigame-unity-webgl-transform/Design/WXFont.html#相关日志","1004":"/minigame-unity-webgl-transform/Design/WXFont.html#系统字体字符集","1005":"/minigame-unity-webgl-transform/Design/WX_SDK.html#sdk-调用微信-api","1006":"/minigame-unity-webgl-transform/Design/WX_SDK.html#基础库","1007":"/minigame-unity-webgl-transform/Design/WX_SDK.html#在-unity-中兼容低版本基础库","1008":"/minigame-unity-webgl-transform/Design/WX_SDK.html#开发建议","1009":"/minigame-unity-webgl-transform/Design/WX_SDK.html#demo-api-示例","1010":"/minigame-unity-webgl-transform/Design/WX_SDK.html#联调效率","1011":"/minigame-unity-webgl-transform/Design/WX_SDK.html#注意事项","1012":"/minigame-unity-webgl-transform/Design/WasmSplit.html#代码分包","1013":"/minigame-unity-webgl-transform/Design/WasmSplit.html#概述","1014":"/minigame-unity-webgl-transform/Design/WasmSplit.html#背景","1015":"/minigame-unity-webgl-transform/Design/WasmSplit.html#作用","1016":"/minigame-unity-webgl-transform/Design/WasmSplit.html#实现原理","1017":"/minigame-unity-webgl-transform/Design/WasmSplit.html#插件安装","1018":"/minigame-unity-webgl-transform/Design/WasmSplit.html#插件更新","1019":"/minigame-unity-webgl-transform/Design/WasmSplit.html#插件使用","1020":"/minigame-unity-webgl-transform/Design/WasmSplit.html#启用分包","1021":"/minigame-unity-webgl-transform/Design/WasmSplit.html#输入版本描述","1022":"/minigame-unity-webgl-transform/Design/WasmSplit.html#等待上传文件","1023":"/minigame-unity-webgl-transform/Design/WasmSplit.html#等待预处理","1024":"/minigame-unity-webgl-transform/Design/WasmSplit.html#选择是否增量分包","1025":"/minigame-unity-webgl-transform/Design/WasmSplit.html#等待分包","1026":"/minigame-unity-webgl-transform/Design/WasmSplit.html#android收集-ios收集","1027":"/minigame-unity-webgl-transform/Design/WasmSplit.html#重复收集与生成","1028":"/minigame-unity-webgl-transform/Design/WasmSplit.html#关闭分包","1029":"/minigame-unity-webgl-transform/Design/WasmSplit.html#注意事项","1030":"/minigame-unity-webgl-transform/Design/WasmSplit.html#faq","1031":"/minigame-unity-webgl-transform/Design/WasmSplit.html#分包是否是必要的","1032":"/minigame-unity-webgl-transform/Design/WasmSplit.html#收集到什么时候可以结束","1033":"/minigame-unity-webgl-transform/Design/WasmSplit.html#游戏内容难以遍历完整怎么办","1034":"/minigame-unity-webgl-transform/Design/WasmSplit.html#分包总大小比原始包大","1035":"/minigame-unity-webgl-transform/Design/WasmSplit.html#新增收集的函数要重新再次提审才会在首包吗","1036":"/minigame-unity-webgl-transform/Design/WasmSplit.html#会不会最终跑到所有函数都收集的情况","1037":"/minigame-unity-webgl-transform/Design/WasmSplit.html#ios-高性能模式收集很卡","1038":"/minigame-unity-webgl-transform/Design/WasmSplit.html#ios-高性能模式代码分包后内存反而变得很高","1039":"/minigame-unity-webgl-transform/Design/WasmSplit.html#ios-高性能模式出现-impport-section-s-count-is-too-big","1040":"/minigame-unity-webgl-transform/Design/WasmSplit.html#没有看到增量分包的界面","1041":"/minigame-unity-webgl-transform/Design/WasmSplit.html#增量分包没生效","1042":"/minigame-unity-webgl-transform/Design/WasmSplit.html#如何更新分包插件","1043":"/minigame-unity-webgl-transform/Design/WasmSplit.html#分包插件安装失败","1044":"/minigame-unity-webgl-transform/Design/WasmSplit.html#分包插件卡住","1045":"/minigame-unity-webgl-transform/Design/WasmSplit.html#内存优化版本未观察到内存优化","1046":"/minigame-unity-webgl-transform/Design/WasmSplit.html#如何查看分包插件日志","1047":"/minigame-unity-webgl-transform/Design/WasmSplit.html#changelog","1048":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-13","1049":"/minigame-unity-webgl-transform/Design/WasmSplit.html#fixed","1050":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-12","1051":"/minigame-unity-webgl-transform/Design/WasmSplit.html#fixed-1","1052":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-11","1053":"/minigame-unity-webgl-transform/Design/WasmSplit.html#fixed-2","1054":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-10","1055":"/minigame-unity-webgl-transform/Design/WasmSplit.html#fixed-3","1056":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-9","1057":"/minigame-unity-webgl-transform/Design/WasmSplit.html#feature","1058":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-8","1059":"/minigame-unity-webgl-transform/Design/WasmSplit.html#changed","1060":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-6","1061":"/minigame-unity-webgl-transform/Design/WasmSplit.html#changed-1","1062":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-5","1063":"/minigame-unity-webgl-transform/Design/WasmSplit.html#fixed-4","1064":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-4","1065":"/minigame-unity-webgl-transform/Design/WasmSplit.html#fixed-5","1066":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-2","1067":"/minigame-unity-webgl-transform/Design/WasmSplit.html#changed-2","1068":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-1-0","1069":"/minigame-unity-webgl-transform/Design/WasmSplit.html#added","1070":"/minigame-unity-webgl-transform/Design/WasmSplit.html#v1-0-2","1071":"/minigame-unity-webgl-transform/Design/WasmSplit.html#added-1","1072":"/minigame-unity-webgl-transform/Design/fixScreen.html#屏幕适配","1073":"/minigame-unity-webgl-transform/Design/fixScreen.html#安全区域适配","1074":"/minigame-unity-webgl-transform/Design/fixScreen.html#高分辨屏下模糊问题","1075":"/minigame-unity-webgl-transform/Design/WebGL2.html#webgl2-0渲染支持说明","1076":"/minigame-unity-webgl-transform/Design/WebGL2.html#适合使用场景","1077":"/minigame-unity-webgl-transform/Design/WebGL2.html#用户占比","1078":"/minigame-unity-webgl-transform/Design/WebGL2.html#已知兼容问题","1079":"/minigame-unity-webgl-transform/Design/WebGL2.html#ios高性能模式开启gpu-instance-模型闪烁-消失-不绘制等问题","1080":"/minigame-unity-webgl-transform/Design/WebGL2.html#ios高性能模式drawmeshinstanced显示错乱","1081":"/minigame-unity-webgl-transform/Design/WebGL2.html#参考文档","1082":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#ios-高性能与高性能-模式","1083":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#什么是高性能模式","1084":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#什么是高性能-模式","1085":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#性能提升","1086":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#cpu-消耗","1087":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#压力测试","1088":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#如何开通","1089":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#高性能模式限制","1090":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#内存限制","1091":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#代码体积限制","1092":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#qa","1093":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_1-如何判别游戏否已经开启了高性能模式","1094":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_2-使用高性能模式下-游戏本身是否需要做修改","1095":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_3-ios-报错提示未开启-gzip-br-压缩","1096":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_4-资源下载提示istrusted","1097":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_5-卡在启动封面无法启动","1098":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_6-个别游戏-ui-会出现闪烁问题","1099":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_7-为什么开启了高性能模式-游戏启动很烫","1100":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_8-使用高性能模式下-不优化内存、wasm-代码包体积就发布上线可以吗","1101":"/minigame-unity-webgl-transform/Design/iOSOptimization.html#_9-ios-高性能模式与安卓性能对比如何","1102":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#unity-webgl小游戏适配方案性能标准","1103":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#为什么需要性能评测标准","1104":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#评测标准细则","1105":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#性能基线","1106":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#指标与测量方法","1107":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#代码与资源体积","1108":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#评测工具","1109":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#启动性能","1110":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#运行性能","1111":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#评测标准","1112":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#开发者需要关注哪些性能指标","1113":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#游戏类型说明","1114":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#ios性能评测标准","1115":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_20230517.html#android性能评测标准","1116":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#unity-webgl小游戏适配方案性能标准","1117":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#为什么需要性能评测标准","1118":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#开发者需要关注哪些性能指标","1119":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#评测标准细则","1120":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#性能基线","1121":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#评测工具","1122":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#代码与资源体积","1123":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#android-评测标准","1124":"/minigame-unity-webgl-transform/Design/performance-standard/PerfMeasure_old.html#ios-评测标准","1125":"/minigame-unity-webgl-transform/Design/video.html#视频设计规范","1126":"/minigame-unity-webgl-transform/Design/video.html#建议启动视频内带有团队宣传logo动画-游戏logo动画-带有吸引力的游戏玩法视频","1127":"/minigame-unity-webgl-transform/Design/wasmWaterMark.html#wasm水印插件","1128":"/minigame-unity-webgl-transform/Design/wasmWaterMark.html#说明","1129":"/minigame-unity-webgl-transform/Design/wasmWaterMark.html#使用方式","1130":"/minigame-unity-webgl-transform/Design/wasmWaterMark.html#添加插件","1131":"/minigame-unity-webgl-transform/Design/wasmWaterMark.html#使用插件","1132":"/minigame-unity-webgl-transform/Design/wasmWaterMark.html#注意","1133":"/minigame-unity-webgl-transform/README.html#微信小游戏unity-团结引擎适配方案","1134":"/minigame-unity-webgl-transform/README.html#方案特点","1135":"/minigame-unity-webgl-transform/README.html#转换案例","1136":"/minigame-unity-webgl-transform/README.html#安装与使用"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[1,1,15],"1":[5,1,17],"2":[1,5,4],"3":[1,5,6],"4":[5,1,1],"5":[1,5,8],"6":[1,5,17],"7":[5,1,1],"8":[1,5,6],"9":[1,5,10],"10":[5,1,1],"11":[1,5,5],"12":[1,5,9],"13":[5,1,1],"14":[1,5,3],"15":[5,1,1],"16":[1,5,23],"17":[5,1,1],"18":[1,5,9],"19":[5,1,1],"20":[1,5,9],"21":[1,5,6],"22":[5,1,3],"23":[1,5,6],"24":[5,1,3],"25":[1,5,6],"26":[5,1,11],"27":[1,5,11],"28":[5,1,5],"29":[1,5,3],"30":[5,1,1],"31":[1,5,10],"32":[1,5,9],"33":[5,1,3],"34":[1,5,9],"35":[1,5,8],"36":[5,1,3],"37":[1,5,4],"38":[1,5,3],"39":[4,1,3],"40":[1,4,10],"41":[5,1,3],"42":[1,5,9],"43":[1,5,8],"44":[5,1,1],"45":[1,5,3],"46":[3,1,4],"47":[1,3,9],"48":[1,3,4],"49":[3,1,2],"50":[1,3,7],"51":[3,1,2],"52":[1,3,2],"53":[3,1,2],"54":[1,3,7],"55":[1,3,6],"56":[5,1,1],"57":[1,5,10],"58":[3,1,4],"59":[1,3,4],"60":[1,3,7],"61":[3,1,1],"62":[1,3,8],"63":[3,1,1],"64":[1,3,2],"65":[1,3,9],"66":[3,1,1],"67":[1,3,6],"68":[1,3,11],"69":[3,1,1],"70":[1,3,19],"71":[1,3,17],"72":[3,1,1],"73":[1,3,7],"74":[3,1,1],"75":[1,3,18],"76":[1,3,14],"77":[3,1,1],"78":[1,3,4],"79":[1,3,7],"80":[3,1,1],"81":[1,3,6],"82":[1,3,3],"83":[3,1,1],"84":[1,3,8],"85":[3,1,1],"86":[1,3,9],"87":[1,3,2],"88":[3,1,1],"89":[1,3,5],"90":[1,3,4],"91":[3,1,1],"92":[1,3,6],"93":[3,1,1],"94":[1,3,10],"95":[1,3,4],"96":[3,1,1],"97":[1,3,5],"98":[3,1,1],"99":[1,3,3],"100":[1,3,6],"101":[3,1,1],"102":[1,3,15],"103":[1,3,5],"104":[3,1,1],"105":[1,3,6],"106":[1,3,2],"107":[3,1,1],"108":[1,3,26],"109":[1,3,20],"110":[3,1,1],"111":[1,3,4],"112":[3,1,1],"113":[1,3,2],"114":[3,1,1],"115":[1,3,3],"116":[3,1,1],"117":[1,3,5],"118":[3,1,1],"119":[1,3,8],"120":[1,3,4],"121":[3,1,1],"122":[1,3,4],"123":[3,1,1],"124":[1,3,9],"125":[1,3,7],"126":[3,1,1],"127":[1,3,37],"128":[1,3,2],"129":[3,1,1],"130":[1,3,17],"131":[1,3,6],"132":[3,1,1],"133":[1,3,5],"134":[3,1,1],"135":[1,3,9],"136":[3,1,1],"137":[1,3,11],"138":[1,3,3],"139":[3,1,1],"140":[1,3,6],"141":[3,1,1],"142":[1,3,4],"143":[1,3,3],"144":[3,1,1],"145":[1,3,4],"146":[3,1,1],"147":[1,3,7],"148":[1,3,2],"149":[3,1,1],"150":[1,3,2],"151":[1,3,3],"152":[3,1,1],"153":[1,3,5],"154":[3,1,1],"155":[1,3,7],"156":[1,3,2],"157":[3,1,1],"158":[1,3,6],"159":[1,3,4],"160":[3,1,1],"161":[1,3,4],"162":[1,3,3],"163":[3,1,1],"164":[1,3,4],"165":[3,1,1],"166":[1,3,3],"167":[1,3,10],"168":[3,1,1],"169":[1,3,4],"170":[3,1,1],"171":[1,3,5],"172":[3,1,1],"173":[1,3,5],"174":[3,1,1],"175":[1,3,6],"176":[3,1,1],"177":[1,3,2],"178":[3,1,1],"179":[1,3,3],"180":[1,3,9],"181":[3,1,1],"182":[1,3,2],"183":[3,1,1],"184":[1,3,2],"185":[1,3,2],"186":[1,3,2],"187":[3,1,1],"188":[1,3,4],"189":[3,1,1],"190":[1,3,4],"191":[3,1,1],"192":[1,3,4],"193":[3,1,1],"194":[1,3,2],"195":[1,3,3],"196":[3,1,1],"197":[1,3,2],"198":[3,1,1],"199":[1,3,3],"200":[1,3,3],"201":[3,1,1],"202":[1,3,5],"203":[3,1,1],"204":[1,3,2],"205":[1,3,6],"206":[3,1,1],"207":[1,3,3],"208":[3,1,1],"209":[1,3,2],"210":[3,1,1],"211":[1,3,2],"212":[3,1,1],"213":[1,3,2],"214":[3,1,1],"215":[1,3,3],"216":[1,3,3],"217":[3,1,1],"218":[1,3,5],"219":[3,1,1],"220":[1,3,2],"221":[3,1,1],"222":[1,3,2],"223":[1,3,4],"224":[3,1,1],"225":[1,3,7],"226":[3,1,1],"227":[1,3,6],"228":[1,3,3],"229":[3,1,1],"230":[1,3,3],"231":[3,1,1],"232":[1,3,2],"233":[3,1,1],"234":[1,3,6],"235":[3,1,1],"236":[1,3,6],"237":[3,1,1],"238":[1,3,2],"239":[3,1,1],"240":[1,3,11],"241":[3,1,1],"242":[1,3,4],"243":[3,1,1],"244":[1,3,4],"245":[3,1,1],"246":[1,3,12],"247":[3,1,1],"248":[1,3,2],"249":[3,1,1],"250":[1,3,4],"251":[3,1,1],"252":[1,3,3],"253":[3,1,1],"254":[1,3,5],"255":[3,1,1],"256":[1,3,3],"257":[3,1,1],"258":[1,3,3],"259":[1,3,15],"260":[3,1,1],"261":[1,3,4],"262":[3,1,1],"263":[1,3,2],"264":[1,3,2],"265":[3,1,1],"266":[1,3,6],"267":[3,1,1],"268":[1,3,5],"269":[3,1,1],"270":[1,3,4],"271":[3,1,1],"272":[1,3,4],"273":[3,1,1],"274":[1,3,8],"275":[3,1,1],"276":[1,3,3],"277":[3,1,1],"278":[1,3,2],"279":[3,1,1],"280":[1,3,8],"281":[1,3,4],"282":[3,1,1],"283":[1,3,7],"284":[3,1,1],"285":[1,3,4],"286":[1,3,8],"287":[3,1,1],"288":[1,3,2],"289":[3,1,1],"290":[1,3,10],"291":[1,3,2],"292":[1,3,2],"293":[3,1,1],"294":[1,3,4],"295":[3,1,1],"296":[1,3,3],"297":[3,1,1],"298":[1,3,2],"299":[3,1,1],"300":[1,3,5],"301":[1,3,6],"302":[1,3,8],"303":[3,1,1],"304":[1,3,3],"305":[1,3,2],"306":[3,1,1],"307":[1,3,2],"308":[3,1,1],"309":[1,3,2],"310":[3,1,1],"311":[1,3,3],"312":[3,1,1],"313":[1,3,7],"314":[3,1,1],"315":[1,3,3],"316":[3,1,1],"317":[1,3,5],"318":[3,1,1],"319":[1,3,6],"320":[3,1,1],"321":[1,3,2],"322":[3,1,1],"323":[1,3,3],"324":[1,3,2],"325":[3,1,1],"326":[1,3,5],"327":[3,1,1],"328":[1,3,4],"329":[3,1,1],"330":[1,3,5],"331":[3,1,1],"332":[1,3,2],"333":[3,1,1],"334":[1,3,5],"335":[1,3,3],"336":[3,1,1],"337":[1,3,5],"338":[3,1,1],"339":[1,3,3],"340":[3,1,1],"341":[1,3,2],"342":[1,3,3],"343":[3,1,1],"344":[1,3,2],"345":[1,3,2],"346":[1,3,6],"347":[1,3,3],"348":[1,3,13],"349":[3,1,1],"350":[1,3,6],"351":[3,1,99],"352":[3,1,16],"353":[2,3,102],"354":[2,3,13],"355":[2,3,66],"356":[2,3,29],"357":[2,3,3],"358":[2,3,39],"359":[1,1,3],"360":[1,1,4],"361":[1,1,1],"362":[1,2,50],"363":[1,1,16],"364":[1,1,1],"365":[1,1,9],"366":[1,1,12],"367":[1,2,54],"368":[1,1,7],"369":[2,2,23],"370":[1,2,65],"371":[1,1,1],"372":[1,1,17],"373":[1,1,10],"374":[1,1,141],"375":[1,1,1],"376":[1,1,15],"377":[1,1,60],"378":[1,1,21],"379":[1,2,3],"380":[1,1,40],"381":[1,1,7],"382":[1,2,2],"383":[1,2,79],"384":[1,2,42],"385":[4,1,1],"386":[1,4,42],"387":[1,4,30],"388":[2,4,45],"389":[1,4,9],"390":[4,4,7],"391":[4,4,10],"392":[2,8,33],"393":[2,8,38],"394":[2,4,13],"395":[2,4,25],"396":[2,4,18],"397":[5,4,12],"398":[1,4,26],"399":[1,4,20],"400":[1,4,10],"401":[1,4,12],"402":[3,4,1],"403":[2,6,10],"404":[2,6,5],"405":[2,6,29],"406":[3,6,24],"407":[3,6,10],"408":[9,6,10],"409":[2,15,21],"410":[2,15,28],"411":[1,4,12],"412":[3,4,17],"413":[1,7,12],"414":[1,7,42],"415":[3,4,12],"416":[1,7,4],"417":[1,7,14],"418":[1,1,13],"419":[1,1,1],"420":[1,2,15],"421":[2,2,123],"422":[1,1,22],"423":[1,1,112],"424":[1,1,20],"425":[1,1,5],"426":[1,1,39],"427":[3,1,35],"428":[3,3,151],"429":[1,3,136],"430":[3,3,94],"431":[3,4,203],"432":[3,4,52],"433":[1,3,94],"434":[1,3,4],"435":[1,1,36],"436":[1,1,13],"437":[1,2,30],"438":[1,2,4],"439":[1,2,7],"440":[1,2,14],"441":[1,1,27],"442":[1,1,2],"443":[1,2,2],"444":[1,1,3],"445":[1,1,1],"446":[1,2,34],"447":[1,2,1],"448":[2,3,7],"449":[1,3,12],"450":[1,1,14],"451":[2,2,100],"452":[2,2,13],"453":[2,2,11],"454":[1,1,1],"455":[1,1,1],"456":[5,2,5],"457":[5,2,3],"458":[2,2,9],"459":[2,2,22],"460":[8,2,8],"461":[5,2,8],"462":[5,2,4],"463":[4,2,4],"464":[5,2,7],"465":[3,2,3],"466":[5,2,12],"467":[6,2,3],"468":[2,2,21],"469":[2,1,1],"470":[3,3,4],"471":[8,3,8],"472":[3,3,14],"473":[6,3,10],"474":[3,3,4],"475":[2,3,7],"476":[3,3,6],"477":[3,3,6],"478":[4,3,3],"479":[12,3,65],"480":[7,3,4],"481":[10,3,8],"482":[1,1,1],"483":[3,2,4],"484":[3,2,2],"485":[3,2,2],"486":[3,2,3],"487":[3,2,3],"488":[3,2,12],"489":[3,2,3],"490":[2,2,40],"491":[11,2,8],"492":[13,2,5],"493":[16,2,42],"494":[3,2,15],"495":[1,1,1],"496":[2,1,24],"497":[2,1,8],"498":[2,1,63],"499":[1,1,35],"500":[1,1,62],"501":[1,1,24],"502":[2,1,12],"503":[3,1,7],"504":[2,1,1],"505":[1,3,46],"506":[1,4,3],"507":[1,5,48],"508":[1,5,6],"509":[1,4,7],"510":[1,5,19],"511":[1,5,5],"512":[1,4,55],"513":[1,3,72],"514":[2,1,2],"515":[1,3,37],"516":[1,3,19],"517":[1,1,1],"518":[4,2,16],"519":[6,2,9],"520":[9,2,10],"521":[11,2,27],"522":[11,2,11],"523":[2,1,57],"524":[1,1,1],"525":[3,2,5],"526":[4,2,28],"527":[5,2,20],"528":[2,2,4],"529":[3,2,7],"530":[1,1,15],"531":[1,1,42],"532":[2,1,73],"533":[2,1,41],"534":[2,1,19],"535":[3,2,8],"536":[3,2,2],"537":[2,4,10],"538":[1,4,22],"539":[2,4,21],"540":[1,4,24],"541":[1,4,10],"542":[3,2,1],"543":[1,4,20],"544":[1,4,13],"545":[3,2,7],"546":[2,4,18],"547":[1,4,9],"548":[1,4,14],"549":[1,4,29],"550":[1,4,19],"551":[1,4,15],"552":[3,2,9],"553":[1,1,1],"554":[5,1,1],"555":[2,1,80],"556":[3,1,11],"557":[1,3,36],"558":[1,3,11],"559":[3,3,1],"560":[3,6,7],"561":[1,1,7],"562":[2,1,12],"563":[1,1,2],"564":[1,1,10],"565":[1,1,27],"566":[1,1,11],"567":[2,1,14],"568":[3,1,14],"569":[1,3,1],"570":[1,3,10],"571":[1,3,11],"572":[1,3,8],"573":[1,3,7],"574":[1,3,6],"575":[2,3,11],"576":[2,3,94],"577":[1,3,39],"578":[1,3,14],"579":[1,3,14],"580":[2,4,52],"581":[1,3,27],"582":[1,3,50],"583":[3,3,10],"584":[2,5,13],"585":[2,5,33],"586":[2,5,2],"587":[4,5,8],"588":[4,5,2],"589":[4,5,17],"590":[4,5,2],"591":[4,5,39],"592":[4,5,2],"593":[5,5,2],"594":[6,5,2],"595":[6,5,2],"596":[6,5,2],"597":[4,3,1],"598":[1,6,7],"599":[5,6,14],"600":[3,6,6],"601":[3,6,2],"602":[8,6,30],"603":[8,6,2],"604":[6,6,2],"605":[4,6,2],"606":[1,1,1],"607":[2,1,5],"608":[2,1,17],"609":[2,1,7],"610":[2,3,11],"611":[2,3,12],"612":[2,3,21],"613":[2,3,12],"614":[2,3,64],"615":[2,3,31],"616":[2,3,16],"617":[2,1,4],"618":[3,3,32],"619":[3,3,11],"620":[4,5,7],"621":[4,7,38],"622":[4,7,75],"623":[3,5,4],"624":[4,6,20],"625":[3,6,10],"626":[2,1,15],"627":[1,3,38],"628":[1,3,23],"629":[1,3,43],"630":[1,3,1],"631":[2,4,2],"632":[1,6,50],"633":[1,6,14],"634":[1,6,44],"635":[2,7,36],"636":[2,4,2],"637":[1,6,8],"638":[1,6,12],"639":[2,4,3],"640":[1,6,10],"641":[1,6,5],"642":[1,3,1],"643":[2,4,2],"644":[1,6,27],"645":[1,6,14],"646":[1,6,34],"647":[2,4,2],"648":[1,6,8],"649":[1,6,5],"650":[2,4,3],"651":[1,6,10],"652":[1,6,5],"653":[1,3,1],"654":[2,4,5],"655":[1,6,34],"656":[1,6,6],"657":[1,6,29],"658":[2,4,5],"659":[1,6,27],"660":[1,6,6],"661":[1,6,23],"662":[1,3,1],"663":[2,4,2],"664":[1,6,15],"665":[1,6,4],"666":[2,4,13],"667":[1,6,36],"668":[1,6,20],"669":[1,3,1],"670":[2,4,5],"671":[1,6,16],"672":[1,6,8],"673":[1,6,17],"674":[1,3,1],"675":[2,4,12],"676":[1,6,41],"677":[1,6,6],"678":[1,6,69],"679":[1,3,11],"680":[2,4,3],"681":[1,6,13],"682":[1,6,9],"683":[1,6,17],"684":[1,3,1],"685":[2,4,4],"686":[1,6,10],"687":[1,6,12],"688":[1,6,33],"689":[1,3,3],"690":[2,4,8],"691":[1,6,15],"692":[1,6,19],"693":[4,1,1],"694":[4,6,5],"695":[5,6,9],"696":[1,1,1],"697":[1,1,48],"698":[1,1,1],"699":[2,2,17],"700":[2,2,1],"701":[5,4,54],"702":[4,4,11],"703":[5,4,48],"704":[2,2,12],"705":[2,2,27],"706":[2,2,8],"707":[3,4,102],"708":[3,4,80],"709":[1,1,50],"710":[2,1,1],"711":[2,2,35],"712":[3,2,74],"713":[2,2,17],"714":[3,4,11],"715":[5,7,9],"716":[5,7,5],"717":[3,4,69],"718":[2,4,5],"719":[4,4,12],"720":[4,4,14],"721":[1,8,1],"722":[4,8,1],"723":[6,8,1],"724":[2,4,40],"725":[3,4,19],"726":[3,4,20],"727":[3,4,59],"728":[2,4,16],"729":[3,4,10],"730":[3,4,6],"731":[2,2,58],"732":[2,1,1],"733":[2,2,16],"734":[4,4,37],"735":[3,4,18],"736":[1,4,13],"737":[2,2,14],"738":[2,2,1],"739":[7,4,16],"740":[4,4,17],"741":[2,4,12],"742":[2,2,1],"743":[2,4,10],"744":[2,4,9],"745":[2,4,7],"746":[2,4,6],"747":[2,4,9],"748":[2,4,26],"749":[2,4,6],"750":[3,4,3],"751":[2,4,11],"752":[3,4,9],"753":[2,4,25],"754":[2,1,1],"755":[2,2,6],"756":[1,2,1],"757":[1,3,4],"758":[1,3,20],"759":[1,3,69],"760":[1,4,24],"761":[1,3,11],"762":[1,3,24],"763":[1,4,8],"764":[1,4,3],"765":[1,3,1],"766":[1,4,1],"767":[1,5,7],"768":[1,5,10],"769":[1,4,3],"770":[1,5,6],"771":[1,5,8],"772":[1,5,6],"773":[1,3,11],"774":[1,1,1],"775":[3,1,16],"776":[2,1,6],"777":[2,1,1],"778":[3,3,17],"779":[3,3,13],"780":[2,3,8],"781":[3,3,14],"782":[3,3,16],"783":[1,1,15],"784":[1,1,6],"785":[1,1,48],"786":[1,1,7],"787":[1,1,1],"788":[1,2,2],"789":[1,3,21],"790":[1,3,23],"791":[1,2,10],"792":[1,3,24],"793":[1,3,45],"794":[1,2,10],"795":[1,3,17],"796":[1,3,22],"797":[1,2,6],"798":[1,3,81],"799":[1,3,81],"800":[1,2,4],"801":[1,3,25],"802":[1,3,23],"803":[1,1,1],"804":[1,2,11],"805":[2,1,70],"806":[1,1,5],"807":[4,1,46],"808":[1,1,58],"809":[4,1,37],"810":[1,1,1],"811":[1,2,58],"812":[1,2,92],"813":[1,2,43],"814":[1,2,55],"815":[2,2,38],"816":[2,2,11],"817":[1,2,26],"818":[1,2,9],"819":[1,2,6],"820":[1,1,5],"821":[1,1,1],"822":[2,1,17],"823":[2,1,7],"824":[2,3,21],"825":[2,1,67],"826":[2,1,64],"827":[2,1,28],"828":[1,1,25],"829":[5,1,76],"830":[1,1,5],"831":[7,2,41],"832":[5,2,16],"833":[5,2,20],"834":[1,1,28],"835":[4,1,6],"836":[1,5,29],"837":[2,1,6],"838":[1,3,7],"839":[1,1,17],"840":[1,1,1],"841":[3,3,12],"842":[1,1,1],"843":[1,1,7],"844":[1,1,8],"845":[1,1,4],"846":[1,1,7],"847":[1,1,6],"848":[1,1,4],"849":[1,1,1],"850":[1,1,1],"851":[1,1,2],"852":[1,1,3],"853":[1,1,4],"854":[1,1,9],"855":[1,1,1],"856":[1,1,4],"857":[1,1,7],"858":[1,1,1],"859":[1,1,1],"860":[1,1,1],"861":[1,1,1],"862":[1,1,1],"863":[1,1,5],"864":[2,1,22],"865":[2,1,19],"866":[2,1,1],"867":[2,2,1],"868":[2,4,7],"869":[3,4,6],"870":[2,2,1],"871":[3,4,12],"872":[2,4,1],"873":[3,4,55],"874":[2,4,32],"875":[3,4,18],"876":[3,4,9],"877":[3,4,3],"878":[2,2,7],"879":[2,2,1],"880":[5,4,11],"881":[5,4,16],"882":[4,4,14],"883":[5,4,14],"884":[2,1,1],"885":[2,2,16],"886":[2,2,3],"887":[2,2,30],"888":[2,1,1],"889":[1,2,56],"890":[1,1,1],"891":[2,1,5],"892":[2,1,1],"893":[3,3,55],"894":[2,3,10],"895":[3,3,4],"896":[3,3,25],"897":[2,1,20],"898":[2,3,1],"899":[1,5,53],"900":[1,5,22],"901":[2,1,2],"902":[2,1,106],"903":[1,1,1],"904":[1,1,12],"905":[1,1,90],"906":[3,1,2],"907":[1,1,44],"908":[1,1,1],"909":[1,1,3],"910":[2,1,1],"911":[4,3,20],"912":[2,3,1],"913":[5,4,15],"914":[2,4,7],"915":[1,1,3],"916":[3,1,1],"917":[2,3,31],"918":[2,3,1],"919":[5,5,35],"920":[2,5,22],"921":[5,5,6],"922":[3,5,24],"923":[2,3,1],"924":[3,5,26],"925":[3,5,1],"926":[4,8,76],"927":[3,5,51],"928":[2,5,15],"929":[2,3,1],"930":[3,5,31],"931":[3,5,48],"932":[3,5,29],"933":[2,3,6],"934":[3,3,39],"935":[3,3,6],"936":[2,3,1],"937":[3,5,8],"938":[3,5,4],"939":[2,5,41],"940":[3,1,4],"941":[2,3,3],"942":[2,5,39],"943":[3,5,42],"944":[2,3,28],"945":[2,3,73],"946":[2,3,1],"947":[3,5,30],"948":[3,5,20],"949":[2,3,40],"950":[1,1,1],"951":[4,1,11],"952":[3,1,20],"953":[3,1,1],"954":[3,4,2],"955":[1,7,6],"956":[1,7,12],"957":[3,4,9],"958":[1,7,19],"959":[2,7,70],"960":[2,4,15],"961":[1,6,6],"962":[2,6,21],"963":[3,4,4],"964":[3,4,4],"965":[3,4,33],"966":[1,1,1],"967":[1,1,25],"968":[1,1,59],"969":[1,1,1],"970":[1,2,14],"971":[1,2,57],"972":[1,1,1],"973":[3,2,61],"974":[2,2,8],"975":[1,1,23],"976":[2,1,7],"977":[1,3,61],"978":[2,1,15],"979":[1,3,99],"980":[1,3,1],"981":[1,4,65],"982":[1,4,23],"983":[2,1,104],"984":[1,1,37],"985":[1,2,35],"986":[1,2,11],"987":[1,1,1],"988":[1,1,25],"989":[1,1,1],"990":[1,2,1],"991":[2,3,9],"992":[1,2,28],"993":[3,2,17],"994":[1,5,32],"995":[1,5,52],"996":[1,1,27],"997":[1,1,14],"998":[1,1,22],"999":[1,1,18],"1000":[1,1,9],"1001":[1,1,27],"1002":[1,1,20],"1003":[1,1,35],"1004":[1,1,100],"1005":[3,1,76],"1006":[1,3,3],"1007":[3,4,13],"1008":[1,3,1],"1009":[3,4,6],"1010":[1,4,38],"1011":[1,3,8],"1012":[1,1,64],"1013":[1,1,1],"1014":[1,2,34],"1015":[1,2,11],"1016":[1,1,34],"1017":[1,1,7],"1018":[1,1,6],"1019":[1,1,23],"1020":[1,3,6],"1021":[1,3,1],"1022":[1,3,1],"1023":[1,3,8],"1024":[1,3,18],"1025":[1,3,1],"1026":[3,3,16],"1027":[1,3,13],"1028":[1,2,3],"1029":[1,2,25],"1030":[1,1,1],"1031":[1,2,28],"1032":[1,2,15],"1033":[1,2,4],"1034":[1,2,17],"1035":[1,2,3],"1036":[1,2,14],"1037":[2,2,16],"1038":[2,2,8],"1039":[9,2,3],"1040":[1,2,5],"1041":[1,2,5],"1042":[1,2,12],"1043":[1,2,15],"1044":[1,2,6],"1045":[1,2,13],"1046":[1,2,16],"1047":[1,1,1],"1048":[3,2,1],"1049":[1,5,4],"1050":[3,2,1],"1051":[1,5,2],"1052":[3,2,1],"1053":[1,5,2],"1054":[3,2,1],"1055":[1,5,3],"1056":[3,2,1],"1057":[1,5,3],"1058":[3,2,1],"1059":[1,5,2],"1060":[3,2,1],"1061":[1,5,2],"1062":[3,2,1],"1063":[1,5,5],"1064":[3,2,1],"1065":[1,5,9],"1066":[3,2,1],"1067":[1,5,2],"1068":[3,2,1],"1069":[1,5,9],"1070":[3,2,1],"1071":[1,5,6],"1072":[1,1,1],"1073":[1,1,50],"1074":[1,1,24],"1075":[2,1,1],"1076":[1,2,29],"1077":[1,2,21],"1078":[1,2,7],"1079":[5,3,30],"1080":[1,3,8],"1081":[1,2,4],"1082":[2,1,41],"1083":[1,2,21],"1084":[1,2,10],"1085":[1,2,1],"1086":[2,3,18],"1087":[1,3,28],"1088":[1,2,22],"1089":[1,2,1],"1090":[1,3,30],"1091":[1,3,14],"1092":[1,2,1],"1093":[3,3,29],"1094":[4,3,11],"1095":[6,3,21],"1096":[2,3,7],"1097":[2,3,49],"1098":[4,3,12],"1099":[4,3,5],"1100":[6,3,14],"1101":[4,3,8],"1102":[2,1,1],"1103":[2,2,6],"1104":[1,2,1],"1105":[1,3,29],"1106":[1,3,65],"1107":[1,3,11],"1108":[1,3,1],"1109":[1,4,5],"1110":[1,4,6],"1111":[1,3,11],"1112":[1,4,24],"1113":[1,4,20],"1114":[1,4,8],"1115":[1,4,3],"1116":[2,1,1],"1117":[2,2,3],"1118":[1,2,14],"1119":[1,2,1],"1120":[1,3,73],"1121":[1,3,11],"1122":[1,3,11],"1123":[2,3,29],"1124":[2,3,29],"1125":[1,1,1],"1126":[3,1,52],"1127":[1,1,4],"1128":[2,1,8],"1129":[2,1,9],"1130":[1,3,6],"1131":[1,3,21],"1132":[1,1,7],"1133":[2,1,21],"1134":[1,2,9],"1135":[1,2,10],"1136":[1,2,35]},"averageFieldLength":[2.020228671943709,2.745822339489886,14.209322779243628],"storedFields":{"0":{"title":"稳定版本","titles":[]},"1":{"title":"2024-10-18 【预发布】","titles":[]},"2":{"title":"Feature","titles":["2024-10-18 【预发布】"]},"3":{"title":"Fixed","titles":["2024-10-18 【预发布】"]},"4":{"title":"2024-10-8 【重要更新】","titles":[]},"5":{"title":"Feature","titles":["2024-10-8 【重要更新】"]},"6":{"title":"Fixed","titles":["2024-10-8 【重要更新】"]},"7":{"title":"2024-8-13 【重要更新】","titles":[]},"8":{"title":"Feature","titles":["2024-8-13 【重要更新】"]},"9":{"title":"Fixed","titles":["2024-8-13 【重要更新】"]},"10":{"title":"2024-7-09 【普通更新】","titles":[]},"11":{"title":"Feature","titles":["2024-7-09 【普通更新】"]},"12":{"title":"Fixed","titles":["2024-7-09 【普通更新】"]},"13":{"title":"2024-5-17 【普通更新】","titles":[]},"14":{"title":"Fixed","titles":["2024-5-17 【普通更新】"]},"15":{"title":"2024-5-15 【普通更新】","titles":[]},"16":{"title":"Feature","titles":["2024-5-15 【普通更新】"]},"17":{"title":"2024-4-26 【普通更新】","titles":[]},"18":{"title":"Fixed","titles":["2024-4-26 【普通更新】"]},"19":{"title":"2024-4-17 【普通更新】","titles":[]},"20":{"title":"Feature","titles":["2024-4-17 【普通更新】"]},"21":{"title":"Fixed","titles":["2024-4-17 【普通更新】"]},"22":{"title":"2024-4-3 【重要更新】","titles":[]},"23":{"title":"Fixed","titles":["2024-4-3 【重要更新】"]},"24":{"title":"2024-3-28 【普通更新】","titles":[]},"25":{"title":"Fixed","titles":["2024-3-28 【普通更新】"]},"26":{"title":"2024-3-5 【普通更新】","titles":[]},"27":{"title":"Fixed","titles":["2024-3-5 【普通更新】"]},"28":{"title":"2024-1-18 【普通更新】","titles":[]},"29":{"title":"Fixed","titles":["2024-1-18 【普通更新】"]},"30":{"title":"2024-1-15 【普通更新】","titles":[]},"31":{"title":"Feature","titles":["2024-1-15 【普通更新】"]},"32":{"title":"Fixed","titles":["2024-1-15 【普通更新】"]},"33":{"title":"2024-1-2 【重要更新】","titles":[]},"34":{"title":"Feature","titles":["2024-1-2 【重要更新】"]},"35":{"title":"Fixed","titles":["2024-1-2 【重要更新】"]},"36":{"title":"2023-12-18 【重要更新】","titles":[]},"37":{"title":"Feature","titles":["2023-12-18 【重要更新】"]},"38":{"title":"Fixed","titles":["2023-12-18 【重要更新】"]},"39":{"title":"2023-12-12 【重要更新】","titles":[]},"40":{"title":"Feature","titles":["2023-12-12 【重要更新】"]},"41":{"title":"2023-12-08 【重要更新】","titles":[]},"42":{"title":"Feature","titles":["2023-12-08 【重要更新】"]},"43":{"title":"Fixed","titles":["2023-12-08 【重要更新】"]},"44":{"title":"2023-11-29 【普通更新】","titles":[]},"45":{"title":"Fixed","titles":["2023-11-29 【普通更新】"]},"46":{"title":"2023-11-28","titles":[]},"47":{"title":"Feature","titles":["2023-11-28"]},"48":{"title":"Fixed","titles":["2023-11-28"]},"49":{"title":"2023-11-10","titles":[]},"50":{"title":"Feature","titles":["2023-11-10"]},"51":{"title":"2023-11-02","titles":[]},"52":{"title":"Fixed","titles":["2023-11-02"]},"53":{"title":"2023-10-20","titles":[]},"54":{"title":"Feature","titles":["2023-10-20"]},"55":{"title":"Fixed","titles":["2023-10-20"]},"56":{"title":"2023-10-11【普通更新】","titles":[]},"57":{"title":"Feature","titles":["2023-10-11【普通更新】"]},"58":{"title":"2023-9-26","titles":[]},"59":{"title":"Feature","titles":["2023-9-26"]},"60":{"title":"Fixed","titles":["2023-9-26"]},"61":{"title":"2023-09-20","titles":[]},"62":{"title":"Feature","titles":["2023-09-20"]},"63":{"title":"2023-09-01","titles":[]},"64":{"title":"Feature","titles":["2023-09-01"]},"65":{"title":"Fixed","titles":["2023-09-01"]},"66":{"title":"2023-08-24","titles":[]},"67":{"title":"Feature","titles":["2023-08-24"]},"68":{"title":"Fixed","titles":["2023-08-24"]},"69":{"title":"2023-08-18","titles":[]},"70":{"title":"Feature","titles":["2023-08-18"]},"71":{"title":"Fixed","titles":["2023-08-18"]},"72":{"title":"2023-08-10","titles":[]},"73":{"title":"Feature","titles":["2023-08-10"]},"74":{"title":"2023-08-3","titles":[]},"75":{"title":"Feature","titles":["2023-08-3"]},"76":{"title":"Fixed","titles":["2023-08-3"]},"77":{"title":"2023-07-27","titles":[]},"78":{"title":"Feature","titles":["2023-07-27"]},"79":{"title":"Fixed","titles":["2023-07-27"]},"80":{"title":"2023-07-20","titles":[]},"81":{"title":"Feature","titles":["2023-07-20"]},"82":{"title":"Fixed","titles":["2023-07-20"]},"83":{"title":"2023-07-12","titles":[]},"84":{"title":"Feature","titles":["2023-07-12"]},"85":{"title":"2023-07-05","titles":[]},"86":{"title":"Feature","titles":["2023-07-05"]},"87":{"title":"Fixed","titles":["2023-07-05"]},"88":{"title":"2023-06-29","titles":[]},"89":{"title":"Feature","titles":["2023-06-29"]},"90":{"title":"Fixed","titles":["2023-06-29"]},"91":{"title":"2023-06-16","titles":[]},"92":{"title":"Fixed","titles":["2023-06-16"]},"93":{"title":"2023-06-14","titles":[]},"94":{"title":"Feature","titles":["2023-06-14"]},"95":{"title":"Fixed","titles":["2023-06-14"]},"96":{"title":"2023-06-12","titles":[]},"97":{"title":"Fixed","titles":["2023-06-12"]},"98":{"title":"2023-06-7","titles":[]},"99":{"title":"Feature","titles":["2023-06-7"]},"100":{"title":"Fixed","titles":["2023-06-7"]},"101":{"title":"2023-06-1","titles":[]},"102":{"title":"Feature","titles":["2023-06-1"]},"103":{"title":"Fixed","titles":["2023-06-1"]},"104":{"title":"2023-05-24","titles":[]},"105":{"title":"Feature","titles":["2023-05-24"]},"106":{"title":"Fixed","titles":["2023-05-24"]},"107":{"title":"2023-05-22","titles":[]},"108":{"title":"Feature","titles":["2023-05-22"]},"109":{"title":"Fixed","titles":["2023-05-22"]},"110":{"title":"2023-04-26","titles":[]},"111":{"title":"Changed","titles":["2023-04-26"]},"112":{"title":"2023-03-31","titles":[]},"113":{"title":"Feature","titles":["2023-03-31"]},"114":{"title":"2023-02-22","titles":[]},"115":{"title":"Feature","titles":["2023-02-22"]},"116":{"title":"2023-02-15","titles":[]},"117":{"title":"Fixed","titles":["2023-02-15"]},"118":{"title":"2023-02-9","titles":[]},"119":{"title":"Feature","titles":["2023-02-9"]},"120":{"title":"Fixed","titles":["2023-02-9"]},"121":{"title":"2023-01-17","titles":[]},"122":{"title":"Fixed","titles":["2023-01-17"]},"123":{"title":"2023-01-17","titles":[]},"124":{"title":"Feature","titles":["2023-01-17"]},"125":{"title":"Fixed","titles":["2023-01-17"]},"126":{"title":"2023-01-04","titles":[]},"127":{"title":"Feature","titles":["2023-01-04"]},"128":{"title":"Fixed","titles":["2023-01-04"]},"129":{"title":"2022-12-28","titles":[]},"130":{"title":"Feature","titles":["2022-12-28"]},"131":{"title":"Fixed","titles":["2022-12-28"]},"132":{"title":"2022-12-22","titles":[]},"133":{"title":"Fixed","titles":["2022-12-22"]},"134":{"title":"2022-12-21","titles":[]},"135":{"title":"Feature","titles":["2022-12-21"]},"136":{"title":"2022-12-7","titles":[]},"137":{"title":"Feature","titles":["2022-12-7"]},"138":{"title":"Fixed","titles":["2022-12-7"]},"139":{"title":"2022-11-30","titles":[]},"140":{"title":"Feature","titles":["2022-11-30"]},"141":{"title":"2022-11-23","titles":[]},"142":{"title":"Feature","titles":["2022-11-23"]},"143":{"title":"Fixed","titles":["2022-11-23"]},"144":{"title":"2022-11-17","titles":[]},"145":{"title":"Feature","titles":["2022-11-17"]},"146":{"title":"2022-11-9","titles":[]},"147":{"title":"Feature","titles":["2022-11-9"]},"148":{"title":"Fixed","titles":["2022-11-9"]},"149":{"title":"2022-10-27","titles":[]},"150":{"title":"Feature","titles":["2022-10-27"]},"151":{"title":"Fixed","titles":["2022-10-27"]},"152":{"title":"2022-10-20","titles":[]},"153":{"title":"Feature","titles":["2022-10-20"]},"154":{"title":"2022-10-12","titles":[]},"155":{"title":"Feature","titles":["2022-10-12"]},"156":{"title":"Fixed","titles":["2022-10-12"]},"157":{"title":"2022-9-28","titles":[]},"158":{"title":"Feature","titles":["2022-9-28"]},"159":{"title":"Fixed","titles":["2022-9-28"]},"160":{"title":"2022-9-21","titles":[]},"161":{"title":"Feature","titles":["2022-9-21"]},"162":{"title":"Fixed","titles":["2022-9-21"]},"163":{"title":"2022-9-13","titles":[]},"164":{"title":"Feature","titles":["2022-9-13"]},"165":{"title":"2022-9-8","titles":[]},"166":{"title":"Fixed","titles":["2022-9-8"]},"167":{"title":"Feature","titles":["2022-9-8"]},"168":{"title":"2022-9-7","titles":[]},"169":{"title":"Fixed","titles":["2022-9-7"]},"170":{"title":"2022-8-31","titles":[]},"171":{"title":"Fixed","titles":["2022-8-31"]},"172":{"title":"2022-8-26","titles":[]},"173":{"title":"Feature","titles":["2022-8-26"]},"174":{"title":"2022-8-17","titles":[]},"175":{"title":"Feature","titles":["2022-8-17"]},"176":{"title":"2022-8-11","titles":[]},"177":{"title":"Fixed","titles":["2022-8-11"]},"178":{"title":"2022-8-10","titles":[]},"179":{"title":"Feature","titles":["2022-8-10"]},"180":{"title":"Fixed","titles":["2022-8-10"]},"181":{"title":"2022-7-28","titles":[]},"182":{"title":"Feature","titles":["2022-7-28"]},"183":{"title":"2022-7-20","titles":[]},"184":{"title":"Feature","titles":["2022-7-20"]},"185":{"title":"Fixed","titles":["2022-7-20"]},"186":{"title":"Feature","titles":["2022-7-20"]},"187":{"title":"2022-7-14","titles":[]},"188":{"title":"Fixed","titles":["2022-7-14"]},"189":{"title":"2022-7-1","titles":[]},"190":{"title":"Fixed","titles":["2022-7-1"]},"191":{"title":"2022-6-30","titles":[]},"192":{"title":"Fixed","titles":["2022-6-30"]},"193":{"title":"2022-6-28","titles":[]},"194":{"title":"Feature","titles":["2022-6-28"]},"195":{"title":"Fixed","titles":["2022-6-28"]},"196":{"title":"2022-6-18","titles":[]},"197":{"title":"Fixed","titles":["2022-6-18"]},"198":{"title":"2022-6-16","titles":[]},"199":{"title":"Feature","titles":["2022-6-16"]},"200":{"title":"Fixed","titles":["2022-6-16"]},"201":{"title":"2022-6-13","titles":[]},"202":{"title":"Fixed","titles":["2022-6-13"]},"203":{"title":"2022-6-8","titles":[]},"204":{"title":"Feature","titles":["2022-6-8"]},"205":{"title":"Fixed","titles":["2022-6-8"]},"206":{"title":"2022-6-7","titles":[]},"207":{"title":"Feature","titles":["2022-6-7"]},"208":{"title":"2022-6-1","titles":[]},"209":{"title":"Feature","titles":["2022-6-1"]},"210":{"title":"2022-5-31","titles":[]},"211":{"title":"Feature","titles":["2022-5-31"]},"212":{"title":"2022-5-30","titles":[]},"213":{"title":"Fixed","titles":["2022-5-30"]},"214":{"title":"2022-5-26","titles":[]},"215":{"title":"Changed","titles":["2022-5-26"]},"216":{"title":"Fixed","titles":["2022-5-26"]},"217":{"title":"2022-5-24","titles":[]},"218":{"title":"Feature","titles":["2022-5-24"]},"219":{"title":"2022-4-29","titles":[]},"220":{"title":"Fixed","titles":["2022-4-29"]},"221":{"title":"2022-4-26","titles":[]},"222":{"title":"Fixed","titles":["2022-4-26"]},"223":{"title":"Feature","titles":["2022-4-26"]},"224":{"title":"2022-4-24","titles":[]},"225":{"title":"Fixed","titles":["2022-4-24"]},"226":{"title":"2022-4-22","titles":[]},"227":{"title":"Fixed","titles":["2022-4-22"]},"228":{"title":"Feature","titles":["2022-4-22"]},"229":{"title":"2022-4-18","titles":[]},"230":{"title":"Feature","titles":["2022-4-18"]},"231":{"title":"2022-4-14","titles":[]},"232":{"title":"Feature","titles":["2022-4-14"]},"233":{"title":"2022-4-11","titles":[]},"234":{"title":"Changed","titles":["2022-4-11"]},"235":{"title":"2022-3-29","titles":[]},"236":{"title":"Changed","titles":["2022-3-29"]},"237":{"title":"2022-3-22","titles":[]},"238":{"title":"Changed","titles":["2022-3-22"]},"239":{"title":"2022-3-7","titles":[]},"240":{"title":"Changed","titles":["2022-3-7"]},"241":{"title":"2022-3-7","titles":[]},"242":{"title":"Changed","titles":["2022-3-7"]},"243":{"title":"2022-2-17","titles":[]},"244":{"title":"Changed","titles":["2022-2-17"]},"245":{"title":"2022-2-15","titles":[]},"246":{"title":"Fixed","titles":["2022-2-15"]},"247":{"title":"2022-2-14","titles":[]},"248":{"title":"Feature","titles":["2022-2-14"]},"249":{"title":"2022-2-11","titles":[]},"250":{"title":"Feature","titles":["2022-2-11"]},"251":{"title":"2022-1-26","titles":[]},"252":{"title":"Feature","titles":["2022-1-26"]},"253":{"title":"2022-1-25","titles":[]},"254":{"title":"Fixed","titles":["2022-1-25"]},"255":{"title":"2022-1-24","titles":[]},"256":{"title":"Feature","titles":["2022-1-24"]},"257":{"title":"2022-1-21","titles":[]},"258":{"title":"Feature","titles":["2022-1-21"]},"259":{"title":"Changed","titles":["2022-1-21"]},"260":{"title":"2022-1-20","titles":[]},"261":{"title":"Feature","titles":["2022-1-20"]},"262":{"title":"2022-1-17","titles":[]},"263":{"title":"Fixed","titles":["2022-1-17"]},"264":{"title":"Changed","titles":["2022-1-17"]},"265":{"title":"2022-1-13","titles":[]},"266":{"title":"Fixed","titles":["2022-1-13"]},"267":{"title":"2022-1-7","titles":[]},"268":{"title":"Fixed","titles":["2022-1-7"]},"269":{"title":"2021-12-31","titles":[]},"270":{"title":"Fixed","titles":["2021-12-31"]},"271":{"title":"2021-12-30","titles":[]},"272":{"title":"Fixed","titles":["2021-12-30"]},"273":{"title":"2021-12-20","titles":[]},"274":{"title":"Fixed","titles":["2021-12-20"]},"275":{"title":"2021-12-16","titles":[]},"276":{"title":"Feature","titles":["2021-12-16"]},"277":{"title":"2021-12-10","titles":[]},"278":{"title":"Fixed","titles":["2021-12-10"]},"279":{"title":"2021-12-06","titles":[]},"280":{"title":"Feature","titles":["2021-12-06"]},"281":{"title":"Fixed","titles":["2021-12-06"]},"282":{"title":"2021-12-02","titles":[]},"283":{"title":"Fixed","titles":["2021-12-02"]},"284":{"title":"2021-11-30","titles":[]},"285":{"title":"Changed","titles":["2021-11-30"]},"286":{"title":"Fixed","titles":["2021-11-30"]},"287":{"title":"2021-11-19","titles":[]},"288":{"title":"Fixed","titles":["2021-11-19"]},"289":{"title":"2021-11-18","titles":[]},"290":{"title":"Feature","titles":["2021-11-18"]},"291":{"title":"Fixed","titles":["2021-11-18"]},"292":{"title":"Changed","titles":["2021-11-18"]},"293":{"title":"2021-10-26","titles":[]},"294":{"title":"Feature","titles":["2021-10-26"]},"295":{"title":"2021-10-09","titles":[]},"296":{"title":"Feature","titles":["2021-10-09"]},"297":{"title":"2021-09-23","titles":[]},"298":{"title":"Fixed","titles":["2021-09-23"]},"299":{"title":"2021-09-22","titles":[]},"300":{"title":"Feature","titles":["2021-09-22"]},"301":{"title":"Feature","titles":["2021-09-22"]},"302":{"title":"Feature","titles":["2021-09-22"]},"303":{"title":"2021-09-14","titles":[]},"304":{"title":"Feature","titles":["2021-09-14"]},"305":{"title":"Fixed","titles":["2021-09-14"]},"306":{"title":"2021-09-06","titles":[]},"307":{"title":"Feature","titles":["2021-09-06"]},"308":{"title":"2021-8-20","titles":[]},"309":{"title":"Feature","titles":["2021-8-20"]},"310":{"title":"2021-8-12","titles":[]},"311":{"title":"Feature","titles":["2021-8-12"]},"312":{"title":"2021-8-10","titles":[]},"313":{"title":"Changed","titles":["2021-8-10"]},"314":{"title":"2021-08-05","titles":[]},"315":{"title":"Feature","titles":["2021-08-05"]},"316":{"title":"2021-08-04","titles":[]},"317":{"title":"Fixed","titles":["2021-08-04"]},"318":{"title":"2021-08-02","titles":[]},"319":{"title":"Fixed","titles":["2021-08-02"]},"320":{"title":"2021-08-01","titles":[]},"321":{"title":"Changed","titles":["2021-08-01"]},"322":{"title":"2021-07-31","titles":[]},"323":{"title":"Feature","titles":["2021-07-31"]},"324":{"title":"Changed","titles":["2021-07-31"]},"325":{"title":"2021-07-26","titles":[]},"326":{"title":"Feature","titles":["2021-07-26"]},"327":{"title":"2021-07-26","titles":[]},"328":{"title":"Feature","titles":["2021-07-26"]},"329":{"title":"2021-07-20","titles":[]},"330":{"title":"Fixed","titles":["2021-07-20"]},"331":{"title":"2021-07-19","titles":[]},"332":{"title":"Changed","titles":["2021-07-19"]},"333":{"title":"2021-07-13","titles":[]},"334":{"title":"Fixed","titles":["2021-07-13"]},"335":{"title":"Changed","titles":["2021-07-13"]},"336":{"title":"2021-07-09","titles":[]},"337":{"title":"Fixed","titles":["2021-07-09"]},"338":{"title":"2021-07-02","titles":[]},"339":{"title":"Fixed","titles":["2021-07-02"]},"340":{"title":"2021-06-30","titles":[]},"341":{"title":"Fixed","titles":["2021-06-30"]},"342":{"title":"Feature","titles":["2021-06-30"]},"343":{"title":"2021-06-29","titles":[]},"344":{"title":"Fixed","titles":["2021-06-29"]},"345":{"title":"Feature","titles":["2021-06-29"]},"346":{"title":"Removed","titles":["2021-06-29"]},"347":{"title":"Changed","titles":["2021-06-29"]},"348":{"title":"Others","titles":["2021-06-29"]},"349":{"title":"2021-06-10","titles":[]},"350":{"title":"Fixed","titles":["2021-06-10"]},"351":{"title":"使用Android CPU Profiler性能调优","titles":[]},"352":{"title":"MiniGameConfig.asset 配置文件说明","titles":[]},"353":{"title":"ProjectConfig:","titles":["MiniGameConfig.asset 配置文件说明"]},"354":{"title":"SDKOptions:","titles":["MiniGameConfig.asset 配置文件说明"]},"355":{"title":"CompileOptions:","titles":["MiniGameConfig.asset 配置文件说明"]},"356":{"title":"CompressTexture:","titles":["MiniGameConfig.asset 配置文件说明"]},"357":{"title":"PlayerPrefsKeys:","titles":["MiniGameConfig.asset 配置文件说明"]},"358":{"title":"FontOptions:","titles":["MiniGameConfig.asset 配置文件说明"]},"359":{"title":"资源优化","titles":[]},"360":{"title":"工具入口","titles":["资源优化"]},"361":{"title":"工具介绍","titles":["资源优化"]},"362":{"title":"Texture","titles":["资源优化","工具介绍"]},"363":{"title":"优化建议","titles":["资源优化"]},"364":{"title":"音视频适配","titles":[]},"365":{"title":"音频","titles":["音视频适配"]},"366":{"title":"兼容原理","titles":["音视频适配"]},"367":{"title":"QA","titles":["音视频适配","兼容原理"]},"368":{"title":"视频","titles":["音视频适配"]},"369":{"title":"VideoPlayer 支持版本","titles":["音视频适配","视频"]},"370":{"title":"QA","titles":["音视频适配","视频"]},"371":{"title":"后端服务指引","titles":[]},"372":{"title":"后端服务模式","titles":["后端服务指引"]},"373":{"title":"自建后端服务","titles":["后端服务指引"]},"374":{"title":"云开发","titles":["后端服务指引"]},"375":{"title":"配置构建模板","titles":[]},"376":{"title":"简介","titles":["配置构建模板"]},"377":{"title":"结构说明","titles":["配置构建模板"]},"378":{"title":"新版本SDK引起的冲突提醒","titles":["配置构建模板"]},"379":{"title":"消除冲突提醒","titles":["配置构建模板","新版本SDK引起的冲突提醒"]},"380":{"title":"JSON配置合并","titles":["配置构建模板"]},"381":{"title":"构建模板前后不同时机的钩子","titles":["配置构建模板"]},"382":{"title":"钩子介绍","titles":["配置构建模板","构建模板前后不同时机的钩子"]},"383":{"title":"使用钩子","titles":["配置构建模板","构建模板前后不同时机的钩子"]},"384":{"title":"BuildTemplateHelper介绍","titles":["配置构建模板","构建模板前后不同时机的钩子"]},"385":{"title":"微信小游戏压缩纹理工具2.0(Beta)","titles":[]},"386":{"title":"概述","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"387":{"title":"使用建议","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"388":{"title":"Unity 版本支持问题","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"389":{"title":"使用说明","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"390":{"title":"1.安装 Node.js","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明"]},"391":{"title":"2.构建 Bundle 文件","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明"]},"392":{"title":"构建前的纹理格式配置说明:","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明","2.构建 Bundle 文件"]},"393":{"title":"ASTC格式配置说明:","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明","2.构建 Bundle 文件"]},"394":{"title":"3.导出游戏","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明"]},"395":{"title":"4.执行压缩纹理","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明"]},"396":{"title":"5.上传CDN","titles":["微信小游戏压缩纹理工具2.0(Beta)","使用说明"]},"397":{"title":"WebGL2.0 支持说明(Beta)","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"398":{"title":"忽略配置说明","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"399":{"title":"首资源包优化说明","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"400":{"title":"新版本异常回退说明","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"401":{"title":"原理解释","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"402":{"title":"Q&A","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"403":{"title":"1.生成的纹理太大","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A"]},"404":{"title":"2.资源上传至CDN的注意事项","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A"]},"405":{"title":"3.非4倍数的资源处理底层逻辑","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A"]},"406":{"title":"4.Node.js异常处理","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A"]},"407":{"title":"5.分离纹理后各自单独下载是否会增加下载开销?","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A"]},"408":{"title":"6.MacOS系统执行报错 “'System.Drawing.GDIPlus' threw an exception”","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A"]},"409":{"title":"解决方案一:","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A","6.MacOS系统执行报错 “'System.Drawing.GDIPlus' threw an exception”"]},"410":{"title":"解决方案二:","titles":["微信小游戏压缩纹理工具2.0(Beta)","Q&A","6.MacOS系统执行报错 “'System.Drawing.GDIPlus' threw an exception”"]},"411":{"title":"微信压缩纹理API介绍","titles":["微信小游戏压缩纹理工具2.0(Beta)"]},"412":{"title":"WXAssetsTextTools.CompressText( ... )","titles":["微信小游戏压缩纹理工具2.0(Beta)","微信压缩纹理API介绍"]},"413":{"title":"说明","titles":["微信小游戏压缩纹理工具2.0(Beta)","微信压缩纹理API介绍","WXAssetsTextTools.CompressText( ... )"]},"414":{"title":"参数","titles":["微信小游戏压缩纹理工具2.0(Beta)","微信压缩纹理API介绍","WXAssetsTextTools.CompressText( ... )"]},"415":{"title":"WXAssetsTextTools.GetAssetBundles( ... )","titles":["微信小游戏压缩纹理工具2.0(Beta)","微信压缩纹理API介绍"]},"416":{"title":"说明","titles":["微信小游戏压缩纹理工具2.0(Beta)","微信压缩纹理API介绍","WXAssetsTextTools.GetAssetBundles( ... )"]},"417":{"title":"参数","titles":["微信小游戏压缩纹理工具2.0(Beta)","微信压缩纹理API介绍","WXAssetsTextTools.GetAssetBundles( ... )"]},"418":{"title":"启动封面","titles":[]},"419":{"title":"完整配置","titles":["启动封面"]},"420":{"title":"转换插件配置","titles":["启动封面","完整配置"]},"421":{"title":"game.js配置","titles":["启动封面","完整配置"]},"422":{"title":"默认效果","titles":["启动封面"]},"423":{"title":"定制效果","titles":["启动封面"]},"424":{"title":"自定义SDK调用","titles":[]},"425":{"title":"版本要求","titles":["自定义SDK调用"]},"426":{"title":"代码示例","titles":["自定义SDK调用"]},"427":{"title":"定制微信小游戏的 URP 管线","titles":[]},"428":{"title":"本地化 URP 包","titles":["定制微信小游戏的 URP 管线"]},"429":{"title":"准备条件编译宏","titles":["定制微信小游戏的 URP 管线"]},"430":{"title":"定制本地化 URP 管线","titles":["定制微信小游戏的 URP 管线"]},"431":{"title":"供参考的 URP 定制版本","titles":["定制微信小游戏的 URP 管线","定制本地化 URP 管线"]},"432":{"title":"微信 URP 定制版本的性能数据对比","titles":["定制微信小游戏的 URP 管线","定制本地化 URP 管线"]},"433":{"title":"注意事项","titles":["定制微信小游戏的 URP 管线"]},"434":{"title":"参考","titles":["定制微信小游戏的 URP 管线"]},"435":{"title":"资源部署与缓存","titles":[]},"436":{"title":"资源部署","titles":["资源部署与缓存"]},"437":{"title":"首资源包","titles":["资源部署与缓存","资源部署"]},"438":{"title":"Assets","titles":["资源部署与缓存","资源部署"]},"439":{"title":"StreamingAssets","titles":["资源部署与缓存","资源部署"]},"440":{"title":"资源服务器注意事项","titles":["资源部署与缓存","资源部署"]},"441":{"title":"资源更新说明","titles":["资源部署与缓存"]},"442":{"title":"资源缓存","titles":["资源部署与缓存"]},"443":{"title":"资源缓存规则","titles":["资源部署与缓存","资源缓存"]},"444":{"title":"错误调试与异常排查","titles":[]},"445":{"title":"如何排查程序中出现的异常","titles":["错误调试与异常排查"]},"446":{"title":"如何查看日志","titles":["错误调试与异常排查","如何排查程序中出现的异常"]},"447":{"title":"如何通过错误堆栈查找源代码问题","titles":["错误调试与异常排查","如何排查程序中出现的异常"]},"448":{"title":"使用Profiling-funcs","titles":["错误调试与异常排查","如何排查程序中出现的异常","如何通过错误堆栈查找源代码问题"]},"449":{"title":"使用symbols文件可读函数名","titles":["错误调试与异常排查","如何排查程序中出现的异常","如何通过错误堆栈查找源代码问题"]},"450":{"title":"影响异常错误的导出选项","titles":["错误调试与异常排查"]},"451":{"title":"Enable Exceptions","titles":["错误调试与异常排查","影响异常错误的导出选项"]},"452":{"title":"Debug Symbols","titles":["错误调试与异常排查","影响异常错误的导出选项"]},"453":{"title":"Development Build","titles":["错误调试与异常排查","影响异常错误的导出选项"]},"454":{"title":"技术常见问题QA","titles":[]},"455":{"title":"工具使用","titles":["技术常见问题QA"]},"456":{"title":"1.微信开发者工具打开时提示“app.json未找到”","titles":["技术常见问题QA","工具使用"]},"457":{"title":"2.微信开发者工具打开时提示“找不到game.json或读取错误”","titles":["技术常见问题QA","工具使用"]},"458":{"title":"3.如何在真机上预览游戏","titles":["技术常见问题QA","工具使用"]},"459":{"title":"4.如何在真机上进行调试和错误日志排查","titles":["技术常见问题QA","工具使用"]},"460":{"title":"5.Unity PlayerSettings导出选项中使用"brotli"或"gzip", 使用微信开发者工具无法启动游戏","titles":["技术常见问题QA","工具使用"]},"461":{"title":"6.使用代码分包的情况下,启动游戏出现“首次拉取代码分包”提示","titles":["技术常见问题QA","工具使用"]},"462":{"title":"7.微信开发者工具提示"资源下载失败"","titles":["技术常见问题QA","工具使用"]},"463":{"title":"8.微信开发者工具能正常打开游戏,但Android卡在首屏,资源下载失败","titles":["技术常见问题QA","工具使用"]},"464":{"title":"9.开发者工具提示“插件申请成功,待审核确认”","titles":["技术常见问题QA","工具使用"]},"465":{"title":"10.内网开发时,微信开发者工具服务异常","titles":["技术常见问题QA","工具使用"]},"466":{"title":"11.开发者工具提示pluginid: wx7a727ff7d940bb3f, permission deny字样错误","titles":["技术常见问题QA","工具使用"]},"467":{"title":"12.小游戏包中的webgl.wasm.symbols.unityweb不会被上传,是做什么用的","titles":["技术常见问题QA","工具使用"]},"468":{"title":"13.如何自定义接入构建流程","titles":["技术常见问题QA","工具使用"]},"469":{"title":"Unity WebGL","titles":["技术常见问题QA"]},"470":{"title":"1.能否使用System.Net命名空间下的接口","titles":["技术常见问题QA","Unity WebGL"]},"471":{"title":"2.小游戏启动出现"Unable to load DLL ...."","titles":["技术常见问题QA","Unity WebGL"]},"472":{"title":"3.能否使用System.File相关接口做文件存储","titles":["技术常见问题QA","Unity WebGL"]},"473":{"title":"4.如何接入第三方的js sdk, 能写js脚本和C#进行交互吗?","titles":["技术常见问题QA","Unity WebGL"]},"474":{"title":"5.小游戏的中文字体不显示,但Editor没问题","titles":["技术常见问题QA","Unity WebGL"]},"475":{"title":"6.游戏逻辑是否能使用lua","titles":["技术常见问题QA","Unity WebGL"]},"476":{"title":"7.Touch事件丢失或错误,导致多点触控不正确","titles":["技术常见问题QA","Unity WebGL"]},"477":{"title":"8.显示黑屏,运行提示大量shader编译错误","titles":["技术常见问题QA","Unity WebGL"]},"478":{"title":"9.Unity FMOD音频插件是否支持?","titles":["技术常见问题QA","Unity WebGL"]},"479":{"title":"10.Mac 系统下 Unity 构建 WebGL 项目报Failed running "../il2cppcore/il2cppcore.dll"错误解决办法","titles":["技术常见问题QA","Unity WebGL"]},"480":{"title":"11.引擎代码裁剪级别(Managed Striping Level)应该如何设置?","titles":["技术常见问题QA","Unity WebGL"]},"481":{"title":"12.使用xlua等方案在WebGL平台报“ArgumentException: Destination array was not long enough”?","titles":["技术常见问题QA","Unity WebGL"]},"482":{"title":"平台适配","titles":["技术常见问题QA"]},"483":{"title":"1.文本输入框点击无法输入,没有弹出输入法","titles":["技术常见问题QA","平台适配"]},"484":{"title":"2.高性能模式下iOS无法加载,但Android和微信开发者工具没问题","titles":["技术常见问题QA","平台适配"]},"485":{"title":"3.Android运行达到满帧较为流畅,iOS性能差","titles":["技术常见问题QA","平台适配"]},"486":{"title":"4.小游戏中能插入超链接跳转网页吗?","titles":["技术常见问题QA","平台适配"]},"487":{"title":"5.小游戏是否支持Unity VideoPlayer","titles":["技术常见问题QA","平台适配"]},"488":{"title":"6.小游戏应该使用哪个接口进行限制帧率?","titles":["技术常见问题QA","平台适配"]},"489":{"title":"7.Unity Audio音频是否需要使用小游戏音频适配","titles":["技术常见问题QA","平台适配"]},"490":{"title":"8.PlayerPref或用户数据存储失效","titles":["技术常见问题QA","平台适配"]},"491":{"title":"9.微信接口提示“fail require user interaction (only in touchend event)”","titles":["技术常见问题QA","平台适配"]},"492":{"title":"10. 团结引擎导出的小游戏卡在Loading界面并提示“MONO_WASM: Failed to load config file ./blazor.boot.json”","titles":["技术常见问题QA","平台适配"]},"493":{"title":"11. 使用 WebGL2 URP管线导出小游戏时提示 shader 编译报错 “Hidden/Universal/CoreBlit: invalid pass index 1 in DrawProcedural”","titles":["技术常见问题QA","平台适配"]},"494":{"title":"12. PC端输入框无法输入,移动端正常","titles":["技术常见问题QA","平台适配"]},"495":{"title":"方案评估","titles":[]},"496":{"title":"1. 游戏类目","titles":["方案评估"]},"497":{"title":"2. 引擎版本","titles":["方案评估"]},"498":{"title":"3. 能力支持","titles":["方案评估"]},"499":{"title":"微信开发者工具域名列表","titles":[]},"500":{"title":"资源缓存","titles":[]},"501":{"title":"介绍","titles":[]},"502":{"title":"一、什么情况触发资源缓存","titles":["介绍"]},"503":{"title":"二、哪些资源会自动缓存?","titles":["介绍"]},"504":{"title":"三、缓存规则","titles":["介绍"]},"505":{"title":"相关配置","titles":["介绍","三、缓存规则"]},"506":{"title":"是否缓存规则","titles":["介绍","三、缓存规则","相关配置"]},"507":{"title":"是否缓存业务资源","titles":["介绍","三、缓存规则","相关配置","是否缓存规则"]},"508":{"title":"是否缓存纹理","titles":["介绍","三、缓存规则","相关配置","是否缓存规则"]},"509":{"title":"资源淘汰规则","titles":["介绍","三、缓存规则","相关配置"]},"510":{"title":"识别业务资源版本","titles":["介绍","三、缓存规则","相关配置","资源淘汰规则"]},"511":{"title":"识别纹理资源版本","titles":["介绍","三、缓存规则","相关配置","资源淘汰规则"]},"512":{"title":"缓存清理规则","titles":["介绍","三、缓存规则","相关配置"]},"513":{"title":"示例","titles":["介绍","三、缓存规则"]},"514":{"title":"四、查看缓存日志","titles":["介绍"]},"515":{"title":"判断是否走缓存","titles":["介绍","四、查看缓存日志"]},"516":{"title":"其他缓存日志","titles":["介绍","四、查看缓存日志"]},"517":{"title":"对外接口","titles":["介绍"]},"518":{"title":"public string WX.PluginCachePath","titles":["介绍","对外接口"]},"519":{"title":"public string WX.GetCachePath(string url)","titles":["介绍","对外接口"]},"520":{"title":"public void CleanAllFileCache(Action<bool> action)","titles":["介绍","对外接口"]},"521":{"title":"public void CleanFileCache(int fileSize, Action<ReleaseResult> action)","titles":["介绍","对外接口"]},"522":{"title":"public void RemoveFile(string path, Action<bool> action)","titles":["介绍","对外接口"]},"523":{"title":"五、注意项","titles":["介绍"]},"524":{"title":"QA","titles":["介绍"]},"525":{"title":"1. PC上配置为不自动缓存的文件,仍然没有走网络下载","titles":["介绍","QA"]},"526":{"title":"2. 同一个文件,日志提示执行缓存逻辑,下次运行时仍然从网络下载","titles":["介绍","QA"]},"527":{"title":"3. 已经有无缓存,执行缓存逻辑的日志,缓存仍不生效,下次访问资源仍从网络下载","titles":["介绍","QA"]},"528":{"title":"4. 如何切换备用CDN地址","titles":["介绍","QA"]},"529":{"title":"5. 一些配置文件不希望被自动清理,由业务控制何时清理","titles":["介绍","QA"]},"530":{"title":"首场景启动优化","titles":[]},"531":{"title":"小游戏Profile","titles":["首场景启动优化"]},"532":{"title":"Unity CallMain","titles":["首场景启动优化"]},"533":{"title":"CallMain Profile分析","titles":["首场景启动优化"]},"534":{"title":"Unity 游戏接入微信小游戏指南","titles":[]},"535":{"title":"【阶段一】兼容性评估","titles":["Unity 游戏接入微信小游戏指南"]},"536":{"title":"【阶段二】项目转换","titles":["Unity 游戏接入微信小游戏指南"]},"537":{"title":"快速开始——转换工具导出微信小游戏","titles":["Unity 游戏接入微信小游戏指南","【阶段二】项目转换"]},"538":{"title":"资源按需加载","titles":["Unity 游戏接入微信小游戏指南","【阶段二】项目转换"]},"539":{"title":"后端/网络通信适配","titles":["Unity 游戏接入微信小游戏指南","【阶段二】项目转换"]},"540":{"title":"资源服务器部署配置","titles":["Unity 游戏接入微信小游戏指南","【阶段二】项目转换"]},"541":{"title":"开发阶段的错误排查","titles":["Unity 游戏接入微信小游戏指南","【阶段二】项目转换"]},"542":{"title":"【阶段三】微信平台能力接入","titles":["Unity 游戏接入微信小游戏指南"]},"543":{"title":"接入微信API","titles":["Unity 游戏接入微信小游戏指南","【阶段三】微信平台能力接入"]},"544":{"title":"启动留存数据上报统计","titles":["Unity 游戏接入微信小游戏指南","【阶段三】微信平台能力接入"]},"545":{"title":"【阶段四】体验调优","titles":["Unity 游戏接入微信小游戏指南"]},"546":{"title":"首场景启动优化——首帧逻辑优化","titles":["Unity 游戏接入微信小游戏指南","【阶段四】体验调优"]},"547":{"title":"资源预下载","titles":["Unity 游戏接入微信小游戏指南","【阶段四】体验调优"]},"548":{"title":"运行性能及调优","titles":["Unity 游戏接入微信小游戏指南","【阶段四】体验调优"]},"549":{"title":"压缩纹理资源","titles":["Unity 游戏接入微信小游戏指南","【阶段四】体验调优"]},"550":{"title":"WASM代码分包","titles":["Unity 游戏接入微信小游戏指南","【阶段四】体验调优"]},"551":{"title":"封面图配置","titles":["Unity 游戏接入微信小游戏指南","【阶段四】体验调优"]},"552":{"title":"【阶段五】发布上线与现网监控","titles":["Unity 游戏接入微信小游戏指南"]},"553":{"title":"输入法适配","titles":[]},"554":{"title":"支持2022和团结引擎的 Input Field 组件自动适配,低版本或者其他组件暂不支持自动适配","titles":["输入法适配"]},"555":{"title":"低版本兼容:","titles":["输入法适配"]},"556":{"title":"使用 AutoStreaming 进行资源按需加载","titles":[]},"557":{"title":"方案选择建议","titles":["使用 AutoStreaming 进行资源按需加载"]},"558":{"title":"实践指南","titles":["使用 AutoStreaming 进行资源按需加载"]},"559":{"title":"Q&A","titles":["使用 AutoStreaming 进行资源按需加载"]},"560":{"title":"1.游戏在微信开发者工具中运行缺失资源?","titles":["使用 AutoStreaming 进行资源按需加载","Q&A"]},"561":{"title":"问题反馈与联系我们","titles":[]},"562":{"title":"Git Issue","titles":["问题反馈与联系我们"]},"563":{"title":"小游戏客服助手","titles":["问题反馈与联系我们"]},"564":{"title":"现网错误日志上报与排查","titles":[]},"565":{"title":"用户反馈日志","titles":["现网错误日志上报与排查"]},"566":{"title":"小游戏实时日志","titles":["现网错误日志上报与排查"]},"567":{"title":"JS Error错误日志","titles":["现网错误日志上报与排查"]},"568":{"title":"启动剧情(Beta)","titles":[]},"569":{"title":"剧情效果","titles":["启动剧情(Beta)"]},"570":{"title":"演示视频及演示工程源码","titles":["启动剧情(Beta)","剧情效果"]},"571":{"title":"优秀作品","titles":["启动剧情(Beta)","剧情效果"]},"572":{"title":"能力特性","titles":["启动剧情(Beta)"]},"573":{"title":"推荐内容","titles":["启动剧情(Beta)"]},"574":{"title":"接入方式","titles":["启动剧情(Beta)"]},"575":{"title":"步骤一:设计剧情","titles":["启动剧情(Beta)","接入方式"]},"576":{"title":"步骤二:配置启动剧情","titles":["启动剧情(Beta)","接入方式"]},"577":{"title":"基于异步干预剧情发展","titles":["启动剧情(Beta)","接入方式"]},"578":{"title":"自定义上报分析","titles":["启动剧情(Beta)","接入方式"]},"579":{"title":"外显进度条接入","titles":["启动剧情(Beta)","接入方式"]},"580":{"title":"关闭/样式调整","titles":["启动剧情(Beta)","接入方式","外显进度条接入"]},"581":{"title":"弱网处理","titles":["启动剧情(Beta)","接入方式"]},"582":{"title":"API执行环境说明","titles":["启动剧情(Beta)"]},"583":{"title":"API(JavaScript侧)","titles":["启动剧情(Beta)"]},"584":{"title":".running","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"585":{"title":".config","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"586":{"title":".end()","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"587":{"title":".onEnd(callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"588":{"title":".offEnd(callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"589":{"title":".onErr(callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"590":{"title":".offErr(callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"591":{"title":".onWeakNetwork(callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"592":{"title":".offWeakNetwork(callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"593":{"title":".setGlobalVar(globalName: string, value: string)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"594":{"title":".getGlobalVar(globalName: string): string | null","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"595":{"title":".onGlobalVarChange(globalName: string, callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"596":{"title":".offGlobalVarChange(globalName: string, callback: Function)","titles":["启动剧情(Beta)","API(JavaScript侧)"]},"597":{"title":"API(C#侧)","titles":["启动剧情(Beta)"]},"598":{"title":"获得交互句柄","titles":["启动剧情(Beta)","API(C#侧)"]},"599":{"title":"void SetPercentage(double value)","titles":["启动剧情(Beta)","API(C#侧)"]},"600":{"title":"bool GetRunning()","titles":["启动剧情(Beta)","API(C#侧)"]},"601":{"title":"void End()","titles":["启动剧情(Beta)","API(C#侧)"]},"602":{"title":"void onEnd(Action<bool> callback)","titles":["启动剧情(Beta)","API(C#侧)"]},"603":{"title":"void offEnd(Action<bool> callback)","titles":["启动剧情(Beta)","API(C#侧)"]},"604":{"title":"void SetGlobalVar(string key, string value)","titles":["启动剧情(Beta)","API(C#侧)"]},"605":{"title":"string GetGlobalVar(string key)","titles":["启动剧情(Beta)","API(C#侧)"]},"606":{"title":"启动剧情剧本自助设计工具及文档","titles":[]},"607":{"title":"1.文档说明","titles":["启动剧情剧本自助设计工具及文档"]},"608":{"title":"2.准备工作","titles":["启动剧情剧本自助设计工具及文档"]},"609":{"title":"3.快速入门","titles":["启动剧情剧本自助设计工具及文档"]},"610":{"title":"Step1 安装启动剧情Cli工具","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"611":{"title":"Step2 创建剧情工程","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"612":{"title":"Step3 启动开发模式","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"613":{"title":"Step4 预览默认剧情","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"614":{"title":"Step5 对剧本修改","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"615":{"title":"Step6 导出剧本","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"616":{"title":"Step7 尝试更多的模板","titles":["启动剧情剧本自助设计工具及文档","3.快速入门"]},"617":{"title":"4.进阶指南","titles":["启动剧情剧本自助设计工具及文档"]},"618":{"title":"4.1 了解构建工具","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南"]},"619":{"title":"4.2 基本概念","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南"]},"620":{"title":"4.2.1 关键动作帧","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南","4.2 基本概念"]},"621":{"title":"4.2.1.1 属性","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南","4.2 基本概念","4.2.1 关键动作帧"]},"622":{"title":"4.2.1.2 事件","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南","4.2 基本概念","4.2.1 关键动作帧"]},"623":{"title":"4.2.2 故事线","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南","4.2 基本概念"]},"624":{"title":"4.2.2.1 创建及添加关键动作帧","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南","4.2 基本概念","4.2.2 故事线"]},"625":{"title":"4.2.2.2 主故事线","titles":["启动剧情剧本自助设计工具及文档","4.进阶指南","4.2 基本概念","4.2.2 故事线"]},"626":{"title":"5.API速查","titles":["启动剧情剧本自助设计工具及文档"]},"627":{"title":"FrameType速查表","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"628":{"title":"类型约定","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"629":{"title":"空间描述约定","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"630":{"title":"视频相关","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"631":{"title":"FrameType.createVideo","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关"]},"632":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.createVideo"]},"633":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.createVideo"]},"634":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.createVideo"]},"635":{"title":"seek 的使用案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.createVideo","案例"]},"636":{"title":"FrameType.pauseVideo","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关"]},"637":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.pauseVideo"]},"638":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.pauseVideo"]},"639":{"title":"FrameType.playVideo","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关"]},"640":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.playVideo"]},"641":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","视频相关","FrameType.playVideo"]},"642":{"title":"音频相关","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"643":{"title":"FrameType.createAudio","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关"]},"644":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.createAudio"]},"645":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.createAudio"]},"646":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.createAudio"]},"647":{"title":"FrameType.pauseAudio","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关"]},"648":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.pauseAudio"]},"649":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.pauseAudio"]},"650":{"title":"FrameType.playAudio","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关"]},"651":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.playAudio"]},"652":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","音频相关","FrameType.playAudio"]},"653":{"title":"贴图相关","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"654":{"title":"FrameType.createImage","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关"]},"655":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关","FrameType.createImage"]},"656":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关","FrameType.createImage"]},"657":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关","FrameType.createImage"]},"658":{"title":"FrameType.createRect","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关"]},"659":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关","FrameType.createRect"]},"660":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关","FrameType.createRect"]},"661":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","贴图相关","FrameType.createRect"]},"662":{"title":"属性修改","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"663":{"title":"FrameType.setParam","titles":["启动剧情剧本自助设计工具及文档","5.API速查","属性修改"]},"664":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","属性修改","FrameType.setParam"]},"665":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","属性修改","FrameType.setParam"]},"666":{"title":"FrameType.setParamSizeAndPosition","titles":["启动剧情剧本自助设计工具及文档","5.API速查","属性修改"]},"667":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","属性修改","FrameType.setParamSizeAndPosition"]},"668":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","属性修改","FrameType.setParamSizeAndPosition"]},"669":{"title":"延迟执行","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"670":{"title":"FrameType.setTimeout","titles":["启动剧情剧本自助设计工具及文档","5.API速查","延迟执行"]},"671":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","延迟执行","FrameType.setTimeout"]},"672":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","延迟执行","FrameType.setTimeout"]},"673":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","延迟执行","FrameType.setTimeout"]},"674":{"title":"动画相关","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"675":{"title":"FrameType.createAnimationFunction","titles":["启动剧情剧本自助设计工具及文档","5.API速查","动画相关"]},"676":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","动画相关","FrameType.createAnimationFunction"]},"677":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","动画相关","FrameType.createAnimationFunction"]},"678":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","动画相关","FrameType.createAnimationFunction"]},"679":{"title":"全局变量","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"680":{"title":"FrameType.var","titles":["启动剧情剧本自助设计工具及文档","5.API速查","全局变量"]},"681":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","全局变量","FrameType.var"]},"682":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","全局变量","FrameType.var"]},"683":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","全局变量","FrameType.var"]},"684":{"title":"条件判断","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"685":{"title":"FrameType.if","titles":["启动剧情剧本自助设计工具及文档","5.API速查","条件判断"]},"686":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","条件判断","FrameType.if"]},"687":{"title":"事件","titles":["启动剧情剧本自助设计工具及文档","5.API速查","条件判断","FrameType.if"]},"688":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","条件判断","FrameType.if"]},"689":{"title":"上报","titles":["启动剧情剧本自助设计工具及文档","5.API速查"]},"690":{"title":"FrameType.Report","titles":["启动剧情剧本自助设计工具及文档","5.API速查","上报"]},"691":{"title":"属性","titles":["启动剧情剧本自助设计工具及文档","5.API速查","上报","FrameType.Report"]},"692":{"title":"案例","titles":["启动剧情剧本自助设计工具及文档","5.API速查","上报","FrameType.Report"]},"693":{"title":"6.常见Q&A","titles":["启动剧情剧本自助设计工具及文档"]},"694":{"title":"6.1 图片资源可以使用网络图片吗?","titles":["启动剧情剧本自助设计工具及文档","6.常见Q&A","上报"]},"695":{"title":"6.2 为什么要放首帧图片(firstFramePic)","titles":["启动剧情剧本自助设计工具及文档","6.常见Q&A","上报"]},"696":{"title":"Unity中如何展示排行榜这类微信关系数据","titles":[]},"697":{"title":"背景和原理介绍","titles":["Unity中如何展示排行榜这类微信关系数据"]},"698":{"title":"详细步骤","titles":["Unity中如何展示排行榜这类微信关系数据"]},"699":{"title":"1、设置占位纹理","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤"]},"700":{"title":"2、调用SDK的API","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤"]},"701":{"title":"2.1 在需要展示的地方调用,WX.ShowOpenData","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤","2、调用SDK的API"]},"702":{"title":"2.2 需要关闭时则调用,WX.HideOpenData","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤","2、调用SDK的API"]},"703":{"title":"2.3 通过 PostMessage 向开放数据域传递消息","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤","2、调用SDK的API"]},"704":{"title":"3、导出选项勾选使用好友关系链","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤"]},"705":{"title":"4、用JS开发排行榜这类微信关系逻辑","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤"]},"706":{"title":"5、示例DEMO","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤"]},"707":{"title":"5.1 好友排行榜","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤","5、示例DEMO"]},"708":{"title":"5.2 群好友排行榜","titles":["Unity中如何展示排行榜这类微信关系数据","详细步骤","5、示例DEMO"]},"709":{"title":"常见问题QA","titles":["Unity中如何展示排行榜这类微信关系数据"]},"710":{"title":"优化Unity WebGL的内存","titles":[]},"711":{"title":"一、内存与OOM","titles":["优化Unity WebGL的内存"]},"712":{"title":"二、Unity WebGL适配小游戏的内存结构","titles":["优化Unity WebGL的内存"]},"713":{"title":"三、内存查看工具","titles":["优化Unity WebGL的内存"]},"714":{"title":"3.1 进程总内存","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"715":{"title":"Instruments in Xcode(iOS)","titles":["优化Unity WebGL的内存","三、内存查看工具","3.1 进程总内存"]},"716":{"title":"Perfdog(Android or iOS)","titles":["优化Unity WebGL的内存","三、内存查看工具","3.1 进程总内存"]},"717":{"title":"3.2 UnityHeap","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"718":{"title":"3.3 ProfilingMemory","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"719":{"title":"3.4 Unity Profiler","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"720":{"title":"3.5 JavaScript Heap","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"721":{"title":"微信开发者工具","titles":["优化Unity WebGL的内存","三、内存查看工具","3.5 JavaScript Heap"]},"722":{"title":"FireFox Memory(PC)","titles":["优化Unity WebGL的内存","三、内存查看工具","3.5 JavaScript Heap"]},"723":{"title":"iOS Safari Timeline(PC or iOS)","titles":["优化Unity WebGL的内存","三、内存查看工具","3.5 JavaScript Heap"]},"724":{"title":"四、内存优化方案","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"725":{"title":"4.1 WASM代码编译内存","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"726":{"title":"4.2 GPU内存","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"727":{"title":"4.3 UnityHeap","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"728":{"title":"4.4 首资源包与AssetBundle内存","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"729":{"title":"4.5 音频内存","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"730":{"title":"4.6 其他常见优化手段","titles":["优化Unity WebGL的内存","三、内存查看工具"]},"731":{"title":"五、QA","titles":["优化Unity WebGL的内存"]},"732":{"title":"优化Unity WebGL的运行性能","titles":[]},"733":{"title":"一、运行性能概述","titles":["优化Unity WebGL的运行性能"]},"734":{"title":"Unity WebGL VS APP的运行性能差异","titles":["优化Unity WebGL的运行性能","一、运行性能概述"]},"735":{"title":"WASM VS JS的运行差异","titles":["优化Unity WebGL的运行性能","一、运行性能概述"]},"736":{"title":"系统平台之间的性能差异","titles":["优化Unity WebGL的运行性能","一、运行性能概述"]},"737":{"title":"二、优化目标","titles":["优化Unity WebGL的运行性能"]},"738":{"title":"三、常用优化工具","titles":["优化Unity WebGL的运行性能"]},"739":{"title":"3.1 小游戏Android CPU Profiler(推荐)","titles":["优化Unity WebGL的运行性能","三、常用优化工具"]},"740":{"title":"3.2 Unity Profiler","titles":["优化Unity WebGL的运行性能","三、常用优化工具"]},"741":{"title":"3.3 小游戏云测","titles":["优化Unity WebGL的运行性能","三、常用优化工具"]},"742":{"title":"三、常见优化手段","titles":["优化Unity WebGL的运行性能"]},"743":{"title":"1. 配置加载与协议解析","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"744":{"title":"2. LUA性能","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"745":{"title":"3. 物理性能","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"746":{"title":"4. 实例化","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"747":{"title":"5. 限制帧率","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"748":{"title":"6. 限制分辨率","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"749":{"title":"7. 使用压缩纹理","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"750":{"title":"8. WebGL2.0说明","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"751":{"title":"9. 减少Drawcall","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"752":{"title":"10. 使用SRP Batcher","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"753":{"title":"11. 如何获取设备硬件信息","titles":["优化Unity WebGL的运行性能","三、常见优化手段"]},"754":{"title":"Unity WebGL小游戏适配方案性能标准","titles":[]},"755":{"title":"为什么需要性能评测标准?","titles":["Unity WebGL小游戏适配方案性能标准"]},"756":{"title":"评测标准细则","titles":["Unity WebGL小游戏适配方案性能标准"]},"757":{"title":"性能基线","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"758":{"title":"游戏类型说明","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"759":{"title":"指标与测量方法","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"760":{"title":"开发者需要关注哪些性能指标","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","指标与测量方法"]},"761":{"title":"代码与资源体积","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"762":{"title":"评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"763":{"title":"iOS性能评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测标准"]},"764":{"title":"Android性能评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测标准"]},"765":{"title":"评测工具","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"766":{"title":"现网阶段","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具"]},"767":{"title":"性能报告","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具","现网阶段"]},"768":{"title":"性能数据","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具","现网阶段"]},"769":{"title":"开发阶段","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具"]},"770":{"title":"小游戏云测试","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具","开发阶段"]},"771":{"title":"性能诊断工具","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具","开发阶段"]},"772":{"title":"Perfdog","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具","开发阶段"]},"773":{"title":"历史评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"774":{"title":"性能优化总览","titles":[]},"775":{"title":"一、为何需要进行性能优化?","titles":["性能优化总览"]},"776":{"title":"二、优化目标","titles":["性能优化总览"]},"777":{"title":"三、最佳实践","titles":["性能优化总览"]},"778":{"title":"3.1 加快游戏启动速度","titles":["性能优化总览","三、最佳实践"]},"779":{"title":"3.2 资源按需加载","titles":["性能优化总览","三、最佳实践"]},"780":{"title":"3.3 资源处理建议","titles":["性能优化总览","三、最佳实践"]},"781":{"title":"3.4 降低小游戏内存使用","titles":["性能优化总览","三、最佳实践"]},"782":{"title":"3.5 降低CPU消耗","titles":["性能优化总览","三、最佳实践"]},"783":{"title":"最佳实践检测工具","titles":[]},"784":{"title":"作用","titles":["最佳实践检测工具"]},"785":{"title":"如何使用","titles":["最佳实践检测工具"]},"786":{"title":"检测示意","titles":["最佳实践检测工具"]},"787":{"title":"检测指标解释","titles":["最佳实践检测工具"]},"788":{"title":"启动检测","titles":["最佳实践检测工具","检测指标解释"]},"789":{"title":"监控指标","titles":["最佳实践检测工具","检测指标解释","启动检测"]},"790":{"title":"优化建议概览","titles":["最佳实践检测工具","检测指标解释","启动检测"]},"791":{"title":"预下载检测","titles":["最佳实践检测工具","检测指标解释"]},"792":{"title":"监控指标","titles":["最佳实践检测工具","检测指标解释","预下载检测"]},"793":{"title":"优化建议概览","titles":["最佳实践检测工具","检测指标解释","预下载检测"]},"794":{"title":"wasm分包检测","titles":["最佳实践检测工具","检测指标解释"]},"795":{"title":"监控指标","titles":["最佳实践检测工具","检测指标解释","wasm分包检测"]},"796":{"title":"优化建议概览","titles":["最佳实践检测工具","检测指标解释","wasm分包检测"]},"797":{"title":"网络信息检测","titles":["最佳实践检测工具","检测指标解释"]},"798":{"title":"监控指标","titles":["最佳实践检测工具","检测指标解释","网络信息检测"]},"799":{"title":"优化建议概览","titles":["最佳实践检测工具","检测指标解释","网络信息检测"]},"800":{"title":"帧率检测","titles":["最佳实践检测工具","检测指标解释"]},"801":{"title":"监控指标","titles":["最佳实践检测工具","检测指标解释","帧率检测"]},"802":{"title":"优化建议概览","titles":["最佳实践检测工具","检测指标解释","帧率检测"]},"803":{"title":"优化分析工具","titles":["最佳实践检测工具"]},"804":{"title":"微信开发者工具","titles":["最佳实践检测工具","优化分析工具"]},"805":{"title":"使用Unity Profiler性能调优","titles":[]},"806":{"title":"RenderOptimization","titles":[]},"807":{"title":"WebGL1.0 还是 WebGL2.0","titles":["RenderOptimization"]},"808":{"title":"选择哪种渲染管线","titles":["RenderOptimization"]},"809":{"title":"线性颜色空间 还是 Gamma 颜色空间","titles":["RenderOptimization"]},"810":{"title":"渲染性能优化的一些建议","titles":["RenderOptimization"]},"811":{"title":"光照和阴影","titles":["RenderOptimization","渲染性能优化的一些建议"]},"812":{"title":"材质和Shader","titles":["RenderOptimization","渲染性能优化的一些建议"]},"813":{"title":"纹理设置","titles":["RenderOptimization","渲染性能优化的一些建议"]},"814":{"title":"网格和蒙皮","titles":["RenderOptimization","渲染性能优化的一些建议"]},"815":{"title":"DrawCall 相关","titles":["RenderOptimization","渲染性能优化的一些建议"]},"816":{"title":"摄像机 Camera","titles":["RenderOptimization","渲染性能优化的一些建议"]},"817":{"title":"渲染分辨率","titles":["RenderOptimization","渲染性能优化的一些建议"]},"818":{"title":"后处理","titles":["RenderOptimization","渲染性能优化的一些建议"]},"819":{"title":"特效","titles":["RenderOptimization","渲染性能优化的一些建议"]},"820":{"title":"参考文档","titles":["RenderOptimization"]},"821":{"title":"启动留存数据上报统计","titles":[]},"822":{"title":"一、概述","titles":["启动留存数据上报统计"]},"823":{"title":"二、上报广告信息","titles":["启动留存数据上报统计"]},"824":{"title":"如何上报?","titles":["启动留存数据上报统计","二、上报广告信息"]},"825":{"title":"三、上报自定义阶段","titles":["启动留存数据上报统计"]},"826":{"title":"四、获取Loader启动阶段","titles":["启动留存数据上报统计"]},"827":{"title":"五、获取数据统计","titles":["启动留存数据上报统计"]},"828":{"title":"资源按需加载概述","titles":[]},"829":{"title":"AA包、AB包、Instant Game 方案选择说明","titles":["资源按需加载概述"]},"830":{"title":"各类型游戏的资源优化建议","titles":["资源按需加载概述"]},"831":{"title":"原生 APP 手游已使用 AB/AA 包等资源按需加载的游戏**","titles":["资源按需加载概述","各类型游戏的资源优化建议"]},"832":{"title":"原生 APP 手游未使用 资源按需加载 的轻度游戏","titles":["资源按需加载概述","各类型游戏的资源优化建议"]},"833":{"title":"原生 APP 手游未使用 资源按需加载 的中重度游戏","titles":["资源按需加载概述","各类型游戏的资源优化建议"]},"834":{"title":"微信SDK安装","titles":[]},"835":{"title":"方法一(推荐):Package 方式安装","titles":["微信SDK安装"]},"836":{"title":"安装指南","titles":["微信SDK安装","方法一(推荐):Package 方式安装"]},"837":{"title":"方法二:资源包方式安装","titles":["微信SDK安装"]},"838":{"title":"安装指南","titles":["微信SDK安装","方法二:资源包方式安装"]},"839":{"title":"目录结构说明","titles":["微信SDK安装"]},"840":{"title":"常见问题","titles":["微信SDK安装"]},"841":{"title":"1.游戏工程可以导出但在微信开发者工具运行提示报错:","titles":["微信SDK安装","常见问题","安装指南"]},"842":{"title":"技术沙龙","titles":[]},"843":{"title":"微信小游戏技术沙龙分享材料2023","titles":["技术沙龙"]},"844":{"title":"转换案例","titles":[]},"845":{"title":"无尽冬日","titles":["转换案例"]},"846":{"title":"九梦仙域","titles":["转换案例"]},"847":{"title":"地铁跑酷","titles":["转换案例"]},"848":{"title":"谜题大陆","titles":["转换案例"]},"849":{"title":"三国吧兄弟","titles":["转换案例"]},"850":{"title":"鱼吃鱼","titles":["转换案例"]},"851":{"title":"剑心吟","titles":["转换案例"]},"852":{"title":"巨兽战场","titles":["转换案例"]},"853":{"title":"小小蚁国","titles":["转换案例"]},"854":{"title":"翡翠大师","titles":["转换案例"]},"855":{"title":"超能世界","titles":["转换案例"]},"856":{"title":"大侠不哭","titles":["转换案例"]},"857":{"title":"我叫MT2","titles":["转换案例"]},"858":{"title":"葫芦娃大作战","titles":["转换案例"]},"859":{"title":"大圣顶住","titles":["转换案例"]},"860":{"title":"银河战舰","titles":["转换案例"]},"861":{"title":"守护球球","titles":["转换案例"]},"862":{"title":"小游戏启动流程与时序","titles":[]},"863":{"title":"启动加载时序","titles":["小游戏启动流程与时序"]},"864":{"title":"Unity Loader工作流程","titles":["小游戏启动流程与时序"]},"865":{"title":"QA:","titles":["小游戏启动流程与时序"]},"866":{"title":"提升Unity WebGL游戏启动速度","titles":[]},"867":{"title":"一、 为什么要做启动优化","titles":["提升Unity WebGL游戏启动速度"]},"868":{"title":"1.1 小游戏与手游APP的启动差异","titles":["提升Unity WebGL游戏启动速度","一、 为什么要做启动优化"]},"869":{"title":"1.2 优化的目标与标准","titles":["提升Unity WebGL游戏启动速度","一、 为什么要做启动优化"]},"870":{"title":"二、分析小游戏启动速度","titles":["提升Unity WebGL游戏启动速度"]},"871":{"title":"2.1. 查看启动耗时","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"872":{"title":"2.2 分阶段耗时","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"873":{"title":"2.2.1 首资源包下载与体积","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"874":{"title":"2.2.2 WASM代码下载和编译","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"875":{"title":"2.2.3 引擎初始化与开发者首帧逻辑","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"876":{"title":"2.2.4 游戏内资源按需加载","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"877":{"title":"2.3 优化总览","titles":["提升Unity WebGL游戏启动速度","二、分析小游戏启动速度"]},"878":{"title":"三、常用启动优化技巧","titles":["提升Unity WebGL游戏启动速度"]},"879":{"title":"四、常用启动优化工具","titles":["提升Unity WebGL游戏启动速度"]},"880":{"title":"4.1. AssetStudio(推荐)","titles":["提升Unity WebGL游戏启动速度","四、常用启动优化工具"]},"881":{"title":"4.2 BuildReportTool(推荐)","titles":["提升Unity WebGL游戏启动速度","四、常用启动优化工具"]},"882":{"title":"4.3 Asset Hunter","titles":["提升Unity WebGL游戏启动速度","四、常用启动优化工具"]},"883":{"title":"4.4 Unity Addressable Assets System","titles":["提升Unity WebGL游戏启动速度","四、常用启动优化工具"]},"884":{"title":"Unity WebGL小游戏适配方案概述","titles":[]},"885":{"title":"一、技术原理","titles":["Unity WebGL小游戏适配方案概述"]},"886":{"title":"二、接入流程","titles":["Unity WebGL小游戏适配方案概述"]},"887":{"title":"三、参考资料","titles":["Unity WebGL小游戏适配方案概述"]},"888":{"title":"Symbol 相关","titles":[]},"889":{"title":"Tool","titles":["Symbol 相关"]},"890":{"title":"转换工具导出微信小游戏","titles":[]},"891":{"title":"一、Unity导出WebGL","titles":["转换工具导出微信小游戏"]},"892":{"title":"二、适配小游戏","titles":["转换工具导出微信小游戏"]},"893":{"title":"2.1 转换小游戏","titles":["转换工具导出微信小游戏","二、适配小游戏"]},"894":{"title":"2.2 了解转换后目录结构","titles":["转换工具导出微信小游戏","二、适配小游戏"]},"895":{"title":"2.3 资源部署","titles":["转换工具导出微信小游戏","二、适配小游戏"]},"896":{"title":"2.4 小游戏预览","titles":["转换工具导出微信小游戏","二、适配小游戏"]},"897":{"title":"三、使用脚本集成到自己的构建系统","titles":["转换工具导出微信小游戏"]},"898":{"title":"MiniGameConfig.asset支持的配置","titles":["转换工具导出微信小游戏","三、使用脚本集成到自己的构建系统"]},"899":{"title":"与转换面板配置有对应关系的配置项","titles":["转换工具导出微信小游戏","三、使用脚本集成到自己的构建系统","MiniGameConfig.asset支持的配置"]},"900":{"title":"不常用配置","titles":["转换工具导出微信小游戏","三、使用脚本集成到自己的构建系统","MiniGameConfig.asset支持的配置"]},"901":{"title":"四、常见问题","titles":["转换工具导出微信小游戏"]},"902":{"title":"使用Unity Profiler性能调优","titles":[]},"903":{"title":"推荐引擎版本","titles":[]},"904":{"title":"版本兼容性","titles":["推荐引擎版本"]},"905":{"title":"推荐版本","titles":["推荐引擎版本"]},"906":{"title":"Unity InstantGame/团结引擎获取","titles":["推荐引擎版本"]},"907":{"title":"QA","titles":["推荐引擎版本"]},"908":{"title":"版本更新","titles":[]},"909":{"title":"代码更新","titles":["版本更新"]},"910":{"title":"更新策略:","titles":["版本更新"]},"911":{"title":"1. 静默更新(默认方式)","titles":["版本更新","更新策略:"]},"912":{"title":"2. 强制更新","titles":["版本更新","更新策略:"]},"913":{"title":"2.1 实时检测更新(UpdateManager)","titles":["版本更新","更新策略:","2. 强制更新"]},"914":{"title":"2.2 设置最低可用版本","titles":["版本更新","更新策略:","2. 强制更新"]},"915":{"title":"资源更新","titles":["版本更新"]},"916":{"title":"使用Addressable Assets System进行资源按需加载","titles":[]},"917":{"title":"一、概述","titles":["使用Addressable Assets System进行资源按需加载"]},"918":{"title":"二、Addressable在小游戏中的应用","titles":["使用Addressable Assets System进行资源按需加载"]},"919":{"title":"2.1 什么是Addressable Assets System","titles":["使用Addressable Assets System进行资源按需加载","二、Addressable在小游戏中的应用"]},"920":{"title":"2.2 相对于AssetsBundles的优势","titles":["使用Addressable Assets System进行资源按需加载","二、Addressable在小游戏中的应用"]},"921":{"title":"2.3 在小游戏中使用Addressable Assets System","titles":["使用Addressable Assets System进行资源按需加载","二、Addressable在小游戏中的应用"]},"922":{"title":"2.4 使用WXAssetBundleProvider节省内存","titles":["使用Addressable Assets System进行资源按需加载","二、Addressable在小游戏中的应用"]},"923":{"title":"三、启动优化与资源优化实战","titles":["使用Addressable Assets System进行资源按需加载"]},"924":{"title":"3.1 从首包开始","titles":["使用Addressable Assets System进行资源按需加载","三、启动优化与资源优化实战"]},"925":{"title":"3.2 资源按需加载","titles":["使用Addressable Assets System进行资源按需加载","三、启动优化与资源优化实战"]},"926":{"title":"3.2.1 场景动态加载","titles":["使用Addressable Assets System进行资源按需加载","三、启动优化与资源优化实战","3.2 资源按需加载"]},"927":{"title":"3.2.2 物件动态加载","titles":["使用Addressable Assets System进行资源按需加载","三、启动优化与资源优化实战"]},"928":{"title":"3.3 小结","titles":["使用Addressable Assets System进行资源按需加载","三、启动优化与资源优化实战"]},"929":{"title":"四、如何优雅地异步加载","titles":["使用Addressable Assets System进行资源按需加载"]},"930":{"title":"4.1 最基本的异步回调","titles":["使用Addressable Assets System进行资源按需加载","四、如何优雅地异步加载"]},"931":{"title":"4.2 使用协程","titles":["使用Addressable Assets System进行资源按需加载","四、如何优雅地异步加载"]},"932":{"title":"4.3 使用await","titles":["使用Addressable Assets System进行资源按需加载","四、如何优雅地异步加载"]},"933":{"title":"五、旧系统资源改造","titles":["使用Addressable Assets System进行资源按需加载"]},"934":{"title":"5.1 Resource改造","titles":["使用Addressable Assets System进行资源按需加载"]},"935":{"title":"5.2 AssetsBundle迁移","titles":["使用Addressable Assets System进行资源按需加载"]},"936":{"title":"六、部署","titles":["使用Addressable Assets System进行资源按需加载"]},"937":{"title":"6.1 Addressable编译与部署","titles":["使用Addressable Assets System进行资源按需加载","六、部署"]},"938":{"title":"6.2 资源预下载","titles":["使用Addressable Assets System进行资源按需加载","六、部署"]},"939":{"title":"五、参考资料","titles":["使用Addressable Assets System进行资源按需加载","六、部署"]},"940":{"title":"使用 AssetBundle 进行资源按需加载","titles":[]},"941":{"title":"一、AssetBundle使用","titles":["使用 AssetBundle 进行资源按需加载"]},"942":{"title":"1.1 AssetBundle打包参数建议","titles":["使用 AssetBundle 进行资源按需加载","一、AssetBundle使用"]},"943":{"title":"1.2 AssetBundle下载","titles":["使用 AssetBundle 进行资源按需加载","一、AssetBundle使用"]},"944":{"title":"二、小游戏与APP的AssetBundle缓存更新流程差异","titles":["使用 AssetBundle 进行资源按需加载"]},"945":{"title":"三、更节省内存的WXAssetBundle","titles":["使用 AssetBundle 进行资源按需加载"]},"946":{"title":"四、AssetBundle内存分析","titles":["使用 AssetBundle 进行资源按需加载"]},"947":{"title":"4.1 切勿使用带Cache能力的线管接口","titles":["使用 AssetBundle 进行资源按需加载","四、AssetBundle内存分析"]},"948":{"title":"4.2 尽可能使用Unload","titles":["使用 AssetBundle 进行资源按需加载","四、AssetBundle内存分析"]},"949":{"title":"四、参考资料","titles":["使用 AssetBundle 进行资源按需加载"]},"950":{"title":"使用Loader进行游游戏加载","titles":[]},"951":{"title":"一、什么是Unity Loader?","titles":["使用Loader进行游游戏加载"]},"952":{"title":"二、如何使用Unity Loader插件","titles":["使用Loader进行游游戏加载"]},"953":{"title":"三、配置Unity Loader功能","titles":["使用Loader进行游游戏加载"]},"954":{"title":"3.1 资源下载","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能"]},"955":{"title":"转换插件相关配置","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能","3.1 资源下载"]},"956":{"title":"通过接口修改","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能","3.1 资源下载"]},"957":{"title":"3.2 启动界面","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能"]},"958":{"title":"转换插件相关配置","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能","3.2 启动界面"]},"959":{"title":"game.js配置","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能","3.2 启动界面"]},"960":{"title":"3.3 首包资源加载方式","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能"]},"961":{"title":"转换插件相关配置","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能","3.3 首包资源加载方式"]},"962":{"title":"game.js配置","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能","3.3 首包资源加载方式"]},"963":{"title":"3.4 预加载资源","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能"]},"964":{"title":"3.5 资源缓存与淘汰策略","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能"]},"965":{"title":"3.6 插件调试日志","titles":["使用Loader进行游游戏加载","三、配置Unity Loader功能"]},"966":{"title":"使用ProfilingMemory内存分析","titles":[]},"967":{"title":"概述","titles":["使用ProfilingMemory内存分析"]},"968":{"title":"步骤","titles":["使用ProfilingMemory内存分析"]},"969":{"title":"数据分析","titles":["使用ProfilingMemory内存分析"]},"970":{"title":"浏览数据","titles":["使用ProfilingMemory内存分析","数据分析"]},"971":{"title":"SQL统计分析","titles":["使用ProfilingMemory内存分析","数据分析"]},"972":{"title":"常见问题","titles":["使用ProfilingMemory内存分析"]},"973":{"title":"1. 开启ProflingMemory后非常慢,特别是在有Lua逻辑的情况","titles":["使用ProfilingMemory内存分析","常见问题"]},"974":{"title":"2. ProfilingMemory在真机上更容易出现内存崩溃","titles":["使用ProfilingMemory内存分析","常见问题"]},"975":{"title":"网络通信适配","titles":[]},"976":{"title":"HTTP 通信","titles":["网络通信适配"]},"977":{"title":"使用方式","titles":["网络通信适配","HTTP 通信"]},"978":{"title":"TCP 网络通信","titles":["网络通信适配"]},"979":{"title":"TCPSocket","titles":["网络通信适配","TCP 网络通信"]},"980":{"title":"WebSocket","titles":["网络通信适配","TCP 网络通信"]},"981":{"title":"客户端","titles":["网络通信适配","TCP 网络通信","WebSocket"]},"982":{"title":"服务端","titles":["网络通信适配","TCP 网络通信","WebSocket"]},"983":{"title":"UDP 网络通信","titles":["网络通信适配"]},"984":{"title":"注意事项","titles":["网络通信适配"]},"985":{"title":"安全域名","titles":["网络通信适配","注意事项"]},"986":{"title":"SSL证书","titles":["网络通信适配","注意事项"]},"987":{"title":"使用预下载功能","titles":[]},"988":{"title":"概述","titles":["使用预下载功能"]},"989":{"title":"配置方式","titles":["使用预下载功能"]},"990":{"title":"导出预下载列表","titles":["使用预下载功能","配置方式"]},"991":{"title":"MiniGameConfig.asset相关配置","titles":["使用预下载功能","配置方式","导出预下载列表"]},"992":{"title":"手动配置","titles":["使用预下载功能","配置方式"]},"993":{"title":"运行时配置「推荐」","titles":["使用预下载功能","配置方式"]},"994":{"title":"在插件启动前修改","titles":["使用预下载功能","配置方式","运行时配置「推荐」"]},"995":{"title":"引擎初始化完成后修改","titles":["使用预下载功能","配置方式","运行时配置「推荐」"]},"996":{"title":"并发数","titles":["使用预下载功能"]},"997":{"title":"路径规范","titles":["使用预下载功能"]},"998":{"title":"如何验证","titles":["使用预下载功能"]},"999":{"title":"注意事项","titles":["使用预下载功能"]},"1000":{"title":"微信系统字体","titles":[]},"1001":{"title":"版本要求","titles":["微信系统字体"]},"1002":{"title":"代码示例","titles":["微信系统字体"]},"1003":{"title":"相关日志","titles":["微信系统字体"]},"1004":{"title":"系统字体字符集","titles":["微信系统字体"]},"1005":{"title":"SDK 调用微信 API","titles":[]},"1006":{"title":"基础库","titles":["SDK 调用微信 API"]},"1007":{"title":"在 Unity 中兼容低版本基础库","titles":["SDK 调用微信 API","基础库"]},"1008":{"title":"开发建议","titles":["SDK 调用微信 API"]},"1009":{"title":"Demo API 示例","titles":["SDK 调用微信 API","开发建议"]},"1010":{"title":"联调效率","titles":["SDK 调用微信 API","开发建议"]},"1011":{"title":"注意事项","titles":["SDK 调用微信 API"]},"1012":{"title":"代码分包","titles":[]},"1013":{"title":"概述","titles":["代码分包"]},"1014":{"title":"背景","titles":["代码分包","概述"]},"1015":{"title":"作用","titles":["代码分包","概述"]},"1016":{"title":"实现原理","titles":["代码分包"]},"1017":{"title":"插件安装","titles":["代码分包"]},"1018":{"title":"插件更新","titles":["代码分包"]},"1019":{"title":"插件使用","titles":["代码分包"]},"1020":{"title":"启用分包","titles":["代码分包","插件使用","作用"]},"1021":{"title":"输入版本描述","titles":["代码分包","插件使用","作用"]},"1022":{"title":"等待上传文件","titles":["代码分包","插件使用","作用"]},"1023":{"title":"等待预处理","titles":["代码分包","插件使用","作用"]},"1024":{"title":"选择是否增量分包","titles":["代码分包","插件使用","作用"]},"1025":{"title":"等待分包","titles":["代码分包","插件使用","作用"]},"1026":{"title":"android收集 + iOS收集","titles":["代码分包","插件使用","作用"]},"1027":{"title":"重复收集与生成","titles":["代码分包","插件使用","作用"]},"1028":{"title":"关闭分包","titles":["代码分包","插件使用"]},"1029":{"title":"注意事项","titles":["代码分包","插件使用"]},"1030":{"title":"FAQ","titles":["代码分包"]},"1031":{"title":"分包是否是必要的","titles":["代码分包","FAQ"]},"1032":{"title":"收集到什么时候可以结束","titles":["代码分包","FAQ"]},"1033":{"title":"游戏内容难以遍历完整怎么办","titles":["代码分包","FAQ"]},"1034":{"title":"分包总大小比原始包大","titles":["代码分包","FAQ"]},"1035":{"title":"新增收集的函数要重新再次提审才会在首包吗","titles":["代码分包","FAQ"]},"1036":{"title":"会不会最终跑到所有函数都收集的情况","titles":["代码分包","FAQ"]},"1037":{"title":"iOS 高性能模式收集很卡","titles":["代码分包","FAQ"]},"1038":{"title":"iOS 高性能模式代码分包后内存反而变得很高","titles":["代码分包","FAQ"]},"1039":{"title":"iOS 高性能模式出现 impport section's count is too big","titles":["代码分包","FAQ"]},"1040":{"title":"没有看到增量分包的界面","titles":["代码分包","FAQ"]},"1041":{"title":"增量分包没生效","titles":["代码分包","FAQ"]},"1042":{"title":"如何更新分包插件","titles":["代码分包","FAQ"]},"1043":{"title":"分包插件安装失败","titles":["代码分包","FAQ"]},"1044":{"title":"分包插件卡住","titles":["代码分包","FAQ"]},"1045":{"title":"内存优化版本未观察到内存优化","titles":["代码分包","FAQ"]},"1046":{"title":"如何查看分包插件日志","titles":["代码分包","FAQ"]},"1047":{"title":"Changelog","titles":["代码分包"]},"1048":{"title":"v1.1.13","titles":["代码分包","Changelog"]},"1049":{"title":"Fixed","titles":["代码分包","Changelog","v1.1.13"]},"1050":{"title":"v1.1.12","titles":["代码分包","Changelog"]},"1051":{"title":"Fixed","titles":["代码分包","Changelog","v1.1.12"]},"1052":{"title":"v1.1.11","titles":["代码分包","Changelog"]},"1053":{"title":"Fixed","titles":["代码分包","Changelog","v1.1.11"]},"1054":{"title":"v1.1.10","titles":["代码分包","Changelog"]},"1055":{"title":"Fixed","titles":["代码分包","Changelog","v1.1.10"]},"1056":{"title":"v1.1.9","titles":["代码分包","Changelog"]},"1057":{"title":"Feature","titles":["代码分包","Changelog","v1.1.9"]},"1058":{"title":"v1.1.8","titles":["代码分包","Changelog"]},"1059":{"title":"Changed","titles":["代码分包","Changelog","v1.1.8"]},"1060":{"title":"v1.1.6","titles":["代码分包","Changelog"]},"1061":{"title":"Changed","titles":["代码分包","Changelog","v1.1.6"]},"1062":{"title":"v1.1.5","titles":["代码分包","Changelog"]},"1063":{"title":"Fixed","titles":["代码分包","Changelog","v1.1.5"]},"1064":{"title":"v1.1.4","titles":["代码分包","Changelog"]},"1065":{"title":"Fixed","titles":["代码分包","Changelog","v1.1.4"]},"1066":{"title":"v1.1.2","titles":["代码分包","Changelog"]},"1067":{"title":"Changed","titles":["代码分包","Changelog","v1.1.2"]},"1068":{"title":"v1.1.0","titles":["代码分包","Changelog"]},"1069":{"title":"Added","titles":["代码分包","Changelog","v1.1.0"]},"1070":{"title":"v1.0.2","titles":["代码分包","Changelog"]},"1071":{"title":"Added","titles":["代码分包","Changelog","v1.0.2"]},"1072":{"title":"屏幕适配","titles":[]},"1073":{"title":"安全区域适配","titles":["屏幕适配"]},"1074":{"title":"高分辨屏下模糊问题","titles":["屏幕适配"]},"1075":{"title":"WebGL2.0渲染支持说明","titles":[]},"1076":{"title":"适合使用场景","titles":["WebGL2.0渲染支持说明"]},"1077":{"title":"用户占比","titles":["WebGL2.0渲染支持说明"]},"1078":{"title":"已知兼容问题","titles":["WebGL2.0渲染支持说明"]},"1079":{"title":"iOS高性能模式开启GPU Instance,模型闪烁/消失/不绘制等问题","titles":["WebGL2.0渲染支持说明","已知兼容问题"]},"1080":{"title":"iOS高性能模式DrawMeshInstanced显示错乱","titles":["WebGL2.0渲染支持说明","已知兼容问题"]},"1081":{"title":"参考文档","titles":["WebGL2.0渲染支持说明"]},"1082":{"title":"iOS 高性能与高性能+模式","titles":[]},"1083":{"title":"什么是高性能模式","titles":["iOS 高性能与高性能+模式"]},"1084":{"title":"什么是高性能+模式","titles":["iOS 高性能与高性能+模式"]},"1085":{"title":"性能提升","titles":["iOS 高性能与高性能+模式"]},"1086":{"title":"CPU 消耗","titles":["iOS 高性能与高性能+模式","性能提升"]},"1087":{"title":"压力测试","titles":["iOS 高性能与高性能+模式","性能提升"]},"1088":{"title":"如何开通","titles":["iOS 高性能与高性能+模式"]},"1089":{"title":"高性能模式限制","titles":["iOS 高性能与高性能+模式"]},"1090":{"title":"内存限制","titles":["iOS 高性能与高性能+模式","高性能模式限制"]},"1091":{"title":"代码体积限制","titles":["iOS 高性能与高性能+模式","高性能模式限制"]},"1092":{"title":"QA","titles":["iOS 高性能与高性能+模式"]},"1093":{"title":"1. 如何判别游戏否已经开启了高性能模式?","titles":["iOS 高性能与高性能+模式","QA"]},"1094":{"title":"2. 使用高性能模式下,游戏本身是否需要做修改?","titles":["iOS 高性能与高性能+模式","QA"]},"1095":{"title":"3. iOS 报错提示未开启 gzip/br 压缩","titles":["iOS 高性能与高性能+模式","QA"]},"1096":{"title":"4. 资源下载提示isTrusted","titles":["iOS 高性能与高性能+模式","QA"]},"1097":{"title":"5. 卡在启动封面无法启动","titles":["iOS 高性能与高性能+模式","QA"]},"1098":{"title":"6. 个别游戏 UI 会出现闪烁问题","titles":["iOS 高性能与高性能+模式","QA"]},"1099":{"title":"7. 为什么开启了高性能模式,游戏启动很烫?","titles":["iOS 高性能与高性能+模式","QA"]},"1100":{"title":"8. 使用高性能模式下,不优化内存、WASM 代码包体积就发布上线可以吗?","titles":["iOS 高性能与高性能+模式","QA"]},"1101":{"title":"9. iOS 高性能模式与安卓性能对比如何?","titles":["iOS 高性能与高性能+模式","QA"]},"1102":{"title":"Unity WebGL小游戏适配方案性能标准","titles":[]},"1103":{"title":"为什么需要性能评测标准?","titles":["Unity WebGL小游戏适配方案性能标准"]},"1104":{"title":"评测标准细则","titles":["Unity WebGL小游戏适配方案性能标准"]},"1105":{"title":"性能基线","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1106":{"title":"指标与测量方法","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1107":{"title":"代码与资源体积","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1108":{"title":"评测工具","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1109":{"title":"启动性能","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具"]},"1110":{"title":"运行性能","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测工具"]},"1111":{"title":"评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1112":{"title":"开发者需要关注哪些性能指标","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测标准"]},"1113":{"title":"游戏类型说明","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测标准"]},"1114":{"title":"iOS性能评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测标准"]},"1115":{"title":"Android性能评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则","评测标准"]},"1116":{"title":"Unity WebGL小游戏适配方案性能标准","titles":[]},"1117":{"title":"为什么需要性能评测标准?","titles":["Unity WebGL小游戏适配方案性能标准"]},"1118":{"title":"开发者需要关注哪些性能指标","titles":["Unity WebGL小游戏适配方案性能标准"]},"1119":{"title":"评测标准细则","titles":["Unity WebGL小游戏适配方案性能标准"]},"1120":{"title":"性能基线","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1121":{"title":"评测工具","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1122":{"title":"代码与资源体积","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1123":{"title":"Android 评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1124":{"title":"iOS 评测标准","titles":["Unity WebGL小游戏适配方案性能标准","评测标准细则"]},"1125":{"title":"视频设计规范","titles":[]},"1126":{"title":"建议启动视频内带有团队宣传logo动画,游戏logo动画,带有吸引力的游戏玩法视频","titles":["视频设计规范"]},"1127":{"title":"wasm水印插件","titles":[]},"1128":{"title":"说明:","titles":["wasm水印插件"]},"1129":{"title":"使用方式:","titles":["wasm水印插件"]},"1130":{"title":"添加插件","titles":["wasm水印插件","使用方式:"]},"1131":{"title":"使用插件","titles":["wasm水印插件","使用方式:"]},"1132":{"title":"注意","titles":["wasm水印插件"]},"1133":{"title":"微信小游戏Unity/团结引擎适配方案","titles":[]},"1134":{"title":"方案特点","titles":["微信小游戏Unity/团结引擎适配方案"]},"1135":{"title":"转换案例","titles":["微信小游戏Unity/团结引擎适配方案"]},"1136":{"title":"安装与使用","titles":["微信小游戏Unity/团结引擎适配方案"]}},"dirtCount":0,"index":[["热血神剑",{"2":{"1135":1}}],["旅行串串",{"2":{"1135":1}}],["又称unity",{"2":{"1133":1}}],["又相比于bundle全部加载至内存时占用过多的系统内存",{"2":{"401":1}}],["欢迎使用",{"2":{"1133":1}}],["欢迎更多游戏接入成为优秀案例",{"2":{"571":1}}],["操作同理",{"2":{"1131":1}}],["操作步骤",{"2":{"562":1}}],["码率",{"2":{"1126":1}}],["期间重复播放",{"2":{"1126":1}}],["竖屏视频",{"2":{"1126":1}}],["×",{"2":{"1126":2}}],["素材分辨率",{"2":{"1126":1}}],["素材类型",{"2":{"824":1}}],["素材类型的数据",{"2":{"823":1}}],["横屏视频",{"2":{"1126":1}}],["横竖屏切换",{"2":{"8":1}}],["流畅度",{"2":{"1118":1}}],["流畅度难以达到上线标准",{"2":{"1083":1}}],["人工批量测试数据",{"2":{"1111":1}}],["⾼通骁⻰765g",{"2":{"1105":1,"1120":1}}],["⾼通骁⻰865",{"2":{"1105":1,"1120":1}}],["⼩⽶10",{"2":{"1105":1,"1120":1}}],["档位",{"2":{"1105":1}}],["难以横向对比",{"2":{"1101":1}}],["苹果官方17",{"2":{"1097":1}}],["头",{"2":{"1095":1}}],["虽无法达到",{"2":{"1087":1}}],["虽然适配方案有较为广泛的兼容性",{"2":{"907":1}}],["虽然不再是标准的浏览器",{"2":{"712":1}}],["明显低于普通模式",{"2":{"1086":1}}],["算力得到明显提升",{"2":{"1083":1}}],["算力不及原生app",{"2":{"775":1}}],["计算资源消耗过高",{"2":{"1083":1}}],["计算公式",{"2":{"724":1}}],["报错提示未开启",{"0":{"1095":1},"2":{"1082":1}}],["报错原因",{"2":{"479":1}}],["压力测试",{"0":{"1087":1},"2":{"1082":1}}],["压缩",{"0":{"1095":1},"2":{"1082":1}}],["压缩后为",{"2":{"1014":1}}],["压缩后",{"2":{"1014":1}}],["压缩后只有几十k",{"2":{"705":1}}],["压缩音频",{"2":{"905":1}}],["压缩音频等支持",{"2":{"497":1}}],["压缩至原code包的20",{"2":{"874":1}}],["压缩首资源包",{"2":{"873":1}}],["压缩比更大",{"2":{"813":1}}],["压缩纹理优化能最大程度地减少内存与解压开销",{"2":{"726":1}}],["压缩纹理优化",{"2":{"549":1,"781":1}}],["压缩纹理资源",{"0":{"549":1}}],["压缩纹理产物输出目录",{"2":{"356":1}}],["压缩纹理",{"2":{"356":1,"395":1,"413":1,"497":1,"731":1,"905":1}}],["压缩纹理兼容flare",{"2":{"341":1}}],["压缩纹理替换速度优化",{"2":{"328":1}}],["压缩纹理替换优化",{"2":{"294":1}}],["压缩纹理工具独立命名",{"2":{"195":1}}],["压缩纹理工具逻辑异常",{"2":{"192":1}}],["压缩纹理工具支持特殊字符资源",{"2":{"180":1}}],["压缩纹理工具替换过程的卡死问题",{"2":{"171":1}}],["压缩纹理支持剔除功能",{"2":{"175":1}}],["压缩纹理对于不支持的引擎版本增加提示",{"2":{"173":1}}],["压缩纹理回退使用png时也支持缓存逻辑",{"2":{"150":1}}],["得到其中的安全区域",{"2":{"1073":1}}],["拉取分包时网络异常弹框提示",{"2":{"1059":1}}],["拉取游戏后台接口获取最新的预下载列表后",{"2":{"995":1}}],["拉取游戏后台获取最新的预下载列表",{"2":{"994":1}}],["遇到流程卡住问题",{"2":{"1044":1}}],["遇到事件不生效的问题",{"2":{"709":1}}],["拓展",{"2":{"1043":1}}],["拓展列表查看插件版本确认是否为最新版本",{"2":{"1042":1}}],["拓展设置",{"2":{"1017":1,"1043":1}}],["刚开始收集时又基本是跑子包函数",{"2":{"1037":1}}],["了再来考虑这个问题",{"2":{"1036":1}}],["了解小游戏分包",{"2":{"960":1}}],["了解小游戏的更新机制",{"2":{"909":1}}],["了解转换后目录结构",{"0":{"894":1}}],["了解",{"2":{"712":1}}],["了解基本概念后",{"2":{"626":1}}],["了解构建工具",{"0":{"618":1}}],["到",{"2":{"1036":1}}],["到底用线性还是gamma",{"2":{"809":1}}],["到底怎么选",{"2":{"808":1}}],["把之前收集过的函数当做放到首包",{"2":{"1024":1}}],["拆分为两个",{"2":{"1014":1}}],["拆分得尽量细",{"2":{"917":1}}],["放首包的内存占用相对小些",{"2":{"1038":1}}],["放在",{"2":{"1014":1}}],["放到wx",{"2":{"922":1}}],["收集界面增加连接状态",{"2":{"1069":1}}],["收集时可使用安卓和ios同时进行",{"2":{"1069":1}}],["收集操作",{"2":{"1026":1}}],["收集的场景覆盖率越高",{"2":{"1016":1}}],["收集到什么时候可以结束",{"0":{"1032":1},"2":{"1012":1}}],["收益应该会比较明显",{"2":{"815":1}}],["启用分包",{"0":{"1020":1},"2":{"1012":1}}],["启动时长",{"2":{"1118":1}}],["启动时发烫现象严重等问题",{"2":{"1100":1}}],["启动流程与时序我们知道",{"2":{"988":1}}],["启动流程与时时序",{"2":{"546":1}}],["启动进度显示",{"2":{"951":1}}],["启动优化与资源优化实战",{"0":{"923":1},"1":{"924":1,"925":1,"926":1,"927":1,"928":1}}],["启动界面",{"0":{"957":1},"1":{"958":1,"959":1},"2":{"900":1}}],["启动loader设置",{"2":{"899":1}}],["启动loader提供的默认加载界面为了契合不同游戏",{"2":{"423":1}}],["启动阶段",{"2":{"1014":1,"1118":1}}],["启动阶段背景图片",{"2":{"893":1}}],["启动阶段点三次封面视频下方unity",{"2":{"446":1,"965":1}}],["启动背景",{"2":{"893":1}}],["启动背景图",{"2":{"353":1}}],["启动需要一定耗时",{"2":{"893":1}}],["启动准备阶段有两个处理分支",{"2":{"864":1}}],["启动加载时序",{"0":{"863":1}}],["启动仅能加载少量资源",{"2":{"828":1}}],["启动下载的wasm包大小",{"2":{"789":1}}],["启动检测",{"0":{"788":1},"1":{"789":1,"790":1},"2":{"783":1}}],["启动较慢",{"2":{"775":1}}],["启动性能",{"0":{"1109":1},"2":{"763":1,"764":1,"1114":1,"1115":1,"1121":1}}],["启动",{"2":{"760":1,"1112":1}}],["启动与运行性能由于网络和设备条件稳定性问题不一定准确",{"2":{"741":1}}],["启动上报每个sceneid在一次启动过程中最多只能上报1次",{"2":{"690":1}}],["启动开发模式",{"0":{"612":1}}],["启动后",{"2":{"582":1}}],["启动场景上报分析",{"2":{"578":1,"690":1}}],["启动剧情需要存在一个主故事线作为启动入口",{"2":{"623":1}}],["启动剧情将立即结束",{"2":{"622":1}}],["启动剧情能够设计很复杂的交互剧情内容",{"2":{"616":1}}],["启动剧情能力上线初期微信小游戏团队希望更多开发者能够一定程度上自助接入该能力设计剧本",{"2":{"607":1}}],["启动剧情能力工作期间",{"2":{"579":1}}],["启动剧情通常以视频内容呈现为主",{"2":{"581":1}}],["启动剧情外显进度条默认为用户开启",{"2":{"579":1}}],["启动剧情的运行环境主要以",{"2":{"582":1}}],["启动剧情的",{"2":{"578":1}}],["启动剧情是一个持续较长时间的业务内容",{"2":{"578":1}}],["启动剧情插件允许配置相关变量进而干预剧情发展",{"2":{"577":1}}],["启动剧情剧本自助设计工具及文档",{"0":{"606":1},"1":{"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1,"626":1,"627":1,"628":1,"629":1,"630":1,"631":1,"632":1,"633":1,"634":1,"635":1,"636":1,"637":1,"638":1,"639":1,"640":1,"641":1,"642":1,"643":1,"644":1,"645":1,"646":1,"647":1,"648":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1,"660":1,"661":1,"662":1,"663":1,"664":1,"665":1,"666":1,"667":1,"668":1,"669":1,"670":1,"671":1,"672":1,"673":1,"674":1,"675":1,"676":1,"677":1,"678":1,"679":1,"680":1,"681":1,"682":1,"683":1,"684":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"695":1},"2":{"575":1}}],["启动剧情",{"0":{"568":1},"1":{"569":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1},"2":{"568":1}}],["启动剧情新增hash",{"2":{"34":1}}],["启动留存数据上报统计",{"0":{"544":1,"821":1},"1":{"822":1,"823":1,"824":1,"825":1,"826":1,"827":1},"2":{"544":1}}],["启动插件版本",{"2":{"527":2}}],["启动游戏出现",{"0":{"461":1}}],["启动视频",{"2":{"420":1,"422":1,"958":1}}],["启动视频样式错误",{"2":{"177":1}}],["启动封面图",{"2":{"420":1,"422":1,"958":1}}],["启动封面",{"0":{"418":1},"1":{"419":1,"420":1,"421":1,"422":1,"423":1},"2":{"551":1}}],["启动封面拉伸",{"2":{"166":1}}],["启动期间校验首资源包大小",{"2":{"84":1}}],["启动卡住时补充上报dependency",{"2":{"75":1}}],["编辑器区域",{"2":{"1042":1,"1043":1}}],["编辑器自定义拓展",{"2":{"1017":1}}],["编写需要调试的",{"2":{"1010":1}}],["编译优化将耗费大量性能",{"2":{"1099":1}}],["编译优化",{"2":{"1086":1}}],["编译",{"2":{"920":1,"975":1}}],["编译速度都更快利于版本迭代",{"2":{"907":1}}],["编译体积更小利于启动速度和运行内存",{"2":{"907":1}}],["编译体积",{"2":{"905":1}}],["编译与实例化",{"2":{"864":1}}],["编译选项中仅勾选首场景",{"2":{"778":1}}],["编译选项增加",{"2":{"302":1}}],["编译选项增加cleanbuild",{"2":{"137":1}}],["编译所占用内存占用非常大",{"2":{"725":1}}],["编译为跨平台的webassembly二进制代码",{"2":{"725":1}}],["编译内存",{"2":{"724":2}}],["编译报错",{"0":{"493":1}}],["编译阶段文案",{"2":{"421":1,"423":1,"959":1}}],["编译中",{"2":{"421":1,"959":1}}],["编译版本仅当导出勾选profiling",{"2":{"351":1}}],["编译代码将含有函数名",{"2":{"302":1}}],["编译参数增加error",{"2":{"20":1}}],["联调效率",{"0":{"1010":1}}],["版中的wx替换为",{"2":{"1005":1}}],["版的wx",{"2":{"1005":1}}],["版的调用如下",{"2":{"1005":1}}],["版的",{"2":{"1005":1}}],["版本更新请查看更新日志",{"2":{"1136":1}}],["版本更新",{"0":{"908":1},"1":{"909":1,"910":1,"911":1,"912":1,"913":1,"914":1,"915":1}}],["版本兼容性",{"0":{"904":1}}],["版本引擎使用资源包方式可安装",{"2":{"837":1}}],["版本游戏完全没有做资源的拆包",{"2":{"829":1}}],["版本信息",{"2":{"799":1}}],["版本b被清理后写入版本a的缓存",{"2":{"526":1}}],["版本建议",{"2":{"497":1}}],["版本构建",{"2":{"479":1}}],["版本和",{"2":{"433":1,"493":1}}],["版本和微信定制的",{"2":{"433":1}}],["版本不一样",{"2":{"433":1}}],["版本是越新越好吗",{"2":{"907":1}}],["版本是绑定的",{"2":{"493":1}}],["版本是很接近的",{"2":{"433":1}}],["版本是基于大部分微信小游戏的渲染需要来定制的",{"2":{"431":1}}],["版本可以直接拿来用吗",{"2":{"433":1}}],["版本可能不一样",{"2":{"433":1}}],["版本对应",{"2":{"433":1}}],["版本后",{"2":{"433":1}}],["版本后需要重新构建",{"2":{"388":1}}],["版本目前没有对",{"2":{"433":1}}],["版本定制的渲染管线",{"2":{"431":1}}],["版本进行游戏开发",{"2":{"428":1}}],["版本要求",{"0":{"425":1,"1001":1},"2":{"785":1}}],["版本支持",{"2":{"388":1}}],["版本支持问题",{"0":{"388":1}}],["版本",{"2":{"369":1,"388":1,"428":1,"431":1,"432":2,"433":2,"493":2,"608":1,"1005":1}}],["版本限制条件更新",{"2":{"264":1}}],["版本包进行回退",{"2":{"108":1}}],["版本使用新的目录结构为wx",{"2":{"108":1}}],["版本号兼容验证逻辑",{"2":{"34":1}}],["里面有详细注释说明",{"2":{"1005":1}}],["里面要实现",{"2":{"697":1}}],["箭头",{"2":{"1004":1}}],["货币符号",{"2":{"1004":1}}],["装饰符号",{"2":{"1004":1}}],["杂项符号",{"2":{"1004":1}}],["英文标点",{"2":{"1004":1}}],["英文大小写",{"2":{"1004":1}}],["日志中的",{"2":{"1093":1}}],["日志中查看以下字样",{"2":{"1003":1}}],["日志",{"2":{"1093":1}}],["日志获取方式",{"2":{"1046":1}}],["日志提示执行缓存逻辑",{"0":{"526":1},"2":{"500":1}}],["验证此资源预下载成功",{"2":{"998":1}}],["伪代码如下",{"2":{"994":1,"995":1}}],["访问https请求时",{"2":{"986":1}}],["经实际游戏测试",{"2":{"1087":1}}],["经过",{"2":{"1014":1}}],["经过微信小游戏团队测试",{"2":{"401":1}}],["经常有开发者问道",{"2":{"984":1}}],["向指定的",{"2":{"983":1}}],["向开放数据域传递消息",{"0":{"703":1}}],["粘包",{"2":{"982":1}}],["挪到最后",{"2":{"981":1}}],["感谢",{"2":{"981":1}}],["消耗",{"0":{"1086":1},"2":{"1082":1}}],["消失",{"0":{"1079":1}}],["消息",{"2":{"979":1,"983":1}}],["消除",{"2":{"496":1}}],["消除冲突提醒",{"0":{"379":1}}],["连接",{"2":{"981":1}}],["连接失败",{"2":{"979":1}}],["连接成功时发送数据",{"2":{"979":1}}],["连接成功",{"2":{"979":1}}],["出于应用场景考虑",{"2":{"979":1,"983":1}}],["出现首个业务场景",{"2":{"759":1,"1106":1,"1120":1}}],["出现两个版本的下载日志",{"2":{"526":1}}],["出现以下两种日志",{"2":{"515":1}}],["出现vconsole",{"2":{"446":1,"965":1}}],["采用代码分包后",{"2":{"1086":1}}],["采用单线程机制",{"2":{"977":1}}],["采集profile",{"2":{"531":1}}],["环境运行性能不足",{"2":{"1088":1}}],["环境下",{"2":{"1083":1}}],["环境下禁止使用以下代码",{"2":{"977":1}}],["环境中的函数调用",{"2":{"582":1}}],["键值对",{"2":{"977":1}}],["套接字来实现网络连接",{"2":{"975":1}}],["浏览数据",{"0":{"970":1}}],["浏览器中渲染图形的",{"2":{"1076":1}}],["浏览器http对象",{"2":{"948":1}}],["浏览器或小游戏",{"2":{"712":1}}],["浏览器菜单打开",{"2":{"351":1}}],["拖拽并以csv方式导入sqlite数据库",{"2":{"968":1}}],["省略其他配置",{"2":{"962":1,"992":1}}],["khz",{"2":{"1126":1}}],["kbit",{"2":{"1126":2}}],["kongregate",{"2":{"949":1}}],["keep",{"2":{"622":3,"657":1,"678":3}}],["keyboard",{"2":{"494":1}}],["key",{"0":{"604":1,"605":1},"2":{"380":1,"576":1,"977":1}}],["略大于ab本身体积",{"2":{"948":1}}],["拷贝到wasm临时内存",{"2":{"948":1}}],["读磁盘必定影响性能",{"2":{"945":1}}],["读取字体文件失败",{"2":{"1003":1}}],["读取字体文件耗时=xxms",{"2":{"1003":1}}],["读取systeminfo",{"2":{"841":1}}],["读取首资源包",{"2":{"826":1}}],["读取启动剧情全局变量值",{"2":{"594":1,"605":1}}],["读取",{"2":{"576":1}}],["读取路径是否正确等",{"2":{"560":1}}],["读取你的自定义模板目录并对其中的资源做动态修改",{"2":{"383":1}}],["于是我们仍旧在js内存中维护了完整bundle的缓存",{"2":{"945":1}}],["于是微信小游戏提供了wasm代码分包能力",{"2":{"550":1}}],["频繁读写磁盘损耗性能",{"2":{"945":1}}],["阐述如何在小游戏环境对assetbundle进行打包",{"2":{"940":1}}],["六",{"0":{"936":1},"1":{"937":1,"938":1,"939":1}}],["物件动态加载",{"0":{"927":1}}],["物理计算较重的游戏使用fixed",{"2":{"782":1}}],["物理性能",{"0":{"745":1}}],["物理",{"2":{"498":1}}],["答案是assetreference",{"2":{"927":1}}],["答案是肯定的",{"2":{"926":1,"984":1}}],["答题",{"2":{"496":1}}],["战斗等",{"2":{"926":1}}],["场景动态加载",{"0":{"926":1}}],["场景中必须与非及时资源在启动时一并加载",{"2":{"833":1}}],["然而",{"2":{"927":1,"934":1}}],["然而使用ab需要做不少的工作",{"2":{"920":1}}],["然后重启开发者工具",{"2":{"1044":1}}],["然后收集",{"2":{"1019":1}}],["然后继续下一步",{"2":{"1019":2}}],["然后下一步",{"2":{"1019":1}}],["然后对应方法名首字母由小写改为大写",{"2":{"1005":1}}],["然后使用类似这种方式加载",{"2":{"934":1}}],["然后调用wxeditorwindow",{"2":{"897":1}}],["然后找到",{"2":{"493":1}}],["然后通过",{"2":{"433":1}}],["然后在project",{"2":{"429":1}}],["然后再导入universal",{"2":{"428":1}}],["然后点击apply",{"2":{"429":1}}],["然后点击面板右下角的",{"2":{"428":1}}],["然后点击加载前面导出的cpuprofile文件即可",{"2":{"351":1}}],["附可参考的项目",{"2":{"917":1}}],["附录",{"2":{"805":1,"902":1}}],["剩余的游戏资源如何加载",{"2":{"917":1}}],["戏运行期间检查是否有新版本",{"2":{"913":1}}],["依赖的开发者工具版本为",{"2":{"1016":1}}],["依赖的基础代码包",{"2":{"428":1}}],["依赖关系以及后期维护的复杂工作",{"2":{"920":1}}],["依赖管理",{"2":{"919":1}}],["依然可能体验到旧版本内容",{"2":{"911":1}}],["老项目请尽量选择2019以上版本",{"2":{"905":1}}],["备注",{"2":{"905":1}}],["具有非常宽泛的兼容性",{"2":{"904":1}}],["具体操作和注意事项如下",{"2":{"1019":1}}],["具体做法",{"2":{"973":1}}],["具体参见assetbundle缓存",{"2":{"893":2}}],["具体请参考使用",{"2":{"831":1}}],["具体请移步版本更新",{"2":{"441":1}}],["具体如何抉择",{"2":{"577":1}}],["具体可参阅首场景启动优化手册",{"2":{"546":1}}],["具体可阅读后续资源缓存规则文档",{"2":{"441":1}}],["具体实施可阅读具体指引文档",{"2":{"538":1}}],["具体方式请参考unity官方文档interaction",{"2":{"473":1}}],["具体值可通过minigame",{"2":{"259":1}}],["端小游戏高性能模式适用于遇到",{"2":{"1088":1}}],["端普通模式与高性能模式的得分",{"2":{"1087":1}}],["端口可达",{"2":{"902":1}}],["端口可通修改webgl",{"2":{"902":1}}],["端口",{"2":{"902":1}}],["端无法循环播放完整音频",{"2":{"367":1}}],["想脚本调用的话",{"2":{"897":1}}],["扫码二维码预览即可",{"2":{"896":1}}],["扫描结束的回调函数",{"2":{"417":1}}],["扫描的资源将包含ab包内的单个纹理资源信息",{"2":{"398":1}}],["稳定版",{"2":{"896":1,"1016":1,"1129":1}}],["稳定版本",{"0":{"0":1}}],["勿用测试appid",{"2":{"893":1}}],["信息有说明要如何操作",{"2":{"889":1}}],["映射到函数名",{"2":{"889":1}}],["zh",{"2":{"887":1}}],["zoommode",{"2":{"421":1,"423":1}}],["强烈建议2022",{"2":{"905":1}}],["强烈建议开发者可以使用代码分包工具将代码包减少到原始尺寸的到1",{"2":{"874":1}}],["强制更新",{"0":{"912":1},"1":{"913":1,"914":1}}],["强制结束",{"2":{"589":1,"591":1}}],["强制结束启动剧情",{"2":{"589":1}}],["强制storebinary",{"2":{"404":1}}],["务必在服务器对txt后缀开启",{"2":{"924":1}}],["务必对首资源包进行压缩传输",{"2":{"873":1}}],["务必对首资源包压缩",{"2":{"873":1}}],["务必避免这样使用",{"2":{"720":1}}],["另一个可以延迟加载",{"2":{"1014":1}}],["另",{"2":{"873":1}}],["另外这两个",{"2":{"1031":1}}],["另外对于",{"2":{"1015":1}}],["另外对于ios高性能模式",{"2":{"1014":1}}],["另外",{"2":{"426":1}}],["守护球球",{"0":{"861":1}}],["银河战舰",{"0":{"860":1}}],["葫芦娃大作战",{"0":{"858":1}}],["钓鱼挖矿",{"2":{"857":1}}],["延续了传统",{"2":{"857":1}}],["延迟加载",{"2":{"928":1}}],["延迟时长",{"2":{"671":1}}],["延迟执行",{"0":{"669":1},"1":{"670":1,"671":1,"672":1,"673":1}}],["延迟渲染",{"2":{"430":1,"431":1}}],["我已收集好",{"2":{"1026":1}}],["我叫mt",{"2":{"857":1}}],["我叫mt2",{"0":{"857":1},"2":{"1135":1}}],["我们得到以下结论",{"2":{"1086":1}}],["我们得到实际游戏项目的",{"2":{"1086":1}}],["我们发现相对于webgl1",{"2":{"1076":1}}],["我们针对这种情况也有线上patch可以进行补漏",{"2":{"1033":1}}],["我们也会在启动",{"2":{"1031":1}}],["我们也可以根据业务自己的使用特点来进行sql分析",{"2":{"971":1}}],["我们会对比前后两个包的symbol",{"2":{"1024":1}}],["我们会根据验证情况以及大量转换游戏反馈的情况给出引擎版本建议",{"2":{"904":1}}],["我们认为添加到预下载列表的资源都是需要尽快使用到的资源",{"2":{"988":1}}],["我们可以在此阶段提前下载资源",{"2":{"988":1}}],["我们可以在",{"2":{"971":1}}],["我们可以通过size进行排序分析内存最大占用的堆栈情况",{"2":{"970":1}}],["我们可以分析unityheap",{"2":{"967":1}}],["我们可以看到",{"2":{"577":1}}],["我们在微信小游戏环境将文件系统接口桥接到了微信的文件系统接口",{"2":{"945":1}}],["我们只需要将对应的streammingassets上传到对应的cdn服务器即可",{"2":{"937":1}}],["我们只需要关注callmain调用的playerloadfirstscene函数",{"2":{"533":1}}],["我们需要将这些资源设置为",{"2":{"934":1}}],["我们需要先确定监控的小游戏进程名称",{"2":{"714":1}}],["我们还会经常动态实例化",{"2":{"927":1}}],["我们应将这些冗余的内容单独进行设置为addressable",{"2":{"926":1}}],["我们应让启动剧情插件正常启动",{"2":{"577":1}}],["我们构建时仅选择了splash",{"2":{"926":1}}],["我们总结下启动时序以及开发者",{"2":{"877":1}}],["我们必要理解启动流程",{"2":{"871":1}}],["我们建议得优化原则是",{"2":{"917":1}}],["我们建议开发者",{"2":{"928":1}}],["我们建议开发者使用预下载功能",{"2":{"875":1}}],["我们建议开发者将启动优化作为上线前最为重要的事项",{"2":{"869":1}}],["我们建议原始代码包",{"2":{"874":1}}],["我们建议内存峰值控制在以下范围",{"2":{"711":1}}],["我们希望sdk与工程代码解耦",{"2":{"839":1}}],["我们拆分了三个部分",{"2":{"825":1}}],["我们给出unity",{"2":{"776":1}}],["我们此处给出转换游戏中最容易遇到的内存问题与解决方案",{"2":{"724":1}}],["我们关注的内存",{"2":{"720":1}}],["我们从大到小各个角度去监控和分析游戏的内存情况",{"2":{"713":1}}],["我们通常也是从该入口进行能力迭代",{"2":{"582":1}}],["我们提供了一个微信开发者工具里的插件来辅助分包过程",{"2":{"1016":1}}],["我们提供了以下支持",{"2":{"885":1}}],["我们提供了多种模板可供选择",{"2":{"616":1}}],["我们提供了",{"2":{"381":1}}],["我们正在尝试兼容",{"2":{"367":1}}],["曾梦想惩恶扬善",{"2":{"856":1}}],["喜欢武侠世界",{"2":{"856":1}}],["熠熠生辉",{"2":{"854":1}}],["抛光的流程获得精美的翡翠雕刻成品",{"2":{"854":1}}],["翡翠大师",{"0":{"854":1}}],["建立你的地下王国",{"2":{"853":1}}],["建议启动视频内带有团队宣传logo动画",{"0":{"1126":1}}],["建议新增收集函数个数超过100个的还是要生成新分包+发版本",{"2":{"1033":1}}],["建议先重启下开发者工具",{"2":{"1023":1}}],["建议先以",{"2":{"1010":1}}],["建议在微信开发者工具",{"2":{"967":1}}],["建议自行在修改接口时候加编译宏方便控制导出版本",{"2":{"945":1}}],["建议直接升级到2022支持压缩纹理",{"2":{"907":1}}],["建议仅勾选loading场景",{"2":{"891":1}}],["建议首屏启动时间控制在5~10s甚至更短",{"2":{"871":1}}],["建议继续沿用常规资源加载方案",{"2":{"829":1}}],["建议开发者勾选",{"2":{"874":1}}],["建议开发者具体测试一下",{"2":{"815":1}}],["建议开发者根据指引优化",{"2":{"1090":1}}],["建议开发者根据",{"2":{"388":1}}],["建议用",{"2":{"813":1}}],["建议材质引用的纹理数尽量控制在",{"2":{"813":1}}],["建议检查一下最终生成的",{"2":{"812":1}}],["建议从256尝试是否合适",{"2":{"811":1}}],["建议进行cdn预热",{"2":{"799":1}}],["建议游戏依据自身游戏特性",{"2":{"762":1}}],["建议以性能评估标准实测为准",{"2":{"741":1}}],["建议中轻度游戏不超过该值",{"2":{"727":1}}],["建议值",{"2":{"727":1}}],["建议使用webgl2",{"2":{"1084":1}}],["建议使用微信开发者工具或android真机进行内存堆栈导出",{"2":{"974":1}}],["建议使用",{"2":{"808":1,"832":1,"981":1}}],["建议使用压缩纹理优化",{"2":{"749":1}}],["建议使用2022或团结版的memoryprofiler",{"2":{"731":1}}],["建议使用lts版本",{"2":{"497":1}}],["建议使用异步接口以不影响主线程帧率",{"2":{"490":1}}],["建议勾选并设置为high",{"2":{"480":1}}],["建议单文件2~5mb以内",{"2":{"440":1}}],["建议基于当前",{"2":{"433":1}}],["建议优先使用brotli",{"2":{"403":1}}],["建议",{"2":{"387":1,"565":1,"709":1,"737":1,"799":1,"873":1}}],["建议限制同时播放的音频数量",{"2":{"367":1}}],["巨兽战场",{"0":{"852":1}}],["剑心吟",{"0":{"851":1}}],["鱼吃鱼",{"0":{"850":1}}],["神奇的消除战争之旅",{"2":{"848":1}}],["谜题大陆",{"0":{"848":1},"2":{"1135":1}}],["让高度占满刘海屏以下的区域",{"2":{"1073":1}}],["让自己的翡翠珍宝展馆发展壮大",{"2":{"854":1}}],["让你爱不释手",{"2":{"847":1}}],["让其生效",{"2":{"429":1}}],["众多的城市场景",{"2":{"847":1}}],["丰富的游戏画面",{"2":{"847":1}}],["地铁跑酷",{"0":{"847":1}}],["立志阻挡魔族入侵的游戏",{"2":{"846":1}}],["仙侠为题材",{"2":{"846":1}}],["九梦仙域",{"0":{"846":1}}],["探索冻土",{"2":{"845":1}}],["登录mp微信公众平台",{"2":{"834":1,"1136":1}}],["登录态参考登录态管理",{"2":{"373":1}}],["往往会非常大",{"2":{"831":1}}],["往往由于场景过大或由于业务原因造成瞬间内存峰值",{"2":{"727":1}}],["卸载",{"2":{"831":1}}],["各类型游戏的资源优化建议",{"0":{"830":1},"1":{"831":1,"832":1,"833":1}}],["各有优缺点",{"2":{"807":1}}],["希望减少游戏的转化周期",{"2":{"829":1}}],["必须",{"2":{"893":1}}],["必要的代码修改",{"2":{"829":1}}],["必然是",{"2":{"809":1}}],["骨骼动画",{"2":{"829":1}}],["懒加载资源类型",{"2":{"829":1}}],["技术沙龙",{"0":{"842":1},"1":{"843":1}}],["技术原理",{"0":{"885":1},"2":{"829":1}}],["技术常见问题qa",{"0":{"454":1},"1":{"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1},"2":{"535":1}}],["效率变低等现象",{"2":{"1079":1}}],["效率更高",{"2":{"386":1}}],["效果提升明显",{"2":{"829":1}}],["较少",{"2":{"829":2}}],["较大",{"2":{"829":1}}],["较为普遍的是assetbundle加载与prefab实例化",{"2":{"746":1}}],["倒是功能强大的",{"2":{"829":1}}],["公众平台",{"2":{"827":1}}],["及以上",{"2":{"1016":1,"1129":2}}],["及",{"2":{"825":1}}],["及时卸载不再使用的资源包释放内存",{"2":{"831":1}}],["及时释放以节省内存",{"2":{"728":1}}],["及时挂载到主故事线使其生效",{"2":{"683":1,"688":1}}],["~",{"2":{"817":1}}],["绘制主场景和ui",{"2":{"816":1}}],["绘制到",{"2":{"697":1}}],["摄像机",{"0":{"816":1}}],["差不多",{"2":{"814":1}}],["网页webgl",{"2":{"902":1}}],["网格和蒙皮",{"0":{"814":1}}],["网络等",{"2":{"1118":1}}],["网络通信",{"0":{"978":1,"983":1},"1":{"979":1,"980":1,"981":1,"982":1}}],["网络通信适配",{"0":{"539":1,"975":1},"1":{"976":1,"977":1,"978":1,"979":1,"980":1,"981":1,"982":1,"983":1,"984":1,"985":1,"986":1},"2":{"539":1}}],["网络",{"2":{"977":1}}],["网络类",{"2":{"975":1}}],["网络传输大小应控制在3~5mb",{"2":{"873":1}}],["网络条件绝大部分为wifi或4g",{"2":{"873":1}}],["网络时间占监控时长占比不足70",{"2":{"799":1}}],["网络未充分利用",{"2":{"799":1}}],["网络并发数过少",{"2":{"799":1}}],["网络协议",{"2":{"798":1}}],["网络信息检测",{"0":{"797":1},"1":{"798":1,"799":1},"2":{"783":1}}],["网络请求造成的浏览器端js临时内存",{"2":{"712":1}}],["网络较差",{"2":{"591":1}}],["网络较弱正在缓冲",{"2":{"591":1}}],["网络流畅度对用户体验是存在直接关系",{"2":{"581":1}}],["网络空闲时预下载的资源",{"2":{"893":1}}],["网络空闲",{"2":{"547":1}}],["网络系统",{"2":{"498":1}}],["网络安全域名",{"2":{"440":1}}],["网络url",{"2":{"421":1}}],["网络接口如unitywebrequest支持通过添加特殊请求头request",{"2":{"16":2}}],["张以内",{"2":{"813":1}}],["着色器变体和关键字说明",{"2":{"812":1}}],["着重检查",{"2":{"523":1}}],["法线等一般半精度就够了",{"2":{"812":1}}],["法线重建",{"2":{"431":1}}],["语句等待下载完成",{"2":{"977":1}}],["语句很复杂的就不建议使用",{"2":{"812":1}}],["语句",{"2":{"812":2}}],["蒙版的设置",{"2":{"812":1}}],["遮罩",{"2":{"812":1}}],["遮蔽",{"2":{"430":1}}],["像",{"2":{"812":1,"814":1}}],["好处是",{"2":{"812":1}}],["好友关系链",{"2":{"893":1}}],["好友数据加载中",{"2":{"709":1}}],["好友排行榜",{"0":{"707":1}}],["复制一份并尽可能简化",{"2":{"812":1}}],["复制示例中",{"2":{"374":1}}],["烘焙",{"2":{"811":1}}],["投射阴影",{"2":{"811":1}}],["逐渐调大",{"2":{"811":1}}],["阴影贴图的大小越小越好",{"2":{"811":1}}],["阴影生效的距离",{"2":{"811":1}}],["远处物体不用阴影也难观察出来",{"2":{"811":1}}],["离摄像机的",{"2":{"811":1}}],["至多额外加一个",{"2":{"816":1}}],["至少",{"2":{"809":1}}],["至此你已经完成了一次很小变动的剧本导出工作",{"2":{"615":1}}],["至此问题解决",{"2":{"479":1}}],["才为",{"2":{"1073":1}}],["才让游戏能稳定跑起来",{"2":{"1031":1}}],["才可以开通广告主",{"2":{"1011":1}}],["才可真正卸载",{"2":{"945":1}}],["才能用于定位问题",{"2":{"889":1}}],["才支持",{"2":{"809":1}}],["才会看到",{"2":{"428":1}}],["颜色空间呢",{"2":{"809":1}}],["颜色空间",{"0":{"809":1},"2":{"809":2}}],["颜色偏移后处理",{"2":{"430":1}}],["线性颜色空间渲染",{"2":{"1076":1}}],["线性颜色空间比较方便",{"2":{"809":1}}],["线性颜色空间",{"0":{"809":1},"2":{"809":1}}],["线上版本不会检测",{"2":{"785":1}}],["冗余功能较多",{"2":{"808":1}}],["冗余功能很少",{"2":{"808":1}}],["灵活",{"2":{"808":1}}],["固定",{"2":{"808":1}}],["固定为unity小游戏封面启动进度",{"2":{"579":1}}],["拿来即用",{"2":{"808":2}}],["现有的游戏原来是什么管线就什么管线",{"2":{"808":1}}],["现网阶段",{"0":{"766":1},"1":{"767":1,"768":1}}],["现网真实玩家上报的性能数据",{"2":{"762":1,"1111":1}}],["现网错误日志上报与排查",{"0":{"564":1},"1":{"565":1,"566":1,"567":1}}],["帧耗时数据是否正常",{"2":{"1084":1}}],["帧数",{"2":{"801":1}}],["帧率低于此值的帧会被记录",{"2":{"785":1}}],["帧率检测",{"0":{"800":1},"1":{"801":1,"802":1},"2":{"783":1}}],["帧率",{"2":{"759":1,"1106":1,"1120":1,"1123":1,"1124":1}}],["辅助定位是cpu耗时还是网络耗时导致启动慢",{"2":{"800":1}}],["充分利用网络",{"2":{"799":1}}],["平均并发数小于5",{"2":{"799":1}}],["平均并发数",{"2":{"798":1}}],["平台可通过水印准确检测出游戏的原作者",{"2":{"1128":1}}],["平台暂不保证所有能力完善",{"2":{"1078":1}}],["平台提升启动性能的优化事项",{"2":{"877":1}}],["平台目前所反馈到的结论是使用",{"2":{"829":1}}],["平台针对启动和运行输出了大量优化手段",{"2":{"784":1}}],["平台通过对评测标准和游戏性能数据的整合",{"2":{"767":1}}],["平台能力适配",{"2":{"543":1}}],["平台适配",{"0":{"482":1},"1":{"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1}}],["平台是没有开启这一项优化",{"2":{"429":1}}],["平台也会启用这个宏",{"2":{"429":1}}],["平台会启用",{"2":{"429":1}}],["平台特有的",{"2":{"429":1}}],["平台相关的宏",{"2":{"429":1}}],["平台",{"2":{"428":1,"429":3,"433":1,"831":1}}],["平台的游戏开发",{"2":{"427":1}}],["减小预下载资源量",{"2":{"793":1}}],["减小预下载个数",{"2":{"793":1}}],["减少shader中instance",{"2":{"1079":1}}],["减少编译时间",{"2":{"1015":1}}],["减少玩家进行核心玩法的等待时间",{"2":{"876":1}}],["减少骨骼数量",{"2":{"814":1}}],["减少模型面数",{"2":{"814":1}}],["减少不必要的材质变体",{"2":{"812":1}}],["减少不必要的unity模块引入",{"2":{"725":1}}],["减少代码包体",{"2":{"778":1}}],["减少初始化与首帧逻辑",{"2":{"778":1}}],["减少drawcall",{"0":{"751":1}}],["减少首资源包大小",{"2":{"728":1}}],["减少内存使用",{"2":{"748":1,"1015":1}}],["减少内存",{"2":{"549":1}}],["减少内存占用",{"2":{"549":1}}],["条件",{"2":{"790":4,"793":5,"796":3,"799":9,"802":3}}],["条件判断",{"0":{"684":1},"1":{"685":1,"686":1,"687":1,"688":1},"2":{"627":1}}],["弹框提醒优化建议",{"2":{"786":1}}],["弹框时用户可尝试重启小游戏",{"2":{"71":1}}],["监控时长",{"2":{"798":1}}],["监控指标",{"0":{"789":1,"792":1,"795":1,"798":1,"801":1},"2":{"783":5}}],["监听收到消息的事件",{"2":{"983":1}}],["监听当接收到数据的时触发该事件",{"2":{"979":1}}],["监听",{"2":{"708":1}}],["监听该全局变量",{"2":{"683":1,"688":1}}],["检测指标解释",{"0":{"787":1},"1":{"788":1,"789":1,"790":1,"791":1,"792":1,"793":1,"794":1,"795":1,"796":1,"797":1,"798":1,"799":1,"800":1,"801":1,"802":1},"2":{"783":1}}],["检测示意",{"0":{"786":1},"2":{"783":1}}],["检查更新",{"2":{"944":1}}],["检查",{"2":{"812":1}}],["检查是否有大长帧",{"2":{"800":1}}],["检查是否32位微信导致无法进入游戏",{"2":{"223":1}}],["检查缓存配置",{"2":{"799":2}}],["检查可缓存资源配置",{"2":{"797":1}}],["检查wasm分包代码的加载时机",{"2":{"794":1}}],["检查预下载列表使用情况",{"2":{"791":1}}],["检查框架启动阶段的耗时和资源大小",{"2":{"788":1}}],["检查存储空间是否足够",{"2":{"513":1}}],["检查异常时将终止导出",{"2":{"378":1}}],["检查异常时将在unity控制台中给出详细的冲突信息",{"2":{"378":1}}],["释放不使用的资源",{"2":{"781":1}}],["释义",{"2":{"627":1}}],["剔除不必要的插件",{"2":{"778":1}}],["精简首场景",{"2":{"928":1}}],["精简首场景物件",{"2":{"778":1}}],["精确获取每帧性能瓶颈",{"2":{"739":1}}],["机型档位",{"2":{"1120":1}}],["机型的内存限制为",{"2":{"1090":1}}],["机型下的评测",{"2":{"776":1}}],["机型分档等多种维度建立",{"2":{"755":1,"1103":1}}],["历史现网标准请查阅文档",{"2":{"1111":1}}],["历史现网标准请查阅历史评测标准",{"2":{"762":1}}],["历史评测标准",{"0":{"773":1}}],["协助开发者更精确地定位问题并提供优化建议",{"2":{"771":1}}],["协议实现",{"2":{"539":1}}],["面向全平台",{"2":{"808":1}}],["面向开发者提供一个较为全面的大盘性能监控系统",{"2":{"767":1}}],["面板右测会显示",{"2":{"428":1}}],["面板中配置",{"2":{"413":1}}],["面板中",{"2":{"413":1}}],["面板配置后将被存盘记录无需每次执行前进行配置",{"2":{"411":1}}],["红米k30",{"2":{"1105":1,"1120":1}}],["红色指标值表示指标标准下降",{"2":{"762":1}}],["红中在手",{"2":{"423":1}}],["白屏",{"2":{"760":1,"1112":1}}],["白色为预留部分",{"2":{"717":1}}],["黑屏等严重问题",{"2":{"1118":1}}],["黑",{"2":{"760":1,"1112":1}}],["逻辑异常",{"2":{"760":1,"1112":1}}],["逻辑代码可以继续",{"2":{"451":1}}],["卡在启动封面无法启动",{"0":{"1097":1},"2":{"1082":1}}],["卡顿时长占比xx",{"2":{"802":1}}],["卡顿率",{"2":{"759":1,"760":1,"801":1,"1106":1,"1112":1}}],["卡帧问题",{"2":{"802":1}}],["卡牌等",{"2":{"758":1,"1113":1}}],["卡牌成长",{"2":{"727":1}}],["卡牌",{"2":{"496":1}}],["研发能力",{"2":{"1088":1}}],["研发工具箱",{"2":{"759":1,"768":1}}],["研发成本",{"2":{"372":1}}],["测试过程为不断增加运算复杂度",{"2":{"1087":1}}],["测试对应进程的内存占用",{"2":{"731":1}}],["测量5分钟以上游戏核心玩法卡顿率",{"2":{"759":1,"1106":1}}],["测量5分钟以上游戏核心玩法帧率",{"2":{"759":1,"1106":1,"1120":1}}],["测量方法请参考优化unity",{"2":{"759":1,"1106":1,"1120":1}}],["测量方法",{"2":{"759":1,"1106":1,"1120":1}}],["指标与测量方法",{"0":{"759":1,"1106":1},"1":{"760":1},"2":{"1120":1}}],["指引",{"2":{"372":1}}],["玩法较复杂",{"2":{"758":1,"1113":1}}],["玩家平均下载速度约2mb",{"2":{"873":1}}],["玩家将体验到富有风险的翡翠原石选石过程",{"2":{"854":1}}],["玩家扮演一个攀星阁学艺有成",{"2":{"846":1}}],["玩家可以交互",{"2":{"825":1}}],["玩家可通过游戏右上方",{"2":{"565":1}}],["玩家对启动时长与体验非常敏感",{"2":{"822":1}}],["玩家提交反馈",{"2":{"565":1}}],["玩家存档请使用服务器或云开发",{"2":{"498":1}}],["评测工具",{"0":{"765":1,"1108":1,"1121":1},"1":{"766":1,"767":1,"768":1,"769":1,"770":1,"771":1,"772":1,"1109":1,"1110":1}}],["评测小游戏性能首先需要确定性能基线",{"2":{"757":1}}],["评测标准文档",{"2":{"773":1}}],["评测标准依赖于",{"2":{"762":1,"1111":1}}],["评测标准更新时间",{"2":{"762":1,"1111":1}}],["评测标准",{"0":{"762":1,"1111":1,"1123":1,"1124":1},"1":{"763":1,"764":1,"1112":1,"1113":1,"1114":1,"1115":1}}],["评测标准细则",{"0":{"756":1,"1104":1,"1119":1},"1":{"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1,"770":1,"771":1,"772":1,"773":1,"1105":1,"1106":1,"1107":1,"1108":1,"1109":1,"1110":1,"1111":1,"1112":1,"1113":1,"1114":1,"1115":1,"1120":1,"1121":1,"1122":1,"1123":1,"1124":1}}],["评测标准根据小游戏整体的性能数据表现",{"2":{"755":1,"1103":1}}],["限制每次draw",{"2":{"1079":1}}],["限制分辨率以一定的画质牺牲来降低对设备消耗",{"2":{"748":1}}],["限制分辨率",{"0":{"748":1}}],["限制帧率有利于降低设备发热量与提升游戏时长",{"2":{"747":1}}],["限制帧率",{"0":{"747":1}}],["限帧与当前fps",{"2":{"488":1}}],["限帧时禁用后台执行loop",{"2":{"244":1}}],["轻度",{"2":{"758":1,"1113":1}}],["轻度休闲游戏应保证低档机型30fps以上",{"2":{"737":1}}],["轻度io",{"2":{"496":1}}],["之前的版本对高分辨屏适配不是很好",{"2":{"1074":1}}],["之间",{"2":{"1036":1}}],["之间的性能差异",{"2":{"733":1}}],["之后画面先黑一下再展示排行榜",{"2":{"709":1}}],["之后黑屏",{"2":{"370":1}}],["峰值不要超过500m",{"2":{"731":1}}],["双声道会产生2倍内存消耗",{"2":{"729":1}}],["约5",{"2":{"727":1}}],["观察dynamicmemory的峰值",{"2":{"727":1}}],["观察到异常提醒后开发者需要根据提醒前往对比冲突的脚本内容自行适配",{"2":{"379":1}}],["手动更新",{"2":{"1018":1}}],["手动配置",{"0":{"992":1}}],["手动删除多余插件",{"2":{"725":1}}],["手游app则往往需要较长时间的下载",{"2":{"868":1}}],["手游未使用",{"0":{"832":1,"833":1}}],["手游已使用",{"0":{"831":1}}],["手机上用的是带txt后缀的",{"2":{"403":1}}],["托管的对象和本机对象",{"2":{"727":1}}],["托管",{"2":{"724":1}}],["托管堆的内存预留内存",{"2":{"717":1}}],["托管堆",{"2":{"712":1,"717":2}}],["占用并维持正常水平",{"2":{"1086":1}}],["占用因此长期运行容易越来越烫",{"2":{"1086":1}}],["占用如下图所示",{"2":{"1086":1}}],["占用比较高时",{"2":{"719":1}}],["占大头",{"2":{"814":1}}],["占位区域对应的高度",{"2":{"701":1}}],["占位区域对应的宽度",{"2":{"701":1}}],["占位区域对应屏幕左上角纵坐标",{"2":{"701":1}}],["占位区域对应屏幕左上角横坐标",{"2":{"701":1}}],["任何分配都会产生记录",{"2":{"718":1}}],["任何时候当",{"2":{"394":1}}],["绿色为空闲内存或碎片",{"2":{"717":1}}],["空闲内存值",{"2":{"717":1}}],["空间描述主要涉及",{"2":{"629":1}}],["空间描述约定",{"0":{"629":1}}],["空间提升的游戏",{"2":{"523":1}}],["空间提升开通空间提升的游戏",{"2":{"512":1}}],["空间足够",{"2":{"521":1}}],["捕捉",{"2":{"715":1}}],["垃圾回收",{"2":{"712":1}}],["举例",{"2":{"712":1}}],["画布与设备物理分辨率相关",{"2":{"712":1}}],["典型的流程如下图所示",{"2":{"863":1}}],["典型由以下几部分组成",{"2":{"717":1}}],["典型游戏的内存占用如下图所示",{"2":{"712":1}}],["典型地",{"2":{"471":1,"712":1,"970":1,"1120":1}}],["容易出现这种情形",{"2":{"819":1}}],["容易失败的问题",{"2":{"254":1}}],["容器",{"2":{"712":1}}],["堆栈",{"2":{"970":1}}],["堆栈信息",{"2":{"467":1}}],["堆",{"2":{"712":1}}],["低档",{"2":{"1105":1,"1120":1}}],["低档机",{"2":{"711":2,"1123":2,"1124":2}}],["低端机",{"2":{"1090":1}}],["低端机上运行高性能模式",{"2":{"1015":1}}],["低使用门槛",{"2":{"919":1}}],["低版本使用微信压缩纹理",{"2":{"731":1}}],["低版本兼容",{"0":{"555":1}}],["低版本或者其他组件暂不支持自动适配",{"0":{"554":1}}],["低版本c",{"2":{"286":1}}],["给开放数据域发消息要求展示群排行",{"2":{"708":1}}],["给开放数据域侧抛一个事件",{"2":{"701":1}}],["谁是第一",{"2":{"708":1}}],["群好友排行榜",{"0":{"708":1}}],["整体流程示意",{"2":{"707":1,"708":1}}],["要尽量保持关注",{"2":{"1029":1}}],["要尽可能将playerloadfirstscene的耗时控制在整个callmain耗时的20",{"2":{"532":1}}],["要知道各个阶段的含义",{"2":{"871":1}}],["要求展示好友排行榜",{"2":{"707":1}}],["展示群排行",{"2":{"707":1,"708":1}}],["展示",{"2":{"707":1}}],["滚动列表等处理",{"2":{"705":1}}],["很有可能会遇到超出内存限制而崩溃",{"2":{"1100":1}}],["很好的前端用于查看unity编译信息",{"2":{"881":1}}],["很容易导致",{"2":{"814":1}}],["很可能导致排行榜关闭之后文理错乱",{"2":{"702":1}}],["很关键",{"2":{"678":1}}],["告知开放域去执行数据拉取和渲染操作",{"2":{"701":1}}],["停止步骤",{"2":{"697":1}}],["停止性能数据录制",{"2":{"351":1}}],["核心玩法资源",{"2":{"761":1,"1107":1,"1122":1}}],["核心玩法的平均卡顿率",{"2":{"759":1,"1106":1}}],["核心玩法的平均帧率",{"2":{"759":1,"1106":1,"1120":1}}],["核心资源",{"2":{"759":1,"1106":1,"1120":1}}],["核心目的是告诉开放数据域",{"2":{"709":1}}],["核心是三个作用",{"2":{"701":1}}],["核心在于",{"2":{"697":1}}],["核心思想在于执行到该帧时会引发某种动作",{"2":{"619":1}}],["鉴于第4点",{"2":{"697":1}}],["绝大部分接口都只能在开放数据域内调用",{"2":{"697":1}}],["绝对路径",{"2":{"384":2}}],["成为瓶颈",{"2":{"814":1}}],["成立时执行的故事线",{"2":{"688":1}}],["成功与否都开始启动unity",{"2":{"994":2}}],["成功",{"2":{"468":1}}],["成功加载立即上传gpu后将从系统内存释放",{"2":{"401":1}}],["缺点",{"2":{"808":3,"911":1,"913":1}}],["缺点是用户删除本地小游戏则记录丢失",{"2":{"490":1}}],["缺失函数过多",{"2":{"796":1}}],["缺省则为剧情内部全局变量",{"2":{"681":1}}],["外域探险玩法都将为您呈现独一无二的掌中魔幻世界",{"2":{"857":1}}],["外界可根据此名称读取",{"2":{"683":1,"688":1}}],["外界可以修改全局变量使得剧情内部完成基于条件判断实现的不同逻辑分支",{"2":{"679":1}}],["外界无法访问",{"2":{"681":1}}],["外界也可以通过监听某个全局变量值来实时监控剧情内部通过属性修改产生的一些消息反馈",{"2":{"679":1}}],["外显进度条的进度设置等",{"2":{"582":1}}],["外显进度条配置",{"2":{"580":1,"585":1}}],["外显进度条接入",{"0":{"579":1},"1":{"580":1}}],["沟通",{"2":{"679":1}}],["挂载一个适合的故事线中触发后则实现",{"2":{"678":1}}],["循环之",{"2":{"678":1}}],["淡入",{"2":{"678":1}}],["呼吸态",{"2":{"678":2}}],["曲率函数",{"2":{"676":1}}],["持续时长",{"2":{"676":1}}],["几乎一个数量级的差异",{"2":{"1087":1}}],["几乎不需要任何代价",{"2":{"919":1}}],["几乎不需要修改代码",{"2":{"919":1}}],["几何图形",{"2":{"1004":1}}],["几",{"2":{"675":1}}],["动画数据",{"2":{"971":1}}],["动画等",{"2":{"740":1}}],["动画",{"2":{"734":1}}],["动画被作用的关键动作帧句柄",{"2":{"676":1}}],["动画在微信开发者工具",{"2":{"675":1}}],["动画函数将自动结束",{"2":{"675":1}}],["动画相关",{"0":{"674":1},"1":{"675":1,"676":1,"677":1,"678":1}}],["动作",{"2":{"496":1}}],["句柄",{"2":{"664":1,"667":1}}],["句柄执行",{"2":{"624":1}}],["十六进制颜色描述字符串",{"2":{"659":1}}],["背景",{"0":{"1014":1},"2":{"1012":1}}],["背景和原理介绍",{"0":{"697":1}}],["背景色",{"2":{"658":1}}],["背景图",{"2":{"899":1}}],["背景图片",{"2":{"421":1}}],["背景图或背景视频",{"2":{"421":1,"423":1,"959":1}}],["纯色矩形区域",{"2":{"658":1}}],["透明度从",{"2":{"678":2}}],["透明度",{"2":{"655":1,"667":1,"676":1}}],["继续下一步",{"2":{"1026":1}}],["继续迭代",{"2":{"796":1}}],["继续",{"2":{"639":1,"640":1,"650":1,"651":1}}],["继续上面的例子",{"2":{"513":1}}],["暂时只能通过",{"2":{"705":1}}],["暂停音频",{"2":{"647":1}}],["暂停视频",{"2":{"636":1}}],["暂不支持",{"2":{"369":1}}],["意味着",{"2":{"814":1}}],["意味着当触发",{"2":{"635":1}}],["意味着实际运行时多次达到该事件条件都会引发该事件",{"2":{"622":1}}],["意味其他事件触发",{"2":{"635":1}}],["互相独立",{"2":{"634":1,"646":1}}],["互通的特性",{"2":{"473":1}}],["案例",{"0":{"634":1,"638":1,"641":1,"646":1,"649":1,"652":1,"657":1,"661":1,"665":1,"668":1,"673":1,"678":1,"683":1,"688":1,"692":1},"1":{"635":1},"2":{"635":1,"665":1}}],["秒",{"2":{"633":1,"645":1,"1126":1}}],["覆盖尽可能多的场景",{"2":{"1026":1}}],["覆盖",{"2":{"632":1}}],["宽度传",{"2":{"707":2}}],["宽度放缩系数",{"2":{"655":1,"667":1,"676":1}}],["宽度",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["宽度适配",{"2":{"423":1}}],["底层资源的缓存与更新已由适配层自动完成",{"2":{"944":1}}],["底层分配器会尽量复用",{"2":{"717":1}}],["底层分配器",{"2":{"717":1}}],["底层分配器视角",{"2":{"717":1}}],["底端",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["底部",{"2":{"580":1,"585":1}}],["底部增加启动剧情配置",{"2":{"576":1}}],["顶点",{"2":{"814":1}}],["顶端",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["顶部菜单栏",{"2":{"893":1}}],["顶部",{"2":{"580":1,"585":1}}],["表达式方式",{"2":{"629":1}}],["表示有请求会排队",{"2":{"798":1}}],["表示预下载已发起但未完成",{"2":{"793":1}}],["表示游戏的稳定运行时长",{"2":{"759":1,"1106":1}}],["表示",{"2":{"429":2}}],["时这两个字段会返回null",{"2":{"979":1,"983":1}}],["时将找不到这些类",{"2":{"975":1}}],["时的",{"2":{"889":1}}],["时对后续场景使用",{"2":{"833":1}}],["时触发新的关键动作帧",{"2":{"634":1,"646":1}}],["时",{"2":{"629":1,"635":1,"687":2,"905":1,"924":2}}],["时常开发者需要对",{"2":{"380":1}}],["百分比字符串",{"2":{"628":1}}],["数学运算符号",{"2":{"1004":1}}],["数字形式",{"2":{"1004":1}}],["数字",{"2":{"1004":1}}],["数",{"2":{"815":1}}],["数值",{"2":{"628":1}}],["数据路径",{"2":{"1106":1}}],["数据上报",{"2":{"951":1}}],["数据目录",{"2":{"839":1}}],["数据统计报表需要联系我们获取",{"2":{"827":1}}],["数据分析",{"0":{"969":1},"1":{"970":1,"971":1},"2":{"827":1}}],["数据分析接口",{"2":{"70":1}}],["数据报表数据未来会开放到",{"2":{"827":1}}],["数据报表统计分析请参考文档启动场景上报分析",{"2":{"827":1}}],["数据报表包含unity",{"2":{"827":1}}],["数据报告",{"2":{"562":1}}],["数据仅供参考",{"2":{"762":1}}],["数据",{"2":{"759":1,"768":1,"1106":1}}],["数据的通信一定是单向的",{"2":{"697":1}}],["数据入口",{"2":{"565":1,"566":1,"567":1}}],["布尔值",{"2":{"628":1}}],["填充拉伸",{"2":{"632":1}}],["填充纯色",{"2":{"627":1}}],["填写相应参数",{"2":{"893":1}}],["填写该项则意味开启启动剧情",{"2":{"585":1}}],["填写encoding时没有返回数据",{"2":{"162":1}}],["主流品牌",{"2":{"1027":1}}],["主包",{"2":{"1014":1}}],["主关卡优先",{"2":{"832":1}}],["主域要更新",{"2":{"697":1}}],["主域无法感知到开放数据域发生了什么",{"2":{"697":1}}],["主域",{"2":{"697":1}}],["主故事线有一些很常见的用途",{"2":{"625":1}}],["主故事线是启动剧情启动后最先执行的内容",{"2":{"625":1}}],["主故事线",{"0":{"625":1}}],["主要由启动和运行两个阶段产生性能问题",{"2":{"1118":1}}],["主要是减少了编译相关的内存",{"2":{"1045":1}}],["主要是用来参考如何定制",{"2":{"431":1}}],["主要关注wasm首包",{"2":{"1034":1}}],["主要来源是ios高性能",{"2":{"1029":1}}],["主要讲述在仙域大陆上",{"2":{"846":1}}],["主要分成",{"2":{"532":1}}],["主要分成两部分调用",{"2":{"532":1}}],["主要用于错误调试与异常排查",{"2":{"467":1}}],["主要修改有以下这些",{"2":{"431":1}}],["主要需要修改",{"2":{"428":1}}],["主要有以下组成",{"2":{"873":1}}],["主要有",{"2":{"428":1}}],["主要的执行过程如下图所示",{"2":{"389":1}}],["组织bundle",{"2":{"920":1}}],["组成的数组",{"2":{"622":1}}],["组件",{"2":{"812":1,"834":1}}],["组件视频将从10秒的位置开始播放",{"2":{"635":1}}],["组件的依赖",{"2":{"555":1}}],["组件自动适配",{"0":{"554":1}}],["组件已自动适配微信小游戏",{"2":{"368":1}}],["③",{"2":{"622":3}}],["②中均是",{"2":{"622":1}}],["②",{"2":{"622":4}}],["①",{"2":{"622":4}}],["事件之后有个同步的渲染行为",{"2":{"709":1}}],["事件之后没有任何渲染行为",{"2":{"709":1}}],["事件始终有效",{"2":{"657":1}}],["事件名",{"2":{"633":1,"645":1,"656":1,"660":1,"672":1,"677":1,"682":1,"687":1}}],["事件是对于不同关键动作帧存在不同的事件从而可以引发新的故事线的能力",{"2":{"622":1}}],["事件",{"0":{"622":1,"633":1,"645":1,"656":1,"660":1,"672":1,"677":1,"682":1,"687":1},"2":{"620":1,"622":1}}],["贴图尽量不使用可写属性",{"2":{"780":1}}],["贴图尽量不生成mipmap",{"2":{"780":1}}],["贴图maxsize尽量不超过1024",{"2":{"780":1}}],["贴图只能加载小游戏包内图片资源",{"2":{"654":1}}],["贴图相关",{"0":{"653":1},"1":{"654":1,"655":1,"656":1,"657":1,"658":1,"659":1,"660":1,"661":1}}],["贴图资源只能放置",{"2":{"618":1}}],["贴花",{"2":{"430":1,"431":1}}],["尝试更多的模板",{"0":{"616":1}}],["常规资源加载方案",{"2":{"829":1}}],["常用启动优化工具",{"0":{"879":1},"1":{"880":1,"881":1,"882":1,"883":1}}],["常用启动优化技巧",{"0":{"878":1}}],["常用优化工具",{"0":{"738":1},"1":{"739":1,"740":1,"741":1}}],["常用之一",{"2":{"423":3}}],["常见情况是",{"2":{"1083":1}}],["常见为安卓系统版本低于7",{"2":{"1003":1}}],["常见app",{"2":{"944":1}}],["常见的适配方式都可以在小游中使用",{"2":{"1073":1}}],["常见的callback分配堆栈特征",{"2":{"971":1}}],["常见的情况是发生在如空项目或游戏代码中从未使用wxsdk的任何runtime能力时",{"2":{"841":1}}],["常见的头像用圆来做一个mask",{"2":{"812":1}}],["常见问题",{"0":{"840":1,"901":1,"972":1},"1":{"841":1,"973":1,"974":1}}],["常见问题qa",{"0":{"709":1}}],["常见纹理资源",{"2":{"829":1}}],["常见优化手段",{"0":{"742":1},"1":{"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1,"752":1,"753":1}}],["常见优化步骤如何",{"2":{"731":1}}],["常见q",{"0":{"693":1},"1":{"694":1,"695":1},"2":{"615":1}}],["行的",{"2":{"614":1}}],["你的主逻辑",{"2":{"1005":1,"1074":1}}],["你的内容彻底可用时",{"2":{"919":1}}],["你都能快速的切换来addressable系统中",{"2":{"919":1}}],["你也就知道驱动整个剧情发展无非3点",{"2":{"626":1}}],["你将学会设计复杂的剧情内容",{"2":{"617":1}}],["你将在根目录看到",{"2":{"615":1}}],["你将在工具完全载入资源后看到默认的启动剧情内容",{"2":{"613":1}}],["你可以略读",{"2":{"626":1}}],["你可以快速修改你看到的很多属性内容",{"2":{"614":1}}],["你可以使用微信开发者工具查看",{"2":{"351":1}}],["你会看到被你刚刚修改的按钮贴图位置从右下角变成左下角",{"2":{"614":1}}],["你无需修改",{"2":{"614":1}}],["确认游戏的光照",{"2":{"811":1}}],["确认是否和data",{"2":{"527":1}}],["确保正确安装node",{"2":{"610":1}}],["|",{"0":{"594":1},"2":{"942":3}}],["||",{"2":{"429":2}}],["退出按钮",{"2":{"591":1}}],["退后台暂停播放音频",{"2":{"266":1}}],["产生本次回调的远程资源url",{"2":{"591":1}}],["产生时已终止",{"2":{"451":1}}],["获得交互句柄",{"0":{"598":1}}],["获得当前剧情插件运行状态",{"2":{"584":1,"600":1}}],["获取url列表",{"2":{"995":1}}],["获取数据统计",{"0":{"827":1}}],["获取loader启动阶段",{"0":{"826":1}}],["获取游戏的现网玩家的性能采集数据",{"2":{"759":1,"768":1}}],["获取自动缓存的文件存储路径",{"2":{"518":1}}],["获取微信定制版的",{"2":{"431":1}}],["获取不到实际dpr",{"2":{"6":1}}],["何时结束剧情",{"2":{"582":1}}],["准备工作",{"0":{"608":1}}],["准备充分",{"2":{"582":1}}],["准备条件编译宏",{"0":{"429":1}}],["他会随着",{"2":{"614":1}}],["他会与游戏资源缓存共用",{"2":{"490":1}}],["他的时机将更晚",{"2":{"582":1}}],["区别的是一些屏幕信息的获取",{"2":{"1073":1}}],["区别于",{"2":{"582":1}}],["区间浮点数",{"2":{"599":1}}],["区域",{"2":{"490":1}}],["区域6",{"2":{"362":1}}],["区域5",{"2":{"362":1}}],["区域4",{"2":{"362":1}}],["区域3",{"2":{"362":1}}],["区域2",{"2":{"362":1}}],["区域1",{"2":{"362":1}}],["侧就可能出现黑一下的情况",{"2":{"709":1}}],["侧隐藏了",{"2":{"702":1}}],["侧有个占位的纹理",{"2":{"697":1}}],["侧",{"0":{"597":1},"1":{"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1}}],["侧需要等待",{"2":{"582":1}}],["侧需要用到的访问接口",{"2":{"582":1}}],["侧指的是游戏在",{"2":{"582":1}}],["侧指的是导出目录中",{"2":{"582":1}}],["侧完成标记",{"2":{"576":1}}],["长耗时帧信息",{"2":{"801":1}}],["长耗时帧的个数",{"2":{"801":1}}],["长耗时的帧",{"2":{"801":1}}],["长时间等待视频数据缓冲",{"2":{"581":1}}],["长音频请使用unityaudio",{"2":{"498":1}}],["长音频播放使用的是inneraudio",{"2":{"366":1}}],["跳过按钮由用户主动放弃剧情",{"2":{"581":1}}],["跳转小游戏接口错误",{"2":{"274":1}}],["弱网级别",{"2":{"581":1,"591":1}}],["弱网处理",{"0":{"581":1},"2":{"576":1}}],["浮点数",{"2":{"580":1}}],["声明cdn地址",{"2":{"954":1}}],["声明控制后30",{"2":{"580":1}}],["声明成员函数",{"2":{"383":1}}],["仍需要开发者结合游戏实际情况进行优化",{"2":{"784":1}}],["仍未得到期望的结果",{"2":{"577":1}}],["仍然会自动在",{"2":{"839":1}}],["仍然提供了加载进度外显能力",{"2":{"579":1}}],["仍然没有走网络下载",{"0":{"525":1},"2":{"500":1}}],["仍然需要",{"2":{"479":1}}],["防沉迷提醒等",{"2":{"577":1}}],["防沉迷等信息披露",{"2":{"573":1}}],["异步接口修改可能需要涉及到业务逻辑改造",{"2":{"831":1}}],["异步干预剧情需要使用到",{"2":{"577":1}}],["异步的获取时间明显是不可控的",{"2":{"577":1}}],["异步由于存在不确定的结果返回时间",{"2":{"577":1}}],["异常日志",{"2":{"1003":1}}],["异常等问题并进行排查原因",{"2":{"564":1}}],["异常信息",{"2":{"451":4}}],["异常捕捉",{"2":{"451":4}}],["显存",{"2":{"967":1}}],["显示timelog开发者可以看到小游戏目前的启动首屏时长",{"2":{"871":1}}],["显示性能面板",{"2":{"717":1,"727":1}}],["显示跳过",{"2":{"591":1}}],["显示",{"2":{"580":1}}],["显示进度则启动剧情插件将在首资源包与wasm初始化完成后以平滑动画完成100",{"2":{"579":1}}],["显示黑屏",{"0":{"477":1}}],["显然不是可靠的判断新用户的方案",{"2":{"577":1}}],["发送消息",{"2":{"983":1}}],["发送",{"2":{"981":2}}],["发送事件给开放数据域",{"2":{"707":1}}],["发起资源下载任务",{"2":{"799":1}}],["发布新版本时",{"2":{"799":1}}],["发布前使用压缩纹理工具进行优化",{"2":{"781":1}}],["发布上线与现网监控",{"0":{"552":1},"2":{"534":1}}],["发布上线版本请务必关闭该选项",{"2":{"351":1}}],["发现该部分内存明显大于我们预留的unityheap",{"2":{"720":1}}],["发生一次事件后再达成条件也不会再次引发该事件",{"2":{"622":1}}],["发生异常时强制结束",{"2":{"576":1}}],["发生异常",{"2":{"576":1}}],["剧本与启动剧情插件版本不兼容",{"2":{"589":1}}],["剧本文件读取失败",{"2":{"589":1}}],["剧本文件路径",{"2":{"585":1}}],["剧本",{"2":{"578":1}}],["剧本设计请阅读",{"2":{"575":1}}],["剧情的设计将由操作它开始",{"2":{"618":1}}],["剧情播放结束",{"2":{"576":1}}],["剧情效果",{"0":{"569":1},"1":{"570":1,"571":1}}],["早于wasm初始化",{"2":{"574":1}}],["故事线的理解比较简单",{"2":{"626":1}}],["故事线是将一个或多个关键动作帧有序打包的容器",{"2":{"623":1}}],["故事线",{"0":{"623":1},"1":{"624":1,"625":1},"2":{"619":1,"622":2,"634":1,"646":1,"673":1}}],["故事背景的介绍",{"2":{"573":1}}],["故无法正确删除旧版本资源",{"2":{"513":1}}],["赛季cg动画短片",{"2":{"573":1}}],["前面",{"2":{"1010":1}}],["前面我们提到开发者需要将资源从首包分离以较少首屏加载时间",{"2":{"876":1}}],["前期建议继续使用当前版本",{"2":{"907":1}}],["前置新人",{"2":{"573":1}}],["前往微信开发者工具下载安装stable版开发者工具",{"2":{"834":1,"1136":1}}],["前往",{"2":{"353":1,"479":1}}],["插图等形式展现",{"2":{"572":1}}],["插件会自动执行逻辑",{"2":{"1131":1}}],["插件会根据音频文件大小自动适配使用不同的播放方式",{"2":{"366":1}}],["插件检测并展示项目中的wasm文件",{"2":{"1131":1}}],["插件依赖微信开发者工具1",{"2":{"1129":1}}],["插件新旧版本分包兼容",{"2":{"1067":1}}],["插件面板当前后台服务版本为3",{"2":{"1045":1}}],["插件使用",{"0":{"1019":1},"1":{"1020":1,"1021":1,"1022":1,"1023":1,"1024":1,"1025":1,"1026":1,"1027":1,"1028":1,"1029":1},"2":{"1012":1}}],["插件更新",{"0":{"1018":1},"2":{"1012":1}}],["插件安装",{"0":{"1017":1},"2":{"1012":1}}],["插件调试日志",{"0":{"965":1}}],["插件已做兼容",{"2":{"959":1}}],["插件底层会判断是否已有缓存",{"2":{"944":1}}],["插件启动",{"2":{"826":1}}],["插件并不知道什么时候检测截止",{"2":{"785":1}}],["插件导出的",{"2":{"706":1}}],["插件环境异常",{"2":{"589":1}}],["插件为游戏提供了一些基础上报数据",{"2":{"544":1}}],["插件下载",{"2":{"537":1}}],["插件认为已经本地已经有同名文件streamingassets",{"2":{"513":1}}],["插件与非平台相关的c原生插件",{"2":{"498":1}}],["插件申请成功",{"0":{"464":1}}],["插件",{"2":{"365":1}}],["插件错误报实时日志",{"2":{"259":1}}],["插件特性动态开关",{"2":{"173":1}}],["比",{"2":{"813":1}}],["比较特殊的是",{"2":{"623":1}}],["比wasm",{"2":{"572":1}}],["比如几百个",{"2":{"1038":1}}],["比如新手教学",{"2":{"1016":1}}],["比如splash界面以及对应文案",{"2":{"924":1}}],["比如应用市场自动更新",{"2":{"911":1}}],["比如内存更低",{"2":{"905":1,"907":1}}],["比如以下这段堆栈",{"2":{"889":1}}],["比如超过",{"2":{"814":1}}],["比如大范围的代码重构",{"2":{"1024":1}}],["比如大型游戏在使用addressable时catalog文件往往会超过10mb",{"2":{"743":1}}],["比如大量反序列化操作",{"2":{"533":1}}],["比如黑屏",{"2":{"741":1}}],["比如物理",{"2":{"740":1}}],["比如wasm与宿主接口互调频次",{"2":{"735":1}}],["比如iphone",{"2":{"712":1}}],["比如小游戏公共库",{"2":{"712":1}}],["比如绘制个文案",{"2":{"709":1}}],["比如canavs宽度为960",{"2":{"707":1}}],["比如有些地方的纹理变成了排行榜对应的纹理",{"2":{"702":1}}],["比如刚刚的案例中你可以这样描述",{"2":{"629":1}}],["比如当你规定了",{"2":{"629":1}}],["比如挂载一些全局变量放到主故事线上就很合理",{"2":{"625":1}}],["比如位置信息",{"2":{"614":1}}],["比如游戏自己计算了crc",{"2":{"523":1}}],["比如订阅消息wx",{"2":{"491":1}}],["比如addressable打包后生成streamingassets",{"2":{"523":1}}],["比如assetbundle",{"2":{"472":1}}],["比如aa的setting",{"2":{"441":1}}],["比如version1",{"2":{"441":1}}],["比如",{"2":{"372":1,"451":1,"622":1,"629":1,"707":1,"709":1,"927":1}}],["镜花异闻录",{"2":{"571":1}}],["飞翔之光",{"2":{"571":1}}],["飞行设计",{"2":{"496":1}}],["魔魔打勇士",{"2":{"571":1}}],["演示工程源码",{"2":{"570":1}}],["演示视频及演示工程源码",{"0":{"570":1}}],["迎新",{"2":{"568":1}}],["定义",{"2":{"758":1,"759":1,"1106":1,"1113":1,"1120":1}}],["定位问题",{"2":{"566":1}}],["定制urp",{"2":{"432":2}}],["定制版本的",{"2":{"432":2,"433":1}}],["定制版本的性能数据对比",{"0":{"432":1}}],["定制版本",{"0":{"431":1},"2":{"430":2}}],["定制本地化",{"0":{"430":1},"1":{"431":1,"432":1}}],["定制",{"2":{"427":1,"428":1,"430":1}}],["定制适合微信小游戏的",{"2":{"427":1}}],["定制微信小游戏的",{"0":{"427":1},"1":{"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1}}],["定制效果",{"0":{"423":1}}],["问题",{"2":{"982":1}}],["问题原因",{"2":{"725":1,"726":1,"727":1,"728":1,"729":1,"1095":1}}],["问题复现尽可能详细",{"2":{"562":1}}],["问题反馈与联系我们",{"0":{"561":1},"1":{"562":1,"563":1}}],["讨论与跟踪",{"2":{"562":1}}],["阅读转换指引",{"2":{"558":1}}],["转化过程中的复杂度以及关注的侧重点自然也是不同的",{"2":{"830":1}}],["转化人力",{"2":{"829":1}}],["转化的游戏一般具备",{"2":{"557":1}}],["转换完成后",{"2":{"895":1}}],["转换后文件目录",{"2":{"893":1}}],["转换后开发者应在微信开发者工具检查控制台中network面板资源是否加载正常",{"2":{"560":1}}],["转换打包工具",{"2":{"885":1}}],["转换案例目的是分享学习",{"2":{"844":1}}],["转换案例",{"0":{"844":1,"1135":1},"1":{"845":1,"846":1,"847":1,"848":1,"849":1,"850":1,"851":1,"852":1,"853":1,"854":1,"855":1,"856":1,"857":1,"858":1,"859":1,"860":1,"861":1}}],["转换工具自动替换",{"2":{"962":1}}],["转换工具会在game",{"2":{"952":1}}],["转换工具会将unity",{"2":{"874":1}}],["转换工具最低需要引擎版本为2018",{"2":{"907":1}}],["转换工具可以实现",{"2":{"556":1}}],["转换工具导出微信小游戏进行小游戏导出转换",{"2":{"834":1,"1136":1}}],["转换工具导出微信小游戏",{"0":{"537":1,"890":1},"1":{"891":1,"892":1,"893":1,"894":1,"895":1,"896":1,"897":1,"898":1,"899":1,"900":1,"901":1},"2":{"537":2}}],["转换工具对代码包自动进行br压缩",{"2":{"460":1}}],["转换方案已通过webaudio支持unity音频",{"2":{"489":1}}],["转换面板勾选",{"2":{"873":1}}],["转换面板勾选profiling",{"2":{"448":1}}],["转换面板设置内存值多少合适",{"2":{"731":1}}],["转换面板设置合理的",{"2":{"727":1}}],["转换面板的最大内存提示与指引优化",{"2":{"188":1}}],["转换插件有提供配置来自动使用这项能力",{"2":{"913":1}}],["转换插件理论上支持的unity版本涵盖",{"2":{"904":1}}],["转换插件版本高于202212070000导出的包",{"2":{"1071":1}}],["转换插件版本高于202212070000且重新导出",{"2":{"1069":1}}],["转换插件版本",{"2":{"785":1,"827":1}}],["转换插件相关配置",{"0":{"955":1,"958":1,"961":1},"2":{"513":2}}],["转换插件默认设置",{"2":{"450":1}}],["转换插件",{"2":{"425":1,"1001":1}}],["转换插件配置",{"0":{"420":1}}],["转换插件添加启动并行下载配置",{"2":{"78":1}}],["转换小游戏",{"0":{"893":1},"2":{"394":1,"413":1,"893":1}}],["转换微信小游戏产物",{"2":{"377":1}}],["转换导出插件勾选",{"2":{"351":1}}],["转换配置新增ios",{"2":{"34":1}}],["适合使用场景",{"0":{"1076":1}}],["适合于对版本一致性要求不高的游戏使用",{"2":{"911":1}}],["适中",{"2":{"829":2}}],["适当增加预下载资源大小",{"2":{"793":1}}],["适当使用static",{"2":{"751":1}}],["适当调整fixed",{"2":{"745":1}}],["适用于主机平台",{"2":{"808":1}}],["适用于小游戏",{"2":{"808":3}}],["适用于",{"2":{"557":1}}],["适配文档",{"2":{"1042":1}}],["适配小游戏",{"0":{"892":1},"1":{"893":1,"894":1,"895":1,"896":1}}],["适配在小游戏后",{"2":{"712":1}}],["适配插件自身脚本错误",{"2":{"567":1}}],["适配插件将自动埋点游戏启动与特殊异常日志",{"2":{"565":1}}],["适配插件已自动完成",{"2":{"472":1}}],["适配插件版本号更新为1",{"2":{"108":1}}],["适配插件版本升级到1",{"2":{"16":1,"20":1,"124":1,"135":1,"137":1,"147":1,"153":1,"155":1,"158":1}}],["适配unity",{"2":{"124":1}}],["适配audioclip",{"2":{"67":1}}],["适配application",{"2":{"59":1}}],["适配video",{"2":{"57":1}}],["适配2021",{"2":{"9":1}}],["服务端",{"0":{"982":1}}],["服务",{"2":{"557":1}}],["服务中",{"2":{"557":1}}],["服务器域名",{"2":{"985":1}}],["服务器开启http2",{"2":{"799":1}}],["服务器状态码",{"2":{"798":1}}],["服务器未开启br或gzip",{"2":{"790":1}}],["服务器返回不缓存的头",{"2":{"525":1}}],["服务器中",{"2":{"396":1,"540":1}}],["绑定端口",{"2":{"983":1}}],["绑定回调",{"2":{"555":1}}],["绑定以下脚本",{"2":{"555":1}}],["封面图",{"2":{"551":1,"899":1}}],["封面图配置",{"0":{"551":1}}],["封面自动隐藏时机",{"2":{"418":1,"551":1}}],["均需要使用cpuprofile定位",{"2":{"802":1}}],["均需要重新执行该步骤",{"2":{"394":1}}],["均建议进行该优化",{"2":{"549":1}}],["客户端",{"0":{"981":1}}],["客户端根据硬件",{"2":{"549":1}}],["客户端版本修复",{"2":{"367":1}}],["它才会告诉你加载完成",{"2":{"919":1}}],["它的目的是减少渲染状态的切换",{"2":{"815":1}}],["它的优点是",{"2":{"549":1}}],["它并不能减少",{"2":{"815":1}}],["它与",{"2":{"815":1}}],["它有多种压缩格式",{"2":{"813":1}}],["它完全不理解自己最终是怎么被绘制到屏幕上的",{"2":{"697":1}}],["它核心处理两件事",{"2":{"697":1}}],["它包含的功能很全面也很强大",{"2":{"427":1}}],["过配置",{"2":{"1088":1}}],["过程中会自动记录所有内存分配数据",{"2":{"968":1}}],["过大的资源下载会造成带宽抢占",{"2":{"793":1}}],["过长的启动时间会导致用户的显著流失",{"2":{"546":1}}],["过滤下不需要缓存的文件",{"2":{"507":1}}],["过滤不需缓存的文件类型",{"2":{"290":1}}],["尤其www",{"2":{"947":1}}],["尤其是战斗释放技能时候",{"2":{"819":1}}],["尤其是在游戏启动阶段",{"2":{"743":1}}],["尤其是native",{"2":{"719":1}}],["尤其从",{"2":{"544":1,"822":1}}],["尤其关注安全域名",{"2":{"463":1}}],["广告买量启动优化",{"2":{"1071":1}}],["广告买量时",{"2":{"824":1}}],["广告接口是否需要上线后才能调试",{"2":{"1011":1}}],["广告的调用如下",{"2":{"1005":1}}],["广告位类型",{"2":{"824":1}}],["广告类型",{"2":{"823":1,"824":1}}],["广告",{"2":{"544":1,"822":1}}],["广告等等",{"2":{"543":1}}],["广告api",{"2":{"102":1}}],["震动",{"2":{"543":1}}],["输入当前项目版本描述",{"2":{"1019":1}}],["输入版本描述",{"0":{"1021":1},"2":{"1012":1}}],["输入法complete回调",{"2":{"555":1}}],["输入法confirm回调",{"2":{"555":1}}],["输入法适配",{"0":{"553":1},"1":{"554":1,"555":1},"2":{"543":1}}],["输入com",{"2":{"433":1}}],["申请",{"2":{"540":1}}],["快速对接平台开放能力",{"2":{"1134":1}}],["快速上手创建小游戏类目应用",{"2":{"834":1,"1136":1}}],["快速适配对微信api能力的接入",{"2":{"832":1}}],["快速入门",{"0":{"609":1},"1":{"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1}}],["快速熟悉工具的使用并完成一次简单的转化工作",{"2":{"537":1}}],["快速开始",{"0":{"537":1},"2":{"537":2}}],["快适配",{"2":{"464":1,"827":1,"834":1,"896":1,"1136":1}}],["阶段耗时",{"2":{"826":1}}],["阶段",{"2":{"760":1,"1112":1}}],["阶段五",{"0":{"552":1},"2":{"534":1}}],["阶段四",{"0":{"545":1},"1":{"546":1,"547":1,"548":1,"549":1,"550":1,"551":1},"2":{"534":1}}],["阶段三",{"0":{"542":1},"1":{"543":1,"544":1},"2":{"534":1}}],["阶段二",{"0":{"536":1},"1":{"537":1,"538":1,"539":1,"540":1,"541":1},"2":{"534":1}}],["阶段一",{"0":{"535":1},"2":{"398":1,"534":1}}],["初步确认技术方案是否符合游戏项目",{"2":{"534":1}}],["初始值则为",{"2":{"621":1}}],["初始场景中需要后续主场景或配置加载时可采取分帧策略",{"2":{"530":1,"875":1}}],["初始场景不宜过大",{"2":{"530":1,"875":1}}],["初始化sdk",{"2":{"1074":1}}],["初始化wxsdk",{"2":{"979":1}}],["初始化",{"2":{"759":1,"1106":1,"1120":1}}],["初始化期间可以同步读取本地资源简单判断是否需要播放剧情",{"2":{"577":1}}],["初始化时遇到了缺失函数",{"2":{"461":1}}],["初始化完成",{"2":{"421":1,"423":1,"959":1}}],["初始化阶段文案",{"2":{"421":1,"423":1,"959":1}}],["初始化中",{"2":{"421":1,"959":1}}],["真正执行开始游戏逻辑",{"2":{"533":1}}],["真机环境下",{"2":{"984":1}}],["真机环境中",{"2":{"459":1}}],["真机访问异常",{"2":{"984":1}}],["真机预览时",{"2":{"985":1,"986":1}}],["真机预览",{"2":{"896":1}}],["真机可通过抓包工具查看下载url",{"2":{"527":1}}],["真机安卓缓存目录",{"2":{"523":2}}],["真机调试",{"2":{"458":1,"805":1}}],["真机",{"2":{"446":1,"541":1,"965":1}}],["真机播放正常",{"2":{"370":1}}],["关注",{"2":{"1093":1}}],["关注ios高性能是否有fetch",{"2":{"1029":1}}],["关注android或者ios普通模式的子包是否过早加载",{"2":{"1029":1}}],["关注总体流失漏斗以确定需要优化的方向",{"2":{"827":1}}],["关键过程",{"2":{"864":1}}],["关键动作帧赋值",{"2":{"635":1}}],["关键动作帧句柄",{"2":{"628":1}}],["关键动作帧可以达成某种事件从而产生新的一条故事线",{"2":{"626":1}}],["关键动作帧更像是一个",{"2":{"619":1}}],["关键动作帧",{"0":{"620":1},"1":{"621":1,"622":1},"2":{"619":1,"622":1}}],["关卡分包加载",{"2":{"832":1}}],["关卡",{"2":{"832":1}}],["关于跨域问题",{"2":{"1097":1}}],["关于wasm代码对启动速度的影响",{"2":{"874":1}}],["关于他们的选择对于轻度游戏来说两者没有特别要求",{"2":{"829":1}}],["关于该工具在微信小游戏的使用请查阅使用",{"2":{"719":1}}],["关于该能力的使用请查阅使用profilingmemory分析内存",{"2":{"718":1}}],["关于该阶段耗时",{"2":{"530":1,"875":1}}],["关闭分包",{"0":{"1028":1},"2":{"1012":1}}],["关闭连接",{"2":{"981":1}}],["关闭hdr",{"2":{"726":1}}],["关闭",{"0":{"580":1},"2":{"984":1,"985":1}}],["关闭mipmap",{"2":{"362":1}}],["关闭readable",{"2":{"362":1}}],["写入文件系统",{"2":{"944":1}}],["写入版本b缓存",{"2":{"526":1}}],["写缓存时未删除同名旧缓存",{"2":{"180":1}}],["随机id",{"2":{"523":2}}],["随着游戏进度的推进",{"2":{"512":1}}],["随着wxsdk的更新",{"2":{"378":1}}],["传入url或文件相对路径",{"2":{"519":1}}],["传输大小与zip压缩后体积相当",{"2":{"460":1}}],["传输录制文件到pc",{"2":{"351":1}}],["总释放次数",{"2":{"970":1}}],["总分配次数",{"2":{"970":1}}],["总是使用异步接口从远程下载并使用",{"2":{"944":1}}],["总上限为20mb",{"2":{"893":1}}],["总耗时",{"2":{"826":1}}],["总面数比较高",{"2":{"814":1}}],["总卡顿时长xxxms",{"2":{"802":1}}],["总卡帧时长",{"2":{"801":1}}],["总文件大小=xxx",{"2":{"516":1}}],["总体而言",{"2":{"490":1}}],["耗时=xxms",{"2":{"1003":1}}],["耗时",{"2":{"515":3,"516":1,"526":1}}],["都支持",{"2":{"808":1}}],["都可认为需要自动缓存",{"2":{"515":1}}],["都有",{"2":{"431":1}}],["假设有后台接口",{"2":{"993":1}}],["假设有以下配置",{"2":{"513":1}}],["假设",{"2":{"992":1}}],["假设loading场景中a资源完成为1001",{"2":{"825":1}}],["假如游戏需要支持低档机型",{"2":{"724":1}}],["假如本地已经有streamingassets",{"2":{"513":1}}],["永不被自动清理",{"2":{"512":1}}],["累计资源体积可能会超过允许的最大值",{"2":{"512":1}}],["框架不会做额外计算来验证资源版本",{"2":{"510":1}}],["框架自动做缓存控制",{"2":{"501":1}}],["命名空间",{"2":{"981":1}}],["命名空间中的一切",{"2":{"975":1}}],["命名更替为",{"2":{"109":1}}],["命中子包的时机就可以相应延后",{"2":{"1016":1}}],["命中cdn缓存个数",{"2":{"798":1}}],["命中cdn缓存的数量",{"2":{"792":1}}],["命中本地缓存",{"2":{"515":1}}],["命中路径标识符的情况下",{"2":{"507":1}}],["判断",{"2":{"688":1}}],["判断是否需要自动缓存的文件",{"2":{"507":1}}],["判断是否走缓存",{"0":{"515":1},"2":{"500":1}}],["判定为下载bundle的路径标识符",{"2":{"507":1}}],["\`launchopera",{"2":{"621":2}}],["\`分隔",{"2":{"505":2}}],["\`",{"2":{"505":2}}],["业务自定义",{"2":{"1120":1}}],["业务自定下载",{"2":{"759":1,"1106":1,"1120":1}}],["业务无感知",{"2":{"999":1}}],["业务代码无需做任何调整",{"2":{"1094":1}}],["业务代码",{"2":{"725":1}}],["业务侧提高请求并发数",{"2":{"799":1}}],["业务侧",{"2":{"724":1}}],["业务侧注意在适当时机清理文件",{"2":{"529":1}}],["业务逻辑",{"2":{"717":1}}],["业务资源相关",{"2":{"505":1}}],["业务bundle资源",{"2":{"501":1}}],["五",{"0":{"523":1,"731":1,"827":1,"933":1,"939":1},"2":{"500":1}}],["四",{"0":{"514":1,"724":1,"826":1,"879":1,"901":1,"929":1,"946":1,"949":1},"1":{"515":1,"516":1,"880":1,"881":1,"882":1,"883":1,"930":1,"931":1,"932":1,"947":1,"948":1},"2":{"500":1}}],["示例demo",{"0":{"706":1},"1":{"707":1,"708":1}}],["示例拷贝至",{"2":{"704":1}}],["示例",{"0":{"513":1,"1009":1},"2":{"500":1,"825":1}}],["示例api",{"2":{"483":1}}],["识别不同版本的资源",{"2":{"510":1}}],["识别纹理资源版本",{"0":{"511":1},"2":{"500":1}}],["识别业务资源版本",{"0":{"510":1},"2":{"500":1}}],["三国吧兄弟",{"0":{"849":1}}],["三种方案",{"2":{"828":1}}],["三",{"0":{"504":1,"713":1,"738":1,"742":1,"777":1,"825":1,"878":1,"887":1,"897":1,"923":1,"945":1,"953":1},"1":{"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"714":1,"715":1,"716":1,"717":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"730":1,"739":1,"740":1,"741":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1,"752":1,"753":1,"778":1,"779":1,"780":1,"781":1,"782":1,"898":1,"899":1,"900":1,"924":1,"925":1,"926":1,"927":1,"928":1,"954":1,"955":1,"956":1,"957":1,"958":1,"959":1,"960":1,"961":1,"962":1,"963":1,"964":1,"965":1},"2":{"500":1}}],["哪些资源会自动缓存",{"0":{"503":1},"2":{"500":1,"799":2}}],["什么是高性能+模式",{"0":{"1084":1},"2":{"1082":1}}],["什么是高性能模式",{"0":{"1083":1},"2":{"1082":1}}],["什么是unity",{"0":{"951":1}}],["什么是addressable",{"0":{"919":1}}],["什么是异常级别",{"2":{"451":1}}],["什么情况触发资源缓存",{"0":{"502":1},"2":{"500":1}}],["介绍",{"0":{"501":1},"1":{"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"514":1,"515":1,"516":1,"517":1,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":1,"527":1,"528":1,"529":1},"2":{"500":1,"632":1,"633":1,"637":1,"640":1,"644":1,"645":1,"648":1,"651":1,"655":1,"656":1,"659":1,"660":1,"664":1,"667":1,"671":1,"672":1,"676":1,"677":1,"681":1,"682":1,"686":1,"687":1,"691":1}}],["大致与",{"2":{"1076":2}}],["大致流程如图",{"2":{"501":1}}],["大部分时候有奇效",{"2":{"1044":1}}],["大部分游戏收集",{"2":{"1036":1}}],["大部分设备将启动失败",{"2":{"727":1}}],["大体是将",{"2":{"1005":1}}],["大体与官网",{"2":{"1005":1}}],["大圣顶住",{"0":{"859":1}}],["大侠不哭",{"0":{"856":1}}],["大型游戏不建议使用addressable",{"2":{"831":1}}],["大型工程可能花费一些时间",{"2":{"398":1}}],["大量dc会造成非常大的cpu压力",{"2":{"751":1}}],["大小都为",{"2":{"1014":1}}],["大小为30mb的游戏占用内存为",{"2":{"724":1}}],["大小限制为200mb",{"2":{"498":1}}],["大概知道有哪些能力",{"2":{"626":1}}],["大多是因为在首场景执行了不必要的操作",{"2":{"533":1}}],["删除本地小游戏",{"2":{"1093":1}}],["删除掉相关事件监听",{"2":{"555":1}}],["删除文件",{"2":{"516":1,"526":1}}],["删除",{"2":{"516":1}}],["删除多线程用法",{"2":{"498":1}}],["删减多余代码",{"2":{"47":1}}],["策略",{"2":{"496":1}}],["角色",{"2":{"496":1}}],["牌类",{"2":{"496":1}}],["牌从门前过",{"2":{"423":3}}],["棋类",{"2":{"496":1}}],["棋牌等",{"2":{"758":1,"1113":1}}],["棋牌",{"2":{"496":1}}],["跑酷",{"2":{"496":1}}],["益智等",{"2":{"496":1}}],["塔防",{"2":{"496":1}}],["休闲类小游戏等",{"2":{"832":1}}],["休闲游戏为核心玩法",{"2":{"759":1,"1106":1,"1120":1}}],["休闲",{"2":{"496":1,"1135":1}}],["考虑到游戏体积与逻辑复杂度",{"2":{"496":1}}],["考虑到玩家平均下载带宽",{"2":{"440":1}}],["第二次导出的版本开始才可以使用",{"2":{"1040":1}}],["第二种方法",{"2":{"493":1}}],["第三方原生插件",{"2":{"712":1,"717":1}}],["第三方插件",{"2":{"498":1,"717":1,"725":1}}],["第一种方法",{"2":{"493":1}}],["升级引擎至2021使用astc压缩纹理",{"2":{"726":1}}],["升级",{"2":{"493":1}}],["存在大量依赖opengl",{"2":{"1076":1}}],["存在长耗时帧cost=xxxms",{"2":{"802":1}}],["存在稍微卡顿但可及时恢复播放",{"2":{"581":1}}],["存在http缓存",{"2":{"525":1}}],["存在业务的bundle资源和使用微信压缩纹理工具后的纹理资源",{"2":{"506":1}}],["存在这个问题",{"2":{"493":1}}],["存储",{"2":{"490":1,"543":1}}],["尽可能使用unload",{"0":{"948":1}}],["尽可能地设置lod",{"2":{"751":1}}],["尽快渲染让玩家看到游戏首画面",{"2":{"778":1}}],["尽量合并成",{"2":{"813":1}}],["尽量选择压缩比大的",{"2":{"813":1}}],["尽量用半精度",{"2":{"812":1}}],["尽量不要超过",{"2":{"813":1}}],["尽量不要再用环境反射立体贴图",{"2":{"811":1}}],["尽量不用",{"2":{"811":1}}],["尽量设置小一些",{"2":{"811":1}}],["尽量避免在各级resource包含资源",{"2":{"779":1}}],["尽量强制使用单声道音频",{"2":{"729":1}}],["尽量使用",{"2":{"815":1}}],["尽量使用压缩纹理",{"2":{"813":1}}],["尽量使用android",{"2":{"782":1}}],["尽量使用2022",{"2":{"497":1}}],["尽量使用云端存储",{"2":{"490":1}}],["尽管发布前进行了多数unity年限版本与常见机型的测试",{"2":{"400":1}}],["尽管你在导出期间动态的创建",{"2":{"383":1}}],["阻塞时间过长",{"2":{"794":1}}],["阻塞游戏线程",{"2":{"490":1}}],["阻止继续构建导出",{"2":{"383":1}}],["官网下载对应版本的",{"2":{"812":1}}],["官网下载对应的",{"2":{"479":1}}],["官方论坛的临时修复方案",{"2":{"1097":1}}],["官方demo",{"2":{"939":1}}],["官方提供的自动加载方案",{"2":{"829":1}}],["官方也提供了",{"2":{"556":1}}],["官方文档",{"2":{"434":1,"1133":1}}],["官方urp",{"2":{"432":2}}],["官方",{"2":{"427":1,"428":2,"433":1}}],["系统出现",{"2":{"1097":1}}],["系统和基础库要求是",{"2":{"1093":1}}],["系统字体字符集",{"0":{"1004":1}}],["系统字体",{"2":{"1001":1}}],["系统依然能够高效地找到准确的依赖进行打包",{"2":{"919":1}}],["系统自动启用引用计数",{"2":{"919":1}}],["系统",{"2":{"812":1}}],["系统平台之间的性能差异",{"0":{"736":1}}],["系统下使用",{"2":{"615":1}}],["系统下",{"0":{"479":1}}],["系列的格式",{"2":{"393":1}}],["打水印和下载过程可能会有一定耗时",{"2":{"1132":1}}],["打些日志来辅佐排查",{"2":{"709":1}}],["打包ab时文件名带hash",{"2":{"944":1}}],["打包bundle时",{"2":{"942":1}}],["打包参数加上buildassetbundleoptions",{"2":{"510":1}}],["打包在首资源包或bundle",{"2":{"474":1,"873":1}}],["打开拓展设置",{"2":{"1130":1}}],["打开插件开关后",{"2":{"1020":1}}],["打开插件调试日志",{"2":{"1003":1}}],["打开浏览器时",{"2":{"902":1}}],["打开游戏工程",{"2":{"836":1}}],["打开游戏圈",{"2":{"6":1}}],["打开unity",{"2":{"805":1,"902":1}}],["打开性能面板查看dynamicmemory",{"2":{"731":1}}],["打开广告",{"2":{"565":1}}],["打开chrome浏览器",{"2":{"531":1}}],["打开文件管理后进入applet",{"2":{"523":1}}],["打开文件夹",{"2":{"523":1}}],["打开导出目录",{"2":{"457":1}}],["打开vconsole",{"2":{"446":1,"965":1}}],["打开调试时正常",{"2":{"984":1}}],["打开调试",{"2":{"446":1,"459":1,"965":2}}],["打开调试模式",{"2":{"446":1,"965":1}}],["打开该窗口",{"2":{"429":1}}],["打开",{"2":{"428":2,"576":1,"613":1,"614":1,"1097":1}}],["打开配置面板",{"2":{"398":1}}],["打开bundle配置面板",{"2":{"395":1}}],["某些依赖平台的第三方插件",{"2":{"471":1}}],["能解决大部分问题",{"2":{"1046":1}}],["能不用光照",{"2":{"811":1}}],["能提升细碎文件的下载效率",{"2":{"799":1}}],["能准确反映游戏实际运行情况",{"2":{"739":1}}],["能够减少渲染的开销",{"2":{"816":1}}],["能够减少游戏的转化工时",{"2":{"557":1}}],["能够快速有效的将原生",{"2":{"557":1}}],["能写js脚本和c",{"0":{"473":1}}],["能否使用system",{"0":{"470":1,"472":1}}],["能力特性",{"0":{"572":1}}],["能力",{"2":{"498":1,"568":1,"577":1,"690":1,"761":1,"1107":1,"1120":1,"1122":1}}],["能力支持",{"0":{"498":1}}],["能力地图",{"2":{"464":1,"512":1,"523":1,"827":1,"834":1,"896":1,"1088":1,"1136":1}}],["能力隶属于微信压缩纹理工具的扩展范畴",{"2":{"399":1}}],["失败",{"2":{"468":1}}],["方可查看数据",{"2":{"827":1}}],["方法等信息",{"2":{"873":1}}],["方法二",{"0":{"837":1},"1":{"838":1}}],["方法一",{"0":{"835":1},"1":{"836":1}}],["方法",{"2":{"701":1}}],["方法实现导出",{"2":{"468":1}}],["方案特点",{"0":{"1134":1}}],["方案可以快速完成转化工作",{"2":{"829":1}}],["方案选择说明",{"0":{"829":1}}],["方案选择建议",{"0":{"557":1}}],["方案",{"2":{"811":1}}],["方案评估",{"0":{"495":1},"1":{"496":1,"497":1,"498":1}}],["方式直接修改",{"2":{"1010":1}}],["方式安装wxsdk",{"2":{"835":1}}],["方式安装",{"0":{"835":1},"1":{"836":1}}],["方式安装的一般无需改动",{"2":{"479":1}}],["方式进行按需加载与及时资源释放",{"2":{"833":1}}],["方式在游戏运行时异步按需下载",{"2":{"828":1}}],["方式完成",{"2":{"576":1}}],["方式2",{"2":{"459":1,"968":1}}],["方式1",{"2":{"459":1,"968":1}}],["添加插件",{"0":{"1130":1},"2":{"1130":1}}],["添加插件的报错信息添加插件",{"2":{"466":1}}],["添加到预下载列表中的文件",{"2":{"999":1}}],["添加需要导出的scene",{"2":{"891":1}}],["添加",{"2":{"555":1}}],["添加宏wx",{"2":{"429":1}}],["待审核确认",{"0":{"464":1}}],["代价是占用与文件同等大小的内存",{"2":{"712":1}}],["代表的运行能力越强",{"2":{"1087":1}}],["代表可缺省",{"2":{"667":1}}],["代表屏幕中间",{"2":{"629":1}}],["代表启动成功",{"2":{"612":1}}],["代表正在播放剧情",{"2":{"584":1,"600":1}}],["代表在",{"2":{"461":1}}],["代码将被编译并优化",{"2":{"1091":1}}],["代码包体积就发布上线可以吗",{"0":{"1100":1},"2":{"1082":1}}],["代码包进行拆分",{"2":{"1016":1}}],["代码体积限制",{"0":{"1091":1},"2":{"1082":1}}],["代码体积变大",{"2":{"302":1}}],["代码是在一个",{"2":{"1014":1}}],["代码是无法",{"2":{"451":1}}],["代码进行调试",{"2":{"1010":1}}],["代码经验",{"2":{"1010":1}}],["代码没有直接访问",{"2":{"975":1}}],["代码更新",{"0":{"909":1}}],["代码使用il2cpp生成cpp代码时",{"2":{"873":1}}],["代码分包+压缩纹理+unityheap预留这几种优化手段",{"2":{"1091":1,"1100":1}}],["代码分包",{"0":{"1012":1},"1":{"1013":1,"1014":1,"1015":1,"1016":1,"1017":1,"1018":1,"1019":1,"1020":1,"1021":1,"1022":1,"1023":1,"1024":1,"1025":1,"1026":1,"1027":1,"1028":1,"1029":1,"1030":1,"1031":1,"1032":1,"1033":1,"1034":1,"1035":1,"1036":1,"1037":1,"1038":1,"1039":1,"1040":1,"1041":1,"1042":1,"1043":1,"1044":1,"1045":1,"1046":1,"1047":1,"1048":1,"1049":1,"1050":1,"1051":1,"1052":1,"1053":1,"1054":1,"1055":1,"1056":1,"1057":1,"1058":1,"1059":1,"1060":1,"1061":1,"1062":1,"1063":1,"1064":1,"1065":1,"1066":1,"1067":1,"1068":1,"1069":1,"1070":1,"1071":1},"2":{"864":1,"1012":1,"1097":1}}],["代码与资源体积",{"0":{"761":1,"1107":1,"1122":1}}],["代码编译",{"2":{"822":1}}],["代码编译与运行时指令优化产生的内存",{"2":{"712":1}}],["代码编辑器打开当前工程目录",{"2":{"614":1}}],["代码启动较晚",{"2":{"602":1}}],["代码改动",{"2":{"431":1}}],["代码用",{"2":{"431":1}}],["代码增加宏定义wx",{"2":{"429":1}}],["代码",{"2":{"429":3,"430":1,"507":1,"1101":1}}],["代码示例",{"0":{"426":1,"1002":1}}],["代码配置微信压缩纹理工具用于执行的",{"2":{"409":1}}],["代码来替换或变更是更灵活自由的方案",{"2":{"381":1}}],["保持较高还原度",{"2":{"1134":1}}],["保持原引擎工具链与技术栈",{"2":{"1134":1}}],["保持端口为54998",{"2":{"805":1}}],["保持为不压缩",{"2":{"460":1}}],["保存后只需再次执行即可",{"2":{"398":1}}],["错误日志",{"2":{"567":1}}],["错误日志中的业务代码堆栈分析可参考文档",{"2":{"459":1}}],["错误解决办法",{"0":{"479":1}}],["错误调试与异常排查",{"0":{"444":1},"1":{"445":1,"446":1,"447":1,"448":1,"449":1,"450":1,"451":1,"452":1,"453":1}}],["功能相匹配",{"2":{"1076":2}}],["功能包括",{"2":{"951":1}}],["功能强大并且学习曲线变得平滑",{"2":{"920":1}}],["功能全面",{"2":{"808":1}}],["功能异常打开反馈入口",{"2":{"565":1}}],["功能",{"2":{"458":1}}],["切忌使用www",{"2":{"943":1}}],["切忌产生跳跃峰值",{"2":{"727":1}}],["切忌超出使用",{"2":{"727":1}}],["切忌在发布版本中使用",{"2":{"451":1}}],["切勿使用带cache能力的线管接口",{"0":{"947":1}}],["切勿使用微信开发者工具的",{"2":{"458":1}}],["切勿在start",{"2":{"530":1,"875":1}}],["二次访问通常删除本地微信小游戏包再次访问游戏可体验剧情内容",{"2":{"571":1}}],["二次启动最佳实践检测逻辑调整",{"2":{"99":1}}],["二",{"0":{"503":1,"712":1,"737":1,"776":1,"823":1,"870":1,"886":1,"892":1,"918":1,"944":1,"952":1},"1":{"824":1,"871":1,"872":1,"873":1,"874":1,"875":1,"876":1,"877":1,"893":1,"894":1,"895":1,"896":1,"919":1,"920":1,"921":1,"922":1},"2":{"500":1}}],["二维码",{"2":{"458":1}}],["找不到game",{"0":{"457":1}}],["找到水印工具",{"2":{"1130":1}}],["找到wasmcodesplit",{"2":{"1043":1}}],["找到项目的game",{"2":{"533":1}}],["找到",{"2":{"428":2,"614":1,"981":1}}],["类",{"2":{"976":1}}],["类也是这样",{"2":{"975":1}}],["类实现",{"2":{"539":1}}],["类似",{"2":{"453":1,"616":1,"670":1,"1005":1}}],["类型数据",{"2":{"981":2}}],["类型枚举",{"2":{"826":1}}],["类型中",{"2":{"667":1}}],["类型名",{"2":{"628":1}}],["类型主要包括以下几种",{"2":{"628":1}}],["类型约定",{"0":{"628":1}}],["类型从",{"2":{"431":1}}],["类型",{"2":{"353":1,"354":1,"355":1,"356":1,"358":1,"414":1,"417":1,"632":1,"637":1,"640":1,"644":1,"648":1,"651":1,"655":1,"659":1,"664":1,"667":1,"671":1,"676":1,"681":1,"686":1,"691":1}}],["个别游戏",{"0":{"1098":1},"2":{"1082":1}}],["个别游戏可能会接近",{"2":{"1032":1}}],["个别微信接口",{"2":{"491":1}}],["个全局变量进行判断的关键动作帧",{"2":{"685":1}}],["个属性能够按照持续时间完成渐变",{"2":{"675":1}}],["个",{"2":{"451":1,"550":1,"996":4}}],["结合操作系统",{"2":{"755":1,"1103":1}}],["结合profilingmem",{"2":{"731":1}}],["结合启动loader有以下优势",{"2":{"501":1}}],["结尾的脚本不会覆盖",{"2":{"618":1}}],["结构",{"2":{"591":1}}],["结构说明",{"0":{"377":1}}],["结束后互相调用",{"2":{"678":1}}],["结束开发模式",{"2":{"615":1}}],["结束",{"2":{"451":1}}],["虚拟机",{"2":{"451":1}}],["未知原因",{"2":{"1003":1}}],["未命中cdn缓存",{"2":{"799":1}}],["未开启http2",{"2":{"799":1}}],["未开通mp后台",{"2":{"523":1}}],["未使用预下载能力",{"2":{"793":1}}],["未使用wasm代码分包",{"2":{"790":2}}],["未压缩原始大小",{"2":{"789":1}}],["未上报游戏可交互上报的游戏",{"2":{"785":1}}],["未标注颜色指标值则表示当前指标项标准提升",{"2":{"762":1}}],["未前往mp后台",{"2":{"512":1}}],["未被捕捉的异常将抛给",{"2":{"451":1}}],["未弹框提示更新客户端",{"2":{"339":1}}],["yunser",{"2":{"1004":1}}],["yield",{"2":{"926":1,"927":1,"931":2,"934":1,"943":2,"945":1,"977":3,"995":1}}],["y",{"2":{"701":4,"707":6,"709":2,"1073":1}}],["yes",{"2":{"450":1}}],["your",{"2":{"383":1,"570":1}}],["步骤",{"0":{"968":1}}],["步骤二",{"0":{"576":1}}],["步骤一",{"0":{"575":1},"2":{"576":1}}],["步骤2",{"2":{"446":1,"965":1}}],["步骤1",{"2":{"446":1,"965":1}}],["除非后处理对画质很关键或游戏性能能支撑起后处理的开销",{"2":{"818":1}}],["除非是",{"2":{"809":1}}],["除非了解小程序更新机制",{"2":{"441":1}}],["除首资源包外进入游戏核心玩法所需的资源量",{"2":{"759":1,"1106":1,"1120":1}}],["除此外",{"2":{"565":2}}],["除在微信小游戏转换工具面板配置导出外",{"2":{"468":1}}],["除了在unity转换导出插件填写文件列表外",{"2":{"992":1}}],["除了常见的堆栈特征外",{"2":{"971":1}}],["除了静态场景外",{"2":{"927":1}}],["除了开发者需要确保使用可靠的cdn服务托管视频资源确保足够的输出带宽",{"2":{"581":1}}],["除了上面列举的功能",{"2":{"430":1}}],["除了",{"2":{"428":2,"429":1}}],["源代码中的函数名",{"2":{"452":1}}],["源站或者cdn加上不允许缓存的http头",{"2":{"441":1}}],["源码",{"2":{"431":1,"812":1}}],["跨域与ssl证书等问题",{"2":{"463":1}}],["跨域",{"2":{"440":1}}],["理论最大值",{"2":{"440":1}}],["理论上unityheap",{"2":{"974":1}}],["理论上",{"2":{"373":1}}],["超能世界",{"0":{"855":1}}],["超好玩的3d跑酷手游",{"2":{"847":1}}],["超休闲游戏256",{"2":{"727":1}}],["超过整包",{"2":{"1036":1}}],["超过",{"2":{"1032":1,"1037":1}}],["超过将会排队",{"2":{"999":1}}],["超过最大存储容量",{"2":{"521":1}}],["超过时底层自动排队",{"2":{"440":1}}],["超时默认为60s",{"2":{"440":1}}],["针对txt文件进行开启brotli或gzip压缩",{"2":{"440":1}}],["~",{"2":{"433":1,"599":2}}],["变体这部分开发者可以在定制的过程中剔除掉不需要的功能",{"2":{"433":1}}],["变体做剔除的",{"2":{"433":1}}],["变量值",{"2":{"681":1}}],["变量",{"2":{"430":1,"431":1}}],["变量中",{"2":{"406":1}}],["利用profilingmemory",{"2":{"967":1}}],["利用pc",{"2":{"351":1}}],["利用网络空闲期",{"2":{"928":1}}],["利用addressable进行更灵活和细粒度的拆解",{"2":{"928":1}}],["利用率",{"2":{"432":4}}],["且ip",{"2":{"902":1}}],["且有助于后续压缩纹理等优化工作的进行有效提升游戏运行性能",{"2":{"829":1}}],["且设置为以宽度作为缩放",{"2":{"707":1}}],["且开启纹理缓存后",{"2":{"503":1}}],["且url包含自动缓存路径标识符的文件",{"2":{"503":1}}],["且对性能有较大影响",{"2":{"453":1}}],["且程序未捕捉异常也有详细堆栈",{"2":{"453":1}}],["且引擎还会增加额外的底层异常检查",{"2":{"451":1}}],["且",{"2":{"432":2,"793":1,"799":4}}],["且请求了不同版本的资源时报错",{"2":{"71":1}}],["降级为使用离屏canvas渲染进度的方式",{"2":{"959":1}}],["降幅达到",{"2":{"432":2}}],["降低了游戏前期的发烫情况",{"2":{"1015":1}}],["降低总面数",{"2":{"814":1}}],["降低cpu消耗",{"0":{"782":1}}],["降低小游戏内存使用",{"0":{"781":1}}],["降低分辨率后可降低50",{"2":{"748":1}}],["降低版本更新时的流量消耗",{"2":{"501":1}}],["降低",{"2":{"386":1}}],["降低资源大小",{"2":{"353":1}}],["降低webcontent进程内存",{"2":{"31":1}}],["统计得出",{"2":{"762":1,"1111":1}}],["统计的数据",{"2":{"432":2}}],["统一资源cdn路径配置",{"2":{"285":1}}],["静默更新",{"0":{"911":1}}],["静置如下图",{"2":{"432":2}}],["静音状态对长音频在切换场景后无效的问题",{"2":{"138":1}}],["改用",{"2":{"829":1}}],["改造原有tcp服务兼容wss服务",{"2":{"982":1}}],["改造最后几行即可",{"2":{"533":1}}],["改造小游戏代码",{"2":{"533":1}}],["改动详情可参考源代码",{"2":{"431":1}}],["改为false可盖住黑屏",{"2":{"959":1}}],["改为",{"2":{"431":1,"981":1}}],["影响该步骤包括",{"2":{"988":1}}],["影响游戏的呈现速度因素中如首资源包的下载往往占比较大",{"2":{"538":1}}],["影响异常错误的导出选项",{"0":{"450":1},"1":{"451":1,"452":1,"453":1}}],["影响",{"2":{"431":1}}],["影响安卓帧率",{"2":{"215":1}}],["函数堆栈是不可读的函数id",{"2":{"446":1}}],["函数",{"2":{"431":4,"619":1,"889":1}}],["替代",{"2":{"431":1}}],["替换成通过",{"2":{"697":1}}],["替换加载图片",{"2":{"418":1}}],["替换unity",{"2":{"108":1}}],["运行日志或小游戏云测试获取性能数据",{"2":{"1109":1}}],["运行发烫的小游戏",{"2":{"1088":1}}],["运行一段时间后设备温度持续上升",{"2":{"1083":1}}],["运行模式是无",{"2":{"1083":1}}],["运行阶段",{"2":{"885":1,"1118":1}}],["运行10mins内存峰值",{"2":{"763":1}}],["运行",{"2":{"760":1,"1112":1}}],["运行中的这种行为会造成明显的帧率卡顿问题",{"2":{"749":1}}],["运行环境以cr识别+随机点击",{"2":{"741":1}}],["运行性能以及启动耗时等信息",{"2":{"771":1}}],["运行性能",{"0":{"1110":1},"2":{"763":1,"764":1,"1106":1,"1114":1,"1115":1,"1121":1,"1123":1,"1124":1}}],["运行性能会极大影响可承载的游戏内容玩法",{"2":{"733":1}}],["运行性能概述",{"0":{"733":1},"1":{"734":1,"735":1,"736":1}}],["运行性能及调优",{"0":{"548":1}}],["运行时配置",{"0":{"993":1},"1":{"994":1,"995":1}}],["运行时unityloader将根据列表内容在网络空闲期下载",{"2":{"991":1}}],["运行时loadfromfile",{"2":{"944":1}}],["运行时application",{"2":{"893":1}}],["运行时的网络和接口调用",{"2":{"771":1}}],["运行时需进行编译执行",{"2":{"725":1}}],["运行时赋值false可提前终止延迟执行",{"2":{"671":1}}],["运行在浏览器环境",{"2":{"712":1}}],["运行的入口文件",{"2":{"576":1}}],["运行提示大量shader编译错误",{"0":{"477":1}}],["运行报错",{"2":{"274":1,"281":1}}],["运动向量或运动模糊",{"2":{"431":1}}],["屏幕适配",{"0":{"1072":1},"1":{"1073":1,"1074":1},"2":{"543":1}}],["屏幕空间阴影",{"2":{"430":1}}],["屏蔽了",{"2":{"431":1}}],["清理后写入版本a",{"2":{"526":1}}],["清理成功",{"2":{"521":1}}],["清理文件缓存的结果",{"2":{"521":1}}],["清理所有自动缓存的文件",{"2":{"520":1}}],["清理旧缓存或达到缓存上限时删除文件",{"2":{"516":1}}],["清理同名文件旧缓存",{"2":{"516":1}}],["清理时",{"2":{"513":1}}],["清理掉同名旧文件",{"2":{"513":1}}],["清理缓存时是否可被自动清理",{"2":{"512":1}}],["清理缓存时默认额外清理的大小",{"2":{"353":1,"505":1}}],["清理出所需大小",{"2":{"512":1}}],["清漆效果",{"2":{"431":1}}],["细节纹理",{"2":{"431":1}}],["镂空功能",{"2":{"431":1}}],["镂空",{"2":{"431":1}}],["级联数也是建议",{"2":{"811":1}}],["级的",{"2":{"431":1}}],["级",{"2":{"431":1,"811":1}}],["额外开销",{"2":{"431":1}}],["额外的光照信息可以烘焙到",{"2":{"811":1}}],["额外的光照",{"2":{"431":1}}],["额外的光源",{"2":{"430":1}}],["裁剪掉的功能",{"2":{"433":1}}],["裁剪了",{"2":{"431":1}}],["裁剪软阴影",{"2":{"431":1}}],["裁剪支持",{"2":{"431":1}}],["裁剪",{"2":{"431":38}}],["供参考的",{"0":{"431":1},"2":{"430":2}}],["雾效",{"2":{"430":1,"431":1}}],["看首包的减少量即可",{"2":{"1034":1}}],["看发烫是否有改善",{"2":{"817":1}}],["看下默认材质shader",{"2":{"812":1}}],["看到游戏界面后stop",{"2":{"533":1}}],["看是否去掉",{"2":{"430":7}}],["看工具的提示",{"2":{"374":1}}],["简单的上手操作",{"2":{"847":1}}],["简单配置即可",{"2":{"808":1}}],["简单来说",{"2":{"451":1}}],["简化过的材质对性能更好",{"2":{"812":1}}],["简化",{"2":{"431":1}}],["简化了",{"2":{"431":4}}],["简化级联阴影",{"2":{"431":1}}],["简化阴影",{"2":{"430":1}}],["简化计算等",{"2":{"430":1}}],["简介与原理",{"2":{"945":1}}],["简介",{"0":{"376":1}}],["半宽韩文字母",{"2":{"1004":1}}],["半宽平假名",{"2":{"1004":1}}],["半宽片假名",{"2":{"1004":1}}],["半透明物体投射阴影",{"2":{"431":1}}],["半精度利用率",{"2":{"432":2}}],["半精度",{"2":{"430":1}}],["半角分号分隔",{"2":{"353":3}}],["多半由于跨域问题导致",{"2":{"1096":1}}],["多次使用onmessage时needinfo以第一个onmessage为准",{"2":{"979":1,"983":1}}],["多大的内存是合理的呢",{"2":{"711":1}}],["多线程",{"2":{"498":1,"814":2}}],["多余的",{"2":{"430":1}}],["多光源分簇渲染",{"2":{"430":1}}],["多光源管理等",{"2":{"427":1}}],["属性自己选择透明的图片即可",{"2":{"699":1}}],["属性修改",{"0":{"662":1},"1":{"663":1,"664":1,"665":1,"666":1,"667":1,"668":1}}],["属性设置为",{"2":{"635":1}}],["属性名",{"2":{"632":1,"637":1,"640":1,"644":1,"648":1,"651":1,"655":1,"659":1,"664":2,"667":1,"671":1,"676":1,"681":1,"686":1,"691":1}}],["属性决定了该帧的真实视图表现",{"2":{"621":1}}],["属性是从关键动作帧激活的那一刻起被赋予其特定的值",{"2":{"621":1}}],["属性",{"0":{"621":1,"632":1,"637":1,"640":1,"644":1,"648":1,"651":1,"655":1,"659":1,"664":1,"667":1,"671":1,"676":1,"681":1,"686":1,"691":1},"2":{"430":1,"620":1,"622":1,"807":1}}],["材质shader",{"2":{"812":1}}],["材质和shader",{"0":{"812":1}}],["材质可参考",{"2":{"811":1}}],["材质比较简单",{"2":{"807":1}}],["材质",{"2":{"430":1,"431":1,"812":1}}],["光照材质尽量简单",{"2":{"811":1}}],["光照和阴影",{"0":{"811":1}}],["光照计算尤其是",{"2":{"809":1}}],["光照贴图",{"2":{"430":1}}],["光照探头",{"2":{"430":1}}],["光照分簇渲染",{"2":{"430":1}}],["反射探头",{"2":{"430":1}}],["反馈与投诉",{"2":{"565":1}}],["反馈",{"2":{"426":1}}],["基于webassembly技术",{"2":{"1133":1}}],["基于2022",{"2":{"905":1}}],["基于业务侧统计",{"2":{"798":1}}],["基于异步干预剧情发展",{"0":{"577":1},"2":{"576":1}}],["基于",{"2":{"468":1,"808":1,"829":1,"1076":1}}],["基本就会内存",{"2":{"1031":1}}],["基本就可以测试和发布了",{"2":{"1027":1}}],["基本拉丁语",{"2":{"1004":1}}],["基本汉字",{"2":{"1004":1}}],["基本设置",{"2":{"899":1,"914":1}}],["基本兼容",{"2":{"807":1}}],["基本上只可能是没调用",{"2":{"709":1}}],["基本上不上",{"2":{"430":1}}],["基本概念",{"0":{"619":1},"1":{"620":1,"621":1,"622":1,"623":1,"624":1,"625":1}}],["基本一个主方向光就够了",{"2":{"430":1}}],["基础模板",{"2":{"377":3}}],["基础模板不建议开发者进行编辑",{"2":{"377":1}}],["基础库版本分布",{"2":{"1006":1}}],["基础库介绍",{"2":{"1006":1}}],["基础库+canvas",{"2":{"712":1}}],["基础库",{"0":{"1006":1},"1":{"1007":1},"2":{"369":2,"1093":1}}],["圆柱状投影",{"2":{"430":1}}],["胶片颗粒",{"2":{"430":1}}],["宏关闭",{"2":{"430":1}}],["宏是",{"2":{"429":1}}],["宏",{"2":{"429":1,"430":1}}],["宏来开启的",{"2":{"429":1}}],["宏观来说你开启了cdn压缩情况下",{"2":{"407":1}}],["没有比较大的代码修改的情况下",{"2":{"1024":1}}],["没有看到增量分包的界面",{"0":{"1040":1},"2":{"1012":1}}],["没有设置",{"2":{"622":1}}],["没有弹出输入法",{"0":{"483":1}}],["没有定义",{"2":{"429":1}}],["没有实际影响",{"2":{"367":1}}],["标识asset",{"2":{"920":1}}],["标记大长帧出现的位置",{"2":{"800":1}}],["标签页",{"2":{"429":1}}],["标准的微信小游戏",{"2":{"1083":1}}],["标准的cdn服务会支持http2协议",{"2":{"407":1}}],["标准渲染管线",{"2":{"751":1}}],["标准渲染管线在",{"2":{"726":1}}],["标准模板",{"2":{"384":2}}],["脚本开发渲染管线",{"2":{"808":1}}],["脚本定制渲染管线",{"2":{"808":1}}],["脚本尝试用一些途径来确定后续的剧情发展",{"2":{"577":1}}],["脚本实现",{"2":{"574":1}}],["脚本文件",{"2":{"479":1}}],["脚本提供的",{"2":{"468":1}}],["脚本环境就会有宏wx",{"2":{"429":1}}],["脚本增加宏定义wx",{"2":{"429":1}}],["脚本",{"2":{"429":1,"614":1}}],["脚本来执行构建模板相关的设计",{"2":{"383":1}}],["也有开发者问道",{"2":{"984":1}}],["也在发布之后",{"2":{"911":1}}],["也可使用高性能+模式处理",{"2":{"1097":1}}],["也可通过联系我们添加",{"2":{"844":1}}],["也可以引入sdk",{"2":{"1074":1}}],["也可以使用http",{"2":{"984":1}}],["也可以使用",{"2":{"978":1}}],["也可以选择完整的",{"2":{"705":1}}],["也可以创建后再修改其属性",{"2":{"621":1}}],["也可以在生成的game",{"2":{"992":1}}],["也可以在",{"2":{"576":1}}],["也可以再用",{"2":{"430":1}}],["也不支持",{"2":{"814":1}}],["也足够",{"2":{"807":1}}],["也就是屏幕的大小",{"2":{"1073":1}}],["也就是选择之前的某个包作为参考",{"2":{"1024":1}}],["也就是",{"2":{"701":1}}],["也就意味着",{"2":{"629":1}}],["也就意味着如下设置只有最后一个是生效的",{"2":{"621":1}}],["也对网络情况做了三个级别的分级",{"2":{"581":1}}],["也无效",{"2":{"451":1}}],["也无法捕捉任何异常",{"2":{"451":1}}],["也方便知道自己修改了哪些内容",{"2":{"429":1}}],["也支持更多的调试工具",{"2":{"905":1,"907":1}}],["也支持时间段内的汇总信息",{"2":{"739":1}}],["也支持从本地加载",{"2":{"428":1}}],["也支持",{"2":{"365":1}}],["接受阴影的物体要区分开",{"2":{"811":1}}],["接受",{"2":{"599":1}}],["接入",{"2":{"982":1}}],["接入流程请参考文档unity",{"2":{"886":1}}],["接入流程",{"0":{"886":1}}],["接入方式",{"0":{"574":1},"1":{"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1}}],["接入微信api",{"0":{"543":1}}],["接入更多平台能力",{"2":{"534":1}}],["接下来的问题是",{"2":{"917":1}}],["接下来请你使用",{"2":{"614":1}}],["接下来",{"2":{"429":1}}],["接下来需要准备条件编译宏",{"2":{"428":1}}],["接口用于加载后备",{"2":{"1001":1}}],["接口",{"2":{"956":1,"995":1}}],["接口setpreloadlist",{"2":{"167":1}}],["接口setdatacdn",{"2":{"167":1}}],["接口名变更",{"2":{"109":1}}],["就需要明确告诉开放数据域",{"2":{"707":1}}],["就会显得很麻烦",{"2":{"705":1}}],["就会被替换成",{"2":{"701":1}}],["就可以继续点生成profile分包或者生成release分包",{"2":{"1027":1}}],["就可以了",{"2":{"629":1}}],["就可以在",{"2":{"429":1}}],["就无法直接使用",{"2":{"629":1}}],["就好了",{"2":{"428":1}}],["就是确定哪些异常由引擎捕捉",{"2":{"451":1}}],["就是",{"2":{"428":1}}],["否则会导致下载浪费",{"2":{"999":1}}],["否则会自动引入官方的core",{"2":{"428":1}}],["否则下载永远不会完成",{"2":{"977":1}}],["否则您的应用程序将冻结",{"2":{"977":1}}],["否则请参考前文手动",{"2":{"902":1}}],["否则可能会有额外的api",{"2":{"812":1}}],["否则可能导致旧版本游戏的用户运行报错",{"2":{"441":1}}],["否则文件将会一直在缓存目录中",{"2":{"529":1}}],["否则返回空字符串",{"2":{"519":1}}],["否则无法显示",{"2":{"959":1}}],["否则无法按照前文的缓存规则获得资源的唯一标识",{"2":{"513":1}}],["否则无效",{"2":{"513":1,"899":1}}],["否则遵循兜底策略",{"2":{"405":1}}],["顺序不能反",{"2":{"428":1}}],["左端",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["左上角",{"2":{"428":1}}],["左右",{"2":{"355":1,"532":1,"1014":2}}],["再使用水印插件对分包后的wasm代码打水印",{"2":{"1127":1}}],["再使用同版本的压缩纹理工具完成后续操作",{"2":{"394":1}}],["再打开分包",{"2":{"1044":1}}],["再进行收集",{"2":{"1037":1}}],["再多跑几次收集",{"2":{"1027":1}}],["再异步加载剩下的分包",{"2":{"1014":1}}],["再编译",{"2":{"1014":1}}],["再不支持使用微信系统字体时",{"2":{"1000":1}}],["再调整到游戏中合适的位置",{"2":{"699":1}}],["再创建一个淡入的动画",{"2":{"678":1}}],["再次观察",{"2":{"622":1}}],["再次执行",{"2":{"615":1}}],["再次点击",{"2":{"428":1}}],["再下载版本b",{"2":{"526":1}}],["再执行写入",{"2":{"509":1}}],["号按钮",{"2":{"428":2}}],["稍等一会",{"2":{"428":1}}],["带有吸引力的游戏玩法视频",{"0":{"1126":1}}],["带圈或括号的字母数字",{"2":{"1004":1}}],["带你探索不一样的魔幻体验",{"2":{"848":1}}],["带上广告相关自定义参数",{"2":{"824":1}}],["带上相关query",{"2":{"708":1}}],["带的版本号不一样",{"2":{"428":1}}],["带datafilesubprefix时ios首包资源下载bug",{"2":{"222":1}}],["配套unity",{"2":{"428":1}}],["配置方式",{"0":{"989":1},"1":{"990":1,"991":1,"992":1,"993":1,"994":1,"995":1}}],["配置unity",{"0":{"953":1},"1":{"954":1,"955":1,"956":1,"957":1,"958":1,"959":1,"960":1,"961":1,"962":1,"963":1,"964":1,"965":1}}],["配置首包资源加载路径",{"2":{"900":1}}],["配置加载与协议解析",{"0":{"743":1}}],["配置外显进度条",{"2":{"580":1}}],["配置本地剧本路径",{"2":{"576":1}}],["配置工作需要在该回调中使用",{"2":{"576":1}}],["配置启动剧情",{"0":{"576":1}}],["配置解析操作",{"2":{"533":1}}],["配置到不自动缓存文件类型中的文件",{"2":{"523":1}}],["配置到预下载列表的文件",{"2":{"503":1}}],["配置",{"2":{"505":2}}],["配置错误",{"2":{"408":1}}],["配置项中",{"2":{"393":1}}],["配置项支持列表",{"2":{"392":1}}],["配置文件内容的做针对性的修改",{"2":{"380":1}}],["配置文件说明",{"0":{"352":1},"1":{"353":1,"354":1,"355":1,"356":1,"357":1,"358":1}}],["配置构建模板",{"0":{"375":1},"1":{"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"383":1,"384":1}}],["配置顺序调整",{"2":{"285":1}}],["项目首次使用插件默认会启用打水印功能",{"2":{"1131":1}}],["项目为常见到使用范例",{"2":{"1009":1}}],["项目发布为webgl或转换为小游戏时unity会自动拷贝bundle文件到最终的生成目录下",{"2":{"937":1}}],["项目在使用2018",{"2":{"907":1}}],["项目使用2017",{"2":{"907":1}}],["项目使用了小游戏unity适配插件",{"2":{"896":1}}],["项目转换",{"0":{"536":1},"1":{"537":1,"538":1,"539":1,"540":1,"541":1},"2":{"534":1}}],["项目报failed",{"0":{"479":1}}],["项目工程的",{"2":{"428":1}}],["项目名称",{"2":{"353":1}}],["右上方",{"2":{"836":1}}],["右上角打开调试",{"2":{"1097":1}}],["右上角菜单",{"2":{"446":1,"965":1}}],["右上角",{"2":{"351":1,"459":1}}],["右下角跳过贴图",{"2":{"657":1}}],["右端",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["右键审查元素或者按f12即可打开控制台界面",{"2":{"531":1}}],["右小角有",{"2":{"428":1}}],["列表会有",{"2":{"428":1}}],["列表总览",{"2":{"362":1}}],["一款开源的资源查看工具",{"2":{"880":1}}],["一款独具创新的魔幻三消策略小游戏",{"2":{"848":1}}],["一款代码",{"2":{"724":1}}],["一次性设置",{"2":{"666":1}}],["一个用于启动加载",{"2":{"1014":1}}],["一个用于启动加载另一个将被延迟加载",{"2":{"550":1}}],["一个广告类型可以投放不同素材",{"2":{"824":1}}],["一个广告位可以投放不同类型的广告",{"2":{"824":1}}],["一个位于底部居中的",{"2":{"678":1}}],["一个全屏的透明区域",{"2":{"661":1}}],["一个专业的javascript代码编辑器",{"2":{"608":1}}],["一种推荐的配置",{"2":{"591":1}}],["一种解决办法",{"2":{"479":1}}],["一些应用场景反而不如js轻量",{"2":{"735":1}}],["一些游戏前期的资源已经不需要再被使用",{"2":{"512":1}}],["一些配置文件不希望被自动清理",{"0":{"529":1},"2":{"500":1}}],["一些功能",{"2":{"430":1}}],["一",{"0":{"502":1,"711":1,"733":1,"775":1,"822":1,"867":1,"885":1,"891":1,"917":1,"941":1,"951":1},"1":{"734":1,"735":1,"736":1,"868":1,"869":1,"942":1,"943":1},"2":{"500":1}}],["一旦命中异常即使",{"2":{"451":1}}],["一栏会看到core",{"2":{"428":1}}],["一栏显示的是",{"2":{"428":1}}],["一般先尝试关闭分包",{"2":{"1044":1}}],["一般就是没问题的",{"2":{"1037":1}}],["一般就主",{"2":{"816":1}}],["一般ios高性能模式才有内存使用瓶颈",{"2":{"1034":1}}],["一般分包后wasm首包可以控制在原包的1",{"2":{"1034":1}}],["一般首包函数有整包个数的",{"2":{"1032":1}}],["一般跑完这两个步骤首包函数占整包函数个数的30",{"2":{"1026":1}}],["一般需要android和ios单独收集",{"2":{"1026":1}}],["一般小游戏的",{"2":{"1014":1}}],["一般都是",{"2":{"814":1,"889":1}}],["一般考虑效果",{"2":{"813":1}}],["一般涉及到坐标值",{"2":{"812":1}}],["一般是为了实现遮罩等效果用的",{"2":{"812":1}}],["一般是通过",{"2":{"697":1}}],["一般建议只用一盏方向光",{"2":{"811":1}}],["一般来说",{"2":{"805":1}}],["一般大小较大",{"2":{"799":1}}],["一般真机上渲染是正常的",{"2":{"493":1}}],["一般重启一下",{"2":{"428":1}}],["一般不需要手动更新",{"2":{"1042":1}}],["一般不需要访问纹理像素",{"2":{"363":1}}],["一般不更换",{"2":{"421":1}}],["一般不修改",{"2":{"421":1}}],["一般这种情况都是服务端设置问题",{"2":{"370":1}}],["窗口使用sql进行数据统计和分析",{"2":{"971":1}}],["窗口的",{"2":{"433":1}}],["窗口选择",{"2":{"429":1}}],["窗口找到",{"2":{"428":1}}],["窗口",{"2":{"428":4}}],["菜单选择",{"2":{"429":1}}],["菜单",{"2":{"428":1}}],["菜单栏",{"2":{"360":1,"836":1,"1043":1,"1046":1}}],["点三次下方的",{"2":{"1097":1}}],["点启用代码分包",{"2":{"1019":1}}],["点开",{"2":{"428":1}}],["点击关闭水印",{"2":{"1131":1}}],["点击关闭代码分包即可",{"2":{"1028":1}}],["点击上传按钮后",{"2":{"1131":1}}],["点击显示水印插件面板",{"2":{"1131":1}}],["点击开通高性能模式",{"2":{"1088":1}}],["点击开发者工具的预览",{"2":{"1026":1}}],["点击获取",{"2":{"1043":1}}],["点击进入详情页",{"2":{"1043":1}}],["点击安装",{"2":{"1043":1}}],["点击后即可进入插件页",{"2":{"1020":1}}],["点击性能面板左上角的",{"2":{"968":1}}],["点击预览",{"2":{"896":1}}],["点击生成并转换按钮",{"2":{"893":1}}],["点击录制按钮",{"2":{"804":1}}],["点击调试器",{"2":{"804":1}}],["点击继续",{"2":{"678":2}}],["点击事件",{"2":{"657":1,"661":1}}],["点击名称可快速查阅说明",{"2":{"627":1}}],["点击屏幕触发真正的开始游戏逻辑",{"2":{"533":1}}],["点击load导入步骤2的profile文件",{"2":{"531":1}}],["点击右上角菜单",{"2":{"531":1}}],["点击vconsole打开日志面板",{"2":{"446":1,"965":1}}],["点击+号",{"2":{"429":1}}],["点击左上角",{"2":{"428":1}}],["点击",{"2":{"374":1,"395":1,"893":1,"926":1}}],["相同md5的小游戏包会复用同一份分包结果",{"2":{"1019":1}}],["相同参数情况下",{"2":{"416":1}}],["相对于app常用的loadfromfile",{"2":{"948":1}}],["相对于assetsbundles的优势",{"0":{"920":1}}],["相对于原生app",{"2":{"775":1}}],["相对于用户反馈日志",{"2":{"566":1}}],["相对而言",{"2":{"711":1}}],["相比较于",{"2":{"666":1}}],["相当于opengles2",{"2":{"498":1}}],["相机缩放会引入额外的",{"2":{"431":1}}],["相关日志",{"0":{"1003":1}}],["相关代码",{"2":{"812":1}}],["相关属性",{"2":{"666":1}}],["相关下载",{"2":{"537":1}}],["相关手册",{"2":{"535":1,"537":1,"538":1,"539":1,"540":1,"541":1,"543":1,"544":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"829":1}}],["相关配置",{"0":{"505":1},"1":{"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1},"2":{"500":1}}],["相关",{"0":{"815":1,"888":1},"1":{"889":1},"2":{"430":1}}],["相关功能",{"2":{"430":1}}],["相关pass",{"2":{"430":1,"431":1}}],["相关的",{"2":{"428":1}}],["相关的编程知识",{"2":{"427":1}}],["和开发者工具却可以下载则参考",{"2":{"1097":1}}],["和函数个数相关",{"2":{"1045":1}}],["和lauxlib",{"2":{"973":1}}],["和志同道合的伙伴携手闯仗剑走天涯",{"2":{"856":1}}],["和阴影都是关闭的",{"2":{"811":1}}],["和检测完成时两个结果",{"2":{"791":1}}],["和",{"2":{"427":1,"428":9,"429":3,"430":1,"431":10,"433":1,"523":1,"753":1,"762":1,"807":2,"811":1,"812":1,"814":1,"889":1,"922":1,"983":1,"1031":1,"1111":1}}],["和微信小游戏大部分后端服务可以直接复用",{"2":{"373":1}}],["那就还要继续收集+生成分包",{"2":{"1029":1}}],["那是最好",{"2":{"816":1}}],["那也可以用",{"2":{"812":1}}],["那条线也就是主故事线了",{"2":{"625":1}}],["那会方便很多",{"2":{"429":1}}],["那些用不到的功能在运行时可能也会有性能开销",{"2":{"427":1}}],["那么主场景",{"2":{"926":1}}],["那么可以尝试设置",{"2":{"817":1}}],["那么可以通过",{"2":{"814":1}}],["那么可通过以下两种方法之一来获得可读函数名",{"2":{"446":1}}],["那么就选择",{"2":{"813":1}}],["那么用投射平面阴影的方式来表现阴影",{"2":{"811":1}}],["那么尽量用烘焙",{"2":{"811":1}}],["那么选择了",{"2":{"809":1}}],["那么必须要用",{"2":{"807":1}}],["那么这里的",{"2":{"707":1}}],["那么",{"2":{"513":1,"614":1,"709":1,"711":1,"807":1,"815":1,"917":1,"926":2,"927":1}}],["那么需要一个手段来区分资源版本",{"2":{"509":1}}],["那么应该是使用了定制",{"2":{"433":1}}],["那么渲染结果基本一致的",{"2":{"433":1}}],["那么在",{"2":{"429":1}}],["那么在新版本wxsdk导入后可能会引起部分功能表现异常",{"2":{"378":1}}],["那么只会影响到",{"2":{"429":1}}],["那么不要使用此选项",{"2":{"351":1}}],["直到帧率下降到特定数值",{"2":{"1087":1}}],["直到结束剧本设计",{"2":{"612":1}}],["直接转换成小游戏包",{"2":{"885":1}}],["直接调用malloc产生",{"2":{"717":1}}],["直接用的",{"2":{"433":1}}],["直接用官方",{"2":{"427":1}}],["直观的结构",{"2":{"377":1}}],["诸如延迟渲染",{"2":{"427":1}}],["管线一般而言",{"2":{"430":1}}],["管线除了具备",{"2":{"427":1}}],["管线基础上",{"2":{"427":1}}],["管线",{"0":{"427":1,"430":1},"1":{"428":1,"429":1,"430":1,"431":2,"432":2,"433":1,"434":1},"2":{"427":2,"429":1,"431":1,"808":1}}],["实时检测更新",{"0":{"913":1}}],["实时日志为帮助小程序开发者快捷地排查小程序漏洞",{"2":{"566":1}}],["实时日志",{"2":{"566":1}}],["实例化来合并",{"2":{"815":1}}],["实例化",{"0":{"746":1}}],["实践指南",{"0":{"558":1},"2":{"538":1,"829":2}}],["实际发起请求的url为data",{"2":{"997":1}}],["实际发起预载请求的url采用填写的地址",{"2":{"997":1}}],["实际不会发起网络请求",{"2":{"944":1}}],["实际运行可限帧30以保持长时间挂机运行的发热量",{"2":{"737":1}}],["实际上有些函数可能只是调用比较冷门",{"2":{"1032":1}}],["实际上大部分unity版本都可正常使用",{"2":{"919":1}}],["实际上描述一个组件在屏幕中的位置有时不需要将5个属性完全设置",{"2":{"629":1}}],["实际上最特殊的关键动作帧",{"2":{"622":1}}],["实际上你可以直接执行",{"2":{"616":1}}],["实际游戏永远不要让单个文件这么大",{"2":{"440":1}}],["实际首包资源加载方式会根据包体决定",{"2":{"437":1}}],["实际使用中请自行更改",{"2":{"426":1}}],["实现原理",{"0":{"1016":1},"2":{"1012":1}}],["实现变更可能会导致适配问题",{"2":{"907":1}}],["实现",{"2":{"629":1}}],["实现资源的管理",{"2":{"557":1}}],["实现网络通信",{"2":{"539":1}}],["实现默认效果很简单",{"2":{"422":1}}],["实现硬件解码",{"2":{"386":1}}],["实现一个云函数",{"2":{"374":1}}],["与转换面板配置有对应关系的配置项",{"0":{"899":1}}],["与此帧网络并发",{"2":{"804":1}}],["与原有标准一致",{"2":{"762":1}}],["与历史评测标准相比",{"2":{"762":1}}],["与ios普通模式大概率启动失败",{"2":{"727":1}}],["与剧情内部",{"2":{"679":1}}],["与上面的写法实际效果完全一样",{"2":{"621":1}}],["与app游戏不同",{"2":{"501":1}}],["与",{"2":{"453":1,"549":1,"629":1,"805":1,"902":1,"968":1}}],["与浏览器脚本交互进行自定义定制",{"2":{"424":1}}],["与步骤1相似",{"2":{"351":1}}],["​\\t示例中的",{"2":{"426":1}}],["​\\t\\t不同的游戏所需要的性能不尽相同",{"2":{"830":1}}],["​\\t\\t不会",{"2":{"407":1}}],["​\\t\\taa",{"2":{"829":1}}],["​\\t\\tastc",{"2":{"393":1}}],["​\\t\\t目前分包将基于",{"2":{"828":1}}],["​\\t\\t经过",{"2":{"560":1}}],["​\\t\\t请前往",{"2":{"558":1}}],["​\\t\\tinstant",{"2":{"557":2,"829":1}}],["​\\t\\t除常规使用",{"2":{"556":1}}],["​\\t\\t现网错误日志上报与排查",{"2":{"552":1}}],["​\\t\\t审核发布可参考",{"2":{"552":1}}],["​\\t\\t由于",{"2":{"551":1}}],["​\\t\\t纹理压缩对于",{"2":{"549":1}}],["​\\t\\t纹理资源的",{"2":{"392":1}}],["​\\t\\t游戏转化完成后仍需要对各项的性能指标进行量化测试",{"2":{"548":1}}],["​\\t\\t游戏导出小游戏包",{"2":{"540":1}}],["​\\t\\t根据统计数据反应",{"2":{"546":1}}],["​\\t\\t截止本阶段",{"2":{"545":1}}],["​\\t\\tunity",{"2":{"543":1,"550":1}}],["​\\t\\t区别于原生环境",{"2":{"539":1}}],["​\\t\\t区别于原生",{"2":{"538":1,"828":1}}],["​\\t\\t阅读",{"2":{"537":1}}],["​\\t\\t本节内容将指引开发者如何让自己的游戏工程在微信小游戏平台成功运行",{"2":{"536":1}}],["​\\t\\t本地安装官方",{"2":{"409":1}}],["​\\t\\t新计划接入游戏的开发者应阅读本节相关手册内容",{"2":{"535":1}}],["​\\t\\t新版本已不再依赖",{"2":{"390":1}}],["​\\t\\t下图中介绍了新游戏接入微信小游戏平台的主要转换流程",{"2":{"534":1}}],["​\\t\\t下载并安装",{"2":{"390":1}}],["​\\t\\t获取微信压缩纹理工具所能扫描到的符合条件的ab包路径数组",{"2":{"416":1}}],["​\\t\\t执行微信压缩纹理流程",{"2":{"413":1}}],["​\\t\\t执行完上述步骤后",{"2":{"396":1}}],["​\\t\\tvoid",{"2":{"412":1,"415":1}}],["​\\t\\t为方便开发者构建个性化的工程导出能力",{"2":{"411":1}}],["​\\t\\t先下载",{"2":{"410":1}}],["​\\t\\t因为",{"2":{"408":1}}],["​\\t\\t移动设备中大多数使用",{"2":{"405":1}}],["​\\t\\t上传至cdn时",{"2":{"404":1}}],["​\\t\\tpc端上预览的时候展示的是png图片会比较大",{"2":{"403":1}}],["​\\t\\t微信纹理压缩工具底层原理是将bundle内纹理资源分离",{"2":{"401":1}}],["​\\t\\t微信纹理压缩升级了全新的内核程序",{"2":{"400":1}}],["​\\t\\t微信纹理压缩目前已支持webgl2",{"2":{"397":1}}],["​\\t\\t默认情况下无需开发者进行手动的配置",{"2":{"399":1}}],["​\\t\\t位于",{"2":{"399":1}}],["​\\t\\t有时忽略整个ab包并不是一种好的策略",{"2":{"398":1}}],["​\\t\\t对于微信压缩纹理工具处理后部分资源渲染效果较差",{"2":{"398":1}}],["​\\t\\t该步骤根据项目实际情况不同",{"2":{"395":1}}],["​\\t\\t调试模式",{"2":{"395":1}}],["​\\t\\t点击",{"2":{"395":1}}],["​\\t\\t点击微信小游戏",{"2":{"394":1}}],["​\\t\\t若以上述4种格式配置后",{"2":{"393":1}}],["​\\t\\t在小游戏中玩家对启动时长与体验十分敏感",{"2":{"544":1}}],["​\\t\\t在",{"2":{"393":1,"547":1}}],["​\\t\\t项目中若使用",{"2":{"391":1}}],["​\\t\\t压缩纹理工具是微信sdk提供的一种能够根据不同的游戏运行平台而按需加载压缩后纹理资源的能力",{"2":{"549":1}}],["​\\t\\t压缩纹理工具执行需要依赖",{"2":{"406":1}}],["​\\t\\t压缩纹理工具对于",{"2":{"388":1}}],["​\\t\\t压缩纹理工具将纹理资源从",{"2":{"386":1}}],["​\\t\\t低版本引擎",{"2":{"387":1}}],["​\\t\\t如引擎版本高于2021",{"2":{"387":1}}],["​\\t\\t支持不同平台的自适应",{"2":{"387":1}}],["​\\t\\t更统一的工作流",{"2":{"387":1}}],["​\\t\\t使用压缩后的纹理本身将节约更多的内存空间",{"2":{"386":1}}],["​\\t\\t早期",{"2":{"386":1}}],["​",{"2":{"424":4}}],["高档机",{"2":{"1123":2,"1124":2}}],["高档",{"2":{"1105":1,"1120":1}}],["高峰用于",{"2":{"1086":1}}],["高分辨屏下模糊问题",{"0":{"1074":1}}],["高清渲染管线",{"2":{"808":1}}],["高度放缩系数",{"2":{"655":1,"667":1,"676":1}}],["高度",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["高度适配",{"2":{"423":1}}],["高性能与高性能+模式",{"0":{"1082":1},"1":{"1083":1,"1084":1,"1085":1,"1086":1,"1087":1,"1088":1,"1089":1,"1090":1,"1091":1,"1092":1,"1093":1,"1094":1,"1095":1,"1096":1,"1097":1,"1098":1,"1099":1,"1100":1,"1101":1},"2":{"781":1,"782":1}}],["高性能模式虽然能提运行算力",{"2":{"1100":1}}],["高性能模式提示资源下载失败等网络问题",{"2":{"1094":1}}],["高性能模式下",{"2":{"1090":1,"1091":1,"1094":1}}],["高性能模式下ios无法加载",{"0":{"484":1}}],["高性能模式能较快回落",{"2":{"1086":1}}],["高性能模式存在",{"2":{"1086":1}}],["高性能模式在长期执行过程中",{"2":{"1086":1}}],["高性能模式与安卓性能对比如何",{"0":{"1101":1},"2":{"1082":1}}],["高性能模式限制",{"0":{"1089":1},"1":{"1090":1,"1091":1},"2":{"1082":1}}],["高性能模式的子包代码也会占用大量内存",{"2":{"1038":1}}],["高性能模式由于加载子包的实现不同",{"2":{"1037":1}}],["高性能模式则是必须的",{"2":{"1031":1}}],["高性能模式出现",{"0":{"1039":1},"2":{"1012":1}}],["高性能模式代码分包后内存反而变得很高",{"0":{"1038":1},"2":{"1012":1}}],["高性能模式收集很卡",{"0":{"1037":1},"2":{"1012":1}}],["高性能模式",{"2":{"540":1,"714":1,"1031":1}}],["高性能模式只能同时播放一个视频",{"2":{"370":1}}],["高性能模式http网络切换为小游戏接口",{"2":{"153":1}}],["高性能",{"2":{"369":1}}],["高性能+模式开创新地在保留游戏独立进程的基础上将渲染重新挪回了微信进程",{"2":{"1084":1}}],["高性能+模式有更好的兼容性",{"2":{"1078":1}}],["高性能+模式下",{"2":{"26":1}}],["高性能+",{"2":{"369":1}}],["天下我有",{"2":{"423":1}}],["做好资源加载过程中的ui上的进度条反馈",{"2":{"833":1}}],["做了限帧的游戏应该适当调低",{"2":{"785":1}}],["做一些换算",{"2":{"707":1}}],["做得相对通用",{"2":{"423":1}}],["做预下载",{"2":{"16":1}}],["下由于子包可以全量加载",{"2":{"1031":1}}],["下图给出一种推荐的做法",{"2":{"577":1}}],["下的游戏运行效率可前往",{"2":{"540":1}}],["下文将介绍每一个阶段的工作",{"2":{"534":1}}],["下表数据均为development模式下数据",{"2":{"532":1}}],["下表为针对unity",{"2":{"532":1}}],["下次使用时从本地缓存中读取文件",{"2":{"988":1}}],["下次启动游戏再次下载版本a",{"2":{"526":1}}],["下次访问资源仍从网络下载",{"0":{"527":1},"2":{"500":1}}],["下次运行时仍然从网络下载",{"0":{"526":1},"2":{"500":1}}],["下降到",{"2":{"432":2}}],["下面简单分析流程",{"2":{"532":1}}],["下面实验均采用unity",{"2":{"532":1}}],["下面介绍如何通过在小游戏下通过profile的方式对小游戏首场景耗时进行针对性优化",{"2":{"530":1}}],["下面是一个",{"2":{"430":1}}],["下面根据配置介绍两种加载效果的实现",{"2":{"421":1}}],["下",{"2":{"429":1,"730":1}}],["下一步可以在本地的包定制",{"2":{"428":1}}],["下载中",{"2":{"1131":1}}],["下载资源无问题",{"2":{"1094":1}}],["下载stable版本微信开发者工具",{"2":{"1042":1}}],["下载完成",{"2":{"977":1}}],["下载更新全量资源",{"2":{"944":1}}],["下载wxassetbundleprovider",{"2":{"922":1}}],["下载wasm代码",{"2":{"826":1}}],["下载小游戏开发者工具",{"2":{"896":1}}],["下载代码分包",{"2":{"864":1}}],["下载",{"2":{"864":1}}],["下载unitysdk",{"2":{"838":1}}],["下载首资源包",{"2":{"826":1}}],["下载量",{"2":{"761":1,"1107":1,"1122":1}}],["下载可被识别的压缩纹理",{"2":{"386":1}}],["下载路径命中标识符时会自动缓存本次下载文件",{"2":{"290":1}}],["下载地址请查阅",{"2":{"902":1}}],["下载地址请查阅推荐引擎版本",{"2":{"719":1}}],["下载地址",{"2":{"0":1,"1136":1}}],["两种系统环境下",{"2":{"1101":1}}],["两者并行",{"2":{"864":1}}],["两者在实际使用时并不能简单以语言算力对比",{"2":{"735":1}}],["两者都填时",{"2":{"421":1,"423":1,"959":1}}],["两",{"2":{"685":1}}],["两个场景都使用同样资源是否产生冗余",{"2":{"926":1}}],["两个子文件夹",{"2":{"428":1}}],["两个目录中的",{"2":{"377":1}}],["控制音效数量",{"2":{"729":1}}],["控制icon样式",{"2":{"421":1}}],["控制是否清理webgl",{"2":{"234":1}}],["文档的",{"2":{"1005":1}}],["文档为使用unity",{"2":{"844":1}}],["文档可查看启动场景上报分析",{"2":{"825":1}}],["文档说明",{"0":{"607":1}}],["文档",{"2":{"552":1,"773":1}}],["文本输入框点击无法输入",{"0":{"483":1}}],["文字样式",{"2":{"421":1}}],["文件里",{"2":{"1014":1}}],["文件数量应控制在10个以内",{"2":{"999":1}}],["文件一般会自动生成在",{"2":{"889":1}}],["文件一起传给工具处理",{"2":{"889":1}}],["文件不存在或读取失败则自动放弃启动剧情",{"2":{"576":1}}],["文件根据游戏逻辑的主次内容分为",{"2":{"550":1}}],["文件才可以运行",{"2":{"550":1}}],["文件中",{"2":{"550":1}}],["文件管理",{"2":{"523":1}}],["文件名需要带上hash",{"2":{"523":1}}],["文件粒度缓存",{"2":{"501":1}}],["文件api",{"2":{"498":1}}],["文件系统",{"2":{"490":2}}],["文件存储将随之被删除",{"2":{"472":1}}],["文件非",{"2":{"433":1}}],["文件后",{"2":{"410":1}}],["文件路径",{"2":{"408":1}}],["文件路径通常为",{"2":{"351":1}}],["文件的",{"2":{"406":1}}],["文件",{"0":{"391":1},"1":{"392":1,"393":1},"2":{"391":1,"410":1,"449":1,"550":1,"576":1,"1041":1}}],["文件冲突",{"2":{"378":1}}],["文件夹下的代码在开放数据域初始化之后才能够执行",{"2":{"701":1}}],["文件夹中的脚本",{"2":{"582":1}}],["文件夹",{"2":{"374":1,"428":1,"612":1}}],["文件缓存等",{"2":{"965":1}}],["文件缓存与规则判定效率优化",{"2":{"173":1}}],["文件缓存清理逻辑优化",{"2":{"156":1}}],["每种机型测试3组数据再取平均",{"2":{"772":1,"1110":1,"1121":1}}],["每项指标有三个数值",{"2":{"717":1}}],["每个关键动作帧均有两个必要的组成部分",{"2":{"620":1}}],["每个文案展示时间",{"2":{"421":1,"423":1,"959":1}}],["每次生成会当前的分包version会加1",{"2":{"1027":1}}],["每次点生成时",{"2":{"1027":1}}],["每次收集发现新增函数趋于稳定之后",{"2":{"1027":1}}],["每次只能设置1个属性",{"2":{"666":1}}],["每次发新版本更换cdn路径",{"2":{"441":1}}],["每次修复时将当前所要修复资源的importer覆盖写入到library",{"2":{"362":1}}],["正式上线必须使用https",{"2":{"984":1}}],["正式上线版本请务必关闭profiling",{"2":{"448":1}}],["正在打水印",{"2":{"1131":1}}],["正在预下载数量",{"2":{"792":1}}],["正在加载资源",{"2":{"421":1,"959":1}}],["正常调用api即可",{"2":{"502":1}}],["正常情况下对内容进行安全校验的逻辑应该是内容校验通过+内容存储到后端在同一个云函数中实现",{"2":{"374":1}}],["正交投影相机需要注意",{"2":{"431":1}}],["尺寸相对设计宽高",{"2":{"421":1}}],["取而代之的做法是使用协程和",{"2":{"977":1}}],["取值范围",{"2":{"824":1}}],["取值和效果参考",{"2":{"421":1}}],["取平均值",{"2":{"759":2,"772":1,"1106":2,"1110":1,"1120":1,"1121":1}}],["取消此文件的自动缓存",{"2":{"799":1}}],["取消勾选",{"2":{"726":1}}],["取消勾选则使用optimizespeed",{"2":{"355":1}}],["取消状态",{"2":{"671":1}}],["取决于虚拟机",{"2":{"451":1}}],["缩放模式",{"2":{"421":1}}],["样式调整外显进度条",{"2":{"580":1}}],["样式调整",{"0":{"580":1}}],["样式配置未提供对应的转换插件配置入口",{"2":{"421":1}}],["样例",{"2":{"383":1}}],["铺满全屏呈现",{"2":{"418":1}}],["例子",{"2":{"414":1,"622":1}}],["例如想要判断当前环境wx",{"2":{"1007":1}}],["例如预下载发起和命中",{"2":{"965":1}}],["例如使用正则替换",{"2":{"384":1}}],["例如",{"2":{"109":1,"380":1,"430":1,"431":1,"433":1,"512":1,"513":1,"621":1,"813":1,"1003":1}}],["独立线程",{"2":{"572":1}}],["独立ab包处理后的输出目录",{"2":{"414":1}}],["独立域插件版本升级为1",{"2":{"330":1,"334":1,"337":1}}],["独立域插件版本更新为1",{"2":{"317":1}}],["独立域插件版本更新到1",{"2":{"259":1}}],["独立域插件更新",{"2":{"350":1}}],["独立域插件更新为",{"2":{"348":1}}],["独立域插件更新为1",{"2":{"313":1}}],["独立域插件更新1",{"2":{"319":1}}],["形参",{"2":{"417":1}}],["形参2",{"2":{"414":1}}],["形参1",{"2":{"414":1}}],["返回如下数据",{"2":{"993":1}}],["返回缓存路径",{"2":{"519":1}}],["返回值",{"2":{"518":1}}],["返回false不可自动清理",{"2":{"512":1}}],["返回true可自动清理",{"2":{"512":1}}],["返回true自动缓存",{"2":{"507":1}}],["返回扫描到的ab包资源绝对路径",{"2":{"417":1}}],["返回执行错误时的错误提示信息",{"2":{"414":1}}],["返回执行是否成功",{"2":{"414":1}}],["返回码",{"2":{"374":1}}],["工作量极大时也可结合使用",{"2":{"831":1}}],["工程联系",{"2":{"1098":1}}],["工程",{"2":{"1005":1,"1010":1}}],["工程时开发者应主要对游戏代码如首帧逻辑进行修改",{"2":{"546":1}}],["工程目录任意位置创建",{"2":{"479":1}}],["工程路径等数据均来自面板配置此处不提供相应参数传入",{"2":{"411":1}}],["工具上会显示收集到的函数个数",{"2":{"1016":1}}],["工具本身会增加不少内存",{"2":{"967":1}}],["工具本身不会造成大幅度的性能降低",{"2":{"739":1}}],["工具会自动将冗余项逐个设置为addressable",{"2":{"926":1}}],["工具预览",{"2":{"896":1}}],["工具",{"2":{"829":1}}],["工具需要开启development模式",{"2":{"740":1}}],["工具将可以享受到函数名联想及参数注释能力",{"2":{"618":1}}],["工具使用",{"0":{"455":1},"1":{"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1}}],["工具已经能够识别多数unity",{"2":{"399":1}}],["工具支持识别",{"2":{"393":1}}],["工具类来便捷的获得三个目录的绝对路径",{"2":{"381":1}}],["工具介绍",{"0":{"361":1},"1":{"362":1}}],["工具入口",{"0":{"360":1}}],["即minigame",{"2":{"1034":1}}],["即无需重复收集",{"2":{"1024":1}}],["即不运行游戏逻辑",{"2":{"1010":1}}],["即不设置该属性",{"2":{"667":1}}],["即使通过",{"2":{"996":1}}],["即使开发者用的",{"2":{"433":1}}],["即性能面板中的dynamicmemory中可被追踪到的内存情况",{"2":{"967":1}}],["即总预下载大小超过20mb",{"2":{"793":1}}],["即预下载列表数大于15",{"2":{"793":1}}],["即导出时未配置预下载列表",{"2":{"793":1}}],["即未压缩的首资源包超过15mb",{"2":{"790":1}}],["即callmain",{"2":{"785":1}}],["即开即用",{"2":{"775":1,"868":1}}],["即先确定机型设备条件",{"2":{"757":1}}],["即js运行效率的150",{"2":{"735":1}}],["即让",{"2":{"699":1}}],["即",{"2":{"678":1}}],["即点即玩",{"2":{"538":1,"828":1}}],["即webgl",{"2":{"501":1}}],["即wasm",{"2":{"501":1}}],["即加载动画默认播放时间",{"2":{"421":1,"423":1,"959":1}}],["即可测试小游戏是否正常运行",{"2":{"1131":1}}],["即可完成sdk导入",{"2":{"836":1}}],["即可看到相关性能数据",{"2":{"716":1}}],["即可看到所有进程的cpu与内存情况",{"2":{"715":1}}],["即可正常使用",{"2":{"466":1}}],["即可",{"2":{"410":1,"433":1}}],["即为复用未完成的预下载网络链接",{"2":{"998":1}}],["即为复用内存中已预下载完成的资源",{"2":{"998":1}}],["即为预下载请求日志",{"2":{"998":1}}],["即为",{"2":{"352":1}}],["后者长期处于高",{"2":{"1086":1}}],["后备字体",{"2":{"1001":1}}],["后释放",{"2":{"988":1}}],["后台",{"2":{"985":1}}],["后台配置安全域名白名单",{"2":{"540":1}}],["后缀",{"2":{"873":1}}],["后导入游戏工程中",{"2":{"838":1}}],["后多少ms截止",{"2":{"785":1}}],["后多长时间停止检测",{"2":{"785":1}}],["后执行的关键动作帧",{"2":{"673":1}}],["后为",{"2":{"635":1}}],["后才能够进行一系列的函数调用",{"2":{"582":1}}],["后续还是可能会被调到",{"2":{"1032":1}}],["后续从本地文件缓存加载",{"2":{"1001":1}}],["后续请求已预下载的资源没有日志可以区分",{"2":{"998":1}}],["后续请查阅",{"2":{"616":1}}],["后续场景使用assetsbundle",{"2":{"891":1}}],["后续关卡按需加载等",{"2":{"832":1}}],["后续的",{"2":{"814":1}}],["后续展示时会被动态替换",{"2":{"699":1}}],["后续剧情不播放",{"2":{"577":1}}],["后续操作",{"2":{"468":1}}],["后端",{"0":{"539":1}}],["后端服务模式",{"0":{"372":1}}],["后端服务指引",{"0":{"371":1},"1":{"372":1,"373":1,"374":1},"2":{"539":1}}],["后处理的销不小",{"2":{"818":1}}],["后处理慎用",{"2":{"431":1}}],["后处理",{"0":{"818":1},"2":{"430":1}}],["后",{"2":{"409":1,"428":1,"712":1,"998":1,"1031":1,"1074":1}}],["却享受了不同设备按需使用纹理格式的能力",{"2":{"407":1}}],["链接次数没变",{"2":{"407":1}}],["所提供的",{"2":{"1087":1}}],["所有内存",{"2":{"971":1}}],["所有加载完成",{"2":{"825":1}}],["所有配置项均可缺省",{"2":{"580":1,"585":1}}],["所有",{"2":{"431":1}}],["所有文件",{"2":{"374":1}}],["所以最好选择unity",{"2":{"1074":1}}],["所以最开始的收集会比较卡",{"2":{"1037":1}}],["所以如果是使用了",{"2":{"1031":1}}],["所以除非您将控制权交回给浏览器",{"2":{"977":1}}],["所以我们只推荐对内存要求高的重度游戏使用",{"2":{"945":1}}],["所以即使资源移动了或是重新命名了",{"2":{"919":1}}],["所以建议尽量使用表格中有实际游戏验证的版本",{"2":{"907":1}}],["所以开放数据域名要正确处理好事件处理",{"2":{"707":1}}],["所以配置好首帧图片后",{"2":{"695":1}}],["所以在小游戏主逻辑运行时",{"2":{"695":1}}],["所以在调用之前需要保证sdk位于gameglobal下且sdk中含有该名称的function",{"2":{"424":1}}],["所以你真正需要修改的是",{"2":{"614":1}}],["所以正确的修改目录应该位于",{"2":{"582":1}}],["所以需要开发者自行对不同阶段剧情进行上报打点",{"2":{"578":1}}],["所以并不会增加额外的请求开销",{"2":{"407":1}}],["所需配置项",{"2":{"422":1}}],["所扫描到的资源列表则为实际可被执行处理的资源",{"2":{"416":1}}],["解压到内存",{"2":{"864":1}}],["解压并保持在内存",{"2":{"864":1}}],["解压首资源包",{"2":{"826":1}}],["解析的",{"2":{"618":1}}],["解决方法",{"2":{"1079":1,"1080":1}}],["解决方案也很多",{"2":{"982":1}}],["解决方案",{"2":{"498":1}}],["解决方案二",{"0":{"410":1}}],["解决方案一",{"0":{"409":1}}],["解决办法是在游戏合理位置增加对wxsdk的使用即可",{"2":{"841":1}}],["解决办法是保证监听到",{"2":{"709":1}}],["解决办法",{"2":{"725":1,"726":1,"727":1,"728":1,"729":1,"1095":1}}],["解决这个报错",{"2":{"493":1}}],["解释器完整路径",{"2":{"409":2}}],["解释器",{"2":{"406":1}}],["解包纹理",{"2":{"398":1}}],["渲染兼容性",{"2":{"1084":1}}],["渲染分辨率",{"0":{"817":1}}],["渲染性能优化的一些建议",{"0":{"810":1},"1":{"811":1,"812":1,"813":1,"814":1,"815":1,"816":1,"817":1,"818":1,"819":1}}],["渲染特性如gpu",{"2":{"734":1}}],["渲染无法得到多线程的加速",{"2":{"734":1}}],["渲染速度更快",{"2":{"549":1}}],["渲染接口",{"2":{"498":1}}],["渲染管线",{"2":{"498":1}}],["渲染",{"2":{"405":1}}],["而ios上子包是按需加载的",{"2":{"1034":1}}],["而高频读取资源时通过缓存完成请求",{"2":{"945":1}}],["而由于webgl的文件系统是在js内存中维护的",{"2":{"945":1}}],["而新address提供了非常好的资源管理流程",{"2":{"928":1}}],["而更为简单的做法是",{"2":{"926":1}}],["而如果不经优化的unity",{"2":{"869":1}}],["而且手机屏幕左上角为",{"2":{"1073":1}}],["而且满足画质要求",{"2":{"813":1}}],["而且",{"2":{"812":1}}],["而且方便修改",{"2":{"812":1}}],["而言",{"2":{"807":1}}],["而没有调用",{"2":{"702":1}}],["而视频是存放在cdn的远程资源",{"2":{"695":1}}],["而故事线则是将多个独立的关键动作帧串联有序执行",{"2":{"619":1}}],["而无需带后面的参数进行能力的自主选择",{"2":{"616":1}}],["而游戏启动时需要完整的",{"2":{"550":1}}],["而资源目录",{"2":{"540":1}}],["而小游戏需要做到",{"2":{"538":1}}],["而callmain会在码包下载编译完成和首包资源下载完成后就执行",{"2":{"533":1}}],["而unity大部分的ui解决方案都是延迟到下一帧才执行ui事件回调",{"2":{"491":1}}],["而mac",{"2":{"479":1}}],["而",{"2":{"429":1,"622":2,"1076":1}}],["而不是",{"2":{"429":1}}],["而不是导出的资源目录",{"2":{"377":1}}],["而是通过",{"2":{"429":1}}],["而加了",{"2":{"429":1}}],["而对于其余的资源开发者最好使用按需加载的方式进行加载",{"2":{"876":1}}],["而对于重度游戏",{"2":{"829":1}}],["而对于",{"2":{"405":1,"1005":1}}],["倍数底层逻辑处理并不会对移动设备上的表现有差异",{"2":{"405":1}}],["作用",{"0":{"784":1,"1015":1},"1":{"1020":1,"1021":1,"1022":1,"1023":1,"1024":1,"1025":1,"1026":1,"1027":1},"2":{"783":1,"1012":1}}],["作为主要的纹理资源格式",{"2":{"405":1}}],["作出检查",{"2":{"378":1}}],["非minigame版",{"2":{"1018":1}}],["非压缩纹理软解",{"2":{"971":2}}],["非小游戏版",{"2":{"896":1}}],["非常建议开发者熟练使用",{"2":{"739":1}}],["非微信",{"2":{"429":1}}],["非4倍数的资源处理底层逻辑",{"0":{"405":1}}],["非pot图也支持延迟加载",{"2":{"315":1}}],["非playing状态调用wx接口的告警提示",{"2":{"188":1}}],["速度快很多",{"2":{"403":1}}],["分钟内",{"2":{"1091":1}}],["分数越高",{"2":{"1087":1}}],["分隔",{"2":{"899":1,"900":2}}],["分阶段耗时",{"0":{"872":1}}],["分包主要目的是优化启动加载",{"2":{"1031":1}}],["分包能降低内存占用",{"2":{"1031":1}}],["分包的目的主要是将启动时需要的包减小",{"2":{"1034":1}}],["分包的收集",{"2":{"1026":1}}],["分包的作用在于优化启动时间",{"2":{"1015":1}}],["分包工具会优化函数名",{"2":{"1024":1}}],["分包流程如下",{"2":{"1019":1}}],["分包还有两个作用",{"2":{"1015":1}}],["分包插件交互优化",{"2":{"1069":1}}],["分包插件上也会更新",{"2":{"1029":1}}],["分包插件按小游戏的md5",{"2":{"1019":1}}],["分包插件卡住",{"0":{"1044":1},"2":{"1012":1}}],["分包插件安装失败",{"0":{"1043":1},"2":{"1012":1}}],["分包总大小比原始包大",{"0":{"1034":1},"2":{"1012":1}}],["分包是否是必要的",{"0":{"1031":1},"2":{"1012":1}}],["分包收集不足",{"2":{"796":1}}],["分包方案外",{"2":{"556":1}}],["分为引擎初始化完成",{"2":{"791":1}}],["分类",{"2":{"758":1,"1113":1}}],["分配内存并未呈现",{"2":{"717":1}}],["分别是",{"2":{"619":1}}],["分割",{"2":{"513":1}}],["分析小游戏启动速度",{"0":{"870":1},"1":{"871":1,"872":1,"873":1,"874":1,"875":1,"876":1,"877":1}}],["分析每个环节可能存在的流失",{"2":{"822":1}}],["分析每一帧游戏函数耗时情况",{"2":{"351":1}}],["分析场景帧",{"2":{"814":1}}],["分析网络并发和网络耗时",{"2":{"804":1}}],["分析手段",{"2":{"717":1}}],["分析调用堆栈",{"2":{"449":1}}],["分离的资源被压缩成多种格式的纹理资源在",{"2":{"549":1}}],["分离纹理后各自单独下载是否会增加下载开销",{"0":{"407":1}}],["分离出的资源将被处理成多种不同gpu所支持的纹理格式托管至cdn中",{"2":{"401":1}}],["来区分不同的小游戏包",{"2":{"1019":1}}],["来收集信息",{"2":{"1016":1}}],["来判断",{"2":{"1007":1}}],["来管理unityperdraw",{"2":{"807":1}}],["来开发",{"2":{"705":1}}],["来完成剧情的自主设计",{"2":{"626":1}}],["来减少人工协助带来的额外时间消耗",{"2":{"607":1}}],["来决定是否直接使用微信定制的版本",{"2":{"433":1}}],["来做条件编译",{"2":{"431":1}}],["来自定义剔除",{"2":{"399":1}}],["来播放音频",{"2":{"365":1}}],["进无止境",{"2":{"730":2}}],["进程内存峰值",{"2":{"759":1,"1106":1,"1120":1}}],["进程内存离1",{"2":{"731":1}}],["进程名",{"2":{"716":1}}],["进程总内存",{"0":{"714":1},"1":{"715":1,"716":1}}],["进程级别",{"2":{"713":1}}],["进阶指南",{"0":{"617":1},"1":{"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1},"2":{"616":1}}],["进度",{"2":{"599":1}}],["进度条高度",{"2":{"580":1,"585":1}}],["进度条背景颜色",{"2":{"580":1,"585":1}}],["进度条颜色",{"2":{"580":1,"585":1}}],["进度条样式",{"2":{"418":1,"421":1,"551":1}}],["进度显示",{"2":{"579":1}}],["进度的显示",{"2":{"579":1}}],["进而提升玩家的代入感与游戏的顺畅体验",{"2":{"568":1}}],["进入正式分包阶段",{"2":{"1019":1}}],["进入aa的组设置修改provider如下",{"2":{"922":1}}],["进入核心玩法时",{"2":{"825":1}}],["进入原本的unity",{"2":{"581":1}}],["进入关卡等关键信息",{"2":{"565":1}}],["进入配置页",{"2":{"398":1}}],["进行设置",{"2":{"985":1}}],["进行自查",{"2":{"984":1}}],["进行替代",{"2":{"978":1}}],["进行网络通信",{"2":{"978":1}}],["进行unity",{"2":{"885":1}}],["进行加载",{"2":{"828":1}}],["进行查看",{"2":{"827":1}}],["进行了解和使用",{"2":{"767":1}}],["进行渲染而是可以选择任意第三方渲染引擎",{"2":{"707":1}}],["进行简单的魔改就能够满足需求",{"2":{"706":1}}],["进行功能反馈将会提交",{"2":{"565":1}}],["进行资源按需加载缩短转换周期",{"2":{"832":1}}],["进行资源按需加载将部分资源自动剥离",{"2":{"831":1}}],["进行资源按需加载",{"0":{"556":1,"940":1},"1":{"557":1,"558":1,"559":1,"560":1,"941":1,"942":1,"943":1,"944":1,"945":1,"946":1,"947":1,"948":1,"949":1},"2":{"538":2,"779":1,"829":2,"831":1}}],["进行交互吗",{"0":{"473":1}}],["进行定制",{"2":{"433":1}}],["进行剔除",{"2":{"399":1}}],["进行校验",{"2":{"391":1}}],["进行处理",{"2":{"387":1}}],["甚至",{"2":{"428":1}}],["甚至无法处理的情况",{"2":{"398":1}}],["甚至是图片等资源的变更",{"2":{"384":1}}],["上图分别是",{"2":{"1087":1}}],["上线发布时",{"2":{"1091":1,"1100":1}}],["上线后",{"2":{"1029":1}}],["上线后的问题排查与分析",{"2":{"534":1}}],["上线前",{"2":{"1029":1}}],["上线版本的网络请求必须配置安全域名",{"2":{"985":1}}],["上",{"2":{"730":1}}],["上报当前自定义阶段错误信息",{"2":{"825":1}}],["上报自定义阶段",{"0":{"825":1}}],["上报广告信息",{"0":{"823":1},"1":{"824":1}}],["上报模块有助于帮助开发者量化启动剧情不同阶段的用户曝光情况分析用户体验",{"2":{"689":1}}],["上报",{"0":{"689":1},"1":{"690":1,"691":1,"692":1,"694":1,"695":1}}],["上报unity版本和转换插件版本",{"2":{"259":1}}],["上面的例子展示了实际应用的多种可能",{"2":{"622":1}}],["上述代码改写成",{"2":{"927":1}}],["上述方法之后",{"2":{"459":1}}],["上述定制的",{"2":{"433":1}}],["上述的代码除了启用了",{"2":{"429":1}}],["上传cdn",{"0":{"396":1}}],["执行都是",{"2":{"1101":1}}],["执行sql",{"2":{"971":1}}],["执行渲染",{"2":{"705":1}}],["执行好友排行榜渲染",{"2":{"703":1}}],["执行缓存逻辑",{"2":{"515":1}}],["执行缓存逻辑的日志",{"0":{"527":1},"2":{"500":1}}],["执行结束的回调函数",{"2":{"414":1}}],["执行完成后请留意控制台提示信息",{"2":{"395":1}}],["执行压缩纹理",{"0":{"395":1}}],["处理",{"2":{"864":2}}],["处理时间也会有差异",{"2":{"395":1}}],["处理资源",{"2":{"395":1,"413":1}}],["调用微信",{"0":{"1005":1},"1":{"1006":1,"1007":1,"1008":1,"1009":1,"1010":1,"1011":1}}],["调用openprofilestats",{"2":{"968":1}}],["调用开销",{"2":{"812":1}}],["调用的malloc分配",{"2":{"712":1}}],["调用",{"2":{"701":1,"825":1}}],["调用sdk的api",{"0":{"700":1},"1":{"701":1,"702":1,"703":1}}],["调用关系链接口拉好友数据和将数据绘制到",{"2":{"697":1}}],["调用接口",{"2":{"411":1}}],["调试微信开发者工具",{"2":{"1046":1}}],["调试",{"2":{"1046":1}}],["调试编译选项",{"2":{"893":1,"899":1}}],["调试器",{"2":{"446":1,"965":1}}],["调试结束后可再次选用全量模式",{"2":{"395":1}}],["调整屏幕移到刘海屏下面",{"2":{"1073":1}}],["调整unityprofiler",{"2":{"902":1}}],["调整为unitywebrequest异步接口创建ab",{"2":{"831":1}}],["调整为从unitywebrequest下载创建ab即可",{"2":{"831":1}}],["调整为默认不打开性能面板",{"2":{"270":1}}],["调整image位置",{"2":{"668":1}}],["调整部分api",{"2":{"250":1}}],["调整wxtouchoverride更新逻辑为lateupdate",{"2":{"171":1}}],["调整默认打开窗口宽度",{"2":{"92":1}}],["调整启动封面表现",{"2":{"16":1}}],["查找表",{"2":{"945":1}}],["查找资源被引用关系",{"2":{"362":1}}],["查阅更多转换案例",{"2":{"1135":1}}],["查阅快速开始",{"2":{"834":1,"1136":1}}],["查阅小游戏开发者文档",{"2":{"834":1,"1136":1}}],["查看",{"2":{"1093":1}}],["查看启动耗时",{"0":{"871":1}}],["查看每帧耗时",{"2":{"804":1}}],["查看总内存时",{"2":{"714":1}}],["查看插件调试日志",{"2":{"514":1,"998":1}}],["查看缓存日志",{"0":{"514":1},"1":{"515":1,"516":1},"2":{"500":1}}],["查看player",{"2":{"492":1}}],["查看分包工具是否有新收集函数",{"2":{"461":1}}],["查看识别情况",{"2":{"395":1}}],["全角中英文标点",{"2":{"1004":1}}],["全角ascii",{"2":{"1004":1}}],["全支持dxt",{"2":{"905":5}}],["全屏视频",{"2":{"634":1}}],["全局设置及引用到的资源",{"2":{"873":1}}],["全局变量名",{"2":{"681":1}}],["全局变量目前以字符串类型进行内容存储",{"2":{"680":1}}],["全局变量是外界脚本",{"2":{"679":1}}],["全局变量",{"0":{"679":1},"1":{"680":1,"681":1,"682":1,"683":1},"2":{"577":1,"583":1,"625":1}}],["全局宏的接口",{"2":{"429":1}}],["全双工通信改用",{"2":{"539":1}}],["全精度利用率",{"2":{"432":2}}],["全游戏工程请勿使用",{"2":{"392":1}}],["全部使用webaudio",{"2":{"366":1}}],["安全内存建议1",{"2":{"1090":1}}],["安全内存峰值是1",{"2":{"731":1}}],["安全区域适配",{"0":{"1073":1}}],["安全域名",{"0":{"985":1}}],["安装与使用",{"0":{"1136":1},"2":{"1042":1}}],["安装指南",{"0":{"836":1,"838":1},"1":{"841":1}}],["安装时选择webgl组件",{"2":{"1136":1}}],["安装时选择",{"2":{"834":1}}],["安装启动剧情cli工具",{"0":{"610":1}}],["安装包直接进行安装",{"2":{"479":1}}],["安装",{"0":{"390":1},"2":{"428":1,"1017":1}}],["安卓微信客户端8",{"2":{"1063":1}}],["安卓微信客户端版本",{"2":{"1001":1}}],["安卓小米10",{"2":{"532":1}}],["安卓魅族6s",{"2":{"532":1}}],["安卓",{"2":{"369":1,"429":1}}],["安卓8",{"2":{"180":1}}],["安卓3",{"2":{"57":1}}],["按函数粒度对小游戏的",{"2":{"1016":1}}],["按结果配置",{"2":{"577":1}}],["按需剔除后再次profile即可验证效果",{"2":{"533":1}}],["按照我们经验",{"2":{"1032":1}}],["按照提示申请权限",{"2":{"613":1}}],["按照提示创建",{"2":{"611":1}}],["按照lru清理出所需大小",{"2":{"513":1}}],["按照本地没有缓存来使用",{"2":{"502":1}}],["按钮的执行",{"2":{"413":1}}],["按钮",{"2":{"398":1,"428":2,"678":1}}],["按设备加载",{"2":{"388":1}}],["按资源名搜索",{"2":{"362":1}}],["年份大版本",{"2":{"388":1}}],["等游戏第一帧渲染时隐藏",{"2":{"959":1}}],["等事件",{"2":{"622":1}}],["等具备",{"2":{"618":1}}],["等待第一次分包",{"2":{"1019":1}}],["等待上传代码包",{"2":{"1019":1}}],["等待上传文件",{"0":{"1022":1},"2":{"1012":1}}],["等待分包",{"0":{"1025":1},"2":{"1012":1}}],["等待预处理提前到选择是否增量更新的界面",{"2":{"1069":1}}],["等待预处理",{"0":{"1023":1},"2":{"1012":1,"1019":1}}],["等待预载完成",{"2":{"998":1}}],["等待网络完成",{"2":{"998":1}}],["等待转换完成",{"2":{"893":1}}],["等待程序执行结束后",{"2":{"615":1}}],["等待片刻提示",{"2":{"612":1}}],["等待片刻创建成功后请进入该目录",{"2":{"611":1}}],["等待完全解包后可进行纹理的配置操作",{"2":{"398":1}}],["等买量场景进入的玩家",{"2":{"544":1,"822":1}}],["等同于修改导出插件面板的bundle名中hash长度",{"2":{"510":1}}],["等同于修改导出插件面板的不自动缓存文件类型配置",{"2":{"507":1}}],["等函数得到完整的堆栈",{"2":{"451":1}}],["等函数与程序未捕捉异常都只有输出简要的异常信息",{"2":{"451":1}}],["等函数等与程序未捕捉异常可输出简要的异常信息",{"2":{"451":1}}],["等少数后处理",{"2":{"431":1}}],["等",{"2":{"430":1,"431":1,"608":1,"807":1,"1090":2}}],["等包的情况",{"2":{"428":1}}],["等文件",{"2":{"396":1}}],["等不可用",{"2":{"388":1}}],["等云函数部署完成",{"2":{"374":1}}],["应当明显小于",{"2":{"815":1}}],["应设置showresultafterlaunch=false",{"2":{"785":1}}],["应减少assetbundle大小",{"2":{"728":1}}],["应避免使用",{"2":{"728":1}}],["应检查是否有使用unity",{"2":{"720":1}}],["应使其始终保持活跃",{"2":{"612":1}}],["应使用devicepixelratio来控制",{"2":{"748":1}}],["应使用",{"2":{"387":1}}],["应该设置showresultafterlaunch=true",{"2":{"785":1}}],["应该如何设置",{"0":{"480":1}}],["应该以",{"2":{"377":1}}],["应该使用哪个引擎版本转换",{"2":{"907":1}}],["应该使用jxxx的数字作为函数id",{"2":{"446":1}}],["应该使用",{"2":{"370":1}}],["内置函数替代",{"2":{"812":1}}],["内置管线",{"2":{"808":2}}],["内置内购商城等",{"2":{"758":1,"1113":1}}],["内的",{"2":{"701":1}}],["内分离后按渲染需要进行后续加载",{"2":{"549":1}}],["内存压力大的游戏开启此选项",{"2":{"1084":1}}],["内存压力大时",{"2":{"387":1}}],["内存限制",{"0":{"1090":1},"2":{"1082":1}}],["内存中的资源会释放",{"2":{"998":1}}],["内存管理",{"2":{"919":1}}],["内存更多优化",{"2":{"905":1}}],["内存异常退出分析",{"2":{"1106":1}}],["内存异常退出率",{"2":{"760":1,"763":1,"1112":1,"1114":1}}],["内存异常退出运行时长",{"2":{"759":1,"760":1,"763":1,"1106":1,"1112":1,"1114":1}}],["内存峰值取最大值",{"2":{"772":1,"1110":1,"1121":1}}],["内存峰值",{"2":{"759":2,"760":1,"763":1,"1106":2,"1112":1,"1114":1,"1118":1,"1120":1}}],["内存工具请查阅优化unity",{"2":{"740":1}}],["内存数据不准确",{"2":{"740":1}}],["内存与模块上报数据",{"2":{"740":1}}],["内存与oom",{"0":{"711":1}}],["内存篇",{"2":{"730":2}}],["内存优化版本未观察到内存优化",{"0":{"1045":1},"2":{"1012":1}}],["内存优化方案",{"0":{"724":1}}],["内存优化极为重要",{"2":{"711":1}}],["内存分配峰值",{"2":{"717":1}}],["内存查看工具",{"0":{"713":1},"1":{"714":1,"715":1,"716":1,"717":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"730":1}}],["内存等要求并不是特别吃紧的游戏",{"2":{"557":1}}],["内存",{"2":{"548":1,"712":1,"1105":1,"1120":1,"1123":1,"1124":1}}],["内网使用微信开发者工具时需要放开这些域名的限制方可正常使用",{"2":{"499":1}}],["内网开发时",{"0":{"465":1}}],["内容打包",{"2":{"919":1}}],["内容如下",{"2":{"479":1}}],["内容含有违法违规内容",{"2":{"374":1}}],["内容正常",{"2":{"374":1}}],["内容安全检查",{"2":{"374":1}}],["移动端android",{"2":{"905":1}}],["移动端正常",{"0":{"494":1}}],["移动端",{"2":{"433":1}}],["移动端覆盖率较广",{"2":{"387":1}}],["移动设备使用",{"2":{"395":1}}],["移除无用代码",{"2":{"1061":1}}],["移除所有回调后再次onmessage可重新设置needinfo",{"2":{"979":1,"983":1}}],["移除掉官方的",{"2":{"428":1}}],["移除转换小游戏面板中游戏内存大小字段",{"2":{"346":1}}],["移除markdown插件",{"2":{"135":1}}],["移除对node",{"2":{"94":1}}],["移除不用的纹理下载api",{"2":{"82":1}}],["使其与父节点一样大",{"2":{"1073":1}}],["使其可以读写到小游戏缓存目录",{"2":{"945":1}}],["使得首包可以满足大部分新玩家前几分钟的游戏进程",{"2":{"1016":1}}],["使得小游戏可以先加载较小的首包进入主场景",{"2":{"1014":1}}],["使得视图组件的某",{"2":{"675":1}}],["使得ab占用内存更小",{"2":{"387":1}}],["使用插件",{"0":{"1131":1}}],["使用高性能模式下",{"0":{"1094":1,"1100":1},"2":{"1082":2}}],["使用高性能+模式",{"2":{"731":1}}],["使用高性能+模式将显著降低gpu内存",{"2":{"726":1}}],["使用urp",{"2":{"1076":1}}],["使用unity适配提供timelog窗口或运行日志获取性能数据",{"2":{"1121":1}}],["使用unity适配提供timelog窗口",{"2":{"1109":1}}],["使用unity",{"0":{"805":1,"902":1},"2":{"567":1,"782":1,"802":1}}],["使用gpu",{"2":{"1076":1,"1079":1}}],["使用getwxfont加载的字体集合可以在转换面板进行自定义",{"2":{"1004":1}}],["使用条件",{"2":{"1069":1,"1071":1}}],["使用示例我们会逐渐补充到demo",{"2":{"1009":1}}],["使用时可以参考之",{"2":{"1005":1}}],["使用网络字体",{"2":{"1003":1}}],["使用网络模拟工具1mb",{"2":{"769":1,"1109":1,"1121":1}}],["使用如通过在线工具检测",{"2":{"986":1}}],["使用调试模式的真机环境",{"2":{"984":1}}],["使用举例",{"2":{"979":1,"983":1}}],["使用coverview需要基础库版本",{"2":{"959":1}}],["使用cdn下载首包资源",{"2":{"893":1}}],["使用loader进行游游戏加载",{"0":{"950":1},"1":{"951":1,"952":1,"953":1,"954":1,"955":1,"956":1,"957":1,"958":1,"959":1,"960":1,"961":1,"962":1,"963":1,"964":1,"965":1}}],["使用这种方式加载资源",{"2":{"934":1}}],["使用协程",{"0":{"931":1}}],["使用任何你喜欢的资源管理技术",{"2":{"919":1}}],["使用好友关系链",{"2":{"899":1}}],["使用脚本集成到自己的构建系统",{"0":{"897":1},"1":{"898":1,"899":1,"900":1}}],["使用预下载",{"2":{"893":1}}],["使用预下载功能",{"0":{"987":1},"1":{"988":1,"989":1,"990":1,"991":1,"992":1,"993":1,"994":1,"995":1,"996":1,"997":1,"998":1,"999":1},"2":{"547":1,"779":1,"793":2}}],["使用门槛更低一些",{"2":{"829":1}}],["使用转换脚本导出微信小游戏包并启动小游戏",{"2":{"805":1,"902":1}}],["使用本地缓存的个数",{"2":{"798":1}}],["使用分包工具继续迭代",{"2":{"796":1}}],["使用最佳实践检测",{"2":{"784":1}}],["使用js代码获取gpu信息",{"2":{"753":1}}],["使用javascriptprofile进行数据分析",{"2":{"351":1}}],["使用srp",{"0":{"752":1},"2":{"1076":1}}],["使用symbols文件可读函数名",{"0":{"449":1}}],["使用压缩纹理",{"0":{"749":1}}],["使用工具在真机上获取profile数据以分析热点函数和性能瓶颈",{"2":{"739":1}}],["使用await",{"0":{"932":1}}],["使用addressables",{"2":{"926":1}}],["使用addressable是最佳做法",{"2":{"921":1}}],["使用addressable在开发前期就进入快速开发的阶段",{"2":{"919":1}}],["使用addressable",{"0":{"916":1},"1":{"917":1,"918":1,"919":1,"920":1,"921":1,"922":1,"923":1,"924":1,"925":1,"926":1,"927":1,"928":1,"929":1,"930":1,"931":1,"932":1,"933":1,"934":1,"935":1,"936":1,"937":1,"938":1,"939":1},"2":{"876":1,"878":1}}],["使用addressable进行资源按需加载",{"2":{"779":1}}],["使用assetsbundle",{"2":{"779":1}}],["使用assetbundle",{"2":{"728":1}}],["使用android",{"0":{"351":1},"2":{"782":1,"802":1}}],["使用rgba",{"2":{"726":1}}],["使用群排行功能需要特殊设置分享功能",{"2":{"708":1}}],["使用动画实现贴图按钮",{"2":{"678":1}}],["使用代码编辑工具打开unity工程中",{"2":{"576":1}}],["使用代码分包工具缩减webassembly首次下载包体",{"2":{"778":1}}],["使用代码分包工具能降低原编译代码内存50",{"2":{"725":1}}],["使用代码分包工具",{"2":{"550":1,"778":1,"790":1}}],["使用代码分包的情况下",{"0":{"461":1}}],["使用姿势为",{"2":{"531":1}}],["使用异步等其他替代方式",{"2":{"498":1}}],["使用小程序云开发或自建服务器进行云端存储",{"2":{"490":1}}],["使用导出插件的",{"2":{"488":1}}],["使用xlua等方案在webgl平台报",{"0":{"481":1}}],["使用文本方式打开即可",{"2":{"452":1}}],["使用perfdog测试",{"2":{"772":1,"1110":1,"1121":1}}],["使用perfdog",{"2":{"731":1}}],["使用perfdog查看android版本的gl",{"2":{"731":1}}],["使用perfdog查看帧率并不总是准确",{"2":{"488":1}}],["使用perfdog选择对应的设置",{"2":{"716":1}}],["使用profilingmemory内存分析",{"0":{"966":1},"1":{"967":1,"968":1,"969":1,"970":1,"971":1,"972":1,"973":1,"974":1}}],["使用profiling",{"0":{"448":1}}],["使用playerpref接口时传入的key",{"2":{"357":1}}],["使用了定制的",{"2":{"433":1}}],["使用",{"0":{"493":1,"556":1,"940":1},"1":{"557":1,"558":1,"559":1,"560":1,"941":1,"942":1,"943":1,"944":1,"945":1,"946":1,"947":1,"948":1,"949":1},"2":{"431":1,"432":2,"548":2,"557":1,"591":1,"613":1,"624":1,"635":1,"641":1,"649":1,"652":1,"715":1,"779":1,"812":1,"829":1,"924":2,"982":1,"1010":1,"1087":1}}],["使用官方",{"2":{"428":1}}],["使用说明参考loader配置",{"2":{"900":1}}],["使用说明",{"0":{"389":1},"1":{"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1},"2":{"945":1}}],["使用新的",{"2":{"388":1}}],["使用建议",{"0":{"387":1}}],["使用该工具将对项目获得如下增益",{"2":{"386":1}}],["使用钩子",{"0":{"383":1}}],["使用微信字体",{"2":{"1003":1}}],["使用微信小游戏插件技术开发",{"2":{"951":1}}],["使用微信压缩纹理工具",{"2":{"503":1}}],["使用微信压缩纹理工具sprite",{"2":{"12":1}}],["使用微信开发者工具的network标签确认传输量",{"2":{"873":1}}],["使用微信开发者工具无法启动游戏",{"0":{"460":1}}],["使用微信开发者工具打开并上传",{"2":{"376":1}}],["使用方式",{"0":{"977":1,"1129":1},"1":{"1130":1,"1131":1},"2":{"351":1}}],["使用wasm代码分包后",{"2":{"794":1}}],["使用worker做文件写入临时绕过安卓文件写入多时造成卡顿",{"2":{"209":1}}],["使用wxassetbundleprovider节省内存",{"0":{"922":1}}],["使用wx",{"2":{"108":1,"490":2,"753":1,"1007":1}}],["使用date",{"2":{"180":1}}],["使用node命令时同时查找默认安装路径",{"2":{"151":1}}],["使用请阅读相关文档",{"2":{"130":1}}],["使用请查阅",{"2":{"127":1}}],["使用请查阅网络通信适配",{"2":{"40":1}}],["由转换工具与微信小游戏运行环境保证适配兼容",{"2":{"1134":1}}],["由unity中国区特殊优化",{"2":{"905":1}}],["由乐动卓越研发的精美3d手游",{"2":{"857":1}}],["由开发者定义",{"2":{"578":1}}],["由工具构建",{"2":{"575":1}}],["由此推出",{"2":{"568":1}}],["由业务控制何时清理",{"0":{"529":1},"2":{"500":1}}],["由于跨域获取不到",{"2":{"1095":1}}],["由于增量分包是新增的功能",{"2":{"1040":1}}],["由于内存限制",{"2":{"1031":1}}],["由于内存不足而使小游戏发生crash时",{"2":{"759":1,"1106":1}}],["由于安全性的影响",{"2":{"975":1}}],["由于ios内存更苛刻",{"2":{"974":1}}],["由于重启后",{"2":{"913":1}}],["由于游戏可能会存在限帧逻辑",{"2":{"762":1}}],["由于",{"2":{"602":1}}],["由于启动剧情为unity启动加载耗时过久而推出的能力",{"2":{"574":1}}],["由于缓存清理逻辑",{"2":{"526":1}}],["由于接口是同步调用",{"2":{"490":1}}],["由于微信环境下玩家非常容易删除本地小游戏而导致存档丢失",{"2":{"490":1}}],["由于通过http请求的资源会自动缓存",{"2":{"441":1}}],["由于unity2021之前不支持压缩纹理",{"2":{"712":1}}],["由于unity",{"2":{"418":1,"720":1,"727":1,"737":1,"746":1,"957":1}}],["由于unity自身产生的symbols存在缺失问题",{"2":{"234":1}}],["由",{"2":{"386":1}}],["根据机型分级",{"2":{"1079":1}}],["根据机型性能不同",{"2":{"988":1}}],["根据游戏项目统计",{"2":{"1076":1}}],["根据游戏实际情况修改",{"2":{"785":1}}],["根据优先级设置需要预加载的分包",{"2":{"928":1}}],["根据平台在不同游戏类型",{"2":{"776":1}}],["根据最近使用时间判断是哪个目录",{"2":{"523":2}}],["根据url生成缓存路径",{"2":{"513":1}}],["根据项目需要",{"2":{"430":7}}],["根据实际运行设备",{"2":{"386":1}}],["根据是否调试模式控制日志输出",{"2":{"348":1}}],["体验调优",{"0":{"545":1},"1":{"546":1,"547":1,"548":1,"549":1,"550":1,"551":1},"2":{"534":1}}],["体验版和正式版",{"2":{"1093":1}}],["体验版",{"2":{"771":1,"785":1}}],["体验版本增加性能面板",{"2":{"276":1}}],["体验版小游戏支持最佳实践检测",{"2":{"108":1}}],["体验版小游戏支持最佳实践检测工具",{"2":{"105":1}}],["体积更小",{"2":{"549":1}}],["体积将变小",{"2":{"386":1}}],["体积",{"2":{"386":1,"549":1}}],["完全通过",{"2":{"808":1}}],["完整的原理为",{"2":{"697":1}}],["完整配置",{"0":{"419":1},"1":{"420":1,"421":1}}],["完成后",{"2":{"1131":1}}],["完成后再回来",{"2":{"1027":1}}],["完成之后再使用",{"2":{"1010":1}}],["完成导出",{"2":{"968":1}}],["完成准备阶段后进入unity引擎初始化与首场景加载",{"2":{"864":1}}],["完成",{"2":{"582":1}}],["完成设计与调试",{"2":{"575":1}}],["完成发布上传前的自动化操作",{"2":{"411":1}}],["完成硬件的解码渲染",{"2":{"386":1}}],["完善限帧率接口setpreferredframespersecond",{"2":{"192":1}}],["完善filesystemmanager",{"2":{"75":1}}],["纹理存储路径",{"2":{"900":1}}],["纹理存放路径",{"2":{"505":1}}],["纹理等",{"2":{"873":1}}],["纹理",{"2":{"829":1}}],["纹理的大小当然越小越好",{"2":{"813":1}}],["纹理设置",{"0":{"813":1}}],["纹理会由于需要在cpu中软解为rgb",{"2":{"749":1}}],["纹理内存会造成明显膨胀",{"2":{"712":1}}],["纹理或模型upload",{"2":{"712":1}}],["纹理就还没有准备好",{"2":{"709":1}}],["纹理中hash长度",{"2":{"505":1,"900":1}}],["纹理相关",{"2":{"505":1}}],["纹理资源从",{"2":{"549":1}}],["纹理资源",{"2":{"503":1}}],["纹理资源的",{"2":{"393":1}}],["纹理差异降低值是不相同的",{"2":{"401":1}}],["纹理格式进行导出",{"2":{"386":1}}],["纹理压缩并行下载完成未正常显示",{"2":{"185":1}}],["概述",{"0":{"386":1,"822":1,"917":1,"967":1,"988":1,"1013":1},"1":{"1014":1,"1015":1},"2":{"1012":1}}],["这使得渲染效果和渲染内存消耗都得到了改善",{"2":{"1084":1}}],["这时候不代表没收集的函数都没用了",{"2":{"1032":1}}],["这时候就可以重新分包",{"2":{"1016":1}}],["这时候要留意下顶点着色会不会成为瓶颈",{"2":{"814":1}}],["这部分配置表示使用unity",{"2":{"952":1}}],["这部分资源就必须准备好",{"2":{"927":1}}],["这三种加载方式加载前后内存无变化",{"2":{"947":1}}],["这三种压缩格式",{"2":{"393":1}}],["这会极大影响场景初始化速度",{"2":{"927":1}}],["这会触发开放数据域的初始化",{"2":{"701":1}}],["这意味着即使还没调用instantiate",{"2":{"927":1}}],["这种情况一般是太多新增函数",{"2":{"1038":1}}],["这种形式和app版本类似",{"2":{"911":1}}],["这种语句",{"2":{"812":1}}],["这种结构化语句",{"2":{"812":1}}],["这种可以用网格化一个圆作为替代方案",{"2":{"812":1}}],["这将使得jit优化能更准确预判运行期类型",{"2":{"735":1}}],["这将涉及到异步方式来干预启动剧情插件的工作",{"2":{"577":1}}],["这需要你掌握一些简单的",{"2":{"705":1}}],["这一步一般是分钟级的耗时",{"2":{"1023":1}}],["这一步可以重复进行",{"2":{"1019":1}}],["这一步会做两个事情",{"2":{"704":1}}],["这一步非常重要",{"2":{"702":1}}],["这5个属性均支持缺省",{"2":{"629":1}}],["这其实是一种匿名故事线",{"2":{"622":1}}],["这有助于在剧情播放期间通过截图方式反馈一些加载进度信息",{"2":{"579":1}}],["这有助于加快游戏运行进度",{"2":{"386":1}}],["这段时间中任何时刻均会有用户离开",{"2":{"578":1}}],["这段等待期间游戏与玩家之间没有更多的交互",{"2":{"568":1}}],["这段代码有两处异常",{"2":{"451":1}}],["这得益于",{"2":{"557":1}}],["这个时候可以观察分包插件面板",{"2":{"1037":1}}],["这个时候要继续生成分包",{"2":{"1029":1}}],["这个插件",{"2":{"1017":1}}],["这个目录拷贝至",{"2":{"1005":1}}],["这个过程是cpu处理密集",{"2":{"988":1}}],["这个方法可能会牺牲一点画质效果",{"2":{"817":1}}],["这个问题已经反馈给",{"2":{"809":1}}],["这个文件不会自动缓存",{"2":{"523":1}}],["这个",{"2":{"431":1}}],["这是正常情况",{"2":{"973":1}}],["这是正常现象",{"2":{"428":1}}],["这是会产生一个问题",{"2":{"926":1}}],["这是由于手游app往往很少针对首包资源进行特殊优化",{"2":{"917":1}}],["这是导致了unity",{"2":{"734":1}}],["这是微信开发者工具打开的脚本目录",{"2":{"582":1}}],["这是新用户的留存率影响的重要因素",{"2":{"568":1}}],["这是基于",{"2":{"431":1}}],["这两个文件的开头新增以下代码",{"2":{"429":1}}],["这两个包从项目工程的缓存目录里拷贝出来",{"2":{"428":1}}],["这两个包",{"2":{"428":1}}],["这里的内存优化主要针对ios高性能模式",{"2":{"1045":1}}],["这里的目的就是为了算出",{"2":{"707":1}}],["这里不需要关注分包后所有wasm包的总和",{"2":{"1034":1}}],["这里会占用较高的内存和时间",{"2":{"1014":1}}],["这里提供了一个小工具用来替换函数",{"2":{"889":1}}],["这里主要关注首包函数个数",{"2":{"1026":1}}],["这里主要针对新开发的小游戏",{"2":{"808":1}}],["这里主要讲unityloader的资源缓存策略",{"2":{"442":1}}],["这里有个小工具可以帮助替换日志",{"2":{"449":1}}],["这里是导出",{"2":{"582":1}}],["这里是指",{"2":{"431":1}}],["这里是放",{"2":{"428":1}}],["这里列举一些微信小游戏可考虑优化的功能",{"2":{"430":1}}],["这里顺带把它开启了",{"2":{"429":1}}],["这里采用了一种取巧的方式来定义",{"2":{"429":1}}],["这里以竖屏游戏按高度适配为例",{"2":{"1073":1}}],["这里以unitywebsocket为例",{"2":{"981":1}}],["这里以",{"2":{"428":1}}],["这里需要将",{"2":{"428":1}}],["这里假设",{"2":{"428":1}}],["这样打包时就会导出symbol文件",{"2":{"1024":1}}],["这样做有个非常严重的问题",{"2":{"927":1}}],["这样表示材质复用的概率高",{"2":{"815":1}}],["这样对内存",{"2":{"813":1}}],["这样性能更好",{"2":{"811":1}}],["这样阴影贴图可以小一点",{"2":{"811":1}}],["这样你可以在任何时候对全局变量进行使用",{"2":{"625":1}}],["这样就允许先加载较小的首包快速进入主场景",{"2":{"550":1}}],["这样",{"2":{"429":1}}],["这样加载的时候纹理就会很小",{"2":{"403":1}}],["这样的工作原理即做到了不同硬件所支持的纹理格式按需加载",{"2":{"401":1}}],["这些版本需要用微信压缩纹理以优化内存",{"2":{"907":1}}],["这些文件压缩率很高",{"2":{"403":1}}],["这些修改同时也要跟随项目内容一起进行代码托管",{"2":{"376":1}}],["这对于内存吃紧的游戏至关重要",{"2":{"386":1}}],["这对于你托管项目代码很便捷",{"2":{"384":1}}],["搭配钩子介绍小节中的不同阶段",{"2":{"384":1}}],["回退成通过cdn下载后备字体的形式",{"2":{"1000":1}}],["回退至unitywebrequestassetbundle模式运行",{"2":{"73":1}}],["回包大小",{"2":{"798":1}}],["回调后再执行你的主逻辑",{"2":{"1005":1}}],["回调",{"2":{"708":1}}],["回调函数参数中可获得句柄外",{"2":{"583":1}}],["回调钩子请使用",{"2":{"383":1}}],["回合战斗",{"2":{"1135":1}}],["回合",{"2":{"496":1}}],["子包是有延迟加载的",{"2":{"1034":1}}],["子包不会加载",{"2":{"1014":1}}],["子包",{"2":{"1014":1}}],["子",{"2":{"383":1}}],["构建场景及依赖",{"2":{"864":1}}],["构建时默认打包到streamingassets目录下",{"2":{"439":1}}],["构建前的纹理格式配置说明",{"0":{"392":1}}],["构建",{"0":{"391":1,"479":1},"1":{"392":1,"393":1}}],["构建生命周期回调钩子",{"2":{"383":1}}],["构建模板能够自动帮你完成相同json文件的字段合并",{"2":{"380":1}}],["构建模板能力为开发者提供了一个json配置合并能力",{"2":{"380":1}}],["构建模板前后不同时机的钩子",{"0":{"381":1},"1":{"382":1,"383":1,"384":1},"2":{"377":1}}],["钩子介绍",{"0":{"382":1}}],["但建议综合cpu",{"2":{"1105":1}}],["但由于底层虚拟机差异过大以及自身不断迭代",{"2":{"1101":1}}],["但对内存",{"2":{"1100":1}}],["但对于有网络存档的游戏而言",{"2":{"577":1}}],["但对于大部分微信小游戏",{"2":{"427":1}}],["但",{"2":{"1097":1}}],["但网络空闲的期间",{"2":{"988":1}}],["但关闭时异常",{"2":{"984":1}}],["但小游戏包体的更新机制和app不同",{"2":{"911":1}}],["但小游戏平台不支持",{"2":{"799":1}}],["但新版本",{"2":{"907":1}}],["但引擎针对小游戏",{"2":{"905":1,"907":1}}],["但2018缺少部分功能",{"2":{"905":1}}],["但我们并不推荐使用早期版本",{"2":{"905":1}}],["但包体",{"2":{"905":1}}],["但未使用",{"2":{"833":1}}],["但未完成",{"2":{"793":1}}],["但自定义阶段与启动加载完成需开发者主动调用接口进行上报",{"2":{"825":1}}],["但尽量不要超过250个",{"2":{"815":1}}],["但仍然是需要注意",{"2":{"814":1}}],["但有些",{"2":{"813":1}}],["但线性颜色空间",{"2":{"809":1}}],["但并发数改为1个",{"2":{"996":1}}],["但并非每个小版本我们都有足够的验证",{"2":{"904":1}}],["但并不是完全向后兼容",{"2":{"807":1}}],["但并没有同步修改资源下载url",{"2":{"527":1}}],["但该模式也存在更严格的内存与代码包体限制",{"2":{"1083":1}}],["但该模式需要更多精力进行调优",{"2":{"736":1}}],["但该能力仍然允许开发者进行手动的进行资源选择",{"2":{"399":1}}],["但要注意移动平台散热更差",{"2":{"736":1}}],["但基本的渲染能力与原生app接近",{"2":{"734":1}}],["但依然会存在一些基本消耗",{"2":{"712":1}}],["但内存组成结构与上图基本一致",{"2":{"712":1}}],["但如果if",{"2":{"812":1}}],["但如果需要事件点击",{"2":{"705":1}}],["但如果是用的ab",{"2":{"439":1}}],["但只需要核心理解几个点即可",{"2":{"697":1}}],["但都是独立生效",{"2":{"622":1}}],["但需要调用扩展方法wxunload",{"2":{"945":1}}],["但需要注意的是javascript",{"2":{"720":1}}],["但需要注意该部分数据使用小游戏storage",{"2":{"490":1}}],["但需要开发者上报游戏关键节点信息与异常日志",{"2":{"566":1}}],["但为了能够达到更佳的游戏体验开发者应继续进行对游戏工程的调优工作",{"2":{"545":1}}],["但hash与本次写入的文件不一致",{"2":{"513":1}}],["但可使用微信小游戏wx",{"2":{"498":1}}],["但不支持wwise",{"2":{"498":1}}],["但不支持astc",{"2":{"388":1}}],["但android和微信开发者工具没问题",{"0":{"484":1}}],["但android卡在首屏",{"0":{"463":1}}],["但具体性能需自己实际评测",{"2":{"475":1}}],["但editor没问题",{"0":{"474":1}}],["但此模式必须保证游戏代码",{"2":{"451":1}}],["但必须保证游戏不使用任何异常",{"2":{"451":1}}],["但定制的做法或思路可以借鉴",{"2":{"433":1}}],["但这个是受gc策略和系统进程内存优化的影响",{"2":{"1045":1}}],["但这会使得代码包明显增大进而影响启动速度",{"2":{"705":1}}],["但这样定制会影响到所有平台",{"2":{"429":1}}],["但这毕竟需要开发者进行一定的代码编写",{"2":{"380":1}}],["但游戏内部关键帧位置仍需要开发者自行上报",{"2":{"544":1}}],["但游戏可能会存在定制启动loading的需求",{"2":{"423":1}}],["但游戏从未使用过",{"2":{"399":1}}],["但执行时提示未找到则需手动填入本机",{"2":{"406":1}}],["但仅支持2019",{"2":{"397":1}}],["但pc端不支持astc依然需要解压",{"2":{"387":1}}],["但是patch有大小限制",{"2":{"1033":1}}],["但是你希望屏幕中间再靠左10像素",{"2":{"629":1}}],["但是这对于初次使用的开发者还需要阅读本文更多的内容",{"2":{"616":1}}],["但是",{"2":{"433":1}}],["但是没有打印到客户端",{"2":{"370":1}}],["但是会降低游戏画面品质",{"2":{"353":1}}],["图形",{"2":{"1081":1}}],["图形库的功能",{"2":{"1076":1}}],["图集",{"2":{"813":1}}],["图片资源也处于就绪状态可以同步加载",{"2":{"695":1}}],["图片资源是跟随微信小游戏包上传至微信服务器",{"2":{"695":1}}],["图片资源可以使用网络图片吗",{"0":{"694":1}}],["图片资源本地路径",{"2":{"655":1}}],["图片",{"2":{"622":1}}],["图片文件不会检查",{"2":{"378":1}}],["图表",{"2":{"351":1}}],["创建udpsocket",{"2":{"983":1}}],["创建实例",{"2":{"981":1}}],["创建tcpsocket",{"2":{"979":1}}],["创建而来的",{"2":{"697":1}}],["创建精灵添加到游戏场景",{"2":{"697":1}}],["创建好多个",{"2":{"692":1}}],["创建变量",{"2":{"688":1}}],["创建image",{"2":{"668":1}}],["创建透明",{"2":{"658":1}}],["创建一个淡出的动画",{"2":{"678":1}}],["创建一个",{"2":{"635":1}}],["创建一系列的动作帧",{"2":{"624":1}}],["创建video",{"2":{"635":1,"638":1}}],["创建上报节点",{"2":{"627":1}}],["创建全局变量",{"2":{"627":1}}],["创建动画函数",{"2":{"627":1,"675":1}}],["创建延迟执行",{"2":{"627":1}}],["创建矩形区域",{"2":{"627":1}}],["创建贴图组件",{"2":{"654":1}}],["创建贴图",{"2":{"627":1}}],["创建音频组件",{"2":{"627":1,"643":1}}],["创建视频组件",{"2":{"627":1,"631":1}}],["创建",{"2":{"624":1}}],["创建故事线以及添加关键动作帧很简单",{"2":{"624":1}}],["创建及添加关键动作帧",{"0":{"624":1}}],["创建了一个",{"2":{"621":1}}],["创建成功后进入",{"2":{"612":1}}],["创建剧情工程",{"0":{"611":1}}],["创建用于覆盖的脚本时",{"2":{"377":1}}],["创建并部署",{"2":{"374":2}}],["值得注意的是",{"2":{"377":1,"393":1,"577":1,"828":1}}],["合法域名",{"2":{"985":1}}],["合适的时机执行需要的关键动作帧",{"2":{"626":1}}],["合理控制游戏帧率表现",{"2":{"762":1}}],["合理的位置进行上报",{"2":{"692":2}}],["合理位置标记为非新用户",{"2":{"576":1}}],["合理设置纹理maxsize可以减小纹理资源大小",{"2":{"363":1}}],["合并规则",{"2":{"380":1}}],["合并结果",{"2":{"377":1}}],["小于",{"2":{"1126":1}}],["小时的函数个数都在",{"2":{"1036":1}}],["小时之内下发新版本信息到用户",{"2":{"911":1}}],["小结",{"0":{"928":1}}],["小程序最低可用版本",{"2":{"914":1}}],["小小蚁国",{"0":{"853":1},"2":{"853":1}}],["小节",{"2":{"377":1,"622":1,"625":1}}],["小游戏适配方案",{"2":{"1133":1}}],["小游戏适配插件已自动进行缓存",{"2":{"831":1}}],["小游戏高性能+模式可以支持ios系统版本",{"2":{"1077":1}}],["小游戏ios高性能模式需要ios系统版本",{"2":{"1077":1}}],["小游戏需要先下载完",{"2":{"1014":1}}],["小游戏需要做到",{"2":{"828":1}}],["小游戏因其平台特殊性",{"2":{"944":1}}],["小游戏与app的assetbundle缓存更新流程差异",{"0":{"944":1}}],["小游戏与手游app的启动差异",{"0":{"868":1}}],["小游戏环境框架提供了高性能运行模式",{"2":{"1083":1}}],["小游戏环境不支持assetbundle本地加载",{"2":{"941":1}}],["小游戏环境适当降低画质",{"2":{"780":1}}],["小游戏底层会自动进行压缩减少网络传输",{"2":{"924":1}}],["小游戏",{"2":{"922":1}}],["小游戏appid",{"2":{"899":1}}],["小游戏android平台在8",{"2":{"1077":1}}],["小游戏android",{"0":{"739":1}}],["小游戏预览",{"0":{"896":1}}],["小游戏的屏幕适配与",{"2":{"1073":1}}],["小游戏的appid",{"2":{"893":1}}],["小游戏的中文字体不显示",{"0":{"474":1}}],["小游戏玩家对于启动时长更为敏感",{"2":{"868":1}}],["小游戏玩家对于游戏的启动时长是较为敏感的",{"2":{"546":1}}],["小游戏启动后将通过",{"2":{"902":1}}],["小游戏启动主要由三部分影响",{"2":{"871":1}}],["小游戏启动流程与时序",{"0":{"862":1},"1":{"863":1,"864":1,"865":1}}],["小游戏启动出现",{"0":{"471":1}}],["小游戏平台的压缩纹理支持",{"2":{"905":1}}],["小游戏平台不支持",{"2":{"799":1}}],["小游戏平台下不需要太大的纹理",{"2":{"363":1}}],["小游戏天生为",{"2":{"775":1}}],["小游戏内存口径",{"2":{"762":1}}],["小游戏数据助手",{"2":{"759":1,"768":1,"827":1}}],["小游戏云测试",{"0":{"770":1}}],["小游戏云测是使用大量真实的移动设备测试游戏的功能",{"2":{"741":1}}],["小游戏云测",{"0":{"741":1}}],["小游戏基础库",{"2":{"724":2}}],["小游戏公共库约占用内存100~150mb",{"2":{"712":1}}],["小游戏进程也就成为了",{"2":{"712":1}}],["小游戏提供了一系列接口获取好友关系链数据",{"2":{"697":1}}],["小游戏直接在",{"2":{"614":1}}],["小游戏实时日志",{"0":{"566":1},"2":{"564":1,"566":1}}],["小游戏接入指南",{"2":{"552":1}}],["小游戏存在开发者工具",{"2":{"541":1}}],["小游戏项目名",{"2":{"893":1,"899":1}}],["小游戏项目",{"2":{"534":1}}],["小游戏项目模板变更",{"2":{"324":1}}],["小游戏项目模板更新",{"2":{"313":1,"321":1}}],["小游戏profile",{"0":{"531":1}}],["小游戏主要存在三种类型的资源",{"2":{"501":1}}],["小游戏应该使用哪个接口进行限制帧率",{"0":{"488":1}}],["小游戏是否支持unity",{"0":{"487":1}}],["小游戏中多大的首包资源合适",{"2":{"917":1}}],["小游戏中能插入超链接跳转网页吗",{"0":{"486":1}}],["小游戏中主要的纹理资源格式",{"2":{"405":1}}],["小游戏包先不要删掉",{"2":{"1029":1}}],["小游戏包中的webgl",{"0":{"467":1}}],["小游戏包内",{"2":{"437":1,"893":1}}],["小游戏包内加载",{"2":{"353":1}}],["小游戏出现异常或错误时",{"2":{"446":1}}],["小游戏资源下载并发数为10",{"2":{"440":1}}],["小游戏分包",{"2":{"437":1,"924":1}}],["小游戏分包加载",{"2":{"75":1}}],["小游戏客服助手",{"0":{"563":1},"2":{"431":1,"561":1,"1098":1}}],["小游戏配置",{"2":{"423":1}}],["小游戏表现",{"2":{"423":1}}],["小游戏模板wechat",{"2":{"421":1}}],["小游戏模板错误",{"2":{"197":1}}],["小游戏退后台后返回音效无法继续播放了",{"2":{"367":1}}],["└──",{"2":{"435":5,"894":1}}],["└─",{"2":{"377":9,"383":5}}],["│",{"2":{"377":19,"383":16,"435":10}}],["├──",{"2":{"435":13,"436":3,"894":1}}],["├─",{"2":{"377":7,"383":4}}],["因最后赋值则有效",{"2":{"621":1}}],["因纹理打包规则不一致",{"2":{"511":1}}],["因本地存储的话",{"2":{"490":1}}],["因需要统计总包体大小",{"2":{"437":1}}],["因为上线后不可能也让玩家打开调试模式",{"2":{"984":1}}],["因为每次分配内存都会获取堆栈信息导致运行慢",{"2":{"973":1}}],["因为大多数unity",{"2":{"924":1}}],["因为存在较多bug",{"2":{"905":1}}],["因为当key达到几千个之后构建的资源索引文件",{"2":{"831":1}}],["因为小游戏对性能要求还是比较高",{"2":{"808":1}}],["因为开放数据域并不是使用",{"2":{"707":1}}],["因为unity纹理与",{"2":{"699":1}}],["因为该事件将被反复执行",{"2":{"678":1}}],["因为不同用户的设备宽度是不相同的",{"2":{"629":1}}],["因为这是一个动态构建的产物",{"2":{"614":1}}],["因为这里可以更好进行问题沉淀",{"2":{"562":1}}],["因为安卓采集profile文件需要手动控制",{"2":{"533":1}}],["因为30",{"2":{"488":1}}],["因为微信用户更容易删除小程序",{"2":{"472":1}}],["因为",{"2":{"433":1,"582":1,"977":1,"1074":1}}],["因为其中包含了大量的占位符将在导出时根据项目不同的实际情况作出替换",{"2":{"377":1}}],["因为随着新的sdk的更新覆盖也将失去其修改内容",{"2":{"377":1}}],["因此这里需要针对该特性在小游戏环境的支持进一步说明",{"2":{"1077":1}}],["因此之前的项目不能被用来增量更新",{"2":{"1040":1}}],["因此耗时上不需要看总的大小",{"2":{"1034":1}}],["因此耗时长的cpu运算会影响帧率",{"2":{"746":1}}],["因此对游戏运行影响最多只有加载子包的一次性影响",{"2":{"1031":1}}],["因此对性能更苛刻",{"2":{"736":1}}],["因此要求前后两个包都必须提供symbol文件",{"2":{"1024":1}}],["因此收集工作非常重要",{"2":{"1016":1}}],["因此必须提供",{"2":{"1001":1}}],["因此js侧内存压力会更大",{"2":{"974":1}}],["因此javascript",{"2":{"720":1}}],["因此不需要存储完整的assetbundle",{"2":{"945":1}}],["因此不推荐背景音乐等大文件使用",{"2":{"366":1}}],["因此占用下载带宽",{"2":{"874":1}}],["因此文件大小极为影响游戏的启动速度",{"2":{"873":1}}],["因此过长的启动时间将导致用户显著流失",{"2":{"868":1}}],["因此无论哪种方案最终都采用上传",{"2":{"828":1}}],["因此相对于js能更快达到jit指令优化后的峰值",{"2":{"735":1}}],["因此cpu算力会受限于虚拟机的执行效率",{"2":{"734":1}}],["因此转换面板的",{"2":{"727":1}}],["因此我们提供了代码分包工具",{"2":{"1014":1}}],["因此我们提供了专门的内存分配器忽略lua内存",{"2":{"973":1}}],["因此我们在底层对bundle文件做了缓存",{"2":{"944":1}}],["因此我们可以通过该能力分析更详细具体的分配行为",{"2":{"718":1}}],["因此我们需要将录制后的文件传输到pc使用chrome进行分析",{"2":{"351":1}}],["因此游戏内存的分配也是完全托管在这个环境中",{"2":{"712":1}}],["因此插件内置的示例采用的是微信自研的轻量级渲染引擎",{"2":{"705":1}}],["因此玩家打开游戏时首帧将看到具体的游戏画面",{"2":{"695":1}}],["因此使用前应阅读该能力文档",{"2":{"690":1}}],["因此建议游戏开发者合理接入该能力",{"2":{"689":1}}],["因此事件也是支持配置参数的",{"2":{"622":1}}],["因此该设置无效",{"2":{"621":2}}],["因此你可以将图片资源放置在本目录中以供引用",{"2":{"618":1}}],["因此配置性的操作是不能此完成",{"2":{"582":1}}],["因此开发者务必保证内存峰值不超过该数值",{"2":{"1090":1}}],["因此开发者需要关注这几部分内存",{"2":{"717":1}}],["因此开发者更清楚一个剧情的不同阶段的时间点",{"2":{"578":1}}],["因此开发者在",{"2":{"377":1}}],["因此上报剧情期间用户不同阶段的行为对于分析剧情内容与留存率是非常重要的",{"2":{"578":1}}],["因此推荐的设计是默认情况下仅播放5秒的启动动画",{"2":{"577":1}}],["因此是有可能在5秒的启动动画结束后",{"2":{"577":1}}],["因此主要配置由",{"2":{"574":1}}],["因此可以充分利用该时机进行一些必要的资源下载可有助于提升游戏场景等资源的载入速度",{"2":{"547":1}}],["因此如何快速呈现游戏场景是",{"2":{"546":1}}],["因此缓存规则也支持忽略某些文件",{"2":{"507":1}}],["因此需要注意业务中不要使用已淘汰的www类",{"2":{"947":1}}],["因此需要手动跑工具生成",{"2":{"889":1}}],["因此需要避免用于重度逻辑",{"2":{"744":1}}],["因此需要在必要的位置进行相关的数据上报",{"2":{"544":1}}],["因此需要根据场景中的主次内容进行资源上的优化分包处理",{"2":{"538":1}}],["因此需要开发者手动调用ontouch监听",{"2":{"491":1}}],["因此需要添加插件",{"2":{"466":1}}],["因此需要使用视频或图片等内容作为过渡以留住玩家",{"2":{"418":1,"957":1}}],["因此在接入故事线打点时请务必确保路径只会执行1次同sceneid的上报",{"2":{"690":1}}],["因此在异步结果返回前",{"2":{"577":1}}],["因此在",{"2":{"429":1}}],["因此在移动端中无法充分利用",{"2":{"386":1}}],["因此看似多条的请求背后系统仅会创建1条tcp",{"2":{"407":1}}],["因此非",{"2":{"405":1}}],["因此也是微信小游戏环境下主要使用到的压缩的纹理资源",{"2":{"393":1}}],["因此",{"2":{"386":1,"427":1,"433":1,"735":1,"775":1,"809":1,"839":1,"948":1,"975":1,"988":1,"1034":1}}],["因此wxsdk将识别到关键脚本发生更新且被开发者自定义覆盖的情况下作出警告",{"2":{"378":1}}],["目录结构说明",{"0":{"839":1}}],["目录内资源放到你的正式游戏工程导出的",{"2":{"615":1}}],["目录资源也将被实时更新",{"2":{"614":1}}],["目录是导出产物",{"2":{"582":1}}],["目录下创建",{"2":{"839":1}}],["目录下使用",{"2":{"615":1}}],["目录下的",{"2":{"493":1}}],["目录下标准模板绝对路径",{"2":{"384":1}}],["目录下",{"2":{"383":1,"922":1,"1005":1,"1014":1}}],["目录中资源将根据层级结构覆盖构建至",{"2":{"618":1}}],["目录中的任何资源",{"2":{"614":1}}],["目录中的资源变化被不断覆盖",{"2":{"614":1}}],["目录中的资源上传至",{"2":{"396":1}}],["目录中的资源内容将会按照完整的层级结构覆盖到最终的",{"2":{"377":1}}],["目录中执行",{"2":{"612":1}}],["目录中",{"2":{"576":1,"582":1,"618":2,"694":1}}],["目录中产物做一些定制化的修改",{"2":{"376":1}}],["目录",{"2":{"377":1,"396":1,"576":1,"613":1,"615":1,"704":1,"889":1,"934":1}}],["目录即为微信小游戏代码包",{"2":{"376":1}}],["目前已发现ios",{"2":{"1098":1}}],["目前已知一些版本无法使用",{"2":{"388":1}}],["目前还没出现这种情况",{"2":{"1036":1}}],["目前还不支持",{"2":{"814":1}}],["目前我们采用了一种",{"2":{"1016":1}}],["目前普通小游戏普遍启动时间为7~10s",{"2":{"869":1}}],["目前团结引擎",{"2":{"835":1}}],["目前需指定版本",{"2":{"829":1}}],["目前只支持js调用",{"2":{"826":1}}],["目前unityaudio将自动适配微信小游戏",{"2":{"712":1}}],["目前图片资源只能存放于小游戏",{"2":{"694":1}}],["目前可通过git",{"2":{"561":1}}],["目前为止",{"2":{"532":1}}],["目前建议中轻度2d",{"2":{"496":1}}],["目前微信小游戏已支持fmod转换的小游戏",{"2":{"478":1}}],["目前仍处于初期测试使用",{"2":{"400":1}}],["目前",{"2":{"365":1,"368":1,"809":1}}],["团结引擎详细安装请查阅sdk安装指引",{"2":{"1136":1}}],["团结引擎快适配",{"2":{"1133":1}}],["团结引擎适配方案",{"0":{"1133":1},"1":{"1134":1,"1135":1,"1136":1}}],["团结引擎相对于普通版本有特别之处",{"2":{"907":1}}],["团结引擎获取",{"0":{"906":1}}],["团结引擎基于2022",{"2":{"905":1,"907":1}}],["团结引擎",{"2":{"834":1,"836":1,"905":1}}],["团结引擎导出的小游戏卡在loading界面并提示",{"0":{"492":1}}],["团结引擎已无需开启该能力",{"2":{"355":1}}],["团结快适配项目最终导出",{"2":{"376":1}}],["\\t",{"2":{"979":5,"983":1}}],["\\tconst",{"2":{"374":1}}],["\\tconsole",{"2":{"374":3}}],["\\t\\t\\t\\t",{"2":{"979":1,"983":1}}],["\\t\\t",{"2":{"374":1}}],["则可进入高性能模式",{"2":{"1088":1}}],["则可在游戏侧完成控制",{"2":{"580":1}}],["则返回缓存文件",{"2":{"944":1}}],["则作为视频封面",{"2":{"893":1}}],["则要这要做一下换算",{"2":{"707":1}}],["则左上角就是离屏幕的距离",{"2":{"707":1}}],["则产生视频跳转",{"2":{"635":1}}],["则不跳转",{"2":{"632":1,"644":1}}],["则在注册该方法时会立即产生回调",{"2":{"602":1}}],["则为高性能模式",{"2":{"1093":1}}],["则为",{"2":{"591":1}}],["则需要使用",{"2":{"982":1}}],["则需要继续迭代",{"2":{"796":1}}],["则需要优化",{"2":{"794":1}}],["则需要根据",{"2":{"707":1}}],["则需要删除streamingassets",{"2":{"513":1}}],["则需要选",{"2":{"374":1}}],["则缓存路径=$",{"2":{"513":1}}],["则先清理旧缓存",{"2":{"509":1}}],["则此处填写目录的绝对路径",{"2":{"414":1,"417":1}}],["则将采用",{"2":{"405":1}}],["则无需修改",{"2":{"374":1}}],["模型闪烁",{"0":{"1079":1}}],["模型",{"2":{"829":1}}],["模拟器",{"2":{"675":1}}],["模拟经营游戏",{"2":{"854":1}}],["模拟经营",{"2":{"496":1,"727":1,"758":1,"1113":1}}],["模块",{"2":{"374":2}}],["模式下",{"2":{"839":1}}],["模式下这个占位纹理会对应有一个",{"2":{"697":1}}],["模式",{"2":{"356":1}}],["本方案设计目的是降低",{"2":{"1133":1}}],["本",{"2":{"1005":1}}],["本机堆",{"2":{"717":4}}],["本机堆与原生插件底层内存",{"2":{"712":1}}],["本机安装的",{"2":{"409":1}}],["本节总结的列举开发者对不同类型的游戏应重点关注的优化内容",{"2":{"830":1}}],["本节说明三种方案的差异",{"2":{"829":1}}],["本节仅介绍全局变量在剧情编辑时的创建及属性介绍",{"2":{"679":1}}],["本节将介绍目前微信小游戏平台为开发者提供的调优能力完成上线前的最后优化工作",{"2":{"545":1}}],["本节将对配置文件中各项字段进行说明",{"2":{"352":1}}],["本演示将提供呼吸态按钮的实现",{"2":{"678":1}}],["本构建工具已经为开发者配置好了相关类型声明",{"2":{"618":1}}],["本案例名",{"2":{"612":1}}],["本地无可用系统字体",{"2":{"1003":1}}],["本地设置",{"2":{"984":1,"985":1}}],["本地读取等",{"2":{"577":1}}],["本地有特定缓存标识意味已经不是首次访问可以不播放",{"2":{"576":1}}],["本地化后我们可以自由地定制化",{"2":{"428":1}}],["本地化",{"0":{"428":1},"2":{"427":1}}],["本篇重点介绍业务资源的缓存规则",{"2":{"501":1}}],["本文介绍如何使用unity新的资源管理流程addressable",{"2":{"917":1}}],["本文档主要关于",{"2":{"806":1}}],["本文档主要说明如何在",{"2":{"427":1}}],["本文主要介绍unity",{"2":{"733":1}}],["本文阐述在微信小游戏环境的最佳实践",{"2":{"564":1}}],["本文阐述开发者在遇到转换后的游戏在开发者工具或真机遇到异常时",{"2":{"444":1}}],["本身的代码包",{"2":{"428":1}}],["本云函数仅依赖了",{"2":{"374":1}}],["本示例为",{"2":{"374":2}}],["生产提效包",{"2":{"464":1,"512":1,"523":1,"827":1,"834":1,"896":1,"1088":1,"1136":1}}],["生产环境",{"2":{"374":1}}],["生成release版分包",{"2":{"1029":1}}],["生成时工具会自动从webgl",{"2":{"991":1}}],["生成微信小游戏项目时",{"2":{"952":1}}],["生成的类",{"2":{"873":1}}],["生成的",{"2":{"807":1}}],["生成的纹理太大",{"0":{"403":1}}],["生成剧本产物",{"2":{"575":1}}],["生成代码小15",{"2":{"355":1}}],["部署",{"0":{"936":1},"1":{"937":1,"938":1,"939":1}}],["部署首资源包需要注意",{"2":{"924":1}}],["部署云函数",{"2":{"374":1}}],["部分示意图可能有出入",{"2":{"1130":1}}],["部分",{"2":{"1010":1}}],["部分版本会出现无法连接的情况",{"2":{"740":1}}],["部分游戏使用异步模式",{"2":{"571":1}}],["部分支持",{"2":{"498":1}}],["部分变量全精度改为半精度",{"2":{"431":1}}],["部分音频文件在安卓无法循环播放",{"2":{"367":1}}],["部分类",{"2":{"109":1}}],["部分js",{"2":{"5":1}}],["为进一步保障wasm小游戏的代码安全",{"2":{"1128":1}}],["为如下所示c",{"2":{"973":1}}],["为high",{"2":{"874":1}}],["为加快二次启动",{"2":{"865":1}}],["为兼容需要",{"2":{"839":1}}],["为兼容历史团结",{"2":{"834":1}}],["为保证稳定性",{"2":{"834":1,"1136":1}}],["为何需要进行性能优化",{"0":{"775":1}}],["为方便使用一般在剧情最早的时候进行创建并挂载到主故事线中",{"2":{"680":1}}],["为",{"2":{"628":1,"748":1,"817":1,"1088":1}}],["为此",{"2":{"945":1}}],["为此提供本指南及工具",{"2":{"607":1}}],["为此微信提供配置构建模板的能力",{"2":{"376":1}}],["为未运行或已播放结束资源析构",{"2":{"600":1}}],["为未运行或已播放结束资源已完成析构",{"2":{"584":1}}],["为避免发生异常时用户无法退出启动剧情插件",{"2":{"589":1}}],["为主",{"2":{"582":1}}],["为游戏的主逻辑争取更多的下载",{"2":{"568":1}}],["为你期望的值",{"2":{"507":1}}],["为你便捷的提供了各个目录的绝对路径",{"2":{"384":1}}],["为什么开启了高性能模式",{"0":{"1099":1},"2":{"1082":1}}],["为什么开发者工具正常",{"2":{"984":1}}],["为什么开放数据域滚动事件不生效",{"2":{"709":1}}],["为什么需要性能评测标准",{"0":{"755":1,"1103":1,"1117":1}}],["为什么我关闭排行榜之后界面上有些问题错乱了",{"2":{"709":1}}],["为什么第一次调用",{"2":{"709":1}}],["为什么要做启动优化",{"0":{"867":1},"1":{"868":1,"869":1}}],["为什么要放首帧图片",{"0":{"695":1}}],["为什么要用条件编译宏来定制代码",{"2":{"429":1}}],["为什么在",{"2":{"370":1}}],["为简化调用",{"2":{"411":1}}],["为了充分利用网络带宽",{"2":{"938":1,"963":1}}],["为了能让导出包运行在微信小游戏环境",{"2":{"885":1}}],["为了能够帮助开发者快速了解游戏整体的性能情况",{"2":{"767":1}}],["为了详细统计玩家的流失情况以便开发者进行优化",{"2":{"825":1}}],["为了帮助开发者分析广告渠道的留存数据",{"2":{"823":1}}],["为了使游戏达到比较好的性能表现",{"2":{"784":1}}],["为了使用群排行榜",{"2":{"708":1}}],["为了提高游戏在中低端机型的稳定性",{"2":{"711":1}}],["为了安全",{"2":{"697":1}}],["为了录制启动阶段完整的profile",{"2":{"533":1}}],["为了避免新版本发布时由于cdn缓存导致加载到旧版本资源",{"2":{"441":1}}],["为了确保压缩纹理工具的顺利进行",{"2":{"388":1}}],["为了统一约定",{"2":{"383":1}}],["为弥补这一缺陷",{"2":{"386":1}}],["为例",{"2":{"374":1}}],["中档机",{"2":{"1123":2,"1124":2}}],["中档",{"2":{"1105":1,"1120":1}}],["中高端机",{"2":{"1090":1}}],["中高档机为iphone",{"2":{"711":1}}],["中高档机",{"2":{"711":2}}],["中低端机帧率较低",{"2":{"1083":1}}],["中获取的安全区域的数值",{"2":{"1073":1}}],["中兼容低版本基础库",{"0":{"1007":1}}],["中文竖排标点",{"2":{"1004":1}}],["中文标点符号",{"2":{"1004":1}}],["中文字体大小少则2",{"2":{"1000":1}}],["中文显示需要自定义字体",{"2":{"873":1}}],["中开发者可以使用微信基础库中的tcpsocket",{"2":{"978":1}}],["中使用",{"2":{"976":1}}],["中使用了一个",{"2":{"622":1}}],["中不能工作",{"2":{"975":1}}],["中国特供版下载地址",{"2":{"906":1}}],["中度",{"2":{"758":1,"1113":1}}],["中度游戏",{"2":{"727":1}}],["中修改配置",{"2":{"748":1,"817":1}}],["中重度游戏应保证中高档机不限帧时达到40fps以上",{"2":{"737":1}}],["中重度游戏建议开启ios高性能模式以支持jit",{"2":{"736":1}}],["中向开放域页面传递数据",{"2":{"703":1}}],["中表现异常",{"2":{"675":1}}],["中是放了一个由",{"2":{"622":1}}],["中是上下文中开发者自行创建的名为",{"2":{"622":1}}],["中这样仅修改属性值就可以替换成自己的游戏素材还是十分便捷",{"2":{"616":1}}],["中说明",{"2":{"615":1}}],["中你开启的命令行窗口",{"2":{"615":1}}],["中启动的开发模式还在工作",{"2":{"614":1}}],["中随意的预览你创作的剧情设计",{"2":{"609":1}}],["中除了",{"2":{"583":1}}],["中小型游戏",{"2":{"557":1}}],["中存储",{"2":{"549":1}}],["中",{"2":{"523":1,"576":1,"618":1,"965":1}}],["中以下配置与缓存相关",{"2":{"505":1}}],["中分离单独托管",{"2":{"386":1}}],["中进行新的脚本创建",{"2":{"384":1}}],["中的大小",{"2":{"1073":1}}],["中的配置needcheckupdate",{"2":{"913":1}}],["中的内存",{"2":{"712":1}}],["中的内容实现服务端逻辑",{"2":{"374":1}}],["中的",{"2":{"622":1,"977":1}}],["中的代码资源",{"2":{"614":1}}],["中的关键脚本",{"2":{"378":1}}],["中的资源作为参考",{"2":{"377":1}}],["中的脚本为修改基准",{"2":{"377":1}}],["中指定",{"2":{"374":1}}],["中函数",{"2":{"70":1}}],["新一代的addressable正是对这些痛点做了不少改进",{"2":{"920":1}}],["新的高性能模式",{"2":{"1015":1}}],["新的值",{"2":{"664":1}}],["新的关键动作帧",{"2":{"634":1,"646":1}}],["新版的插件已经规避这个问题",{"2":{"1039":1}}],["新版导出插件使用小游戏插件来渲染关系链数据",{"2":{"466":1}}],["新版本无需修改",{"2":{"981":1}}],["新版本已新增memorysize",{"2":{"753":1}}],["新版本异常回退说明",{"0":{"400":1}}],["新版本sdk引起的冲突提醒",{"0":{"378":1},"1":{"379":1}}],["新建一个云函数的空工程",{"2":{"374":1}}],["新增收集函数个数这个数据非常重要",{"2":{"1029":1}}],["新增收集函数个数清零",{"2":{"1029":1}}],["新增收集的函数要重新再次提审才会在首包吗",{"0":{"1035":1},"2":{"1012":1}}],["新增wxcleanallfilecache接口",{"2":{"258":1}}],["新增api",{"2":{"252":1,"261":1}}],["新增录屏接口功能",{"2":{"145":1}}],["新增米大师接口requestmidaspaymentgameitem",{"2":{"81":1}}],["新增tcp接口能力",{"2":{"42":1}}],["新增启动剧情能力",{"2":{"42":1}}],["混合的模式",{"2":{"372":1}}],["详情请查阅",{"2":{"1097":1}}],["详情参考资源缓存",{"2":{"964":1}}],["详情可参考unity",{"2":{"812":1}}],["详情可查阅性能诊断工具",{"2":{"771":1}}],["详情可见链接",{"2":{"708":1}}],["详情查看音频视频适配",{"2":{"487":1}}],["详见资源缓存",{"2":{"999":1}}],["详见",{"2":{"707":1,"708":1}}],["详见云开发",{"2":{"372":1}}],["详细文档请查阅高性能+模式",{"2":{"1084":1}}],["详细示例可参考系统字体demo",{"2":{"1002":1}}],["详细示例请参考api",{"2":{"555":1}}],["详细配置请参考使用预下载功能",{"2":{"938":1,"963":1}}],["详细内容可查阅",{"2":{"829":1}}],["详细内容通过vconsole打印",{"2":{"786":1}}],["详细接口可参考c",{"2":{"825":1}}],["详细可通过",{"2":{"767":1}}],["详细的基准机型与性能要求可参考性能评估标准",{"2":{"737":1}}],["详细步骤",{"0":{"698":1},"1":{"699":1,"700":1,"701":1,"702":1,"703":1,"704":1,"705":1,"706":1,"707":1,"708":1}}],["详细缓存日志不写入日志管理器",{"2":{"78":1}}],["通骁⻰625",{"2":{"1105":1,"1120":1}}],["通用标点符号",{"2":{"1004":1}}],["通用",{"2":{"808":1}}],["通用渲染管线",{"2":{"427":1}}],["通常可以3~5mb左右的内容",{"2":{"999":1}}],["通常平均耗时会在3~6s左右",{"2":{"988":1}}],["通常是由于安全域名与ssl证书",{"2":{"984":1}}],["通常是问题所在",{"2":{"451":1}}],["通常需要再asset或其子目录下创建resources的文件夹",{"2":{"934":1}}],["通常需要适配",{"2":{"829":2}}],["通常使用",{"2":{"902":1}}],["通常呈现splah场景即可",{"2":{"875":1}}],["通常呈现splash场景即可",{"2":{"530":1}}],["通常定义为用户可交互的时机",{"2":{"759":1,"1106":1}}],["通常为assetbundle",{"2":{"759":1,"1106":1,"1120":1}}],["通常包含较多游戏场景或支持多人在线游戏",{"2":{"758":1,"1113":1}}],["通常",{"2":{"724":1,"727":1,"812":1,"924":1}}],["通常我们可以使用浏览器自带的内存工具",{"2":{"720":1}}],["通常我们从异常log中找到函数id",{"2":{"452":1}}],["通常而言",{"2":{"717":1,"734":1,"735":1}}],["通常用于透明点击区域",{"2":{"658":1}}],["通常也将重新加载游戏内容",{"2":{"614":1}}],["通常无需替换",{"2":{"489":1}}],["通常有以下两种方式避免",{"2":{"441":1}}],["通信",{"0":{"976":1},"1":{"977":1},"2":{"372":1,"373":1}}],["通过去掉此开关可以正常回退到普通模式",{"2":{"1088":1}}],["通过多款游戏项目",{"2":{"1086":1}}],["通过多路复用和头部压缩的特性",{"2":{"799":1}}],["通过开发者工具的设置",{"2":{"1017":1}}],["通过真机运行小游戏",{"2":{"1016":1}}],["通过运行时收集信息",{"2":{"1016":1}}],["通过微信系统字体",{"2":{"1000":1}}],["通过手机端小游戏右上角菜单",{"2":{"985":1}}],["通过详情",{"2":{"984":1,"985":1}}],["通过修改minigame",{"2":{"965":1}}],["通过修改unity",{"2":{"871":1}}],["通过接口修改",{"0":{"956":1}}],["通过加载前后snapshot来对比总内存变化",{"2":{"947":1}}],["通过addressable检查bultin分组",{"2":{"924":1}}],["通过勾选",{"2":{"913":1}}],["通过切石",{"2":{"854":1}}],["通过c",{"2":{"822":1,"995":1}}],["通过小游戏数据助手查看",{"2":{"759":1,"1106":1}}],["通过timelog",{"2":{"759":2,"1106":2,"1120":2}}],["通过texturespath可让loader识别一条请求是否为纹理",{"2":{"508":1}}],["通过优化逻辑分帧加载可大幅度提升游戏体验",{"2":{"746":1}}],["通过上面的改造",{"2":{"533":1}}],["通过usb链接电脑或者第三方文件管理器即可将profile文件传输至电脑",{"2":{"531":1}}],["通过文件名中的hash区分同名文件的不同版本",{"2":{"513":1}}],["通过文件名中带资源hash",{"2":{"510":1}}],["通过导出的小游戏minigame",{"2":{"512":1}}],["通过细粒度的资源拆分",{"2":{"501":1}}],["通过日志的函数id找到对应的原始函数名",{"2":{"449":1}}],["通过以下方式打开",{"2":{"446":1}}],["通过宏wx",{"2":{"429":1}}],["通过",{"0":{"703":1},"2":{"373":1,"493":1,"988":1}}],["通过替换脚本对cpuprofile进行自动映射到真实函数",{"2":{"351":1}}],["通过webgl导出目录下的symbols文件对照映射",{"2":{"351":1}}],["通过分包加载资源时读取bug",{"2":{"220":1}}],["通过disablehighperformancefallback修改",{"2":{"115":1}}],["先android收集",{"2":{"1019":1}}],["先下载版本a",{"2":{"526":1}}],["先把本地的",{"2":{"433":1}}],["先展示背景图",{"2":{"421":1,"423":1,"959":1}}],["先主动切换到3",{"2":{"370":1}}],["先临时关闭高性能+",{"2":{"370":1}}],["还可以根据项目类型或项目需要简化或去掉",{"2":{"430":1}}],["还会存入内存中的unitycache",{"2":{"947":1}}],["还会启用shader",{"2":{"429":1}}],["还会安装其他依赖包",{"2":{"428":1}}],["还有",{"2":{"429":1}}],["还要对渲染管线有一定了解",{"2":{"427":1}}],["还是",{"0":{"807":1,"809":1},"2":{"370":1}}],["还原时",{"2":{"362":1}}],["只要用了https",{"2":{"986":1}}],["只要不要放到工程目录下即可",{"2":{"428":1}}],["只影响开发版",{"2":{"785":1}}],["只能定期刷新纹理来实现同步开放数据域的变化",{"2":{"697":1}}],["只能从主域流向开放数据域",{"2":{"697":1}}],["只能从逻辑上兼容",{"2":{"370":1}}],["只接受",{"2":{"628":1}}],["只需存储包头",{"2":{"945":1}}],["只需在你的pc命令行中输入",{"2":{"610":1}}],["只需要在命令行中输入",{"2":{"616":1}}],["只需要自定义模板目录放置json",{"2":{"380":1}}],["只需要配置服务端允许微信跨域访问即可",{"2":{"370":1}}],["只读属性",{"2":{"584":1}}],["只可通过fs接口主动删除",{"2":{"512":1}}],["只保留第一个",{"2":{"493":1}}],["只保留",{"2":{"431":1,"1010":1}}],["只支持网络url",{"2":{"959":1}}],["只支持",{"2":{"431":1}}],["只支持最基础的",{"2":{"431":1}}],["只支持一盏实时方向光",{"2":{"431":1}}],["只会检查",{"2":{"378":1}}],["只有使用到已被清理的bundle时才会一次性从磁盘完整读进内存",{"2":{"945":1}}],["只有在",{"2":{"809":1}}],["只有全屏视频的场景也可以选择使用wxvideo",{"2":{"368":1}}],["只有开通高性能模式后并确认不回退才修改",{"2":{"353":1}}],["无字体文件内容",{"2":{"1003":1}}],["无中文字体",{"2":{"1003":1}}],["无尽冬日",{"0":{"845":1}}],["无直接的api能力调用可使用读取系统信息等api",{"2":{"841":1}}],["无内购",{"2":{"758":1,"1113":1}}],["无养成体系",{"2":{"758":1,"1113":1}}],["无论是addressable还是assetbundle在微信小游戏底层都使用xhr进行远程资源访问",{"2":{"921":1}}],["无论是启动耗时或运行时流畅分析都非常有用",{"2":{"739":1}}],["无论从启动还是运行上我们都需要做进一步性能优化",{"2":{"775":1}}],["无论哪一种方案都需要开发者专项的适配",{"2":{"557":1}}],["无缓存",{"2":{"515":1,"1003":1}}],["无法关闭",{"2":{"986":1}}],["无法使用loadfromfile",{"2":{"945":1}}],["无法立刻影响到所有现网用户",{"2":{"911":1}}],["无法启动问题",{"2":{"741":1}}],["无法正确处理版本信息",{"2":{"513":1}}],["无法播放",{"2":{"370":1}}],["无堆栈信息",{"2":{"451":2}}],["无需重写游戏核心逻辑",{"2":{"1134":1}}],["无需更换unity引擎与重写核心代码的情况下将原有游戏项目适配到微信小游戏",{"2":{"1133":1}}],["无需担心开启profiling",{"2":{"1024":1}}],["无需网络下载",{"2":{"1001":1}}],["无需做其他处理",{"2":{"999":1}}],["无需登记安全域名",{"2":{"984":1}}],["无需手动上报",{"2":{"822":1}}],["无需考虑卸载动画函数",{"2":{"675":1}}],["无需开发手动释放",{"2":{"587":1}}],["无需清理",{"2":{"521":1}}],["无需node支持",{"2":{"102":1}}],["无需再调用小游戏的帧率设置api",{"2":{"59":1}}],["+=",{"2":{"926":1,"927":1,"930":1,"981":4}}],["+webgl为核心的技术方案",{"2":{"733":1}}],["+",{"0":{"1026":1},"2":{"369":1,"377":1,"428":2,"437":2,"615":2,"717":2,"724":14,"752":1,"825":3,"836":1,"942":1,"943":4,"945":2,"979":3,"983":2,"1012":1}}],["参见建议第五点",{"2":{"799":1}}],["参阅",{"2":{"665":1}}],["参照小游戏资源部署章节进行资源部署",{"2":{"895":1}}],["参照示例修修改改很快能够上手",{"2":{"705":1}}],["参照unity的benchmark项目",{"2":{"532":1}}],["参照指引放开域名限制微信开发者工具域名列表",{"2":{"465":1}}],["参考lauxlib",{"2":{"973":1}}],["参考常见问题",{"2":{"967":1}}],["参考示例如下",{"2":{"945":1}}],["参考小游戏快速开始",{"2":{"896":1}}],["参考资料",{"0":{"887":1,"939":1,"949":1}}],["参考文档",{"0":{"820":1,"1081":1}}],["参考文档小游戏启动流程中提到的",{"2":{"532":1}}],["参考已转化的案例游戏并结合自身游戏情况评估转化的可行性",{"2":{"535":1}}],["参考本篇",{"2":{"529":1}}],["参考代码如下",{"2":{"468":1}}],["参考指引转换工具导出微信小游戏",{"2":{"464":1}}],["参考",{"0":{"434":1},"2":{"499":1}}],["参考unity",{"2":{"367":1,"528":1}}],["参数为",{"2":{"614":1}}],["参数非法",{"2":{"374":1}}],["参数",{"0":{"414":1,"417":1},"2":{"369":1,"414":1,"417":1,"633":1,"645":1,"656":1,"660":1,"672":1,"677":1,"682":1,"687":1}}],["社区回答",{"2":{"367":1}}],["旧系统资源改造",{"0":{"933":1}}],["旧缓存",{"2":{"516":1}}],["旧版本使用指引请参阅",{"2":{"400":1}}],["旧版本引擎已知问题",{"2":{"367":1}}],["旧",{"2":{"400":2}}],["旧api批量重命名",{"2":{"261":1}}],["格式渲染",{"2":{"405":1}}],["格式是",{"2":{"405":1}}],["格式支持",{"2":{"388":1}}],["格式",{"2":{"367":1,"393":1,"395":1,"405":1}}],["是一种用于在",{"2":{"1076":1}}],["是一个离屏的",{"2":{"697":1}}],["是一个可变系数",{"2":{"622":1}}],["是的",{"2":{"1011":1}}],["是异步的",{"2":{"977":1}}],["是因为www",{"2":{"947":1}}],["是由",{"2":{"829":1}}],["是可以尝试用压缩纹理",{"2":{"813":1}}],["是什么",{"2":{"812":1}}],["是用了",{"2":{"807":1}}],["是用于初始化剧情的回调事件",{"2":{"576":1}}],["是距离屏幕左上角的距离",{"2":{"707":2}}],["是最常见的实用应用",{"2":{"678":1}}],["是整个剧情的编辑句柄",{"2":{"618":1}}],["是整个游戏客户端启动的入口",{"2":{"582":1}}],["是固定的剧情撰写文件",{"2":{"618":1}}],["是固定的启动剧情资源目录",{"2":{"618":1}}],["是做什么用的",{"0":{"467":1}}],["是几种选择中鲁棒性和信息提示较为均衡的",{"2":{"451":1}}],["是具体项目具体分析的",{"2":{"430":1}}],["是不同的概念",{"2":{"815":1}}],["是不一样",{"2":{"807":1}}],["是不支持使用原生套接字",{"2":{"539":1}}],["是不生效的",{"2":{"429":1}}],["是不受纹理资源高宽影响的",{"2":{"405":1}}],["是",{"2":{"427":1,"428":3,"429":1}}],["是多数移动设备中游戏运行的主要支持的纹理格式",{"2":{"393":1}}],["是项目的基础模板",{"2":{"377":1}}],["是有可能造成游戏延迟卡顿的",{"2":{"367":1}}],["是否有跨域头",{"2":{"1096":1}}],["是否有wait",{"2":{"1029":1}}],["是否为",{"2":{"1095":1}}],["是否callmain完成立即隐藏封面",{"2":{"959":1}}],["是否callmain完成后立即隐藏封面",{"2":{"420":1,"422":1,"958":1}}],["是否可以直接使用",{"2":{"907":1}}],["是否初始化完成立即隐藏封面",{"2":{"900":1}}],["是否ios高性能模式",{"2":{"826":1}}],["是否资源文件大部分未缓存",{"2":{"799":1}}],["是否自动缓存的资源",{"2":{"798":1}}],["是否自动播放",{"2":{"632":1,"644":1}}],["是否命中cdn缓存",{"2":{"798":1}}],["是否请求了settings",{"2":{"798":1}}],["是否请求了catalog",{"2":{"798":2}}],["是否在引擎初始化期间加载子包",{"2":{"795":1}}],["是否启用http2",{"2":{"792":1}}],["是否一直检测到游戏可交互完成",{"2":{"785":1}}],["是否代表游戏内存无问题",{"2":{"731":1}}],["是否足够",{"2":{"731":1}}],["是否",{"2":{"688":1}}],["是否循环播放",{"2":{"632":1,"644":1}}],["是否播放中",{"2":{"632":1,"644":1}}],["是否接入自定义外显进度条",{"2":{"585":1}}],["是否隐藏",{"2":{"580":1,"585":1}}],["是否支持",{"2":{"498":1}}],["是否适用于",{"2":{"433":1}}],["是否不透明",{"2":{"431":1}}],["是否需要返回localinfo和remoteinfo",{"2":{"979":1,"983":1}}],["是否需要清理",{"2":{"513":1}}],["是否需要callmain结束后立即隐藏封面视频",{"2":{"421":1}}],["是否需要启动时自动检查小游戏是否有新版本",{"2":{"353":1}}],["是否强制重新执行",{"2":{"356":1}}],["是否开启纹理缓存",{"2":{"900":1}}],["是否开启服务器压缩",{"2":{"798":1}}],["是否开启http2",{"2":{"798":1}}],["是否开启了服务器压缩",{"2":{"792":1,"798":1}}],["是否开启检测",{"2":{"785":1}}],["是否开启仅",{"2":{"356":1}}],["是否开启",{"2":{"356":1}}],["是否显示icon",{"2":{"421":1}}],["是否显示渲染分析日志",{"2":{"355":1}}],["是否显示性能面板",{"2":{"355":1}}],["是否显示最佳实践检测弹框",{"2":{"355":1}}],["是否使用代码分包",{"2":{"826":1}}],["是否使用本地缓存",{"2":{"798":1}}],["是否使用了wasm代码分包",{"2":{"789":1}}],["是否使用自适应屏幕尺寸变化",{"2":{"355":1}}],["是否使用brotli多线程压缩",{"2":{"355":1}}],["是否使用ios高性能plus",{"2":{"355":1}}],["是否使用预载系统字体",{"2":{"354":1}}],["是否使用社交组件",{"2":{"354":1}}],["是否使用好友关系链",{"2":{"354":1}}],["是否禁止开启高性能模式后在不支持的ios设备上回退为普通模式",{"2":{"353":1}}],["是否缓存纹理",{"0":{"508":1},"2":{"500":1,"505":1}}],["是否缓存纹理开关",{"2":{"228":1}}],["是否缓存业务资源",{"0":{"507":1},"2":{"500":1}}],["是否缓存规则",{"0":{"506":1},"1":{"507":1,"508":1},"2":{"500":1}}],["是否缓存微信压缩纹理工具处理的贴图资源",{"2":{"353":1}}],["偶现音频报错",{"2":{"367":1}}],["会自动对页面做一个兼容适配",{"2":{"1074":1}}],["会自动缓存",{"2":{"507":1}}],["会出现如下界面",{"2":{"1132":1}}],["会出现闪烁问题",{"0":{"1098":1},"2":{"1082":1}}],["会出现绘制不正确",{"2":{"1079":1}}],["会出现画面模糊的情况",{"2":{"1074":1}}],["会出现插件无法正常更新或安装",{"2":{"1042":1}}],["会先跳到前面的等待分包界面",{"2":{"1027":1}}],["会转为按函数粒度按需加载",{"2":{"1014":1}}],["会不会最终跑到所有函数都收集的情况",{"0":{"1036":1},"2":{"1012":1}}],["会按照列表顺序发起预下载",{"2":{"999":1}}],["会强制检查",{"2":{"985":1}}],["会降低性能",{"2":{"979":1,"983":1}}],["会加重这个问题",{"2":{"973":1}}],["会将首包资源存放在minigame",{"2":{"960":1}}],["会将函数返回值转换为json后传回",{"2":{"424":1}}],["会经历多次内存分配",{"2":{"948":1}}],["会浪费不少内存",{"2":{"947":1}}],["会导致app与小游戏不同的加载流程",{"2":{"944":1}}],["会导致无法更新到最新版本",{"2":{"799":1}}],["会导致无法更新",{"2":{"799":1}}],["会静默更新到最新版本",{"2":{"911":1}}],["会大于10个",{"2":{"798":1}}],["会比较臃肿",{"2":{"735":1}}],["会声明使用开放数据域",{"2":{"704":1}}],["会调用",{"2":{"697":1}}],["会因下面设置会覆盖",{"2":{"621":2}}],["会弹出浮窗告知profile文件的存储路径",{"2":{"531":1}}],["会在引擎初始完成后继续进行",{"2":{"996":1}}],["会在内存中持有",{"2":{"988":1}}],["会在开发阶段输出错误日志缓存路径不合法",{"2":{"527":1}}],["会在导出路径下生成如下目录",{"2":{"435":1,"894":1}}],["会默认多清理30mb的空间",{"2":{"512":1}}],["会携带32位长度的hash拼接到文件名末尾",{"2":{"510":1}}],["会严重影响性能",{"2":{"451":1}}],["会直接导致程序终止",{"2":{"451":1}}],["会被当作不透明物体",{"2":{"431":1}}],["会报错origin",{"2":{"370":1}}],["会占用很大内存",{"2":{"366":1}}],["会删除library",{"2":{"362":1}}],["播放的音频的关键动作帧句柄",{"2":{"651":1}}],["播放的视频的关键动作帧句柄",{"2":{"640":1}}],["播放音频时将占用的内存",{"2":{"712":1}}],["播放音频",{"2":{"650":1}}],["播放结束时",{"2":{"622":1}}],["播放到第n秒时",{"2":{"622":2}}],["播放视频",{"2":{"421":1,"423":1,"639":1,"959":1}}],["播放有声音没画面",{"2":{"370":1}}],["播放",{"2":{"366":1,"634":1,"646":1}}],["短音频播放使用的是webaudio",{"2":{"366":1}}],["优点",{"2":{"808":3}}],["优秀作品",{"0":{"571":1}}],["优先排查是否stable版本的微信开发者工具",{"2":{"1046":1}}],["优先将画面呈现",{"2":{"530":1,"875":1}}],["优先建议使用",{"2":{"365":1}}],["优化总览",{"0":{"877":1}}],["优化可参考",{"2":{"876":1}}],["优化的目标与标准",{"0":{"869":1}}],["优化手段",{"2":{"790":4,"793":5,"796":3,"799":8}}],["优化分析工具",{"0":{"803":1},"1":{"804":1},"2":{"783":1}}],["优化目标",{"0":{"737":1,"776":1}}],["优化unity",{"0":{"710":1,"732":1},"1":{"711":1,"712":1,"713":1,"714":1,"715":1,"716":1,"717":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"730":1,"731":1,"733":1,"734":1,"735":1,"736":1,"737":1,"738":1,"739":1,"740":1,"741":1,"742":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1,"752":1,"753":1},"2":{"548":1,"781":1}}],["优化udp接口能力",{"2":{"40":1}}],["优化",{"2":{"430":1,"548":1}}],["优化建议通过弹框提示",{"2":{"786":1}}],["优化建议概览",{"0":{"790":1,"793":1,"796":1,"799":1,"802":1},"2":{"783":5}}],["优化建议",{"0":{"363":1},"2":{"799":1,"831":1,"832":1,"833":1}}],["优化maxsize",{"2":{"362":1}}],["优化插件更新提示",{"2":{"332":1}}],["优化文件删除",{"2":{"313":1}}],["优化缓存目录统计",{"2":{"199":1}}],["优化启动插件内存占用",{"2":{"113":1}}],["优化启动剧情能力",{"2":{"40":1}}],["优化开发版",{"2":{"105":1}}],["优化framework胶水层获取canvas与宽高属性的性能损耗",{"2":{"102":1}}],["优化面板",{"2":{"94":1}}],["优化wxtouchinputoverride",{"2":{"89":1}}],["优化wxassetbundle当unitywebrequest异常时downloadhandlerwxassetbundle",{"2":{"65":1}}],["优化构建",{"2":{"70":1}}],["优化微信字体所占用的monoheap临时内存",{"2":{"47":1}}],["优化胶水层代码",{"2":{"47":1}}],["优化tcp接口能力",{"2":{"40":1}}],["优化videoplayer组件",{"2":{"26":1}}],["优化对团结版的导出支持",{"2":{"24":1}}],["音轨",{"2":{"1126":1}}],["音轨sample",{"2":{"1126":1}}],["音轨格式",{"2":{"1126":1}}],["音量",{"2":{"644":1}}],["音视频适配",{"0":{"364":1},"1":{"365":1,"366":1,"367":1,"368":1,"369":1,"370":1}}],["音频支持",{"2":{"907":1}}],["音频支持获取播放状态",{"2":{"315":1}}],["音频将占用小游戏环境的内存",{"2":{"729":1}}],["音频内存",{"0":{"729":1}}],["音频开始播放时",{"2":{"645":1}}],["音频播放结束时",{"2":{"645":1}}],["音频播放时游戏卡顿",{"2":{"367":1}}],["音频播放时小游戏退后台就有可能出现",{"2":{"367":1}}],["音频资源",{"2":{"829":1}}],["音频资源尽可能勾选强制单声道",{"2":{"781":1}}],["音频资源cdn地址",{"2":{"644":1}}],["音频资源均需要存放至",{"2":{"618":1}}],["音频相关",{"0":{"642":1},"1":{"643":1,"644":1,"645":1,"646":1,"647":1,"648":1,"649":1,"650":1,"651":1,"652":1}}],["音频数据流畅",{"2":{"581":1}}],["音频在",{"2":{"367":1}}],["音频",{"0":{"365":1},"2":{"712":1,"724":3,"905":1}}],["音频fmod导出适配",{"2":{"95":1}}],["引入wasm水印机制",{"2":{"1128":1}}],["引入unitymarkdownviewer在inspector面板预览changelog",{"2":{"345":1}}],["引发异常的可能是",{"2":{"589":1}}],["引擎和手场景完成",{"2":{"1120":1}}],["引擎和首场景完成",{"2":{"759":1,"1106":1}}],["引擎和首场景",{"2":{"759":1,"1106":1,"1120":1}}],["引擎自身模块与数据初始化",{"2":{"988":1}}],["引擎默认资源",{"2":{"873":1}}],["引擎导出项目将微信runtime包裁剪",{"2":{"841":1}}],["引擎与首场景初始化",{"2":{"822":1}}],["引擎与资源",{"2":{"713":1}}],["引擎初始化和首场景准备",{"2":{"988":1}}],["引擎初始化",{"2":{"826":2}}],["引擎初始化完成前",{"2":{"996":1}}],["引擎初始化完成后",{"2":{"996":1}}],["引擎初始化完成后修改",{"0":{"995":1}}],["引擎初始化完成后多长时间开始加载子包",{"2":{"795":1}}],["引擎初始化完成时",{"2":{"793":2}}],["引擎初始化与开发者首帧逻辑",{"0":{"875":1},"2":{"790":1,"871":1}}],["引擎初始化耗时",{"2":{"789":1}}],["引擎可监控内存",{"2":{"731":1}}],["引擎",{"2":{"725":1,"905":1}}],["引擎内部对象",{"2":{"717":1}}],["引擎基于底层实现对游戏资源的异步加载能力",{"2":{"557":1}}],["引擎代码裁剪级别",{"0":{"480":1}}],["引擎+业务首场景",{"2":{"461":1}}],["引擎或业务代码导致的异常都会抛出到",{"2":{"451":1}}],["引擎捕捉哪种级别的异常",{"2":{"451":1}}],["引擎启动",{"2":{"378":1}}],["引擎版本",{"0":{"497":1},"2":{"367":1,"829":1,"905":1}}],["引用查找",{"2":{"362":1}}],["资源在预下载完成后",{"2":{"988":1}}],["资源系统迁移可参考unity官方文档upgrading",{"2":{"933":1}}],["资源拆分",{"2":{"928":1}}],["资源按需延迟加载",{"2":{"917":1}}],["资源按需加载概述",{"0":{"828":1},"1":{"829":1,"830":1,"831":1,"832":1,"833":1},"2":{"538":2}}],["资源按需加载",{"0":{"538":1,"779":1,"832":1,"833":1,"925":1},"1":{"926":1},"2":{"386":1}}],["资源更新",{"0":{"915":1}}],["资源更新说明",{"0":{"441":1},"2":{"915":1}}],["资源清理插件",{"2":{"882":1}}],["资源分包",{"2":{"865":1}}],["资源",{"2":{"864":1,"865":1}}],["资源与代码分包处理",{"2":{"864":1}}],["资源包不可再使用小游戏分包加载",{"2":{"960":1}}],["资源包括",{"2":{"864":1}}],["资源包方式安装",{"0":{"837":1},"1":{"838":1}}],["资源包使用cdn远程加载",{"2":{"831":1}}],["资源包请使用cdn",{"2":{"460":1}}],["资源管理",{"2":{"829":1}}],["资源量",{"2":{"797":1}}],["资源处理建议",{"0":{"780":1}}],["资源请求并发数不超过20个",{"2":{"779":1}}],["资源放到",{"2":{"576":1}}],["资源目录",{"2":{"575":1}}],["资源预下载",{"0":{"547":1,"938":1}}],["资源服务器部署配置",{"0":{"540":1}}],["资源服务器注意事项",{"0":{"440":1}}],["资源实际部署的cdn前缀必须与转换面板填写的cdn地址一致",{"2":{"513":1}}],["资源版本=8d265a9dfd6cb7669cdb8b726f0afb1e",{"2":{"513":1}}],["资源唯一标识=streamingassets",{"2":{"513":1}}],["资源下载提示istrusted",{"0":{"1096":1}}],["资源下载提示",{"2":{"1082":1}}],["资源下载通常是贡献最大的部分",{"2":{"917":1}}],["资源下载",{"0":{"954":1},"1":{"955":1,"956":1},"2":{"528":1}}],["资源下载url中不包含data",{"2":{"527":1}}],["资源下载url",{"2":{"523":1}}],["资源下载url=https",{"2":{"513":1}}],["资源下载失败",{"0":{"462":1,"463":1}}],["资源淘汰规则",{"0":{"509":1},"1":{"510":1,"511":1},"2":{"500":1}}],["资源加载与编译",{"2":{"951":1}}],["资源加载与缓存",{"2":{"900":1}}],["资源加载",{"2":{"498":1}}],["资源缓存与淘汰策略",{"0":{"964":1}}],["资源缓存与更新的不同",{"2":{"944":1}}],["资源缓存规则",{"0":{"443":1}}],["资源缓存",{"0":{"442":1,"500":1},"1":{"443":1},"2":{"500":1,"540":1}}],["资源部署",{"0":{"436":1,"895":1},"1":{"437":1,"438":1,"439":1,"440":1}}],["资源部署与缓存",{"0":{"435":1},"1":{"436":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1},"2":{"540":1}}],["资源上传至cdn的注意事项",{"0":{"404":1}}],["资源将保持对应的",{"2":{"393":1}}],["资源占位符专用",{"2":{"392":1}}],["资源列表",{"2":{"362":1}}],["资源优化",{"0":{"359":1},"1":{"360":1,"361":1,"362":1,"363":1}}],["资源优化工具与建议",{"2":{"780":1}}],["资源优化工具",{"2":{"360":1}}],["资源优化工具代码添加namespace",{"2":{"347":1}}],["资源优化工具支持astc6",{"2":{"68":1}}],["筛选列表展示结果",{"2":{"362":1}}],["勾选转换面板",{"2":{"717":1}}],["勾选的导出场景",{"2":{"437":1}}],["勾选项选中后保存即可",{"2":{"398":1}}],["勾选后可修改纹理压缩格式",{"2":{"362":1}}],["勾选后",{"2":{"362":1}}],["勾选时使用optimizesize",{"2":{"355":1}}],["禁用了部分不常用的后处理",{"2":{"431":1}}],["禁用mipmap",{"2":{"362":1}}],["禁用readable",{"2":{"362":1}}],["从小游戏的运行周期来看",{"2":{"1118":1}}],["从本地加载中文",{"2":{"1000":1}}],["从而降低命中预下载列表时的文件读取耗时",{"2":{"988":1}}],["从而再次降低首资源包体积",{"2":{"399":1}}],["从服务器下载bundle的方式主要以下两种",{"2":{"943":1}}],["从首包开始",{"0":{"924":1}}],["从启动时序可以知道loader启动阶段分为以下五个阶段",{"2":{"826":1}}],["从缓存日志中搜索不带hash的资源名",{"2":{"526":1}}],["从自动缓存目录中删除指定文件",{"2":{"522":1}}],["从自动缓存目录中释放指定大小的文件缓存",{"2":{"521":1}}],["从下图看到程序在第",{"2":{"451":1}}],["从",{"2":{"398":1,"1073":1}}],["从library",{"2":{"362":1}}],["从unity",{"2":{"346":1}}],["搜素maxsize大于512纹理",{"2":{"362":1}}],["搜索关键字",{"2":{"1046":1}}],["搜索wasm",{"2":{"1043":1}}],["搜索已开启readable纹理",{"2":{"362":1}}],["搜索已开启了mipmap的纹理",{"2":{"362":1}}],["搜索非pot图片",{"2":{"362":1}}],["搜索规则",{"2":{"362":1}}],["已完成",{"2":{"1131":1}}],["已完成请求数",{"2":{"798":1}}],["已添加水印的wasm游戏",{"2":{"1128":1}}],["已知iphone7p及以下机型需要进一步限制instance",{"2":{"1079":1}}],["已知兼容问题",{"0":{"1078":1},"1":{"1079":1,"1080":1}}],["已知问题",{"2":{"367":2}}],["已支持webgl2",{"2":{"1077":1}}],["已支持",{"2":{"1016":1}}],["已验证小版本",{"2":{"905":1}}],["已下载完成请求详细信息",{"2":{"798":1}}],["已发起但未完成的下载任务",{"2":{"996":1}}],["已发起请求数",{"2":{"798":1}}],["已发起预下载",{"2":{"793":1}}],["已预下载完成大小",{"2":{"792":1}}],["已预下载完成大小字符串表示",{"2":{"792":1}}],["已预下载完成数量",{"2":{"792":1}}],["已被业务使用",{"2":{"717":1}}],["已经有",{"2":{"811":1}}],["已经有无缓存",{"0":{"527":1},"2":{"500":1}}],["已经是一个比较功能完备的工程",{"2":{"706":1}}],["已为您跳过剧情",{"2":{"591":1}}],["已测试easytouch",{"2":{"476":1}}],["已生成资源仍然生成并覆盖",{"2":{"414":1}}],["已有脚本中局部代码的文本替换",{"2":{"384":1}}],["已自动适配微信小游戏",{"2":{"365":1}}],["已开启mipmap",{"2":{"362":1}}],["已废弃",{"2":{"353":2,"354":1,"355":1,"356":3}}],["选择增量更新时可查看首包个数",{"2":{"1057":1}}],["选择生成profile或者release包",{"2":{"1019":1}}],["选择是否增量分包",{"0":{"1024":1},"2":{"1012":1,"1019":1}}],["选择分组",{"2":{"926":1}}],["选择建议",{"2":{"829":1}}],["选择哪种渲染管线",{"0":{"808":1}}],["选择对应的设备",{"2":{"715":1}}],["选择符合当前游戏的方案",{"2":{"538":1}}],["选择",{"2":{"428":5}}],["选云端安装依赖即可",{"2":{"374":1}}],["选中javascript",{"2":{"531":1}}],["选中",{"2":{"428":2,"926":1}}],["选中需要部署的云函数",{"2":{"374":1}}],["选中需要部署的云函数环境",{"2":{"374":1}}],["选中一个资源",{"2":{"362":1}}],["选中目录",{"2":{"362":1}}],["选项表示",{"2":{"451":1}}],["选项",{"2":{"31":1,"968":1}}],["字母式符号",{"2":{"1004":1}}],["字样日志",{"2":{"998":1}}],["字体大小=xxmb",{"2":{"1003":1}}],["字体文件",{"2":{"1002":1,"1003":2}}],["字体文件压缩前最大不超过4mb",{"2":{"780":1}}],["字体往往压缩率很低",{"2":{"924":1}}],["字体相关配置",{"2":{"358":1}}],["字符串类型解析器将耗费大量cpu算力与产生gc",{"2":{"743":1}}],["字符串",{"2":{"628":1}}],["字段为",{"2":{"1093":1}}],["字段告诉剧情引擎该事件是反复有效",{"2":{"622":1}}],["字段将在末位节点新增或覆盖",{"2":{"380":1}}],["字段",{"2":{"353":1,"354":1,"355":1,"356":1,"358":1}}],["此为",{"2":{"1097":1}}],["此套接口只可在微信小游戏环境下使用",{"2":{"945":1}}],["此地址默认为编译机器的",{"2":{"902":1}}],["此部分始终占用内存无法释放",{"2":{"728":1}}],["此处给出",{"2":{"635":1}}],["此处将产生异常",{"2":{"567":1}}],["此处设置将预先加载",{"2":{"357":1}}],["此最大值通过maxstorage修改",{"2":{"512":1}}],["此路径下的下载",{"2":{"507":1}}],["此方法需要确保项目中只使用第一个",{"2":{"493":1}}],["此外",{"2":{"472":1}}],["此时ios",{"2":{"967":1}}],["此时我们可以将每个场景单独作为addressable分组",{"2":{"926":1}}],["此时打开的可能还是旧版本",{"2":{"911":1}}],["此时根据monitorduration的值截止检测",{"2":{"785":1}}],["此时应使用其他资源管理比如assetbundle来减少资源索引文件大小",{"2":{"743":1}}],["此时用到",{"2":{"629":1}}],["此时你可以将",{"2":{"615":1}}],["此时保存这个文件",{"2":{"614":1}}],["此时将自动生成",{"2":{"612":1}}],["此时本地有版本b",{"2":{"526":1}}],["此时本地化",{"2":{"428":1}}],["此时版本a缓存被清理",{"2":{"526":1}}],["此时loader会按照lru规则",{"2":{"512":1}}],["此时可能需要升级",{"2":{"493":1}}],["此时可通过该文件找到c",{"2":{"452":1}}],["此时不需要将首包资源部署到服务器",{"2":{"437":1}}],["此时在",{"2":{"428":1}}],["此时",{"2":{"428":1,"614":1,"805":1,"902":1,"926":1}}],["此时若已经执行过微信压缩纹理能力时",{"2":{"398":1}}],["此时得到的profile中函数为数字id",{"2":{"351":1}}],["此示例仅供参考云函数使用流程",{"2":{"374":1}}],["包体积有更苛刻的要求",{"2":{"1100":1}}],["包体优化",{"2":{"1071":1}}],["包体更小",{"2":{"905":1,"907":1}}],["包体瘦身",{"2":{"395":1,"413":1}}],["包方式进行分包管理",{"2":{"833":1}}],["包方式存放于磁盘本地",{"2":{"831":1}}],["包等资源按需加载的游戏",{"0":{"831":1}}],["包的异步资源管理",{"2":{"829":1}}],["包的按需加载",{"2":{"828":1}}],["包是常规的分包解决方案",{"2":{"829":1}}],["包拷贝到本地路径",{"2":{"493":1}}],["包吗",{"2":{"433":1}}],["包括逻辑异常",{"2":{"1118":1}}],["包括开发版",{"2":{"1093":1}}],["包括上线后",{"2":{"1029":1}}],["包括环境光",{"2":{"811":1}}],["包括以下内容",{"2":{"562":1}}],["包括第三方插件",{"2":{"451":1}}],["包括",{"2":{"431":1,"705":1}}],["包有关系",{"2":{"428":1}}],["包已经完成了",{"2":{"428":1}}],["包就会被移除",{"2":{"428":1}}],["包本地化",{"2":{"428":1}}],["包",{"0":{"428":1},"2":{"427":1,"428":1,"429":1,"493":1}}],["包目录路径",{"2":{"356":1}}],["包含一定养成玩法",{"2":{"758":1,"1113":1}}],["包含",{"2":{"632":1}}],["包含unity",{"2":{"437":1}}],["包含以下修改",{"2":{"259":1}}],["包含重要bugfix",{"2":{"22":1,"33":1,"36":1,"39":1,"41":1,"46":1,"58":1}}],["毫秒",{"2":{"355":1}}],["瘦身首包资源体积",{"2":{"355":1}}],["对的",{"2":{"1035":1}}],["对表格执行格式化换行",{"2":{"968":1}}],["对多",{"2":{"833":1}}],["对下载和解析造成较大压力",{"2":{"831":1}}],["对比帧率",{"2":{"815":1}}],["对比一下性能",{"2":{"807":1}}],["对性能会有比较明显的影响",{"2":{"809":1}}],["对性能有较大影响",{"2":{"740":1}}],["对开发者要求高",{"2":{"808":1}}],["对系统有要求",{"2":{"807":1}}],["对帧率不敏感游戏建议使用",{"2":{"747":1}}],["对象托管对象",{"2":{"717":1}}],["对象等托管内存",{"2":{"712":1}}],["对技术选型并无要求",{"2":{"705":1}}],["对照①",{"2":{"622":1}}],["对剧本修改",{"0":{"614":1}}],["对设备性能如计算",{"2":{"557":1}}],["对外接口",{"0":{"517":1},"1":{"518":1,"519":1,"520":1,"521":1,"522":1},"2":{"500":1}}],["对重度游戏如mmo",{"2":{"496":1}}],["对应unity",{"2":{"827":1}}],["对应外显进度条的",{"2":{"599":1}}],["对应控制剩余",{"2":{"580":1}}],["对应",{"2":{"505":2,"507":1}}],["对应的prefab在editor中需设置为addressable",{"2":{"927":1}}],["对应的",{"2":{"431":1}}],["对应于il2cppcodegeneration选项",{"2":{"355":1}}],["对移动平台的一个优化项",{"2":{"429":1}}],["对运行时性能会有提升",{"2":{"427":1}}],["对",{"2":{"391":1,"635":1,"807":1,"1083":1}}],["对于未更新系统的玩家",{"2":{"1097":1}}],["对于不满足此要求时回退为普通执行方式",{"2":{"1093":1}}],["对于计算性能要求较高的游戏会受到比较大的限制",{"2":{"1083":1}}],["对于计算耗时",{"2":{"875":1}}],["对于webgl2",{"2":{"1078":1}}],["对于webgl版本会启动websockify",{"2":{"805":1,"902":1}}],["对于新构建的小游戏包",{"2":{"1019":1}}],["对于小游戏来说是不推荐使用的方式",{"2":{"934":1}}],["对于使用addressable的项目",{"2":{"922":1}}],["对于已有的游戏资源",{"2":{"921":1}}],["对于unity",{"2":{"917":1}}],["对于分析打包的资源正确性和冗余具有很好的帮助",{"2":{"880":1}}],["对于分析cpu",{"2":{"731":1}}],["对于低端机来说时间依然可观",{"2":{"874":1}}],["对于大型游戏可以适当放宽一点",{"2":{"815":1}}],["对于大多数开发者",{"2":{"808":1}}],["对于相同尺寸的纹理",{"2":{"813":1}}],["对于图标等小图片",{"2":{"813":1}}],["对于图集来说尽量不要超过1024",{"2":{"813":1}}],["对于单图",{"2":{"813":1}}],["对于对性能要求高且熟悉渲染的开发者",{"2":{"808":1}}],["对于用不到的特性",{"2":{"808":1}}],["对于gpu显存压力大的游戏",{"2":{"731":1}}],["对于",{"2":{"701":1,"837":1,"1031":2}}],["对于常见的位置属性可以使用",{"2":{"666":1}}],["对于全局变量的详细介绍请阅读",{"2":{"625":1}}],["对于希望进一步提升游戏启动留存的开发者可以基于该能力精心设计用于",{"2":{"568":1}}],["对于极小的休闲类游戏将具备更快更小修改代价将游戏迁移至微信小游戏环境内运行",{"2":{"557":1}}],["对于开发者而言",{"2":{"557":1}}],["对于进一步提升",{"2":{"540":1}}],["对于游戏中使用到网络请求的操作",{"2":{"539":1}}],["对于少量数据可以采用后两种方式",{"2":{"490":1}}],["对于微信平台的小游戏",{"2":{"430":1}}],["对于ab包的忽略直接在右侧",{"2":{"398":1}}],["对于重度游戏而言",{"2":{"549":1}}],["对于重度游戏",{"2":{"387":1}}],["对于资源体积而言将更小",{"2":{"386":1}}],["对于被分离的纹理资源将在游戏实际的使用过程中按渲染需要动态加载",{"2":{"386":1}}],["对齐最新小游戏基础库2",{"2":{"109":1}}],["单帧耗时",{"2":{"801":1}}],["单帧内瞬间的内存使用非常容易造成crash",{"2":{"727":1}}],["单个包体最好不超过2mb",{"2":{"779":1}}],["单个请求文件最大不超过100mb",{"2":{"440":1}}],["单位ms",{"2":{"789":1}}],["单位mb",{"2":{"353":1,"505":1}}],["单位",{"2":{"516":1,"671":1}}],["单位px",{"2":{"421":2}}],["单位bytes",{"2":{"353":1,"505":1,"513":1,"789":2}}],["单独提供wx",{"2":{"270":1}}],["拼接在data",{"2":{"353":1}}],["h",{"2":{"1126":1}}],["h5",{"2":{"1093":1}}],["host",{"2":{"1046":1}}],["hook",{"2":{"697":2,"701":1,"709":1}}],["hunter",{"0":{"882":1},"2":{"882":1}}],["hub",{"2":{"410":2,"805":2,"902":2}}],["h2或http1",{"2":{"798":1}}],["hitcache",{"2":{"798":1}}],["hitcachecount=0",{"2":{"799":1}}],["hitcachecount",{"2":{"792":1,"798":1}}],["hideopendata",{"0":{"702":1},"2":{"702":1,"709":2}}],["hidekeyboardoption",{"2":{"555":1}}],["hidekeyboard",{"2":{"555":5}}],["hideaftercallmain",{"2":{"353":1,"420":1,"422":1,"900":1,"958":1,"959":2}}],["hidden",{"0":{"493":1},"2":{"580":1,"585":1}}],["hlsl部分",{"2":{"433":1}}],["hlsl",{"2":{"429":8,"431":4}}],["header",{"2":{"1096":1}}],["headers",{"2":{"1095":1}}],["heapu8",{"2":{"981":1}}],["heap是只增不减且存在内存碎片的",{"2":{"727":1}}],["heap通常无法看出具体内存使用",{"2":{"720":1}}],["heap包含了大部分",{"2":{"720":1}}],["heap",{"0":{"720":1},"1":{"721":1,"722":1,"723":1},"2":{"712":2,"713":1}}],["height应当是",{"2":{"707":1}}],["height是为了点击区域能正确点击",{"2":{"707":2}}],["height",{"2":{"421":3,"423":3,"426":1,"580":1,"585":1,"614":1,"621":6,"629":1,"632":1,"655":1,"657":1,"659":1,"667":1,"676":1,"678":1,"701":4,"707":2,"709":1,"1005":2}}],["hello",{"2":{"374":1}}],["hdrp",{"2":{"808":2}}],["hdr",{"2":{"393":1,"431":3,"726":1}}],["hy=sh",{"2":{"370":1}}],["hanle",{"2":{"927":2,"934":1}}],["handler",{"2":{"943":3}}],["handle",{"2":{"926":3,"927":1,"930":3,"931":7,"932":2,"934":4}}],["hash是重要依据",{"2":{"942":1}}],["hash记录了catalog",{"2":{"799":1}}],["hash来做资源热更新",{"2":{"799":1}}],["hash文件用于资源热更新",{"2":{"798":1}}],["hash长度也不一样",{"2":{"511":1}}],["hash",{"2":{"505":1}}],["has",{"2":{"367":1,"512":1}}],["half",{"2":{"812":1}}],["half3",{"2":{"431":1}}],["halfwidth",{"2":{"358":1}}],["halfsize",{"2":{"356":1}}],["http使用unitywebrequest",{"2":{"498":1}}],["http",{"0":{"976":1},"1":{"977":1},"2":{"372":1,"373":1,"539":1,"634":1,"646":1,"887":1,"985":1,"1004":7}}],["http下载时",{"2":{"173":1}}],["https证书",{"2":{"984":1,"985":1}}],["https",{"2":{"0":1,"1":1,"127":2,"353":1,"370":1,"374":1,"421":1,"423":1,"494":1,"499":17,"513":1,"531":1,"532":1,"558":1,"708":2,"805":1,"836":2,"843":1,"880":1,"881":1,"882":1,"883":1,"887":4,"889":2,"902":1,"917":1,"920":1,"939":5,"949":4,"977":2,"979":1,"983":1,"993":4,"994":2,"995":1,"1002":1,"1004":12,"1133":1,"1136":1}}],["html",{"2":{"127":1,"374":1,"435":1,"490":2,"494":1,"708":1,"805":1,"883":1,"887":1,"902":1,"939":1,"949":1,"979":1,"983":1}}],["排行榜所在的纹理绘制在屏幕中的物理坐标系",{"2":{"707":1}}],["排行榜与微信关系数据",{"2":{"543":1}}],["排行榜能力优化",{"2":{"135":1}}],["排除路径下指定类型文件不缓存",{"2":{"353":1}}],["将收集到的函数加入首包",{"2":{"1016":1}}],["将原来的",{"2":{"1014":1}}],["将原本要绘制的",{"2":{"697":1}}],["将原本的",{"2":{"550":1}}],["将simpledlmalloc",{"2":{"973":1}}],["将直接使用本地缓存",{"2":{"865":1}}],["将优先需要使用的资源放到列表头部",{"2":{"793":1}}],["将游戏资源以",{"2":{"831":1}}],["将游戏运行一段时间",{"2":{"727":1}}],["将游戏内纹理资源针对webgl导出做优化",{"2":{"359":1}}],["将内存控制到1g以内",{"2":{"724":1}}],["将插件内置的",{"2":{"704":1}}],["将某个音频组件进行继续播放",{"2":{"627":1}}],["将某个音频组件进行暂停",{"2":{"627":1}}],["将某个视频组件进行继续播放",{"2":{"627":1}}],["将某个视频组件进行暂停",{"2":{"627":1}}],["将得到一些信息反馈",{"2":{"582":1}}],["将方便开发者进行数据分析",{"2":{"578":1}}],["将使用微信开发者工具打开",{"2":{"540":1}}],["将这部分函数放在首包",{"2":{"1038":1}}],["将这段内容保存到文件",{"2":{"889":1}}],["将这些文件添加到inerasableidentifier中",{"2":{"529":1}}],["将这两个子文件夹拷贝到工程目录外的一个本地文件夹",{"2":{"428":1}}],["将其设置为il2cpp后重试",{"2":{"492":1}}],["将其放在",{"2":{"410":1}}],["将此目录部署到服务器即可",{"2":{"438":1}}],["将相关的",{"2":{"433":1}}],["将那些游戏用不到的功能在编译期就去掉",{"2":{"427":1}}],["将资源指针替换至原bundle内",{"2":{"401":1}}],["将",{"2":{"396":1,"410":1,"539":1,"576":1,"831":1,"1005":1}}],["将只生成",{"2":{"395":1}}],["将整节点替换",{"2":{"380":1}}],["将整节点新增或覆盖",{"2":{"380":1}}],["将maxsize设置为纹理宽高最大值的一半",{"2":{"362":1}}],["将被自动缓存",{"2":{"353":1}}],["将首包资源brotli压缩",{"2":{"353":1}}],["路径规范",{"0":{"997":1}}],["路径请自行检查",{"2":{"479":1}}],["路径随意",{"2":{"428":1}}],["路径内容均变更为下载文件的存放完整路径",{"2":{"410":1}}],["路径下",{"2":{"410":1}}],["路径",{"2":{"406":1}}],["路径中包含特定标识符开始下载bundle",{"2":{"353":1}}],["路径命中标识符时",{"2":{"290":1}}],["加上",{"2":{"818":1}}],["加快二次启动速度",{"2":{"964":1}}],["加快游戏启动速度",{"0":{"778":1}}],["加快游戏运行进度",{"2":{"386":1}}],["加快转换速度",{"2":{"175":1}}],["加载方式在转换工具导出时就确定好了",{"2":{"960":1}}],["加载方式取决于导出选项中的首包资源加载方式",{"2":{"437":1}}],["加载文案过长时可设置",{"2":{"959":1}}],["加载文案及样式",{"2":{"418":1,"551":1}}],["加载bundle后内存增加了5403162字节",{"2":{"947":1}}],["加载的bundle文件大小为5403162字节",{"2":{"947":1}}],["加载速度和包体大小更均衡",{"2":{"942":1}}],["加载和内存优化",{"2":{"940":1}}],["加载代码改写成",{"2":{"934":1}}],["加载完成回调",{"2":{"927":2,"934":1}}],["加载你指定的内容",{"2":{"919":1}}],["加载效率低",{"2":{"829":1}}],["加载子包耗时",{"2":{"795":1}}],["加载分包造成的卡顿时长",{"2":{"794":1}}],["加载时间",{"2":{"568":1}}],["加载过程中是存在cpu处理密集而",{"2":{"547":1}}],["加载",{"2":{"437":1}}],["加载进度条宽度",{"2":{"422":1,"900":1,"958":1,"959":1}}],["加载进度条的宽度",{"2":{"353":1}}],["加载视频",{"2":{"421":1}}],["加载页的素材配置",{"2":{"421":1}}],["加载页配置项",{"2":{"421":1}}],["加载阶段循环展示的文案",{"2":{"421":1,"423":1,"959":1}}],["加载阶段视频url",{"2":{"353":1,"893":1,"899":1}}],["首包函数个数至少要有原始包函数总数的30",{"2":{"1029":1}}],["首包资源相对cdn地址的存放目录",{"2":{"955":1}}],["首包资源中确保只包含轻量的首屏以及依赖资源",{"2":{"928":1}}],["首包资源应该只包含首屏所需资源",{"2":{"924":1}}],["首包资源量不超过5m",{"2":{"917":1}}],["首包资源或资源分包",{"2":{"865":1}}],["首包资源是否通过小游戏分包加载",{"2":{"826":1}}],["首包资源读取",{"2":{"826":1}}],["首包资源下载",{"2":{"826":1,"871":1}}],["首包资源",{"2":{"822":1,"873":1,"1122":1}}],["首包资源加载方式",{"0":{"960":1},"1":{"961":1,"962":1},"2":{"437":1,"893":1,"899":1}}],["首屏资源需要注意",{"2":{"924":1}}],["首资源放在小游戏代码包内",{"2":{"893":1}}],["首资源所在http或cdn地址",{"2":{"893":1}}],["首资源包处理",{"2":{"829":1}}],["首资源包未开启服务器压缩",{"2":{"790":1}}],["首资源包下载",{"2":{"1123":1,"1124":1}}],["首资源包下载与体积",{"0":{"873":1},"2":{"790":2}}],["首资源包下载耗时",{"2":{"789":1}}],["首资源包较大",{"2":{"790":1}}],["首资源包是否开启服务器压缩",{"2":{"789":1}}],["首资源包大小",{"2":{"789":1}}],["首资源包和assetbundle都不应使用文件cache",{"2":{"728":1}}],["首资源包和assetbundle自带的cache机制都会使用emscripten使用文件系统",{"2":{"728":1}}],["首资源包永远占用内存且无法释放",{"2":{"728":1}}],["首资源包与assetbundle内存",{"0":{"728":1}}],["首资源包有非常高的压缩率",{"2":{"440":1}}],["首资源包即01367b188873c923",{"2":{"437":1}}],["首资源包",{"0":{"437":1},"2":{"501":1,"759":1,"761":1,"865":1,"1106":1,"1107":1,"1120":1}}],["首资源包优化",{"2":{"399":1}}],["首资源包优化说明",{"0":{"399":1}}],["首资源包加载方式",{"2":{"353":1}}],["首资源包校验兼容微信纹理压缩工具",{"2":{"82":1}}],["首资源包压缩后在pc上运行的基础库版本限制调整",{"2":{"75":1}}],["首个请求开始时间",{"2":{"798":1}}],["首帧逻辑优化",{"0":{"546":1}}],["首场景awake",{"2":{"778":1}}],["首场景加载完成",{"2":{"582":1}}],["首场景初始化",{"2":{"532":1}}],["首场景启动优化的并不是一个简单的步骤就可以完全优化",{"2":{"546":1}}],["首场景启动优化",{"0":{"530":1,"546":1},"1":{"531":1,"532":1,"533":1},"2":{"546":1,"778":1,"878":1}}],["首先排查项目是否已经是内存优化版本的分包",{"2":{"1045":1}}],["首先排查传进来的参数是否符合预期",{"2":{"709":1}}],["首先确认是否为stable版本开发者工具",{"2":{"1043":1}}],["首先",{"2":{"973":1}}],["首先是不同于",{"2":{"622":1}}],["首先打开",{"2":{"429":1}}],["首先将官方的",{"2":{"428":1}}],["首先需要",{"2":{"427":1}}],["首次从网络下载",{"2":{"1001":1}}],["首次下载或更新首资源包时",{"2":{"873":1}}],["首次update不要包含过重逻辑",{"2":{"778":1}}],["首次访问将直接进入剧情模式",{"2":{"571":1}}],["首次拉取代码分包",{"0":{"461":1}}],["首次启动时提示文案",{"2":{"421":1,"423":1,"959":1}}],["首次启动耗时可能会增加200ms",{"2":{"353":1}}],["首次加载请耐心等待",{"2":{"421":1,"959":1}}],["说明这里的状态更新已经中断",{"2":{"1023":1}}],["说明",{"0":{"413":1,"416":1,"1128":1},"2":{"353":1,"354":1,"355":1,"356":1,"358":1,"414":1,"417":1,"628":1}}],["其次阐述在微信小游戏环境下最佳的性能优化工具与常见优化手段",{"2":{"733":1}}],["其实就是开放数据域文件夹外的业务代码",{"2":{"697":1}}],["其实不用宏也可以定制本地化的",{"2":{"429":1}}],["其他兼容性问题",{"2":{"1118":1}}],["其他的像颜色",{"2":{"812":1}}],["其他的一些修改",{"2":{"431":1}}],["其他常见优化手段",{"0":{"730":1}}],["其他颜色",{"2":{"717":1}}],["其他js层未捕获异常",{"2":{"567":1}}],["其他缓存日志",{"0":{"516":1},"2":{"500":1}}],["其他",{"2":{"428":1,"433":2,"712":1,"905":1}}],["其他版本",{"2":{"348":1}}],["其格式优先级为",{"2":{"405":1}}],["其余删除",{"2":{"1010":1}}],["其余部分都必须放cdn进行延迟加载",{"2":{"828":1}}],["其余的都建议选择",{"2":{"809":1}}],["其余值使用timer控制",{"2":{"747":1}}],["其余年限跟随微信纹理压缩支持版本进行选择",{"2":{"397":1}}],["其余格式请勿设置",{"2":{"393":1}}],["其中静态摆放的物件不单独设置为addressable也会一并打包到场景所在bundle",{"2":{"926":1}}],["其中$unity",{"2":{"902":1}}],["其中自动上报为unity",{"2":{"825":1}}],["其中xxx为js对象",{"2":{"791":1}}],["其中webgl1",{"2":{"734":1}}],["其中webgl目录结构如下",{"2":{"435":1}}],["其中部分配置可通过转换插件面板快速修改",{"2":{"505":1}}],["其中部分配置可在微信小游戏导出面板中可视化配置",{"2":{"352":1}}],["其中小游戏工程导出目录路径来自",{"2":{"413":1}}],["其中2019必须使用unity与微信合作的instant",{"2":{"397":1}}],["其中",{"2":{"362":1,"424":1,"479":1,"501":1,"618":1,"622":1,"699":1,"701":1,"893":1,"970":1,"1001":1,"1009":1}}],["位于导出目录",{"2":{"759":2,"1106":2,"1120":2}}],["位于",{"2":{"352":1,"384":1}}],["最新占比请查阅基础库版本分布",{"2":{"1077":1}}],["最新版本chrome",{"2":{"351":1}}],["最近使用时间的目录",{"2":{"968":1}}],["最基本的异步回调",{"0":{"930":1}}],["最差情况下",{"2":{"911":1}}],["最差的情况将使用",{"2":{"405":1}}],["最长帧信息",{"2":{"801":1}}],["最佳实践是业务应该尽可能早地使用ab",{"2":{"948":1}}],["最佳实践检测配置",{"2":{"785":1}}],["最佳实践检测工具",{"0":{"783":1},"1":{"784":1,"785":1,"786":1,"787":1,"788":1,"789":1,"790":1,"791":1,"792":1,"793":1,"794":1,"795":1,"796":1,"797":1,"798":1,"799":1,"800":1,"801":1,"802":1,"803":1,"804":1},"2":{"783":1}}],["最佳实践",{"0":{"777":1},"1":{"778":1,"779":1,"780":1,"781":1,"782":1}}],["最佳实践预下载及网络下载检测项调整",{"2":{"89":1}}],["最小值",{"2":{"717":1}}],["最强战力排行榜",{"2":{"708":1}}],["最后收集时间",{"2":{"1057":1}}],["最后一步这里已经可以随时上传体验版了",{"2":{"1019":1}}],["最后一列dpi",{"2":{"748":1}}],["最后",{"2":{"622":1}}],["最好不要超过1024",{"2":{"811":1}}],["最好能提供非业务相关的可复现代码片段",{"2":{"562":1}}],["最好有截图",{"2":{"562":1}}],["最开始执行的逻辑是callmain主函数",{"2":{"532":1}}],["最高可开通1gb",{"2":{"498":1}}],["最多支持",{"2":{"431":1}}],["最清晰内存占用也会升高",{"2":{"393":1}}],["最终到游戏内有可能会上涨到和原来差不多",{"2":{"1045":1}}],["最终被绘制在了屏幕的位置和尺寸",{"2":{"709":1}}],["最终会调用",{"2":{"701":1}}],["最终会导致",{"2":{"451":1}}],["最终生成的多份格式资源中",{"2":{"393":1}}],["最终模板会因该字段为数组类型",{"2":{"380":1}}],["最终模板仅变更该版本号",{"2":{"380":1}}],["最终模板将新增该字段与值",{"2":{"380":1}}],["最大内存",{"2":{"899":1}}],["最大并发数",{"2":{"798":1}}],["最大阻塞时间",{"2":{"795":1}}],["最大值",{"2":{"717":1,"996":1}}],["最大不要超过1024",{"2":{"363":1}}],["最大缓存容量",{"2":{"353":1,"505":1,"513":1}}],["游戏转换到微信小游戏的开发成本",{"2":{"1133":1}}],["游戏转化至微信小游戏平台的能力",{"2":{"556":1}}],["游戏logo动画",{"0":{"1126":1}}],["游戏端内因为跨域问题会读取不到",{"2":{"1094":1}}],["游戏帧率都会得到明显改善",{"2":{"1087":1}}],["游戏本身是否需要做修改",{"0":{"1094":1},"2":{"1082":1}}],["游戏适配常见手机屏幕没有区别",{"2":{"1073":1}}],["游戏运行会随着收集越来越流畅",{"2":{"1037":1}}],["游戏运行时长",{"2":{"801":1}}],["游戏加载完整",{"2":{"1031":1}}],["游戏加载速度都会有提升",{"2":{"813":1}}],["游戏最初的关卡内容",{"2":{"1016":1}}],["游戏基本会使用中文",{"2":{"1000":1}}],["游戏首个场景加载以及awake流程",{"2":{"988":1}}],["游戏首个data资源文件",{"2":{"759":1,"1106":1,"1120":1}}],["游戏缓存目录",{"2":{"968":1}}],["游戏业务awake逻辑耗时较高时可能导致出现短暂黑屏",{"2":{"959":1}}],["游戏业务侧无需关心资源是否有缓存",{"2":{"502":1}}],["游戏存在备用cdn地址",{"2":{"956":1}}],["游戏不再直接读写文件系统",{"2":{"944":1}}],["游戏不依赖",{"2":{"807":1}}],["游戏发新版本后",{"2":{"911":1}}],["游戏是横屏还是竖屏",{"2":{"893":1}}],["游戏方向",{"2":{"893":1,"899":1}}],["游戏appid",{"2":{"893":1}}],["游戏内容难以遍历完整怎么办",{"0":{"1033":1},"2":{"1012":1}}],["游戏内资源按需加载",{"0":{"876":1}}],["游戏内存大小",{"2":{"353":1}}],["游戏较大",{"2":{"833":1}}],["游戏总包体积较小",{"2":{"832":1}}],["游戏原本发布原生",{"2":{"831":1}}],["游戏开发者可以根据自己游戏的类型进行不同的优化策略来提升实际的游戏体验",{"2":{"830":1}}],["游戏开发者通常可通过阅读指南与使用本工具自行完成剧本的设计并上线能力",{"2":{"607":1}}],["游戏通常安装与启动时将资源都下载完成",{"2":{"828":1}}],["游戏完成所有加载时上报",{"2":{"825":1}}],["游戏在可用内存和性能对比",{"2":{"818":1}}],["游戏在微信手机平台的渲染性能优化一些建议",{"2":{"806":1}}],["游戏在微信开发者工具中运行缺失资源",{"0":{"560":1}}],["游戏前期不应加载子包",{"2":{"796":1}}],["游戏可交互耗时",{"2":{"760":1,"1112":1}}],["游戏可交互完成",{"2":{"759":1,"1106":1,"1120":1,"1123":1,"1124":1}}],["游戏核心场景完成",{"2":{"759":1,"1106":1,"1120":1}}],["游戏启动初始阶段",{"2":{"1086":1}}],["游戏启动很烫",{"0":{"1099":1},"2":{"1082":1}}],["游戏启动调用wechatwasm",{"2":{"968":1}}],["游戏启动耗时",{"2":{"759":1,"1106":1,"1120":1}}],["游戏启动将会有10s黑屏",{"2":{"351":1}}],["游戏初始化完成耗时",{"2":{"760":1,"1112":1}}],["游戏初始化完成",{"2":{"759":1,"1106":1,"1120":1,"1123":1,"1124":1}}],["游戏代码压缩包",{"2":{"759":1,"1106":1,"1120":1}}],["游戏代码的异常将被捕捉",{"2":{"451":1}}],["游戏类型说明",{"0":{"758":1,"1113":1}}],["游戏类目包括",{"2":{"496":1}}],["游戏类目",{"0":{"496":1}}],["游戏占用内存必须以真机环境为准",{"2":{"731":1}}],["游戏占用更大的内存",{"2":{"711":1}}],["游戏左上角显示performence",{"2":{"717":1}}],["游戏状态",{"2":{"717":1}}],["游戏逻辑依然按未使用预下载的异步加载逻辑",{"2":{"999":1}}],["游戏逻辑还是按照未缓存需要从网络下载去编写",{"2":{"944":1}}],["游戏逻辑分配的c",{"2":{"712":1}}],["游戏逻辑是否能使用lua",{"0":{"475":1}}],["游戏引擎比如",{"2":{"705":1}}],["游戏的启动自然不能始终等待这段空隙",{"2":{"577":1}}],["游戏厂家启动logo",{"2":{"573":1}}],["游戏世界观",{"2":{"573":1}}],["游戏相关运行数据请前往",{"2":{"552":1}}],["游戏将在微信小游戏平台成功启动运行",{"2":{"545":1}}],["游戏接入微信小游戏平台的一个重点优化的工作",{"2":{"546":1}}],["游戏接入微信小游戏平台将获得微信提供的",{"2":{"543":1}}],["游戏接入微信小游戏指南",{"0":{"534":1},"1":{"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1}}],["游戏很少考虑场景内的资源规划问题",{"2":{"538":1}}],["游戏资源cdn下不自动缓存的文件类型",{"2":{"893":1}}],["游戏资源cdn",{"2":{"462":1,"893":1,"899":1}}],["游戏项目工程已经安装好",{"2":{"428":1}}],["游戏所需资源下载的总量没变",{"2":{"407":1}}],["游戏实际运行时将劫持渲染时根据资源指针以及当前设备gpu所支持的纹理格式进行远程加载",{"2":{"401":1}}],["游戏工程可以导出但在微信开发者工具运行提示报错",{"0":{"841":1}}],["游戏工程本身已采用完善的",{"2":{"829":1}}],["游戏工程没有使用",{"2":{"557":1}}],["游戏工程在较少的代码修改的情况下完成微信小游戏平台的运行",{"2":{"557":1}}],["游戏工程中",{"2":{"384":1}}],["游戏工程目录",{"2":{"377":1,"383":1}}],["游戏中大量泛型集合的高频访问建议optimizespeed",{"2":{"355":1}}],["游戏cdn前缀",{"2":{"353":1}}],["游戏异常时增加重启游戏按钮",{"2":{"223":1}}],["$stream",{"2":{"992":1}}],["$symbol",{"2":{"351":1}}],["$preload",{"2":{"991":1,"992":1}}],["$load",{"2":{"961":1,"962":1}}],["$loading",{"2":{"420":1,"421":1,"422":2,"958":2,"959":2}}],["$verson",{"2":{"805":2,"902":2}}],["$",{"2":{"518":1,"523":2,"926":1}}],["$hide",{"2":{"420":1,"421":1,"422":1,"958":1,"959":1}}],["$background",{"2":{"420":1,"421":1,"422":1,"958":1,"959":1}}],["$unity",{"2":{"410":2,"805":2,"902":2}}],["$cpuprofile",{"2":{"351":1}}],["有两个地方可安装插件",{"2":{"1043":1}}],["有两种解决方案选择其一即可",{"2":{"408":1}}],["有两种做法进行解读",{"2":{"351":1}}],["有玩家遇到新增函数个数",{"2":{"1029":1}}],["有条件的话",{"2":{"1027":1}}],["有条件的建议分别打对应的包",{"2":{"807":1}}],["有人力情况下强烈建议升级2022",{"2":{"907":1}}],["有助于更好地分析webgl内存使用",{"2":{"905":1}}],["有助于提升渲染兼容性",{"2":{"31":1}}],["有哪些文件需要放cdn服务器",{"2":{"865":1}}],["有差距",{"2":{"818":1}}],["有优化空间",{"2":{"814":1}}],["有需要投射或接受阴影的物体才去设置",{"2":{"811":1}}],["有需要根据项目实际情况",{"2":{"433":1}}],["有大量可能游戏用不上的冗余属性",{"2":{"807":1}}],["有网络请求的总时长",{"2":{"798":1}}],["有上报游戏可交互wx",{"2":{"785":1}}],["有以下几点原因",{"2":{"775":1}}],["有时可能需要以管理员身份运行该命令",{"2":{"610":1}}],["有时候简单的覆盖可能并不能满足开发者复杂的修改需要",{"2":{"381":1}}],["有关",{"2":{"829":1}}],["有关外界对全局变量的赋值与监听请阅读api使用文档",{"2":{"679":1}}],["有关故事线创建请阅读",{"2":{"622":1}}],["有关关键动作帧的种类",{"2":{"620":1}}],["有关图片资源路径问题请阅读",{"2":{"615":1}}],["有关自定义上报详细内容请参考",{"2":{"578":1}}],["有关分包策略可参阅",{"2":{"538":1}}],["有部分官方",{"2":{"493":1}}],["有200mb存储上限",{"2":{"490":1}}],["有10mb存储上限",{"2":{"490":1}}],["有效减少",{"2":{"549":1}}],["有效",{"2":{"451":1}}],["有效降低内存",{"2":{"386":1}}],["有相关",{"2":{"430":1}}],["有一些共同点是可以参考的",{"2":{"430":1}}],["有了编译宏可以保留",{"2":{"429":1}}],["有些",{"2":{"428":1,"493":1}}],["有些功能可能是用不上",{"2":{"427":1}}],["有声音没画面",{"2":{"370":1}}],["特点",{"2":{"831":1,"832":1,"833":1}}],["特效",{"0":{"819":1}}],["特别建议使用wasm",{"2":{"1091":1,"1100":1}}],["特别地",{"2":{"943":1,"977":1,"982":1,"1084":1}}],["特别地请避免使用fmod播放长音频",{"2":{"712":1}}],["特别注意不要随意放置资源到resources目录",{"2":{"924":1}}],["特别是启动后最先进入的场景和关卡",{"2":{"1016":1}}],["特别是启动发烫与内存方面",{"2":{"736":1}}],["特别是",{"2":{"988":1}}],["特别是system",{"2":{"975":1}}],["特别是在有lua逻辑的情况",{"0":{"973":1}}],["特别是小版本",{"2":{"907":1}}],["特殊情况下",{"2":{"351":1}}],["特性支持",{"2":{"22":1,"33":1,"36":1,"39":1,"41":1,"46":1,"58":1}}],["或通过js接口",{"2":{"994":1}}],["或js接口",{"2":{"956":1}}],["或协程写法",{"2":{"927":1}}],["或在内存中创建资源对象",{"2":{"927":1}}],["或新addressable",{"2":{"880":1}}],["或资源包是否需每次下载",{"2":{"865":1}}],["或国内gitee镜像",{"2":{"836":1}}],["或较少使用",{"2":{"833":1}}],["或停止检测时",{"2":{"793":1}}],["或是否下载过慢",{"2":{"793":1}}],["或是通过以下方式将它在浏览器显示出来",{"2":{"351":1}}],["或日志查看",{"2":{"759":2,"1106":2,"1120":2}}],["或unity",{"2":{"717":1,"727":1}}],["或使用全局变量控制剧情显示退出",{"2":{"581":1}}],["或使用代码分包",{"2":{"448":1}}],["或导入新的wxsdk时",{"2":{"378":1}}],["或",{"0":{"460":1},"2":{"377":1,"380":1,"513":1,"540":1,"666":1,"731":1,"759":1,"762":1,"768":1,"814":2,"834":1,"873":1,"967":1,"981":1,"1095":1,"1097":1}}],["或者是小程序appid",{"2":{"1132":1}}],["或者看framework最后的api",{"2":{"1045":1}}],["或者新增函数较多",{"2":{"1037":1}}],["或者收到小游戏数据助手的相关告警",{"2":{"1029":1}}],["或者减少顶点的受影响的骨骼权重数",{"2":{"814":1}}],["或者对硬件优化不友好",{"2":{"812":1}}],["或者自定义了bundle的生成目录",{"2":{"439":1}}],["或者右键云函数",{"2":{"374":1}}],["或者",{"2":{"367":1,"373":1,"433":1,"446":1,"965":1,"981":1,"984":1}}],["或development时才能在函数堆栈中看到可读函数名",{"2":{"351":1}}],["或mp文档",{"2":{"127":1}}],["推荐版本",{"0":{"905":1}}],["推荐缓存到本地",{"2":{"799":1}}],["推荐由游戏自行控制加载时机",{"2":{"793":1}}],["推荐开发者在",{"2":{"589":1}}],["推荐开发者创建位于",{"2":{"383":1}}],["推荐内容",{"0":{"573":1}}],["推荐引擎版本",{"0":{"903":1},"1":{"904":1,"905":1,"906":1,"907":1},"2":{"535":1,"808":1,"902":1}}],["推荐发布使用",{"2":{"451":1}}],["推荐配置",{"2":{"450":1}}],["推荐使用db",{"2":{"968":1}}],["推荐使用",{"2":{"833":1}}],["推荐使用catalog",{"2":{"799":1}}],["推荐使用unity",{"2":{"719":1}}],["推荐使用小游戏包内图片",{"2":{"421":1}}],["推荐使用已修复的",{"2":{"367":1}}],["推荐使用什么音频格式",{"2":{"367":1}}],["推荐",{"0":{"739":1,"835":1,"880":1,"881":1,"993":1},"1":{"836":1,"994":1,"995":1},"2":{"351":1,"367":1,"490":1,"608":1,"905":2,"945":1,"982":1,"1097":1}}],["注",{"2":{"827":1,"1126":1}}],["注销启动剧情全局变量变化时回调",{"2":{"596":1}}],["注销当发生弱网情况时的回调事件",{"2":{"592":1}}],["注销当发生异常时的回调事件",{"2":{"590":1}}],["注销当剧情结束时配置的回调事件",{"2":{"588":1,"603":1}}],["注册回调",{"2":{"979":1,"981":1,"983":1}}],["注册开通小游戏请查阅快速上手",{"2":{"893":1}}],["注册的回调只会产生1次",{"2":{"602":1}}],["注册当发生异常时的回调事件",{"2":{"589":1}}],["注册当剧情结束时的回调事件",{"2":{"587":1,"602":1}}],["注册一些其他的启动剧情事件回调",{"2":{"576":1}}],["注册一个小游戏帐号",{"2":{"456":1}}],["注册获得",{"2":{"353":1}}],["注册进度事件",{"2":{"205":1}}],["注意是预览",{"2":{"1026":1}}],["注意onmessage参数与文档不同",{"2":{"979":1}}],["注意浮点精度的使用",{"2":{"812":1}}],["注意这里传x",{"2":{"707":2}}],["注意左上角为",{"2":{"701":1}}],["注意设置属性是一个最终态的表现",{"2":{"621":1}}],["注意在调试期间请勿关闭该命令行",{"2":{"612":1}}],["注意项",{"0":{"523":1},"2":{"500":1}}],["注意bundle命名规则和缓存策略即可",{"2":{"472":1}}],["注意正式环境cdn一定要开启brotli或者gzip",{"2":{"403":1}}],["注意事项第五点",{"2":{"793":1}}],["注意事项",{"0":{"433":1,"984":1,"999":1,"1011":1,"1029":1},"1":{"985":1,"986":1},"2":{"383":1,"902":1,"945":1,"1012":1}}],["注意修改纹理尺寸",{"2":{"363":1}}],["注意",{"0":{"1132":1},"2":{"351":1,"353":2,"362":1,"374":1,"421":1,"428":1,"429":3,"437":1,"446":1,"451":1,"493":1,"512":1,"513":1,"529":1,"690":1,"717":2,"762":1,"834":1,"896":1,"941":1,"979":1,"983":1,"1023":1,"1136":1}}],["视图得渲染应该会恢复正常的",{"2":{"428":1}}],["视图可能显示粉红色的渲染异常",{"2":{"428":1}}],["视图有多种方式",{"2":{"351":1}}],["视频编码",{"2":{"1126":1}}],["视频会在",{"2":{"1126":1}}],["视频时长",{"2":{"1126":1}}],["视频尺寸",{"2":{"1126":1}}],["视频分辨率",{"2":{"1126":1}}],["视频规范",{"2":{"1126":1}}],["视频格式参考",{"2":{"1126":1}}],["视频格式请参考视频规范",{"2":{"893":1}}],["视频设计规范",{"0":{"1125":1},"1":{"1126":1}}],["视频url",{"2":{"959":1}}],["视频范例",{"2":{"939":1}}],["视频封面图",{"2":{"893":1}}],["视频cdn",{"2":{"634":1,"646":1}}],["视频完整呈现",{"2":{"634":1}}],["视频开始播放时",{"2":{"633":1}}],["视频播放结束时",{"2":{"633":1}}],["视频播放能力",{"2":{"370":1}}],["视频跳转到特定秒数",{"2":{"632":1,"644":1}}],["视频的缩放模式",{"2":{"632":1}}],["视频资源cdn地址",{"2":{"632":1}}],["视频相关",{"0":{"630":1},"1":{"631":1,"632":1,"633":1,"634":1,"635":1,"636":1,"637":1,"638":1,"639":1,"640":1,"641":1}}],["视频组件存在开始播放",{"2":{"622":1}}],["视频内容",{"2":{"551":1}}],["视频等内容作为加载期间的过渡来留住玩家",{"2":{"551":1}}],["视频可播放后",{"2":{"421":1,"423":1,"959":1}}],["视频链接",{"2":{"370":1}}],["视频在",{"2":{"370":2}}],["视频",{"0":{"368":1},"1":{"369":1,"370":1},"2":{"418":1,"581":1,"618":1,"957":1}}],["视频透明时全局清理标记",{"2":{"135":1}}],["jit",{"2":{"1083":1,"1099":1,"1101":1}}],["jianshu",{"2":{"939":1}}],["j23511",{"2":{"889":1}}],["j88421",{"2":{"889":2}}],["jankrate",{"2":{"801":1,"802":1}}],["javascript内存",{"2":{"724":1}}],["javascriptcore中还需要大量内存进行jit优化",{"2":{"712":1}}],["javascript侧",{"0":{"583":1},"1":{"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1}}],["javascript环境",{"2":{"539":1}}],["javascript接口",{"2":{"518":1,"519":1,"520":1,"521":1,"522":1}}],["javascriptwx",{"2":{"374":1}}],["javascript",{"0":{"720":1},"1":{"721":1,"722":1,"723":1},"2":{"374":1,"376":1,"574":1,"576":1,"577":1,"582":4,"583":1,"608":1,"614":1,"618":1,"670":1,"679":1,"713":1,"724":2,"975":1,"977":1}}],["javascript探测器",{"2":{"351":1}}],["jpg",{"2":{"423":1}}],["js相关的日志",{"2":{"1029":1}}],["jsvar",{"2":{"1005":1}}],["js手动配置",{"2":{"992":1}}],["js临时内存等",{"2":{"967":1}}],["jsdata",{"2":{"962":1}}],["jsd2vshnvkzexjlsc6ba3guqc8d",{"2":{"939":1}}],["jsexport",{"2":{"826":1}}],["jsgamemanager",{"2":{"826":1}}],["jsgameglobal",{"2":{"580":1,"585":1}}],["js修改",{"2":{"785":1}}],["js的运行差异",{"0":{"735":1}}],["js的preload列表",{"2":{"326":1}}],["jswx",{"2":{"703":1,"965":1,"994":2}}],["jsopendatacontext",{"2":{"701":1}}],["jsonmapper",{"2":{"979":2,"983":1}}],["json中声明",{"2":{"952":1}}],["json中plugins",{"2":{"466":1}}],["json的hash",{"2":{"799":1}}],["json缓存到本地若无版本标识",{"2":{"799":1}}],["json被缓存且无hash",{"2":{"799":1}}],["json记录了所有资源文件的描述信息和依赖关系",{"2":{"799":1}}],["json配置为可缓存文件",{"2":{"799":1}}],["json配置合并",{"0":{"380":1}}],["json文件名带hash的方式来管理catalog版本",{"2":{"799":1}}],["json文件用来记录打包配置",{"2":{"799":1}}],["json文件打开",{"2":{"428":2}}],["json是否带上了hash或其他用于区分版本的信息",{"2":{"798":1}}],["json是否自动缓存",{"2":{"798":2}}],["json解析大文件",{"2":{"743":1}}],["jsonutility",{"2":{"703":1,"707":1,"708":1,"995":1}}],["json或读取错误",{"0":{"457":1}}],["json未找到",{"0":{"456":1}}],["json和catalog",{"2":{"441":1}}],["json",{"0":{"492":1},"2":{"374":4,"376":1,"378":1,"380":5,"435":1,"441":1,"505":1,"507":2,"523":1,"703":1,"704":1,"798":2,"799":1,"952":1,"993":1,"995":2,"1088":1}}],["jsskipbutton",{"2":{"614":1}}],["js与npm包管理器时",{"2":{"610":1}}],["jslib做两处修改",{"2":{"981":1}}],["jslet",{"2":{"962":1,"992":1}}],["jslaunchopera",{"2":{"589":1,"591":1}}],["jsloadingpageconfig",{"2":{"423":1,"959":1}}],["jsconsole",{"2":{"584":1}}],["jsconst",{"2":{"351":1,"622":1,"634":1,"635":1,"638":1,"646":1,"657":1,"661":1,"668":1,"673":1,"683":1,"1010":1}}],["js文件",{"2":{"533":1}}],["js中hidetimelogmodal为false",{"2":{"871":1}}],["js中enableprofilestats变量打开性能面板",{"2":{"717":1,"727":1}}],["js中iserasablefilejavascript函数自行控制",{"2":{"512":1}}],["js中releasememorysize修改",{"2":{"259":1}}],["js增加代码",{"2":{"446":1,"459":1,"965":1}}],["js侧的实际调用逻辑为gameglobal",{"2":{"424":1}}],["jsbgimagesrc",{"2":{"422":1}}],["jshideaftercallmain",{"2":{"421":1}}],["js配置",{"0":{"421":1,"959":1,"962":1}}],["js异常处理",{"0":{"406":1}}],["jsapi",{"2":{"367":1}}],["js末尾代码稍作修改",{"2":{"351":1}}],["js依赖",{"2":{"94":1}}],["js部分环境变量丢失问题",{"2":{"23":1}}],["js",{"0":{"390":1,"567":1},"2":{"9":1,"70":1,"124":1,"301":1,"374":1,"378":1,"380":1,"383":1,"390":2,"406":4,"421":1,"423":1,"426":1,"435":2,"507":2,"512":1,"531":1,"533":1,"564":1,"576":3,"582":1,"608":1,"621":1,"624":1,"678":1,"688":1,"692":1,"701":1,"705":2,"711":1,"735":1,"760":1,"785":1,"805":4,"889":3,"902":5,"965":1,"968":1,"982":1,"991":1,"1004":1,"1005":3,"1010":5,"1112":1}}],["以便两种模式对比",{"2":{"1088":1}}],["以便清理掉该文件的旧缓存",{"2":{"523":1}}],["以支持更多",{"2":{"1015":1}}],["以此提高资源加载速度",{"2":{"988":1}}],["以此类推",{"2":{"614":1}}],["以zip压缩后体积为准",{"2":{"924":1}}],["以减少加载的字体文件大小",{"2":{"1004":1}}],["以减少函数量",{"2":{"874":1}}],["以减少内存",{"2":{"353":1}}],["以帮助开发者更高效",{"2":{"770":1}}],["以休闲娱乐为主",{"2":{"758":1,"1113":1}}],["以达到买量用户覆盖度",{"2":{"737":1}}],["以达到和游戏更贴近的体验",{"2":{"423":1}}],["以实际游戏为准",{"2":{"727":1}}],["以实现一个服务端校验内容安全的云函数为例对云开发流程进行简单介绍",{"2":{"374":1}}],["以上内存机型的内存限制为",{"2":{"1090":1}}],["以上的时候就可以接受了",{"2":{"1032":1}}],["以上的版本",{"2":{"367":1}}],["以上就差不多了",{"2":{"1026":1}}],["以上",{"2":{"725":1,"735":1}}],["以ios高性能模式为例",{"2":{"724":1}}],["以真机表现为准",{"2":{"675":1}}],["以视频",{"2":{"572":1}}],["以ugui的input组件为例",{"2":{"555":1}}],["以addressables为例",{"2":{"510":1}}],["以代码为例",{"2":{"451":1}}],["以文本方式打开导出目录",{"2":{"449":1}}],["以及是否有更换引擎或者其他导致代码变动较大的操作",{"2":{"1041":1}}],["以及是否命中缓存",{"2":{"502":1}}],["以及列表中尚未发起的任务",{"2":{"996":1}}],["以及使用带证书的https",{"2":{"984":1}}],["以及其中的资源引用到的其他资源",{"2":{"873":1}}],["以及",{"2":{"828":1}}],["以及不同系统平台",{"2":{"733":1}}],["以及减少脚本编译的时间",{"2":{"550":1}}],["以及开放能力",{"2":{"543":1}}],["以及assetbundles打包生成的配置文件通常没有带上hash",{"2":{"441":1}}],["以及在assets导入资源模式下的目录",{"2":{"377":1}}],["以及js接口gameglobal",{"2":{"167":2}}],["以",{"2":{"374":1,"817":1}}],["以下是默认值",{"2":{"959":1}}],["以下是微信压缩纹理工具涉及配置",{"2":{"356":1}}],["以下简称addressable",{"2":{"919":1}}],["以下为视频建议参数",{"2":{"1126":1}}],["以下为使用协程方式发送",{"2":{"977":1}}],["以下为默认值",{"2":{"580":1,"585":1}}],["以下为最低支持版本",{"2":{"369":1}}],["以下几种命名都能识别到版本号8d265a9dfd6cb7669cdb8b726f0afb1e",{"2":{"510":1}}],["以下配置的样式",{"2":{"421":1}}],["以下示例为独立项目的模式",{"2":{"374":1}}],["以设定规则修复列表中选中的资源",{"2":{"362":1}}],["以设定规则扫描目录下文件",{"2":{"362":1}}],["以edge为例",{"2":{"351":1}}],["的内存",{"2":{"1090":1}}],["的部分案例进行评测",{"2":{"1087":1}}],["的部分版本有支持",{"2":{"388":1}}],["的示例",{"2":{"1073":1}}],["的都很少",{"2":{"1036":1}}],["的大小即可",{"2":{"1034":1}}],["的插件一般是自动更新的",{"2":{"1018":1}}],["的方式",{"2":{"1016":1}}],["的方式引入",{"2":{"493":1}}],["的代理层",{"2":{"982":1}}],["的代码",{"2":{"429":1}}],["的第三方插件比较多",{"2":{"981":1}}],["的详细分配堆栈与统计数值",{"2":{"967":1}}],["的引用",{"2":{"922":1}}],["的引擎暂时还不支持导出",{"2":{"889":1}}],["的预览版本",{"2":{"919":1}}],["的资源内容",{"2":{"880":1}}],["的经典特色",{"2":{"857":1}}],["的中重度游戏",{"0":{"833":1}}],["的轻度游戏",{"0":{"832":1}}],["的性能要比",{"2":{"829":1}}],["的性能就一定比",{"2":{"807":1}}],["的统计里有",{"2":{"815":1}}],["的数量建议控制在",{"2":{"815":1}}],["的开销",{"2":{"814":1}}],["的时间和",{"2":{"814":1}}],["的时候可能会生成环境反射立体贴图",{"2":{"811":1}}],["的时候调用",{"2":{"707":1}}],["的耗时",{"2":{"814":1}}],["的阴影默认使用",{"2":{"811":1}}],["的版本还是存在这个问题",{"2":{"809":1}}],["的通用渲染管线",{"2":{"808":1}}],["的好",{"2":{"807":1}}],["的特性",{"2":{"807":2,"868":1}}],["的游戏",{"2":{"785":1}}],["的后面四个参数",{"2":{"709":1}}],["的后设置的值将覆盖前设置特点",{"2":{"622":1}}],["的物理尺寸是",{"2":{"707":1}}],["的纹理",{"2":{"701":1}}],["的处理没有任何要求",{"2":{"701":1}}],["的渲染",{"2":{"697":1,"701":1,"709":1}}],["的渲染结果是否一致",{"2":{"433":1}}],["的绘制存在倒立的差异",{"2":{"699":1}}],["的绘制",{"2":{"697":1}}],["的桥梁",{"2":{"679":1}}],["的延迟执行",{"2":{"670":1}}],["的使用案例",{"0":{"635":1}}],["的使用说明",{"2":{"626":1}}],["的句柄",{"2":{"628":1}}],["的事件之后立马就会开始",{"2":{"709":1}}],["的事件",{"2":{"622":1}}],["的剧情工程",{"2":{"611":1}}],["的剧情内容",{"2":{"568":1}}],["的基本语法",{"2":{"608":1}}],["的基础上选用我们已经验证可行的",{"2":{"388":1}}],["的模板文件",{"2":{"582":1}}],["的启动加载需要一定的时间",{"2":{"551":1}}],["的优化方面均有不错的表现效果",{"2":{"549":1}}],["的情况",{"2":{"547":1}}],["的文件不会被自动缓存",{"2":{"507":1}}],["的测试场景",{"2":{"432":2}}],["的是生效的",{"2":{"429":1}}],["的宏",{"2":{"429":1}}],["的定义或计算可能需要全精度的",{"2":{"812":1}}],["的定义",{"2":{"429":1}}],["的日志",{"2":{"428":1}}],["的绝对路径填写至",{"2":{"406":1}}],["的表现上",{"2":{"405":1}}],["的倍数",{"2":{"405":1}}],["的",{"2":{"389":1,"392":1,"393":1,"429":2,"431":2,"433":1,"614":1,"621":1,"622":1,"635":1,"678":1,"697":1,"811":2,"897":1,"1005":2,"1010":1,"1088":1,"1097":1}}],["的导出目录中",{"2":{"377":1}}],["的导出配置文件",{"2":{"352":1}}],["的声明",{"2":{"374":1}}],["的播放策略",{"2":{"370":1}}],["的更新",{"2":{"367":1}}],["的edge",{"2":{"351":1}}],["的问题",{"2":{"6":1}}],["录制结束后",{"2":{"351":1}}],["该数据将显著影响用户打开留存率",{"2":{"1118":1}}],["该运行模式下",{"2":{"1083":1}}],["该",{"2":{"975":1}}],["该工具仅分析业务与引擎的cpu内存",{"2":{"967":1}}],["该工具能够降低游戏的运行时内存情况",{"2":{"401":1}}],["该如何加载",{"2":{"926":1}}],["该目录将无条件被打包到首包中",{"2":{"924":1}}],["该目录将被直接打包在首资源包",{"2":{"779":1}}],["该类游戏需要耐心调优",{"2":{"833":1}}],["该接口使用前需自行判断是否满足基础库版本要求",{"2":{"753":1}}],["该值仅表示unityheap的峰值进行预留",{"2":{"727":1}}],["该上报本质使用的是",{"2":{"690":1}}],["该文件是",{"2":{"576":1}}],["该文件格式可以使用chrome进行解析",{"2":{"351":1}}],["该能力可以有效降低内存的使用",{"2":{"550":1}}],["该能力仍在兼容一些特殊的应用场景",{"2":{"397":1}}],["该提示仅在开发版本提示",{"2":{"461":1}}],["该选项产生的代码体积较大",{"2":{"453":1}}],["该选项性能最高",{"2":{"451":1}}],["该异常的",{"2":{"451":1}}],["该方法对应",{"2":{"413":1}}],["该函数为异步函数",{"2":{"413":1}}],["该格式是要求高宽必须为",{"2":{"405":1}}],["该功能可以利用此阶段的网络空闲期进行资源下载",{"2":{"875":1}}],["该功能可以在不开启微信压缩纹理工具的情况下使用",{"2":{"399":1}}],["该功能需要两个必要条件",{"2":{"565":1}}],["该功能能够将首资源包中",{"2":{"399":1}}],["该过程等同执行微信压缩纹理的",{"2":{"398":1}}],["该部分主要由",{"2":{"376":1}}],["该小游戏首次使用云开发需要先开通云开发",{"2":{"374":1}}],["该模式将极大降低性能",{"2":{"351":1}}],["该特性处于测试阶段",{"2":{"280":1}}],["开通成功后",{"2":{"1088":1}}],["开通后",{"2":{"827":1}}],["开通使用",{"2":{"464":1,"834":1,"896":1,"1136":1}}],["开放域js代码可以通过",{"2":{"703":1}}],["开放数据域才能够正确处理事件监听",{"2":{"709":1}}],["开放数据域监听相应事件",{"2":{"707":1,"708":1}}],["开放数据域的开发和普通小游戏并无区别",{"2":{"705":1}}],["开放数据域甚至可以忽略这个事件",{"2":{"701":1}}],["开放数据域接触到的",{"2":{"697":1}}],["开放数据域所有逻辑都在一个独立的文件夹内完成",{"2":{"697":1}}],["开放数据域虽然乍一看有点复杂",{"2":{"697":1}}],["开放数据",{"2":{"543":1}}],["开始下载wasm子包的时间",{"2":{"795":1}}],["开始",{"2":{"701":1}}],["开始配置启动剧情",{"2":{"576":1}}],["开始游戏",{"2":{"421":1,"959":1}}],["开始处理",{"2":{"395":1}}],["开启后请验证进程内存",{"2":{"1084":1}}],["开启后",{"2":{"1079":1}}],["开启后会占用gpu显存和cpu内存",{"2":{"363":1}}],["开启调试",{"2":{"985":1}}],["开启调试时不检验安全域名",{"2":{"984":1}}],["开启调试模式则输出详细日志",{"2":{"348":1}}],["开启proflingmemory后非常慢",{"0":{"973":1}}],["开启性能面板可通过修改unity",{"2":{"968":1}}],["开启gzip",{"2":{"873":1}}],["开启云函数本地调试",{"2":{"374":1}}],["开启了高性能+",{"2":{"370":1}}],["开启会增大1",{"2":{"363":1}}],["开发建议",{"0":{"1008":1},"1":{"1009":1,"1010":1}}],["开发设置",{"2":{"985":1}}],["开发知识",{"2":{"705":1}}],["开发模式",{"2":{"609":1}}],["开发管理",{"2":{"566":1,"567":1,"985":1}}],["开发时通常将资源在游戏启动时全加载到内存中",{"2":{"538":1}}],["开发调试",{"2":{"531":1}}],["开发错误调试与排查",{"2":{"459":1,"541":1}}],["开发者自行决定是否需要上传并打水印",{"2":{"1131":1}}],["开发者务必验证游戏所用到的特性支持情况",{"2":{"1078":1}}],["开发者一般不需要修改",{"2":{"960":1}}],["开发者无须自己实现缓存",{"2":{"944":1}}],["开发者无需手动修改",{"2":{"952":1}}],["开发者无需感知本地是否存在缓存",{"2":{"501":1}}],["开发者无需关心",{"2":{"501":1}}],["开发者只需要将asset设置为addressable然后加载即可",{"2":{"920":1}}],["开发者只需在导出时配置启动素材即可",{"2":{"422":1}}],["开发者在addressable的default中能看到所有这些资源",{"2":{"934":1}}],["开发者在管理后台发布新版本的小游戏之后",{"2":{"911":1}}],["开发者在导出面板配置的导出路径的微信开发者工具打开的",{"2":{"384":1}}],["开发者往往需要分析玩家从点击到进入游戏核心玩法的整个过程流失率",{"2":{"822":1}}],["开发者依此对游戏的启动与运行性能进行调优",{"2":{"776":1}}],["开发者应尽量减少首资源包压缩后大小",{"2":{"924":1}}],["开发者应该特别注意cpu侧的性能瓶颈",{"2":{"734":1}}],["开发者应根据实际调试后运行效果按需配置",{"2":{"393":1}}],["开发者输入",{"2":{"580":1}}],["开发者配置上报后",{"2":{"578":1}}],["开发者埋点上报异常捕捉的信息",{"2":{"565":1}}],["开发者埋点上报购买物品",{"2":{"565":1}}],["开发者埋点打印日志",{"2":{"565":1}}],["开发者看通过c",{"2":{"565":1}}],["开发者也可以通过wx",{"2":{"741":1}}],["开发者也可以通过客服助手直接与小游戏团队进行技术交流",{"2":{"563":1}}],["开发者也可通过使用wx",{"2":{"565":1}}],["开发者遇到bug或者希望新增特性优先使用git",{"2":{"562":1}}],["开发者的",{"2":{"545":1}}],["开发者根据需要进行按需接入",{"2":{"543":1}}],["开发者需要注意",{"2":{"874":1}}],["开发者需要注意的是",{"2":{"530":1,"875":1}}],["开发者需要关注哪些性能指标",{"0":{"760":1,"1112":1,"1118":1}}],["开发者需要根据不同品类的游戏建立不同的最低机型要求和流畅度标准",{"2":{"737":1}}],["开发者需要收集玩家遇到的错误",{"2":{"564":1}}],["开发者需要手动创建",{"2":{"377":1}}],["开发者请联系",{"2":{"431":1}}],["开发者可通过",{"2":{"759":1,"768":1}}],["开发者可通过机型档位映射获取机型档位的参考机型",{"2":{"757":1}}],["开发者可通过三种途径收集到游戏异常数据",{"2":{"564":1}}],["开发者可阅读本文自行选择转换方案",{"2":{"556":1}}],["开发者可以自定义封面",{"2":{"957":1}}],["开发者可以自行补充后30",{"2":{"579":1}}],["开发者可以自行设计",{"2":{"577":1}}],["开发者可以在离线测试阶段",{"2":{"1016":1}}],["开发者可以在后台下载到对应数据",{"2":{"565":1}}],["开发者可以在游戏内自助构建游戏导出脚本",{"2":{"411":1}}],["开发者可以操作的主要是playerloadfirstscene函数的调用",{"2":{"532":1}}],["开发者可自定义以下内容",{"2":{"418":1}}],["开发者可直接修改其配置内容",{"2":{"352":1}}],["开发者使用转换方案时",{"2":{"561":1}}],["开发者使用的",{"2":{"433":1}}],["开发者使用忽略处理能力完成对资源的保留在ab包内",{"2":{"398":1}}],["开发者使用后需要进行详细的真机测试",{"2":{"397":1}}],["开发者存在需要对",{"2":{"376":1}}],["开发者工具插件偶现下载wk",{"2":{"1055":1}}],["开发者工具上",{"2":{"1018":1}}],["开发者工具上可以打开文件系统查看缓存文件",{"2":{"523":1}}],["开发者工具中展示的小游戏项目名",{"2":{"893":1}}],["开发者工具中使用png资源",{"2":{"395":1}}],["开发者工具或者线上打印出来的堆栈",{"2":{"889":1}}],["开发者工具通过network面板查看资源下载url",{"2":{"527":1}}],["开发者工具提示pluginid",{"0":{"466":1}}],["开发者工具提示",{"0":{"464":1}}],["开发者工具暂时有异常",{"2":{"370":1}}],["开发者工具无法播放",{"2":{"370":1}}],["开发者工具",{"2":{"369":1,"446":1,"532":1,"965":1}}],["开发人员工具",{"2":{"351":1}}],["开发",{"2":{"276":1,"985":1}}],["开发阶段只有内网ip没正式域名",{"2":{"984":1}}],["开发阶段还没ssl证书可以跑起来吗",{"2":{"984":1}}],["开发阶段",{"0":{"769":1},"1":{"770":1,"771":1,"772":1},"2":{"885":1}}],["开发阶段的错误排查",{"0":{"541":1}}],["开发阶段分析内存",{"2":{"207":1}}],["开发阶段没显示耗时弹框",{"2":{"190":1}}],["开发版",{"2":{"108":1,"771":1}}],["若appid为测试号",{"2":{"1132":1}}],["若有异常",{"2":{"1131":1}}],["若遭遇恶意人员扒包抄袭",{"2":{"1128":1}}],["若问题仍无法解决",{"2":{"1046":1}}],["若需要某些特殊unicode",{"2":{"1004":1}}],["若不想使用水印功能",{"2":{"1131":1}}],["若不满足客户端版本要求",{"2":{"1001":1}}],["若不支持",{"2":{"959":1}}],["若填写相对路径",{"2":{"997":1}}],["若填写完成路径",{"2":{"997":1}}],["若填写bundledir则不可省略",{"2":{"414":1}}],["若想修改引擎初始化期间的并发数",{"2":{"996":1}}],["若手动将loaddatapackagefromsubpackage改为true",{"2":{"962":1}}],["若手动将loaddatapackagefromsubpackage改为false",{"2":{"962":1}}],["若已缓存",{"2":{"944":1}}],["若已经注册游戏角色可能会改变剧情内容",{"2":{"571":1}}],["若未缓存则缓存此bundle",{"2":{"944":1}}],["若小游戏是第一次使用本插件",{"2":{"896":1}}],["若作者认为不适合分享",{"2":{"844":1}}],["若加载时机过早",{"2":{"794":1}}],["若一切正常",{"2":{"613":1}}],["若开发者未定义后30",{"2":{"579":1}}],["若开发者使用api调用执行",{"2":{"406":1}}],["若仍未得到结果",{"2":{"577":1}}],["若",{"2":{"576":1}}],["若存在404时",{"2":{"560":1}}],["若存在独立的ab包目录",{"2":{"414":1,"417":1}}],["若追求较好的游戏品质",{"2":{"557":1}}],["若游戏为休闲关卡类等小型游戏",{"2":{"557":1}}],["若本地有版本b",{"2":{"526":1}}],["若本地有文件缓存",{"2":{"519":1}}],["若本地已经有此文件的旧缓存",{"2":{"509":1}}],["若由步骤",{"2":{"479":1}}],["若启动封面无法打开vconsole",{"2":{"459":1}}],["若无返回值则传回",{"2":{"424":1}}],["若执行前已安装",{"2":{"406":1}}],["若资源支持以",{"2":{"405":1}}],["若使用的",{"2":{"827":1}}],["若使用期间存在异常影响正常的游戏发布可前往issues提出问题",{"2":{"400":1}}],["若使用了其他第三方",{"2":{"374":1}}],["若此前从未执行过微信压缩纹理",{"2":{"398":1}}],["若为开发版",{"2":{"348":1}}],["若新版本出现异常",{"2":{"108":1}}],["规则为",{"2":{"348":1}}],["同理",{"2":{"876":1}}],["同理当你",{"2":{"629":1}}],["同样的",{"2":{"962":1,"995":1}}],["同样地",{"2":{"743":1}}],["同样能接触",{"2":{"697":1}}],["同名事件是支持创建多个并同时生效",{"2":{"622":1}}],["同名文件缓存未清理",{"2":{"263":1}}],["同步",{"2":{"576":1}}],["同步和异步",{"2":{"328":1}}],["同一个文件",{"0":{"526":1},"2":{"500":1}}],["同",{"2":{"451":2,"641":1,"649":1,"652":1}}],["同时我们对子包支持按需加载",{"2":{"1031":1}}],["同时提审发布",{"2":{"1029":1}}],["同时提供了包装好的unity",{"2":{"945":1}}],["同时推荐使用wxassetbundle更自动化地节省内存",{"2":{"940":1}}],["同时也能卸载资源",{"2":{"919":1}}],["同时它会自动管理并加载好该内容的全部依赖",{"2":{"919":1}}],["同时结合压缩纹理优化减少包体积",{"2":{"831":1}}],["同时分阶段的耗时分布有利于帮助我们分析该阶段的对应耗时的用户占比",{"2":{"827":1}}],["同时会忽略monitorduration的值",{"2":{"785":1}}],["同时存在的音频数不应该超过20个",{"2":{"729":1}}],["同时设置",{"2":{"666":1}}],["同时设置组件的size",{"2":{"627":1}}],["同时自动释放注册的事件",{"2":{"587":1}}],["同时要注意避免频繁的同步接口调用",{"2":{"490":1}}],["同时需要注意实际未使用关系链数据时请删掉game",{"2":{"466":1}}],["同时",{"2":{"441":1,"512":1,"727":1,"874":1,"927":1,"988":1}}],["同时由于小游戏总包体不能超过20mb",{"2":{"437":1}}],["同时纹理从ab中剥离出来",{"2":{"387":1}}],["同版本",{"2":{"389":1}}],["仅供参考",{"2":{"1126":1}}],["仅需要部分unicode",{"2":{"1004":1}}],["仅表示发布时间",{"2":{"919":1}}],["仅dxt",{"2":{"905":2}}],["仅ios高性能",{"2":{"795":1}}],["仅安卓",{"2":{"795":1}}],["仅当showresultafterlaunch=false时有效",{"2":{"785":1}}],["仅包含线上用户数据",{"2":{"759":1,"1106":1}}],["仅包含简单操作",{"2":{"758":1,"1113":1}}],["仅支持",{"2":{"1007":1}}],["仅支持ios",{"2":{"748":1}}],["仅支持webgl1",{"2":{"498":1}}],["仅支持2021以上版本",{"2":{"137":1}}],["仅仅是ab包内部分纹理资源渲染不佳",{"2":{"398":1}}],["仅推荐使用小游戏分包加载时节省包体大小使用",{"2":{"353":1}}],["仅调试问题时勾选此选项时",{"2":{"302":1}}],["并处罚恶意抄袭人员",{"2":{"1128":1}}],["并尽量覆盖游戏内的场景",{"2":{"1016":1}}],["并修改lualib",{"2":{"973":1}}],["并修改它",{"2":{"493":1}}],["并勾选导出选项",{"2":{"968":1}}],["并将cdn地址填写到game",{"2":{"962":1}}],["并将这些资源托管至",{"2":{"557":1}}],["并重新为someprefab赋值",{"2":{"927":1}}],["并了解启动loader在加载资源时的缓存逻辑",{"2":{"895":1}}],["并设置",{"2":{"874":1}}],["并使用微信小游戏文件存储系统进行缓存",{"2":{"921":1}}],["并使用loadassetasync等异步接口",{"2":{"831":1}}],["并使用上一代稳定版微信纹理压缩包",{"2":{"400":1}}],["并发数",{"0":{"996":1}}],["并发数较少可能导致细碎文件较多时网络利用率不高",{"2":{"799":1}}],["并发数数",{"2":{"797":1}}],["并不能反应真实使用情况",{"2":{"740":1}}],["并不包含小游戏公共库",{"2":{"731":1}}],["并不是所有文件都有必要缓存",{"2":{"507":1}}],["并不是一个可以运行的标准javascript代码包",{"2":{"377":1}}],["并不是undo",{"2":{"362":1}}],["并非每个unity版本unityprofiler都稳定",{"2":{"902":1}}],["并非用",{"2":{"807":1}}],["并非全部",{"2":{"720":1}}],["并非所有文件都适合持久化缓存",{"2":{"507":1}}],["并可以具体查看每一个",{"2":{"626":1}}],["并赋予了他一些初始化的属性",{"2":{"621":1}}],["并做简单的逻辑修改来适配",{"2":{"555":1}}],["并前往",{"2":{"540":1}}],["并正确设置导出面板的",{"2":{"462":1}}],["并申请为小游戏服务类目",{"2":{"456":1}}],["并导致程序",{"2":{"451":1}}],["并选中",{"2":{"428":1}}],["并编辑",{"2":{"410":1}}],["并在console输入命令",{"2":{"968":1}}],["并在2019的版本中已经成为正式版本",{"2":{"919":1}}],["并在后续合理的时机完成故事线的切换",{"2":{"577":1}}],["并在渲染期间做了兜底的渲染策略",{"2":{"405":1}}],["并在unity控制台中给出详细的冲突信息",{"2":{"378":1}}],["并按需忽略部分不希望执行压缩纹理的bundle资源",{"2":{"395":1}}],["并检查环境变量是否生效",{"2":{"390":1}}],["并且有新增函数",{"2":{"1037":1}}],["并且有一个完善的profiler帮助你指出潜在的内存问题",{"2":{"919":1}}],["并且由于",{"2":{"977":1}}],["并且需要主动设置高宽",{"2":{"654":1}}],["并且能够跟随项目git等代码版本托管迭代",{"2":{"582":1}}],["并且进度条前70",{"2":{"579":1}}],["并且为了避免频繁触发清理",{"2":{"512":1}}],["并且已经切换到",{"2":{"428":1}}],["并且不支持",{"2":{"393":1}}],["并且只填写你关注的字段",{"2":{"380":1}}],["并且unity也是默认关闭",{"2":{"363":1}}],["并自动提交用户反馈日志",{"2":{"301":1}}],["并支持不同的块大小",{"2":{"155":1}}],["程序捕捉的异常",{"2":{"451":1}}],["程序捕捉异常",{"2":{"451":1}}],["程序未捕捉异常有最浅层堆栈函数名",{"2":{"451":1}}],["程序未捕捉异常",{"2":{"451":2}}],["程序即将crash之前弹出用户反馈入口",{"2":{"301":1}}],["程序crash时触发用户反馈入口",{"2":{"298":1}}],["提高可缓存数量",{"2":{"799":1}}],["提高下载成功率",{"2":{"501":1}}],["提前加载子包",{"2":{"1031":1}}],["提前在unity环境使用unity",{"2":{"782":1}}],["提前结束启动剧情",{"2":{"586":1,"601":1}}],["提审版本请勿显示",{"2":{"717":1}}],["提示用户重启更新",{"2":{"913":1}}],["提示出错的资源信息",{"2":{"527":1}}],["提示",{"0":{"461":1},"2":{"411":1}}],["提升用户体验",{"2":{"755":1,"1103":1,"1117":1}}],["提升运行速度",{"2":{"549":1}}],["提升unity",{"0":{"866":1},"1":{"867":1,"868":1,"869":1,"870":1,"871":1,"872":1,"873":1,"874":1,"875":1,"876":1,"877":1,"878":1,"879":1,"880":1,"881":1,"882":1,"883":1},"2":{"546":1,"778":1}}],["提升渲染效率",{"2":{"386":1}}],["提升转换速度",{"2":{"294":1}}],["提供日志排查",{"2":{"1046":1}}],["提供了",{"2":{"1001":1}}],["提供了几种简单的描述几乎可以满足大部分的使用需要",{"2":{"629":1}}],["提供autostreaming资源自动化处理",{"2":{"907":1}}],["提供更强的unity",{"2":{"905":1}}],["提供webassembly基础能力",{"2":{"885":1}}],["提供平台能力的c",{"2":{"885":1}}],["提供压缩纹理按需加载的能力工具",{"2":{"386":1}}],["提供loader启动数据",{"2":{"204":1}}],["提供插件缓存路径plugincachepath",{"2":{"127":1}}],["提供instant",{"2":{"94":1}}],["导致配置在预下载列表中的资源是旧版本的资源",{"2":{"993":1}}],["导致mp无法登记安全域名能跑起来吗",{"2":{"984":1}}],["导致markdownviewer报错",{"2":{"286":1}}],["导致解析过慢而影响启动速度",{"2":{"743":1}}],["导致部分模块比如ai",{"2":{"734":1}}],["导致缓存失败",{"2":{"513":1}}],["导致多点触控不正确",{"0":{"476":1}}],["导入插件后会有wxassetbundleprovider",{"2":{"922":1}}],["导入转换后的minigame目录",{"2":{"896":1}}],["导入项目",{"2":{"896":1}}],["导入",{"2":{"838":1}}],["导入文件后",{"2":{"533":1}}],["导入步骤1的启动过程profile文件",{"2":{"533":1}}],["导入本地的",{"2":{"428":2}}],["导入工程后采用旧版本完成游戏发布",{"2":{"400":1}}],["导出时自动替换",{"2":{"992":1}}],["导出时自动清理unityeditor默认打包但游戏项目从未使用的资源",{"2":{"355":1}}],["导出预下载列表",{"0":{"990":1},"1":{"991":1}}],["导出内存堆栈数据",{"2":{"968":1}}],["导出场景不要勾选任何其他场景",{"2":{"924":1}}],["导出阶段",{"2":{"885":1}}],["导出小游戏项目后",{"2":{"1014":1}}],["导出小游戏项目后代码将存储在",{"2":{"550":1}}],["导出小游戏默认在开发版和体验版开启检测",{"2":{"785":1}}],["导出目录",{"2":{"724":1}}],["导出目录中",{"2":{"436":1}}],["导出面板",{"2":{"748":1,"817":1,"913":1}}],["导出面板勾选",{"2":{"717":1,"727":1}}],["导出面板进行导出微信小游戏即可",{"2":{"576":1}}],["导出剧本",{"0":{"615":1}}],["导出选项时勾选",{"2":{"805":1,"902":1}}],["导出选项勾选使用好友关系链",{"0":{"704":1}}],["导出选项勾选webgl2实验能力",{"2":{"477":1}}],["导出选项中禁用异常",{"2":{"567":1}}],["导出profile文件",{"2":{"531":1}}],["导出的webgl游戏在浏览器时能自动连接到unity",{"2":{"805":1,"902":1}}],["导出的代码包中将包含可读函数名",{"2":{"448":1}}],["导出的游戏工程来自",{"2":{"389":1}}],["导出webgl并转化为小游戏",{"2":{"394":1}}],["导出游戏工程",{"2":{"394":2}}],["导出游戏",{"0":{"394":1}}],["导出产物",{"2":{"384":2}}],["导出资源目录",{"2":{"377":1}}],["导出路径",{"2":{"353":1,"893":1,"899":1}}],["导出插件导出到",{"2":{"889":1}}],["导出插件自动生成",{"2":{"438":1}}],["导出插件",{"2":{"367":1}}],["导出插件只提示更新",{"2":{"335":1}}],["导出插件的brotli压缩不依赖python环境",{"2":{"194":1}}],["导出配置调整",{"2":{"285":1}}],["导出增加sbrk函数",{"2":{"142":1}}],["设备发烫",{"2":{"1091":1}}],["设备平台的内存统计口径参考社区公告",{"2":{"762":1}}],["设备默认devicepixelratio",{"2":{"748":1}}],["设备",{"2":{"432":2,"543":1}}],["设备方向",{"2":{"353":1}}],["设备方向无法选中",{"2":{"283":1}}],["设计上尽量按需加载",{"2":{"928":1}}],["设计",{"2":{"854":1}}],["设计剧情",{"0":{"575":1}}],["设计尺寸",{"2":{"423":1}}],["设计稿",{"2":{"423":1}}],["设计高度",{"2":{"421":1}}],["设计宽度",{"2":{"421":1}}],["设置分组属性如下",{"2":{"926":1}}],["设置分享菜单",{"2":{"708":1}}],["设置最低可用版本",{"0":{"914":1}}],["设置为略大于dynamicmemory峰值",{"2":{"727":1}}],["设置为",{"2":{"707":1,"979":2,"983":2}}],["设置为180",{"2":{"699":1}}],["设置占位纹理",{"0":{"699":1}}],["设置后可供外界访问",{"2":{"681":1}}],["设置后若接近容量阈值将自动回收",{"2":{"353":1}}],["设置单个属性",{"2":{"663":1}}],["设置某个关键动作帧的属性",{"2":{"627":1}}],["设置多个不同的事件",{"2":{"622":1}}],["设置启动剧情全局变量值",{"2":{"593":1,"604":1}}],["设置启动时是否自动检查小游戏版本更新",{"2":{"186":1}}],["设置表面的类型",{"2":{"431":1}}],["设置阴影偏移",{"2":{"431":1}}],["设置",{"2":{"370":1,"430":1,"431":1,"523":1,"914":1,"1043":1}}],["缓存策略",{"2":{"951":1}}],["缓存写满之后的自动清理逻辑",{"2":{"526":1}}],["缓存文件在usr目录下",{"2":{"523":1}}],["缓存文件数=xxx",{"2":{"516":1}}],["缓存目录",{"2":{"523":1}}],["缓存",{"2":{"515":1}}],["缓存淘汰相关",{"2":{"505":1}}],["缓存仍不生效",{"0":{"527":1},"2":{"500":1}}],["缓存清理规则",{"0":{"512":1},"2":{"500":1,"526":1,"529":1}}],["缓存规则",{"0":{"504":1},"1":{"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1},"2":{"500":1,"523":1,"799":1}}],["缓存大小为0",{"2":{"274":1}}],["缓存到用户目录但不增加unity内存",{"2":{"16":1}}],["性能评测标准希望能引导开发者优化相关性能数据",{"2":{"1117":1}}],["性能评估标准",{"2":{"711":1}}],["性能上重点对首场景启动优化",{"2":{"832":1}}],["性能诊断工具",{"0":{"771":1}}],["性能监控系统",{"2":{"767":1}}],["性能报告",{"0":{"767":1}}],["性能数据",{"0":{"768":1},"2":{"759":1,"768":1}}],["性能分析",{"2":{"759":1,"768":1,"1106":1}}],["性能基线机型并非特定",{"2":{"1105":1}}],["性能基线",{"0":{"757":1,"1105":1,"1120":1}}],["性能",{"2":{"741":1}}],["性能优化总览",{"0":{"774":1},"1":{"775":1,"776":1,"777":1,"778":1,"779":1,"780":1,"781":1,"782":1}}],["性能优化",{"2":{"730":2}}],["性能调优查看lua的耗时占比",{"2":{"744":1}}],["性能调优",{"2":{"548":2,"719":1,"739":1}}],["性能最高",{"2":{"451":1}}],["性能提升",{"0":{"1085":1},"1":{"1086":1,"1087":1},"2":{"266":1,"1082":1}}],["性能面板",{"2":{"488":1,"713":1}}],["性能面板增加profilingmemory",{"2":{"127":1}}],["性能面板数值显示优化",{"2":{"87":1}}],["用法如下",{"2":{"889":1}}],["用法保持不变",{"2":{"261":1}}],["用不到的材质属性会剔除掉",{"2":{"807":1}}],["用不到的属性可以剔除掉",{"2":{"430":1}}],["用来新建材质替代默认的材质",{"2":{"812":1}}],["用来热更新资源",{"2":{"799":1}}],["用来分析分包收集是否合理",{"2":{"794":1}}],["用js开发排行榜这类微信关系逻辑",{"0":{"705":1}}],["用故事线串联一系列动作帧让他们有序执行",{"2":{"626":1}}],["用户占比约为",{"2":{"1093":1}}],["用户占比",{"0":{"1077":1},"2":{"1077":2}}],["用户占比和兼容性不如",{"2":{"807":1}}],["用户下载的代码包只能是提审发布过的",{"2":{"1035":1}}],["用户",{"2":{"727":1}}],["用户的实际网络也是影响的重要因素",{"2":{"581":1}}],["用户新设备或本地缓存丢失时也将判定为新用户",{"2":{"577":1}}],["用户反馈",{"2":{"565":1}}],["用户反馈日志",{"0":{"565":1},"2":{"564":1,"565":1}}],["用unity网络接口发起请求",{"2":{"503":1}}],["用",{"2":{"431":1,"505":2,"899":1,"900":2}}],["用于区分不同广告位",{"2":{"823":1}}],["用于区域点击识别",{"2":{"627":1}}],["用于websocket转发",{"2":{"805":1,"902":1}}],["用于分析长耗时帧",{"2":{"785":1}}],["用于表明时间类型",{"2":{"703":1}}],["用于特定assetbundle的缓存保持",{"2":{"512":1}}],["用于识别缓存",{"2":{"353":1}}],["用于首包资源没放到data",{"2":{"353":1}}],["用于缓存控制",{"2":{"290":1,"353":1}}],["用于清理所有文件缓存",{"2":{"258":1}}],["用于游戏自定义场景上报",{"2":{"127":1}}],["达到节约内存的目的",{"2":{"945":1}}],["达到最佳仍需要",{"2":{"829":2}}],["达到最好的买量效果",{"2":{"823":1}}],["达到可上线标准的小游戏体验",{"2":{"534":1}}],["达到缓存上限",{"2":{"516":1}}],["达到缓存上限时默认额外清理的存储大小",{"2":{"900":1}}],["达到缓存上限时",{"2":{"512":1}}],["达到缓存上限时清理更多空间",{"2":{"259":1}}],["达到缓存上限后",{"2":{"512":1}}],["达缓存上限时未正常清理旧缓存",{"2":{"225":1}}],["r9s",{"2":{"1105":1,"1120":1}}],["rootrect",{"2":{"1073":1}}],["rootrect初始时设置其anchor",{"2":{"1073":1}}],["rotation设置为180",{"2":{"707":1}}],["rotation的x",{"2":{"699":1}}],["rc",{"2":{"1016":1,"1129":1}}],["rw",{"2":{"947":1}}],["rules",{"2":{"926":1}}],["running",{"0":{"479":1,"584":1},"2":{"584":1}}],["runtimems",{"2":{"826":1}}],["runtime=xxxms",{"2":{"802":1}}],["runtimeinitialize",{"2":{"532":2}}],["runtime",{"2":{"370":1,"377":3,"576":1,"582":1,"801":1,"922":2,"971":2,"1031":1}}],["runtime模式下该选项无效",{"2":{"355":1}}],["run",{"2":{"246":1,"575":1,"902":1}}],["rate",{"2":{"1126":1}}],["ratio",{"2":{"748":1,"817":2}}],["ram",{"2":{"1090":1}}],["rankbody",{"2":{"707":6}}],["rankingbox",{"2":{"707":1}}],["ranking下面的unity工程",{"2":{"706":1}}],["rankmask",{"2":{"707":1}}],["randomdevices替换",{"2":{"274":1}}],["rawimage设置为200",{"2":{"707":1}}],["rawimage",{"2":{"699":1,"701":2,"702":1,"707":2,"709":1}}],["right=0",{"2":{"629":1}}],["right",{"2":{"614":1,"621":2,"629":1,"632":1,"634":1,"655":1,"657":1,"659":1,"661":1,"667":1,"668":1,"676":1}}],["rpgpp",{"2":{"926":2}}],["rpg游戏为创角",{"2":{"759":1,"1106":1,"1120":1}}],["rp",{"2":{"428":16,"808":2}}],["rp包",{"2":{"428":3}}],["rp项",{"2":{"428":1}}],["rgb",{"2":{"392":5,"393":1}}],["rgba32造成巨大的cpu和内存消耗",{"2":{"749":1}}],["rgba",{"2":{"392":4}}],["r",{"2":{"392":2,"947":2}}],["realloc",{"2":{"971":2}}],["ready",{"2":{"930":1,"931":1}}],["readassets",{"2":{"826":2}}],["readme",{"2":{"421":1,"423":1}}],["read",{"2":{"363":1}}],["readfilesync",{"2":{"70":1,"71":1}}],["readfile和fs",{"2":{"70":1}}],["rewrite",{"2":{"889":1}}],["rectmask2d",{"2":{"812":1}}],["recttransform",{"2":{"707":4}}],["rect",{"2":{"661":3,"707":4}}],["receivedbytedcount",{"2":{"798":1}}],["received",{"2":{"602":1}}],["release",{"2":{"615":2,"931":2}}],["releasesuccess",{"2":{"521":1}}],["releaseresult",{"0":{"521":1},"2":{"500":1,"521":2}}],["repot",{"2":{"499":1}}],["reportgamesceneerror",{"2":{"825":1}}],["reportgamestart",{"2":{"785":1,"825":2}}],["report",{"0":{"690":1},"1":{"691":1,"692":1},"2":{"479":1,"627":1,"692":7,"881":1}}],["reporting",{"2":{"479":1}}],["reportscene是否可用",{"2":{"1007":1}}],["reportsceneparams",{"2":{"825":1}}],["reportscene",{"2":{"127":1,"825":5,"1007":1}}],["reportscene接口",{"2":{"127":1}}],["referenceresolution",{"2":{"707":5,"1073":3}}],["references",{"2":{"451":1}}],["reflectivityspecular",{"2":{"431":1}}],["reflectionprobe",{"2":{"431":1}}],["reflection",{"2":{"430":1}}],["renderoptimization",{"0":{"806":1},"1":{"807":1,"808":1,"809":1,"810":1,"811":1,"812":1,"813":1,"814":1,"815":1,"816":1,"817":1,"818":1,"819":1,"820":1}}],["renderer",{"2":{"753":4}}],["rendercom",{"2":{"493":2}}],["renderscale",{"2":{"431":1}}],["rendergraph",{"2":{"431":1}}],["renderinglayer",{"2":{"431":1}}],["rendering",{"2":{"430":1,"531":1}}],["render",{"2":{"428":4,"429":2,"433":1,"1093":1}}],["registry",{"2":{"428":1}}],["resize",{"2":{"971":2}}],["resource改造",{"0":{"934":1}}],["resourcemanager",{"2":{"922":1}}],["resources目录的内容都会被打包进首包资源",{"2":{"934":1}}],["resources",{"2":{"934":2}}],["resources文件夹中的资源",{"2":{"873":1}}],["resources文件",{"2":{"873":1}}],["resources资源",{"2":{"437":1}}],["resource目录所有资源",{"2":{"864":1}}],["reserved内存",{"2":{"724":1}}],["result",{"2":{"374":3,"414":2,"533":1,"927":1,"930":2,"931":1,"932":1,"934":1,"995":2}}],["res",{"2":{"374":7,"499":2,"708":3,"825":6,"979":7,"983":3,"994":6,"1005":4}}],["response",{"2":{"374":5,"1096":1}}],["return",{"2":{"374":4,"507":2,"512":3,"555":2,"703":1,"926":1,"927":1,"931":2,"934":1,"943":2,"945":1,"973":3,"977":2,"995":1}}],["returns",{"2":{"367":1}}],["redo逻辑",{"2":{"362":1}}],["removefile",{"0":{"522":1},"2":{"500":1,"522":1}}],["removefile参数转字符串",{"2":{"202":1}}],["remove",{"2":{"428":2}}],["removed",{"0":{"346":1}}],["requirecomponent",{"2":{"555":1}}],["require时使用bundle",{"2":{"475":1}}],["require",{"0":{"491":1},"2":{"374":1}}],["requireprivacyauthorize等",{"2":{"73":1}}],["requestbundlecatalog=true",{"2":{"799":2}}],["requestbundlecatalog",{"2":{"798":1}}],["requestbundlesettings=true",{"2":{"799":1}}],["requestbundlesettings",{"2":{"798":1}}],["requestcatahash=true",{"2":{"799":1}}],["requestcatahash",{"2":{"798":1}}],["requestsubscribemessage",{"2":{"491":1}}],["requestsubscribeliveactivity",{"2":{"73":1}}],["request",{"2":{"374":1,"943":6,"985":1,"994":2}}],["预加载资源",{"0":{"963":1}}],["预加载",{"2":{"928":1}}],["预览默认剧情",{"0":{"613":1}}],["预览",{"2":{"458":1}}],["预下载无效",{"2":{"999":1}}],["预下载所有文件总体积应控制在合理范围内",{"2":{"999":1}}],["预下载的列表的原理是提前通过网络下载资源并缓存到本地",{"2":{"988":1}}],["预下载文件列表",{"2":{"899":1}}],["预下载文件体积不应过大",{"2":{"793":1}}],["预下载",{"2":{"899":1}}],["预下载资源量较大",{"2":{"793":1}}],["预下载资源较小",{"2":{"793":1}}],["预下载资源个数较多",{"2":{"793":1}}],["预下载资源个数",{"2":{"792":1}}],["预下载基本信息",{"2":{"791":1}}],["预下载检测",{"0":{"791":1},"1":{"792":1,"793":1},"2":{"783":1}}],["预下载列表",{"2":{"353":1,"893":1}}],["预下载问题路径bug",{"2":{"227":1}}],["预载列表按照填写顺序生成",{"2":{"240":1}}],["预发布",{"0":{"1":1},"1":{"2":1,"3":1}}],["暴露插件进度事件",{"2":{"211":1}}],["避免模糊的问题",{"2":{"1074":1}}],["避免业务逻辑需要全量资源的情况",{"2":{"928":1}}],["避免大量的大屏幕的半透明特效重叠导致的",{"2":{"819":1}}],["避免同时启用多于",{"2":{"816":1}}],["避免瓶颈的手段有",{"2":{"814":1}}],["避免上述的",{"2":{"812":1}}],["避免使用",{"2":{"811":1,"812":3}}],["避免使用unity自带的文件缓存机制",{"2":{"728":1}}],["避免用实时光照",{"2":{"811":1}}],["避免用户无法退出剧情插件模式",{"2":{"576":1}}],["避免直接从源站拉取资源",{"2":{"799":1}}],["避免直接调用存储接口绕开校验的情况出现",{"2":{"374":1}}],["避免内存不足时导致扩容产生的尖刺",{"2":{"727":1}}],["避免单帧内分配过多的对象",{"2":{"727":1}}],["避免过大的assetbundle导致瞬间峰值",{"2":{"727":1}}],["避免场景过大导致瞬间峰值",{"2":{"727":1}}],["避免云函数代码被业务逻辑代码一同打包发布到外网",{"2":{"374":1}}],["避免与游戏代码冲突",{"2":{"347":1}}],["避免有nuget产生dll冲突",{"2":{"195":1}}],["避免动态创建的类型被裁剪",{"2":{"97":1}}],["6~15",{"2":{"1126":1}}],["6s",{"2":{"1090":1,"1124":1}}],["6sp",{"2":{"711":1}}],["6m",{"2":{"1014":1}}],["67190",{"2":{"889":1}}],["66b71f",{"2":{"423":1}}],["649ms",{"2":{"532":1}}],["64",{"2":{"421":3,"614":1}}],["6x6",{"2":{"393":1}}],["600",{"2":{"1005":2}}],["60s",{"2":{"988":1,"998":1}}],["6028bab6edbc2a750bf5b8a7",{"2":{"949":1}}],["60~80",{"2":{"905":1}}],["60使用raf分片处理",{"2":{"747":1}}],["60",{"2":{"225":1,"614":1}}],["6",{"0":{"191":1,"193":1,"196":1,"198":1,"201":1,"203":1,"206":1,"208":1,"408":1,"461":1,"475":1,"488":1,"693":1,"694":1,"695":1,"730":1,"748":1,"937":1,"938":1,"965":1,"1060":1,"1098":1},"1":{"192":1,"194":1,"195":1,"197":1,"199":1,"200":1,"202":1,"204":1,"205":1,"207":1,"209":1,"409":1,"410":1,"694":1,"695":1,"1061":1},"2":{"580":1,"826":1,"947":1,"1012":1,"1082":1}}],["6格式",{"2":{"68":1,"135":1}}],["补充小程序框架异常时上报实时日志",{"2":{"272":1}}],["补充touchcancel事件",{"2":{"171":1}}],["补充启动阶段关键日志",{"2":{"81":1}}],["在目录树上方工具栏找到水印工具icon",{"2":{"1131":1}}],["在目录树上的工具栏中",{"2":{"1020":1}}],["在平台原有相似度检测基础上",{"2":{"1128":1}}],["在这个时间之后才触发未收集函数的情况也不会有加载子包的影响",{"2":{"1031":1}}],["在真机上跑游戏",{"2":{"1026":1}}],["在真机环境则无",{"2":{"451":1}}],["在主入口初始化",{"2":{"1005":1}}],["在插件启动前",{"2":{"994":1}}],["在插件启动前修改",{"0":{"994":1}}],["在处理websocket数据包时",{"2":{"982":1}}],["在处理相对位置的时候有时",{"2":{"629":1}}],["在给定的套接字上启动连接",{"2":{"979":1}}],["在不同端上的行为基本是一致的",{"2":{"974":1}}],["在lua源码目录下的同名文件中增加simple",{"2":{"973":1}}],["在业务侧看来",{"2":{"944":1}}],["在网络空闲时可预下载游戏需要用到的ab包",{"2":{"938":1,"963":1}}],["在用到的时候才下载该场景包",{"2":{"926":1}}],["在所有的依赖加载完成",{"2":{"919":1}}],["在此阶段最多只能允许10个并发",{"2":{"999":1}}],["在此可使用handle",{"2":{"926":1}}],["在此",{"2":{"917":1}}],["在打开小游戏前",{"2":{"911":1}}],["在启动加载时会循环播放这段视频",{"2":{"893":1}}],["在启动剧情中由两个剧本元素组成",{"2":{"619":1}}],["在得到成就感的同时收获相关的翡翠知识",{"2":{"854":1}}],["在满足画质情况下",{"2":{"813":1}}],["在移动端性能更好",{"2":{"812":1}}],["在开发者工具会报错提示插件未授权",{"2":{"896":1}}],["在开发者工具有出现详细堆栈函数",{"2":{"451":1}}],["在开始长耗时逻辑前",{"2":{"799":1}}],["在cpu繁忙时未充分利用网络空闲",{"2":{"799":1}}],["在新包做wasm分包期间可能会频繁提示优化建议",{"2":{"794":1}}],["在引擎初始化完成后仍会重置为",{"2":{"996":1}}],["在引擎初始化完成前",{"2":{"996":1}}],["在引擎初始化完成",{"2":{"785":1}}],["在中低端机型限制帧率以减轻设备发烫",{"2":{"782":1}}],["在压缩纹理不支持的情况下",{"2":{"749":1}}],["在勾选profile",{"2":{"739":1}}],["在相同算力条件下两者性能是接近的",{"2":{"736":1}}],["在相同的菜单中选择stop",{"2":{"351":1}}],["在unity侧使用微信插件导出时",{"2":{"1024":1}}],["在unity转换导出插件填写文件列表",{"2":{"991":1}}],["在unityloader加载过程中存在网络空闲的情况",{"2":{"988":1}}],["在unity",{"2":{"731":1}}],["在android",{"2":{"712":1}}],["在android微信小游戏打开调试进行录制",{"2":{"351":1}}],["在小游戏底层对bundle做缓存及缓存淘汰时",{"2":{"942":1}}],["在小游戏环境",{"2":{"927":1}}],["在小游戏环境下",{"2":{"822":1}}],["在小游戏环境中并不存在dom",{"2":{"712":1}}],["在小游戏生态下玩家对启动耗时更敏感",{"2":{"775":1}}],["在小游戏平台请勿使用unity的setresulution等接口修改分辨率",{"2":{"748":1}}],["在小游戏未开启webgl2",{"2":{"734":1}}],["在小游戏中使用addressable",{"0":{"921":1}}],["在小游戏中unity游戏唤不起输入法",{"2":{"555":1}}],["在小游戏中推荐将资源包拆分成为一个个小文件加载",{"2":{"501":1}}],["在操作系统的控制策略下超出阈值时非常容易被oom",{"2":{"711":1}}],["在分享时",{"2":{"708":1}}],["在屏幕中绝对的位置和尺寸",{"2":{"707":1}}],["在需要展示的地方调用",{"0":{"701":1}}],["在需要绘制排行榜的时候",{"2":{"697":1}}],["在游戏运行时适宜的位置进行加载",{"2":{"831":1}}],["在游戏运行中如需按需加载",{"2":{"386":1}}],["在游戏过程中也尽量避免这类cpu消耗",{"2":{"743":1}}],["在游戏需要展示的地方创建一个",{"2":{"699":1}}],["在关闭排行榜的时候",{"2":{"697":1}}],["在视频可播放后再隐藏图片资源",{"2":{"695":1}}],["在特定条件下触发",{"2":{"635":1,"638":1,"668":1}}],["在描述组件的空间位置时",{"2":{"629":1}}],["在使用前请了解本工具的一些行为约束",{"2":{"618":1}}],["在使用hybridclr等第三方组件时只能用optimizespeed",{"2":{"355":1}}],["在合适的目录下创建你的剧情编辑工程",{"2":{"611":1}}],["在合理的时机进行路径配置",{"2":{"409":1}}],["在重新导出游戏时将会被覆盖",{"2":{"582":1}}],["在3~5秒期间",{"2":{"577":1}}],["在文件底部增加启动剧情初始化配置",{"2":{"576":1}}],["在部署方面",{"2":{"557":1}}],["在初始化",{"2":{"1074":1}}],["在初始化期间对启动剧情组件进行相关配置",{"2":{"585":1}}],["在初始",{"2":{"546":1}}],["在进入小游戏后",{"2":{"533":1}}],["在timelog中呈现的首场景耗时即为引擎初始化与开发者首帧逻辑",{"2":{"530":1,"875":1}}],["在touchend时触发点击事件",{"2":{"89":1}}],["在提升unity",{"2":{"530":1}}],["在写入缓存前",{"2":{"513":1}}],["在写入缓存前需要经过三步",{"2":{"513":1}}],["在清理时也支持忽略一些文件",{"2":{"512":1}}],["在微信开发者工具中选择gamecontext",{"2":{"968":1}}],["在微信开发者工具运行游戏",{"2":{"967":1,"968":1}}],["在微信开发者工具上可能渲染会异常",{"2":{"493":1}}],["在微信小游戏中有两种播放视频的方式",{"2":{"368":1}}],["在回调内使用这类api",{"2":{"491":1}}],["在webgl模式下",{"2":{"532":1}}],["在wasm代码分包情况下",{"2":{"446":1,"449":1}}],["在wx",{"2":{"424":1}}],["在wxsdk初始化时",{"2":{"378":1}}],["在转换完成后",{"2":{"435":1,"894":1}}],["在该标签页下找到",{"2":{"429":1}}],["在弹出的",{"2":{"428":1}}],["在弹出列表选择",{"2":{"428":1}}],["在js侧代码中合适位置添加以下代码",{"2":{"426":1}}],["在结束导出后不会真实的影响你的游戏工程内容",{"2":{"384":1}}],["在导出期间修改你的自定义模板",{"2":{"384":1}}],["在导出结束后wxsdk会自动恢复你的修改",{"2":{"383":1}}],["在导出微信小游戏时作出检查",{"2":{"378":1}}],["在构建模板中通常需要以下几个阶段的钩子",{"2":{"382":1}}],["在构建时提供的不同时机钩子允许开发者使用c",{"2":{"381":1}}],["在package",{"2":{"377":1}}],["在实际的游戏开发中",{"2":{"376":1}}],["在其他平台都可以播放",{"2":{"370":1}}],["在双端有较好的兼容",{"2":{"367":1}}],["在",{"0":{"1007":1},"2":{"367":1,"370":1,"377":1,"405":1,"428":4,"429":6,"479":1,"583":1,"709":1,"812":1,"975":1,"977":1,"978":1,"985":1,"1083":1}}],["在ios普通模式无法正常渲染的问题",{"2":{"159":1}}],["需是插件会自动缓存的文件",{"2":{"999":1}}],["需再次修改为你需要的值",{"2":{"996":1}}],["需将游戏内资源逐一拆分",{"2":{"833":1}}],["需使用腾讯云cdn服务",{"2":{"829":1}}],["需使用新微信账号访问体验",{"2":{"571":1}}],["需前往",{"2":{"827":1}}],["需开发者自行评估devicepixelratio降低后的品质变化",{"2":{"748":1}}],["需开发者自行分析",{"2":{"717":1}}],["需特别注意机型兼容性",{"2":{"737":1}}],["需控制在500mb左右",{"2":{"724":1}}],["需以",{"2":{"513":1}}],["需调整",{"2":{"498":2}}],["需根据实际游戏在真机验证性能",{"2":{"498":1}}],["需游戏自行排查",{"2":{"471":1}}],["需先构建",{"2":{"391":1}}],["需要更多的精力做优化",{"2":{"1100":1}}],["需要占用更多的编译消耗与内存",{"2":{"1091":1}}],["需要该能力的开发者登录微信公众平台",{"2":{"1088":1}}],["需要乘以",{"2":{"1073":1}}],["需要重启开发者工具",{"2":{"1023":1}}],["需要上线并累计",{"2":{"1011":1}}],["需要上传至开发者的",{"2":{"540":1}}],["需要游戏服务器自行处理",{"2":{"982":1}}],["需要微信基础库版本",{"2":{"978":1}}],["需要将webgl目录下的资源包copy到minigame",{"2":{"962":1}}],["需要将webgl目录下的资源包上传到cdn",{"2":{"962":1}}],["需要将bundle移动到streamingassets目录",{"2":{"439":1}}],["需要同时导出webgl版本的",{"2":{"945":1}}],["需要保证加载速度",{"2":{"944":1}}],["需要保证profile的录制开始之后才真正执行游戏开始逻辑",{"2":{"533":1}}],["需要给wx",{"2":{"922":1}}],["需要给input",{"2":{"555":1}}],["需要替换provider来使用wxassetbundle",{"2":{"922":1}}],["需要注意保证旧版本资源可访问",{"2":{"911":1}}],["需要注意的是",{"2":{"734":1}}],["需要下载",{"2":{"896":1}}],["需要在使用分包插件后",{"2":{"1127":1}}],["需要在网络空闲时预加载的资源",{"2":{"992":1}}],["需要在小游戏的启动前期下载",{"2":{"873":1}}],["需要在touch回调才能被使用",{"2":{"491":1}}],["需要知道留存率",{"2":{"825":1}}],["需要知道完成的留存率",{"2":{"825":1}}],["需要留意",{"2":{"819":1}}],["需要画质和性能之前取一个平衡",{"2":{"817":1}}],["需要用到实时光的",{"2":{"811":1}}],["需要通过",{"2":{"808":1,"889":1}}],["需要开启profiling",{"2":{"1024":1}}],["需要开启高性能模式",{"2":{"370":1}}],["需要开发者采取合适的手段以达到最优",{"2":{"1083":1}}],["需要开发者提供",{"2":{"959":1}}],["需要开发者更关注性能与体验调优",{"2":{"775":1}}],["需要开发者根据自身游戏商业化要求制定",{"2":{"737":1}}],["需要以实测游戏为准",{"2":{"735":1}}],["需要调用",{"2":{"708":1}}],["需要关闭时则调用",{"0":{"702":1}}],["需要对比的变量值或全局变量句柄",{"2":{"686":2}}],["需要两个",{"2":{"678":1}}],["需要暂停的音频的关键动作帧句柄",{"2":{"648":1}}],["需要暂停的视频的关键动作帧句柄",{"2":{"637":1}}],["需要",{"2":{"640":1,"651":1}}],["需要配合",{"2":{"635":1}}],["需要导出剧本给正式的游戏工程使用时",{"2":{"615":1}}],["需要了解一些",{"2":{"608":1}}],["需要查看资源是否正确上传",{"2":{"560":1}}],["需要使用js接口",{"2":{"996":1}}],["需要使用平台提供的",{"2":{"557":1}}],["需要使用wx",{"2":{"555":1}}],["需要快速转化上线",{"2":{"557":1}}],["需要进行相应的适配",{"2":{"539":1}}],["需要进行缓存",{"2":{"472":1}}],["需要释放的空间大小",{"2":{"516":1}}],["需要释放xxmb存储空间",{"2":{"516":1,"526":1}}],["需要缓存的路径",{"2":{"505":1}}],["需要传一下maxlength参数",{"2":{"494":1}}],["需要自行稍做修改",{"2":{"449":1}}],["需要避免这些文件使用缓存",{"2":{"441":1}}],["需要部署到服务器",{"2":{"437":1}}],["需要分别对",{"2":{"429":1}}],["需要先导入本地的",{"2":{"428":1}}],["需要修改的",{"2":{"664":1,"667":1}}],["需要修改文字和进度条样式",{"2":{"421":1}}],["需要修改unity工程中",{"2":{"421":1}}],["需要点击",{"2":{"398":1}}],["需要被覆盖的资源文件",{"2":{"377":1}}],["需升级unity到2021",{"2":{"246":1}}],["需unity2021版本",{"2":{"155":1}}],["需同时升级分包工具插件至1",{"2":{"35":1}}],["es",{"2":{"1076":4}}],["ev",{"2":{"981":1}}],["every",{"2":{"507":1}}],["events",{"2":{"576":1}}],["eventsystems",{"2":{"555":1}}],["eventdata",{"2":{"555":2}}],["event",{"0":{"491":1},"2":{"374":3,"580":1,"602":1,"622":3,"634":2,"646":2,"657":1,"661":1,"673":1,"678":2,"688":2,"692":2}}],["echo",{"2":{"981":1}}],["ease",{"2":{"676":1,"678":2}}],["easing",{"2":{"676":1,"678":2}}],["errcode",{"2":{"1005":1}}],["errmsg",{"2":{"979":1}}],["errstr",{"2":{"825":1}}],["err",{"2":{"576":1,"589":1}}],["errortype取值",{"2":{"825":1}}],["errortype",{"2":{"825":1}}],["error错误日志",{"0":{"567":1},"2":{"564":1}}],["errorcode",{"2":{"374":1}}],["error",{"2":{"367":1,"428":1,"703":1,"760":1,"943":4,"945":2,"977":2,"995":1,"1112":1}}],["error与实时日志",{"2":{"301":1}}],["eg3",{"2":{"510":1}}],["eg2",{"2":{"510":1}}],["eg1",{"2":{"510":1}}],["eg",{"2":{"505":2,"758":3,"759":1,"792":1,"798":1,"824":1,"1106":1,"1113":3}}],["egret",{"2":{"421":2,"423":2}}],["emsdk",{"2":{"479":1}}],["emscripten使用文件系统模拟linux",{"2":{"712":1}}],["emscripten",{"2":{"130":2,"887":1,"902":1}}],["else",{"2":{"414":1,"429":2,"468":1,"591":1,"943":2,"945":1,"973":1,"977":2,"981":1,"995":1}}],["etc均支持",{"2":{"388":1}}],["etc",{"2":{"388":1,"392":1,"410":1}}],["etc2",{"2":{"387":1,"392":2,"405":1,"905":8}}],["example",{"2":{"979":1,"983":1,"993":4,"994":2,"995":1}}],["exact",{"2":{"423":1}}],["exactfit",{"2":{"423":1}}],["exists",{"2":{"942":1}}],["extensions",{"2":{"1097":1}}],["extension",{"2":{"1046":1}}],["extra",{"2":{"873":1}}],["extjsonstr",{"2":{"825":1}}],["exe",{"2":{"805":1,"902":1}}],["execution",{"2":{"531":1}}],["exceedmax",{"2":{"521":1}}],["exceptions",{"0":{"451":1},"2":{"450":2,"451":4}}],["exception",{"0":{"408":1},"1":{"409":1,"410":1},"2":{"383":2,"451":2,"889":2}}],["excludeidentifier",{"2":{"507":2}}],["excludefileidentifier",{"2":{"507":2}}],["excludefileextensions",{"2":{"505":1}}],["ex",{"2":{"451":2}}],["expose",{"2":{"1095":1}}],["export",{"2":{"423":1}}],["exports",{"2":{"374":1}}],["explicitly",{"2":{"450":1,"451":3}}],["e",{"2":{"374":2,"576":1,"703":1,"826":8}}],["edit",{"2":{"429":1,"920":1,"939":1}}],["editor监听固定端口",{"2":{"740":1}}],["editor的无用资源",{"2":{"399":1}}],["editor",{"2":{"352":1,"377":2,"380":1,"383":3,"384":1,"399":1,"406":1,"409":1,"410":5,"428":3,"429":2,"479":1,"505":1,"805":4,"836":1,"897":1,"902":4}}],["editor中的兼容",{"2":{"169":1}}],["edge已经将javascript",{"2":{"351":1}}],["encoding",{"2":{"979":1,"983":1,"1095":3}}],["enclosed",{"2":{"358":2}}],["engine",{"2":{"874":1}}],["engine2d",{"2":{"421":1,"423":1}}],["enum",{"2":{"521":1}}],["enough",{"0":{"481":1}}],["environment",{"2":{"479":1}}],["env",{"2":{"374":3,"513":1,"518":1}}],["enablecontentencoding",{"2":{"798":1}}],["enablemonitor",{"2":{"785":1}}],["enable",{"0":{"451":1},"2":{"450":1,"451":1}}],["enabledebuglog=true",{"2":{"965":1}}],["enabledebuglog=false且为调试模式时输出详细日志",{"2":{"348":1}}],["enabledebug",{"2":{"446":1,"459":1,"965":1}}],["enabled",{"2":{"363":1}}],["enableiosperformanceplus",{"2":{"355":1}}],["enablerenderanalysis",{"2":{"355":1}}],["enableprofilestats或c",{"2":{"968":1}}],["enableprofilestats",{"2":{"355":1}}],["endtime",{"2":{"798":1}}],["endframe",{"2":{"622":2}}],["ending",{"2":{"602":1}}],["endif",{"2":{"409":1,"429":6,"479":1}}],["end",{"0":{"586":1,"601":1},"2":{"130":1,"576":1,"589":1,"591":1,"602":1}}],["qwe25878",{"2":{"977":1}}],["q3",{"2":{"709":1}}],["q2",{"2":{"709":1}}],["q1",{"2":{"709":1}}],["qpic",{"2":{"708":1}}],["query",{"2":{"708":5}}],["quot",{"0":{"460":4,"462":2,"471":2,"479":2},"2":{"16":8,"246":2,"283":4,"302":2,"351":6,"374":4,"424":2,"426":4,"437":2,"446":2,"451":4,"458":2,"459":6,"565":2,"709":1,"717":2,"726":4,"775":2,"805":10,"874":4,"893":2,"902":14,"968":8,"971":2,"981":6,"984":2,"1007":2,"1093":6,"1095":4,"1097":6}}],["q",{"0":{"402":1,"559":1},"1":{"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"560":1},"2":{"466":1,"731":3}}],["qa3",{"2":{"1097":1}}],["qa",{"0":{"367":1,"370":1,"524":1,"731":1,"865":1,"907":1,"1092":1},"1":{"525":1,"526":1,"527":1,"528":1,"529":1,"1093":1,"1094":1,"1095":1,"1096":1,"1097":1,"1098":1,"1099":1,"1100":1,"1101":1},"2":{"500":1,"1082":1}}],["qq",{"2":{"127":1,"353":1,"370":1,"374":1,"377":2,"490":2,"494":1,"499":10,"513":3,"708":1,"843":1,"979":1,"983":1,"985":1}}],[">淡出",{"2":{"678":1}}],[">结束",{"2":{"678":2}}],[">1",{"2":{"678":1}}],[">0",{"2":{"678":1}}],[">",{"2":{"109":3,"678":1}}],["l",{"2":{"973":6}}],["lz4压缩方式",{"2":{"942":1}}],["lh",{"2":{"939":1}}],["lp",{"2":{"499":1}}],["lualib",{"2":{"973":1}}],["lual",{"2":{"973":2}}],["lua会存在大量分配行为",{"2":{"973":1}}],["luam",{"2":{"971":2}}],["luah",{"2":{"971":2}}],["luay",{"2":{"971":2}}],["lua",{"2":{"971":2,"973":8}}],["lua性能",{"0":{"744":1}}],["lua脚本",{"2":{"498":1}}],["lua可使用assetbundle方式整体打包",{"2":{"475":1}}],["lua外部模块",{"2":{"471":1}}],["length",{"2":{"1095":1}}],["learn",{"2":{"949":1}}],["let",{"2":{"576":1}}],["letterlike",{"2":{"358":1}}],["letters",{"2":{"358":1}}],["level0",{"2":{"683":3,"688":5}}],["level",{"0":{"480":1},"2":{"591":4,"874":1}}],["left=calc",{"2":{"629":1}}],["left=50",{"2":{"629":1}}],["left=0",{"2":{"629":2}}],["left",{"2":{"426":1,"614":1,"629":1,"632":1,"634":1,"655":1,"659":1,"661":1,"667":1,"676":1,"678":1,"1005":2,"1073":1}}],["locale=zh",{"2":{"881":1}}],["local",{"2":{"812":2,"1003":1}}],["localhost",{"2":{"805":2,"902":2}}],["loop",{"2":{"632":1,"644":1}}],["longestframe",{"2":{"801":1,"802":1}}],["long",{"0":{"481":1},"2":{"499":2}}],["lod",{"2":{"431":1,"814":1}}],["lodfade",{"2":{"431":1}}],["loadmain",{"2":{"926":1}}],["loadscenemode",{"2":{"926":1}}],["loadsceneasync",{"2":{"926":1}}],["loadsceneasync可以动态加载场景与获取加载进度",{"2":{"926":1}}],["loadsubwasmpackagecosttime",{"2":{"795":1}}],["loadsubwasmpackagestarttime",{"2":{"795":1}}],["loadfrommemory",{"2":{"971":1}}],["loadfromfile",{"2":{"831":1,"945":1}}],["loadfromcacheordownload除了会将文件存入indexdb外",{"2":{"947":1}}],["loadfromcacheordownload",{"2":{"947":2}}],["loadfromcacheordownload或www等带cache接口",{"2":{"943":1}}],["loadfromcacheordownload等cache",{"2":{"712":1}}],["loadfromcachecount",{"2":{"798":1}}],["loadasset通过文件描述符fd去读实际的目标对象",{"2":{"945":1}}],["loadasset",{"2":{"930":1,"943":2}}],["loadassetasync",{"2":{"831":2,"931":1,"932":1,"934":1}}],["loadassetscript",{"2":{"927":3}}],["loadassets",{"2":{"826":2}}],["loadasset同步接口获取脚本",{"2":{"475":1}}],["loadwasm",{"2":{"826":2}}],["loaddatapackagefromsubpackage",{"2":{"826":1,"962":1}}],["loaddurationcallmain=true",{"2":{"796":1}}],["loaddurationcallmain",{"2":{"795":1}}],["loadcount",{"2":{"798":1,"799":1}}],["loadedtasks",{"2":{"798":1}}],["loadedsize",{"2":{"792":1,"793":3,"798":1}}],["loadedsizestr",{"2":{"792":1,"798":1}}],["loadedcount",{"2":{"792":1,"793":1,"798":1}}],["loader会自动按一定规则做文件缓存",{"2":{"964":1}}],["loader默认使用视频+进度信息呈现",{"2":{"957":1}}],["loader默认使用图片+进度信息",{"2":{"418":1}}],["loader功能",{"0":{"953":1},"1":{"954":1,"955":1,"956":1,"957":1,"958":1,"959":1,"960":1,"961":1,"962":1,"963":1,"964":1,"965":1}}],["loader是在微信小游戏环境加载unity",{"2":{"951":1}}],["loader工作流程",{"0":{"864":1}}],["loader进行初始化",{"2":{"863":1}}],["loader版本",{"2":{"827":1}}],["loader自动完成开发者无需关注",{"2":{"825":1}}],["loader自动上报与开发者自定义阶段",{"2":{"827":1}}],["loader自动上报",{"2":{"824":1}}],["loader提供了上报广告参数的能力",{"2":{"823":1}}],["loader插件进行游戏加载",{"2":{"952":1}}],["loader插件",{"0":{"952":1}}],["loader插件自动统计了代码包",{"2":{"822":1}}],["loader插件会构造正常响应返回给游戏",{"2":{"502":1}}],["loader的数据统计功能如下",{"2":{"822":1}}],["loader",{"0":{"951":1},"2":{"528":1,"544":1}}],["load",{"0":{"471":1,"492":1},"2":{"920":1,"926":1,"934":1,"1003":2}}],["loading场景",{"2":{"926":1}}],["loadingcount",{"2":{"792":1,"793":1}}],["loading",{"2":{"759":1,"1106":1,"1120":1,"1126":2}}],["loading模式",{"2":{"581":1}}],["loadingpageconfig",{"2":{"421":1}}],["loadingbarwidth",{"2":{"353":1,"422":1,"900":1,"958":1}}],["logwarning",{"2":{"926":1}}],["logger",{"2":{"576":1}}],["logo出现",{"2":{"446":1,"965":1}}],["logo",{"2":{"421":1,"423":1,"459":1,"1097":1}}],["logerror",{"2":{"414":1,"468":1,"943":2,"945":1}}],["log",{"2":{"374":3,"383":1,"414":1,"451":6,"468":1,"515":3,"533":1,"555":8,"576":2,"584":1,"703":1,"753":2,"825":3,"977":4,"979":5,"983":4,"995":1,"1003":7,"1005":2}}],["login",{"2":{"374":1}}],["lacop",{"2":{"616":2}}],["lac",{"2":{"611":1,"612":1}}],["launchplugin",{"2":{"826":2}}],["launcheventtype",{"2":{"826":8}}],["launchevent",{"2":{"826":2}}],["launch",{"2":{"610":1}}],["launchoperahandler",{"2":{"598":1}}],["launchopera",{"2":{"580":1,"583":1,"584":1,"585":1,"589":1,"591":1,"602":1}}],["launchoperalocaldataxxx",{"2":{"576":2}}],["launchoperainit",{"2":{"576":2,"580":1,"583":1}}],["launchoperaplay",{"2":{"575":1,"576":2,"614":2,"618":2,"657":1,"678":1}}],["layout配置",{"2":{"466":1}}],["layers",{"2":{"431":1}}],["labs",{"2":{"421":1,"423":1}}],["latin",{"2":{"358":1}}],["landscape",{"2":{"353":1}}],["landscaperight",{"2":{"283":1,"353":1}}],["landscapeleft",{"2":{"283":1,"353":1}}],["like",{"2":{"971":27}}],["list",{"2":{"708":2,"991":1,"992":1,"993":1,"994":2,"995":3}}],["listener",{"2":{"109":1,"979":2,"983":2}}],["litjson",{"2":{"979":1,"983":1}}],["lit",{"2":{"432":1}}],["litinput",{"2":{"431":1}}],["lightmap",{"2":{"430":1,"431":3,"811":4}}],["light",{"2":{"430":2,"431":3}}],["lights",{"2":{"430":1}}],["lineartosrgb",{"2":{"431":1}}],["lineartogamma22",{"2":{"431":1}}],["linear模式兼容",{"2":{"119":1}}],["lineheight",{"2":{"421":1,"423":1,"426":1}}],["library包",{"2":{"428":2}}],["library",{"2":{"428":9,"479":1,"493":1}}],["lib",{"2":{"410":1}}],["libgdiplus",{"2":{"408":1,"410":3}}],["lifecyclebase",{"2":{"383":1}}],["lt",{"0":{"520":1,"521":1,"522":1,"602":1,"603":1},"2":{"43":1,"412":1,"415":1,"500":3,"520":1,"521":1,"522":1,"527":1,"632":1,"644":1,"711":4,"724":1,"727":1,"761":3,"793":2,"796":1,"799":3,"827":2,"873":1,"926":2,"982":1,"1107":3,"1122":3,"1123":15,"1124":15}}],["原因",{"2":{"1079":1,"1080":1}}],["原因是收集函数不够完备",{"2":{"461":1}}],["原本使用webrequest的话可按如下修改",{"2":{"945":1}}],["原本是打开一个文件流",{"2":{"945":1}}],["原本的",{"2":{"701":1}}],["原有的代码",{"2":{"576":1}}],["原生app手游之间技术栈导致的性能差异",{"2":{"733":1}}],["原生插件内存",{"2":{"717":1}}],["原生内存",{"2":{"717":1}}],["原生",{"0":{"831":1,"832":1,"833":1},"2":{"546":1,"557":1,"829":1}}],["原来的",{"2":{"429":1}}],["原理也是利用到了js与c",{"2":{"473":1}}],["原理解释",{"0":{"401":1}}],["原理",{"2":{"366":2}}],["原",{"2":{"109":1}}],["可忽略这个错误",{"2":{"1095":1}}],["可右键保存日志文件",{"2":{"1046":1}}],["可联系我们",{"2":{"1046":1}}],["可前往微信开发者工具",{"2":{"1042":1}}],["可提供微信日志给平台侧排查",{"2":{"1003":1}}],["可从本地加载字体",{"2":{"1001":1}}],["可节省启动下载的资源量",{"2":{"1000":1}}],["可节省内存",{"2":{"945":1}}],["可查看插件详细日志",{"2":{"965":1}}],["可查阅官网了解详细信息",{"2":{"905":1,"907":1}}],["可查阅本篇",{"2":{"526":1}}],["可切换版本号",{"2":{"952":1}}],["可看到以下内容",{"2":{"926":1}}],["可更改playersettings面板il2cpp选项为更小尺寸",{"2":{"874":1}}],["可缓存资源小于总请求数的一半",{"2":{"799":1}}],["可缓存文件过少",{"2":{"799":1}}],["可将项目中无用资源清理",{"2":{"882":1}}],["可将catalog",{"2":{"799":1}}],["可将bundle名中hash长度设置为crc长度",{"2":{"523":1}}],["可采用对应的优化手段",{"2":{"790":1}}],["可着重关注网络和卡帧的数据",{"2":{"786":1}}],["可帮助开发者在开发阶段针对问题进行优化",{"2":{"784":1}}],["可见范围以降低渲染物件",{"2":{"751":1}}],["可开启webgl2",{"2":{"751":1}}],["可降低渲染压力可明显降低设备发热量",{"2":{"748":1}}],["可获取函数热点",{"2":{"740":1}}],["可用于超休闲游戏",{"2":{"736":1}}],["可多预留50",{"2":{"727":1}}],["可被使用",{"2":{"717":1}}],["可视",{"2":{"632":1,"655":1,"659":1,"667":1,"676":1}}],["可视化编辑器的包",{"2":{"428":1}}],["可透明",{"2":{"627":1}}],["可控制进度条进度",{"2":{"599":1}}],["可选值参考deviceorientation",{"2":{"893":1}}],["可选值",{"2":{"632":1}}],["可选",{"2":{"585":1,"893":1}}],["可选择将首包资源作为小游戏分包加载",{"2":{"960":1}}],["可选择可交互上报后或在引擎初始化完成",{"2":{"785":1}}],["可选择优化maxsize的方式",{"2":{"362":1}}],["可选择",{"2":{"351":1}}],["可主动提前结束启动剧情",{"2":{"581":1}}],["可适当给出loading动画提醒网络加载",{"2":{"581":1}}],["可体验的webgl",{"2":{"534":1}}],["可认为资源被自动清理",{"2":{"526":1}}],["可能存在资源热更",{"2":{"993":1}}],["可能存在黑边",{"2":{"634":1}}],["可能导致用户流失",{"2":{"913":1}}],["可能涉及资源下载",{"2":{"913":1}}],["可能会支持",{"2":{"814":1}}],["可能会导致一些渲染异常问题",{"2":{"812":1}}],["可能会打断",{"2":{"812":1}}],["可能由于游戏业务初始化逻辑较重",{"2":{"799":1}}],["可能有",{"2":{"812":1}}],["可能有部分内容溢出屏幕",{"2":{"632":1}}],["可能有黑边",{"2":{"632":1}}],["可能有两种情况",{"2":{"526":1}}],["可能都不能满足你的需要",{"2":{"629":1}}],["可能与平时开发小程序",{"2":{"614":1}}],["可能在右上角的三个点展开菜单",{"2":{"531":1}}],["可能是运行期间修改了cdn",{"2":{"527":1}}],["可能预下载列表中配置的资源版本和unitywebrequest请求的版本不一致",{"2":{"526":1}}],["可能和替换",{"2":{"428":1}}],["可修改",{"2":{"507":2,"897":1}}],["可自行替换",{"2":{"959":1}}],["可自动缓存个数",{"2":{"798":1}}],["可自动剔除函数名",{"2":{"448":1}}],["可自定义",{"2":{"374":1}}],["可配合构建模版能力使用",{"2":{"426":1}}],["可参见资源缓存与淘汰",{"2":{"944":1}}],["可参见github文档",{"2":{"127":1}}],["可参阅空间描述约定",{"2":{"632":1,"655":1,"659":1}}],["可参阅相关手册完成上报配置",{"2":{"544":1}}],["可参考unity官方文档说明",{"2":{"1079":1}}],["可参考websocket",{"2":{"981":1}}],["可参考webgl",{"2":{"424":1}}],["可参考启动loader视频规范进行配置",{"2":{"957":1}}],["可参考使用wxassetbundleprovider节省内存",{"2":{"945":1}}],["可参考",{"2":{"807":1,"811":1}}],["可参考手册案例完成适配",{"2":{"539":1}}],["可作为视频加载时的封面",{"2":{"421":1}}],["可根据游戏实际情况进行调整",{"2":{"421":1,"423":1,"959":1}}],["可对该变量进行直接赋值",{"2":{"406":1}}],["可点击还原wasm文件到初始状态",{"2":{"1131":1}}],["可点击",{"2":{"395":1}}],["可结合使用wxassetbundle减少ab体积造成的文件内存",{"2":{"387":1}}],["可使用assetstudio查看文件内的所有资源",{"2":{"873":1}}],["可使用application",{"2":{"747":1}}],["可使用微信开发者工具辅助分析",{"2":{"799":1}}],["可使用小游戏云测获取兼容性报告",{"2":{"737":1}}],["可使用c",{"2":{"472":1}}],["可使用引擎自身的astc压缩格式",{"2":{"387":1}}],["可使用",{"2":{"383":1,"437":1,"744":1}}],["可使用旧版本备份包",{"2":{"108":1}}],["可以明显感受到启动开始阶段",{"2":{"1091":1}}],["可以点右上角退出小游戏触发强制gc来观察",{"2":{"1045":1}}],["可以点击",{"2":{"1026":1}}],["可以继续生成分包",{"2":{"1038":1}}],["可以先继续往下生成分包",{"2":{"1037":1}}],["可以等收集函数超过",{"2":{"1036":1}}],["可以缓解内存问题",{"2":{"1034":1}}],["可以考虑再往下分一次包然后提审发布",{"2":{"1032":1}}],["可以考虑合并成",{"2":{"813":1}}],["可以尽量覆盖各种机型",{"2":{"1027":1}}],["可以看到在几个压测示例中高性能模式均明显优于普通模式",{"2":{"1087":1}}],["可以看到插件的按钮",{"2":{"1020":1}}],["可以看到帧耗时",{"2":{"488":1}}],["可以用wx",{"2":{"1007":1}}],["可以用于生产",{"2":{"919":1}}],["可以用于点击事件透明遮罩",{"2":{"661":1}}],["可以直接看wx",{"2":{"1005":1}}],["可以直接将需要的字符全部填入自定义unicode中",{"2":{"1004":1}}],["可以从",{"2":{"981":1}}],["可以检查data首包以及assetsbundle",{"2":{"880":1}}],["可以适当调小一点渲染分辨率",{"2":{"817":1}}],["可以打个",{"2":{"814":1}}],["可以通过在callmain或者raf之前暂停来观察",{"2":{"1045":1}}],["可以通过分包插件面板的新增收集函数个数来留意线上新增的情况",{"2":{"1032":1}}],["可以通过",{"2":{"812":1}}],["可以通过网络交互",{"2":{"577":1}}],["可以使用增量更新",{"2":{"1024":1}}],["可以使用loader暴露的进度事件上报到自己的系统",{"2":{"826":1}}],["可以使用mesh",{"2":{"814":1}}],["可以使用",{"2":{"808":1}}],["可以在",{"2":{"808":1}}],["可以在资源更新时",{"2":{"510":1}}],["可以参考demo",{"2":{"706":1}}],["可以不依赖任何引擎调用",{"2":{"705":1}}],["可以调用wx",{"2":{"703":1}}],["可以对某",{"2":{"685":1}}],["可以创建多个事件",{"2":{"634":1,"646":1}}],["可以发现发生事件后执行的新的故事线其实可以存在多种表达方式",{"2":{"622":1}}],["可以存在被点击",{"2":{"622":1}}],["可以快速切换提供的多种模板效果拿来使用",{"2":{"616":1}}],["可以让开发者在任意位置访问到控制句柄",{"2":{"583":1}}],["可以按照老用户立即结束剧情即可",{"2":{"577":1}}],["可以按照这个流程采集profile",{"2":{"533":1}}],["可以是游戏厂家logo",{"2":{"577":1}}],["可以借助上面提到的profile工具进行优化",{"2":{"532":1}}],["可以借鉴里面定制的方法或思路",{"2":{"433":1}}],["可以把工程",{"2":{"493":1}}],["可以替代已有unity的playerpref",{"2":{"490":1}}],["可以拿来用",{"2":{"433":1}}],["可以",{"2":{"433":1,"473":1,"475":1}}],["可以切回官方的",{"2":{"433":1}}],["可以手动在",{"2":{"433":1}}],["可以支持镂空",{"2":{"431":1}}],["可以简化",{"2":{"430":4}}],["可以定制本地化",{"2":{"429":1}}],["可以任意的对你的",{"2":{"384":1}}],["可以输入调用云函数代码进行简单测试",{"2":{"374":1}}],["可以根据自身需求选择",{"2":{"372":1}}],["可以尝试优化",{"2":{"814":1}}],["可以尝试使用",{"2":{"812":1}}],["可以尝试这两种方法",{"2":{"493":1}}],["可以尝试把视频播放链接替换我们这个视频链接试试看是否正常",{"2":{"370":1}}],["可以尝试更新最新的插件版本",{"2":{"367":1}}],["可以忽略",{"2":{"367":1}}],["可以避免一些出现的情况",{"2":{"367":1}}],["可通过开发者工具查看对应资源的",{"2":{"1096":1}}],["可通过微信开发者工具查看",{"2":{"1095":1}}],["可通过微信开发者工具控制台",{"2":{"466":1}}],["可通过",{"2":{"998":1}}],["可通过打开调试+http",{"2":{"986":1}}],["可通过csharp接口",{"2":{"996":1}}],["可通过c",{"2":{"956":1}}],["可通过mp后台",{"2":{"914":1}}],["可通过minigame",{"2":{"785":1}}],["可通过minigameconfig",{"2":{"86":1}}],["可通过在命令行执行引擎自带node启动websocketfy",{"2":{"902":1}}],["可通过启动留存上报能力上报统计",{"2":{"759":1,"1106":1}}],["可通过benchmarking",{"2":{"734":1}}],["可通过bundlehashlength修改",{"2":{"510":1}}],["可通过unityprofiler进一步分析问题所在",{"2":{"719":1}}],["可通过请求添加时间戳",{"2":{"525":1}}],["可通过导出选项中bundle名中hash长度来自定义",{"2":{"523":1}}],["可通过defaultreleasesize修改",{"2":{"512":1}}],["可通过textureshashlength配置",{"2":{"511":1}}],["可通过右上角搜索栏检索快速查找对应的纹理资源进行忽略设置",{"2":{"398":1}}],["可通过转换工具配套提供的资源优化工具",{"2":{"359":1}}],["可缺省值",{"2":{"628":1}}],["可缺省创建",{"2":{"377":1}}],["可缺省",{"2":{"353":1,"414":4,"417":1}}],["可在此期间打开调试",{"2":{"351":1}}],["可做缓存",{"2":{"348":1}}],["如按上述文档去除依然无法解决",{"2":{"1098":1}}],["如启动前",{"2":{"1091":1}}],["如遇到问题请联系我们详细排查",{"2":{"1078":1}}],["如安全区域的获取需调用",{"2":{"1073":1}}],["如$stream",{"2":{"997":1}}],["如无ssl证书或正式域名",{"2":{"986":1}}],["如非需要新老unity引擎版本兼容",{"2":{"942":1}}],["如大厅",{"2":{"926":1}}],["如前所述",{"2":{"926":1}}],["如有条件尽可能使用",{"2":{"905":1}}],["如有二次修改请备份",{"2":{"108":1}}],["如2018",{"2":{"905":1}}],["如2019",{"2":{"479":1}}],["如更全的压缩纹理",{"2":{"905":1}}],["如不支持设置webgl分辨率",{"2":{"905":1}}],["如stencil特性支持",{"2":{"1098":1}}],["如splash图片等",{"2":{"873":1}}],["如system",{"2":{"471":1}}],["如arial字体",{"2":{"873":1}}],["如assetbundle",{"2":{"831":2}}],["如astc",{"2":{"386":1,"403":1}}],["如此一来也更方便开发者的代码版本维护",{"2":{"839":1}}],["如此一来你自定义模板也将适应占位符的内容作出最终的结果变更",{"2":{"377":1}}],["如休闲游戏已进入核心玩法",{"2":{"825":1}}],["如进入新手引导或大厅",{"2":{"825":1}}],["如修改端口需重启websocketfy",{"2":{"805":1}}],["如游戏bgm",{"2":{"729":1}}],["如物理",{"2":{"725":1}}],["如在ios系统",{"2":{"725":1}}],["如createbannerad就变为createbannerad",{"2":{"1005":1}}],["如c",{"2":{"717":1}}],["如lua",{"2":{"712":1,"717":2}}],["如litjson解析",{"2":{"97":1}}],["如下是适配刘海屏",{"2":{"1073":1}}],["如下",{"2":{"748":1}}],["如下代码",{"2":{"703":1}}],["如下图",{"2":{"699":1}}],["如下配置",{"2":{"580":1}}],["如名为",{"2":{"611":1}}],["如图所示",{"2":{"579":1,"1020":1}}],["如需手工调整ip",{"2":{"902":1}}],["如需手动删除缓存可在真机中小游戏下拉历史栏将小游戏删除",{"2":{"865":1}}],["如需保持相关的应用配置应始终保留该目录内容",{"2":{"839":1}}],["如需强制设置ios的设备分辨率可以在",{"2":{"748":1,"817":1}}],["如需了解",{"2":{"635":1}}],["如需添加动作帧",{"2":{"624":1}}],["如需关闭",{"2":{"580":1}}],["如需异步请查阅",{"2":{"576":1}}],["如需读取本地缓存请使用",{"2":{"576":1}}],["如需更加复杂的调用",{"2":{"424":1}}],["如开发者希望分享案例",{"2":{"844":1}}],["如开启",{"2":{"580":1}}],["如开篇的流程图所示",{"2":{"509":1}}],["如开源的unitywebsocket插件",{"2":{"498":1}}],["如xlua",{"2":{"498":1}}],["如何判别游戏否已经开启了高性能模式",{"0":{"1093":1},"2":{"1082":1}}],["如何开通",{"0":{"1088":1},"2":{"1082":1}}],["如何查看分包插件日志",{"0":{"1046":1},"2":{"1012":1}}],["如何查看日志",{"0":{"446":1}}],["如何更新分包插件",{"0":{"1042":1},"2":{"1012":1}}],["如何验证",{"0":{"998":1}}],["如何优雅地异步加载",{"0":{"929":1},"1":{"930":1,"931":1,"932":1}}],["如何消除冗余呢",{"2":{"926":1}}],["如何合理与高效地进行资源按需加载是非常重要的事情",{"2":{"828":1}}],["如何上报",{"0":{"824":1}}],["如何使用unity",{"0":{"952":1}}],["如何使用",{"0":{"785":1},"2":{"783":1}}],["如何获取设备硬件信息",{"0":{"753":1}}],["如何解决ios高性能模式出现内存过大导致游戏关闭",{"2":{"731":1}}],["如何设置",{"2":{"727":1}}],["如何检查",{"2":{"526":1,"527":1}}],["如何切换备用cdn地址",{"0":{"528":1},"2":{"500":1}}],["如何接入第三方的js",{"0":{"473":1}}],["如何自定义接入构建流程",{"0":{"468":1}}],["如何在真机上进行调试和错误日志排查",{"0":{"459":1}}],["如何在真机上预览游戏",{"0":{"458":1}}],["如何通过错误堆栈查找源代码问题",{"0":{"447":1},"1":{"448":1,"449":1}}],["如何排查程序中出现的异常",{"0":{"445":1},"1":{"446":1,"447":1,"448":1,"449":1}}],["如何找到对应堆栈并解决问题",{"2":{"444":1}}],["如no",{"2":{"441":1}}],["如mmo",{"2":{"387":1}}],["如测试环境",{"2":{"374":1}}],["如没有用到",{"2":{"374":1}}],["如果同时使用代码分包插件",{"2":{"1127":1}}],["如果同时播放的音频数量过多",{"2":{"367":1}}],["如果不做任何优化的情况下",{"2":{"1100":1}}],["如果不需要建议在",{"2":{"812":1}}],["如果未使用代码分包的情况下",{"2":{"1099":1}}],["如果未进行优化前",{"2":{"1091":1}}],["如果出现资源访问失败",{"2":{"1097":1}}],["如果出现卡顿",{"2":{"1037":1}}],["如果出现红框中的提示",{"2":{"1023":1}}],["如果能看到有新增函数个数的变化",{"2":{"1037":1}}],["如果能用半精度",{"2":{"812":1}}],["如果线上新增较多",{"2":{"1032":1}}],["如果上线后",{"2":{"1029":1}}],["如果想回退到未分包的版本",{"2":{"1028":1}}],["如果这个游戏之前的包已经有用过代码分包",{"2":{"1024":1}}],["如果这里给出的参考版本满足开发者需要",{"2":{"433":1}}],["如果等待超过10分钟",{"2":{"1023":1}}],["如果用的是stable版",{"2":{"1018":1}}],["如果用了",{"2":{"812":1}}],["如果预下载完成unityloader会立即构造网络数据返回",{"2":{"999":1}}],["如果服务端使用",{"2":{"982":1}}],["如果我们希望把someprefab以及它的依赖资源打包在addressable分组进行按需下载应该如何做呢",{"2":{"927":1}}],["如果我们仅将场景作为分组",{"2":{"926":1}}],["如果我们需要尽量少的工作量去做到像h5游戏按需加载",{"2":{"921":1}}],["如果希望用户始终打开最新版本",{"2":{"914":1}}],["如果某个用户本地有小程序的历史版本",{"2":{"911":1}}],["如果发现无法正常的情况请尝试更换小版本",{"2":{"902":1}}],["如果发现部分代码被错误裁剪",{"2":{"480":1}}],["如果无法连接请查看微信开发者工具network页签对应的ws链接是否正常可达",{"2":{"902":1}}],["如果无法连接请关注vconsole输出的ip",{"2":{"805":1}}],["如果配置了加载阶段视频url",{"2":{"893":1}}],["如果当前版本暂不支持",{"2":{"838":1}}],["如果dpr",{"2":{"817":1}}],["如果手机发烫比较严重",{"2":{"817":1}}],["如果只用一个",{"2":{"816":1}}],["如果只是单纯使用全屏的视频播放",{"2":{"370":1}}],["如果渲染状态比较多",{"2":{"815":1}}],["如果渲染差异比较大",{"2":{"433":1}}],["如果使用unity2021以上版本",{"2":{"874":1}}],["如果使用",{"2":{"815":2}}],["如果使用的功能是定制",{"2":{"433":1}}],["如果顶点过多或骨骼数过多",{"2":{"814":1}}],["如果有正确压缩",{"2":{"1095":1}}],["如果有最后两点",{"2":{"1029":1}}],["如果有顶点蒙皮",{"2":{"814":1}}],["如果有用不到的关键字要记得删除掉",{"2":{"812":1}}],["如果有用到纹理压缩",{"2":{"438":1}}],["如果启用",{"2":{"813":1}}],["如果实在代替不了",{"2":{"812":1}}],["如果地表是平的",{"2":{"811":1}}],["如果没有光照和阴影的需要",{"2":{"811":1}}],["如果游戏不能升级版本",{"2":{"1074":1}}],["如果游戏使用",{"2":{"978":1}}],["如果游戏场景比较复杂",{"2":{"814":1}}],["如果游戏需要依赖",{"2":{"807":1}}],["如果游戏内容不多",{"2":{"807":1}}],["如果游戏勾选profiling",{"2":{"351":1}}],["如果需要光照和阴影的",{"2":{"811":1}}],["如果需要手工调整端口可通过修改以下代码",{"2":{"805":1}}],["如果需要在",{"2":{"703":1}}],["如果以上步骤完成还有问题",{"2":{"731":1}}],["如果开发者有简单的",{"2":{"1010":1}}],["如果开发者遇到内存问题时请逐个排查优化",{"2":{"724":1}}],["如果开发者工具控制台没有添加插件的入口请手动在mp端添加插件或者升级至最新版本的开发者工具",{"2":{"466":1}}],["如果开放数据域在监听到",{"2":{"709":1}}],["如果排行榜被绘制在屏幕中央且物理尺寸为",{"2":{"707":1}}],["如果父元素占满整个窗口的话",{"2":{"707":1}}],["如果仅仅在",{"2":{"702":1}}],["如果",{"2":{"632":1,"644":1,"814":1}}],["如果模板还不能满足你的需要",{"2":{"617":1}}],["如果appid是首次打开后会要求添加用于调试的小游戏插件",{"2":{"613":1}}],["如果你希望将导出插件集成到自己的发布流程",{"2":{"897":1}}],["如果你使用例如",{"2":{"618":1}}],["如果你想快速应用场景",{"2":{"616":1}}],["如果你的",{"2":{"614":1}}],["如果你还没接触",{"2":{"609":1}}],["如果你覆盖过",{"2":{"378":1}}],["如果在开发者注册时剧情已经结束",{"2":{"602":1}}],["如果遇到问题可以随时反馈给我们",{"2":{"561":1}}],["如果playerloadfirstscene耗时占比过高",{"2":{"533":1}}],["如果callmain耗时过大",{"2":{"532":1}}],["如果默认没有",{"2":{"531":1}}],["如果非致命异常",{"2":{"451":1}}],["如果wasm代码+首包资源小于20mb",{"2":{"437":1}}],["如果是选择",{"2":{"809":1}}],["如果是新开发的游戏",{"2":{"808":1}}],["如果是scale",{"2":{"707":1}}],["如果是玩家存档",{"2":{"472":1}}],["如果是资源",{"2":{"472":1}}],["如果是用的aa",{"2":{"439":1}}],["如果是",{"2":{"433":1,"809":1,"814":1,"985":1}}],["如果后面版本有相关的接口",{"2":{"429":1}}],["如果此时",{"2":{"428":1}}],["如果按文本传输也会出现加载回来的图片成黑色",{"2":{"404":1}}],["如未使用微信压缩纹理工具可以不予设置",{"2":{"356":1}}],["如希望能从游戏启动立即抓取profile",{"2":{"351":1}}],["如",{"2":{"109":1,"388":1,"396":1,"582":1,"587":1,"614":1,"628":2,"659":1,"676":1,"841":1,"997":1,"1005":1}}],["如心跳",{"2":{"70":1}}],["xhr",{"2":{"998":2,"1003":1}}],["x已提供webgl平台导出模式",{"2":{"905":1}}],["xcode抓帧工具",{"2":{"814":1}}],["xcode",{"0":{"715":1},"2":{"713":1,"731":1}}],["xsamx",{"2":{"1090":1}}],["xs",{"2":{"707":1}}],["xx使用预载内容",{"2":{"998":1}}],["xx",{"2":{"516":4,"526":4,"634":1,"646":1,"998":1}}],["xxxx",{"2":{"441":2,"634":1,"646":1,"1005":2}}],["xxx",{"2":{"71":1,"396":1,"449":1,"493":2,"516":1,"555":1,"724":1,"791":2,"971":4,"1003":7}}],["xlua",{"2":{"481":1}}],["xr",{"2":{"427":1,"430":2,"431":1}}],["x",{"2":{"388":1,"432":2,"701":4,"707":6,"709":2,"968":1,"1073":1,"1105":1,"1120":1}}],["x3c",{"2":{"383":2,"521":8,"555":1,"707":1,"708":1,"825":2,"930":3,"931":2,"932":2,"934":2,"979":3,"983":3,"995":2}}],["x26",{"2":{"374":4,"429":2,"507":2,"708":4,"973":1}}],["xml",{"2":{"97":1}}],["微信提供的",{"2":{"1097":1}}],["微信客户端满足以下版本要求时",{"2":{"1001":1}}],["微信客服两种方式",{"2":{"561":1}}],["微信系统字体",{"0":{"1000":1},"1":{"1001":1,"1002":1,"1003":1,"1004":1}}],["微信系统字体预载bug修复",{"2":{"95":1}}],["微信基础库支持udpsocket类",{"2":{"983":1}}],["微信底层接口支持",{"2":{"885":1}}],["微信用户存在不少",{"2":{"873":1}}],["微信广告可指定网络条件",{"2":{"873":1}}],["微信公众平台",{"2":{"552":1}}],["微信平台能力接入",{"0":{"542":1},"1":{"543":1,"544":1},"2":{"534":1}}],["微信接口提示",{"0":{"491":1}}],["微信sdk内容将不再存放在游戏工程的assets目录中",{"2":{"839":1}}],["微信sdk安装",{"0":{"834":1},"1":{"835":1,"836":1,"837":1,"838":1,"839":1,"840":1,"841":1}}],["微信sdk工具支持开发者自行实现构建",{"2":{"468":1}}],["微信sdk提供了wx",{"2":{"424":1}}],["微信定制的",{"2":{"433":2}}],["微信纹理压缩工具在资源处理的过程中识别了资源能否正确的被压缩处理",{"2":{"405":1}}],["微信unity",{"2":{"394":1}}],["微信unitysdk压缩纹理工具",{"2":{"387":1}}],["微信开发者工具会自动更新分包插件",{"2":{"1042":1}}],["微信开发者工具小游戏profile",{"2":{"805":1,"902":1}}],["微信开发者工具",{"0":{"721":1,"804":1},"2":{"608":1,"609":1,"613":1,"614":2,"783":1,"896":1,"968":1,"984":2,"985":1,"1046":1}}],["微信开发者工具域名列表",{"0":{"499":1}}],["微信开发者工具域名被屏蔽",{"2":{"465":1}}],["微信开发者工具服务异常",{"0":{"465":1}}],["微信开发者工具能正常打开游戏",{"0":{"463":1}}],["微信开发者工具提示",{"0":{"462":1}}],["微信开发者工具打开时提示",{"0":{"456":1,"457":1}}],["微信开发者工具将软解为rgab32",{"2":{"387":1}}],["微信开发者工具支持提示插件审核指引",{"2":{"175":1}}],["微信",{"0":{"432":1},"2":{"386":1,"389":1,"429":1,"523":1,"537":1,"543":1}}],["微信小游戏平台能力以c",{"2":{"1134":1}}],["微信小游戏平台对上线无严格的性能要求",{"2":{"737":1}}],["微信小游戏unity",{"0":{"1133":1},"1":{"1134":1,"1135":1,"1136":1}}],["微信小游戏的网络需要提前在mp后台配置安全域名",{"2":{"984":1}}],["微信小游戏具有",{"2":{"868":1}}],["微信小游戏技术沙龙分享材料2023",{"0":{"843":1}}],["微信小游戏团队将sdk分为如下两种模式安装使用",{"2":{"834":1}}],["微信小游戏环境中不支持对本地的",{"2":{"828":1}}],["微信小游戏将自动连接到unity",{"2":{"805":1,"902":1}}],["微信小游戏性能诊断工具用于查看",{"2":{"771":1}}],["微信小游戏请使用",{"2":{"739":1}}],["微信小游戏启动剧情对可能影响用户体验的弱网情况做了相应的回调事件",{"2":{"581":1}}],["微信小游戏希望能够提供一些更早的交互行为来提升这段等待空窗期的用户访问体验",{"2":{"568":1}}],["微信小游戏框架会在顶层监控到任何未捕捉的js异常",{"2":{"567":1}}],["微信小游戏支持如下自定义配置项",{"2":{"551":1}}],["微信小游戏支持通过配置封面图",{"2":{"551":1}}],["微信小游戏在安卓平台提供了cpu",{"2":{"531":1}}],["微信小游戏专用宏",{"2":{"429":1}}],["微信小游戏转换工具面板",{"2":{"399":1}}],["微信小游戏压缩纹理工具",{"2":{"387":1,"388":1}}],["微信小游戏压缩纹理工具2",{"0":{"385":1},"1":{"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1}}],["微信小游戏对后端服务无任何限制",{"2":{"372":1}}],["微信小游戏",{"2":{"360":1,"395":1,"808":1,"893":1,"944":1}}],["微信小游戏appid",{"2":{"353":1}}],["微信版本或基础库版本过低时wxwebassembly未定义",{"2":{"339":1}}],["微信压缩纹理转换完成",{"2":{"414":1}}],["微信压缩纹理api介绍",{"0":{"411":1},"1":{"412":1,"413":1,"414":1,"415":1,"416":1,"417":1}}],["微信压缩纹理使用说明",{"2":{"400":1}}],["微信压缩纹理",{"2":{"398":1}}],["微信压缩纹理优化",{"2":{"145":1}}],["微信压缩纹理对",{"2":{"140":1}}],["微信压缩纹理支持webgl2",{"2":{"140":1}}],["微信压缩纹理增加支持astc6",{"2":{"135":1}}],["微信压缩纹理新增api可供开发者调用接入自定义自动转化能力",{"2":{"119":1}}],["微信压缩纹理工具提供了相应的",{"2":{"411":1}}],["微信压缩纹理工具将对同一个纹理资源生成多种不同格式的压缩纹理",{"2":{"386":1}}],["微信压缩纹理工具处理的纹理cdn拼接路径",{"2":{"353":1}}],["微信压缩纹理工具处理的尾部hash长度",{"2":{"353":1}}],["微信压缩纹理工具支持bundle级别修改压缩纹理等级",{"2":{"164":1}}],["微信压缩纹理工具支持astc文件读取",{"2":{"155":1}}],["微信压缩纹理工具对webgl2",{"2":{"119":1}}],["微信压缩纹理工具内核优化",{"2":{"119":1}}],["微信压缩纹理工具优化增量逻辑",{"2":{"117":1}}],["微信压缩纹理工具修复自定义路径导出",{"2":{"117":1}}],["微信压缩纹理工具unity全版本支持",{"2":{"64":1}}],["请耐心等待",{"2":{"1132":1}}],["请升级微信开发者工具版本",{"2":{"1130":1}}],["请提供可复现",{"2":{"1098":1}}],["请提供详细数据联系平台侧进一步分析",{"2":{"731":1}}],["请不要服务端设置",{"2":{"1094":1}}],["请不要使用真机调试",{"2":{"896":3}}],["请前往",{"2":{"1042":1}}],["请前往mp后台",{"2":{"464":1,"896":1}}],["请优先查阅用法",{"2":{"1009":1}}],["请按需更改地址和端口",{"2":{"983":1}}],["请按需更改地址与端口",{"2":{"979":1}}],["请按需使用",{"2":{"979":1,"983":1}}],["请查看资源部署",{"2":{"915":1}}],["请查阅文档优化unity",{"2":{"1098":1}}],["请查阅小游戏资源缓存",{"2":{"942":1}}],["请查阅技术常见问题qa",{"2":{"901":1}}],["请查阅推荐引擎版本",{"2":{"834":1,"1136":1}}],["请查阅webgl2",{"2":{"750":1}}],["请查阅",{"2":{"620":1}}],["请查阅高性能+模式",{"2":{"31":1}}],["请查阅模板文档",{"2":{"16":1}}],["请务必使用压缩纹理优化进行优化",{"2":{"905":1}}],["请务必确保使用压缩纹理工具时",{"2":{"389":1}}],["请继续阅读",{"2":{"878":1}}],["请联系联系我们删除",{"2":{"844":1}}],["请",{"2":{"838":1}}],["请用安卓cpuprofile分析热点函数",{"2":{"790":1}}],["请看前文关于unityheap预留内存的说明",{"2":{"731":1}}],["请检查指定参考的旧版本以及当前版本是否都有",{"2":{"1041":1}}],["请检查ssl证书请确认是否过期",{"2":{"986":1}}],["请检查unityprofiler是否已启动监听",{"2":{"902":1}}],["请检查预下载资源是否过大",{"2":{"793":1}}],["请检查",{"2":{"731":1}}],["请检查data",{"2":{"527":1}}],["请移步特定章节阅读",{"2":{"635":1}}],["请仔细阅读本节",{"2":{"617":1}}],["请回到",{"2":{"615":1}}],["请修改脚本中大约第",{"2":{"614":1}}],["请切换成当前登录用户有开发权限的小游戏appid",{"2":{"613":1}}],["请跟随本教程直至你能在",{"2":{"609":1}}],["请在",{"2":{"582":1}}],["请在game",{"2":{"351":1}}],["请开发者对弱网的反馈同样做出合理的处理提升用户体验",{"2":{"581":1}}],["请求请设置到",{"2":{"985":2}}],["请求到服务器的示例",{"2":{"977":1}}],["请求耗时",{"2":{"798":1}}],["请求介绍时间",{"2":{"798":1}}],["请求开始时间",{"2":{"798":1}}],["请求url",{"2":{"798":1}}],["请求详细信息如下",{"2":{"798":1}}],["请求回包总大小",{"2":{"798":1}}],["请求回包总大小的字符串表示",{"2":{"798":1}}],["请求量",{"2":{"797":1}}],["请求量达到一定上限后需要配额调整或申请代金券后更换配额套餐",{"2":{"374":1}}],["请求使用",{"2":{"539":1}}],["请求同名资源的不同版本",{"2":{"526":1}}],["请确认游戏是否依赖webgl2",{"2":{"477":1}}],["请尽量使用2~3mb以内的精简字体以免影响游戏启动速度",{"2":{"474":1,"873":1}}],["请点三次下方的",{"2":{"459":1}}],["请使用disablewritetypetree提升加载速度与降低内存",{"2":{"942":1}}],["请使用如下参数",{"2":{"942":1}}],["请使用android",{"2":{"875":1}}],["请使用分包工具继续收集",{"2":{"796":3}}],["请使用perfdog或mac",{"2":{"731":1}}],["请使用微信开发者工具",{"2":{"458":1}}],["请使用新版unity导出插件重新导出项目",{"2":{"92":1}}],["请注册小程序appid",{"2":{"456":1}}],["请注意数据的",{"2":{"982":1}}],["请注意做好文件备份",{"2":{"704":1}}],["请注意要按二进制传输",{"2":{"404":1}}],["请注意当开发者手动配置时需要自行判断资源是否是游戏中的必要资源",{"2":{"399":1}}],["请注意",{"2":{"394":1,"441":1,"827":1}}],["请自行查询对应cdn服务商文档进行设置",{"2":{"441":1}}],["请将优先需要的资源放到列表前面",{"2":{"999":1}}],["请将大资源调整到预下载列表顶部",{"2":{"793":1}}],["请将先将",{"2":{"699":1}}],["请将wxtouchinputoverride",{"2":{"476":1}}],["请将首资源包放cdn或http服务器",{"2":{"462":1}}],["请将",{"2":{"406":1}}],["请勿同时勾选",{"2":{"968":1}}],["请勿请求catalog",{"2":{"799":1}}],["请勿缓存settings",{"2":{"799":1}}],["请勿修改名称",{"2":{"618":2}}],["请勿修改playersettings的压缩选项",{"2":{"460":1}}],["请勿设置超过200mb的值",{"2":{"512":1}}],["请勿删除旧版本资源",{"2":{"441":1}}],["请勿使用小游戏版微信开发者工具",{"2":{"1042":1}}],["请勿使用小游戏版",{"2":{"834":1,"1136":1}}],["请勿使用首资源包",{"2":{"712":1}}],["请勿使用异步方式",{"2":{"576":1}}],["请勿使用异步函数",{"2":{"576":1}}],["请勿使用",{"2":{"392":1}}],["请勿使用development",{"2":{"351":1}}],["请勿开启",{"2":{"391":1}}],["请创建脚本在",{"2":{"383":1}}],["请创建该文件并编写钩子逻辑",{"2":{"383":1}}],["请参照demo示例",{"2":{"475":1}}],["请参考本文前面部分",{"2":{"1099":1}}],["请参考资源缓存",{"2":{"831":1}}],["请参考小游戏输入法api进行适配",{"2":{"483":1}}],["请参考小游戏开发者文档",{"2":{"456":1}}],["请参考小游戏开发者文档以及示例video",{"2":{"370":1}}],["请参考https",{"2":{"481":1,"490":2}}],["请参考托管代码剥离",{"2":{"480":1}}],["请参考我们提供的c",{"2":{"473":1}}],["请参考文档优化物理性能",{"2":{"745":1}}],["请参考文档ios高性能模式概述部分",{"2":{"485":1}}],["请参考文档ios高性能模式qa部分",{"2":{"484":1}}],["请参考文档资源部署与缓存",{"2":{"472":1}}],["请参考文档网络通信适配关于跨域的问题",{"2":{"1094":1,"1096":1}}],["请参考文档网络通信适配",{"2":{"463":1,"470":1}}],["请参考配置说明",{"2":{"392":1}}],["请参阅",{"2":{"581":1}}],["请参阅最佳实践检测工具",{"2":{"108":1}}],["请参阅文档使用assetbundle其中wxassetbundle部分",{"2":{"108":1}}],["请阅读文档",{"2":{"909":1}}],["请阅读上报说明填写",{"2":{"691":2}}],["请阅读相关手册完成相应的部署",{"2":{"540":1}}],["请阅读资源缓存",{"2":{"443":1}}],["请阅读",{"2":{"358":1,"377":1}}],["当批次较大时出现显示错误",{"2":{"1080":1}}],["当uniform变量过多时",{"2":{"1079":1}}],["当unityheap",{"2":{"727":1}}],["当出现问题时",{"2":{"1046":1}}],["当出现以下日志",{"2":{"526":1}}],["当插件页显示的收集到增量函数个数相对稳定时",{"2":{"1026":1}}],["当符合缓存规则时",{"2":{"1001":1}}],["当预下载完成时间超过",{"2":{"998":1}}],["当存在",{"2":{"998":3}}],["当进行了lua内存分配器替换操作后",{"2":{"967":1}}],["当首包资源通过小游戏代码分包下载时",{"2":{"960":1}}],["当wasm代码+首包资源",{"2":{"960":1}}],["当ab",{"2":{"948":1}}],["当app同步方式使用ab时",{"2":{"831":1}}],["当app异步方式使用ab时",{"2":{"831":1}}],["当app手游使用了这些特性时",{"2":{"734":1}}],["当http对象dispose之后",{"2":{"948":1}}],["当bundle从资源服务器下载并使用",{"2":{"948":1}}],["当bundle数量多时",{"2":{"947":1}}],["当编译addressable资源时会输出到library",{"2":{"937":1}}],["当打开addressables",{"2":{"935":1}}],["当我们adressable面板的tools",{"2":{"926":1}}],["当新版本可用后",{"2":{"913":1}}],["当小游戏无法连接unityprofile时",{"2":{"902":1}}],["当分析出小游戏需要进行启动优化时",{"2":{"878":1}}],["当业务侧需要使用loader启动数据时",{"2":{"826":1}}],["当inspector窗口的材质缺失",{"2":{"812":1}}],["当提示优化建议时",{"2":{"790":1}}],["当场景渲染物件过多时应该采取适当的措施减少drawcall",{"2":{"751":1}}],["当帧率为15",{"2":{"747":1}}],["当发现unityheap",{"2":{"719":1}}],["当发生某种事件自然也就可以触发新的故事线内容",{"2":{"622":1}}],["当发生1",{"2":{"591":1}}],["当",{"2":{"687":2}}],["当变量被赋值且值发生变化时触发的事件",{"2":{"682":1}}],["当变量被赋值时触发的事件",{"2":{"682":1}}],["当动画结束后",{"2":{"677":1}}],["当动画函数被作用的关键动作帧句柄不可视状态时",{"2":{"675":1}}],["当主动取消时",{"2":{"672":1}}],["当延迟结束后",{"2":{"672":1}}],["当贴图被点击",{"2":{"656":1,"660":1}}],["当播放到第sec秒数时",{"2":{"633":1,"645":1}}],["当你需要将打包的资源从本地移到服务器上面",{"2":{"919":1}}],["当你第一次创建故事线时",{"2":{"625":1}}],["当你对剧情设计完成",{"2":{"615":1}}],["当执行到该帧后",{"2":{"622":1}}],["当开启自定义外显进度条时",{"2":{"599":1}}],["当启动剧情全局变量变化时回调",{"2":{"595":1}}],["当产生该回调时意味着启动剧情组件资源已经完全析构",{"2":{"587":1}}],["当剧情启动并给到充分的",{"2":{"582":1}}],["当5秒内明确了后续播与不播放的选择时",{"2":{"577":1}}],["当确认后",{"2":{"577":1}}],["当触发异常时将走到js",{"2":{"567":1}}],["当玩家游戏中出现问题时",{"2":{"565":1}}],["当游戏资源量比较少时",{"2":{"960":1}}],["当游戏完成所有加载阶段",{"2":{"825":1}}],["当游戏发布到现网时",{"2":{"564":1}}],["当游戏出现异常时可通过日志进行错误堆栈分析",{"2":{"541":1}}],["当游戏代码包下载编译完成和首包资源下载完成后会运行游戏逻辑",{"2":{"532":1}}],["当点击stop",{"2":{"531":1}}],["当资源下载url中不包含data",{"2":{"523":1}}],["当文件没有正常缓存时",{"2":{"523":1}}],["当前使用内存",{"2":{"970":1}}],["当前存活的分配次数",{"2":{"970":1}}],["当前是否处于前台",{"2":{"826":1}}],["当前游戏运行时长",{"2":{"801":1}}],["当前游戏的运行时长",{"2":{"759":1,"1106":1}}],["当前期出现子包加载",{"2":{"796":1}}],["当前标准",{"2":{"773":1}}],["当前的内存使用量",{"2":{"717":2}}],["当前帧",{"2":{"717":1}}],["当前缓存目录总文件数和总文件大小",{"2":{"516":1}}],["当前项目安装的",{"2":{"428":1}}],["当前项目模板过旧",{"2":{"92":1}}],["当已有缓存+待写入缓存超过允许的上限时",{"2":{"513":1}}],["当以其他符号分割时",{"2":{"513":1}}],["当需要自动缓存的文件在写入本地之前",{"2":{"509":1}}],["当需要使用时不增加请求头重新请求即可从用户目录读取缓存使用",{"2":{"16":1}}],["当路径中包含字符时不需要缓存",{"2":{"505":1}}],["当有两个wasm文件时",{"2":{"1131":1}}],["当有缓存时",{"2":{"502":1}}],["当有视频时",{"2":{"421":1}}],["当使用以下api发起网络请求时会检查是否需要缓存",{"2":{"502":1}}],["当不使用小游戏分包时",{"2":{"437":1}}],["当导出时wasm代码brotli压缩正常的前提下",{"2":{"437":1}}],["当导入完成后",{"2":{"428":1}}],["当downloadingtext有多个文案时",{"2":{"421":1,"423":1,"959":1}}],["当然能尽量再收集完善刚好",{"2":{"1032":1}}],["当然",{"2":{"808":1}}],["当然我们也提供了部分",{"2":{"582":1}}],["当然使用后面小节提及的钩子能力可以很万能的做出内容修改",{"2":{"380":1}}],["当然也可以在同一个项目中",{"2":{"374":1}}],["当冲突的自定义模板文件较冲突前发生变化后提醒也将自动消除",{"2":{"379":1}}],["当禁用异常时",{"2":{"301":1}}],["当音频路径加入到缓存目录时",{"2":{"158":1}}],["默认object缩放为均匀缩放",{"2":{"1079":1}}],["默认并发10个预下载",{"2":{"996":1}}],["默认检验安全域名",{"2":{"985":1}}],["默认检测条件如上",{"2":{"785":1}}],["默认会检查安全域名",{"2":{"984":1}}],["默认会缓存纹理",{"2":{"508":1}}],["默认首包资源放在cdn一级目录",{"2":{"955":1}}],["默认方式",{"0":{"911":1}}],["默认mesh",{"2":{"873":1}}],["默认loader再次启动时资源",{"2":{"865":1}}],["默认的背景图",{"2":{"959":1}}],["默认的材质一般会有些冗余的设置",{"2":{"812":1}}],["默认的剧情将固定播放一段大约3~5秒钟的启动动画",{"2":{"577":1}}],["默认选项",{"2":{"808":1}}],["默认不检验安全域名",{"2":{"984":1,"985":1}}],["默认不需要",{"2":{"829":1}}],["默认不控制将以动画自动补间",{"2":{"580":1}}],["默认不传timeout",{"2":{"254":1}}],["默认额外清理的大小",{"2":{"513":1}}],["默认hash长度为8",{"2":{"511":1}}],["默认hash长度为32",{"2":{"510":1}}],["默认为0",{"2":{"824":1}}],["默认为1",{"2":{"644":1}}],["默认为assets",{"2":{"508":1}}],["默认为il2cppcodegeneration",{"2":{"84":1}}],["默认包含",{"2":{"507":1}}],["默认url中包含streamingassets的请求会被识别为资源文件被自动缓存",{"2":{"507":1}}],["默认值",{"2":{"996":1}}],["默认值是json",{"2":{"523":1}}],["默认值200mb",{"2":{"505":1}}],["默认值30mb",{"2":{"353":1,"505":1}}],["默认值32",{"2":{"353":1}}],["默认导出未webgl1",{"2":{"477":1}}],["默认情况下5秒未使用的bundle会被从内存中清理",{"2":{"945":1}}],["默认情况下位于小游戏底部区域",{"2":{"579":1}}],["默认情况下",{"2":{"446":1,"565":2,"937":1}}],["默认情况下配置页面中将扫描当前项目所有可被处理的ab包资源",{"2":{"398":1}}],["默认是3",{"2":{"817":1}}],["默认是开启",{"2":{"815":1}}],["默认是",{"2":{"431":1}}],["默认使用",{"2":{"431":1}}],["默认用渲染图形",{"2":{"429":1}}],["默认效果",{"0":{"422":1}}],["默认设计尺寸为667",{"2":{"421":1}}],["默认总启动耗时",{"2":{"421":1,"423":1,"959":1}}],["默认遵循增量逻辑",{"2":{"414":1}}],["默认全量生成",{"2":{"414":1}}],["默认打包的资源",{"2":{"399":1}}],["默认采用增量逻辑不会额外增加处理时间",{"2":{"395":1}}],["默认",{"2":{"384":1}}],["默认推荐使用",{"2":{"393":1}}],["默认推荐",{"2":{"355":1}}],["默认240",{"2":{"353":1,"959":1}}],["默认开启分享",{"2":{"342":1}}],["默认32位长度",{"2":{"523":1}}],["默认32",{"2":{"290":1}}],["默认超时为1000ms",{"2":{"254":1}}],["默认关闭纹理缓存",{"2":{"215":1}}],["默认10s",{"2":{"86":1}}],["默认进度动画加速",{"2":{"16":1}}],["修改并发数",{"2":{"996":1}}],["修改引擎初始化后的预下载并发数",{"2":{"996":1}}],["修改为实际api地址",{"2":{"994":2}}],["修改为最新版本",{"2":{"914":1}}],["修改data",{"2":{"956":1}}],["修改provider",{"2":{"945":1}}],["修改分辨率",{"2":{"907":1}}],["修改前",{"2":{"614":1}}],["修改剧本不同的是",{"2":{"614":1}}],["修改maxstorage超过200mb会导致出现写缓存失败",{"2":{"523":1}}],["修改此值需要联系研发助手开通权限",{"2":{"513":1,"899":1}}],["修改needcachetextures可控制是否缓存纹理资源",{"2":{"508":1}}],["修改设计宽高和缩放模式后",{"2":{"421":1}}],["修改了自定义模板中的资源",{"2":{"383":1}}],["修改",{"2":{"374":2,"431":1,"994":2,"995":1,"1010":1}}],["修改后",{"2":{"351":1,"614":1}}],["修改文件删除接口使用方法cleanfilecache",{"2":{"230":1}}],["修正url中非法路径",{"2":{"223":1}}],["修正调用参数类名的大小写",{"2":{"109":1}}],["修正网络个数和http2",{"2":{"76":1}}],["修复回退为旧分包方案的bug",{"2":{"1053":1}}],["修复安卓分片读取包内资源内存越界",{"2":{"350":1}}],["修复了一些bug",{"2":{"334":1,"337":1}}],["修复初始上报时机",{"2":{"330":1}}],["修复首包资源下载异常",{"2":{"319":1}}],["修复若干问题",{"2":{"317":1}}],["修复资源预载bug",{"2":{"313":1}}],["修复资源量较大时",{"2":{"171":1}}],["修复排行榜内存增长问题",{"2":{"305":1}}],["修复独立域插件未编译子包bug",{"2":{"278":1}}],["修复引擎初始化失败后依然回调calledmaincb导致统计问题",{"2":{"272":1}}],["修复部分api问题",{"2":{"256":1}}],["修复部分首资源包压缩异常问题",{"2":{"52":1}}],["修复login方法",{"2":{"254":1}}],["修复21",{"2":{"216":1}}],["修复2022导出video的bug",{"2":{"48":1}}],["修复2021版本abort时执行wxuncaughtexception",{"2":{"272":1}}],["修复2021",{"2":{"32":1}}],["修复是否需要下载代码包上报",{"2":{"205":1}}],["修复playerpref在unity",{"2":{"169":1}}],["修复png资源windows系统下缓存异常",{"2":{"148":1}}],["修复pc端onkeydown回调报错",{"2":{"79":1}}],["修复send接口性能问题",{"2":{"143":1}}],["修复偶现读取空文件的bug",{"2":{"128":1}}],["修复fmod相关的适配问题",{"2":{"125":1}}],["修复fs",{"2":{"27":1}}],["修复fstate偶现报错",{"2":{"25":1}}],["修复打包后分包插件提示",{"2":{"92":1}}],["修复导出webgl的兼容逻辑",{"2":{"90":1}}],["修复api中不确定类型的数据可能导致类型转换失败的问题",{"2":{"252":1}}],["修复audiosource修改pitch失效",{"2":{"79":1}}],["修复android偶现null",{"2":{"1065":1}}],["修复android的内存异常上涨",{"2":{"120":1}}],["修复android首次退出小游戏后会继续播放的问题",{"2":{"103":1}}],["修复android系统代码分包patch功能不生效的问题",{"2":{"35":1}}],["修复android平台导出时的",{"2":{"18":1}}],["修复最佳实践检测工具首资源包brotli压缩后仍提示未gzip",{"2":{"79":1}}],["修复最佳实践检测工具首资源包是否压缩判断",{"2":{"71":1}}],["修复系统字体未正常预下载",{"2":{"79":1}}],["修复微信压缩纹理dxt占位符当初修复eslint引发的无法替换问题",{"2":{"125":1}}],["修复微信压缩纹理工具在",{"2":{"55":1}}],["修复微信压缩纹理工具对音频ab包的处理bug问题",{"2":{"55":1}}],["修复微信系统字体多行重写的问题",{"2":{"100":1}}],["修复微信系统字体在ios系统部分缺失符号",{"2":{"100":1}}],["修复微信系统字体在ios上部分字符缺失",{"2":{"90":1}}],["修复微信系统字体在安卓上字形异常",{"2":{"90":1}}],["修复微信系统字体加载时报错",{"2":{"76":1}}],["修复使用",{"2":{"71":1}}],["修复旧版本安卓使用系统字体报错",{"2":{"68":1}}],["修复webgl2导出时的胶水层异常",{"2":{"159":1}}],["修复win7下使用unity2021生成symbols时导致的卡死问题",{"2":{"151":1}}],["修复wasm分包patch未生效的问题",{"2":{"60":1}}],["修复wxwritebinfilesync返回值的处理",{"2":{"169":1}}],["修复wxassetbundle",{"2":{"65":1}}],["修复wxassetbundle在异常时上报错误",{"2":{"60":1}}],["修复wxassetbundle与预下载冲突问题",{"2":{"14":1}}],["修复wx",{"2":{"27":3,"76":1}}],["修复ios普通模式运行出错的问题",{"2":{"1065":1}}],["修复ios普通模式的渲染异常",{"2":{"125":1}}],["修复ios",{"2":{"1065":1}}],["修复ios下音频被系统打断后的恢复问题",{"2":{"311":1}}],["修复ios高性能模式进程内存过大的问题",{"2":{"125":1}}],["修复ios音频被打断无法重新播放",{"2":{"48":1}}],["修复ios17",{"2":{"6":1}}],["修复ios18微信系统字体丢失",{"2":{"6":1}}],["修复适配插件处理代码分包时序导致的一定概率启动失败",{"2":{"43":1}}],["修复touchmove优化在2020之前版本产生的导出错误",{"2":{"45":1}}],["修复touchmove在",{"2":{"43":1}}],["修复tcp接口arraybuffer处理",{"2":{"38":1}}],["修复压缩纹理工具在一些特殊字符转义失败的bug",{"2":{"35":1}}],["修复开放域排行榜触控",{"2":{"32":1}}],["修复广告低版本微信reportsharebehavior上报问题",{"2":{"32":1}}],["修复蓝牙数据传输问题",{"2":{"32":1}}],["修复截屏回调",{"2":{"27":1}}],["修复unity2021下使用微信压缩纹理工具",{"2":{"159":1}}],["修复unity2018",{"2":{"18":1}}],["修复unityaudio适配inneraudio时",{"2":{"138":1}}],["修复unityplugin",{"2":{"133":1}}],["修复unity压缩选项导致出包错误",{"2":{"92":1}}],["修复unity",{"2":{"23":1,"100":1}}],["修复udp接口处理buffer",{"2":{"23":1}}],["修复配置文件重置bug",{"2":{"21":1}}],["修复团结版dotnet",{"2":{"21":1}}],["修复多线程压缩的扩展名判定",{"2":{"9":1}}],["修复多点触控产生的异常",{"2":{"9":1}}],["修复游戏圈文案默认显示",{"2":{"6":1}}],["修复音频的长度为负数时的异常stop",{"2":{"21":1}}],["修复音频pc端异常循环播放",{"2":{"6":1}}],["修复音频设置timesamples不生效",{"2":{"6":1}}],["修复插件自动调节dpr后",{"2":{"6":1}}],["修复",{"2":{"6":1}}],["忽略ab",{"2":{"411":1}}],["忽略",{"2":{"398":1}}],["忽略配置说明",{"0":{"398":1}}],["忽略路径下指定类型文件",{"2":{"290":1}}],["忽略unity分析的网络失败上报",{"2":{"76":1}}],["忽略非重要网络异常上报",{"2":{"70":1}}],["=3",{"2":{"978":1}}],["=500mb时",{"2":{"727":1}}],["=14",{"2":{"1077":1,"1093":1}}],["=1024mb时",{"2":{"727":1}}],["=1",{"2":{"527":2}}],["=15",{"2":{"26":1,"1077":1}}],["==",{"2":{"468":1,"591":1,"687":1,"688":1,"708":1,"902":1,"930":1,"931":1,"934":1,"973":1}}],["===",{"2":{"374":1,"703":2,"826":6,"994":2}}],["=>",{"2":{"351":1,"374":1,"414":1,"479":1,"507":2,"512":1,"533":1,"576":4,"580":1,"589":1,"591":1,"602":1,"703":1,"708":1,"825":3,"826":1,"926":1,"927":1,"945":2,"979":4,"983":2,"1002":1,"1005":5,"1074":1}}],["=",{"2":{"351":2,"374":3,"383":3,"384":3,"409":1,"412":5,"415":2,"423":1,"425":1,"426":14,"451":2,"507":3,"512":2,"513":2,"521":1,"533":1,"555":8,"576":4,"580":2,"585":1,"598":1,"602":2,"608":1,"621":2,"622":1,"624":1,"634":1,"635":2,"638":2,"646":1,"657":1,"661":1,"668":2,"673":1,"678":4,"683":1,"687":1,"688":2,"692":2,"703":4,"707":6,"708":12,"717":1,"724":1,"753":3,"785":1,"793":2,"825":7,"826":2,"897":1,"902":3,"926":1,"927":2,"930":2,"931":2,"932":1,"934":3,"942":1,"943":6,"945":2,"962":1,"973":2,"977":3,"979":6,"981":2,"983":6,"992":1,"994":1,"995":4,"1001":3,"1002":3,"1004":1,"1005":9,"1010":1,"1073":4}}],["=2",{"2":{"75":1,"959":1,"1093":1}}],["overview",{"2":{"939":1}}],["overdraw",{"2":{"819":1}}],["override",{"2":{"383":3}}],["object",{"2":{"703":1,"889":1}}],["objectfit",{"2":{"632":1,"634":1}}],["obj",{"2":{"576":1,"926":2,"927":1}}],["osize",{"2":{"973":2}}],["os",{"2":{"479":1}}],["osx",{"2":{"409":1}}],["offmessage",{"2":{"979":1,"983":1}}],["offglobalvarchange",{"0":{"596":1}}],["offweaknetwork",{"0":{"592":1}}],["offerr",{"0":{"590":1}}],["offend",{"0":{"588":1,"603":1}}],["offkeyboardcomplete",{"2":{"555":1}}],["offkeyboardconfirm",{"2":{"555":1}}],["offkeyboardinput",{"2":{"555":1}}],["of",{"2":{"451":1,"973":2}}],["other",{"2":{"428":1,"429":1,"580":1,"971":2,"973":1}}],["others",{"0":{"348":1}}],["out",{"2":{"451":1,"676":1,"678":2}}],["outbundledir",{"2":{"412":1,"414":1}}],["outdir",{"2":{"384":1}}],["opts",{"2":{"902":1}}],["options选项",{"2":{"1079":1}}],["optionstyle",{"2":{"426":1}}],["optimization",{"2":{"949":2,"1016":1}}],["optimizesize",{"2":{"84":1}}],["opacity",{"2":{"655":1,"667":1,"668":1,"676":1,"678":2}}],["oppo",{"2":{"532":1,"1105":1,"1120":1}}],["operadata",{"2":{"618":1,"621":2,"622":3,"624":2,"634":1,"635":1,"638":1,"646":1,"657":1,"661":1,"668":1,"673":1,"678":3,"683":1,"688":2,"692":2}}],["opera",{"2":{"610":1,"611":1,"612":1}}],["operaplay",{"2":{"576":1}}],["operahandler",{"2":{"576":6,"580":2}}],["operateaudio",{"2":{"367":1}}],["operators",{"2":{"358":1}}],["opengl",{"2":{"1076":3}}],["opengles3",{"2":{"477":1}}],["opendatacontext",{"2":{"709":1}}],["opendata",{"2":{"703":2}}],["opendatamessage",{"2":{"703":3,"707":1,"708":2}}],["openapi",{"2":{"374":5}}],["open",{"2":{"374":1,"499":3,"701":2,"704":1,"706":1,"707":1,"708":2}}],["openprofilestats",{"2":{"270":1}}],["openpageoption",{"2":{"109":2}}],["org",{"2":{"887":3,"981":1,"1004":18}}],["orthoparams",{"2":{"431":1}}],["origin",{"2":{"370":1}}],["orientation",{"2":{"353":1,"899":1}}],["or",{"0":{"716":1,"723":1},"2":{"71":1,"584":1,"731":1,"967":1,"971":8,"984":1,"1065":1}}],["onopen",{"2":{"981":2}}],["onfinishreceivedata",{"2":{"971":1}}],["ondump",{"2":{"968":1}}],["onhide",{"2":{"826":1}}],["onshowcallbackresult",{"2":{"708":1}}],["onshow",{"2":{"708":2,"826":1}}],["onmessage函数将分支",{"2":{"981":1}}],["onmessage表现与文档不一致",{"2":{"979":1,"983":1}}],["onmessage",{"2":{"703":3,"979":4,"981":2,"983":4}}],["onclose",{"2":{"981":2}}],["onclick",{"2":{"622":2,"656":1,"657":1,"660":1,"661":1}}],["onchanged",{"2":{"682":1}}],["onchange",{"2":{"682":1}}],["oncancel",{"2":{"672":1}}],["onconnect",{"2":{"979":1}}],["onconfirm",{"2":{"555":4}}],["oncomplete",{"2":{"555":4}}],["oncompasschange",{"2":{"76":1}}],["onglobalvarchange",{"0":{"595":1}}],["onweaknetwork",{"0":{"591":1},"2":{"576":1,"581":1,"591":1}}],["onerror",{"2":{"979":1,"981":2,"1005":2}}],["onerror增加回调信息",{"2":{"103":1}}],["onerr",{"0":{"589":1},"2":{"576":1,"587":1,"589":2}}],["onended",{"2":{"622":1,"633":1,"645":1,"672":1,"673":1,"677":1,"678":2,"692":2}}],["onend",{"0":{"587":1,"602":1},"2":{"576":1,"587":1,"602":1}}],["onkeyboardcomplete",{"2":{"555":1}}],["onkeyboardconfirm",{"2":{"555":1}}],["onkeyboardinput",{"2":{"555":1}}],["onkeyboardinputlistenerresult",{"2":{"109":1,"555":3}}],["onkeyboardinputcallbackresult",{"2":{"109":1}}],["oninput",{"2":{"555":4}}],["onplaytimeat",{"2":{"622":4,"633":1,"634":2,"645":1,"646":2}}],["onplay",{"2":{"622":1,"633":1,"645":1}}],["onpointerexit",{"2":{"555":2}}],["onpointerclick",{"2":{"555":2}}],["onpreprocessbuild",{"2":{"479":1}}],["ontouchstart",{"2":{"533":1}}],["onlaunchprogress",{"2":{"826":1}}],["onload",{"2":{"515":2,"1003":1,"1005":2}}],["only",{"0":{"491":1},"2":{"355":1,"450":1,"451":3,"899":1}}],["onusercapturescreen",{"2":{"27":1}}],["onbluetoothdevicefound",{"2":{"27":1}}],["on",{"2":{"20":1,"428":1,"576":1,"580":1,"602":1,"678":1,"688":1}}],["onapplicationfocus",{"2":{"6":1}}],["重复收集与生成",{"0":{"1027":1},"2":{"1012":1}}],["重复赋相同值也会发生事件",{"2":{"682":1}}],["重新打水印",{"2":{"1131":1}}],["重新进入小游戏并打开调试",{"2":{"1093":1}}],["重新计算缩放",{"2":{"1073":1}}],["重新导出",{"2":{"922":1}}],["重新生成一轮即可",{"2":{"461":1}}],["重建家园",{"2":{"845":1}}],["重度slg品类",{"2":{"852":1}}],["重度mmo品类",{"2":{"846":1,"851":1}}],["重度",{"2":{"758":1,"1113":1}}],["重度游戏",{"2":{"727":1}}],["重点关注",{"2":{"763":1,"1114":1}}],["重点关注指标",{"2":{"760":1,"1112":1}}],["重点关注兼容性问题",{"2":{"741":1}}],["重点是了解微信小游戏为开发者们提供了哪些关键动作帧",{"2":{"626":1}}],["重现条件",{"2":{"562":1}}],["重启unityprofiler监听",{"2":{"902":2}}],["重启小游戏",{"2":{"459":1,"1097":1}}],["重启",{"2":{"410":1}}],["重命名为",{"2":{"374":1}}],["重构fs",{"2":{"70":1}}],["重要",{"2":{"6":4,"23":2,"31":1,"35":1,"38":1,"40":2,"42":2,"47":2,"54":1,"60":2,"942":1}}],["重要更新",{"0":{"4":1,"7":1,"22":1,"33":1,"36":1,"39":1,"41":1},"1":{"5":1,"6":1,"8":1,"9":1,"23":1,"34":1,"35":1,"37":1,"38":1,"40":1,"42":1,"43":1},"2":{"46":1,"58":1}}],["96",{"2":{"1126":1}}],["960",{"2":{"1126":1}}],["90",{"2":{"1093":1}}],["90ms",{"2":{"532":1}}],["9866",{"2":{"889":1}}],["915",{"2":{"515":1}}],["92",{"2":{"432":1}}],["94s",{"2":{"532":1}}],["94",{"2":{"158":1}}],["954ms",{"2":{"532":1}}],["9551162e",{"2":{"515":2}}],["95",{"2":{"155":1}}],["97cd953f8494c3375312e75a29c34fc2",{"2":{"992":1,"997":2}}],["97",{"2":{"153":1}}],["9",{"0":{"58":1,"118":1,"146":1,"157":1,"160":1,"163":1,"165":1,"168":1,"464":1,"478":1,"491":1,"751":1,"1056":1,"1101":1},"1":{"59":1,"60":1,"119":1,"120":1,"147":1,"148":1,"158":1,"159":1,"161":1,"162":1,"164":1,"166":1,"167":1,"169":1,"1057":1},"2":{"432":3,"622":1,"1012":1,"1082":1,"1126":2}}],["mysite",{"2":{"977":2}}],["myconfig",{"2":{"934":2}}],["mytexture",{"2":{"930":1,"931":1,"932":1}}],["multi",{"2":{"812":2}}],["ms",{"2":{"671":1,"789":2,"795":4,"801":4}}],["msgdata",{"2":{"703":3,"707":3,"708":4}}],["msg",{"2":{"414":2,"703":2,"707":2,"708":2}}],["msgseccheck",{"2":{"374":9}}],["moved",{"2":{"934":1}}],["mozilla",{"2":{"887":1}}],["more",{"2":{"531":1}}],["motionvector",{"2":{"431":1}}],["motion",{"2":{"430":1}}],["mobile宏",{"2":{"429":1}}],["mobile",{"2":{"429":6}}],["mode为",{"2":{"707":2}}],["mode宏来控制",{"2":{"433":1}}],["mode宏",{"2":{"429":1}}],["mode来定制代码",{"2":{"429":1}}],["mode",{"2":{"429":15,"430":1,"431":2,"612":1}}],["monitorduration",{"2":{"785":1}}],["monitorconfig",{"2":{"785":1}}],["monitor",{"2":{"715":1}}],["mono内存",{"2":{"724":1}}],["monoheapreserved",{"2":{"717":1}}],["monoheap",{"2":{"717":2}}],["monobehaviour",{"2":{"555":1,"927":3,"979":1,"983":1}}],["monobehaviour脚本的首帧start",{"2":{"530":1,"875":1}}],["monobleedingedge",{"2":{"410":2}}],["mono",{"0":{"492":1},"2":{"408":1,"409":5,"410":1}}],["months",{"2":{"358":1}}],["metadatacache",{"2":{"971":2}}],["metric",{"2":{"691":1,"825":1}}],["memprofiler",{"2":{"968":1}}],["mem更精确分析内存",{"2":{"731":1}}],["memory无法统计到mono相关的内存",{"2":{"967":1}}],["memory将无法统计到lua的内存分配",{"2":{"967":1}}],["memoryprofiler分析",{"2":{"731":1}}],["memory",{"0":{"722":1},"2":{"355":1,"712":2,"949":4,"968":1,"971":2}}],["memorysize",{"2":{"346":1,"353":1}}],["memory查看dynamicmemory",{"2":{"142":1}}],["message",{"2":{"374":2,"979":1,"983":2}}],["mb",{"2":{"353":1}}],["mp4",{"2":{"634":1,"1126":2}}],["mp管理后台提供了漏斗图的数据可视化看板",{"2":{"578":1}}],["mp平台",{"2":{"565":1,"566":1,"567":1}}],["mp3",{"2":{"367":1,"646":1}}],["mp",{"2":{"353":1,"499":1,"540":2,"552":1,"759":1,"768":1,"985":1}}],["mismatch问题",{"2":{"1065":1}}],["miscellaneous",{"2":{"358":1}}],["mixrealtimeandbakedshadows",{"2":{"431":1}}],["minor",{"2":{"952":1}}],["min",{"2":{"396":1,"540":1}}],["minigame为小游戏项目",{"2":{"894":1}}],["minigame文件夹而不是导出的根目录",{"2":{"457":1}}],["minigame目录为转化后的小游戏代码",{"2":{"435":1}}],["minigameconfig",{"0":{"352":1,"898":1,"991":1},"1":{"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"899":1,"900":1},"2":{"137":1,"218":1,"352":1,"505":1,"897":1}}],["minigame",{"2":{"0":1,"1":1,"70":1,"127":2,"374":1,"376":2,"377":8,"380":1,"383":1,"384":4,"435":1,"490":2,"494":1,"507":1,"540":1,"582":4,"612":1,"613":1,"614":2,"615":1,"618":1,"694":1,"701":1,"704":1,"708":3,"759":1,"834":2,"836":3,"889":1,"894":1,"917":1,"979":1,"983":1,"1010":1,"1106":1,"1120":1,"1133":1,"1136":2}}],["miniprogram",{"2":{"0":1,"1":1,"127":1,"836":1,"917":1,"1133":1,"1136":1}}],["mipmap",{"2":{"363":1,"971":2}}],["micromsg",{"2":{"351":1,"523":2,"968":1}}],["mmo游戏进入创角时",{"2":{"825":1}}],["mmo",{"2":{"727":1,"758":1,"1113":1,"1135":1}}],["mmgame",{"2":{"708":1}}],["mm",{"2":{"351":1,"523":2,"968":1}}],["md5",{"2":{"516":1,"526":1,"759":2,"1106":2,"1120":2}}],["md",{"2":{"127":1,"421":1,"423":1}}],["mafanwei",{"2":{"977":1}}],["malloc",{"2":{"970":1}}],["major",{"2":{"952":1}}],["mask",{"2":{"812":3}}],["master",{"2":{"421":1,"423":1}}],["map的",{"2":{"811":1}}],["manual",{"2":{"805":1,"883":1,"887":1,"902":1}}],["managed",{"0":{"480":1},"2":{"874":1}}],["managerconfig",{"2":{"962":1,"992":1,"994":3}}],["manager导入wxsdk模式下的目录",{"2":{"377":1}}],["manager",{"2":{"167":2,"351":1,"428":5,"433":1,"518":1,"519":1,"520":1,"521":1,"522":1,"533":1,"836":1,"956":1,"994":5,"996":2}}],["maxloadingcount",{"2":{"798":1}}],["maxlength",{"2":{"555":1}}],["maxfetchpendingtime",{"2":{"795":1,"796":1}}],["maximum",{"2":{"745":1}}],["max",{"2":{"707":1,"724":2}}],["maxsize大于512",{"2":{"362":1}}],["maxstorage",{"2":{"353":1,"505":1,"513":1,"899":1}}],["mat4x4",{"2":{"1079":1}}],["materialtype",{"2":{"824":1}}],["materialtype=1",{"2":{"824":1}}],["materialconfig",{"2":{"421":1,"423":1}}],["mathematical",{"2":{"358":1}}],["mac",{"0":{"479":1},"2":{"351":1,"713":1,"805":1,"902":1}}],["macos系统执行报错",{"0":{"408":1},"1":{"409":1,"410":1}}],["macos",{"2":{"55":1,"615":1}}],["markdownviewer可能出现guiskin引用丢失",{"2":{"291":1}}],["mainlightshadowparams",{"2":{"431":1}}],["mainlightshadowcasterpass",{"2":{"431":1}}],["mainlightlayermask",{"2":{"431":1}}],["mainlightocclusionprobes",{"2":{"431":1}}],["main",{"2":{"127":1,"374":1,"917":1,"1126":1}}],["m1系列芯片执行异常问题",{"2":{"55":1}}],["blazor",{"0":{"492":1}}],["bleed",{"2":{"431":1}}],["blog",{"2":{"939":1,"949":2,"977":1}}],["bloom",{"2":{"431":1}}],["block",{"2":{"393":3}}],["blob",{"2":{"127":1,"421":1,"423":1,"981":1}}],["boot",{"0":{"492":1}}],["boolean",{"2":{"520":1,"628":1,"632":4,"644":3,"655":1,"659":1,"664":1,"667":1,"671":1,"676":1,"789":2,"792":2,"795":1,"798":12,"826":4}}],["bool",{"0":{"520":1,"522":1,"600":1,"602":1,"603":1},"2":{"353":5,"354":4,"355":16,"356":4,"358":19,"412":3,"414":3,"500":2,"555":1,"979":1,"983":1}}],["bounds",{"2":{"451":1}}],["boxprojection",{"2":{"431":1}}],["borderradius",{"2":{"426":1}}],["border",{"2":{"423":1}}],["bottom",{"2":{"421":3,"423":2,"614":1,"621":2,"629":1,"632":1,"634":1,"655":1,"657":1,"659":1,"661":1,"667":1,"676":1,"678":1}}],["bc7",{"2":{"392":1}}],["big",{"0":{"1039":1},"2":{"1012":1}}],["binarytype",{"2":{"902":1}}],["bind",{"2":{"622":4,"634":1,"646":1,"657":1,"661":1,"673":1,"678":2,"688":2,"692":2,"983":1}}],["bin",{"2":{"396":1,"409":1,"435":1,"436":1,"437":1,"479":1,"759":1,"805":1,"865":1,"1106":1,"1120":1}}],["bizid=1023",{"2":{"370":1}}],["bits",{"2":{"392":3}}],["bit",{"2":{"351":1,"392":2,"1010":1}}],["byte",{"2":{"981":1}}],["bytes",{"2":{"516":1,"792":1,"798":2,"981":1}}],["by",{"2":{"370":1,"433":1}}],["brt显示了编译时包括的每个资源占用的存储空间以及未使用资源情况",{"2":{"881":1}}],["browser",{"2":{"473":1,"570":1,"968":1}}],["brotli或gzip",{"2":{"924":1}}],["brotli",{"0":{"460":1},"2":{"1014":1}}],["brotlimt",{"2":{"355":1}}],["br",{"0":{"1095":1},"2":{"460":1,"759":1,"864":1,"1082":1,"1095":1,"1106":1,"1120":1}}],["br压缩后",{"2":{"761":1,"1107":1,"1122":1}}],["br压缩",{"2":{"79":1,"873":1}}],["bgimagesrc",{"2":{"353":1,"420":1,"899":1,"958":1}}],["bug",{"2":{"1097":2}}],["but",{"2":{"931":1}}],["button",{"2":{"621":2,"678":4}}],["built资源是以文本形式存在",{"2":{"924":1}}],["builtin",{"2":{"437":1,"812":1,"873":1}}],["buildassetbundles",{"2":{"942":1}}],["buildassetbundleoptions",{"2":{"523":1,"942":6}}],["buildpipeline",{"2":{"942":1}}],["buildsetting",{"2":{"902":1}}],["buildsettings中所有active的场景",{"2":{"873":1}}],["buildsettings",{"2":{"451":1,"452":1}}],["build目录下的code文件",{"2":{"874":1}}],["build目录下的data文件",{"2":{"873":1}}],["buildtarget",{"2":{"942":1}}],["buildtools",{"2":{"805":2,"902":3}}],["buildtemplatehelper介绍",{"0":{"384":1}}],["buildtemplatehelper",{"2":{"381":1,"383":1,"384":4}}],["buildreporttool",{"0":{"881":1}}],["buildreport",{"2":{"479":1}}],["build会在异常产生时直接附带完整的函数名",{"2":{"453":1}}],["build才生效",{"2":{"355":1}}],["build报错",{"2":{"283":1}}],["build",{"0":{"453":1},"2":{"117":1,"355":3,"383":1,"435":1,"449":1,"450":1,"479":2,"575":1,"615":1,"724":1,"805":1,"834":1,"881":1,"896":1,"899":2,"902":2,"942":1,"968":1,"1136":1}}],["build的导出支持",{"2":{"54":1}}],["bundle还是assetbundle类型",{"2":{"945":1}}],["bundlereq",{"2":{"945":5}}],["bundle带上hash",{"2":{"942":1}}],["bundle使用缓存",{"2":{"515":1}}],["bundle成功",{"2":{"515":1}}],["bundle中hash的长度",{"2":{"513":1}}],["bundle中hash占多少长度",{"2":{"505":1}}],["bundle名中hash长度",{"2":{"505":1,"893":1,"899":1}}],["bundles",{"2":{"505":1,"949":2}}],["bundlesuffix",{"2":{"356":1}}],["bundle的配置文件",{"2":{"441":1}}],["bundle",{"0":{"391":1},"1":{"392":1,"393":1},"2":{"386":3,"388":1,"391":2,"515":1,"549":2,"828":1,"926":1,"945":2}}],["bundledir",{"2":{"356":1,"412":1,"414":1,"415":1,"417":1}}],["bundleexcludeextensions",{"2":{"353":1,"505":1,"507":1,"899":1}}],["bundlepathidentifier",{"2":{"353":1,"505":1,"507":1,"513":1,"523":1,"900":1}}],["bundlehashlength",{"2":{"353":1,"505":2,"513":2,"899":1}}],["buffer",{"2":{"351":1,"807":1,"981":1,"1010":1}}],["before",{"2":{"932":1,"983":1}}],["beforecovertemplate",{"2":{"383":1}}],["beforecopydefault",{"2":{"383":1}}],["benchmark",{"2":{"532":1,"1087":2}}],["benchmark项目链接",{"2":{"532":1}}],["benchmark项目在不同设备上的callmain耗时分析",{"2":{"532":1}}],["beyond",{"2":{"431":1}}],["be",{"2":{"286":1,"932":1}}],["beta期间请联系研发助手设计剧情期间咨询异步干预能力",{"2":{"577":1}}],["beta",{"0":{"385":1,"397":1,"568":1},"1":{"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"569":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1},"2":{"40":1,"42":1,"119":1}}],["bannerad",{"2":{"1005":8}}],["banner",{"2":{"1005":1}}],["batchsize",{"2":{"1079":1}}],["batch以减少dc",{"2":{"751":1}}],["batcher提高渲染性能",{"2":{"1076":1}}],["batcher的收益情况",{"2":{"815":1}}],["batcher需要两个先决条件",{"2":{"752":1}}],["batcher需要webgl2",{"2":{"734":1}}],["batcher",{"0":{"752":1},"2":{"431":1,"815":2}}],["bakedlitinput",{"2":{"431":1}}],["barwidth",{"2":{"959":1}}],["bar",{"2":{"422":1,"958":1,"959":1}}],["barconfig",{"2":{"421":1,"423":1}}],["backend选项",{"2":{"492":1}}],["backend",{"2":{"374":1}}],["backgroundvideo",{"2":{"421":1,"959":1}}],["backgroundimage需要注意图片宽高不可超过2048",{"2":{"959":1}}],["backgroundimage",{"2":{"421":1,"423":1,"959":1}}],["backgroundcolor",{"2":{"421":1,"423":1,"426":1,"580":1,"585":1}}],["background",{"2":{"246":1,"423":1}}],["bash",{"2":{"435":2,"436":1,"894":1,"947":1}}],["basic",{"2":{"358":1}}],["basedir",{"2":{"384":2}}],["base",{"2":{"130":1,"490":2}}],["drive",{"2":{"939":1}}],["draw",{"2":{"815":5}}],["drawcall",{"0":{"815":1}}],["drawelements",{"2":{"697":1}}],["drawprocedural",{"0":{"493":1}}],["drawwireoverlay",{"2":{"430":1,"431":1}}],["drawgizmos",{"2":{"430":1,"431":1}}],["drawing",{"0":{"408":1},"1":{"409":1,"410":1}}],["d4fcv0h2cqbep1zo6ma",{"2":{"920":1,"939":1}}],["dsvdvrhh6elzrdgzu",{"2":{"843":1}}],["dstminigamedir",{"2":{"384":1}}],["dstmindir",{"2":{"356":1}}],["dst",{"2":{"353":1,"899":1,"942":4}}],["dump",{"2":{"968":1}}],["dump功能",{"2":{"127":1}}],["duplicate",{"2":{"926":1}}],["duration",{"2":{"676":1,"678":2,"798":2,"799":1}}],["dlrealloc",{"2":{"973":1}}],["dlfree",{"2":{"973":1}}],["dlmalloc",{"2":{"973":4}}],["dldir1",{"2":{"499":1}}],["dll",{"0":{"471":1,"479":1}}],["dmg",{"2":{"479":1}}],["d",{"2":{"428":3,"920":1,"939":2}}],["dylib",{"2":{"408":1,"410":3}}],["dynamicmemory",{"2":{"717":2,"967":1}}],["dynamic",{"2":{"374":1,"431":1}}],["dxt等纹理格式将导致巨大的内存开销与运行时解压消耗",{"2":{"726":1}}],["dxt1|bc1",{"2":{"392":2}}],["dxt5|bc3",{"2":{"392":2}}],["dxt",{"2":{"386":1,"387":1,"388":1,"405":4,"905":1}}],["dictionary",{"2":{"708":1,"825":2}}],["dimension",{"2":{"691":1,"825":1}}],["dithering",{"2":{"431":1}}],["directbrdfspecular",{"2":{"431":1}}],["directional",{"2":{"431":1}}],["directx",{"2":{"429":1}}],["directory",{"2":{"71":1,"942":2}}],["dispose",{"2":{"943":2}}],["display",{"2":{"431":1}}],["disablewritetypetree",{"2":{"942":1}}],["disablehighperformancefallback",{"2":{"353":1}}],["disk",{"2":{"428":2}}],["dingbats",{"2":{"358":1}}],["datarate",{"2":{"1126":1}}],["datafilesubprefix",{"2":{"353":1,"900":1,"955":1}}],["data",{"2":{"351":1,"374":1,"396":1,"435":2,"436":1,"437":1,"501":1,"513":3,"518":1,"523":3,"701":2,"703":7,"704":1,"706":1,"707":1,"708":1,"759":1,"805":2,"826":1,"864":1,"865":2,"902":2,"960":1,"961":1,"962":2,"981":1,"994":2,"1106":1,"1120":1}}],["deux",{"2":{"949":2}}],["dependencies",{"2":{"926":1}}],["depthoffield",{"2":{"431":1}}],["delay1000",{"2":{"673":2}}],["deletestreamingassets",{"2":{"355":1,"899":2}}],["destroy",{"2":{"1087":1}}],["destination",{"0":{"481":1}}],["designheight",{"2":{"421":1,"423":1}}],["designwidth",{"2":{"421":1,"423":1}}],["design",{"2":{"127":1}}],["deny字样错误",{"0":{"466":1}}],["detail",{"2":{"431":1}}],["decal",{"2":{"430":1,"431":1}}],["deferred",{"2":{"430":1,"431":1}}],["defined",{"2":{"429":3}}],["define",{"2":{"429":5}}],["defalut",{"2":{"377":1,"378":1}}],["defaultvalue",{"2":{"555":1}}],["default",{"2":{"377":5,"384":2,"421":1,"431":1,"576":3,"582":1,"873":1,"973":1}}],["defaultreleasesize",{"2":{"353":1,"505":1,"513":1,"900":1}}],["debuginfo",{"2":{"753":3}}],["debugsymbols",{"2":{"452":1}}],["debug代码",{"2":{"430":1}}],["debugdisplaysettingsui",{"2":{"430":1,"431":1}}],["debughandler",{"2":{"430":1,"431":1}}],["debug",{"0":{"452":1},"2":{"383":1,"412":1,"414":3,"430":1,"431":1,"450":1,"451":6,"452":1,"468":2,"555":8,"753":1,"825":3,"926":1,"943":2,"945":1,"977":4,"979":5,"983":4,"995":1,"1005":1}}],["debugmode",{"2":{"356":1}}],["demo",{"0":{"1009":1},"2":{"370":1,"483":1,"555":1,"558":1,"917":1,"981":1,"1087":1}}],["devtools",{"2":{"531":1}}],["devicepixelratio",{"2":{"701":2}}],["device",{"2":{"494":1,"748":1,"817":2}}],["dev",{"2":{"127":1,"274":1,"281":1,"283":1,"374":1,"490":2,"494":1,"708":1,"979":1,"983":1}}],["developer",{"2":{"887":1}}],["developers",{"2":{"127":1,"374":1,"490":2,"494":1,"499":1,"531":1,"708":1,"887":1,"979":1,"983":1}}],["develop",{"2":{"355":1,"499":1}}],["developbuild",{"2":{"355":1,"899":1}}],["development模式会对性能有一定影响",{"2":{"532":1}}],["development模式下",{"2":{"75":1}}],["development",{"0":{"453":1},"2":{"54":1,"355":1,"450":1,"453":1,"805":1,"899":1,"902":1,"968":1}}],["dev版本不处理symbols数据",{"2":{"100":1}}],["download合法域名",{"2":{"985":1}}],["downloadhandlerwxassetbundle",{"2":{"945":2}}],["downloadhandlerassetbundle",{"2":{"943":3,"945":1}}],["downloadhandler",{"2":{"943":2,"945":1,"977":2,"995":1}}],["downloadingtext",{"2":{"421":1,"423":1,"959":1}}],["downloading",{"2":{"71":1}}],["done",{"2":{"931":1}}],["double",{"0":{"599":1}}],["does",{"2":{"570":1}}],["doexport方法导出小游戏",{"2":{"897":1}}],["doexport",{"2":{"468":2,"897":1}}],["doexport增加返回值方便第三方工具集成",{"2":{"103":1}}],["documentation",{"2":{"949":1}}],["document",{"2":{"920":1,"939":1}}],["doc",{"2":{"499":1}}],["docs",{"2":{"421":1,"423":1,"558":1,"805":1,"843":1,"883":1,"887":2,"902":1,"920":1,"939":1,"949":1}}],["dotnet",{"2":{"355":1}}],["dpr选项",{"2":{"34":1}}],["vv",{"2":{"805":1,"902":1}}],["vs",{"0":{"734":1,"735":1}}],["vscode",{"2":{"608":1,"614":1,"618":1}}],["volume",{"2":{"644":1}}],["void",{"0":{"520":1,"521":1,"522":1,"599":1,"601":1,"602":1,"603":1,"604":1},"2":{"383":3,"479":1,"500":3,"522":1,"555":8,"927":2,"930":2,"942":1,"973":7,"979":3,"983":3}}],["v",{"2":{"555":7}}],["vm",{"2":{"451":1}}],["vconsole输出如下",{"2":{"791":1}}],["vconsole",{"2":{"446":1,"459":1,"965":1,"1093":1,"1097":1}}],["vfxcalcpixeloutputforward",{"2":{"431":1}}],["vendor",{"2":{"753":3}}],["vector2",{"2":{"1073":2}}],["vector",{"2":{"430":1}}],["veretx",{"2":{"814":1}}],["vertex",{"2":{"814":2}}],["vertical",{"2":{"358":1}}],["versions",{"2":{"479":1}}],["version2",{"2":{"441":1}}],["version",{"2":{"380":1,"410":2,"952":1,"1045":1}}],["vivo",{"2":{"1105":1,"1120":1}}],["view",{"2":{"939":1}}],["visible",{"2":{"421":1,"614":1,"632":1,"655":1,"659":1,"667":1,"676":1}}],["video0",{"2":{"692":1}}],["video1",{"2":{"622":3,"624":1,"692":1}}],["video",{"2":{"420":1,"421":1,"422":1,"570":1,"634":4,"635":5,"637":1,"638":3,"640":1,"958":1,"959":1}}],["videoplayer",{"0":{"369":1,"487":1},"2":{"368":1,"370":4}}],["videoplayer组件",{"2":{"50":1}}],["videourl",{"2":{"353":1,"420":1,"422":1,"899":1,"958":1}}],["video支持修改属性",{"2":{"75":1}}],["var",{"0":{"680":1},"1":{"681":1,"682":1,"683":1},"2":{"383":1,"576":1,"598":1,"624":1,"627":1,"628":2,"632":3,"644":2,"655":1,"664":1,"671":1,"676":2,"683":3,"686":2,"688":5,"691":3,"707":2,"897":1,"926":1,"927":2,"934":2,"983":1}}],["valueb",{"2":{"686":1,"687":2,"688":1}}],["valuea",{"2":{"686":1,"687":2,"688":1}}],["value",{"0":{"593":1,"599":1,"604":1},"2":{"380":1,"555":4,"576":3,"599":1,"635":1,"664":1,"681":1,"683":1,"688":1,"977":1}}],["v8",{"2":{"351":1,"712":1}}],["v1",{"0":{"1048":1,"1050":1,"1052":1,"1054":1,"1056":1,"1058":1,"1060":1,"1062":1,"1064":1,"1066":1,"1068":1,"1070":1},"1":{"1049":1,"1051":1,"1053":1,"1055":1,"1057":1,"1059":1,"1061":1,"1063":1,"1065":1,"1067":1,"1069":1,"1071":1},"2":{"133":1,"1012":12}}],["v2",{"2":{"108":2,"352":1,"377":4,"383":2,"384":1,"576":1,"582":1,"839":1,"922":2}}],["v0",{"2":{"1":1}}],["陀螺仪去json性能优化",{"2":{"31":1,"34":1}}],["增量分包没生效",{"0":{"1041":1},"2":{"1012":1}}],["增强运行时性能",{"2":{"905":1}}],["增强jsonmapper报错信息",{"2":{"2":1}}],["增快游戏的运行进度",{"2":{"549":1}}],["增快游戏运行进度",{"2":{"549":1}}],["增加跨域头部",{"2":{"1095":1}}],["增加以下代码",{"2":{"1010":1}}],["增加了bundle大小的内存",{"2":{"947":1}}],["增加webgl移动端压缩纹理",{"2":{"905":1}}],["增加wx",{"2":{"127":1}}],["增加",{"2":{"429":1,"922":1}}],["增加对",{"2":{"374":1}}],["增加对21",{"2":{"218":1}}],["增加预下载猎豹配置",{"2":{"326":1}}],["增加预下载并发数控制接口wx",{"2":{"323":1}}],["增加unity2020",{"2":{"296":1}}],["增加udp接口能力",{"2":{"182":1}}],["增加部分文件操作api",{"2":{"294":1}}],["增加bundle相关导出配置",{"2":{"290":1}}],["增加error日志回调",{"2":{"280":1}}],["增加适配",{"2":{"280":1}}],["增加日志输出",{"2":{"244":1}}],["增加cleastreamingassets选项",{"2":{"234":1}}],["增加清除文件缓存接口cleanfilecache",{"2":{"232":1}}],["增加清理指定文件接口removefile",{"2":{"228":1}}],["增加memoryprofiler",{"2":{"207":1}}],["增加进度条",{"2":{"192":1}}],["增加重启小游戏的api支持",{"2":{"184":1}}],["增加详细日志输出",{"2":{"175":1}}],["增加动态修改预下载列表的c",{"2":{"167":1}}],["增加动态修改data",{"2":{"167":1}}],["增加游戏圈接口openpageoption",{"2":{"161":1}}],["增加profilingmemory功能",{"2":{"130":1}}],["增加getcachepath接口",{"2":{"127":1}}],["增加rmdir及rmdirsync接口",{"2":{"127":1}}],["增加opencustomerservicechat",{"2":{"89":1}}],["增加onmousedown等pc点击事件",{"2":{"70":1}}],["增加选项il2cppcodegeneration",{"2":{"84":1}}],["增加渲染性能检测日志",{"2":{"75":1}}],["增加api",{"2":{"73":1,"94":1,"102":1}}],["增加隐私信息授权api",{"2":{"73":1}}],["增加downloadfile",{"2":{"70":1}}],["增加模糊地理位置获取接口",{"2":{"62":1}}],["增加接口wx",{"2":{"40":1}}],["增加ios高性能+",{"2":{"31":1}}],["不超过",{"2":{"1126":1}}],["不超过30mb",{"2":{"874":1}}],["不优化内存",{"0":{"1100":1},"2":{"1082":1}}],["不绘制",{"2":{"1079":1}}],["不绘制等问题",{"0":{"1079":1}}],["不发起网络请求",{"2":{"998":1}}],["不检查安全域名",{"2":{"985":1}}],["不检验合法域名",{"2":{"984":1,"985":1}}],["不包含wasm编译内存",{"2":{"967":1}}],["不应超过5m",{"2":{"924":1}}],["不应该缓存到本地",{"2":{"799":1}}],["不应该是负数",{"2":{"709":1}}],["不常用配置",{"0":{"900":1}}],["不断提升自身",{"2":{"846":1}}],["不限制",{"2":{"829":1}}],["不建议",{"2":{"1100":1}}],["不建议在微信小游戏使用后处理",{"2":{"818":1}}],["不建议频率过高的调用",{"2":{"490":1}}],["不适用于小游戏",{"2":{"808":1}}],["不够精简",{"2":{"808":2}}],["不灵活",{"2":{"808":1}}],["不一定",{"2":{"807":1}}],["不用压缩纹理",{"2":{"813":1}}],["不用",{"2":{"811":1}}],["不用使用xml",{"2":{"743":1}}],["不用担心",{"2":{"428":1}}],["不必要的代码路径裁",{"2":{"735":1}}],["不要打包字体文件",{"2":{"924":1}}],["不要用额外的实时光",{"2":{"811":1}}],["不要初始化所有未使用的资源",{"2":{"781":1}}],["不要使用fmod播放长音频",{"2":{"729":1}}],["不要随意修改",{"2":{"353":1}}],["不过不管是什么屏幕适配模式",{"2":{"707":1}}],["不过值得注意的是",{"2":{"582":1}}],["不成立时执行的故事线",{"2":{"688":1}}],["不需要用户反馈行为",{"2":{"566":1}}],["不会实际读写到磁盘",{"2":{"945":1}}],["不会自动读取贴图资源尺寸",{"2":{"654":1}}],["不会自动缓存",{"2":{"523":1}}],["不会产生onweaknetwork回调",{"2":{"581":1}}],["不会显示unity游戏通用loading界面",{"2":{"571":1}}],["不会走缓存逻辑",{"2":{"523":1}}],["不会被自动清理的文件",{"2":{"512":1}}],["不清理",{"2":{"521":1}}],["不自动缓存文件类型",{"2":{"505":1,"893":1,"899":1}}],["不自动下载",{"2":{"335":1}}],["不提供内嵌webview或跳转的能力",{"2":{"486":1}}],["不行",{"2":{"470":1,"486":1}}],["不使用异常",{"2":{"451":1}}],["不在关键路径上",{"2":{"451":1}}],["不捕捉任何异常",{"2":{"451":1}}],["不希望被缓存的文件请添加到缓存忽略目录",{"2":{"441":1}}],["不希望被缓存的文件",{"2":{"441":1}}],["不满足渲染需要",{"2":{"433":1}}],["不能阻止线程等待",{"2":{"977":1}}],["不能直接拿来用",{"2":{"808":1}}],["不能直接用",{"2":{"433":1}}],["不能用wx",{"2":{"433":1}}],["不能拿微信定制的",{"2":{"433":1}}],["不影响",{"2":{"431":1}}],["不是真机调试",{"2":{"1026":1}}],["不是很稳定",{"2":{"740":1}}],["不是",{"2":{"429":1,"591":1,"731":1,"907":1}}],["不留黑边",{"2":{"423":1}}],["不如摸一个",{"2":{"423":3}}],["不同资源的缓存细节略有不同",{"2":{"506":1}}],["不同的游戏之间使用的场景",{"2":{"401":1}}],["不同客户端的支持情况不同",{"2":{"369":1}}],["不慎剔除将导致游戏的渲染异常",{"2":{"399":1}}],["不可避免的存在加载延迟问题",{"2":{"695":1}}],["不可使用网络图片",{"2":{"694":1}}],["不可存在多个警告消息",{"2":{"395":1}}],["不可混版本使用",{"2":{"394":1}}],["不支持移动端压缩纹理",{"2":{"905":1}}],["不支持astc",{"2":{"905":1}}],["不支持设置dpr分辨率",{"2":{"905":1}}],["不支持设备兼容处理",{"2":{"266":1}}],["不支持etc2",{"2":{"905":2}}],["不支持jit",{"2":{"736":1}}],["不支持开发者自建",{"2":{"557":1}}],["不支持system",{"2":{"498":1}}],["不支持luajit",{"2":{"498":1}}],["不支持",{"2":{"388":1,"392":3,"498":1,"829":1}}],["不支持对",{"2":{"386":1}}],["不支持webgl2时提示",{"2":{"227":1}}],["不支持webgl2的旧android微信版本提供升级指引",{"2":{"29":1}}],["不再直接崩溃",{"2":{"65":1}}],["不做旧缓存淘汰",{"2":{"16":1}}],["gfx显存",{"2":{"724":3,"731":1}}],["groups的功能",{"2":{"935":1}}],["groups时",{"2":{"935":1}}],["group",{"2":{"708":2}}],["graphicssetting",{"2":{"726":1}}],["graph包也会同时被移除",{"2":{"428":1}}],["graph",{"2":{"428":3,"812":1}}],["g",{"2":{"610":1}}],["gzip压缩后",{"2":{"761":1,"1107":1,"1122":1}}],["gzip",{"0":{"460":1,"1095":1},"2":{"460":1,"1082":1,"1095":1}}],["goonbuttonanimationfadein",{"2":{"678":3}}],["goonbuttonanimationfadeout",{"2":{"678":4}}],["google",{"2":{"531":1,"920":1,"939":2}}],["go2",{"2":{"451":2}}],["go",{"2":{"451":2,"555":1,"678":1,"688":1}}],["gbuffer",{"2":{"430":1,"431":1}}],["gdiplus",{"0":{"408":1},"1":{"409":1,"410":1}}],["gpu等选取性能相当的机型",{"2":{"1105":1}}],["gpu性能差异",{"2":{"734":1}}],["gpu之后的显存占用",{"2":{"712":1}}],["gpu内存有较大帮助",{"2":{"731":1}}],["gpu内存",{"0":{"726":1},"2":{"712":1}}],["gpu硬解纹理渲染更快",{"2":{"549":1}}],["gpu利用率从",{"2":{"432":2}}],["gpu",{"2":{"386":3,"431":1,"432":2,"549":1,"807":2,"814":2,"815":1}}],["geometric",{"2":{"358":1}}],["general",{"2":{"358":1}}],["getwindowinfo",{"2":{"1073":3}}],["getwxfont",{"2":{"1001":1,"1002":1}}],["getwxfont获取使用系统字体",{"2":{"108":1}}],["getpreloadlist",{"2":{"995":1}}],["getparameter",{"2":{"753":2}}],["gettype",{"2":{"943":2,"945":1}}],["getting",{"2":{"887":1}}],["gettingstarted",{"2":{"887":1}}],["getstring",{"2":{"979":1,"983":1}}],["getstoragesync",{"2":{"576":2}}],["getsysteminfooption",{"2":{"841":1}}],["getsysteminfo",{"2":{"841":1}}],["getextension",{"2":{"753":1}}],["getdeviceinfo获取硬件信息",{"2":{"753":1}}],["getdata",{"2":{"67":1}}],["getopendatacontext",{"2":{"701":1,"703":2,"707":1,"708":1}}],["getrunning",{"0":{"600":1}}],["getrealtimelogmanager",{"2":{"94":1}}],["getlaunchoperahandler",{"2":{"598":1,"602":1}}],["getlogmanager",{"2":{"94":1}}],["getglobalvar",{"0":{"594":1,"605":1}}],["getgameclubdata",{"2":{"161":1}}],["getgameclubdataoption",{"2":{"109":2}}],["getcomponent",{"2":{"555":1,"707":1}}],["getcontext",{"2":{"351":1,"1010":1}}],["getcachepath",{"0":{"519":1},"2":{"500":1,"519":1}}],["getassetbundle",{"2":{"943":2,"945":1,"947":1}}],["getassetbundles",{"0":{"415":1},"1":{"416":1,"417":1},"2":{"415":1}}],["getappauthorizesetting",{"2":{"27":1}}],["get",{"2":{"130":2,"971":2,"977":3,"995":1}}],["glgetstring",{"2":{"1097":1}}],["globalname",{"0":{"593":1,"594":1,"595":1,"596":1},"2":{"681":1,"683":1,"688":1}}],["globalvar",{"2":{"591":1}}],["globalmipbias",{"2":{"431":1}}],["glossyenvironmentcubemap",{"2":{"431":2}}],["glossyenvironmentcolor",{"2":{"431":1}}],["gles3",{"2":{"429":1}}],["gles30",{"2":{"429":1}}],["gles",{"2":{"429":5}}],["gl",{"2":{"351":3,"753":3,"1010":3,"1097":1}}],["guided",{"2":{"1016":1}}],["guide",{"2":{"127":1,"490":2,"624":1,"708":1,"887":1}}],["gamma矫正的",{"2":{"809":1}}],["gamma",{"0":{"809":1},"2":{"119":1,"809":2}}],["gameobject",{"2":{"451":2,"707":1,"927":2,"934":1}}],["game版本",{"2":{"397":1}}],["gamemanager",{"2":{"351":2,"533":3}}],["gameglobal",{"2":{"351":2,"426":1,"518":1,"519":1,"520":1,"521":1,"522":1,"533":1,"576":1,"583":1,"584":1,"956":1,"968":1,"994":5,"996":2,"1010":1}}],["game",{"0":{"421":1,"829":1,"959":1,"962":1},"2":{"94":1,"370":1,"380":3,"421":1,"428":2,"446":1,"459":1,"518":1,"538":1,"557":5,"576":2,"582":1,"704":1,"828":1,"829":6,"831":1,"832":1,"889":2,"965":1,"1010":1,"1088":1,"1093":1}}],["gc后内存峰值",{"2":{"1114":1}}],["gc",{"2":{"86":1,"624":1}}],["gt",{"0":{"520":1,"521":1,"522":1,"602":1,"603":1},"2":{"26":1,"75":1,"412":1,"415":1,"425":1,"446":3,"451":3,"452":3,"500":3,"520":1,"521":1,"522":1,"527":1,"531":4,"533":2,"608":1,"727":2,"785":1,"790":2,"793":2,"796":1,"802":3,"836":4,"893":1,"926":1,"944":4,"948":2,"959":1,"960":1,"965":3,"978":1,"982":1,"1001":3,"1011":1,"1077":4,"1088":4,"1093":2,"1123":3,"1124":3}}],["git安装url",{"2":{"1136":1}}],["gitee",{"2":{"836":1}}],["git目录忽略",{"2":{"140":1}}],["github",{"2":{"0":1,"1":1,"127":1,"421":1,"423":1,"481":1,"532":1,"836":1,"880":1,"917":1,"939":1,"981":1,"1133":1,"1136":1}}],["git",{"0":{"562":1},"2":{"0":2,"1":2,"836":3,"1136":1}}],["更换正确的appid后重新检测即可",{"2":{"1132":1}}],["更换引擎",{"2":{"1024":1}}],["更适合以下游戏需求",{"2":{"1076":1}}],["更节省内存的wxassetbundle",{"0":{"945":1}}],["更小的编译体积",{"2":{"907":1}}],["更好",{"2":{"829":1}}],["更全面地进行自动化游戏性能测试",{"2":{"770":1}}],["更早的运行时机",{"2":{"572":1}}],["更快的编译速度与更小的体积",{"2":{"905":1}}],["更快的转换打包速度",{"2":{"11":1}}],["更快编译和更小体积",{"2":{"497":1}}],["更建议使用服务器或云开发进行定期存储",{"2":{"472":1}}],["更多信息请阅读",{"2":{"779":1,"780":1,"781":1,"782":1}}],["更多信息请参考定制启动封面",{"2":{"959":1}}],["更多信息请参考",{"2":{"778":1}}],["更多信息可查看unityloader",{"2":{"437":1}}],["更多详情可查阅小游戏云测试",{"2":{"770":1}}],["更多配置项",{"2":{"748":1,"817":1,"913":1}}],["更多小游戏成功转换案例",{"2":{"535":1}}],["更多使用细节参考云调用文档",{"2":{"374":1}}],["更多文档和示例请参考云函数文档",{"2":{"374":1}}],["更多工具",{"2":{"351":2}}],["更推荐使用小游戏",{"2":{"370":1}}],["更接近unity的api调用方式",{"2":{"300":1}}],["更新时间",{"2":{"1105":1}}],["更新",{"2":{"1049":1}}],["更新分包插件后",{"2":{"1040":1}}],["更新插件即可",{"2":{"1039":1}}],["更新插件版本为1",{"2":{"236":1}}],["更新不及时",{"2":{"911":1}}],["更新策略",{"0":{"910":1},"1":{"911":1,"912":1,"913":1,"914":1}}],["更新日期",{"2":{"773":1}}],["更新后",{"2":{"394":1}}],["更新最新的",{"2":{"367":1}}],["更新独立域插件版本",{"2":{"244":1}}],["更新独立域插件版本为1",{"2":{"240":1,"242":1}}],["更新独立域插件版本1",{"2":{"225":1,"227":1}}],["更新压缩纹理工具使用方式",{"2":{"238":1}}],["更新启动插件1",{"2":{"111":1}}],["更新需手动删除assets",{"2":{"108":1}}],["更新适配插件1",{"2":{"81":1,"84":1,"102":1,"105":1}}],["更新适配插件为1",{"2":{"75":1}}],["更新适配插件版本到1",{"2":{"28":1,"42":1,"60":1,"62":1,"65":1,"67":1}}],["更新内容",{"2":{"75":1}}],["更新小游戏项目模板",{"2":{"319":1}}],["更新小游戏模板",{"2":{"288":1,"292":1}}],["更新小游戏模板捕获全局错误",{"2":{"26":1}}],["更新小游戏云测试profile获取的性能数据",{"2":{"54":1}}],["ngnix",{"2":{"982":1}}],["nsize",{"2":{"973":3}}],["n",{"2":{"622":1}}],["npm",{"2":{"575":1}}],["npot纹理无法使用压缩纹理",{"2":{"363":1}}],["npot",{"2":{"362":1}}],["native内存",{"2":{"728":1}}],["nativeallocated",{"2":{"717":1}}],["nativeunused",{"2":{"717":1}}],["native",{"2":{"717":3,"724":1}}],["nativereserverd",{"2":{"717":2}}],["native产生",{"2":{"717":1}}],["narrow",{"2":{"423":1}}],["name",{"2":{"374":1,"433":1,"451":2,"977":1}}],["namespace",{"2":{"23":1,"70":1,"259":1,"507":1,"512":1,"717":1,"727":1,"785":1,"871":1,"965":1,"968":1}}],["null",{"0":{"594":1},"2":{"412":3,"414":2,"415":2,"451":3,"576":1,"708":1,"926":1,"927":1,"973":3}}],["number",{"2":{"358":1,"591":1,"628":1,"629":1,"632":7,"633":1,"644":2,"645":1,"655":9,"659":6,"664":1,"667":9,"671":1,"676":9,"789":5,"792":5,"795":4,"798":16,"801":6,"826":2}}],["needinfo",{"2":{"979":2,"983":2}}],["needcheckupdate",{"2":{"353":1}}],["needcachetextures",{"2":{"353":1,"505":1,"900":1}}],["nextstoryline",{"2":{"622":2}}],["network",{"2":{"975":1,"979":1,"983":1,"1003":1}}],["networktime",{"2":{"798":1,"799":1}}],["net",{"2":{"471":1,"975":3}}],["net命名空间下的接口",{"0":{"470":1}}],["net8",{"2":{"6":1}}],["newstate",{"2":{"973":4}}],["newfile",{"2":{"383":1}}],["new",{"2":{"383":3,"426":2,"555":2,"602":1,"703":1,"707":1,"708":3,"825":3,"841":1,"897":1,"902":1,"943":2,"977":1,"979":3,"981":1,"983":2,"1005":2,"1073":2}}],["noneedrelease",{"2":{"521":1}}],["none",{"2":{"451":2,"591":2,"602":1,"628":1,"629":1,"667":11,"676":10,"681":1,"691":2,"942":1}}],["normalws",{"2":{"431":1}}],["normalreconstruction",{"2":{"430":1,"431":1}}],["noborder",{"2":{"423":1}}],["nodejs",{"2":{"805":2,"902":1}}],["node",{"0":{"390":1,"406":1},"2":{"374":1,"390":2,"406":5,"608":1,"805":2,"889":1,"902":3}}],["now以提升性能",{"2":{"180":1}}],["now替换performence",{"2":{"180":1}}],["no",{"2":{"71":1,"367":1,"423":1,"450":1}}],["not",{"0":{"481":1},"2":{"68":1,"76":1,"370":1,"570":1,"703":1,"971":6,"973":1,"1097":1}}],["3s",{"2":{"1123":2,"1124":1}}],["3之后的版本来构建你的游戏",{"2":{"1074":1}}],["3到1",{"2":{"1034":1}}],["3m",{"2":{"1000":1}}],["3m左右最佳",{"2":{"924":1}}],["3倍以上",{"2":{"869":1}}],["3d恐龙自由捕捉",{"2":{"852":1}}],["3d游戏进行转换",{"2":{"496":1}}],["3开始支持",{"2":{"808":1}}],["3g",{"2":{"1090":2}}],["3g左右",{"2":{"731":1}}],["3g或以上机型",{"2":{"711":1}}],["37ms",{"2":{"515":1}}],["375",{"2":{"421":1}}],["3版本起已经不再内置",{"2":{"479":1}}],["3版本unity支持",{"2":{"218":1}}],["3版本unity",{"2":{"205":1}}],["39",{"2":{"432":1,"532":1,"1001":1}}],["35",{"2":{"432":2,"905":1}}],["3个年限中部分版本",{"2":{"397":1}}],["36",{"2":{"367":1,"388":1,"905":1}}],["3内存",{"2":{"363":1}}],["3替换规则",{"2":{"216":1}}],["3unity在ios上网络报错",{"2":{"200":1}}],["3unity服务器错误且无跨域头导致报错",{"2":{"190":1}}],["30m",{"2":{"1014":1}}],["30mb",{"2":{"761":1,"1107":1,"1122":1}}],["30mb未压缩代码需300mb运行时编译内存",{"2":{"725":1}}],["30s",{"2":{"796":1,"1031":1}}],["300kb",{"2":{"873":1}}],["3000",{"2":{"790":1}}],["30000",{"2":{"785":1,"796":1}}],["300mb",{"2":{"724":1}}],["30",{"0":{"139":1,"191":1,"212":1,"271":1,"284":1,"340":1},"1":{"140":1,"192":1,"213":1,"272":1,"285":1,"286":1,"341":1,"342":1},"2":{"109":1,"580":1,"614":2,"628":1,"657":1,"747":1,"1005":2,"1123":1,"1124":1}}],["32位微信",{"2":{"727":1}}],["32",{"2":{"75":1,"392":1,"513":1,"515":2}}],["31普通模式unityaudio短音频适配问题",{"2":{"131":1}}],["31",{"0":{"112":1,"170":1,"210":1,"269":1,"322":1},"1":{"113":1,"171":1,"211":1,"270":1,"323":1,"324":1},"2":{"60":1}}],["34999",{"2":{"805":2,"902":2}}],["348",{"2":{"707":1}}],["34",{"2":{"42":1,"905":1,"1001":1}}],["33ms",{"2":{"532":1}}],["33",{"2":{"32":1,"905":1,"1032":1,"1036":1}}],["38",{"2":{"28":1,"432":2,"515":1}}],["3网络超时时间设置",{"2":{"27":1}}],["3",{"0":{"22":1,"24":1,"26":1,"74":1,"235":1,"237":1,"239":1,"241":1,"394":1,"405":1,"458":1,"472":1,"485":1,"498":1,"527":1,"609":1,"703":1,"704":1,"714":1,"717":1,"718":2,"719":1,"720":1,"727":1,"739":1,"740":1,"741":2,"745":1,"778":1,"779":1,"780":2,"781":1,"782":1,"875":1,"877":1,"882":1,"895":1,"921":1,"924":1,"925":1,"926":1,"927":1,"928":2,"932":1,"954":1,"957":1,"960":2,"963":1,"964":1,"965":1,"1095":1},"1":{"23":1,"25":1,"27":1,"75":1,"76":1,"236":1,"238":1,"240":1,"242":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"715":1,"716":1,"721":1,"722":1,"723":1,"926":1,"955":1,"956":1,"958":1,"959":1,"961":2,"962":2},"2":{"32":1,"57":1,"75":1,"108":1,"137":1,"353":1,"369":2,"388":3,"428":1,"429":2,"431":1,"433":2,"500":1,"513":1,"531":1,"580":1,"585":1,"697":1,"734":1,"760":2,"802":1,"809":1,"826":1,"874":1,"905":8,"907":1,"1074":1,"1076":2,"1082":1,"1112":2}}],["0系统出现",{"2":{"1097":1}}],["0系统bigunit64array兼容性问题",{"2":{"43":1}}],["0用户使用webgl2",{"2":{"1077":1}}],["0以上的shader难以降低",{"2":{"1076":1}}],["0f+py",{"2":{"1073":1}}],["0a",{"2":{"968":1}}],["0xffef",{"2":{"1004":1}}],["0xff00",{"2":{"1004":1}}],["0xfe4f",{"2":{"1004":1}}],["0xfe30",{"2":{"1004":1}}],["0xfe1f",{"2":{"1004":1}}],["0xfe10",{"2":{"1004":1}}],["0x22ff",{"2":{"1004":1}}],["0x2200",{"2":{"1004":1}}],["0x25ff",{"2":{"1004":1}}],["0x25a0",{"2":{"1004":1}}],["0x24ff",{"2":{"1004":1}}],["0x2460",{"2":{"1004":1}}],["0x21ff",{"2":{"1004":1}}],["0x2190",{"2":{"1004":1}}],["0x218f",{"2":{"1004":1}}],["0x2150",{"2":{"1004":1}}],["0x214f",{"2":{"1004":1}}],["0x2100",{"2":{"1004":1}}],["0x27bf",{"2":{"1004":1}}],["0x2700",{"2":{"1004":1}}],["0x26ff",{"2":{"1004":1}}],["0x2600",{"2":{"1004":1}}],["0x20cf",{"2":{"1004":1}}],["0x20a0",{"2":{"1004":1}}],["0x206f",{"2":{"1004":1}}],["0x2000",{"2":{"1004":1}}],["0x33ff",{"2":{"1004":1}}],["0x3300",{"2":{"1004":1}}],["0x32ff",{"2":{"1004":1}}],["0x3200",{"2":{"1004":1}}],["0x303f",{"2":{"1004":1}}],["0x3000",{"2":{"1004":1}}],["0x7f",{"2":{"1004":1}}],["0x0",{"2":{"1004":1}}],["0x9fff",{"2":{"1004":1}}],["0x4e00",{"2":{"1004":1}}],["0x432503",{"2":{"889":1}}],["0x801bd1",{"2":{"889":1}}],["0x13a062b",{"2":{"889":1}}],["0时使用gpu",{"2":{"751":1}}],["0时则会进一步拉大差距",{"2":{"734":1}}],["0渲染支持说明",{"0":{"1075":1},"1":{"1076":1,"1077":1,"1078":1,"1079":1,"1080":1,"1081":1},"2":{"750":1,"807":1}}],["0说明",{"0":{"750":1}}],["0相当于opengles3",{"2":{"734":1}}],["0相当于opengles2",{"2":{"734":1}}],["0级",{"2":{"581":1}}],["0~1之间的数值",{"2":{"644":1}}],["0~1",{"2":{"580":1,"655":1,"667":1,"676":1}}],["000000",{"2":{"580":1,"585":1}}],["000e426d34c788ac39ad82e1756813",{"2":{"499":1}}],["0支持处于beta测试阶段",{"2":{"498":1}}],["0的压缩纹理",{"2":{"250":1}}],["0模式下的gamma与linear颜色空间渲染",{"2":{"397":1}}],["0模式下",{"2":{"120":1,"125":2}}],["03",{"0":{"112":1},"1":{"113":1}}],["04",{"0":{"110":1,"126":1,"316":1},"1":{"111":1,"127":1,"128":1,"317":1}}],["06",{"0":{"88":1,"91":1,"93":1,"96":1,"98":1,"101":1,"279":1,"306":1,"340":1,"343":1,"349":1},"1":{"89":1,"90":1,"92":1,"94":1,"95":1,"97":1,"99":1,"100":1,"102":1,"103":1,"280":1,"281":1,"307":1,"341":1,"342":1,"344":1,"345":1,"346":1,"347":1,"348":1,"350":1},"2":{"369":1}}],["05",{"0":{"85":1,"104":1,"107":1,"314":1},"1":{"86":1,"87":1,"105":1,"106":1,"108":1,"109":1,"315":1},"2":{"773":1,"1016":2,"1105":1,"1111":1,"1129":2}}],["073",{"2":{"515":1}}],["07c160",{"2":{"421":1}}],["07",{"0":{"77":1,"80":1,"83":1,"85":1,"322":1,"325":1,"327":1,"329":1,"331":1,"333":1,"336":1,"338":1},"1":{"78":1,"79":1,"81":1,"82":1,"84":1,"86":1,"87":1,"323":1,"324":1,"326":1,"328":1,"330":1,"332":1,"334":1,"335":1,"337":1,"339":1},"2":{"947":1}}],["0检测",{"2":{"76":1}}],["01367b188873c923",{"2":{"435":1,"436":1}}],["01",{"0":{"63":1,"121":1,"123":1,"126":1,"320":1},"1":{"64":1,"65":1,"122":1,"124":1,"125":1,"127":1,"128":1,"321":1}}],["0基础库",{"2":{"57":1}}],["02",{"0":{"51":1,"114":1,"116":1,"118":1,"282":1,"318":1,"338":1},"1":{"52":1,"115":1,"117":1,"119":1,"120":1,"283":1,"319":1,"339":1}}],["02版本",{"2":{"25":1}}],["08",{"0":{"41":1,"66":1,"69":1,"72":1,"74":1,"314":1,"316":1,"318":1,"320":1},"1":{"42":1,"43":1,"67":1,"68":1,"70":1,"71":1,"73":1,"75":1,"76":1,"315":1,"317":1,"319":1,"321":1},"2":{"762":1,"773":1}}],["0不再限制需要ios",{"2":{"26":1}}],["0",{"0":{"385":1,"397":1,"807":2,"1068":1,"1070":1},"1":{"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"1069":1,"1071":1},"2":{"18":1,"26":1,"57":1,"62":1,"119":1,"131":1,"140":1,"153":1,"155":1,"158":1,"180":1,"202":1,"225":2,"227":1,"236":1,"240":1,"242":1,"259":1,"280":1,"313":1,"317":1,"319":1,"330":1,"334":1,"337":1,"348":1,"350":1,"353":2,"355":1,"367":1,"369":2,"374":3,"421":2,"429":1,"477":1,"498":2,"576":1,"580":3,"585":1,"599":2,"608":2,"632":1,"634":4,"644":1,"661":4,"668":2,"678":2,"701":2,"707":2,"708":1,"734":3,"752":1,"793":2,"798":1,"799":2,"802":1,"805":8,"807":15,"809":3,"813":1,"815":2,"817":2,"820":2,"825":1,"826":1,"899":1,"902":10,"926":1,"943":1,"973":1,"1001":2,"1005":4,"1012":2,"1063":1,"1073":2,"1076":4,"1077":3,"1093":1}}],["09",{"0":{"10":1,"61":1,"63":1,"295":1,"297":1,"299":1,"303":1,"306":1,"336":1},"1":{"11":1,"12":1,"62":1,"64":1,"65":1,"296":1,"298":1,"300":1,"301":1,"302":1,"304":1,"305":1,"307":1,"337":1}}],["兼容性测试",{"2":{"770":1}}],["兼容性问题",{"2":{"760":1,"1112":1}}],["兼容性",{"2":{"741":1}}],["兼容性评估",{"0":{"535":1},"2":{"534":1,"535":1}}],["兼容原理",{"0":{"366":1},"1":{"367":1}}],["兼容浏览器环境",{"2":{"256":1}}],["兼容ios",{"2":{"131":1}}],["兼容fmod2",{"2":{"25":1}}],["兼容playdelayed播放",{"2":{"25":1}}],["兼容windows",{"2":{"18":1}}],["兼容2022新增的音频api",{"2":{"11":1}}],["44",{"2":{"1126":1}}],["44572",{"2":{"889":1}}],["4出现若干渲染bug",{"2":{"1098":1}}],["496",{"2":{"727":1}}],["4g",{"2":{"711":1,"1124":1}}],["4s",{"2":{"532":1,"1123":1,"1124":2}}],["43",{"2":{"432":1}}],["4x4",{"2":{"393":2}}],["4年大部分机型",{"2":{"387":1}}],["403ms",{"2":{"532":1}}],["40",{"2":{"369":1,"1123":1,"1124":1}}],["414",{"2":{"707":1}}],["41",{"2":{"369":1,"527":2}}],["46ms",{"2":{"532":1}}],["463",{"2":{"532":1}}],["46",{"2":{"259":1}}],["4协议",{"2":{"109":1}}],["45",{"2":{"20":1,"423":2,"432":1}}],["4版本template问题",{"2":{"18":1}}],["4",{"0":{"17":1,"19":1,"22":1,"219":1,"221":1,"224":1,"226":1,"229":1,"231":1,"233":1,"395":1,"406":1,"459":1,"473":1,"486":1,"528":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1,"705":1,"719":1,"725":1,"726":1,"727":1,"728":2,"729":1,"730":1,"746":1,"781":1,"876":1,"880":1,"881":1,"882":1,"883":2,"896":1,"922":1,"930":1,"931":1,"932":1,"947":1,"948":1,"963":1,"1064":1,"1096":1},"1":{"18":1,"20":1,"21":1,"23":1,"220":1,"222":1,"223":1,"225":1,"227":1,"228":1,"230":1,"232":1,"234":1,"618":1,"619":1,"620":2,"621":3,"622":3,"623":2,"624":3,"625":3,"1065":1},"2":{"370":1,"388":1,"392":2,"405":2,"431":1,"500":1,"532":1,"760":1,"805":1,"812":1,"826":1,"902":1,"905":6,"949":1,"1012":1,"1082":1,"1097":2,"1112":1}}],["s7",{"2":{"1105":1,"1120":1}}],["ssl证书",{"0":{"986":1},"2":{"984":1,"985":1}}],["ssl等问题请参考文档网络通信适配",{"2":{"440":1}}],["sql统计分析",{"0":{"971":1}}],["sqlite",{"2":{"968":1}}],["safearea",{"2":{"1073":3}}],["safari",{"0":{"723":1}}],["sample",{"2":{"939":1}}],["split",{"2":{"1043":1}}],["spawnsomathing",{"2":{"927":1}}],["spec",{"2":{"820":2}}],["speccube1",{"2":{"431":2}}],["speccube0",{"2":{"431":2}}],["speedtree8passes",{"2":{"431":1}}],["speedtree7passes",{"2":{"431":1}}],["s的低网速玩家",{"2":{"873":1}}],["s",{"0":{"1039":1},"2":{"873":1,"1012":1,"1126":1}}],["skinning",{"2":{"1087":1}}],["skin",{"2":{"814":4}}],["skip",{"2":{"614":1,"621":2,"657":1,"931":1}}],["skipbutton",{"2":{"614":1,"621":7,"622":2}}],["skipclean",{"2":{"16":1}}],["s条件",{"2":{"769":1,"1109":1,"1121":1}}],["slg品类",{"2":{"845":1}}],["slg品类等",{"2":{"758":1,"1113":1}}],["slg",{"2":{"727":1,"1135":1}}],["slg等",{"2":{"387":1}}],["src",{"2":{"614":3,"618":4}}],["srp定制管线",{"2":{"808":1}}],["srp管线",{"2":{"808":1}}],["srp",{"2":{"431":1,"734":1,"808":3,"815":3}}],["sockets",{"2":{"975":1}}],["socket",{"2":{"539":1,"981":9,"985":1}}],["someprefab",{"2":{"927":6}}],["some",{"2":{"507":1,"512":1}}],["sounds",{"2":{"992":1,"997":2}}],["sound",{"2":{"124":1}}],["signature",{"2":{"1065":1}}],["simple",{"2":{"973":2}}],["simpledlmalloc",{"2":{"973":1}}],["simplelit",{"2":{"432":1,"811":1}}],["simplelitinput",{"2":{"431":1}}],["single",{"2":{"926":1}}],["size=xx",{"2":{"1003":1}}],["size的情况下设置的",{"2":{"707":2}}],["size",{"2":{"393":2,"515":1,"516":1,"526":1,"666":1,"707":1,"874":1,"970":1,"971":18,"973":2}}],["symbol",{"0":{"888":1},"1":{"889":1},"2":{"889":5,"1041":1}}],["symbols将产生函数id与函数名之间的映射关系",{"2":{"452":1}}],["symbols分离",{"2":{"280":1}}],["symbols优化",{"2":{"102":1}}],["symbols",{"0":{"452":1,"467":1},"2":{"20":1,"246":1,"358":4,"429":1,"435":1,"449":1,"450":1,"889":1}}],["system进行资源的按需加载",{"2":{"917":1}}],["system进行资源按需加载",{"0":{"916":1},"1":{"917":1,"918":1,"919":1,"920":1,"921":1,"922":1,"923":1,"924":1,"925":1,"926":1,"927":1,"928":1,"929":1,"930":1,"931":1,"932":1,"933":1,"934":1,"935":1,"936":1,"937":1,"938":1,"939":1},"2":{"878":1}}],["system或assetbundle进行资源按需加载",{"2":{"876":1}}],["system",{"0":{"408":1,"883":1,"919":1,"921":1},"1":{"409":1,"410":1},"2":{"383":2,"479":1,"490":1,"703":1,"919":1,"933":1,"939":1,"975":1,"979":1,"983":1,"995":1}}],["sum",{"2":{"971":18}}],["summary>",{"2":{"383":2,"521":8,"979":2,"983":2}}],["sure",{"2":{"932":1}}],["surface",{"2":{"431":1}}],["support",{"2":{"570":1}}],["subpackage",{"2":{"961":1,"962":1}}],["subpackages",{"2":{"380":1}}],["sublime",{"2":{"608":1}}],["subtractiveshadowcolor",{"2":{"431":1}}],["subtractdirectmainlightfromlightmap",{"2":{"431":1}}],["succeeded",{"2":{"930":1,"931":1,"934":1}}],["succeed",{"2":{"468":1}}],["successful",{"2":{"932":1}}],["success",{"2":{"374":2,"825":2,"994":2,"995":1}}],["such",{"2":{"71":1}}],["sendasync",{"2":{"981":2}}],["send",{"2":{"943":1,"983":2}}],["sendwebrequest",{"2":{"943":1,"945":1,"977":2,"995":1}}],["serializable",{"2":{"703":1,"995":1}}],["servicewechat",{"2":{"499":2}}],["server",{"2":{"374":2}}],["seek的使用案例",{"2":{"665":1}}],["seek0",{"2":{"635":3}}],["seek",{"0":{"635":1},"2":{"632":1,"635":5,"644":1}}],["selected",{"2":{"926":1}}],["select",{"2":{"428":1,"971":18}}],["section",{"0":{"1039":1},"2":{"1012":1}}],["sec单位",{"2":{"633":1,"645":1}}],["security",{"2":{"374":4}}],["sec",{"2":{"374":1,"622":2,"633":1,"634":1,"645":1,"646":1,"1126":1}}],["set",{"2":{"968":1}}],["setactive",{"2":{"707":2}}],["setpass",{"2":{"815":3}}],["setparam",{"0":{"663":1},"1":{"664":1,"665":1},"2":{"627":1,"635":5,"666":1}}],["setparamsizeandposition",{"0":{"666":1},"1":{"667":1,"668":1},"2":{"627":1,"666":1,"668":1}}],["setparams",{"2":{"614":2,"621":4,"634":1,"646":1,"657":1,"661":1}}],["setpositon",{"2":{"668":2}}],["setpercentage",{"0":{"599":1}}],["setpreloadlist",{"2":{"167":1,"994":3,"995":2}}],["setglobalvar",{"0":{"593":1,"604":1}}],["setstoragesync",{"2":{"576":1}}],["setevent",{"2":{"634":2,"646":2,"657":1,"661":1,"673":1,"678":2,"692":2}}],["setevents",{"2":{"622":3}}],["setenvironmentvariable",{"2":{"479":1}}],["setenabledebug",{"2":{"446":1,"459":1,"965":1}}],["setemptymainlightcascadeshadowmap",{"2":{"431":1}}],["setting中的scripting",{"2":{"492":1}}],["settings",{"2":{"392":1,"393":1,"429":4,"451":2,"452":2,"798":1}}],["settimeout",{"0":{"670":1},"1":{"671":1,"672":1,"673":1},"2":{"351":1,"627":1,"670":1,"673":1}}],["setconcurrent",{"2":{"323":1,"996":2}}],["setdatacdn",{"2":{"167":1,"956":2}}],["setrequestheader",{"2":{"16":2}}],["snsdyvideodownload",{"2":{"370":1}}],["snapshot支持",{"2":{"130":1}}],["shlacop",{"2":{"611":1,"612":1,"615":1}}],["shnpm",{"2":{"610":1}}],["shareticket",{"2":{"708":5}}],["shareappmessageoption",{"2":{"708":1}}],["shareappmessage",{"2":{"708":1}}],["share",{"2":{"708":2}}],["sharedcanvas",{"2":{"697":7,"701":1,"709":2}}],["shading",{"2":{"814":6}}],["shadowreceiverdepth",{"2":{"515":2}}],["shadowfade",{"2":{"431":1}}],["shadowbias",{"2":{"431":1}}],["shadow",{"2":{"430":1,"431":1,"811":1}}],["shader中添加instancing",{"2":{"1079":1}}],["shader中注释掉",{"2":{"812":1}}],["shaderfromserializedshader",{"2":{"971":1}}],["shaderlab",{"2":{"971":1}}],["shaderlibrary",{"2":{"429":2}}],["shader代码的",{"2":{"812":1}}],["shader代码",{"2":{"812":1}}],["shaders",{"2":{"493":1,"812":1}}],["shader半精度的利用率也有所提高",{"2":{"432":2}}],["shader",{"0":{"493":1},"2":{"427":1,"428":5,"429":16,"430":1,"431":6,"432":2,"433":4,"493":2,"807":1,"811":2,"812":2,"814":1,"971":2}}],["shapes",{"2":{"358":1}}],["showmodaloption",{"2":{"979":2,"983":1}}],["showmodal",{"2":{"979":2,"983":1}}],["showmonitorsuggestmodal",{"2":{"355":1}}],["showresultafterlaunch",{"2":{"785":1}}],["showgroupfriendsrank",{"2":{"708":1}}],["showfriendsrank",{"2":{"703":2,"707":1}}],["showopendata",{"0":{"701":1},"2":{"701":2,"707":2,"708":1,"709":3}}],["showtoastoption",{"2":{"602":1}}],["showtoast",{"2":{"591":2,"602":1}}],["showkeyboardoption",{"2":{"555":1}}],["showkeyboard",{"2":{"494":1,"555":3}}],["show",{"2":{"423":1,"708":1,"1005":2}}],["showall",{"2":{"423":1}}],["shortaudioplayer",{"2":{"300":1}}],["svn",{"2":{"140":1}}],["stencil",{"2":{"812":3}}],["step",{"2":{"624":1,"812":1}}],["step7",{"0":{"616":1}}],["step6",{"0":{"615":1}}],["step5",{"0":{"614":1},"2":{"616":1}}],["step4",{"0":{"613":1},"2":{"804":1}}],["step3",{"0":{"612":1},"2":{"614":1,"615":1,"804":1}}],["step2",{"0":{"611":1},"2":{"804":1}}],["step1",{"0":{"610":1},"2":{"804":1}}],["studio",{"2":{"713":1}}],["storing",{"2":{"932":1}}],["storylinex",{"2":{"678":1}}],["storyline",{"2":{"619":1,"624":2,"683":1,"688":1}}],["storage",{"2":{"490":1,"971":2}}],["stop",{"2":{"531":1}}],["style",{"2":{"421":3,"423":2,"426":1,"1005":3}}],["str",{"2":{"981":1}}],["stripping",{"2":{"874":1}}],["strip",{"2":{"874":1}}],["striping",{"0":{"480":1}}],["string>",{"2":{"708":1,"825":2,"995":1}}],["string",{"0":{"518":1,"519":2,"522":1,"593":2,"594":2,"595":1,"596":1,"604":2,"605":2},"2":{"353":13,"355":1,"356":3,"374":1,"384":3,"412":3,"414":3,"415":2,"417":2,"500":4,"591":1,"628":1,"632":3,"644":2,"655":1,"659":1,"664":2,"671":1,"676":2,"681":2,"686":2,"691":3,"703":3,"707":1,"708":4,"792":1,"798":3,"801":2,"825":4,"942":1,"981":2,"995":1}}],["strings",{"2":{"286":1}}],["stringify导致的浏览器告警",{"2":{"240":1}}],["streamassets目录找资源并填充到game",{"2":{"991":1}}],["streamwriter",{"2":{"383":2}}],["streamcdn",{"2":{"353":1}}],["streamingassetpath=",{"2":{"893":1}}],["streamingassetspath",{"2":{"942":1}}],["streamingassets目录",{"2":{"396":1}}],["streamingassets查找资源并填充到game",{"2":{"326":1}}],["streamingassets",{"0":{"439":1},"2":{"234":1,"435":1,"436":1,"505":1,"507":1,"513":3,"893":1,"992":2,"997":2}}],["streaming",{"2":{"355":1,"992":1}}],["streamingurlsubpath支持传自定义拼接到streamingcdn后面的路径",{"2":{"236":1}}],["stable",{"2":{"896":1}}],["stacktrace",{"2":{"451":4,"453":1}}],["stack",{"2":{"130":2}}],["started",{"2":{"887":1}}],["starttime",{"2":{"798":2}}],["startimg",{"2":{"624":1}}],["starting",{"2":{"612":1}}],["startgame",{"2":{"351":1,"533":2,"994":2}}],["start",{"2":{"127":1,"531":1,"533":1,"555":1,"778":1,"927":2,"930":1,"931":1,"932":1,"979":1,"983":3,"1093":1}}],["state",{"2":{"973":4}}],["static",{"2":{"942":1,"973":1}}],["stats性能面板",{"2":{"717":1}}],["statuscode",{"2":{"798":1,"994":2}}],["status",{"2":{"602":1,"926":1,"930":1,"931":1,"932":1,"934":1}}],["stat支持isdirectory和isfile",{"2":{"47":1}}],["stat",{"2":{"27":1}}],["still",{"2":{"71":1,"931":1}}],["scf",{"2":{"499":1}}],["scaler",{"2":{"707":2}}],["scale",{"2":{"707":2}}],["scaleheight",{"2":{"655":1,"667":1,"676":1}}],["scalewidth",{"2":{"655":1,"667":1,"676":1}}],["scaledscreenparams",{"2":{"431":1}}],["scalemode取值",{"2":{"423":1}}],["scalemode",{"2":{"421":1,"423":3}}],["scaling",{"2":{"431":1}}],["sceneid同启动场景上报分析",{"2":{"825":1}}],["sceneid",{"2":{"691":1,"692":2,"825":2}}],["scene999",{"2":{"515":1}}],["scene",{"2":{"428":2,"833":1,"926":3}}],["screen",{"2":{"707":4}}],["screenspaceocclusion",{"2":{"430":1,"431":1}}],["screenspaceshadows",{"2":{"430":1,"431":1}}],["screenadaptation",{"2":{"421":1,"423":1}}],["scriptreference",{"2":{"949":1}}],["scriptable",{"2":{"808":1}}],["scripting",{"2":{"429":1,"473":1}}],["scripts",{"2":{"355":1,"899":1}}],["scriptonly",{"2":{"355":1,"899":1}}],["sc",{"2":{"68":1,"76":1}}],["sdk方式提供给开发者",{"2":{"1134":1}}],["sdk以便开发者使用",{"2":{"945":1}}],["sdk功能",{"2":{"899":1}}],["sdk功能选项",{"2":{"893":1}}],["sdk帮助开发者快速对接平台能力",{"2":{"885":1}}],["sdk接口让开发者上报自定义启动阶段",{"2":{"822":1}}],["sdk的logmanagerxxx系列函数进行埋点上报",{"2":{"565":1}}],["sdk的文件api进行自行本地存储",{"2":{"490":1}}],["sdk中的wx",{"2":{"825":1}}],["sdk中的小游戏存储接口",{"2":{"472":1}}],["sdk中提供的方法来唤起输入法",{"2":{"555":1}}],["sdk实现文件存储",{"2":{"498":1}}],["sdk适配",{"2":{"498":1}}],["sdk适配或websocket通信替代",{"2":{"498":1}}],["sdk提供的playerpref进行存储",{"2":{"490":1}}],["sdk写法",{"2":{"473":1}}],["sdkname",{"2":{"424":1}}],["sdkoptions",{"0":{"354":1}}],["sdk支持api",{"2":{"130":1}}],["sdk支持文档注释",{"2":{"34":1}}],["sdkv1",{"2":{"108":1}}],["sdk",{"0":{"473":1,"1005":1},"1":{"1006":1,"1007":1,"1008":1,"1009":1,"1010":1,"1011":1},"2":{"0":1,"1":1,"108":3,"352":1,"374":2,"377":4,"383":2,"384":1,"386":1,"389":1,"394":1,"406":1,"426":4,"505":1,"543":1,"576":1,"582":1,"701":1,"707":1,"836":2,"839":1,"897":1,"922":2,"1005":2,"1010":1,"1074":2,"1136":1}}],["支持大部分第三方插件",{"2":{"1134":1}}],["支持大部分插件",{"2":{"498":1}}],["支持格式",{"2":{"1126":1}}],["支持如下形式的路径",{"2":{"992":1}}],["支持在",{"2":{"976":1}}],["支持本地图片和网络图片",{"2":{"959":1}}],["支持framedebugger调试",{"2":{"905":1}}],["支持fmod插件",{"2":{"498":1}}],["支持增强的profiler数据",{"2":{"902":1}}],["支持真机获取",{"2":{"739":1}}],["支持区分新老用户不同的播放内容",{"2":{"572":1}}],["支持jit",{"2":{"498":1,"736":1}}],["支持js构建模板",{"2":{"16":1}}],["支持标准lua与常见binding",{"2":{"498":1}}],["支持标准渲染管线",{"2":{"498":1}}],["支持动画",{"2":{"498":1}}],["支持的格式按需下载渲染",{"2":{"549":1}}],["支持的能力包括登录",{"2":{"543":1}}],["支持的bundle命名",{"2":{"513":1}}],["支持的",{"2":{"433":1}}],["支持移动端",{"2":{"427":1}}],["支持可序列化为json的任意数量的参数与返回值",{"2":{"424":1}}],["支持说明",{"0":{"397":1}}],["支持情况",{"2":{"392":1}}],["支持合并的文件为",{"2":{"380":1}}],["支持",{"2":{"372":1,"388":1,"392":7,"478":1,"487":1,"498":7,"829":1,"981":1}}],["支持版本",{"0":{"369":1}}],["支持一键全选",{"2":{"362":1}}],["支持游戏恢复到前台后自动播放",{"2":{"342":1}}],["支持文件二进制读写",{"2":{"328":1}}],["支持客服消息",{"2":{"311":1}}],["支持创建视频",{"2":{"309":1}}],["支持创建类时传入success等会回调",{"2":{"70":1}}],["支持导出时配置封面图",{"2":{"307":1}}],["支持配置key",{"2":{"304":1}}],["支持短音频的播放api",{"2":{"300":1}}],["支持以文件名全匹配的方式忽略缓存",{"2":{"259":1}}],["支持playerprefs优化",{"2":{"304":1}}],["支持pc端dxt5压缩纹理",{"2":{"248":1}}],["支持position和length参数",{"2":{"70":1}}],["支持自定义可缓存文件及可清理文件",{"2":{"199":1}}],["支持自定义启动封面样式",{"2":{"179":1}}],["支持自定义微信系统字体字符集",{"2":{"16":1}}],["支持小游戏inneraudio",{"2":{"147":1}}],["支持astc使用非4倍数尺寸",{"2":{"145":1}}],["支持指定node路径",{"2":{"137":1}}],["支持开通高性能模式的游戏禁止回退成普通模式运行",{"2":{"115":1}}],["支持webgl2",{"2":{"250":1}}],["支持wxassetbundle",{"2":{"108":1}}],["支持wasm生成external",{"2":{"102":1}}],["支持使用微信字体",{"2":{"108":1}}],["支持unity",{"2":{"102":1}}],["支持对首资源包进行brotli压缩",{"2":{"86":1}}],["支持通过接口在运行时动态修改预下载列表",{"2":{"993":1}}],["支持通过",{"2":{"70":1}}],["支持2022和团结引擎的",{"0":{"554":1}}],["支持2022",{"2":{"50":1}}],["agents",{"2":{"1087":1}}],["avoid",{"2":{"973":1}}],["avgloadingcount",{"2":{"798":1,"799":1}}],["atpanic",{"2":{"973":1}}],["at",{"2":{"889":5,"968":1}}],["atlas",{"2":{"813":1}}],["atlas版本被修改",{"2":{"12":1}}],["adintervals",{"2":{"1005":2}}],["adunitid",{"2":{"1005":2}}],["adressable",{"2":{"865":1}}],["adtype",{"2":{"824":1}}],["adtype=1",{"2":{"824":1}}],["adspacetype",{"2":{"824":1}}],["adspacetype=1",{"2":{"824":1}}],["added",{"0":{"1069":1,"1071":1},"2":{"1012":2}}],["address",{"2":{"979":1,"981":2,"983":1}}],["addressable也可使用",{"2":{"945":1}}],["addressable与assetbundle的对比",{"2":{"939":1}}],["addressable4",{"2":{"939":1}}],["addressable编译与部署",{"0":{"937":1}}],["addressable系统也能轻松做到",{"2":{"919":1}}],["addressable系统自动管理了所有复杂的依赖连接",{"2":{"919":1}}],["addressable系统不仅仅会帮你管理",{"2":{"919":1}}],["addressable不仅仅能记载资源",{"2":{"919":1}}],["addressable提供了以下能力",{"2":{"919":1}}],["addressable在小游戏中的应用",{"0":{"918":1},"1":{"919":1,"920":1,"921":1,"922":1}}],["addressable进行按需加载",{"2":{"891":1}}],["addressable进行资源加载",{"2":{"779":1}}],["addressables的catalog",{"2":{"799":1}}],["addressables的settings",{"2":{"799":1}}],["addressables",{"2":{"502":1,"883":1,"926":1,"930":1,"931":2,"932":1,"933":1,"934":1,"937":1,"939":1}}],["addressable",{"0":{"883":1},"2":{"498":1,"538":1,"712":1,"829":1,"917":1,"934":1,"939":1}}],["addfield",{"2":{"977":3}}],["additional",{"2":{"430":1,"431":1}}],["add",{"2":{"428":1,"433":1,"624":1,"678":1,"683":1,"688":1,"836":1}}],["a4",{"2":{"709":1}}],["a2",{"2":{"709":1}}],["a1",{"2":{"709":1}}],["a37m",{"2":{"532":1}}],["awakefromload",{"2":{"971":2}}],["awake阻塞",{"2":{"530":1,"875":1}}],["awake应足够少逻辑",{"2":{"530":1,"875":1}}],["await",{"2":{"374":1,"932":1}}],["aa包较大项目时生成的未压缩的",{"2":{"829":1}}],["aa包",{"0":{"829":1},"2":{"829":2,"922":1}}],["aa",{"0":{"831":1},"2":{"523":1,"538":1,"556":1,"557":1,"828":1,"829":4,"831":2,"833":2}}],["aac",{"2":{"367":1,"1126":1}}],["ai",{"2":{"498":1,"1087":1}}],["ambientocclusionparam",{"2":{"431":1}}],["amp",{"0":{"402":1,"559":1,"693":1},"1":{"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"560":1,"694":1,"695":1},"2":{"370":3,"615":1,"824":2,"1071":1,"1087":2,"1097":1}}],["archives",{"2":{"939":1}}],["article",{"2":{"499":1}}],["argumentexception",{"0":{"481":1}}],["args",{"2":{"424":1}}],["arraybuffer",{"2":{"902":1}}],["array",{"0":{"481":1},"2":{"380":1,"451":1,"813":1}}],["arrows",{"2":{"358":1}}],["after",{"2":{"420":1,"421":1,"422":1,"931":1,"958":1,"959":1}}],["aftercopydefault",{"2":{"383":2}}],["anchormin",{"2":{"1073":1}}],["analyze进行分析时",{"2":{"926":1}}],["analysis",{"2":{"805":1,"902":1}}],["animationclip",{"2":{"971":1}}],["animation",{"2":{"678":1,"1087":1}}],["anydata",{"2":{"576":1}}],["an",{"0":{"408":1},"1":{"409":1,"410":1},"2":{"931":1}}],["and",{"2":{"358":4,"902":1,"971":2}}],["android参考机型",{"2":{"1105":1,"1120":1}}],["android和ios收集完",{"2":{"1027":1}}],["android收集",{"0":{"1026":1},"2":{"1012":1}}],["android位于data",{"2":{"968":1}}],["android使用",{"2":{"967":1}}],["android或ios启动之后将使用",{"2":{"805":1}}],["android性能评测标准",{"0":{"764":1,"1115":1}}],["android与windows",{"2":{"736":1}}],["android机型的内存更为宽松",{"2":{"711":1}}],["android运行达到满帧较为流畅",{"0":{"485":1}}],["android",{"0":{"716":1,"1123":1},"2":{"351":1,"541":1,"548":1,"711":1,"713":1,"714":1,"731":1,"733":1,"739":1,"744":1,"748":1,"1031":1,"1094":1,"1097":1}}],["android会生成一份xxx",{"2":{"351":1}}],["a",{"0":{"402":1,"559":1,"693":1},"1":{"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"560":1,"694":1,"695":1},"2":{"392":1,"393":1,"466":1,"615":1,"703":1,"931":1}}],["activity",{"2":{"715":1}}],["action=show",{"2":{"708":1}}],["action",{"0":{"520":2,"521":2,"522":2,"602":1,"603":1},"2":{"127":1,"412":1,"414":1,"415":1,"417":1,"500":6,"708":1,"979":1,"983":1}}],["accesses",{"2":{"451":1}}],["access",{"2":{"370":1,"1095":1}}],["always",{"2":{"873":1}}],["alloc",{"2":{"968":2,"971":18,"973":2}}],["allow",{"2":{"370":1}}],["allowed",{"2":{"370":1,"745":1}}],["all",{"2":{"423":1,"715":1}}],["alpha",{"2":{"392":1,"431":1}}],["alphanumerics",{"2":{"358":1}}],["as",{"2":{"943":1,"945":1}}],["assumeuniformscaling",{"2":{"1079":1}}],["assume",{"2":{"431":1}}],["asset相关配置",{"0":{"991":1}}],["assetreference",{"2":{"927":2}}],["asset支持的配置",{"0":{"898":1},"1":{"899":1,"900":1}}],["asset配置",{"2":{"897":1}}],["assetcontentlength超过15",{"2":{"790":1}}],["assetcontentlength",{"2":{"789":1}}],["assetloadcost",{"2":{"789":1}}],["assetloadtype",{"2":{"353":1,"899":1,"961":1}}],["assetimporterbak读取选中资源的importer设置并还原后",{"2":{"362":1}}],["assetimporterbak",{"2":{"362":2}}],["assetstore",{"2":{"881":1,"882":1,"981":1}}],["assetstudio",{"0":{"880":1},"2":{"880":1}}],["assetsbundle迁移",{"0":{"935":1}}],["assetsbundle生成的文件",{"2":{"865":1}}],["assetsbundle缓存适配插件已自动支持",{"2":{"498":1}}],["assetsurl",{"2":{"353":1}}],["assets",{"0":{"438":1,"883":1,"916":1,"919":1,"921":1},"1":{"917":1,"918":1,"919":1,"920":1,"921":1,"922":1,"923":1,"924":1,"925":1,"926":1,"927":1,"928":1,"929":1,"930":1,"931":1,"932":1,"933":1,"934":1,"935":1,"936":1,"937":1,"938":1,"939":1},"2":{"352":1,"355":1,"377":4,"383":2,"384":1,"396":1,"406":1,"435":1,"436":1,"505":1,"576":1,"582":1,"839":1,"876":1,"878":1,"897":1,"917":1,"919":1,"926":1,"1005":1}}],["asset增加不常用配置入口",{"2":{"218":1}}],["assetbundleloadfromstreamasyncoperation",{"2":{"971":1}}],["assetbundleloadfromstream",{"2":{"971":1}}],["assetbundle内存分析",{"0":{"946":1},"1":{"947":1,"948":1}}],["assetbundle目前只支持异步加载",{"2":{"945":1}}],["assetbundle下载",{"0":{"943":1}}],["assetbundle打包参数建议",{"0":{"942":1}}],["assetbundle使用方式",{"2":{"944":2}}],["assetbundle使用",{"0":{"941":1},"1":{"942":1,"943":1}}],["assetbundle使用时被解压占用unity",{"2":{"728":1}}],["assetbundle无需再使用本地文件系统缓存和版本更新",{"2":{"831":1}}],["assetbundle按需加载",{"2":{"728":1}}],["assetbundle",{"0":{"940":1},"1":{"941":1,"942":1,"943":1,"944":1,"945":1,"946":1,"947":1,"948":1,"949":1},"2":{"538":1,"779":1,"829":1,"831":2,"943":4,"945":3,"949":2,"971":9}}],["assetbundle网络异步加载",{"2":{"498":1}}],["assetbundle和addressables资源目录",{"2":{"439":1}}],["assetbundles",{"2":{"435":1,"942":1}}],["assetbundle重试失败问题",{"2":{"274":1}}],["assetbundle以减少内存使用",{"2":{"108":1}}],["assetbundle返回null",{"2":{"65":1}}],["asset",{"0":{"352":1,"882":1},"1":{"353":1,"354":1,"355":1,"356":1,"357":1,"358":1},"2":{"86":1,"137":1,"352":1,"505":1,"882":1,"931":1,"935":1,"939":1,"949":2}}],["asyncoperationstatus",{"2":{"930":1,"931":1,"934":1}}],["asyncoperationhandle",{"2":{"930":2,"931":1,"932":1}}],["async",{"2":{"374":1,"926":1,"932":1}}],["astc8",{"2":{"813":1}}],["astc88",{"2":{"813":1}}],["astc44",{"2":{"813":1}}],["astc压缩",{"2":{"813":1}}],["astc格式资源",{"2":{"395":1}}],["astc格式配置说明",{"0":{"393":1}}],["astc能支持最近3",{"2":{"387":1}}],["astc",{"2":{"356":1,"386":1,"387":1,"388":1,"392":1,"393":3,"395":1,"405":3,"905":10}}],["ab内存文件释放",{"2":{"948":1}}],["ab内存文件",{"2":{"948":2}}],["abort",{"2":{"889":1}}],["abort相关逻辑",{"2":{"567":1}}],["ab分包方式载入",{"2":{"833":1}}],["abc",{"2":{"634":1,"646":1}}],["abc123",{"2":{"380":1}}],["ability",{"2":{"490":2,"708":1}}],["ab包打包到",{"2":{"992":1}}],["ab包后",{"2":{"829":1}}],["ab包",{"0":{"829":1},"2":{"391":1,"829":2,"833":1}}],["ab",{"0":{"831":1},"2":{"356":1,"538":1,"556":1,"557":1,"828":1,"829":4,"831":2,"833":1,"943":6}}],["app包",{"2":{"814":1}}],["appendhashtocatalog=false",{"2":{"799":1}}],["appendhashtocatalog",{"2":{"798":1}}],["appendhashtoassetbundlename",{"2":{"510":1,"523":1,"942":2}}],["app的运行性能差异",{"0":{"734":1}}],["appstate",{"2":{"523":1}}],["application",{"2":{"488":1,"942":1}}],["applications",{"2":{"410":2,"805":2,"902":2}}],["app",{"0":{"456":1,"831":1,"832":1,"833":1},"2":{"373":1,"410":2,"433":1,"538":1,"546":1,"557":2,"805":1,"818":1,"828":1,"829":1,"831":1}}],["appid信息展示",{"2":{"1069":1}}],["appid",{"2":{"353":1,"523":1,"613":1,"899":1}}],["appbrand1",{"2":{"714":1}}],["appbrand",{"2":{"351":1}}],["api进行渲染",{"2":{"734":1}}],["api速查",{"0":{"626":1},"1":{"627":1,"628":1,"629":1,"630":1,"631":1,"632":1,"633":1,"634":1,"635":1,"636":1,"637":1,"638":1,"639":1,"640":1,"641":1,"642":1,"643":1,"644":1,"645":1,"646":1,"647":1,"648":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1,"660":1,"661":1,"662":1,"663":1,"664":1,"665":1,"666":1,"667":1,"668":1,"669":1,"670":1,"671":1,"672":1,"673":1,"674":1,"675":1,"676":1,"677":1,"678":1,"679":1,"680":1,"681":1,"682":1,"683":1,"684":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1},"2":{"620":1}}],["api执行环境说明",{"0":{"582":1}}],["api描述",{"2":{"581":1}}],["api",{"0":{"583":1,"597":1,"1005":1,"1009":1},"1":{"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"1006":1,"1007":1,"1008":1,"1009":1,"1010":1,"1011":1},"2":{"368":1,"370":1,"374":2,"411":1,"429":13,"494":1,"543":2,"697":1,"705":1,"707":1,"712":1,"949":1,"973":2,"977":1,"979":1,"983":1,"993":1,"994":2,"995":1,"1005":4,"1007":1,"1009":1,"1010":1,"1076":1}}],["api协议更新至3",{"2":{"62":1}}],["api接口更新",{"2":{"5":1}}],["autoplay",{"2":{"632":1,"634":1,"644":1,"646":1}}],["autoprofile",{"2":{"355":1,"899":1}}],["autostreaming等功能",{"2":{"905":1}}],["autostreaming等支持",{"2":{"905":1}}],["autostreaming",{"0":{"556":1},"1":{"557":1,"558":1,"559":1,"560":1},"2":{"556":1,"560":1}}],["autostreaming自动配置与上传",{"2":{"94":1}}],["autoadaptscreen",{"2":{"355":1}}],["autoconnection",{"2":{"805":1}}],["autoconnect",{"2":{"355":1,"899":1,"902":1}}],["audio音频是否需要使用小游戏音频适配",{"0":{"489":1}}],["audio",{"2":{"435":1,"646":4,"648":1,"651":1}}],["audio能力适配",{"2":{"266":1,"268":1}}],["audio压缩纹理",{"2":{"147":1}}],["implemented",{"2":{"1097":1}}],["impport",{"0":{"1039":1},"2":{"1012":1}}],["import包失败错误",{"2":{"1055":1}}],["import",{"2":{"1010":1}}],["image1",{"2":{"947":1}}],["imageurl",{"2":{"708":1}}],["images",{"2":{"421":1,"423":2}}],["image",{"2":{"420":1,"421":1,"422":1,"621":1,"657":3,"668":2,"708":1,"958":1,"959":1}}],["its",{"2":{"931":1}}],["ienumerator",{"2":{"926":1,"927":1,"931":1,"977":2,"995":1}}],["iwrongframe",{"2":{"801":1}}],["ibaserequestinfo",{"2":{"798":2}}],["ip",{"2":{"805":1,"902":2,"975":1,"983":1}}],["ipointerexithandler",{"2":{"555":1}}],["ipointerclickhandler",{"2":{"555":1}}],["ipreprocessbuildwithreport",{"2":{"479":1}}],["iphone7",{"2":{"1105":1,"1120":1}}],["iphone11",{"2":{"1105":1,"1120":1}}],["iphone11等ram",{"2":{"711":1}}],["iphone13",{"2":{"1105":1,"1120":1}}],["iphonex",{"2":{"711":1,"1090":1}}],["iphone",{"2":{"432":2,"707":1}}],["ip链路",{"2":{"407":1}}],["icon",{"2":{"591":2,"602":1}}],["icon图片",{"2":{"421":1}}],["iconimage",{"2":{"421":1,"423":1}}],["iconconfig",{"2":{"421":1}}],["io",{"2":{"383":1,"1133":1}}],["ios参考机型",{"2":{"1105":1,"1120":1}}],["ios浏览器webkit",{"2":{"1097":1}}],["ioshighperformance",{"2":{"1088":1}}],["ios降低drawmeshinstanced的参数matrices",{"2":{"1080":1}}],["ios普通模式无法进入游戏",{"2":{"1063":1}}],["ios收集",{"0":{"1026":1},"2":{"1012":1,"1019":1}}],["ios微信客户端版本",{"2":{"1001":1}}],["ios为例",{"2":{"817":1}}],["ios包",{"2":{"814":1}}],["ios平台callmaincost",{"2":{"790":1}}],["ios使用高性能模式",{"2":{"782":1}}],["ios开启高性能+模式",{"2":{"781":1}}],["ios性能评测标准",{"0":{"763":1,"1114":1}}],["ios性能差",{"0":{"485":1}}],["ios默认为普通模式",{"2":{"736":1}}],["ios测试内存务必使用代码分包",{"2":{"731":1}}],["ios测试内存务必不要开启development",{"2":{"731":1}}],["ios设备应以紫色的xcodememory为准",{"2":{"716":1}}],["ios低档机为iphone",{"2":{"711":1}}],["ios系统需14",{"2":{"498":1}}],["iosautogcinterval",{"2":{"355":1}}],["iosautogcinterval调整间隔",{"2":{"86":1}}],["ios限制固定的分辨率",{"2":{"353":1}}],["iosdevicepixelratio",{"2":{"353":1}}],["ios不支持webgl2时提示",{"2":{"236":1}}],["ios高性能使用webgl2会存在较多问题",{"2":{"1078":1}}],["ios高性能内存优化",{"2":{"1069":1}}],["ios高性能加载子包代码时会卡顿",{"2":{"795":1}}],["ios高性能模式drawmeshinstanced显示错乱",{"0":{"1080":1}}],["ios高性能模式开启gpu",{"0":{"1079":1}}],["ios高性能模式收集",{"2":{"796":1}}],["ios高性能模式",{"2":{"540":1}}],["ios高性能模式自动gc间隔",{"2":{"355":1}}],["ios高性能模式自动gc策略",{"2":{"86":1}}],["ios高性能模式2",{"2":{"130":1}}],["ios高性能模式下",{"2":{"122":1}}],["ios高性能最低支持版本调整",{"2":{"95":1}}],["ios",{"0":{"715":1,"716":1,"723":2,"1037":1,"1038":1,"1039":1,"1082":1,"1095":1,"1101":1,"1124":1},"1":{"1083":1,"1084":1,"1085":1,"1086":1,"1087":1,"1088":1,"1089":1,"1090":1,"1091":1,"1092":1,"1093":1,"1094":1,"1095":1,"1096":1,"1097":1,"1098":1,"1099":1,"1100":1,"1101":1},"2":{"43":1,"57":1,"367":3,"369":2,"370":5,"540":2,"541":1,"711":1,"712":1,"714":1,"731":2,"733":1,"748":1,"760":2,"781":1,"782":1,"812":1,"817":1,"905":1,"1012":3,"1015":2,"1031":3,"1037":1,"1038":1,"1079":1,"1080":1,"1082":2,"1083":1,"1087":1,"1088":2,"1090":1,"1093":1,"1097":1,"1100":1,"1112":1}}],["iosperformanceplus",{"2":{"31":1}}],["if语句比较短小",{"2":{"812":1}}],["ifndef",{"2":{"429":2}}],["if",{"0":{"685":1},"1":{"686":1,"687":1,"688":1},"2":{"374":1,"409":1,"414":1,"429":4,"479":1,"507":1,"512":2,"555":4,"576":1,"591":1,"627":1,"688":2,"703":2,"708":1,"812":3,"826":6,"902":1,"930":1,"931":3,"934":2,"942":1,"943":2,"945":1,"973":2,"977":2,"981":1,"994":2,"995":1}}],["il2cpp",{"2":{"971":2}}],["il2cppmetadata",{"2":{"873":1}}],["il2cppcore",{"0":{"479":2}}],["il2cppoptimizesize",{"2":{"355":1}}],["il2cpp默认选项更改为size减少代码包体",{"2":{"164":1}}],["istrusted",{"2":{"1082":1}}],["istrue",{"2":{"687":1,"688":1}}],["isnetworkerror",{"2":{"977":2}}],["isnullorempty",{"2":{"708":1}}],["isolatedcontext",{"2":{"952":1}}],["ishttperror||webrequest",{"2":{"977":2}}],["ishttperror",{"2":{"943":2,"945":1}}],["ishighperformance",{"2":{"826":1}}],["isdone",{"2":{"926":1,"927":1,"931":2,"934":1,"977":1}}],["isvisible",{"2":{"826":1}}],["isprivatemessage",{"2":{"708":1}}],["isfalse",{"2":{"687":1,"688":1}}],["isfocused",{"2":{"555":2}}],["iserasablefile",{"2":{"512":1}}],["iscacheablefile",{"2":{"507":1}}],["iscontentok",{"2":{"374":3}}],["issue",{"0":{"562":1},"2":{"562":1}}],["issue和",{"2":{"561":1}}],["issues",{"2":{"481":1}}],["isshowkeyboard",{"2":{"555":5}}],["isstopped",{"2":{"124":1}}],["is",{"0":{"1039":1},"2":{"370":1,"703":1,"930":1,"931":2,"932":2,"983":1,"1012":1}}],["isreadfromcache",{"2":{"798":1}}],["isreadable",{"2":{"362":1}}],["isreportablehttperror",{"2":{"70":1}}],["id",{"2":{"451":1,"889":2}}],["ide",{"2":{"618":1}}],["identifier",{"2":{"507":2,"512":2}}],["identifier始终返回正整数",{"2":{"122":1}}],["ideographs",{"2":{"358":1}}],["id在特定情况丢失",{"2":{"12":1}}],["include",{"2":{"973":1}}],["include的shader",{"2":{"873":1}}],["includes",{"2":{"507":2,"512":1}}],["instntiate",{"2":{"1087":1}}],["instead",{"2":{"973":1}}],["instrument查看webcontent进程内存是否在安全范围",{"2":{"731":1}}],["instruments",{"0":{"715":1},"2":{"731":1}}],["instrument",{"2":{"713":1}}],["install",{"2":{"610":1}}],["instance特性或合批处理",{"2":{"1079":1}}],["instanceof",{"2":{"981":1}}],["instance",{"0":{"1079":1},"2":{"981":1,"1079":1}}],["instancing提高渲染性能",{"2":{"1076":1}}],["instancing等",{"2":{"807":1}}],["instancing",{"2":{"431":1,"807":1,"815":1}}],["instantiateasync",{"2":{"927":2}}],["instantiate",{"2":{"927":2}}],["instantcing",{"2":{"734":1,"751":1}}],["instantgame增强了unity",{"2":{"907":1}}],["instantgame增加了压缩纹理",{"2":{"907":1}}],["instantgame是对特定正式版本的增强",{"2":{"907":1}}],["instantgame版本目前是在2019",{"2":{"905":1}}],["instantgame版本增强的profiler功能",{"2":{"719":1}}],["instantgame",{"0":{"906":1},"2":{"558":1,"905":2,"907":1}}],["instant",{"0":{"829":1},"2":{"538":1,"557":3,"828":1,"829":5,"831":1,"832":1}}],["inerasableidentifier",{"2":{"512":2}}],["info",{"2":{"512":3,"576":1,"591":4,"753":1,"971":2,"1073":7}}],["invalid",{"0":{"493":1}}],["index",{"0":{"493":1},"2":{"374":1,"435":1,"614":1,"618":1,"883":1}}],["introduction",{"2":{"949":2}}],["interface",{"2":{"591":1,"798":1,"826":1}}],["interaction",{"0":{"491":1}}],["interpolated",{"2":{"286":1}}],["int",{"0":{"521":1},"2":{"353":8,"355":1,"356":1,"374":1,"479":1,"500":1,"707":6,"825":2,"979":1,"983":1,"1005":1,"1074":1}}],["inneraudio支持持久化文件存储",{"2":{"158":1}}],["inneraudio播放音频中文文件名修复",{"2":{"131":1}}],["inneraudio",{"2":{"103":1}}],["in",{"0":{"491":1,"493":1,"715":1},"2":{"68":1,"76":1,"246":1,"428":2,"612":1,"712":1,"731":1,"734":1,"949":2}}],["inputfield>",{"2":{"555":1}}],["inputfield",{"2":{"555":8}}],["input",{"0":{"554":1},"2":{"50":1,"268":1,"429":1}}],["initsdk",{"2":{"968":1,"979":2,"983":2,"1005":1,"1074":1}}],["initwebglplayer主要函数",{"2":{"532":1}}],["initializeil2cppfrommain",{"2":{"532":2}}],["inittext",{"2":{"421":1,"423":1,"959":1}}],["init",{"2":{"3":1,"374":2}}],["5m",{"2":{"1122":2}}],["5mb",{"2":{"761":2,"793":1,"1107":2}}],["540",{"2":{"1126":1}}],["5403162",{"2":{"947":1}}],["54998",{"2":{"902":2}}],["5基础上",{"2":{"905":1}}],["5g上限还有较大差距就突然崩溃",{"2":{"731":1}}],["5g",{"2":{"711":1,"1090":1,"1123":1}}],["5f9144af9f0e32d50fb878e5256d669fa1ae6fdec77550849bfee137be995d18",{"2":{"708":1}}],["5s",{"2":{"634":1,"646":1,"802":1,"1123":2,"1124":2}}],["5个属性",{"2":{"629":1}}],["5b9ef7d7",{"2":{"515":1}}],["5以上",{"2":{"498":1}}],["5以上音频退后台无法恢复",{"2":{"6":1}}],["593",{"2":{"889":1}}],["59",{"2":{"432":5}}],["5x5",{"2":{"393":1}}],["525ms",{"2":{"532":1}}],["52",{"2":{"380":1,"515":1}}],["512",{"2":{"813":1}}],["51",{"2":{"240":1,"367":1,"432":2,"614":1}}],["53",{"2":{"236":1,"515":1}}],["58",{"2":{"227":1}}],["58版本插件ios报错",{"2":{"225":1}}],["5导致特性开关和分包patch逻辑失效",{"2":{"133":1}}],["50万面",{"2":{"814":1}}],["5000",{"2":{"802":1}}],["50",{"2":{"16":1,"242":1,"432":2,"532":1,"629":1,"678":1,"1032":2,"1036":2,"1037":1,"1123":1,"1124":1}}],["5",{"0":{"13":1,"15":1,"26":1,"210":1,"212":1,"214":1,"217":1,"396":1,"407":1,"460":1,"474":1,"487":1,"529":1,"626":1,"706":1,"707":1,"708":1,"720":1,"729":1,"747":1,"782":1,"934":1,"935":1,"964":1,"1062":1,"1097":1},"1":{"14":1,"16":1,"27":1,"211":1,"213":1,"215":1,"216":1,"218":1,"627":1,"628":1,"629":1,"630":1,"631":1,"632":1,"633":1,"634":1,"635":1,"636":1,"637":1,"638":1,"639":1,"640":1,"641":1,"642":1,"643":1,"644":1,"645":1,"646":1,"647":1,"648":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1,"660":1,"661":1,"662":1,"663":1,"664":1,"665":1,"666":1,"667":1,"668":1,"669":1,"670":1,"671":1,"672":1,"673":1,"674":1,"675":1,"676":1,"677":1,"678":1,"679":1,"680":1,"681":1,"682":1,"683":1,"684":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1,"707":1,"708":1,"721":1,"722":1,"723":1,"1063":1},"2":{"105":1,"135":1,"367":1,"432":2,"500":1,"614":2,"634":1,"646":1,"668":1,"735":1,"760":1,"793":1,"799":1,"813":1,"817":1,"826":1,"829":1,"905":1,"1012":1,"1082":1,"1112":1}}],["5暂停音频无法恢复的bug",{"2":{"12":1}}],["临时兼容wk",{"2":{"12":1}}],["7s",{"2":{"1123":1}}],["7mb",{"2":{"971":1}}],["750",{"2":{"1126":1}}],["75",{"2":{"1036":1,"1077":1}}],["751427a66d22b184c95342d556354150",{"2":{"947":1}}],["75ms",{"2":{"532":1}}],["768",{"2":{"727":1}}],["7p",{"2":{"711":1,"1090":1}}],["79ms",{"2":{"515":1}}],["741",{"2":{"481":1}}],["72",{"2":{"432":1}}],["720",{"2":{"423":2}}],["70mb",{"2":{"724":1}}],["70",{"2":{"432":2,"532":1,"599":1}}],["78kb",{"2":{"515":1}}],["78",{"2":{"423":1}}],["7",{"0":{"10":1,"98":1,"136":1,"168":1,"181":1,"183":1,"187":1,"189":1,"206":1,"239":1,"241":1,"267":1,"462":1,"476":1,"489":1,"749":1,"1099":1},"1":{"11":1,"12":1,"99":1,"100":1,"137":1,"138":1,"169":1,"182":1,"184":1,"185":1,"186":1,"188":1,"190":1,"207":1,"240":1,"242":1,"268":1},"2":{"479":2,"711":1,"799":1,"1082":1,"1090":1,"1097":1}}],["去掉了",{"2":{"431":1}}],["去掉",{"2":{"431":2}}],["去调",{"2":{"430":1}}],["去",{"2":{"9":1}}],["严重卡顿",{"2":{"581":1}}],["严重",{"2":{"9":1,"43":2}}],["自选cdn",{"2":{"829":1}}],["自然right也就=0",{"2":{"629":1}}],["自行维护asset的引用计数管理资源",{"2":{"948":1}}],["自行管理的本地缓存",{"2":{"576":1}}],["自行创建该目录内容",{"2":{"377":1}}],["自助完成",{"2":{"552":1}}],["自己写的",{"2":{"431":1}}],["自带的",{"2":{"431":1,"493":1}}],["自带",{"2":{"408":1}}],["自建后端服务",{"0":{"373":1}}],["自建后端",{"2":{"372":1}}],["自定义assetbundle名中hash长度用于缓存控制",{"2":{"893":1}}],["自定义上报指标json字符串",{"2":{"691":1}}],["自定义上报维度json字符串",{"2":{"691":1}}],["自定义上报场景id",{"2":{"691":1}}],["自定义上报分析",{"0":{"578":1}}],["自定义sdk调用",{"0":{"424":1},"1":{"425":1,"426":1}}],["自定义模板",{"2":{"380":1,"384":2}}],["自定义",{"2":{"356":1}}],["自定义bundle文件名中hash部分长度",{"2":{"353":1}}],["自定义bundle名中hash长度",{"2":{"290":1}}],["自定义需缓存的路径标识符",{"2":{"290":1}}],["自定义环境报错",{"2":{"3":1}}],["自动连接到",{"2":{"805":1,"902":1}}],["自动缓存",{"2":{"515":1}}],["自动预览",{"2":{"458":1}}],["自动减半根据当前纹理尺寸",{"2":{"362":1}}],["自动从导出目录webgl",{"2":{"326":1}}],["自动清理存量旧文件",{"2":{"259":1}}],["自动调节dpr属性",{"2":{"8":1}}],["云测试服务是一套完整易用的在线测试服务",{"2":{"770":1}}],["云测试批量测试数据",{"2":{"762":1}}],["云测试设置ui框架导致editor运行错误",{"2":{"344":1}}],["云端安装依赖",{"2":{"374":1}}],["云函数可以同时存在多个环境",{"2":{"374":1}}],["云函数可以和前端的游戏逻辑独立创建为不同的项目",{"2":{"374":1}}],["云函数",{"2":{"374":1}}],["云托管支持",{"2":{"5":1}}],["云开发有一个基本的免费套餐",{"2":{"374":1}}],["云开发可以降低运维",{"2":{"372":1}}],["云开发",{"0":{"374":1},"2":{"5":1,"372":1}}],["8s",{"2":{"1123":1,"1124":1}}],["85",{"2":{"1077":1}}],["800",{"2":{"1126":1}}],["800mb",{"2":{"1124":1}}],["8009c16fcab3",{"2":{"939":1}}],["80",{"2":{"905":3}}],["84",{"2":{"887":1}}],["8162",{"2":{"881":1}}],["815ms",{"2":{"532":1}}],["8p",{"2":{"711":1,"1090":1}}],["8等ram",{"2":{"711":1}}],["896",{"2":{"707":1}}],["8ms",{"2":{"532":1}}],["8d265a9dfd6cb7669cdb8b726f0afb1e",{"2":{"510":3,"512":1,"513":4,"992":1,"997":1}}],["8848",{"2":{"979":1,"983":1}}],["88",{"2":{"432":1}}],["87",{"2":{"432":1}}],["87014",{"2":{"374":1}}],["8x8",{"2":{"393":2}}],["8",{"0":{"4":1,"7":1,"165":1,"170":1,"172":1,"174":1,"176":1,"178":1,"203":1,"308":1,"310":1,"312":1,"463":1,"477":1,"490":1,"750":1,"1058":1,"1100":1},"1":{"5":1,"6":1,"8":1,"9":1,"166":1,"167":1,"171":1,"173":1,"175":1,"177":1,"179":1,"180":1,"204":1,"205":1,"309":1,"311":1,"313":1,"1059":1},"2":{"131":1,"202":1,"367":1,"369":2,"392":3,"432":7,"813":1,"1001":2,"1012":1,"1082":1,"1090":1,"1105":1,"1120":1}}],["c同一目录",{"2":{"973":1}}],["c添加到xlua虚拟机源码目录下参与编译",{"2":{"973":1}}],["c原生代码内存",{"2":{"724":1}}],["ctrl",{"2":{"615":1}}],["ccd",{"2":{"557":1}}],["cdb8b726f0afb1e8d265a9dfd6cb7669",{"2":{"513":2}}],["cdn是以path1为根路径上传到服务器的cdn地址",{"2":{"992":1}}],["cdn字段",{"2":{"962":1}}],["cdn地址",{"2":{"955":1}}],["cdn管理后端针对首资源包",{"2":{"873":1}}],["cdn配置",{"2":{"797":1,"956":1}}],["cdn配置和请求url是否匹配",{"2":{"527":1}}],["cdn必须开启brotli或gzip压缩",{"2":{"778":1}}],["cdn使用gzip压缩",{"2":{"759":2,"1106":2,"1120":2}}],["cdn视频资源播放失败等",{"2":{"589":1}}],["cdn不一致",{"2":{"527":1}}],["cdn部分",{"2":{"527":1}}],["cdn部分后作为缓存路径",{"2":{"513":1}}],["cdn时",{"2":{"523":1}}],["cdn=https",{"2":{"513":1}}],["cdn根目录的情况",{"2":{"353":1}}],["cdn和首包资源文件名的路径",{"2":{"353":1}}],["cdn",{"2":{"353":1,"396":1,"437":1,"513":1,"523":1,"540":1,"549":1,"557":1,"618":1,"828":1,"893":2,"899":1,"924":1,"955":1,"992":1,"993":3,"997":2,"1001":1}}],["cdn的c",{"2":{"167":1}}],["cdn加载",{"2":{"75":1,"353":1}}],["cn",{"2":{"499":1,"558":1,"708":1,"805":1,"881":1,"887":2,"902":1}}],["center",{"2":{"426":1}}],["crash",{"2":{"451":1,"1031":1}}],["crunched",{"2":{"392":2}}],["crc",{"2":{"391":1}}],["createbannerad",{"2":{"1005":2}}],["createudpsocket",{"2":{"983":1}}],["createtcpsocket",{"2":{"979":1}}],["createdirectory",{"2":{"942":1}}],["createanimationfunction",{"0":{"675":1},"1":{"676":1,"677":1,"678":1},"2":{"627":1,"678":2}}],["createaudio",{"0":{"643":1},"1":{"644":1,"645":1,"646":1},"2":{"627":1,"646":1,"648":1,"651":1}}],["createrect",{"0":{"658":1},"1":{"659":1,"660":1,"661":1},"2":{"627":1,"661":1}}],["createstoryline",{"2":{"624":1}}],["createvideo",{"0":{"631":1},"1":{"632":1,"633":1,"634":1,"635":1},"2":{"622":1,"627":1,"634":1,"637":1,"640":1}}],["createimage",{"0":{"654":1},"1":{"655":1,"656":1,"657":1},"2":{"621":2,"627":1,"657":1,"678":1}}],["createfontasset",{"2":{"1002":1}}],["createframe",{"2":{"621":2,"622":1,"634":1,"635":1,"638":1,"646":1,"657":1,"661":1,"668":1,"673":1,"678":3,"683":1,"688":2,"692":2}}],["createfeedbackbutton主动创建反馈入口",{"2":{"565":1}}],["createfeedbackbutton",{"2":{"102":1}}],["create",{"2":{"383":1,"611":1}}],["cs这个文件",{"2":{"1005":1}}],["csv",{"2":{"968":1}}],["cs缺依赖的报错",{"2":{"922":1}}],["cs的接口判定当前云测环境让游戏自动运行特定逻辑",{"2":{"741":1}}],["css",{"2":{"705":1}}],["cs附加到eventsystem对象上",{"2":{"476":1}}],["csharpvar",{"2":{"1002":1,"1005":1,"1073":1}}],["csharpvoid",{"2":{"707":1}}],["csharpprivate",{"2":{"995":1}}],["csharpopendatamessage",{"2":{"707":1}}],["csharp",{"2":{"703":1,"708":1,"1074":1}}],["csharpwx",{"2":{"701":1,"708":2}}],["csharpwechatwasm",{"2":{"426":1}}],["csharpusing",{"2":{"555":1}}],["csharpif",{"2":{"468":1}}],["csm",{"2":{"431":2}}],["cs",{"2":{"377":1,"383":3,"406":1,"431":1,"468":1,"479":1,"521":1,"825":1,"922":1,"1073":3}}],["cf",{"2":{"374":1}}],["cuo",{"2":{"920":1,"939":1}}],["cubes",{"2":{"1087":1}}],["cube",{"2":{"499":1}}],["currentruntime",{"2":{"801":1}}],["current",{"2":{"374":1}}],["currency",{"2":{"358":1}}],["custom",{"2":{"428":3}}],["customtemplatedir",{"2":{"383":1,"384":1}}],["customunicode",{"2":{"358":1}}],["customnodepath",{"2":{"355":1}}],["customnodepath指定自定义node安装目录",{"2":{"137":1}}],["customad增加onhide",{"2":{"102":1}}],["c0",{"2":{"358":1}}],["cjk特殊符号",{"2":{"1004":1}}],["cjk兼容符号",{"2":{"1004":1}}],["cjk字母及月份",{"2":{"1004":1}}],["cjk",{"2":{"358":5}}],["cpu占用",{"2":{"1118":1}}],["cpu利用率和内存使用",{"2":{"815":1}}],["cpu繁忙",{"2":{"799":1}}],["cpu型号",{"2":{"753":1}}],["cputype获取设备内存",{"2":{"753":1}}],["cpu性能差异",{"2":{"734":1}}],["cpu主内存",{"2":{"713":1,"967":1,"974":1}}],["cpuprofiler",{"2":{"351":1}}],["cpuprofile",{"2":{"351":1}}],["cpu",{"0":{"351":1,"739":1,"1086":1},"2":{"351":1,"432":2,"531":3,"533":1,"548":1,"739":1,"744":1,"782":2,"802":1,"814":2,"875":1,"1082":1,"1083":2,"1086":5}}],["closeasync",{"2":{"981":1}}],["cloudfunctionroot",{"2":{"374":1}}],["cloud",{"2":{"3":1,"374":6,"499":1}}],["click",{"2":{"678":1}}],["cli",{"2":{"609":1,"610":1}}],["clusteredrendering",{"2":{"431":1}}],["clustered",{"2":{"430":1}}],["class",{"2":{"383":1,"479":1,"555":1,"703":1,"927":3,"979":1,"983":1,"995":1,"1097":1}}],["cleancache",{"2":{"521":1}}],["cleanallcache",{"2":{"520":1}}],["cleanallfilecache",{"0":{"520":1},"2":{"230":1,"500":1}}],["cleanfilecache",{"0":{"521":1},"2":{"500":1}}],["clean",{"2":{"355":1}}],["cleanbuild",{"2":{"355":1}}],["clearcoatsmoothness",{"2":{"431":1}}],["clearcoatmask",{"2":{"431":1}}],["clear",{"2":{"351":1,"355":1,"1010":1}}],["chunkbasedcompression",{"2":{"942":2}}],["chrome",{"2":{"531":1}}],["chrome导入profile文件",{"2":{"531":1}}],["chrome加载数据",{"2":{"351":1}}],["chromaticaberration",{"2":{"430":1}}],["check",{"2":{"374":1,"926":1,"931":1,"932":1}}],["changelog",{"0":{"1047":1},"1":{"1048":1,"1049":1,"1050":1,"1051":1,"1052":1,"1053":1,"1054":1,"1055":1,"1056":1,"1057":1,"1058":1,"1059":1,"1060":1,"1061":1,"1062":1,"1063":1,"1064":1,"1065":1,"1066":1,"1067":1,"1068":1,"1069":1,"1070":1,"1071":1},"2":{"1012":1}}],["change",{"2":{"362":1}}],["changed",{"0":{"111":1,"215":1,"234":1,"236":1,"238":1,"240":1,"242":1,"244":1,"259":1,"264":1,"285":1,"292":1,"313":1,"321":1,"324":1,"332":1,"335":1,"347":1,"1059":1,"1061":1,"1067":1},"2":{"1012":3}}],["charts",{"2":{"1004":18}}],["chart",{"2":{"351":1}}],["choosemedia",{"2":{"130":1}}],["cascade",{"2":{"811":2}}],["cascades",{"2":{"430":1}}],["cavas",{"2":{"731":1}}],["cavnas",{"2":{"724":2}}],["calc",{"2":{"629":1}}],["called",{"2":{"983":1}}],["call的instance数量",{"2":{"1079":1}}],["call的数量",{"2":{"815":1}}],["call的概念",{"2":{"815":1}}],["call指的切换渲染状态的次数",{"2":{"815":1}}],["calljsfunction",{"2":{"426":1}}],["calljsfunctionwithreturn中",{"2":{"424":1}}],["calljsfunctionwithreturn接口实现了简单的第三方sdk调用",{"2":{"424":1}}],["calljsfunction与wx",{"2":{"424":1}}],["callmain完成时预下载信息",{"2":{"791":1}}],["callmain完成后是否立即隐藏加载封面",{"2":{"353":1}}],["callmaincost",{"2":{"789":1}}],["callmain耗时较长",{"2":{"790":1}}],["callmain耗时",{"2":{"759":1,"1106":1,"1120":1}}],["callmain的主要是initwebglplayer调用",{"2":{"532":1}}],["callmain",{"0":{"532":1,"533":1},"2":{"420":1,"421":1,"422":1,"759":1,"785":1,"791":1,"826":1,"958":1,"959":1,"1031":1,"1106":1,"1120":1,"1123":1,"1124":1}}],["call",{"2":{"374":2,"815":5}}],["callfunction",{"2":{"374":1}}],["callback=replace",{"2":{"968":1}}],["callbackorder",{"2":{"479":1}}],["callback",{"0":{"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"595":1,"596":1,"602":1,"603":1},"2":{"109":1,"415":1,"417":1,"602":1,"968":1,"970":1,"971":27}}],["catalog",{"2":{"523":1,"798":2,"799":3,"829":1,"831":1}}],["catch",{"2":{"374":1,"451":5,"576":1,"703":1}}],["cacheable",{"2":{"798":1}}],["cacheablecount",{"2":{"798":1,"799":1}}],["cacheablefileidentifier",{"2":{"507":2}}],["cachecatalog=true",{"2":{"799":1}}],["cachecatalog=false",{"2":{"799":1}}],["cachecatalog",{"2":{"798":1}}],["cachesettings=true",{"2":{"799":1}}],["cachesettings",{"2":{"798":1}}],["cache进行文件缓存",{"2":{"720":1}}],["cache机制",{"2":{"712":1}}],["cachexmlhttprequest",{"2":{"515":2}}],["cache",{"2":{"441":1,"518":2}}],["camera",{"0":{"816":1},"2":{"431":1,"816":3}}],["cameramotionblur",{"2":{"431":1}}],["can",{"2":{"931":1}}],["cancel",{"2":{"671":1}}],["canvas画布等",{"2":{"712":1}}],["canvasscaler>",{"2":{"707":1}}],["canvasscaler",{"2":{"707":1}}],["canvas2d",{"2":{"705":1}}],["canvas",{"2":{"351":1,"697":2,"712":1,"1010":1}}],["cannot",{"2":{"286":1}}],["caniuse可以判断当前版本是否支持该",{"2":{"1007":1}}],["caniuse",{"2":{"40":1,"1007":1}}],["c",{"0":{"597":1},"1":{"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1},"2":{"34":1,"130":1,"383":1,"384":1,"409":1,"414":1,"427":1,"429":7,"431":1,"451":1,"479":1,"490":2,"498":1,"572":1,"576":1,"580":1,"582":4,"598":1,"602":3,"615":2,"679":1,"717":1,"808":2,"825":3,"841":1,"873":1,"887":1,"927":1,"930":1,"931":1,"932":1,"934":2,"942":1,"943":2,"945":1,"973":2,"977":2,"979":2,"981":1,"983":2,"1010":1}}],["count为32或更小的值",{"2":{"1080":1}}],["count的大小",{"2":{"1079":1}}],["count",{"0":{"1039":1},"2":{"970":1,"1012":1,"1079":1}}],["costtimems",{"2":{"826":1}}],["costtime",{"2":{"825":1}}],["costtimeaftercallmain",{"2":{"795":1,"796":1}}],["cocos",{"2":{"705":1}}],["cover",{"2":{"632":1}}],["cookie",{"2":{"430":1,"431":1,"1094":2}}],["coreblit",{"0":{"493":1},"2":{"493":1}}],["core",{"2":{"428":10,"429":1}}],["connectasync",{"2":{"981":1}}],["connect",{"2":{"979":1}}],["conf",{"2":{"748":1,"817":1,"913":1}}],["confirmtype",{"2":{"555":1}}],["config",{"0":{"492":1,"585":1},"2":{"374":3,"380":2,"410":1,"435":1,"576":1,"580":1,"585":1}}],["console打印检测报告",{"2":{"786":1}}],["console打印详细信息",{"2":{"786":1}}],["console",{"2":{"374":1,"446":2,"533":1,"576":2,"703":2,"753":2,"889":1,"965":1,"1005":1}}],["constant",{"2":{"707":2}}],["const",{"2":{"374":1,"423":1,"507":2,"512":1,"621":2,"624":1,"635":1,"638":1,"668":1,"678":3,"688":2,"692":2,"753":3,"826":1,"1004":1}}],["contain",{"2":{"632":1,"634":1}}],["contexts",{"2":{"952":1}}],["context",{"2":{"374":1}}],["contextmenu适配",{"2":{"32":1}}],["contents",{"2":{"410":2,"805":1}}],["content",{"2":{"374":5,"383":1,"979":2,"983":1,"1095":4}}],["control",{"2":{"370":1,"615":1,"1095":1}}],["controls",{"2":{"358":1}}],["codes",{"2":{"580":1}}],["code",{"2":{"367":1,"374":4,"383":2,"435":1,"501":1,"576":1,"591":1,"724":1,"759":1,"864":1,"874":1,"979":3,"983":3,"1005":1,"1043":1,"1074":1,"1106":1,"1120":1}}],["colorgradinglutpass",{"2":{"430":1,"431":1}}],["color",{"2":{"351":1,"421":1,"423":1,"426":1,"580":1,"585":1,"659":1,"661":1,"1010":1}}],["community",{"2":{"499":1}}],["common",{"2":{"429":1}}],["combine",{"2":{"383":1}}],["compilewasm",{"2":{"826":2}}],["compile",{"2":{"812":2}}],["compileoptions",{"0":{"355":1}}],["compileoption",{"2":{"86":1,"137":1}}],["compilation",{"2":{"612":1}}],["compilingtext",{"2":{"421":1,"423":1,"959":1}}],["completed",{"2":{"926":1,"927":1,"930":3}}],["completetext",{"2":{"421":1,"423":1,"959":1}}],["complete",{"2":{"412":1,"414":1,"825":2,"926":1,"932":1,"994":2}}],["compatibility",{"2":{"358":2}}],["compresstext",{"0":{"412":1},"1":{"413":1,"414":1},"2":{"412":1,"414":1}}],["compresstexture",{"0":{"356":1}}],["compressed",{"2":{"392":6,"393":1}}],["compressdatapackage",{"2":{"353":1}}],["com",{"2":{"0":1,"1":1,"127":2,"351":1,"353":1,"370":1,"374":1,"377":2,"421":1,"423":1,"428":4,"429":2,"481":1,"490":2,"494":1,"499":17,"513":3,"523":2,"531":1,"532":1,"634":1,"646":1,"708":1,"805":1,"836":2,"843":1,"880":1,"881":1,"882":1,"883":2,"887":2,"902":1,"917":1,"920":1,"937":1,"939":5,"949":4,"968":1,"977":2,"979":2,"983":2,"985":1,"993":4,"994":2,"995":1,"1002":1,"1003":1,"1004":1,"1136":1}}],["flex布局",{"2":{"705":1}}],["flexdb",{"2":{"499":1}}],["float3",{"2":{"431":1}}],["float",{"2":{"353":1,"1073":7}}],["free",{"2":{"970":1}}],["frameinfo",{"2":{"801":1}}],["framecost",{"2":{"801":1,"802":1}}],["framecount",{"2":{"801":1}}],["frames",{"2":{"801":1}}],["frametype速查表",{"0":{"627":1},"2":{"626":1}}],["frametype",{"0":{"631":1,"636":1,"639":1,"643":1,"647":1,"650":1,"654":1,"658":1,"663":1,"666":1,"670":1,"675":1,"680":1,"685":1,"690":1},"1":{"632":1,"633":1,"634":1,"635":1,"637":1,"638":1,"640":1,"641":1,"644":1,"645":1,"646":1,"648":1,"649":1,"651":1,"652":1,"655":1,"656":1,"657":1,"659":1,"660":1,"661":1,"664":1,"665":1,"667":1,"668":1,"671":1,"672":1,"673":1,"676":1,"677":1,"678":1,"681":1,"682":1,"683":1,"686":1,"687":1,"688":1,"691":1,"692":1},"2":{"621":2,"622":1,"626":1,"627":1,"628":1,"634":1,"635":1,"638":1,"641":1,"646":1,"649":1,"652":1,"657":1,"661":1,"666":2,"668":1,"673":1,"678":3,"683":1,"688":2,"692":2}}],["frame",{"2":{"619":1,"628":2,"632":3,"635":3,"637":1,"640":1,"644":2,"648":1,"651":1,"655":1,"664":4,"667":3,"668":1,"671":1,"676":4,"678":2,"686":2,"691":3,"801":1,"931":1,"983":1}}],["frameworks",{"2":{"479":1}}],["framework",{"2":{"435":1,"479":1,"902":1}}],["fromil2cpptype",{"2":{"1097":1}}],["fromjson",{"2":{"995":1}}],["from",{"2":{"428":1,"836":1,"961":1,"962":1,"971":18,"1003":2}}],["fps均值为大盘游戏数据计算所得",{"2":{"762":1}}],["fps均值",{"2":{"760":1,"1112":1}}],["fps等游戏需根据实际情况评估",{"2":{"496":1}}],["fps",{"2":{"432":2,"785":1,"1126":1}}],["ff0000",{"2":{"426":1}}],["ffffff00",{"2":{"659":1,"661":1}}],["ffffff",{"2":{"421":1,"423":1,"426":1,"580":1,"585":1}}],["faq",{"0":{"1030":1},"1":{"1031":1,"1032":1,"1033":1,"1034":1,"1035":1,"1036":1,"1037":1,"1038":1,"1039":1,"1040":1,"1041":1,"1042":1,"1043":1,"1044":1,"1045":1,"1046":1},"2":{"1012":1}}],["fallbackfont",{"2":{"1002":2}}],["false不自动缓存",{"2":{"507":1}}],["false",{"2":{"412":2,"414":4,"507":1,"512":2,"555":2,"576":1,"580":1,"584":2,"585":2,"600":1,"943":2,"945":1,"948":1,"979":2,"983":2}}],["fairgui可正常工作",{"2":{"476":1}}],["failure",{"2":{"1097":1}}],["failed",{"0":{"492":1},"2":{"383":1}}],["fail",{"0":{"491":1},"2":{"71":1,"367":1,"374":2,"825":2}}],["far",{"2":{"431":1}}],["fmod音频插件是否支持",{"0":{"478":1}}],["fmod",{"2":{"365":1,"366":2,"367":1}}],["fmod转换适配develop",{"2":{"117":1}}],["fuwu",{"2":{"499":1}}],["full",{"2":{"451":4,"453":1}}],["fullwidth",{"2":{"358":1}}],["func的日志",{"2":{"1029":1}}],["func导致的包体增大",{"2":{"1024":1}}],["func",{"2":{"1024":1}}],["functionname",{"2":{"424":1}}],["function",{"0":{"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"595":1,"596":1},"2":{"374":3,"507":1,"512":1,"889":3,"979":1,"983":1,"1065":2}}],["funcs选项后",{"2":{"739":1}}],["funcs会导致代码包过大",{"2":{"351":1}}],["funcs",{"0":{"448":1},"2":{"302":1,"351":2,"355":1,"448":2,"899":1,"968":1}}],["fbslim",{"2":{"355":1}}],["fog雾效不会用到",{"2":{"433":1}}],["fog",{"2":{"430":1,"431":1}}],["forums",{"2":{"887":1}}],["forum",{"2":{"887":1}}],["for",{"2":{"812":2,"930":1,"931":1,"939":1,"968":1,"1029":1}}],["form",{"2":{"977":5}}],["format",{"2":{"362":1,"392":2,"393":1}}],["forms",{"2":{"358":4}}],["forcemaxcount",{"2":{"1079":1}}],["force",{"2":{"356":1,"412":1,"414":1}}],["found",{"2":{"68":1,"76":1}}],["fontasset",{"2":{"1002":1}}],["font文件不希望自动清理",{"2":{"512":1}}],["fontsize",{"2":{"421":1,"423":1,"426":1}}],["fontoptions",{"0":{"358":1}}],["font",{"2":{"68":1,"76":1,"510":3,"512":1,"1002":5,"1003":8}}],["focus",{"2":{"9":1}}],["firefox",{"0":{"722":1}}],["first",{"2":{"983":1}}],["firstframepic",{"0":{"695":1}}],["firststarttext",{"2":{"421":1,"423":1,"959":1}}],["field",{"0":{"554":1}}],["field组件适配微信输入法",{"2":{"50":1}}],["fill",{"2":{"632":1}}],["filmgrain",{"2":{"430":1,"431":1}}],["file3",{"2":{"993":1}}],["file2",{"2":{"993":1}}],["file1",{"2":{"993":1}}],["file接口",{"2":{"498":1}}],["file相关接口做文件存储",{"0":{"472":1}}],["fileaccess",{"2":{"383":1}}],["filemode",{"2":{"383":1}}],["filesize",{"0":{"521":1},"2":{"500":1,"521":1}}],["filestream",{"2":{"383":2}}],["filesystemmanager异步读取文件",{"2":{"162":1}}],["filesystemmanager增加stat接口",{"2":{"161":1}}],["filesystem",{"2":{"47":1}}],["fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400",{"2":{"370":1}}],["filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400",{"2":{"370":1}}],["file",{"0":{"492":1},"2":{"68":1,"71":1,"76":1,"383":2,"490":1,"493":1,"518":1,"939":1}}],["fit",{"2":{"423":1}}],["fixedwide",{"2":{"423":1}}],["fixedwidth",{"2":{"423":1}}],["fixednarrow",{"2":{"423":1}}],["fixedheight",{"2":{"423":2}}],["fixed",{"0":{"3":1,"6":1,"9":1,"12":1,"14":1,"18":1,"21":1,"23":1,"25":1,"27":1,"29":1,"32":1,"35":1,"38":1,"43":1,"45":1,"48":1,"52":1,"55":1,"60":1,"65":1,"68":1,"71":1,"76":1,"79":1,"82":1,"87":1,"90":1,"92":1,"95":1,"97":1,"100":1,"103":1,"106":1,"109":1,"117":1,"120":1,"122":1,"125":1,"128":1,"131":1,"133":1,"138":1,"143":1,"148":1,"151":1,"156":1,"159":1,"162":1,"166":1,"169":1,"171":1,"177":1,"180":1,"185":1,"188":1,"190":1,"192":1,"195":1,"197":1,"200":1,"202":1,"205":1,"213":1,"216":1,"220":1,"222":1,"225":1,"227":1,"246":1,"254":1,"263":1,"266":1,"268":1,"270":1,"272":1,"274":1,"278":1,"281":1,"283":1,"286":1,"288":1,"291":1,"298":1,"305":1,"317":1,"319":1,"330":1,"334":1,"337":1,"339":1,"341":1,"344":1,"350":1,"1049":1,"1051":1,"1053":1,"1055":1,"1063":1,"1065":1},"2":{"423":4,"926":1,"1012":6}}],["feature和shader",{"2":{"812":1}}],["feature",{"0":{"2":1,"5":1,"8":1,"11":1,"16":1,"20":1,"31":1,"34":1,"37":1,"40":1,"42":1,"47":1,"50":1,"54":1,"57":1,"59":1,"62":1,"64":1,"67":1,"70":1,"73":1,"75":1,"78":1,"81":1,"84":1,"86":1,"89":1,"94":1,"99":1,"102":1,"105":1,"108":1,"113":1,"115":1,"119":1,"124":1,"127":1,"130":1,"135":1,"137":1,"140":1,"142":1,"145":1,"147":1,"150":1,"153":1,"155":1,"158":1,"161":1,"164":1,"167":1,"173":1,"175":1,"179":1,"182":1,"184":1,"186":1,"194":1,"199":1,"204":1,"207":1,"209":1,"211":1,"218":1,"223":1,"228":1,"230":1,"232":1,"248":1,"250":1,"252":1,"256":1,"258":1,"261":1,"276":1,"280":1,"290":1,"294":1,"296":1,"300":1,"301":1,"302":1,"304":1,"307":1,"309":1,"311":1,"315":1,"323":1,"326":1,"328":1,"342":1,"345":1,"1057":1},"2":{"812":1,"1012":1}}],["where",{"2":{"971":17}}],["while",{"2":{"926":1,"927":1,"977":1}}],["ws协议进行开发",{"2":{"986":1}}],["ws等不带ssl证书的协议",{"2":{"984":1}}],["ws",{"2":{"805":1,"902":4,"981":2}}],["wss必然需要ssl证书",{"2":{"986":1}}],["wss等带ssl证书的协议",{"2":{"984":1}}],["wss协议",{"2":{"984":1}}],["wss",{"2":{"499":1,"982":1}}],["wwwform",{"2":{"977":2}}],["www",{"2":{"502":1,"712":1,"939":1,"943":7,"947":2,"977":1,"979":1,"983":1,"995":5,"1002":1,"1003":1,"1004":18}}],["worldtransformparams",{"2":{"431":1}}],["wait",{"2":{"931":1}}],["watch",{"2":{"612":2}}],["was",{"0":{"481":1}}],["wasm水印插件",{"0":{"1127":1},"1":{"1128":1,"1129":1,"1130":1,"1131":1,"1132":1}}],["wasm分包的大小会直接影响代码下载时长以及程序初始化编译的时间",{"2":{"874":1}}],["wasm分包检测",{"0":{"794":1},"1":{"795":1,"796":1},"2":{"783":1}}],["wasm子包加载时机过早",{"2":{"796":1}}],["wasm子包在callmain期间加载",{"2":{"796":1}}],["wasmcontentlength",{"2":{"789":1}}],["wasmcode下的wasm文件名里的md5",{"2":{"1019":1}}],["wasmcodesplit",{"2":{"1017":1}}],["wasmcode",{"2":{"759":1,"1014":2,"1034":1,"1106":1,"1120":1}}],["wasm包下载耗时",{"2":{"789":1}}],["wasmloadcost",{"2":{"789":1}}],["wasm~=1",{"2":{"735":1}}],["wasm是强类型语言",{"2":{"735":1}}],["wasm编译需要cpu资源",{"2":{"874":1}}],["wasm编译",{"2":{"712":1,"826":1}}],["wasm代码回到初始状态",{"2":{"1131":1}}],["wasm代码已是通过代码分包加载",{"2":{"960":1}}],["wasm代码下载与首包资源并行下载",{"2":{"874":1}}],["wasm代码下载和编译",{"0":{"874":1},"2":{"871":1}}],["wasm代码编译",{"2":{"826":1}}],["wasm代码编译内存",{"0":{"725":1}}],["wasm代码包下载",{"2":{"826":1}}],["wasm代码分包",{"0":{"550":1}}],["wasm代码和首资源包框架会强制缓存",{"2":{"501":1}}],["wasm代码",{"2":{"501":1,"759":1,"761":1,"1106":1,"1107":1,"1120":1,"1122":1}}],["wasm代码未发生变化时不在进行压缩",{"2":{"175":1}}],["wasm及图片资源构成",{"2":{"376":1}}],["wasm",{"0":{"467":1,"492":1,"735":1,"1100":1},"2":{"108":3,"351":1,"352":1,"377":4,"383":2,"384":1,"406":1,"435":3,"451":2,"505":1,"550":4,"576":1,"582":3,"602":1,"724":1,"733":1,"759":2,"839":1,"864":1,"887":1,"889":5,"897":1,"902":1,"922":2,"1005":1,"1014":3,"1016":1,"1031":1,"1082":1,"1083":1,"1091":1,"1097":1,"1100":1,"1101":1,"1106":2,"1120":2}}],["wasm加载报错",{"2":{"21":1}}],["wav",{"2":{"435":1}}],["warning",{"2":{"428":1}}],["will",{"2":{"931":1}}],["win",{"2":{"897":2}}],["windowwidth",{"2":{"1073":1}}],["windowheight",{"2":{"1073":2}}],["windows系统下使用",{"2":{"615":1}}],["windows缓存目录",{"2":{"523":1}}],["windows",{"2":{"351":1,"541":1,"733":1,"805":1,"902":1}}],["window",{"2":{"9":1,"428":1,"701":1,"805":1,"902":1}}],["withshareticket",{"2":{"708":1}}],["with",{"2":{"451":2,"453":1,"473":1,"707":1,"931":1}}],["without",{"2":{"451":2}}],["wide",{"2":{"423":1}}],["width是在canvas的ui",{"2":{"707":2}}],["width=100",{"2":{"629":2}}],["width=屏幕宽度",{"2":{"629":1}}],["width",{"2":{"421":3,"422":1,"423":3,"426":1,"614":1,"621":2,"629":1,"632":1,"655":1,"657":1,"659":1,"667":1,"676":1,"678":1,"701":4,"707":6,"709":1,"958":1,"959":1,"1005":2}}],["we",{"2":{"931":1}}],["weapp",{"2":{"370":1}}],["webkit对webgl2的支持存在问题",{"2":{"1079":1,"1080":1}}],["webrequest",{"2":{"977":10}}],["webrequest设置请求头",{"2":{"205":1}}],["webassembly代码分包加载与编译",{"2":{"951":1}}],["webassembly",{"2":{"887":2,"1086":1}}],["webassembly编译以及容器其他内存",{"2":{"731":1}}],["websockify做反向代理",{"2":{"982":1}}],["websockify",{"2":{"805":4,"902":4,"982":1}}],["websocketsend函数中",{"2":{"981":1}}],["websocketconstructor",{"2":{"902":1}}],["websocket",{"0":{"980":1},"1":{"981":1,"982":1},"2":{"372":1,"373":1,"539":1,"978":1,"981":4,"985":1}}],["webcontent进程内存压力会很大",{"2":{"967":1}}],["webcontent",{"2":{"714":1}}],["web",{"2":{"531":1,"699":1,"705":1,"1076":1}}],["webgl较多渲染优化特性依赖webgl2",{"2":{"1077":1}}],["webgl这个目录下",{"2":{"992":1}}],["webgl这部分开销是额外的",{"2":{"948":1}}],["webgl微信小游戏适配方案是以webassembly为基础",{"2":{"904":1}}],["webgl微信小游戏转换指南",{"2":{"886":1}}],["webgl为unity导出为webgl后的资源和代码目录",{"2":{"894":1}}],["webgl胶水层适配",{"2":{"885":1}}],["webgl包自动进行br压缩",{"2":{"874":1}}],["webgl转换的小游戏普遍存在首包资源较大的情况",{"2":{"928":1}}],["webgl转换的小游戏启动耗时",{"2":{"917":1}}],["webgl转换的小游戏主要依靠unity",{"2":{"863":1}}],["webgl转换方案的游戏通常会有这几种错误会产生",{"2":{"567":1}}],["webgl适配小游戏方案的部分上线游戏",{"2":{"844":1}}],["webgl适配小游戏的内存结构",{"0":{"712":1}}],["webgl1",{"0":{"807":1},"2":{"807":6,"809":1,"820":1}}],["webglsupport",{"2":{"805":2,"902":3}}],["webgl内存原理详解",{"2":{"781":1}}],["webgl内存结构可先参考",{"2":{"712":1}}],["webgl小游戏适配方案概述",{"0":{"884":1},"1":{"885":1,"886":1,"887":1}}],["webgl小游戏适配方案性能标准",{"0":{"754":1,"1102":1,"1116":1},"1":{"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1,"770":1,"771":1,"772":1,"773":1,"1103":1,"1104":1,"1105":1,"1106":1,"1107":1,"1108":1,"1109":1,"1110":1,"1111":1,"1112":1,"1113":1,"1114":1,"1115":1,"1117":1,"1118":1,"1119":1,"1120":1,"1121":1,"1122":1,"1123":1,"1124":1}}],["webgl小游戏可以参照的的性能评估标准",{"2":{"776":1}}],["webgl底层基于webassembly",{"2":{"775":1}}],["webgl环境有更多的优化",{"2":{"905":1,"907":1}}],["webgl环境的lua不支持jit",{"2":{"744":1}}],["webgl环境下的中文显示需要自定义字体",{"2":{"474":1}}],["webgl在原生的渲染api进行封装存在少量负荷带来的开销",{"2":{"734":1}}],["webgl在单首帧内无法gc",{"2":{"727":1}}],["webgl了解unity不同模块与手游app的性能差异",{"2":{"734":1}}],["webgl与app存在性能差距的最主要因素",{"2":{"734":1}}],["webgl与基于js引擎的普通h5游戏",{"2":{"733":1}}],["webgl目前不支持多线程",{"2":{"734":1}}],["webgl目录如下三个文件和目录是可能需要远程部署的资源",{"2":{"436":1}}],["webgl目录为游戏对应的webgl版本",{"2":{"435":1}}],["webgl使用tier2",{"2":{"726":1}}],["webgl将所有代码",{"2":{"725":1}}],["webgl是单线程模型",{"2":{"746":1}}],["webgl是app手游性能的1",{"2":{"734":1}}],["webgl是以wasm虚拟机的形式运行在类浏览器环境中",{"2":{"734":1}}],["webgl是以webassebly",{"2":{"733":1}}],["webgl是以webassembly+webgl技术为基础的应用",{"2":{"712":1}}],["webgl是托管在浏览器环境中",{"2":{"720":1}}],["webgl游戏的加载与适配器",{"2":{"951":1}}],["webgl游戏启动会是该时间的2",{"2":{"869":1}}],["webgl游戏启动速度",{"0":{"866":1},"1":{"867":1,"868":1,"869":1,"870":1,"871":1,"872":1,"873":1,"874":1,"875":1,"876":1,"877":1,"878":1,"879":1,"880":1,"881":1,"882":1,"883":1},"2":{"546":1,"778":1}}],["webgl游戏启动速度章节我们提到过",{"2":{"530":1}}],["webgl游戏运行时以websocket连接并定期发送性能数据",{"2":{"740":1}}],["webgl游戏通常比普通h5",{"2":{"711":1}}],["webgl的渲染性能",{"2":{"1098":1}}],["webgl的srp",{"2":{"752":1}}],["webgl的性能无法完全达到原生app的性能水平",{"2":{"737":1}}],["webgl的内存",{"0":{"710":1},"1":{"711":1,"712":1,"713":1,"714":1,"715":1,"716":1,"717":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"730":1,"731":1},"2":{"740":1,"759":1,"781":1,"1106":1,"1120":1}}],["webgl的运行性能",{"0":{"732":1},"1":{"733":1,"734":1,"735":1,"736":1,"737":1,"738":1,"739":1,"740":1,"741":1,"742":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1,"752":1,"753":1},"2":{"548":1}}],["webglobject",{"2":{"697":3}}],["webgl模式下将会使用js模拟文件系统带来额外内存消耗",{"2":{"943":1}}],["webgl模式",{"2":{"539":1}}],["webgl模式不允许加载非源码编译的插件",{"2":{"471":1}}],["webgl导出包是基于webassembly技术运行在浏览器环境",{"2":{"885":1}}],["webgl导出形式相对于原生app应用",{"2":{"775":1}}],["webgl导出时网络需要进行改造适配",{"2":{"470":1}}],["webgl导出失败时不进行小游戏转换",{"2":{"188":1}}],["webgl启动加载需要一定时间",{"2":{"418":1,"957":1}}],["webgl",{"0":{"469":1,"479":1,"734":1},"1":{"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1},"2":{"127":1,"346":1,"351":1,"355":1,"377":1,"392":1,"393":1,"396":2,"427":1,"428":1,"429":8,"435":7,"436":1,"437":1,"449":1,"479":1,"513":3,"523":1,"540":2,"548":1,"551":1,"697":1,"712":4,"724":1,"753":3,"759":3,"806":1,"814":1,"818":1,"834":1,"865":1,"873":1,"874":1,"887":2,"889":2,"894":1,"917":1,"942":1,"949":4,"975":2,"976":1,"977":2,"978":1,"992":2,"997":3,"1010":1,"1076":3,"1081":1,"1090":1,"1097":1,"1106":3,"1120":3,"1133":2}}],["webgl2",{"0":{"397":1,"493":1,"750":1,"807":1,"1075":1},"1":{"1076":1,"1077":1,"1078":1,"1079":1,"1080":1,"1081":1},"2":{"26":1,"120":1,"125":2,"280":1,"355":2,"734":1,"752":1,"807":9,"809":2,"813":1,"815":2,"820":1,"899":2}}],["weixinbridge",{"2":{"499":1}}],["weixin",{"2":{"127":1,"353":1,"374":1,"377":2,"490":2,"494":1,"499":8,"513":3,"708":1,"834":1,"979":1,"983":1,"985":1}}],["wechatwasm",{"2":{"383":1,"555":1,"945":1,"979":1,"983":1,"1002":1}}],["wechatminigame",{"2":{"16":2,"558":1}}],["wechat",{"2":{"0":1,"1":1,"127":1,"370":1,"377":8,"378":1,"384":4,"576":3,"582":1,"714":1,"836":2,"917":1,"1133":1,"1136":1}}],["writelineasync",{"2":{"383":1}}],["writer",{"2":{"383":2}}],["write",{"2":{"363":1,"383":1,"979":2}}],["writefile",{"2":{"16":1}}],["write适配",{"2":{"5":1}}],["wxcreatebanneradparam",{"2":{"1005":1}}],["wxconvertcore",{"2":{"468":3}}],["wxtcpsocket",{"2":{"979":1}}],["wxe5a48f1ed5f544b7",{"2":{"952":1}}],["wxeditorwindow",{"2":{"897":1}}],["wxexporterror",{"2":{"468":1}}],["wxunload",{"2":{"945":1}}],["wxunload后再次load同个assetbundle可能出现的异常",{"2":{"65":1}}],["wxuncaughtexception",{"2":{"889":1}}],["wxrender",{"2":{"701":2,"709":3}}],["wxinputfieldadapter",{"2":{"555":1}}],["wxaderrorresponse",{"2":{"1005":1}}],["wxanewfiles",{"2":{"523":2,"968":1}}],["wxagame",{"2":{"499":2}}],["wxassetstexttools",{"0":{"412":1,"415":1},"1":{"413":1,"414":1,"416":1,"417":1},"2":{"406":1,"409":1,"412":1,"414":1,"415":1}}],["wxassetbundle可以减轻ios的内存压力",{"2":{"922":1}}],["wxassetbundles",{"2":{"512":1}}],["wxassetbundle兼容webgl浏览器环境",{"2":{"73":1}}],["wxassetbundle",{"2":{"71":1,"945":2}}],["wxassetbundle支持切换cdn",{"2":{"26":1}}],["wx7a727ff7d940bb3f",{"0":{"466":1}}],["wxvideo",{"2":{"370":3}}],["wxshowopendata",{"2":{"701":1}}],["wxsnsdy",{"2":{"370":1}}],["wxsdk已经为你还原",{"2":{"384":1}}],["wxsdk目录",{"2":{"377":1}}],["wxsdk",{"2":{"352":1,"384":1,"837":1}}],["wxsdk代码简化",{"2":{"2":1}}],["wxfont章节",{"2":{"358":1}}],["wx",{"0":{"518":1,"519":1,"701":1,"702":1},"2":{"3":1,"108":2,"300":1,"352":1,"374":3,"377":4,"383":2,"384":1,"406":1,"426":1,"429":12,"430":1,"431":2,"446":1,"459":1,"494":1,"499":1,"500":2,"505":1,"513":1,"518":1,"533":1,"543":1,"555":8,"576":3,"582":1,"591":2,"598":1,"602":2,"701":2,"702":1,"703":3,"707":2,"708":4,"709":5,"825":5,"839":1,"841":1,"897":1,"956":1,"968":1,"979":4,"983":3,"995":2,"996":1,"1001":1,"1002":1,"1005":4,"1007":1,"1073":3,"1074":1}}],["普通模式与高性能模式可以无缝切换",{"2":{"1094":1}}],["普通模式",{"2":{"1031":1}}],["普通模式wechat",{"2":{"714":1}}],["普通更新",{"0":{"10":1,"13":1,"15":1,"17":1,"19":1,"24":1,"26":1,"28":1,"30":1,"44":1,"56":1},"1":{"11":1,"12":1,"14":1,"16":1,"18":1,"20":1,"21":1,"25":1,"27":1,"29":1,"31":1,"32":1,"45":1,"57":1},"2":{"49":1,"51":1,"53":1}}],["普通",{"2":{"2":2,"3":1,"5":3,"6":3,"8":2,"9":2,"11":3,"12":3,"14":1,"16":7,"18":3,"20":1,"21":3,"24":1,"25":3,"26":4,"27":6,"28":1,"29":1,"31":1,"32":4,"34":4,"35":1,"37":1,"40":2,"42":1,"45":1,"47":2,"48":2,"50":2,"54":1,"55":2}}],["2s",{"2":{"1124":1}}],["2之间",{"2":{"1034":1}}],["2个的camera",{"2":{"816":1}}],["2g~1",{"2":{"1090":1}}],["2g机型为主",{"2":{"711":1}}],["2g",{"2":{"711":1,"1090":1,"1123":1,"1124":1}}],["2级弱网情况时发生的回调事件",{"2":{"591":1}}],["2级",{"2":{"581":1}}],["2ms",{"2":{"532":1}}],["2105100",{"2":{"1016":1,"1129":1}}],["2104251",{"2":{"1016":1,"1129":1}}],["213ms",{"2":{"532":1}}],["21",{"0":{"134":1,"160":1,"257":1},"1":{"135":1,"161":1,"162":1,"258":1,"259":1},"2":{"190":1,"200":1,"205":1}}],["275",{"2":{"515":1}}],["27",{"0":{"77":1,"149":1},"1":{"78":1,"79":1,"150":1,"151":1},"2":{"313":1,"432":1}}],["2310312",{"2":{"369":1}}],["23",{"0":{"141":1,"297":1},"1":{"142":1,"143":1,"298":1},"2":{"75":1,"421":1,"432":4,"433":1,"809":1,"1093":1}}],["25无法进入游戏",{"2":{"1063":1}}],["25~2018",{"2":{"905":1}}],["256",{"2":{"353":1}}],["25启动异常",{"2":{"180":1}}],["25",{"0":{"253":1},"1":{"254":1},"2":{"67":1,"621":4,"678":1}}],["247583",{"2":{"889":1}}],["24s",{"2":{"532":1}}],["24f1版本",{"2":{"532":1}}],["240",{"2":{"421":2}}],["24",{"0":{"66":1,"104":1,"217":1,"224":1,"255":1},"1":{"67":1,"68":1,"105":1,"106":1,"218":1,"225":1,"256":1},"2":{"317":1,"421":3,"432":1,"911":1,"1077":1,"1126":1}}],["29",{"0":{"44":1,"88":1,"219":1,"235":1,"343":1},"1":{"45":1,"89":1,"90":1,"220":1,"236":1,"344":1,"345":1,"346":1,"347":1,"348":1},"2":{"62":1,"75":1,"130":1,"905":2}}],["28~2019",{"2":{"905":1}}],["28f1c1",{"2":{"388":1}}],["28",{"0":{"24":1,"46":1,"129":1,"157":1,"181":1,"193":1},"1":{"25":1,"47":1,"48":1,"130":1,"131":1,"158":1,"159":1,"182":1,"194":1,"195":1},"2":{"423":1}}],["20s",{"2":{"1123":1}}],["20m时",{"2":{"960":1}}],["20mb",{"2":{"793":1}}],["200个以内",{"2":{"815":1}}],["2000",{"2":{"796":1}}],["200",{"2":{"707":4,"824":1,"994":2,"1005":2}}],["2018~2020",{"2":{"971":1}}],["2018版本不支持修改dpr",{"2":{"907":1}}],["2018",{"2":{"386":1,"387":1,"532":1,"837":1,"904":1,"905":2}}],["2019及以后版本推荐使用",{"2":{"835":1}}],["2019支持dxt等",{"2":{"388":1}}],["2019支持部分",{"2":{"388":1}}],["2019",{"2":{"388":3,"805":1,"808":1,"902":1,"904":1,"905":4,"907":1,"949":1,"1074":2}}],["2019开始已不支持设置playersettings",{"2":{"346":1}}],["2019的兼容",{"2":{"18":1}}],["20",{"0":{"53":1,"61":1,"80":1,"152":1,"183":1,"260":1,"273":1,"308":1,"329":1},"1":{"54":1,"55":1,"62":1,"81":1,"82":1,"153":1,"184":1,"185":1,"186":1,"261":1,"274":1,"309":1,"330":1},"2":{"319":1,"421":1,"426":1,"515":1,"555":1,"678":1,"793":1}}],["2020版本",{"2":{"907":1}}],["2020版本导出的",{"2":{"124":1}}],["2020及以前",{"2":{"479":1}}],["2020支持dxt",{"2":{"388":1}}],["2020支持部分格式",{"2":{"388":1}}],["2020",{"2":{"386":1,"387":1,"388":4,"397":1,"904":1,"905":3}}],["2021以上",{"2":{"752":1}}],["2021以上可使用引擎astc",{"2":{"731":1}}],["2021才开始支持移动平台的压缩纹理",{"2":{"726":1}}],["2021均有版本支持",{"2":{"388":1}}],["2021支持多数",{"2":{"388":1}}],["2021支持",{"2":{"388":1}}],["20210",{"2":{"370":1}}],["2021增加embedded",{"2":{"280":1}}],["2021版本",{"2":{"393":1}}],["2021版本支持",{"2":{"296":1}}],["2021版本修改为默认使用external",{"2":{"246":1}}],["2021版本调整为需要手动分离symbols",{"2":{"234":1}}],["2021",{"0":{"269":1,"271":1,"273":1,"275":1,"277":1,"279":1,"282":1,"284":1,"287":1,"289":1,"293":1,"295":1,"297":1,"299":1,"303":1,"306":1,"308":1,"310":1,"312":1,"314":1,"316":1,"318":1,"320":1,"322":1,"325":1,"327":1,"329":1,"331":1,"333":1,"336":1,"338":1,"340":1,"343":1,"349":1},"1":{"270":1,"272":1,"274":1,"276":1,"278":1,"280":1,"281":1,"283":1,"285":1,"286":1,"288":1,"290":1,"291":1,"292":1,"294":1,"296":1,"298":1,"300":1,"301":1,"302":1,"304":1,"305":1,"307":1,"309":1,"311":1,"313":1,"315":1,"317":1,"319":1,"321":1,"323":1,"324":1,"326":1,"328":1,"330":1,"332":1,"334":1,"335":1,"337":1,"339":1,"341":1,"342":1,"344":1,"345":1,"346":1,"347":1,"348":1,"350":1},"2":{"240":1,"274":1,"281":1,"388":3,"397":1,"428":1,"429":1,"431":1,"433":2,"829":1,"889":1,"904":1,"905":5,"907":1,"971":1}}],["2021无需profiling",{"2":{"142":1}}],["2021编译参数增加",{"2":{"130":1}}],["2022年中版本",{"2":{"1077":1}}],["2022等",{"2":{"904":1}}],["202211101011",{"2":{"827":1}}],["2022",{"0":{"129":1,"132":1,"134":1,"136":1,"139":1,"141":1,"144":1,"146":1,"149":1,"152":1,"154":1,"157":1,"160":1,"163":1,"165":1,"168":1,"170":1,"172":1,"174":1,"176":1,"178":1,"181":1,"183":1,"187":1,"189":1,"191":1,"193":1,"196":1,"198":1,"201":1,"203":1,"206":1,"208":1,"210":1,"212":1,"214":1,"217":1,"219":1,"221":1,"224":1,"226":1,"229":1,"231":1,"233":1,"235":1,"237":1,"239":1,"241":1,"243":1,"245":1,"247":1,"249":1,"251":1,"253":1,"255":1,"257":1,"260":1,"262":1,"265":1,"267":1},"1":{"130":1,"131":1,"133":1,"135":1,"137":1,"138":1,"140":1,"142":1,"143":1,"145":1,"147":1,"148":1,"150":1,"151":1,"153":1,"155":1,"156":1,"158":1,"159":1,"161":1,"162":1,"164":1,"166":1,"167":1,"169":1,"171":1,"173":1,"175":1,"177":1,"179":1,"180":1,"182":1,"184":1,"185":1,"186":1,"188":1,"190":1,"192":1,"194":1,"195":1,"197":1,"199":1,"200":1,"202":1,"204":1,"205":1,"207":1,"209":1,"211":1,"213":1,"215":1,"216":1,"218":1,"220":1,"222":1,"223":1,"225":1,"227":1,"228":1,"230":1,"232":1,"234":1,"236":1,"238":1,"240":1,"242":1,"244":1,"246":1,"248":1,"250":1,"252":1,"254":1,"256":1,"258":1,"259":1,"261":1,"263":1,"264":1,"266":1,"268":1},"2":{"905":2,"1077":2}}],["2022引擎版本导出微信小游戏",{"2":{"102":1}}],["2022引擎版本导出web版本的模板",{"2":{"100":1}}],["202306292010",{"2":{"1001":1}}],["202305230000",{"2":{"785":1}}],["2023年度热门休闲小程序",{"2":{"853":1}}],["2023",{"0":{"36":1,"39":1,"41":1,"44":1,"46":1,"49":1,"51":1,"53":1,"56":1,"58":1,"61":1,"63":1,"66":1,"69":1,"72":1,"74":1,"77":1,"80":1,"83":1,"85":1,"88":1,"91":1,"93":1,"96":1,"98":1,"101":1,"104":1,"107":1,"110":1,"112":1,"114":1,"116":1,"118":1,"121":1,"123":1,"126":1},"1":{"37":1,"38":1,"40":1,"42":1,"43":1,"45":1,"47":1,"48":1,"50":1,"52":1,"54":1,"55":1,"57":1,"59":1,"60":1,"62":1,"64":1,"65":1,"67":1,"68":1,"70":1,"71":1,"73":1,"75":1,"76":1,"78":1,"79":1,"81":1,"82":1,"84":1,"86":1,"87":1,"89":1,"90":1,"92":1,"94":1,"95":1,"97":1,"99":1,"100":1,"102":1,"103":1,"105":1,"106":1,"108":1,"109":1,"111":1,"113":1,"115":1,"117":1,"119":1,"120":1,"122":1,"124":1,"125":1,"127":1,"128":1},"2":{"773":1,"1105":1,"1111":1}}],["202406062127",{"2":{"425":1}}],["2024",{"0":{"1":1,"4":1,"7":1,"10":1,"13":1,"15":1,"17":1,"19":1,"22":1,"24":1,"26":1,"28":1,"30":1,"33":1},"1":{"2":1,"3":1,"5":1,"6":1,"8":1,"9":1,"11":1,"12":1,"14":1,"16":1,"18":1,"20":1,"21":1,"23":1,"25":1,"27":1,"29":1,"31":1,"32":1,"34":1,"35":1},"2":{"762":1,"773":1}}],["264",{"2":{"1126":1}}],["26",{"0":{"17":1,"58":1,"110":1,"172":1,"214":1,"221":1,"251":1,"293":1,"325":1,"327":1},"1":{"18":1,"59":1,"60":1,"111":1,"173":1,"215":1,"216":1,"222":1,"223":1,"252":1,"294":1,"326":1,"328":1},"2":{"65":1}}],["2",{"0":{"33":1,"243":1,"245":1,"247":1,"249":1,"391":1,"404":1,"457":1,"471":1,"484":1,"497":1,"526":1,"608":1,"619":1,"620":1,"621":1,"622":2,"623":2,"624":2,"625":3,"695":1,"700":1,"701":1,"702":2,"703":1,"708":1,"717":1,"726":1,"740":1,"744":1,"779":1,"869":1,"871":1,"872":2,"873":2,"874":3,"875":2,"876":2,"877":1,"881":1,"893":1,"894":2,"895":1,"896":1,"912":1,"913":1,"914":2,"919":1,"920":2,"921":1,"922":1,"925":1,"926":1,"927":2,"931":1,"935":1,"938":1,"943":1,"948":1,"957":1,"974":1,"1066":1,"1070":1,"1094":1},"1":{"34":1,"35":1,"244":1,"246":1,"248":1,"250":1,"392":1,"393":1,"620":1,"621":2,"622":2,"623":1,"624":3,"625":3,"701":1,"702":1,"703":1,"913":1,"914":1,"926":1,"958":1,"959":1,"1067":1,"1071":1},"2":{"16":1,"20":1,"28":1,"42":1,"60":1,"62":1,"65":1,"67":1,"75":3,"81":1,"84":1,"102":1,"105":1,"108":1,"147":1,"240":1,"246":1,"351":3,"353":1,"369":2,"372":1,"380":1,"388":1,"421":1,"423":1,"429":1,"431":1,"432":3,"451":1,"479":2,"498":1,"500":1,"513":1,"527":2,"531":1,"532":3,"533":1,"550":1,"591":1,"622":1,"678":3,"714":1,"731":1,"748":1,"760":3,"799":1,"817":3,"825":2,"826":1,"827":1,"829":1,"905":5,"907":1,"1012":2,"1076":2,"1082":1,"1112":3}}],["222ms",{"2":{"515":1}}],["22",{"0":{"107":1,"114":1,"132":1,"226":1,"237":1,"299":1},"1":{"108":1,"109":1,"115":1,"133":1,"227":1,"228":1,"238":1,"300":1,"301":1,"302":1},"2":{"1":1,"432":1,"947":1}}],["px",{"2":{"1126":4}}],["physics",{"2":{"1087":1}}],["psygames",{"2":{"981":1}}],["ptr",{"2":{"973":3}}],["pdf",{"2":{"843":1,"1004":36}}],["pbr光照",{"2":{"809":1,"811":1}}],["pbr渲染",{"2":{"809":1}}],["pbr需要在线性颜色空间进行",{"2":{"809":1}}],["p",{"2":{"707":3,"939":1}}],["pivot",{"2":{"707":1}}],["pixelratio",{"2":{"1073":1}}],["pixel",{"2":{"707":2,"748":1,"814":3,"817":2}}],["pipeline",{"2":{"429":1}}],["pipelines",{"2":{"428":4,"433":1,"493":2}}],["pipelins",{"2":{"429":1}}],["pnplaytimeat",{"2":{"622":1}}],["png\`",{"2":{"621":2}}],["png",{"2":{"405":2,"421":1,"423":1,"614":1,"657":1,"678":1}}],["purets",{"2":{"498":1}}],["publish",{"2":{"451":1,"452":1}}],["public",{"0":{"518":1,"519":1,"520":1,"521":1,"522":1},"2":{"383":5,"479":3,"500":5,"521":1,"555":3,"703":2,"927":6,"931":1,"932":1,"942":1,"979":2,"983":2,"995":2}}],["punctuation",{"2":{"358":2}}],["percentcomplete进行进度展示",{"2":{"926":1}}],["percent",{"2":{"628":1,"629":2,"632":6,"655":6,"659":6,"667":6,"676":6}}],["percentage",{"2":{"580":1}}],["permissions",{"2":{"374":1}}],["permission",{"0":{"466":1},"2":{"367":1}}],["perfare",{"2":{"880":1}}],["perfdog记录性能数据并上传",{"2":{"772":1,"1110":1,"1121":1}}],["perfdog",{"0":{"716":1,"772":1},"2":{"713":1}}],["perfdog统计的是raf触发帧率而不是分帧后的帧率",{"2":{"488":1}}],["perfog",{"2":{"432":2}}],["performance",{"2":{"127":1,"429":17,"430":1,"431":2,"433":1,"734":1,"804":1}}],["perf",{"2":{"127":1}}],["port是否可达",{"2":{"805":1}}],["port",{"2":{"805":3,"902":4,"979":1,"983":2}}],["portrait",{"2":{"353":1}}],["postprocessing效果提升品质",{"2":{"1076":1}}],["post",{"2":{"977":3}}],["postmessage",{"0":{"703":1},"2":{"701":1,"703":1,"707":1,"708":1,"709":1}}],["posix接口",{"2":{"712":1}}],["position属性",{"2":{"627":1}}],["position",{"2":{"580":1,"585":1,"666":1,"707":1}}],["pointereventdata",{"2":{"555":2}}],["pointer",{"2":{"240":1}}],["py",{"2":{"351":1,"1073":1}}],["python2",{"2":{"479":3}}],["python",{"2":{"351":1,"479":5}}],["print",{"2":{"973":1}}],["private",{"2":{"555":8,"927":3,"930":1}}],["pragma",{"2":{"812":3}}],["pragma指令删除",{"2":{"433":1}}],["props的大小",{"2":{"1079":1}}],["provider",{"2":{"952":1}}],["profier内存分析",{"2":{"905":1}}],["profile版在高性能模式下卡与内存不足的问题",{"2":{"1065":1}}],["profile窗口",{"2":{"805":1,"902":1}}],["profile分析",{"0":{"533":1}}],["profile文件的使用可以参考google的开发文档",{"2":{"531":1}}],["profile之后",{"2":{"531":1}}],["profile能力",{"2":{"531":1}}],["profilestats",{"2":{"488":1}}],["profilestats性能面板增加frametime",{"2":{"102":1}}],["profiler内存分析能力",{"2":{"907":1}}],["profilerwindow",{"2":{"805":1,"902":1}}],["profiler窗口使用说明",{"2":{"805":1,"902":1}}],["profiler发现问题",{"2":{"782":1}}],["profiler在小游戏真机环境profie计算瓶颈",{"2":{"782":1}}],["profiler的运行原理是在unity",{"2":{"740":1}}],["profiler仅能看到",{"2":{"731":1}}],["profiler看到内存才200mb+",{"2":{"731":1}}],["profiler",{"0":{"719":1,"739":1,"740":1},"2":{"355":1,"548":2,"719":1,"739":1,"744":1,"805":4,"899":1,"902":4}}],["profiler默认隐藏",{"2":{"351":1}}],["profiler性能调优分析每一帧的耗时部分",{"2":{"875":1}}],["profiler性能调优",{"0":{"351":1,"805":1,"902":1},"2":{"782":2,"802":2}}],["profile",{"2":{"351":2,"531":3,"533":2,"1016":1,"1126":1}}],["profilingmem等模式",{"2":{"731":1}}],["profilingmemory功能需要额外的内存记录堆栈与相关统计",{"2":{"974":1}}],["profilingmemory在真机上更容易出现内存崩溃",{"0":{"974":1}}],["profilingmemory可以分析unityheap底层分配器的分配细节",{"2":{"718":1}}],["profilingmemory",{"0":{"718":1},"2":{"355":1,"713":1,"717":1,"968":1}}],["profilingfuncs",{"2":{"355":1,"899":1}}],["profiling",{"2":{"302":1,"351":1,"355":2,"731":1,"899":1,"967":2,"968":2}}],["pro",{"2":{"882":1}}],["protocol",{"2":{"798":1}}],["processes",{"2":{"715":1}}],["promax占用约80mb",{"2":{"712":1}}],["promise",{"2":{"520":1,"521":1,"522":1}}],["progressstyle",{"2":{"580":1,"585":1}}],["probesocclusion",{"2":{"431":1}}],["probe",{"2":{"430":2}}],["product",{"2":{"374":2}}],["project",{"2":{"374":1,"380":2,"428":2,"429":1,"748":1,"817":1,"913":1}}],["projectname",{"2":{"353":1,"865":1,"899":1}}],["projectconfig",{"0":{"353":1}}],["prefab本身以及依赖的所有资源需要在场景加载前完成",{"2":{"927":1}}],["preparegame",{"2":{"826":2}}],["prebuildprocessing",{"2":{"479":1}}],["preloadmanager",{"2":{"998":2}}],["preloadconcurrent",{"2":{"996":1}}],["preloadlistdata>",{"2":{"995":1}}],["preloadlistdata",{"2":{"995":4}}],["preloadlist",{"2":{"993":1,"994":2,"995":1}}],["preloadlistlength=0",{"2":{"793":1}}],["preloadlistlength",{"2":{"792":1,"793":1}}],["preloaddatalist",{"2":{"992":1,"994":3}}],["preloadwxfont",{"2":{"354":1}}],["preloadfiles",{"2":{"353":1,"899":1,"991":1}}],["preload",{"2":{"16":1}}],["pre",{"2":{"1":1}}],["playbackengines",{"2":{"805":2,"902":3}}],["playing",{"2":{"632":1,"644":1}}],["playaudio",{"0":{"650":1},"1":{"651":1,"652":1},"2":{"627":1}}],["playvideo0",{"2":{"638":2}}],["playvideo",{"0":{"639":1},"1":{"640":1,"641":1},"2":{"627":1,"638":1}}],["playpath",{"2":{"576":2,"585":1}}],["play",{"2":{"576":3}}],["playerloadfirstscene",{"2":{"532":1}}],["playerloadfirstscene函数调用",{"2":{"532":1}}],["playerinitenginegraphics",{"2":{"532":1}}],["playerinitenginenographics",{"2":{"532":1}}],["playerinitenginenographics和playerinitenginegraphics等函数调用",{"2":{"532":1}}],["playerpref或用户数据存储失效",{"0":{"490":1}}],["playerprefskeys",{"0":{"357":1}}],["playersettings导出选项中使用",{"0":{"460":1}}],["playersettings默认去除",{"2":{"246":1}}],["player页选择",{"2":{"429":1}}],["player项",{"2":{"429":1}}],["player",{"2":{"57":1,"451":1,"452":1}}],["plugincachepath",{"0":{"518":1},"2":{"500":1}}],["plugindemo",{"2":{"383":1}}],["plugins",{"2":{"380":1,"952":1}}],["plugins目录增加link",{"2":{"97":1}}],["plugin",{"2":{"377":1,"383":3,"515":3,"518":1,"1003":7}}],["pc使用v8作为wasm虚拟机内核",{"2":{"736":1}}],["pc命令行中输入",{"2":{"611":1}}],["pc上使用了chromium的网络模块",{"2":{"525":1}}],["pc上配置为不自动缓存的文件",{"0":{"525":1},"2":{"500":1}}],["pc端dxt",{"2":{"905":1}}],["pc端输入框无法输入",{"0":{"494":1}}],["pc端和开发者工具支持unity",{"2":{"50":1}}],["pc",{"0":{"722":1,"723":1},"2":{"356":1,"367":1,"369":1,"405":2,"427":1,"541":1,"733":1}}],["pc小游戏兼容",{"2":{"259":1}}],["pc小游戏首包资源通过分包加载时读取失败",{"2":{"213":1}}],["pc小游戏下载路径处理",{"2":{"166":1}}],["pc微信",{"2":{"387":1}}],["pc微信支持启动封面",{"2":{"179":1}}],["pc微信因loadsubpackage无回调的容错处理",{"2":{"79":1}}],["pc增加是否支持brotli压缩条件判断",{"2":{"78":1}}],["pc下载资源出现",{"2":{"71":1}}],["pc分辨率模糊",{"2":{"8":1}}],["pc窗口大小自动适配",{"2":{"8":1}}],["panic",{"2":{"973":1}}],["paniniprojection",{"2":{"430":1,"431":1}}],["patch编译后未生效",{"2":{"1051":1}}],["patch",{"2":{"952":1}}],["path1",{"2":{"992":1}}],["path为对应unity版本的安装目录",{"2":{"902":1}}],["path",{"0":{"522":1},"2":{"383":1,"406":1,"409":1,"500":1,"507":3,"512":2,"513":1,"518":2,"522":1,"805":2,"902":2}}],["part",{"2":{"949":2}}],["parser",{"2":{"971":2}}],["parse",{"2":{"703":1}}],["param",{"2":{"634":1,"635":1,"646":1,"664":1}}],["params",{"2":{"622":2}}],["parallelwithbundle",{"2":{"356":1}}],["pauseaudio",{"0":{"647":1},"1":{"648":1,"649":1},"2":{"627":1}}],["pausevideo",{"0":{"636":1},"1":{"637":1,"638":1},"2":{"641":1,"649":1,"652":1}}],["pausevide",{"2":{"627":1}}],["pause适配",{"2":{"6":1}}],["pass",{"0":{"493":1},"2":{"431":1,"493":2,"809":1}}],["padding",{"2":{"421":1,"423":1}}],["package下",{"2":{"962":1}}],["package这个分包下",{"2":{"960":1}}],["packagecache",{"2":{"428":1,"493":1}}],["package",{"0":{"835":1},"1":{"836":1},"2":{"428":10,"433":2,"835":1,"836":2,"905":1}}],["packages",{"2":{"377":2,"428":9,"881":1,"882":1,"883":1}}],["packagemanager",{"2":{"0":1,"1":1,"838":1,"839":1,"1136":1}}],["1已fix",{"2":{"1097":1}}],["1w",{"2":{"939":1}}],["1hplnldrf0qavjejtpkf",{"2":{"920":1,"939":1}}],["1~2022",{"2":{"905":1}}],["1~2020",{"2":{"905":1}}],["1~2",{"2":{"811":1}}],["1s",{"2":{"802":1}}],["1g",{"2":{"711":1,"1090":1,"1123":1}}],["1级能满足要求是最好的",{"2":{"811":1}}],["1级",{"2":{"581":1}}],["1mb",{"2":{"513":1,"792":1,"793":1,"798":1}}],["1支持bufferurl",{"2":{"130":1}}],["14",{"0":{"93":1,"187":1,"231":1,"247":1,"303":1},"1":{"94":1,"95":1,"188":1,"232":1,"248":1,"304":1,"305":1},"2":{"334":1,"905":1}}],["1600",{"2":{"423":2}}],["16安卓worker写文件报错",{"2":{"202":1}}],["16",{"0":{"91":1,"198":1,"275":1},"1":{"92":1,"199":1,"200":1,"276":1},"2":{"330":1,"392":1,"883":1,"947":1,"959":1,"1097":1,"1126":2}}],["19m",{"2":{"971":1}}],["19",{"0":{"287":1,"331":1},"1":{"288":1,"332":1},"2":{"81":1,"111":1,"428":1,"431":1,"433":2}}],["1版本",{"2":{"62":1}}],["1基础库且只支持播放一个视频",{"2":{"57":1}}],["11~2021",{"2":{"905":1}}],["113ms",{"2":{"532":1}}],["115",{"2":{"423":1}}],["11以上",{"2":{"246":1}}],["11以后版本已支持",{"2":{"240":1}}],["11",{"0":{"44":1,"46":1,"49":1,"51":1,"56":1,"139":1,"141":1,"144":1,"146":1,"176":1,"233":1,"249":1,"284":1,"287":1,"289":1,"466":1,"480":1,"493":1,"753":1,"1052":1},"1":{"45":1,"47":1,"48":1,"50":1,"52":1,"57":1,"140":1,"142":1,"143":1,"145":1,"147":1,"148":1,"177":1,"234":1,"250":1,"285":1,"286":1,"288":1,"290":1,"291":1,"292":1,"1053":1},"2":{"102":1,"348":1,"432":1,"712":1,"1012":1,"1090":1}}],["12无法安装",{"2":{"1049":1}}],["127",{"2":{"902":1}}],["1264",{"2":{"889":1}}],["126ms",{"2":{"532":1}}],["12s",{"2":{"532":1,"1123":2,"1124":1}}],["12",{"0":{"36":1,"39":2,"41":1,"83":1,"96":1,"129":1,"132":1,"134":1,"136":1,"154":1,"269":1,"271":1,"273":1,"275":1,"277":1,"279":1,"282":1,"310":1,"467":1,"481":1,"494":1,"1050":1},"1":{"37":1,"38":1,"40":2,"42":1,"43":1,"84":1,"97":1,"130":1,"131":1,"133":1,"135":1,"137":1,"138":1,"155":1,"156":1,"270":1,"272":1,"274":1,"276":1,"278":1,"280":1,"281":1,"283":1,"311":1,"1051":1},"2":{"35":1,"124":1,"421":1,"428":5,"429":2,"431":1,"433":1,"479":1,"1012":1,"1077":2,"1090":1}}],["15s",{"2":{"1123":1,"1124":1}}],["154ms",{"2":{"532":1}}],["15等帧率是微信使用raf分帧处理",{"2":{"488":1}}],["15032",{"2":{"435":1}}],["1500或安卓平台callmaincost",{"2":{"790":1}}],["1500",{"2":{"421":1,"423":1,"959":1}}],["15000",{"2":{"421":1,"423":1,"959":1}}],["15",{"0":{"15":1,"30":1,"116":1,"245":1},"1":{"16":1,"31":1,"32":1,"117":1,"246":1},"2":{"43":1,"423":1,"793":1,"812":1,"1097":2,"1098":1}}],["173",{"2":{"614":1}}],["17",{"0":{"13":1,"19":1,"121":1,"123":1,"144":1,"174":1,"243":1,"262":1},"1":{"14":1,"20":1,"21":1,"122":1,"124":1,"125":1,"145":1,"175":1,"244":1,"263":1,"264":1},"2":{"12":1,"367":1,"773":1,"1097":1,"1105":1,"1111":1}}],["1334",{"2":{"1126":1}}],["135296",{"2":{"882":1}}],["130mb",{"2":{"724":1}}],["139ms",{"2":{"532":1}}],["13",{"0":{"7":1,"163":1,"201":1,"265":1,"333":1,"468":1,"1048":1},"1":{"8":1,"9":1,"164":1,"202":1,"266":1,"334":1,"335":1,"1049":1},"2":{"337":1,"762":1,"773":1,"1012":1}}],["1",{"0":{"28":1,"30":1,"33":1,"101":1,"189":1,"208":1,"251":1,"253":1,"255":1,"257":1,"260":1,"262":1,"265":1,"267":1,"390":1,"403":1,"456":1,"470":1,"483":1,"493":1,"496":1,"525":1,"560":1,"607":1,"618":1,"620":1,"621":2,"622":1,"624":1,"694":1,"699":1,"701":1,"707":1,"714":1,"725":1,"739":1,"743":1,"778":1,"841":1,"868":2,"869":1,"871":1,"873":1,"880":1,"893":1,"911":1,"913":1,"919":1,"924":1,"926":1,"930":1,"934":1,"937":1,"942":2,"943":1,"947":1,"954":1,"973":1,"1048":1,"1050":1,"1052":1,"1054":1,"1056":1,"1058":1,"1060":1,"1062":1,"1064":1,"1066":1,"1068":1,"1093":1},"1":{"29":1,"31":1,"32":1,"34":1,"35":1,"102":1,"103":1,"190":1,"209":1,"252":1,"254":1,"256":1,"258":1,"259":1,"261":1,"263":1,"264":1,"266":1,"268":1,"621":1,"622":1,"715":1,"716":1,"955":1,"956":1,"1049":1,"1051":1,"1053":1,"1055":1,"1057":1,"1059":1,"1061":1,"1063":1,"1065":1,"1067":1,"1069":1},"2":{"1":1,"16":2,"18":1,"35":1,"57":1,"111":1,"124":1,"133":1,"135":1,"137":1,"147":1,"225":1,"348":1,"350":1,"351":1,"353":2,"355":1,"369":3,"372":1,"374":2,"380":1,"428":5,"429":4,"431":1,"432":3,"433":1,"451":2,"479":3,"500":1,"513":1,"515":1,"521":1,"531":1,"532":2,"533":1,"580":2,"585":2,"591":2,"599":1,"614":2,"634":2,"646":2,"678":2,"683":1,"688":3,"711":3,"731":1,"760":3,"793":1,"798":1,"807":1,"824":1,"825":2,"826":1,"827":2,"883":1,"902":1,"926":1,"947":1,"959":1,"967":1,"978":2,"996":2,"1003":1,"1012":11,"1016":2,"1036":1,"1049":2,"1073":1,"1076":1,"1082":1,"1090":1,"1091":1,"1093":1,"1112":3,"1123":2,"1124":2,"1126":1,"1129":1}}],["18f1c1",{"2":{"388":1}}],["18",{"0":{"1":1,"28":1,"36":1,"69":1,"196":1,"229":1,"289":1},"1":{"2":1,"3":1,"29":1,"37":1,"38":1,"70":1,"71":1,"197":1,"230":1,"290":1,"291":1,"292":1},"2":{"84":1,"515":1,"608":1}}],["10s",{"2":{"1123":1,"1124":2}}],["10w+函数的包可以减少约100m",{"2":{"1045":1}}],["108",{"2":{"889":1}}],["10mb",{"2":{"727":1,"1126":1}}],["107",{"2":{"707":1}}],["102",{"2":{"621":2}}],["1024bytes",{"2":{"513":1}}],["1024",{"2":{"513":1,"790":2,"793":6}}],["1024kb",{"2":{"513":1}}],["101",{"2":{"621":1}}],["100mb内存",{"2":{"748":1}}],["100mb",{"2":{"724":1,"727":1}}],["1002",{"2":{"692":3}}],["1001",{"2":{"692":3,"825":1}}],["1000ms",{"2":{"673":2}}],["1000",{"2":{"673":1,"678":2,"802":1,"1011":1}}],["10000",{"2":{"351":1,"825":1}}],["100",{"2":{"426":3,"599":1,"621":5,"657":1,"678":1,"825":1,"905":4}}],["1045",{"2":{"423":2}}],["10f1c1",{"2":{"388":1}}],["10版本基础库查看",{"2":{"370":1}}],["105",{"2":{"370":1}}],["10",{"0":{"1":1,"4":1,"49":1,"53":1,"56":1,"72":1,"149":1,"152":1,"154":1,"178":1,"277":1,"293":1,"295":1,"312":1,"349":1,"465":1,"479":1,"492":1,"752":1,"1054":1},"1":{"2":1,"3":1,"5":1,"6":1,"50":1,"54":1,"55":1,"57":1,"73":1,"150":1,"151":1,"153":1,"155":1,"156":1,"179":1,"180":1,"278":1,"294":1,"296":1,"313":1,"350":1,"1055":1},"2":{"350":1,"426":3,"428":5,"429":2,"431":1,"433":1,"515":2,"532":1,"629":1,"635":2,"657":2,"668":1,"785":1,"792":1,"798":1,"996":2,"1012":1}}],["t",{"2":{"973":2}}],["tutorial",{"2":{"949":1}}],["tuanjie",{"2":{"0":1,"1":1,"836":2,"1136":1}}],["tips",{"2":{"794":1,"826":1,"998":1}}],["tier2",{"2":{"726":1}}],["timestep控制计算频率",{"2":{"782":1}}],["timestep降低计算频率",{"2":{"745":1}}],["timestep与",{"2":{"745":1}}],["timeline",{"0":{"723":1}}],["timeout",{"2":{"671":1,"673":1}}],["title",{"2":{"591":2,"602":1,"708":1}}],["that",{"2":{"931":1}}],["the",{"2":{"570":1,"602":1,"712":1,"930":1,"931":4,"932":3,"933":1,"983":1}}],["this",{"2":{"555":6}}],["threw",{"0":{"408":1},"1":{"409":1,"410":1}}],["thrown",{"2":{"450":1,"451":3}}],["throw",{"2":{"383":1}}],["task",{"2":{"932":2}}],["tag",{"2":{"570":1}}],["tab",{"2":{"531":1}}],["target=",{"2":{"410":1}}],["targetframerate限帧",{"2":{"747":1}}],["targetframerate",{"2":{"59":1,"488":1}}],["tw",{"2":{"515":1}}],["ttf",{"2":{"510":1,"512":1,"1002":1,"1003":2}}],["ttc",{"2":{"68":1,"76":1}}],["ts",{"2":{"507":1,"614":1,"618":2}}],["typetree",{"2":{"971":4}}],["typescript",{"2":{"618":1}}],["typeof",{"2":{"555":1,"703":1}}],["type",{"2":{"426":1,"701":1,"703":4,"707":1,"708":1,"826":7,"952":1}}],["too",{"0":{"1039":1},"2":{"1012":1}}],["tool",{"0":{"889":1},"2":{"881":1}}],["tools",{"2":{"531":2,"805":2,"881":1,"882":1,"889":1,"902":1}}],["tools里面",{"2":{"531":1}}],["toarray",{"2":{"995":1}}],["tostring",{"2":{"943":1}}],["tojson",{"2":{"703":1,"707":1,"708":1,"979":2,"983":1}}],["tolua等",{"2":{"498":1}}],["to",{"0":{"471":1,"492":1},"2":{"887":1,"932":1,"933":1,"949":2,"973":1}}],["totaljanktime",{"2":{"801":1,"802":1}}],["totalheapmemory",{"2":{"717":1}}],["total",{"2":{"432":2}}],["totallaunchtime",{"2":{"421":1,"423":1,"959":1}}],["top",{"2":{"426":1,"629":1,"632":1,"634":1,"655":1,"659":1,"661":1,"667":1,"668":1,"676":1,"1005":2,"1073":2}}],["touchend",{"0":{"491":1}}],["touchend去json性能优化",{"2":{"37":1}}],["touch事件丢失或错误",{"0":{"476":1}}],["touch能力适配",{"2":{"268":1}}],["touchmove触摸性能优化",{"2":{"47":1}}],["touchstart",{"2":{"37":1}}],["touch",{"2":{"12":1,"122":1}}],["txt",{"2":{"396":1,"403":1,"435":1,"436":1,"437":1,"759":1,"865":1,"873":1,"889":1,"1106":1,"1120":1}}],["tmptext",{"2":{"1002":1}}],["tmp",{"2":{"383":2,"1002":1}}],["tree",{"2":{"917":1}}],["true",{"2":{"421":1,"446":1,"459":1,"507":1,"512":1,"555":1,"576":1,"580":1,"584":2,"600":1,"614":1,"622":1,"634":1,"646":1,"657":1,"678":3,"707":2,"708":2,"785":2,"926":1,"965":1,"979":2,"983":1,"1088":1}}],["true时将强制生成",{"2":{"414":1}}],["true时仅生成astc格式纹理",{"2":{"414":1}}],["try",{"2":{"374":1,"451":3,"576":1,"703":1}}],["transition",{"2":{"431":1}}],["transformworldtoobjectnormal",{"2":{"431":1}}],["transformobjecttoworldnormal",{"2":{"431":1}}],["transform",{"2":{"0":1,"1":1,"127":1,"707":1,"836":2,"917":1,"1133":1,"1136":1}}],["trace",{"2":{"351":1,"973":1}}],["tcptest",{"2":{"979":1}}],["tcpsocketconnectoption",{"2":{"979":1}}],["tcpsocketonmessagelistenerresult>",{"2":{"979":1}}],["tcpsocket",{"0":{"979":1},"2":{"979":3,"983":1}}],["tcp",{"0":{"978":1},"1":{"979":1,"980":1,"981":1,"982":1},"2":{"978":1,"979":11,"982":2}}],["tcp使用wx",{"2":{"498":1}}],["tcb",{"2":{"499":2}}],["tc",{"2":{"370":1}}],["technology",{"2":{"949":1}}],["technologies",{"2":{"532":1,"939":1}}],["textasset>",{"2":{"934":2}}],["textasset",{"2":{"934":1}}],["textalign",{"2":{"426":1}}],["text",{"2":{"426":2,"555":1,"934":1,"977":2,"979":1,"983":1,"995":1,"1002":1}}],["textduration",{"2":{"421":1,"423":1,"959":1}}],["textconfig",{"2":{"421":1,"423":1}}],["texturehandle",{"2":{"930":4}}],["texture2d>",{"2":{"930":3,"931":2,"932":2}}],["texture2d",{"2":{"813":1,"930":1,"931":1}}],["textureeditor",{"2":{"406":1}}],["textureeditor插件目录不参与编译",{"2":{"106":1}}],["texture",{"0":{"362":1},"2":{"362":1,"435":1,"699":1,"701":1,"707":1,"709":1,"930":1,"931":2}}],["textures",{"2":{"435":1,"508":1,"513":8,"992":1,"997":1}}],["texturespath",{"2":{"353":1,"505":1,"900":1}}],["textureshashlength",{"2":{"353":1,"505":1,"900":1}}],["testudpsocket",{"2":{"983":3}}],["testtcpsocket",{"2":{"979":3}}],["testvalue2",{"2":{"825":1}}],["testvalue1",{"2":{"825":1}}],["testkey2",{"2":{"825":2}}],["testkey1",{"2":{"825":2}}],["testfunctionoption",{"2":{"426":1}}],["testfunctionoption仅作为演示",{"2":{"426":1}}],["testfunction",{"2":{"426":2}}],["test",{"2":{"380":1,"431":1,"611":1,"612":1,"979":1,"983":1}}],["templatedir",{"2":{"384":1}}],["template",{"2":{"377":5,"380":1,"383":2,"384":3,"616":1}}],["tencentcloudapi",{"2":{"499":3}}],["tencent",{"2":{"351":1,"481":1,"499":1,"523":2,"968":1}}],["uff00",{"2":{"1004":1}}],["ufe30",{"2":{"1004":1}}],["ufe10",{"2":{"1004":1}}],["u2200",{"2":{"1004":1}}],["u25a0",{"2":{"1004":1}}],["u20a0",{"2":{"1004":1}}],["u2000",{"2":{"1004":1}}],["u2190",{"2":{"1004":1}}],["u2150",{"2":{"1004":1}}],["u2100",{"2":{"1004":1}}],["u2460",{"2":{"1004":1}}],["u2700",{"2":{"1004":1}}],["u2600",{"2":{"1004":1}}],["u3300",{"2":{"1004":1}}],["u3200",{"2":{"1004":1}}],["u3000",{"2":{"1004":1}}],["u0000",{"2":{"1004":1}}],["u4e00",{"2":{"1004":1}}],["utf8",{"2":{"979":1,"983":1}}],["utilities",{"2":{"881":1,"882":1}}],["utils",{"2":{"493":1}}],["ud",{"2":{"973":2}}],["udptest",{"2":{"983":1}}],["udp",{"0":{"983":1},"2":{"983":7}}],["udp使用wx",{"2":{"498":1}}],["udpclient使用connect+write",{"2":{"143":1}}],["udpsocketsendoption",{"2":{"983":1}}],["udpsocketonmessagelistenerresult>",{"2":{"983":1}}],["udpsocket",{"2":{"5":1,"983":2}}],["uwa4d",{"2":{"939":1}}],["uwa关于addressable的介绍",{"2":{"939":1}}],["uv",{"2":{"812":1,"1011":1}}],["ui纹理的精细度可能要求不高",{"2":{"813":1}}],["ui系统的合批",{"2":{"812":1}}],["uinty",{"2":{"752":1}}],["ui控件延x轴旋转180度",{"2":{"699":1}}],["ui",{"0":{"1098":1},"2":{"555":1,"813":1,"816":1,"1082":1}}],["ui等基础模块",{"2":{"498":1}}],["ui不需要开启mipmap",{"2":{"363":1}}],["ugui",{"2":{"476":1}}],["uri",{"2":{"943":1}}],["uripath",{"2":{"943":2}}],["urp的基础上定制",{"2":{"808":1}}],["urp复杂的特性尽量少用",{"2":{"808":1}}],["urp管线通过renderer配置取消",{"2":{"726":1}}],["urp管线导出小游戏时提示",{"0":{"493":1}}],["urp包移除掉",{"2":{"433":1}}],["urp版本一致",{"2":{"433":1}}],["urp版本",{"2":{"428":1}}],["urp版本的路径是差不多的",{"2":{"428":1}}],["urp版本信息",{"2":{"428":1}}],["urp后",{"2":{"428":1}}],["urp",{"0":{"427":1,"428":1,"430":1,"431":1,"432":1},"1":{"428":1,"429":1,"430":1,"431":2,"432":2,"433":1,"434":1},"2":{"427":6,"428":14,"429":3,"430":4,"431":5,"432":2,"433":14,"434":1,"493":3,"498":1,"808":4,"811":2,"815":1}}],["url=https",{"2":{"1003":1}}],["url中包含特定标识符时需要自动缓存",{"2":{"900":1}}],["url地址为",{"2":{"836":1}}],["url地址从而改变剧情的内容",{"2":{"614":1}}],["url剔除掉data",{"2":{"513":1}}],["url",{"0":{"519":1},"2":{"0":1,"1":1,"420":1,"421":1,"422":1,"499":1,"500":1,"591":1,"614":1,"621":2,"632":1,"634":1,"644":1,"646":1,"655":1,"657":1,"678":1,"798":1,"836":1,"902":2,"945":1,"958":1,"959":1,"994":2}}],["updatemanager",{"0":{"913":1}}],["updatesharemenuoption",{"2":{"708":1}}],["updatesharemenu",{"2":{"708":2}}],["update",{"2":{"351":1,"968":1,"983":1}}],["usparkle",{"2":{"939":1}}],["usr",{"2":{"409":1,"523":1,"889":2,"968":1}}],["using",{"2":{"383":5,"479":4,"555":3,"945":1,"973":1,"979":4,"981":1,"983":4,"995":1}}],["usingmemoryprofiler",{"2":{"127":1}}],["useh2=false",{"2":{"799":1}}],["useh2",{"2":{"792":1,"798":1}}],["use",{"2":{"726":1,"930":1,"931":2}}],["usecodesplit为false",{"2":{"790":1}}],["usecodesplit",{"2":{"789":1,"826":1}}],["usecontentencoding值为false",{"2":{"790":1}}],["usecontentencoding",{"2":{"789":1,"792":1,"798":1}}],["usecompressedtexture",{"2":{"354":1}}],["usecustomprogress",{"2":{"580":2,"585":1,"599":1}}],["users",{"2":{"947":1}}],["user",{"0":{"491":1},"2":{"513":1,"518":1}}],["useoptimizedstoreactions",{"2":{"430":1,"431":1}}],["useminigamechat",{"2":{"354":1}}],["usefriendrelation",{"2":{"354":1,"899":1}}],["usedheapmemory",{"2":{"717":1}}],["usedxt5",{"2":{"356":1}}],["used",{"2":{"286":1,"968":2,"971":18,"973":1}}],["unload时",{"2":{"948":1}}],["unload",{"2":{"920":1,"943":2,"948":1}}],["unlit",{"2":{"811":1}}],["unlitinput",{"2":{"431":1}}],["unlink操作文件时同步更新启动插件维护的缓存信息",{"2":{"16":1}}],["unzipassets",{"2":{"826":1}}],["unmasked",{"2":{"753":2}}],["unallocatedmemory",{"2":{"717":1}}],["unable",{"0":{"471":1}}],["untiy",{"2":{"512":1}}],["untiy3d拓展名文件视为bundle文件",{"2":{"348":1}}],["understanding",{"2":{"712":1,"949":2}}],["undergameview",{"2":{"370":1}}],["undef",{"2":{"429":1}}],["undefined",{"2":{"20":1}}],["unicoderange",{"2":{"1004":1}}],["unicode",{"2":{"1004":20}}],["unicode集合参考",{"2":{"1004":1}}],["uniform可以减少sizeof",{"2":{"1079":1}}],["uniform",{"2":{"430":1,"431":2,"807":1}}],["unified",{"2":{"358":1}}],["universal",{"0":{"493":1},"2":{"428":11,"429":1,"433":1,"493":2,"808":1}}],["unity社区讨论",{"2":{"1097":1}}],["unity官方文档",{"2":{"1081":1}}],["unity提供了将所有assetsbundle迁移到addressable",{"2":{"935":1}}],["unity首资源包的压缩率是比较高的",{"2":{"924":1}}],["unity中资源按需加载也可以使用老的assetbundle",{"2":{"920":1}}],["unity中如何展示排行榜这类微信关系数据",{"0":{"696":1},"1":{"697":1,"698":1,"699":1,"700":1,"701":1,"702":1,"703":1,"704":1,"705":1,"706":1,"707":1,"708":1,"709":1}}],["unity在2018版本中推出了addressable",{"2":{"919":1}}],["unity5等早期版本",{"2":{"907":1}}],["unity导出webgl",{"0":{"891":1}}],["unity的",{"2":{"945":1}}],["unity的buildtarget支持webgl平台",{"2":{"885":1}}],["unity的阴影方案",{"2":{"811":1}}],["unity全新资源管理流程",{"2":{"883":1}}],["unity默认内建资源",{"2":{"864":1}}],["unity默认的材质",{"2":{"812":1}}],["unity会自动使用内置的默认材质",{"2":{"812":1}}],["unity会多一个全屏",{"2":{"809":1}}],["unity了",{"2":{"809":1}}],["unity内置shader",{"2":{"807":1}}],["unity3d",{"2":{"805":1,"883":1,"887":1,"902":1,"949":1}}],["unity将自动移动到",{"2":{"934":1}}],["unity将自启动监听端口34999等待调试链接",{"2":{"805":1,"902":1}}],["unity将音频传递给容器",{"2":{"712":1}}],["unity并未对webgl平台做特别裁剪",{"2":{"775":1}}],["unity小游戏的启动可参考启动流程与时序",{"2":{"759":1,"1106":1,"1120":1}}],["unity性能评测标准用于开发者优化游戏性能数据",{"2":{"755":1,"1103":1}}],["unity是以webgl",{"2":{"734":1}}],["unity数据统计等",{"2":{"725":1}}],["unityheap不宜过大",{"2":{"727":1}}],["unityheap=dynamicmemory+少量静态内存",{"2":{"727":1}}],["unityheap预留内存",{"2":{"727":3,"731":1}}],["unityheap预留量",{"2":{"717":1}}],["unityheap是用于存储所有状态",{"2":{"727":1}}],["unityheap真实使用量",{"2":{"717":1}}],["unityheap使用上限",{"2":{"717":1}}],["unityheap总预分配内存大小",{"2":{"717":1}}],["unityheap非常关键",{"2":{"717":1}}],["unityheap",{"0":{"717":1,"727":1},"2":{"713":1,"724":4,"727":1}}],["unity管理的assetbundle和场景结构等本机内存",{"2":{"712":1}}],["unity博客",{"2":{"712":2}}],["unity微信小游戏首次启动会花费较长的加载时间",{"2":{"568":1}}],["unity微信小游戏专区",{"2":{"558":1}}],["unity引擎在早期版本如5",{"2":{"905":1}}],["unity引擎",{"2":{"834":1}}],["unity引擎底层资源异步加载策略",{"2":{"829":1}}],["unity引擎目前没有很好地针对浏览器环境优化",{"2":{"735":1}}],["unity引擎视角",{"2":{"717":1}}],["unity引擎初始化",{"2":{"532":1}}],["unity引擎自带压缩纹理",{"2":{"387":1,"388":1}}],["unitynamespace",{"2":{"507":1,"512":2,"785":1}}],["unity音频",{"2":{"498":1}}],["unity基础模块",{"2":{"498":1}}],["unityloader插件已经考虑到业务会重复请求预下载的文件",{"2":{"999":1}}],["unityloader",{"2":{"435":1,"547":1}}],["unity版本的使用",{"2":{"834":1}}],["unity版本支持从2018到最新的2022版本",{"2":{"497":1}}],["unity版本",{"2":{"433":1,"814":1}}],["unityeditor",{"2":{"410":1,"479":3,"942":1}}],["unityengine",{"2":{"383":1,"479":1,"555":3,"975":1,"979":1,"983":1}}],["unitywebsocket需要对websocket",{"2":{"981":1}}],["unitywebsocket",{"2":{"981":1}}],["unityweb或code",{"2":{"724":1}}],["unitywebrequest按需下载并使用资源",{"2":{"944":1}}],["unitywebrequestassetbundle",{"2":{"502":1,"943":2,"945":1,"947":1}}],["unitywebrequest",{"2":{"502":1,"539":1,"943":4,"945":1,"947":1,"976":1,"977":5,"995":3}}],["unitywebrequest支持timeout属性",{"2":{"99":1}}],["unityweb文件",{"2":{"501":2}}],["unityweb不会被上传",{"0":{"467":1}}],["unityweb",{"2":{"396":1,"435":5,"436":1,"437":1,"759":2,"865":1,"889":1,"902":1,"1106":2,"1120":2}}],["unityprofiler以及更小的包体",{"2":{"905":1}}],["unityprofiler会默认启动监听",{"2":{"902":1}}],["unityprofiler",{"2":{"713":1}}],["unitypermaterial",{"2":{"430":1,"431":1,"807":1}}],["unityplugin",{"2":{"380":1,"952":1}}],["unitypackage",{"2":{"0":1,"1136":1}}],["unityaudio基本能力支持",{"2":{"498":1}}],["unityaudio",{"2":{"365":2,"366":1}}],["unityaudio循环播放修复",{"2":{"246":1}}],["unity插件",{"2":{"108":1}}],["unity",{"0":{"388":1,"460":1,"469":1,"478":1,"479":1,"489":1,"532":1,"534":1,"712":1,"719":1,"734":1,"740":1,"754":1,"864":1,"883":1,"884":1,"906":1,"1007":1,"1102":1,"1116":1},"1":{"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1,"770":1,"771":1,"772":1,"773":1,"885":1,"886":1,"887":1,"1103":1,"1104":1,"1105":1,"1106":1,"1107":1,"1108":1,"1109":1,"1110":1,"1111":1,"1112":1,"1113":1,"1114":1,"1115":1,"1117":1,"1118":1,"1119":1,"1120":1,"1121":1,"1122":1,"1123":1,"1124":1},"2":{"70":1,"127":1,"130":1,"147":1,"259":1,"266":1,"268":2,"366":1,"367":2,"376":1,"386":2,"388":9,"389":1,"393":1,"399":1,"408":1,"409":1,"410":5,"418":1,"421":1,"423":1,"427":2,"428":12,"429":6,"431":11,"433":6,"434":1,"451":1,"459":1,"479":3,"493":4,"507":1,"532":1,"537":1,"544":1,"545":1,"546":2,"548":2,"551":1,"556":2,"557":1,"558":1,"582":1,"697":5,"701":2,"702":1,"703":1,"707":1,"709":2,"711":1,"712":9,"717":1,"719":1,"725":1,"726":1,"731":1,"733":1,"734":4,"740":2,"744":1,"752":1,"775":2,"781":1,"785":1,"805":4,"806":1,"807":1,"808":2,"809":1,"811":1,"812":2,"814":1,"815":1,"822":2,"828":1,"829":1,"831":1,"832":1,"835":1,"836":1,"837":1,"863":1,"873":2,"881":1,"882":1,"883":1,"887":1,"889":1,"902":3,"904":1,"905":1,"907":2,"917":1,"922":1,"926":1,"928":1,"937":1,"939":2,"948":3,"949":6,"951":1,"957":1,"965":1,"971":2,"976":1,"977":1,"978":1,"981":1,"1005":4,"1010":1,"1014":1,"1073":2,"1074":1,"1077":1,"1087":1,"1090":1,"1097":3,"1098":1,"1133":3,"1136":1}}],["unity2018~2020在webgl上没有明显的性能差异",{"2":{"905":1}}],["unity2021~2022开始支持更多特性",{"2":{"905":1}}],["unity2021建议使用instantgame版本",{"2":{"902":1}}],["unity2021不再提示分离symbols",{"2":{"240":1}}],["unity2021",{"2":{"164":1,"809":1}}],["unity2022支持新的memoryprofiler",{"2":{"905":1}}],["unity2022",{"2":{"54":1}}],["unity21",{"2":{"27":1}}],["unity侧添加设置分辨率接口",{"2":{"11":1}}]],"serializationVersion":2}`;export{t as default}; diff --git a/assets/chunks/IOSDevicePixelRatio.DHUlmbuM.js b/assets/chunks/IOSDevicePixelRatio.DHUlmbuM.js new file mode 100644 index 00000000..babcc7be --- /dev/null +++ b/assets/chunks/IOSDevicePixelRatio.DHUlmbuM.js @@ -0,0 +1 @@ +const s="/minigame-unity-webgl-transform/assets/IOSDevicePixelRatio.B1RP7CsG.png";export{s as _}; diff --git a/assets/chunks/VPLocalSearchBox.BANsnCko.js b/assets/chunks/VPLocalSearchBox.BANsnCko.js new file mode 100644 index 00000000..8f1a2259 --- /dev/null +++ b/assets/chunks/VPLocalSearchBox.BANsnCko.js @@ -0,0 +1,7 @@ +var It=Object.defineProperty;var Dt=(o,e,t)=>e in o?It(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Oe=(o,e,t)=>(Dt(o,typeof e!="symbol"?e+"":e,t),t);import{Y as yt,h as oe,y as $e,aj as kt,ak as Ot,d as _t,H as xe,al as tt,k as Fe,am as Rt,an as Mt,z as Lt,ao as Pt,l as _e,U as de,S as Ee,ap as zt,aq as Vt,Z as Bt,j as $t,ar as Wt,o as ee,b as Kt,m as k,a2 as Jt,p as j,as as Ut,at as jt,au as Gt,c as re,n as rt,e as Se,G as at,F as nt,a as ve,t as pe,av as qt,q as Ht,s as Qt,aw as it,ax as Yt,a8 as Zt,ae as Xt,ay as er,_ as tr}from"./framework.Br2U662V.js";import{u as rr,c as ar}from"./theme.DuJp6K1e.js";const nr={root:()=>yt(()=>import("./@localSearchIndexroot.DOuO4YaK.js"),[])};/*! +* tabbable 6.2.0 +* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE +*/var mt=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"],Ne=mt.join(","),gt=typeof Element>"u",ue=gt?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,Ce=!gt&&Element.prototype.getRootNode?function(o){var e;return o==null||(e=o.getRootNode)===null||e===void 0?void 0:e.call(o)}:function(o){return o==null?void 0:o.ownerDocument},Ie=function o(e,t){var r;t===void 0&&(t=!0);var n=e==null||(r=e.getAttribute)===null||r===void 0?void 0:r.call(e,"inert"),a=n===""||n==="true",i=a||t&&e&&o(e.parentNode);return i},ir=function(e){var t,r=e==null||(t=e.getAttribute)===null||t===void 0?void 0:t.call(e,"contenteditable");return r===""||r==="true"},bt=function(e,t,r){if(Ie(e))return[];var n=Array.prototype.slice.apply(e.querySelectorAll(Ne));return t&&ue.call(e,Ne)&&n.unshift(e),n=n.filter(r),n},wt=function o(e,t,r){for(var n=[],a=Array.from(e);a.length;){var i=a.shift();if(!Ie(i,!1))if(i.tagName==="SLOT"){var s=i.assignedElements(),u=s.length?s:i.children,l=o(u,!0,r);r.flatten?n.push.apply(n,l):n.push({scopeParent:i,candidates:l})}else{var h=ue.call(i,Ne);h&&r.filter(i)&&(t||!e.includes(i))&&n.push(i);var d=i.shadowRoot||typeof r.getShadowRoot=="function"&&r.getShadowRoot(i),v=!Ie(d,!1)&&(!r.shadowRootFilter||r.shadowRootFilter(i));if(d&&v){var y=o(d===!0?i.children:d.children,!0,r);r.flatten?n.push.apply(n,y):n.push({scopeParent:i,candidates:y})}else a.unshift.apply(a,i.children)}}return n},xt=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},se=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||ir(e))&&!xt(e)?0:e.tabIndex},or=function(e,t){var r=se(e);return r<0&&t&&!xt(e)?0:r},sr=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},Ft=function(e){return e.tagName==="INPUT"},ur=function(e){return Ft(e)&&e.type==="hidden"},lr=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(r){return r.tagName==="SUMMARY"});return t},cr=function(e,t){for(var r=0;rsummary:first-of-type"),i=a?e.parentElement:e;if(ue.call(i,"details:not([open]) *"))return!0;if(!r||r==="full"||r==="legacy-full"){if(typeof n=="function"){for(var s=e;e;){var u=e.parentElement,l=Ce(e);if(u&&!u.shadowRoot&&n(u)===!0)return ot(e);e.assignedSlot?e=e.assignedSlot:!u&&l!==e.ownerDocument?e=l.host:e=u}e=s}if(vr(e))return!e.getClientRects().length;if(r!=="legacy-full")return!0}else if(r==="non-zero-area")return ot(e);return!1},yr=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var r=0;r=0)},gr=function o(e){var t=[],r=[];return e.forEach(function(n,a){var i=!!n.scopeParent,s=i?n.scopeParent:n,u=or(s,i),l=i?o(n.candidates):s;u===0?i?t.push.apply(t,l):t.push(s):r.push({documentOrder:a,tabIndex:u,item:n,isScope:i,content:l})}),r.sort(sr).reduce(function(n,a){return a.isScope?n.push.apply(n,a.content):n.push(a.content),n},[]).concat(t)},br=function(e,t){t=t||{};var r;return t.getShadowRoot?r=wt([e],t.includeContainer,{filter:We.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:mr}):r=bt(e,t.includeContainer,We.bind(null,t)),gr(r)},wr=function(e,t){t=t||{};var r;return t.getShadowRoot?r=wt([e],t.includeContainer,{filter:De.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):r=bt(e,t.includeContainer,De.bind(null,t)),r},le=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,Ne)===!1?!1:We(t,e)},xr=mt.concat("iframe").join(","),Re=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,xr)===!1?!1:De(t,e)};/*! +* focus-trap 7.5.4 +* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE +*/function st(o,e){var t=Object.keys(o);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(o);e&&(r=r.filter(function(n){return Object.getOwnPropertyDescriptor(o,n).enumerable})),t.push.apply(t,r)}return t}function ut(o){for(var e=1;e0){var r=e[e.length-1];r!==t&&r.pause()}var n=e.indexOf(t);n===-1||e.splice(n,1),e.push(t)},deactivateTrap:function(e,t){var r=e.indexOf(t);r!==-1&&e.splice(r,1),e.length>0&&e[e.length-1].unpause()}},Ar=function(e){return e.tagName&&e.tagName.toLowerCase()==="input"&&typeof e.select=="function"},Tr=function(e){return(e==null?void 0:e.key)==="Escape"||(e==null?void 0:e.key)==="Esc"||(e==null?void 0:e.keyCode)===27},ge=function(e){return(e==null?void 0:e.key)==="Tab"||(e==null?void 0:e.keyCode)===9},Nr=function(e){return ge(e)&&!e.shiftKey},Cr=function(e){return ge(e)&&e.shiftKey},ct=function(e){return setTimeout(e,0)},ft=function(e,t){var r=-1;return e.every(function(n,a){return t(n)?(r=a,!1):!0}),r},ye=function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n1?p-1:0),I=1;I=0)c=r.activeElement;else{var f=i.tabbableGroups[0],p=f&&f.firstTabbableNode;c=p||h("fallbackFocus")}if(!c)throw new Error("Your focus-trap needs to have at least one focusable element");return c},v=function(){if(i.containerGroups=i.containers.map(function(c){var f=br(c,a.tabbableOptions),p=wr(c,a.tabbableOptions),C=f.length>0?f[0]:void 0,I=f.length>0?f[f.length-1]:void 0,M=p.find(function(m){return le(m)}),P=p.slice().reverse().find(function(m){return le(m)}),z=!!f.find(function(m){return se(m)>0});return{container:c,tabbableNodes:f,focusableNodes:p,posTabIndexesFound:z,firstTabbableNode:C,lastTabbableNode:I,firstDomTabbableNode:M,lastDomTabbableNode:P,nextTabbableNode:function(x){var $=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,K=f.indexOf(x);return K<0?$?p.slice(p.indexOf(x)+1).find(function(q){return le(q)}):p.slice(0,p.indexOf(x)).reverse().find(function(q){return le(q)}):f[K+($?1:-1)]}}}),i.tabbableGroups=i.containerGroups.filter(function(c){return c.tabbableNodes.length>0}),i.tabbableGroups.length<=0&&!h("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(i.containerGroups.find(function(c){return c.posTabIndexesFound})&&i.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},y=function w(c){var f=c.activeElement;if(f)return f.shadowRoot&&f.shadowRoot.activeElement!==null?w(f.shadowRoot):f},b=function w(c){if(c!==!1&&c!==y(document)){if(!c||!c.focus){w(d());return}c.focus({preventScroll:!!a.preventScroll}),i.mostRecentlyFocusedNode=c,Ar(c)&&c.select()}},E=function(c){var f=h("setReturnFocus",c);return f||(f===!1?!1:c)},g=function(c){var f=c.target,p=c.event,C=c.isBackward,I=C===void 0?!1:C;f=f||Ae(p),v();var M=null;if(i.tabbableGroups.length>0){var P=l(f,p),z=P>=0?i.containerGroups[P]:void 0;if(P<0)I?M=i.tabbableGroups[i.tabbableGroups.length-1].lastTabbableNode:M=i.tabbableGroups[0].firstTabbableNode;else if(I){var m=ft(i.tabbableGroups,function(V){var U=V.firstTabbableNode;return f===U});if(m<0&&(z.container===f||Re(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!z.nextTabbableNode(f,!1))&&(m=P),m>=0){var x=m===0?i.tabbableGroups.length-1:m-1,$=i.tabbableGroups[x];M=se(f)>=0?$.lastTabbableNode:$.lastDomTabbableNode}else ge(p)||(M=z.nextTabbableNode(f,!1))}else{var K=ft(i.tabbableGroups,function(V){var U=V.lastTabbableNode;return f===U});if(K<0&&(z.container===f||Re(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!z.nextTabbableNode(f))&&(K=P),K>=0){var q=K===i.tabbableGroups.length-1?0:K+1,H=i.tabbableGroups[q];M=se(f)>=0?H.firstTabbableNode:H.firstDomTabbableNode}else ge(p)||(M=z.nextTabbableNode(f))}}else M=h("fallbackFocus");return M},S=function(c){var f=Ae(c);if(!(l(f,c)>=0)){if(ye(a.clickOutsideDeactivates,c)){s.deactivate({returnFocus:a.returnFocusOnDeactivate});return}ye(a.allowOutsideClick,c)||c.preventDefault()}},T=function(c){var f=Ae(c),p=l(f,c)>=0;if(p||f instanceof Document)p&&(i.mostRecentlyFocusedNode=f);else{c.stopImmediatePropagation();var C,I=!0;if(i.mostRecentlyFocusedNode)if(se(i.mostRecentlyFocusedNode)>0){var M=l(i.mostRecentlyFocusedNode),P=i.containerGroups[M].tabbableNodes;if(P.length>0){var z=P.findIndex(function(m){return m===i.mostRecentlyFocusedNode});z>=0&&(a.isKeyForward(i.recentNavEvent)?z+1=0&&(C=P[z-1],I=!1))}}else i.containerGroups.some(function(m){return m.tabbableNodes.some(function(x){return se(x)>0})})||(I=!1);else I=!1;I&&(C=g({target:i.mostRecentlyFocusedNode,isBackward:a.isKeyBackward(i.recentNavEvent)})),b(C||i.mostRecentlyFocusedNode||d())}i.recentNavEvent=void 0},F=function(c){var f=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;i.recentNavEvent=c;var p=g({event:c,isBackward:f});p&&(ge(c)&&c.preventDefault(),b(p))},L=function(c){if(Tr(c)&&ye(a.escapeDeactivates,c)!==!1){c.preventDefault(),s.deactivate();return}(a.isKeyForward(c)||a.isKeyBackward(c))&&F(c,a.isKeyBackward(c))},R=function(c){var f=Ae(c);l(f,c)>=0||ye(a.clickOutsideDeactivates,c)||ye(a.allowOutsideClick,c)||(c.preventDefault(),c.stopImmediatePropagation())},B=function(){if(i.active)return lt.activateTrap(n,s),i.delayInitialFocusTimer=a.delayInitialFocus?ct(function(){b(d())}):b(d()),r.addEventListener("focusin",T,!0),r.addEventListener("mousedown",S,{capture:!0,passive:!1}),r.addEventListener("touchstart",S,{capture:!0,passive:!1}),r.addEventListener("click",R,{capture:!0,passive:!1}),r.addEventListener("keydown",L,{capture:!0,passive:!1}),s},N=function(){if(i.active)return r.removeEventListener("focusin",T,!0),r.removeEventListener("mousedown",S,!0),r.removeEventListener("touchstart",S,!0),r.removeEventListener("click",R,!0),r.removeEventListener("keydown",L,!0),s},_=function(c){var f=c.some(function(p){var C=Array.from(p.removedNodes);return C.some(function(I){return I===i.mostRecentlyFocusedNode})});f&&b(d())},A=typeof window<"u"&&"MutationObserver"in window?new MutationObserver(_):void 0,O=function(){A&&(A.disconnect(),i.active&&!i.paused&&i.containers.map(function(c){A.observe(c,{subtree:!0,childList:!0})}))};return s={get active(){return i.active},get paused(){return i.paused},activate:function(c){if(i.active)return this;var f=u(c,"onActivate"),p=u(c,"onPostActivate"),C=u(c,"checkCanFocusTrap");C||v(),i.active=!0,i.paused=!1,i.nodeFocusedBeforeActivation=r.activeElement,f==null||f();var I=function(){C&&v(),B(),O(),p==null||p()};return C?(C(i.containers.concat()).then(I,I),this):(I(),this)},deactivate:function(c){if(!i.active)return this;var f=ut({onDeactivate:a.onDeactivate,onPostDeactivate:a.onPostDeactivate,checkCanReturnFocus:a.checkCanReturnFocus},c);clearTimeout(i.delayInitialFocusTimer),i.delayInitialFocusTimer=void 0,N(),i.active=!1,i.paused=!1,O(),lt.deactivateTrap(n,s);var p=u(f,"onDeactivate"),C=u(f,"onPostDeactivate"),I=u(f,"checkCanReturnFocus"),M=u(f,"returnFocus","returnFocusOnDeactivate");p==null||p();var P=function(){ct(function(){M&&b(E(i.nodeFocusedBeforeActivation)),C==null||C()})};return M&&I?(I(E(i.nodeFocusedBeforeActivation)).then(P,P),this):(P(),this)},pause:function(c){if(i.paused||!i.active)return this;var f=u(c,"onPause"),p=u(c,"onPostPause");return i.paused=!0,f==null||f(),N(),O(),p==null||p(),this},unpause:function(c){if(!i.paused||!i.active)return this;var f=u(c,"onUnpause"),p=u(c,"onPostUnpause");return i.paused=!1,f==null||f(),v(),B(),O(),p==null||p(),this},updateContainerElements:function(c){var f=[].concat(c).filter(Boolean);return i.containers=f.map(function(p){return typeof p=="string"?r.querySelector(p):p}),i.active&&v(),O(),this}},s.updateContainerElements(e),s};function kr(o,e={}){let t;const{immediate:r,...n}=e,a=oe(!1),i=oe(!1),s=d=>t&&t.activate(d),u=d=>t&&t.deactivate(d),l=()=>{t&&(t.pause(),i.value=!0)},h=()=>{t&&(t.unpause(),i.value=!1)};return $e(()=>kt(o),d=>{d&&(t=Dr(d,{...n,onActivate(){a.value=!0,e.onActivate&&e.onActivate()},onDeactivate(){a.value=!1,e.onDeactivate&&e.onDeactivate()}}),r&&s())},{flush:"post"}),Ot(()=>u()),{hasFocus:a,isPaused:i,activate:s,deactivate:u,pause:l,unpause:h}}class fe{constructor(e,t=!0,r=[],n=5e3){this.ctx=e,this.iframes=t,this.exclude=r,this.iframesTimeout=n}static matches(e,t){const r=typeof t=="string"?[t]:t,n=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(n){let a=!1;return r.every(i=>n.call(e,i)?(a=!0,!1):!0),a}else return!1}getContexts(){let e,t=[];return typeof this.ctx>"u"||!this.ctx?e=[]:NodeList.prototype.isPrototypeOf(this.ctx)?e=Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?e=this.ctx:typeof this.ctx=="string"?e=Array.prototype.slice.call(document.querySelectorAll(this.ctx)):e=[this.ctx],e.forEach(r=>{const n=t.filter(a=>a.contains(r)).length>0;t.indexOf(r)===-1&&!n&&t.push(r)}),t}getIframeContents(e,t,r=()=>{}){let n;try{const a=e.contentWindow;if(n=a.document,!a||!n)throw new Error("iframe inaccessible")}catch{r()}n&&t(n)}isIframeBlank(e){const t="about:blank",r=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&r!==t&&r}observeIframeLoad(e,t,r){let n=!1,a=null;const i=()=>{if(!n){n=!0,clearTimeout(a);try{this.isIframeBlank(e)||(e.removeEventListener("load",i),this.getIframeContents(e,t,r))}catch{r()}}};e.addEventListener("load",i),a=setTimeout(i,this.iframesTimeout)}onIframeReady(e,t,r){try{e.contentWindow.document.readyState==="complete"?this.isIframeBlank(e)?this.observeIframeLoad(e,t,r):this.getIframeContents(e,t,r):this.observeIframeLoad(e,t,r)}catch{r()}}waitForIframes(e,t){let r=0;this.forEachIframe(e,()=>!0,n=>{r++,this.waitForIframes(n.querySelector("html"),()=>{--r||t()})},n=>{n||t()})}forEachIframe(e,t,r,n=()=>{}){let a=e.querySelectorAll("iframe"),i=a.length,s=0;a=Array.prototype.slice.call(a);const u=()=>{--i<=0&&n(s)};i||u(),a.forEach(l=>{fe.matches(l,this.exclude)?u():this.onIframeReady(l,h=>{t(l)&&(s++,r(h)),u()},u)})}createIterator(e,t,r){return document.createNodeIterator(e,t,r,!1)}createInstanceOnIframe(e){return new fe(e.querySelector("html"),this.iframes)}compareNodeIframe(e,t,r){const n=e.compareDocumentPosition(r),a=Node.DOCUMENT_POSITION_PRECEDING;if(n&a)if(t!==null){const i=t.compareDocumentPosition(r),s=Node.DOCUMENT_POSITION_FOLLOWING;if(i&s)return!0}else return!0;return!1}getIteratorNode(e){const t=e.previousNode();let r;return t===null?r=e.nextNode():r=e.nextNode()&&e.nextNode(),{prevNode:t,node:r}}checkIframeFilter(e,t,r,n){let a=!1,i=!1;return n.forEach((s,u)=>{s.val===r&&(a=u,i=s.handled)}),this.compareNodeIframe(e,t,r)?(a===!1&&!i?n.push({val:r,handled:!0}):a!==!1&&!i&&(n[a].handled=!0),!0):(a===!1&&n.push({val:r,handled:!1}),!1)}handleOpenIframes(e,t,r,n){e.forEach(a=>{a.handled||this.getIframeContents(a.val,i=>{this.createInstanceOnIframe(i).forEachNode(t,r,n)})})}iterateThroughNodes(e,t,r,n,a){const i=this.createIterator(t,e,n);let s=[],u=[],l,h,d=()=>({prevNode:h,node:l}=this.getIteratorNode(i),l);for(;d();)this.iframes&&this.forEachIframe(t,v=>this.checkIframeFilter(l,h,v,s),v=>{this.createInstanceOnIframe(v).forEachNode(e,y=>u.push(y),n)}),u.push(l);u.forEach(v=>{r(v)}),this.iframes&&this.handleOpenIframes(s,e,r,n),a()}forEachNode(e,t,r,n=()=>{}){const a=this.getContexts();let i=a.length;i||n(),a.forEach(s=>{const u=()=>{this.iterateThroughNodes(e,s,t,r,()=>{--i<=0&&n()})};this.iframes?this.waitForIframes(s,u):u()})}}let Or=class{constructor(e){this.ctx=e,this.ie=!1;const t=window.navigator.userAgent;(t.indexOf("MSIE")>-1||t.indexOf("Trident")>-1)&&(this.ie=!0)}set opt(e){this._opt=Object.assign({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:()=>{},noMatch:()=>{},filter:()=>!0,done:()=>{},debug:!1,log:window.console},e)}get opt(){return this._opt}get iterator(){return new fe(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}log(e,t="debug"){const r=this.opt.log;this.opt.debug&&typeof r=="object"&&typeof r[t]=="function"&&r[t](`mark.js: ${e}`)}escapeStr(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}createRegExp(e){return this.opt.wildcards!=="disabled"&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),this.opt.wildcards!=="disabled"&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),e}createSynonymsRegExp(e){const t=this.opt.synonyms,r=this.opt.caseSensitive?"":"i",n=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(let a in t)if(t.hasOwnProperty(a)){const i=t[a],s=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(a):this.escapeStr(a),u=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(i):this.escapeStr(i);s!==""&&u!==""&&(e=e.replace(new RegExp(`(${this.escapeStr(s)}|${this.escapeStr(u)})`,`gm${r}`),n+`(${this.processSynomyms(s)}|${this.processSynomyms(u)})`+n))}return e}processSynomyms(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}setupWildcardsRegExp(e){return e=e.replace(/(?:\\)*\?/g,t=>t.charAt(0)==="\\"?"?":""),e.replace(/(?:\\)*\*/g,t=>t.charAt(0)==="\\"?"*":"")}createWildcardsRegExp(e){let t=this.opt.wildcards==="withSpaces";return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}setupIgnoreJoinersRegExp(e){return e.replace(/[^(|)\\]/g,(t,r,n)=>{let a=n.charAt(r+1);return/[(|)\\]/.test(a)||a===""?t:t+"\0"})}createJoinersRegExp(e){let t=[];const r=this.opt.ignorePunctuation;return Array.isArray(r)&&r.length&&t.push(this.escapeStr(r.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join(`[${t.join("")}]*`):e}createDiacriticsRegExp(e){const t=this.opt.caseSensitive?"":"i",r=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"];let n=[];return e.split("").forEach(a=>{r.every(i=>{if(i.indexOf(a)!==-1){if(n.indexOf(i)>-1)return!1;e=e.replace(new RegExp(`[${i}]`,`gm${t}`),`[${i}]`),n.push(i)}return!0})}),e}createMergedBlanksRegExp(e){return e.replace(/[\s]+/gmi,"[\\s]+")}createAccuracyRegExp(e){const t="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿";let r=this.opt.accuracy,n=typeof r=="string"?r:r.value,a=typeof r=="string"?[]:r.limiters,i="";switch(a.forEach(s=>{i+=`|${this.escapeStr(s)}`}),n){case"partially":default:return`()(${e})`;case"complementary":return i="\\s"+(i||this.escapeStr(t)),`()([^${i}]*${e}[^${i}]*)`;case"exactly":return`(^|\\s${i})(${e})(?=$|\\s${i})`}}getSeparatedKeywords(e){let t=[];return e.forEach(r=>{this.opt.separateWordSearch?r.split(" ").forEach(n=>{n.trim()&&t.indexOf(n)===-1&&t.push(n)}):r.trim()&&t.indexOf(r)===-1&&t.push(r)}),{keywords:t.sort((r,n)=>n.length-r.length),length:t.length}}isNumeric(e){return Number(parseFloat(e))==e}checkRanges(e){if(!Array.isArray(e)||Object.prototype.toString.call(e[0])!=="[object Object]")return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];const t=[];let r=0;return e.sort((n,a)=>n.start-a.start).forEach(n=>{let{start:a,end:i,valid:s}=this.callNoMatchOnInvalidRanges(n,r);s&&(n.start=a,n.length=i-a,t.push(n),r=i)}),t}callNoMatchOnInvalidRanges(e,t){let r,n,a=!1;return e&&typeof e.start<"u"?(r=parseInt(e.start,10),n=r+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&n-t>0&&n-r>0?a=!0:(this.log(`Ignoring invalid or overlapping range: ${JSON.stringify(e)}`),this.opt.noMatch(e))):(this.log(`Ignoring invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)),{start:r,end:n,valid:a}}checkWhitespaceRanges(e,t,r){let n,a=!0,i=r.length,s=t-i,u=parseInt(e.start,10)-s;return u=u>i?i:u,n=u+parseInt(e.length,10),n>i&&(n=i,this.log(`End range automatically set to the max value of ${i}`)),u<0||n-u<0||u>i||n>i?(a=!1,this.log(`Invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)):r.substring(u,n).replace(/\s+/g,"")===""&&(a=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:u,end:n,valid:a}}getTextNodes(e){let t="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,n=>{r.push({start:t.length,end:(t+=n.textContent).length,node:n})},n=>this.matchesExclude(n.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT,()=>{e({value:t,nodes:r})})}matchesExclude(e){return fe.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}wrapRangeInTextNode(e,t,r){const n=this.opt.element?this.opt.element:"mark",a=e.splitText(t),i=a.splitText(r-t);let s=document.createElement(n);return s.setAttribute("data-markjs","true"),this.opt.className&&s.setAttribute("class",this.opt.className),s.textContent=a.textContent,a.parentNode.replaceChild(s,a),i}wrapRangeInMappedTextNode(e,t,r,n,a){e.nodes.every((i,s)=>{const u=e.nodes[s+1];if(typeof u>"u"||u.start>t){if(!n(i.node))return!1;const l=t-i.start,h=(r>i.end?i.end:r)-i.start,d=e.value.substr(0,i.start),v=e.value.substr(h+i.start);if(i.node=this.wrapRangeInTextNode(i.node,l,h),e.value=d+v,e.nodes.forEach((y,b)=>{b>=s&&(e.nodes[b].start>0&&b!==s&&(e.nodes[b].start-=h),e.nodes[b].end-=h)}),r-=h,a(i.node.previousSibling,i.start),r>i.end)t=i.end;else return!1}return!0})}wrapMatches(e,t,r,n,a){const i=t===0?0:t+1;this.getTextNodes(s=>{s.nodes.forEach(u=>{u=u.node;let l;for(;(l=e.exec(u.textContent))!==null&&l[i]!=="";){if(!r(l[i],u))continue;let h=l.index;if(i!==0)for(let d=1;d{let u;for(;(u=e.exec(s.value))!==null&&u[i]!=="";){let l=u.index;if(i!==0)for(let d=1;dr(u[i],d),(d,v)=>{e.lastIndex=v,n(d)})}a()})}wrapRangeFromIndex(e,t,r,n){this.getTextNodes(a=>{const i=a.value.length;e.forEach((s,u)=>{let{start:l,end:h,valid:d}=this.checkWhitespaceRanges(s,i,a.value);d&&this.wrapRangeInMappedTextNode(a,l,h,v=>t(v,s,a.value.substring(l,h),u),v=>{r(v,s)})}),n()})}unwrapMatches(e){const t=e.parentNode;let r=document.createDocumentFragment();for(;e.firstChild;)r.appendChild(e.removeChild(e.firstChild));t.replaceChild(r,e),this.ie?this.normalizeTextNode(t):t.normalize()}normalizeTextNode(e){if(e){if(e.nodeType===3)for(;e.nextSibling&&e.nextSibling.nodeType===3;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}markRegExp(e,t){this.opt=t,this.log(`Searching with expression "${e}"`);let r=0,n="wrapMatches";const a=i=>{r++,this.opt.each(i)};this.opt.acrossElements&&(n="wrapMatchesAcrossElements"),this[n](e,this.opt.ignoreGroups,(i,s)=>this.opt.filter(s,i,r),a,()=>{r===0&&this.opt.noMatch(e),this.opt.done(r)})}mark(e,t){this.opt=t;let r=0,n="wrapMatches";const{keywords:a,length:i}=this.getSeparatedKeywords(typeof e=="string"?[e]:e),s=this.opt.caseSensitive?"":"i",u=l=>{let h=new RegExp(this.createRegExp(l),`gm${s}`),d=0;this.log(`Searching with expression "${h}"`),this[n](h,1,(v,y)=>this.opt.filter(y,l,r,d),v=>{d++,r++,this.opt.each(v)},()=>{d===0&&this.opt.noMatch(l),a[i-1]===l?this.opt.done(r):u(a[a.indexOf(l)+1])})};this.opt.acrossElements&&(n="wrapMatchesAcrossElements"),i===0?this.opt.done(r):u(a[0])}markRanges(e,t){this.opt=t;let r=0,n=this.checkRanges(e);n&&n.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(n)),this.wrapRangeFromIndex(n,(a,i,s,u)=>this.opt.filter(a,i,s,u),(a,i)=>{r++,this.opt.each(a,i)},()=>{this.opt.done(r)})):this.opt.done(r)}unmark(e){this.opt=e;let t=this.opt.element?this.opt.element:"*";t+="[data-markjs]",this.opt.className&&(t+=`.${this.opt.className}`),this.log(`Removal selector "${t}"`),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,r=>{this.unwrapMatches(r)},r=>{const n=fe.matches(r,t),a=this.matchesExclude(r);return!n||a?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}};function _r(o){const e=new Or(o);return this.mark=(t,r)=>(e.mark(t,r),this),this.markRegExp=(t,r)=>(e.markRegExp(t,r),this),this.markRanges=(t,r)=>(e.markRanges(t,r),this),this.unmark=t=>(e.unmark(t),this),this}var W=function(){return W=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])&&(l[0]===6||l[0]===2)){t=0;continue}if(l[0]===3&&(!a||l[1]>a[0]&&l[1]=o.length&&(o=void 0),{value:o&&o[r++],done:!o}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function J(o,e){var t=typeof Symbol=="function"&&o[Symbol.iterator];if(!t)return o;var r=t.call(o),n,a=[],i;try{for(;(e===void 0||e-- >0)&&!(n=r.next()).done;)a.push(n.value)}catch(s){i={error:s}}finally{try{n&&!n.done&&(t=r.return)&&t.call(r)}finally{if(i)throw i.error}}return a}var Lr="ENTRIES",Et="KEYS",St="VALUES",G="",Me=function(){function o(e,t){var r=e._tree,n=Array.from(r.keys());this.set=e,this._type=t,this._path=n.length>0?[{node:r,keys:n}]:[]}return o.prototype.next=function(){var e=this.dive();return this.backtrack(),e},o.prototype.dive=function(){if(this._path.length===0)return{done:!0,value:void 0};var e=ce(this._path),t=e.node,r=e.keys;if(ce(r)===G)return{done:!1,value:this.result()};var n=t.get(ce(r));return this._path.push({node:n,keys:Array.from(n.keys())}),this.dive()},o.prototype.backtrack=function(){if(this._path.length!==0){var e=ce(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}},o.prototype.key=function(){return this.set._prefix+this._path.map(function(e){var t=e.keys;return ce(t)}).filter(function(e){return e!==G}).join("")},o.prototype.value=function(){return ce(this._path).node.get(G)},o.prototype.result=function(){switch(this._type){case St:return this.value();case Et:return this.key();default:return[this.key(),this.value()]}},o.prototype[Symbol.iterator]=function(){return this},o}(),ce=function(o){return o[o.length-1]},Pr=function(o,e,t){var r=new Map;if(e===void 0)return r;for(var n=e.length+1,a=n+t,i=new Uint8Array(a*n).fill(t+1),s=0;st)continue e}At(o.get(y),e,t,r,n,E,i,s+y)}}}catch(f){u={error:f}}finally{try{v&&!v.done&&(l=d.return)&&l.call(d)}finally{if(u)throw u.error}}},Le=function(){function o(e,t){e===void 0&&(e=new Map),t===void 0&&(t=""),this._size=void 0,this._tree=e,this._prefix=t}return o.prototype.atPrefix=function(e){var t,r;if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");var n=J(ke(this._tree,e.slice(this._prefix.length)),2),a=n[0],i=n[1];if(a===void 0){var s=J(je(i),2),u=s[0],l=s[1];try{for(var h=D(u.keys()),d=h.next();!d.done;d=h.next()){var v=d.value;if(v!==G&&v.startsWith(l)){var y=new Map;return y.set(v.slice(l.length),u.get(v)),new o(y,e)}}}catch(b){t={error:b}}finally{try{d&&!d.done&&(r=h.return)&&r.call(h)}finally{if(t)throw t.error}}}return new o(a,e)},o.prototype.clear=function(){this._size=void 0,this._tree.clear()},o.prototype.delete=function(e){return this._size=void 0,zr(this._tree,e)},o.prototype.entries=function(){return new Me(this,Lr)},o.prototype.forEach=function(e){var t,r;try{for(var n=D(this),a=n.next();!a.done;a=n.next()){var i=J(a.value,2),s=i[0],u=i[1];e(s,u,this)}}catch(l){t={error:l}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}},o.prototype.fuzzyGet=function(e,t){return Pr(this._tree,e,t)},o.prototype.get=function(e){var t=Ke(this._tree,e);return t!==void 0?t.get(G):void 0},o.prototype.has=function(e){var t=Ke(this._tree,e);return t!==void 0&&t.has(G)},o.prototype.keys=function(){return new Me(this,Et)},o.prototype.set=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Pe(this._tree,e);return r.set(G,t),this},Object.defineProperty(o.prototype,"size",{get:function(){if(this._size)return this._size;this._size=0;for(var e=this.entries();!e.next().done;)this._size+=1;return this._size},enumerable:!1,configurable:!0}),o.prototype.update=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Pe(this._tree,e);return r.set(G,t(r.get(G))),this},o.prototype.fetch=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Pe(this._tree,e),n=r.get(G);return n===void 0&&r.set(G,n=t()),n},o.prototype.values=function(){return new Me(this,St)},o.prototype[Symbol.iterator]=function(){return this.entries()},o.from=function(e){var t,r,n=new o;try{for(var a=D(e),i=a.next();!i.done;i=a.next()){var s=J(i.value,2),u=s[0],l=s[1];n.set(u,l)}}catch(h){t={error:h}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n},o.fromObject=function(e){return o.from(Object.entries(e))},o}(),ke=function(o,e,t){var r,n;if(t===void 0&&(t=[]),e.length===0||o==null)return[o,t];try{for(var a=D(o.keys()),i=a.next();!i.done;i=a.next()){var s=i.value;if(s!==G&&e.startsWith(s))return t.push([o,s]),ke(o.get(s),e.slice(s.length),t)}}catch(u){r={error:u}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(r)throw r.error}}return t.push([o,e]),ke(void 0,"",t)},Ke=function(o,e){var t,r;if(e.length===0||o==null)return o;try{for(var n=D(o.keys()),a=n.next();!a.done;a=n.next()){var i=a.value;if(i!==G&&e.startsWith(i))return Ke(o.get(i),e.slice(i.length))}}catch(s){t={error:s}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}},Pe=function(o,e){var t,r,n=e.length;e:for(var a=0;o&&a0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new Le,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}},o.prototype.discard=function(e){var t=this,r=this._idToShortId.get(e);if(r==null)throw new Error("MiniSearch: cannot discard document with ID ".concat(e,": it is not in the index"));this._idToShortId.delete(e),this._documentIds.delete(r),this._storedFields.delete(r),(this._fieldLength.get(r)||[]).forEach(function(n,a){t.removeFieldLength(r,a,t._documentCount,n)}),this._fieldLength.delete(r),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()},o.prototype.maybeAutoVacuum=function(){if(this._options.autoVacuum!==!1){var e=this._options.autoVacuum,t=e.minDirtFactor,r=e.minDirtCount,n=e.batchSize,a=e.batchWait;this.conditionalVacuum({batchSize:n,batchWait:a},{minDirtCount:r,minDirtFactor:t})}},o.prototype.discardAll=function(e){var t,r,n=this._options.autoVacuum;try{this._options.autoVacuum=!1;try{for(var a=D(e),i=a.next();!i.done;i=a.next()){var s=i.value;this.discard(s)}}catch(u){t={error:u}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}finally{this._options.autoVacuum=n}this.maybeAutoVacuum()},o.prototype.replace=function(e){var t=this._options,r=t.idField,n=t.extractField,a=n(e,r);this.discard(a),this.add(e)},o.prototype.vacuum=function(e){return e===void 0&&(e={}),this.conditionalVacuum(e)},o.prototype.conditionalVacuum=function(e,t){var r=this;return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(function(){var n=r._enqueuedVacuumConditions;return r._enqueuedVacuumConditions=Ue,r.performVacuuming(e,n)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)},o.prototype.performVacuuming=function(e,t){return Rr(this,void 0,void 0,function(){var r,n,a,i,s,u,l,h,d,v,y,b,E,g,S,T,F,L,R,B,N,_,A,O,w;return Mr(this,function(c){switch(c.label){case 0:if(r=this._dirtCount,!this.vacuumConditionsMet(t))return[3,10];n=e.batchSize||Je.batchSize,a=e.batchWait||Je.batchWait,i=1,c.label=1;case 1:c.trys.push([1,7,8,9]),s=D(this._index),u=s.next(),c.label=2;case 2:if(u.done)return[3,6];l=J(u.value,2),h=l[0],d=l[1];try{for(v=(_=void 0,D(d)),y=v.next();!y.done;y=v.next()){b=J(y.value,2),E=b[0],g=b[1];try{for(S=(O=void 0,D(g)),T=S.next();!T.done;T=S.next())F=J(T.value,1),L=F[0],!this._documentIds.has(L)&&(g.size<=1?d.delete(E):g.delete(L))}catch(f){O={error:f}}finally{try{T&&!T.done&&(w=S.return)&&w.call(S)}finally{if(O)throw O.error}}}}catch(f){_={error:f}}finally{try{y&&!y.done&&(A=v.return)&&A.call(v)}finally{if(_)throw _.error}}return this._index.get(h).size===0&&this._index.delete(h),i%n!==0?[3,4]:[4,new Promise(function(f){return setTimeout(f,a)})];case 3:c.sent(),c.label=4;case 4:i+=1,c.label=5;case 5:return u=s.next(),[3,2];case 6:return[3,9];case 7:return R=c.sent(),B={error:R},[3,9];case 8:try{u&&!u.done&&(N=s.return)&&N.call(s)}finally{if(B)throw B.error}return[7];case 9:this._dirtCount-=r,c.label=10;case 10:return[4,null];case 11:return c.sent(),this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null,[2]}})})},o.prototype.vacuumConditionsMet=function(e){if(e==null)return!0;var t=e.minDirtCount,r=e.minDirtFactor;return t=t||Be.minDirtCount,r=r||Be.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=r},Object.defineProperty(o.prototype,"isVacuuming",{get:function(){return this._currentVacuum!=null},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtCount",{get:function(){return this._dirtCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtFactor",{get:function(){return this._dirtCount/(1+this._documentCount+this._dirtCount)},enumerable:!1,configurable:!0}),o.prototype.has=function(e){return this._idToShortId.has(e)},o.prototype.getStoredFields=function(e){var t=this._idToShortId.get(e);if(t!=null)return this._storedFields.get(t)},o.prototype.search=function(e,t){var r,n;t===void 0&&(t={});var a=this.executeQuery(e,t),i=[];try{for(var s=D(a),u=s.next();!u.done;u=s.next()){var l=J(u.value,2),h=l[0],d=l[1],v=d.score,y=d.terms,b=d.match,E=y.length||1,g={id:this._documentIds.get(h),score:v*E,terms:Object.keys(b),queryTerms:y,match:b};Object.assign(g,this._storedFields.get(h)),(t.filter==null||t.filter(g))&&i.push(g)}}catch(S){r={error:S}}finally{try{u&&!u.done&&(n=s.return)&&n.call(s)}finally{if(r)throw r.error}}return e===o.wildcard&&t.boostDocument==null&&this._options.searchOptions.boostDocument==null||i.sort(vt),i},o.prototype.autoSuggest=function(e,t){var r,n,a,i;t===void 0&&(t={}),t=W(W({},this._options.autoSuggestOptions),t);var s=new Map;try{for(var u=D(this.search(e,t)),l=u.next();!l.done;l=u.next()){var h=l.value,d=h.score,v=h.terms,y=v.join(" "),b=s.get(y);b!=null?(b.score+=d,b.count+=1):s.set(y,{score:d,terms:v,count:1})}}catch(R){r={error:R}}finally{try{l&&!l.done&&(n=u.return)&&n.call(u)}finally{if(r)throw r.error}}var E=[];try{for(var g=D(s),S=g.next();!S.done;S=g.next()){var T=J(S.value,2),b=T[0],F=T[1],d=F.score,v=F.terms,L=F.count;E.push({suggestion:b,terms:v,score:d/L})}}catch(R){a={error:R}}finally{try{S&&!S.done&&(i=g.return)&&i.call(g)}finally{if(a)throw a.error}}return E.sort(vt),E},Object.defineProperty(o.prototype,"documentCount",{get:function(){return this._documentCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"termCount",{get:function(){return this._index.size},enumerable:!1,configurable:!0}),o.loadJSON=function(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)},o.getDefault=function(e){if(Ve.hasOwnProperty(e))return ze(Ve,e);throw new Error('MiniSearch: unknown option "'.concat(e,'"'))},o.loadJS=function(e,t){var r,n,a,i,s,u,l=e.index,h=e.documentCount,d=e.nextId,v=e.documentIds,y=e.fieldIds,b=e.fieldLength,E=e.averageFieldLength,g=e.storedFields,S=e.dirtCount,T=e.serializationVersion;if(T!==1&&T!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");var F=new o(t);F._documentCount=h,F._nextId=d,F._documentIds=Te(v),F._idToShortId=new Map,F._fieldIds=y,F._fieldLength=Te(b),F._avgFieldLength=E,F._storedFields=Te(g),F._dirtCount=S||0,F._index=new Le;try{for(var L=D(F._documentIds),R=L.next();!R.done;R=L.next()){var B=J(R.value,2),N=B[0],_=B[1];F._idToShortId.set(_,N)}}catch(z){r={error:z}}finally{try{R&&!R.done&&(n=L.return)&&n.call(L)}finally{if(r)throw r.error}}try{for(var A=D(l),O=A.next();!O.done;O=A.next()){var w=J(O.value,2),c=w[0],f=w[1],p=new Map;try{for(var C=(s=void 0,D(Object.keys(f))),I=C.next();!I.done;I=C.next()){var M=I.value,P=f[M];T===1&&(P=P.ds),p.set(parseInt(M,10),Te(P))}}catch(z){s={error:z}}finally{try{I&&!I.done&&(u=C.return)&&u.call(C)}finally{if(s)throw s.error}}F._index.set(c,p)}}catch(z){a={error:z}}finally{try{O&&!O.done&&(i=A.return)&&i.call(A)}finally{if(a)throw a.error}}return F},o.prototype.executeQuery=function(e,t){var r=this;if(t===void 0&&(t={}),e===o.wildcard)return this.executeWildcardQuery(t);if(typeof e!="string"){var n=W(W(W({},t),e),{queries:void 0}),a=e.queries.map(function(g){return r.executeQuery(g,n)});return this.combineResults(a,n.combineWith)}var i=this._options,s=i.tokenize,u=i.processTerm,l=i.searchOptions,h=W(W({tokenize:s,processTerm:u},l),t),d=h.tokenize,v=h.processTerm,y=d(e).flatMap(function(g){return v(g)}).filter(function(g){return!!g}),b=y.map(Jr(h)),E=b.map(function(g){return r.executeQuerySpec(g,h)});return this.combineResults(E,h.combineWith)},o.prototype.executeQuerySpec=function(e,t){var r,n,a,i,s=W(W({},this._options.searchOptions),t),u=(s.fields||this._options.fields).reduce(function(M,P){var z;return W(W({},M),(z={},z[P]=ze(s.boost,P)||1,z))},{}),l=s.boostDocument,h=s.weights,d=s.maxFuzzy,v=s.bm25,y=W(W({},ht.weights),h),b=y.fuzzy,E=y.prefix,g=this._index.get(e.term),S=this.termResults(e.term,e.term,1,g,u,l,v),T,F;if(e.prefix&&(T=this._index.atPrefix(e.term)),e.fuzzy){var L=e.fuzzy===!0?.2:e.fuzzy,R=L<1?Math.min(d,Math.round(e.term.length*L)):L;R&&(F=this._index.fuzzyGet(e.term,R))}if(T)try{for(var B=D(T),N=B.next();!N.done;N=B.next()){var _=J(N.value,2),A=_[0],O=_[1],w=A.length-e.term.length;if(w){F==null||F.delete(A);var c=E*A.length/(A.length+.3*w);this.termResults(e.term,A,c,O,u,l,v,S)}}}catch(M){r={error:M}}finally{try{N&&!N.done&&(n=B.return)&&n.call(B)}finally{if(r)throw r.error}}if(F)try{for(var f=D(F.keys()),p=f.next();!p.done;p=f.next()){var A=p.value,C=J(F.get(A),2),I=C[0],w=C[1];if(w){var c=b*A.length/(A.length+w);this.termResults(e.term,A,c,I,u,l,v,S)}}}catch(M){a={error:M}}finally{try{p&&!p.done&&(i=f.return)&&i.call(f)}finally{if(a)throw a.error}}return S},o.prototype.executeWildcardQuery=function(e){var t,r,n=new Map,a=W(W({},this._options.searchOptions),e);try{for(var i=D(this._documentIds),s=i.next();!s.done;s=i.next()){var u=J(s.value,2),l=u[0],h=u[1],d=a.boostDocument?a.boostDocument(h,"",this._storedFields.get(l)):1;n.set(l,{score:d,terms:[],match:{}})}}catch(v){t={error:v}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return n},o.prototype.combineResults=function(e,t){if(t===void 0&&(t=Ge),e.length===0)return new Map;var r=t.toLowerCase();return e.reduce($r[r])||new Map},o.prototype.toJSON=function(){var e,t,r,n,a=[];try{for(var i=D(this._index),s=i.next();!s.done;s=i.next()){var u=J(s.value,2),l=u[0],h=u[1],d={};try{for(var v=(r=void 0,D(h)),y=v.next();!y.done;y=v.next()){var b=J(y.value,2),E=b[0],g=b[1];d[E]=Object.fromEntries(g)}}catch(S){r={error:S}}finally{try{y&&!y.done&&(n=v.return)&&n.call(v)}finally{if(r)throw r.error}}a.push([l,d])}}catch(S){e={error:S}}finally{try{s&&!s.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:a,serializationVersion:2}},o.prototype.termResults=function(e,t,r,n,a,i,s,u){var l,h,d,v,y;if(u===void 0&&(u=new Map),n==null)return u;try{for(var b=D(Object.keys(a)),E=b.next();!E.done;E=b.next()){var g=E.value,S=a[g],T=this._fieldIds[g],F=n.get(T);if(F!=null){var L=F.size,R=this._avgFieldLength[T];try{for(var B=(d=void 0,D(F.keys())),N=B.next();!N.done;N=B.next()){var _=N.value;if(!this._documentIds.has(_)){this.removeTerm(T,_,t),L-=1;continue}var A=i?i(this._documentIds.get(_),t,this._storedFields.get(_)):1;if(A){var O=F.get(_),w=this._fieldLength.get(_)[T],c=Kr(O,L,this._documentCount,w,R,s),f=r*S*A*c,p=u.get(_);if(p){p.score+=f,jr(p.terms,e);var C=ze(p.match,t);C?C.push(g):p.match[t]=[g]}else u.set(_,{score:f,terms:[e],match:(y={},y[t]=[g],y)})}}}catch(I){d={error:I}}finally{try{N&&!N.done&&(v=B.return)&&v.call(B)}finally{if(d)throw d.error}}}}}catch(I){l={error:I}}finally{try{E&&!E.done&&(h=b.return)&&h.call(b)}finally{if(l)throw l.error}}return u},o.prototype.addTerm=function(e,t,r){var n=this._index.fetch(r,pt),a=n.get(e);if(a==null)a=new Map,a.set(t,1),n.set(e,a);else{var i=a.get(t);a.set(t,(i||0)+1)}},o.prototype.removeTerm=function(e,t,r){if(!this._index.has(r)){this.warnDocumentChanged(t,e,r);return}var n=this._index.fetch(r,pt),a=n.get(e);a==null||a.get(t)==null?this.warnDocumentChanged(t,e,r):a.get(t)<=1?a.size<=1?n.delete(e):a.delete(t):a.set(t,a.get(t)-1),this._index.get(r).size===0&&this._index.delete(r)},o.prototype.warnDocumentChanged=function(e,t,r){var n,a;try{for(var i=D(Object.keys(this._fieldIds)),s=i.next();!s.done;s=i.next()){var u=s.value;if(this._fieldIds[u]===t){this._options.logger("warn","MiniSearch: document with ID ".concat(this._documentIds.get(e),' has changed before removal: term "').concat(r,'" was not present in field "').concat(u,'". Removing a document after it has changed can corrupt the index!'),"version_conflict");return}}}catch(l){n={error:l}}finally{try{s&&!s.done&&(a=i.return)&&a.call(i)}finally{if(n)throw n.error}}},o.prototype.addDocumentId=function(e){var t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t},o.prototype.addFields=function(e){for(var t=0;t(Ht("data-v-4eeb92d2"),o=o(),Qt(),o),Hr=["aria-owns"],Qr={class:"shell"},Yr=["title"],Zr=Y(()=>k("span",{"aria-hidden":"true",class:"vpi-search search-icon local-search-icon"},null,-1)),Xr=[Zr],ea={class:"search-actions before"},ta=["title"],ra=Y(()=>k("span",{class:"vpi-arrow-left local-search-icon"},null,-1)),aa=[ra],na=["placeholder"],ia={class:"search-actions"},oa=["title"],sa=Y(()=>k("span",{class:"vpi-layout-list local-search-icon"},null,-1)),ua=[sa],la=["disabled","title"],ca=Y(()=>k("span",{class:"vpi-delete local-search-icon"},null,-1)),fa=[ca],ha=["id","role","aria-labelledby"],da=["aria-selected"],va=["href","aria-label","onMouseenter","onFocusin"],pa={class:"titles"},ya=Y(()=>k("span",{class:"title-icon"},"#",-1)),ma=["innerHTML"],ga=Y(()=>k("span",{class:"vpi-chevron-right local-search-icon"},null,-1)),ba={class:"title main"},wa=["innerHTML"],xa={key:0,class:"excerpt-wrapper"},Fa={key:0,class:"excerpt",inert:""},Ea=["innerHTML"],Sa=Y(()=>k("div",{class:"excerpt-gradient-bottom"},null,-1)),Aa=Y(()=>k("div",{class:"excerpt-gradient-top"},null,-1)),Ta={key:0,class:"no-results"},Na={class:"search-keyboard-shortcuts"},Ca=["aria-label"],Ia=Y(()=>k("span",{class:"vpi-arrow-up navigate-icon"},null,-1)),Da=[Ia],ka=["aria-label"],Oa=Y(()=>k("span",{class:"vpi-arrow-down navigate-icon"},null,-1)),_a=[Oa],Ra=["aria-label"],Ma=Y(()=>k("span",{class:"vpi-corner-down-left navigate-icon"},null,-1)),La=[Ma],Pa=["aria-label"],za=_t({__name:"VPLocalSearchBox",emits:["close"],setup(o,{emit:e}){var P,z;const t=e,r=xe(),n=xe(),a=xe(nr),i=rr(),{activate:s}=kr(r,{immediate:!0,allowOutsideClick:!0,clickOutsideDeactivates:!0,escapeDeactivates:!0}),{localeIndex:u,theme:l}=i,h=tt(async()=>{var m,x,$,K,q,H,V,U,Z;return it(Br.loadJSON(($=await((x=(m=a.value)[u.value])==null?void 0:x.call(m)))==null?void 0:$.default,{fields:["title","titles","text"],storeFields:["title","titles"],searchOptions:{fuzzy:.2,prefix:!0,boost:{title:4,text:2,titles:1},...((K=l.value.search)==null?void 0:K.provider)==="local"&&((H=(q=l.value.search.options)==null?void 0:q.miniSearch)==null?void 0:H.searchOptions)},...((V=l.value.search)==null?void 0:V.provider)==="local"&&((Z=(U=l.value.search.options)==null?void 0:U.miniSearch)==null?void 0:Z.options)}))}),v=Fe(()=>{var m,x;return((m=l.value.search)==null?void 0:m.provider)==="local"&&((x=l.value.search.options)==null?void 0:x.disableQueryPersistence)===!0}).value?oe(""):Rt("vitepress:local-search-filter",""),y=Mt("vitepress:local-search-detailed-list",((P=l.value.search)==null?void 0:P.provider)==="local"&&((z=l.value.search.options)==null?void 0:z.detailedView)===!0),b=Fe(()=>{var m,x,$;return((m=l.value.search)==null?void 0:m.provider)==="local"&&(((x=l.value.search.options)==null?void 0:x.disableDetailedView)===!0||(($=l.value.search.options)==null?void 0:$.detailedView)===!1)}),E=Fe(()=>{var x,$,K,q,H,V,U;const m=((x=l.value.search)==null?void 0:x.options)??l.value.algolia;return((H=(q=(K=($=m==null?void 0:m.locales)==null?void 0:$[u.value])==null?void 0:K.translations)==null?void 0:q.button)==null?void 0:H.buttonText)||((U=(V=m==null?void 0:m.translations)==null?void 0:V.button)==null?void 0:U.buttonText)||"Search"});Lt(()=>{b.value&&(y.value=!1)});const g=xe([]),S=oe(!1);$e(v,()=>{S.value=!1});const T=tt(async()=>{if(n.value)return it(new _r(n.value))},null),F=new qr(16);Pt(()=>[h.value,v.value,y.value],async([m,x,$],K,q)=>{var be,qe,He,Qe;(K==null?void 0:K[0])!==m&&F.clear();let H=!1;if(q(()=>{H=!0}),!m)return;g.value=m.search(x).slice(0,16),S.value=!0;const V=$?await Promise.all(g.value.map(Q=>L(Q.id))):[];if(H)return;for(const{id:Q,mod:ae}of V){const ne=Q.slice(0,Q.indexOf("#"));let te=F.get(ne);if(te)continue;te=new Map,F.set(ne,te);const X=ae.default??ae;if(X!=null&&X.render||X!=null&&X.setup){const ie=Yt(X);ie.config.warnHandler=()=>{},ie.provide(Zt,i),Object.defineProperties(ie.config.globalProperties,{$frontmatter:{get(){return i.frontmatter.value}},$params:{get(){return i.page.value.params}}});const Ye=document.createElement("div");ie.mount(Ye),Ye.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(he=>{var et;const we=(et=he.querySelector("a"))==null?void 0:et.getAttribute("href"),Ze=(we==null?void 0:we.startsWith("#"))&&we.slice(1);if(!Ze)return;let Xe="";for(;(he=he.nextElementSibling)&&!/^h[1-6]$/i.test(he.tagName);)Xe+=he.outerHTML;te.set(Ze,Xe)}),ie.unmount()}if(H)return}const U=new Set;if(g.value=g.value.map(Q=>{const[ae,ne]=Q.id.split("#"),te=F.get(ae),X=(te==null?void 0:te.get(ne))??"";for(const ie in Q.match)U.add(ie);return{...Q,text:X}}),await de(),H)return;await new Promise(Q=>{var ae;(ae=T.value)==null||ae.unmark({done:()=>{var ne;(ne=T.value)==null||ne.markRegExp(M(U),{done:Q})}})});const Z=((be=r.value)==null?void 0:be.querySelectorAll(".result .excerpt"))??[];for(const Q of Z)(qe=Q.querySelector('mark[data-markjs="true"]'))==null||qe.scrollIntoView({block:"center"});(Qe=(He=n.value)==null?void 0:He.firstElementChild)==null||Qe.scrollIntoView({block:"start"})},{debounce:200,immediate:!0});async function L(m){const x=Xt(m.slice(0,m.indexOf("#")));try{if(!x)throw new Error(`Cannot find file for id: ${m}`);return{id:m,mod:await yt(()=>import(x),[])}}catch($){return console.error($),{id:m,mod:{}}}}const R=oe(),B=Fe(()=>{var m;return((m=v.value)==null?void 0:m.length)<=0});function N(m=!0){var x,$;(x=R.value)==null||x.focus(),m&&(($=R.value)==null||$.select())}_e(()=>{N()});function _(m){m.pointerType==="mouse"&&N()}const A=oe(-1),O=oe(!1);$e(g,m=>{A.value=m.length?0:-1,w()});function w(){de(()=>{const m=document.querySelector(".result.selected");m&&m.scrollIntoView({block:"nearest"})})}Ee("ArrowUp",m=>{m.preventDefault(),A.value--,A.value<0&&(A.value=g.value.length-1),O.value=!0,w()}),Ee("ArrowDown",m=>{m.preventDefault(),A.value++,A.value>=g.value.length&&(A.value=0),O.value=!0,w()});const c=zt();Ee("Enter",m=>{if(m.isComposing||m.target instanceof HTMLButtonElement&&m.target.type!=="submit")return;const x=g.value[A.value];if(m.target instanceof HTMLInputElement&&!x){m.preventDefault();return}x&&(c.go(x.id),t("close"))}),Ee("Escape",()=>{t("close")});const p=ar({modal:{displayDetails:"Display detailed list",resetButtonTitle:"Reset search",backButtonTitle:"Close search",noResultsText:"No results for",footer:{selectText:"to select",selectKeyAriaLabel:"enter",navigateText:"to navigate",navigateUpKeyAriaLabel:"up arrow",navigateDownKeyAriaLabel:"down arrow",closeText:"to close",closeKeyAriaLabel:"escape"}}});_e(()=>{window.history.pushState(null,"",null)}),Vt("popstate",m=>{m.preventDefault(),t("close")});const C=Bt($t?document.body:null);_e(()=>{de(()=>{C.value=!0,de().then(()=>s())})}),Wt(()=>{C.value=!1});function I(){v.value="",de().then(()=>N(!1))}function M(m){return new RegExp([...m].sort((x,$)=>$.length-x.length).map(x=>`(${er(x)})`).join("|"),"gi")}return(m,x)=>{var $,K,q,H;return ee(),Kt(qt,{to:"body"},[k("div",{ref_key:"el",ref:r,role:"button","aria-owns":($=g.value)!=null&&$.length?"localsearch-list":void 0,"aria-expanded":"true","aria-haspopup":"listbox","aria-labelledby":"localsearch-label",class:"VPLocalSearchBox"},[k("div",{class:"backdrop",onClick:x[0]||(x[0]=V=>m.$emit("close"))}),k("div",Qr,[k("form",{class:"search-bar",onPointerup:x[4]||(x[4]=V=>_(V)),onSubmit:x[5]||(x[5]=Jt(()=>{},["prevent"]))},[k("label",{title:E.value,id:"localsearch-label",for:"localsearch-input"},Xr,8,Yr),k("div",ea,[k("button",{class:"back-button",title:j(p)("modal.backButtonTitle"),onClick:x[1]||(x[1]=V=>m.$emit("close"))},aa,8,ta)]),Ut(k("input",{ref_key:"searchInput",ref:R,"onUpdate:modelValue":x[2]||(x[2]=V=>Gt(v)?v.value=V:null),placeholder:E.value,id:"localsearch-input","aria-labelledby":"localsearch-label",class:"search-input"},null,8,na),[[jt,j(v)]]),k("div",ia,[b.value?Se("",!0):(ee(),re("button",{key:0,class:rt(["toggle-layout-button",{"detailed-list":j(y)}]),type:"button",title:j(p)("modal.displayDetails"),onClick:x[3]||(x[3]=V=>A.value>-1&&(y.value=!j(y)))},ua,10,oa)),k("button",{class:"clear-button",type:"reset",disabled:B.value,title:j(p)("modal.resetButtonTitle"),onClick:I},fa,8,la)])],32),k("ul",{ref_key:"resultsEl",ref:n,id:(K=g.value)!=null&&K.length?"localsearch-list":void 0,role:(q=g.value)!=null&&q.length?"listbox":void 0,"aria-labelledby":(H=g.value)!=null&&H.length?"localsearch-label":void 0,class:"results",onMousemove:x[7]||(x[7]=V=>O.value=!1)},[(ee(!0),re(nt,null,at(g.value,(V,U)=>(ee(),re("li",{key:V.id,role:"option","aria-selected":A.value===U?"true":"false"},[k("a",{href:V.id,class:rt(["result",{selected:A.value===U}]),"aria-label":[...V.titles,V.title].join(" > "),onMouseenter:Z=>!O.value&&(A.value=U),onFocusin:Z=>A.value=U,onClick:x[6]||(x[6]=Z=>m.$emit("close"))},[k("div",null,[k("div",pa,[ya,(ee(!0),re(nt,null,at(V.titles,(Z,be)=>(ee(),re("span",{key:be,class:"title"},[k("span",{class:"text",innerHTML:Z},null,8,ma),ga]))),128)),k("span",ba,[k("span",{class:"text",innerHTML:V.title},null,8,wa)])]),j(y)?(ee(),re("div",xa,[V.text?(ee(),re("div",Fa,[k("div",{class:"vp-doc",innerHTML:V.text},null,8,Ea)])):Se("",!0),Sa,Aa])):Se("",!0)])],42,va)],8,da))),128)),j(v)&&!g.value.length&&S.value?(ee(),re("li",Ta,[ve(pe(j(p)("modal.noResultsText"))+' "',1),k("strong",null,pe(j(v)),1),ve('" ')])):Se("",!0)],40,ha),k("div",Na,[k("span",null,[k("kbd",{"aria-label":j(p)("modal.footer.navigateUpKeyAriaLabel")},Da,8,Ca),k("kbd",{"aria-label":j(p)("modal.footer.navigateDownKeyAriaLabel")},_a,8,ka),ve(" "+pe(j(p)("modal.footer.navigateText")),1)]),k("span",null,[k("kbd",{"aria-label":j(p)("modal.footer.selectKeyAriaLabel")},La,8,Ra),ve(" "+pe(j(p)("modal.footer.selectText")),1)]),k("span",null,[k("kbd",{"aria-label":j(p)("modal.footer.closeKeyAriaLabel")},"esc",8,Pa),ve(" "+pe(j(p)("modal.footer.closeText")),1)])])])],8,Hr)])}}}),Ja=tr(za,[["__scopeId","data-v-4eeb92d2"]]);export{Ja as default}; diff --git a/assets/chunks/extension-panel.CY9x27Ol.js b/assets/chunks/extension-panel.CY9x27Ol.js new file mode 100644 index 00000000..3bdd83dc --- /dev/null +++ b/assets/chunks/extension-panel.CY9x27Ol.js @@ -0,0 +1 @@ +const s="/minigame-unity-webgl-transform/assets/extension-panel.CsEDE2eK.png";export{s as _}; diff --git a/assets/chunks/framework.Br2U662V.js b/assets/chunks/framework.Br2U662V.js new file mode 100644 index 00000000..d4910d9e --- /dev/null +++ b/assets/chunks/framework.Br2U662V.js @@ -0,0 +1,17 @@ +/** +* @vue/shared v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Tr(e,t){const n=new Set(e.split(","));return t?r=>n.has(r.toLowerCase()):r=>n.has(r)}const ee={},_t=[],xe=()=>{},Si=()=>!1,Wt=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ar=e=>e.startsWith("onUpdate:"),ce=Object.assign,Rr=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Ti=Object.prototype.hasOwnProperty,Y=(e,t)=>Ti.call(e,t),B=Array.isArray,vt=e=>An(e)==="[object Map]",Zs=e=>An(e)==="[object Set]",q=e=>typeof e=="function",ne=e=>typeof e=="string",At=e=>typeof e=="symbol",Z=e=>e!==null&&typeof e=="object",eo=e=>(Z(e)||q(e))&&q(e.then)&&q(e.catch),to=Object.prototype.toString,An=e=>to.call(e),Ai=e=>An(e).slice(8,-1),no=e=>An(e)==="[object Object]",Lr=e=>ne(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,bt=Tr(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Rn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Ri=/-(\w)/g,Fe=Rn(e=>e.replace(Ri,(t,n)=>n?n.toUpperCase():"")),Li=/\B([A-Z])/g,ft=Rn(e=>e.replace(Li,"-$1").toLowerCase()),Ln=Rn(e=>e.charAt(0).toUpperCase()+e.slice(1)),hn=Rn(e=>e?`on${Ln(e)}`:""),Ze=(e,t)=>!Object.is(e,t),pn=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},ur=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Oi=e=>{const t=ne(e)?Number(e):NaN;return isNaN(t)?e:t};let rs;const ro=()=>rs||(rs=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Or(e){if(B(e)){const t={};for(let n=0;n{if(n){const r=n.split(Mi);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Ir(e){let t="";if(ne(e))t=e;else if(B(e))for(let n=0;nne(e)?e:e==null?"":B(e)||Z(e)&&(e.toString===to||!q(e.toString))?JSON.stringify(e,oo,2):String(e),oo=(e,t)=>t&&t.__v_isRef?oo(e,t.value):vt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],o)=>(n[qn(r,o)+" =>"]=s,n),{})}:Zs(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>qn(n))}:At(t)?qn(t):Z(t)&&!B(t)&&!no(t)?String(t):t,qn=(e,t="")=>{var n;return At(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ve;class Hi{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=ve,!t&&ve&&(this.index=(ve.scopes||(ve.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=ve;try{return ve=this,t()}finally{ve=n}}}on(){ve=this}off(){ve=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n=4))break}this._dirtyLevel===1&&(this._dirtyLevel=0),ht()}return this._dirtyLevel>=4}set dirty(t){this._dirtyLevel=t?4:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Ye,n=ct;try{return Ye=!0,ct=this,this._runnings++,ss(this),this.fn()}finally{os(this),this._runnings--,ct=n,Ye=t}}stop(){var t;this.active&&(ss(this),os(this),(t=this.onStop)==null||t.call(this),this.active=!1)}}function Di(e){return e.value}function ss(e){e._trackId++,e._depsLength=0}function os(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t{const n=new Map;return n.cleanup=e,n.computed=t,n},vn=new WeakMap,at=Symbol(""),hr=Symbol("");function ye(e,t,n){if(Ye&&ct){let r=vn.get(e);r||vn.set(e,r=new Map);let s=r.get(n);s||r.set(n,s=fo(()=>r.delete(n))),ao(ct,s)}}function je(e,t,n,r,s,o){const i=vn.get(e);if(!i)return;let l=[];if(t==="clear")l=[...i.values()];else if(n==="length"&&B(e)){const c=Number(r);i.forEach((a,f)=>{(f==="length"||!At(f)&&f>=c)&&l.push(a)})}else switch(n!==void 0&&l.push(i.get(n)),t){case"add":B(e)?Lr(n)&&l.push(i.get("length")):(l.push(i.get(at)),vt(e)&&l.push(i.get(hr)));break;case"delete":B(e)||(l.push(i.get(at)),vt(e)&&l.push(i.get(hr)));break;case"set":vt(e)&&l.push(i.get(at));break}Pr();for(const c of l)c&&uo(c,4);Nr()}function Ui(e,t){var n;return(n=vn.get(e))==null?void 0:n.get(t)}const Bi=Tr("__proto__,__v_isRef,__isVue"),ho=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(At)),is=ki();function ki(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=J(this);for(let o=0,i=this.length;o{e[t]=function(...n){dt(),Pr();const r=J(this)[t].apply(this,n);return Nr(),ht(),r}}),e}function Ki(e){const t=J(this);return ye(t,"has",e),t.hasOwnProperty(e)}class po{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,r){const s=this._isReadonly,o=this._isShallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return o;if(n==="__v_raw")return r===(s?o?rl:_o:o?yo:mo).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const i=B(t);if(!s){if(i&&Y(is,n))return Reflect.get(is,n,r);if(n==="hasOwnProperty")return Ki}const l=Reflect.get(t,n,r);return(At(n)?ho.has(n):Bi(n))||(s||ye(t,"get",n),o)?l:de(l)?i&&Lr(n)?l:l.value:Z(l)?s?Mn(l):In(l):l}}class go extends po{constructor(t=!1){super(!1,t)}set(t,n,r,s){let o=t[n];if(!this._isShallow){const c=St(o);if(!bn(r)&&!St(r)&&(o=J(o),r=J(r)),!B(t)&&de(o)&&!de(r))return c?!1:(o.value=r,!0)}const i=B(t)&&Lr(n)?Number(n)e,On=e=>Reflect.getPrototypeOf(e);function Qt(e,t,n=!1,r=!1){e=e.__v_raw;const s=J(e),o=J(t);n||(Ze(t,o)&&ye(s,"get",t),ye(s,"get",o));const{has:i}=On(s),l=r?Fr:n?jr:Dt;if(i.call(s,t))return l(e.get(t));if(i.call(s,o))return l(e.get(o));e!==s&&e.get(t)}function Zt(e,t=!1){const n=this.__v_raw,r=J(n),s=J(e);return t||(Ze(e,s)&&ye(r,"has",e),ye(r,"has",s)),e===s?n.has(e):n.has(e)||n.has(s)}function en(e,t=!1){return e=e.__v_raw,!t&&ye(J(e),"iterate",at),Reflect.get(e,"size",e)}function ls(e){e=J(e);const t=J(this);return On(t).has.call(t,e)||(t.add(e),je(t,"add",e,e)),this}function cs(e,t){t=J(t);const n=J(this),{has:r,get:s}=On(n);let o=r.call(n,e);o||(e=J(e),o=r.call(n,e));const i=s.call(n,e);return n.set(e,t),o?Ze(t,i)&&je(n,"set",e,t):je(n,"add",e,t),this}function as(e){const t=J(this),{has:n,get:r}=On(t);let s=n.call(t,e);s||(e=J(e),s=n.call(t,e)),r&&r.call(t,e);const o=t.delete(e);return s&&je(t,"delete",e,void 0),o}function us(){const e=J(this),t=e.size!==0,n=e.clear();return t&&je(e,"clear",void 0,void 0),n}function tn(e,t){return function(r,s){const o=this,i=o.__v_raw,l=J(i),c=t?Fr:e?jr:Dt;return!e&&ye(l,"iterate",at),i.forEach((a,f)=>r.call(s,c(a),c(f),o))}}function nn(e,t,n){return function(...r){const s=this.__v_raw,o=J(s),i=vt(o),l=e==="entries"||e===Symbol.iterator&&i,c=e==="keys"&&i,a=s[e](...r),f=n?Fr:t?jr:Dt;return!t&&ye(o,"iterate",c?hr:at),{next(){const{value:h,done:p}=a.next();return p?{value:h,done:p}:{value:l?[f(h[0]),f(h[1])]:f(h),done:p}},[Symbol.iterator](){return this}}}}function Be(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Xi(){const e={get(o){return Qt(this,o)},get size(){return en(this)},has:Zt,add:ls,set:cs,delete:as,clear:us,forEach:tn(!1,!1)},t={get(o){return Qt(this,o,!1,!0)},get size(){return en(this)},has:Zt,add:ls,set:cs,delete:as,clear:us,forEach:tn(!1,!0)},n={get(o){return Qt(this,o,!0)},get size(){return en(this,!0)},has(o){return Zt.call(this,o,!0)},add:Be("add"),set:Be("set"),delete:Be("delete"),clear:Be("clear"),forEach:tn(!0,!1)},r={get(o){return Qt(this,o,!0,!0)},get size(){return en(this,!0)},has(o){return Zt.call(this,o,!0)},add:Be("add"),set:Be("set"),delete:Be("delete"),clear:Be("clear"),forEach:tn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(o=>{e[o]=nn(o,!1,!1),n[o]=nn(o,!0,!1),t[o]=nn(o,!1,!0),r[o]=nn(o,!0,!0)}),[e,n,t,r]}const[Yi,Ji,Qi,Zi]=Xi();function $r(e,t){const n=t?e?Zi:Qi:e?Ji:Yi;return(r,s,o)=>s==="__v_isReactive"?!e:s==="__v_isReadonly"?e:s==="__v_raw"?r:Reflect.get(Y(n,s)&&s in r?n:r,s,o)}const el={get:$r(!1,!1)},tl={get:$r(!1,!0)},nl={get:$r(!0,!1)},mo=new WeakMap,yo=new WeakMap,_o=new WeakMap,rl=new WeakMap;function sl(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ol(e){return e.__v_skip||!Object.isExtensible(e)?0:sl(Ai(e))}function In(e){return St(e)?e:Hr(e,!1,qi,el,mo)}function il(e){return Hr(e,!1,zi,tl,yo)}function Mn(e){return Hr(e,!0,Gi,nl,_o)}function Hr(e,t,n,r,s){if(!Z(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const o=s.get(e);if(o)return o;const i=ol(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return s.set(e,l),l}function wt(e){return St(e)?wt(e.__v_raw):!!(e&&e.__v_isReactive)}function St(e){return!!(e&&e.__v_isReadonly)}function bn(e){return!!(e&&e.__v_isShallow)}function vo(e){return wt(e)||St(e)}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function Mt(e){return Object.isExtensible(e)&&_n(e,"__v_skip",!0),e}const Dt=e=>Z(e)?In(e):e,jr=e=>Z(e)?Mn(e):e;class bo{constructor(t,n,r,s){this.getter=t,this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this.effect=new Mr(()=>t(this._value),()=>Pt(this,this.effect._dirtyLevel===2?2:3)),this.effect.computed=this,this.effect.active=this._cacheable=!s,this.__v_isReadonly=r}get value(){const t=J(this);return(!t._cacheable||t.effect.dirty)&&Ze(t._value,t._value=t.effect.run())&&Pt(t,4),Vr(t),t.effect._dirtyLevel>=2&&Pt(t,2),t._value}set value(t){this._setter(t)}get _dirty(){return this.effect.dirty}set _dirty(t){this.effect.dirty=t}}function ll(e,t,n=!1){let r,s;const o=q(e);return o?(r=e,s=xe):(r=e.get,s=e.set),new bo(r,s,o||!s,n)}function Vr(e){var t;Ye&&ct&&(e=J(e),ao(ct,(t=e.dep)!=null?t:e.dep=fo(()=>e.dep=void 0,e instanceof bo?e:void 0)))}function Pt(e,t=4,n){e=J(e);const r=e.dep;r&&uo(r,t)}function de(e){return!!(e&&e.__v_isRef===!0)}function se(e){return wo(e,!1)}function Dr(e){return wo(e,!0)}function wo(e,t){return de(e)?e:new cl(e,t)}class cl{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:J(t),this._value=n?t:Dt(t)}get value(){return Vr(this),this._value}set value(t){const n=this.__v_isShallow||bn(t)||St(t);t=n?t:J(t),Ze(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Dt(t),Pt(this,4))}}function Eo(e){return de(e)?e.value:e}const al={get:(e,t,n)=>Eo(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const s=e[t];return de(s)&&!de(n)?(s.value=n,!0):Reflect.set(e,t,n,r)}};function Co(e){return wt(e)?e:new Proxy(e,al)}class ul{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>Vr(this),()=>Pt(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function fl(e){return new ul(e)}class dl{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Ui(J(this._object),this._key)}}class hl{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function pl(e,t,n){return de(e)?e:q(e)?new hl(e):Z(e)&&arguments.length>1?gl(e,t,n):se(e)}function gl(e,t,n){const r=e[t];return de(r)?r:new dl(e,t,n)}/** +* @vue/runtime-core v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Je(e,t,n,r){try{return r?e(...r):e()}catch(s){qt(s,t,n)}}function Se(e,t,n,r){if(q(e)){const o=Je(e,t,n,r);return o&&eo(o)&&o.catch(i=>{qt(i,t,n)}),o}const s=[];for(let o=0;o>>1,s=he[r],o=Bt(s);oPe&&he.splice(t,1)}function vl(e){B(e)?Et.push(...e):(!qe||!qe.includes(e,e.allowRecurse?ot+1:ot))&&Et.push(e),So()}function fs(e,t,n=Ut?Pe+1:0){for(;nBt(n)-Bt(r));if(Et.length=0,qe){qe.push(...t);return}for(qe=t,ot=0;ote.id==null?1/0:e.id,bl=(e,t)=>{const n=Bt(e)-Bt(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function To(e){pr=!1,Ut=!0,he.sort(bl);try{for(Pe=0;Pene(y)?y.trim():y)),h&&(s=n.map(ur))}let l,c=r[l=hn(t)]||r[l=hn(Fe(t))];!c&&o&&(c=r[l=hn(ft(t))]),c&&Se(c,e,6,s);const a=r[l+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Se(a,e,6,s)}}function Ao(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const o=e.emits;let i={},l=!1;if(!q(e)){const c=a=>{const f=Ao(a,t,!0);f&&(l=!0,ce(i,f))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!o&&!l?(Z(e)&&r.set(e,null),null):(B(o)?o.forEach(c=>i[c]=null):ce(i,o),Z(e)&&r.set(e,i),i)}function Fn(e,t){return!e||!Wt(t)?!1:(t=t.slice(2).replace(/Once$/,""),Y(e,t[0].toLowerCase()+t.slice(1))||Y(e,ft(t))||Y(e,t))}let le=null,$n=null;function En(e){const t=le;return le=e,$n=e&&e.type.__scopeId||null,t}function Qa(e){$n=e}function Za(){$n=null}function El(e,t=le,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&Ss(-1);const o=En(t);let i;try{i=e(...s)}finally{En(o),r._d&&Ss(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function Gn(e){const{type:t,vnode:n,proxy:r,withProxy:s,props:o,propsOptions:[i],slots:l,attrs:c,emit:a,render:f,renderCache:h,data:p,setupState:y,ctx:v,inheritAttrs:I}=e;let N,K;const k=En(e);try{if(n.shapeFlag&4){const _=s||r,M=_;N=Re(f.call(M,_,h,o,y,p,v)),K=c}else{const _=t;N=Re(_.length>1?_(o,{attrs:c,slots:l,emit:a}):_(o,null)),K=t.props?c:Cl(c)}}catch(_){jt.length=0,qt(_,e,1),N=oe(be)}let g=N;if(K&&I!==!1){const _=Object.keys(K),{shapeFlag:M}=g;_.length&&M&7&&(i&&_.some(Ar)&&(K=xl(K,i)),g=et(g,K))}return n.dirs&&(g=et(g),g.dirs=g.dirs?g.dirs.concat(n.dirs):n.dirs),n.transition&&(g.transition=n.transition),N=g,En(k),N}const Cl=e=>{let t;for(const n in e)(n==="class"||n==="style"||Wt(n))&&((t||(t={}))[n]=e[n]);return t},xl=(e,t)=>{const n={};for(const r in e)(!Ar(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function Sl(e,t,n){const{props:r,children:s,component:o}=e,{props:i,children:l,patchFlag:c}=t,a=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?ds(r,i,a):!!i;if(c&8){const f=t.dynamicProps;for(let h=0;he.__isSuspense;function Oo(e,t){t&&t.pendingBranch?B(e)?t.effects.push(...e):t.effects.push(e):vl(e)}const Rl=Symbol.for("v-scx"),Ll=()=>xt(Rl);function kr(e,t){return Hn(e,null,t)}function nu(e,t){return Hn(e,null,{flush:"post"})}const rn={};function Ve(e,t,n){return Hn(e,t,n)}function Hn(e,t,{immediate:n,deep:r,flush:s,once:o,onTrack:i,onTrigger:l}=ee){if(t&&o){const L=t;t=(...F)=>{L(...F),M()}}const c=ue,a=L=>r===!0?L:lt(L,r===!1?1:void 0);let f,h=!1,p=!1;if(de(e)?(f=()=>e.value,h=bn(e)):wt(e)?(f=()=>a(e),h=!0):B(e)?(p=!0,h=e.some(L=>wt(L)||bn(L)),f=()=>e.map(L=>{if(de(L))return L.value;if(wt(L))return a(L);if(q(L))return Je(L,c,2)})):q(e)?t?f=()=>Je(e,c,2):f=()=>(y&&y(),Se(e,c,3,[v])):f=xe,t&&r){const L=f;f=()=>lt(L())}let y,v=L=>{y=g.onStop=()=>{Je(L,c,4),y=g.onStop=void 0}},I;if(Xt)if(v=xe,t?n&&Se(t,c,3,[f(),p?[]:void 0,v]):f(),s==="sync"){const L=Ll();I=L.__watcherHandles||(L.__watcherHandles=[])}else return xe;let N=p?new Array(e.length).fill(rn):rn;const K=()=>{if(!(!g.active||!g.dirty))if(t){const L=g.run();(r||h||(p?L.some((F,T)=>Ze(F,N[T])):Ze(L,N)))&&(y&&y(),Se(t,c,3,[L,N===rn?void 0:p&&N[0]===rn?[]:N,v]),N=L)}else g.run()};K.allowRecurse=!!t;let k;s==="sync"?k=K:s==="post"?k=()=>ge(K,c&&c.suspense):(K.pre=!0,c&&(K.id=c.uid),k=()=>Nn(K));const g=new Mr(f,xe,k),_=io(),M=()=>{g.stop(),_&&Rr(_.effects,g)};return t?n?K():N=g.run():s==="post"?ge(g.run.bind(g),c&&c.suspense):g.run(),I&&I.push(M),M}function Ol(e,t,n){const r=this.proxy,s=ne(e)?e.includes(".")?Io(r,e):()=>r[e]:e.bind(r,r);let o;q(t)?o=t:(o=t.handler,n=t);const i=zt(this),l=Hn(s,o.bind(r),n);return i(),l}function Io(e,t){const n=t.split(".");return()=>{let r=e;for(let s=0;s0){if(n>=t)return e;n++}if(r=r||new Set,r.has(e))return e;if(r.add(e),de(e))lt(e.value,t,n,r);else if(B(e))for(let s=0;s{lt(s,t,n,r)});else if(no(e))for(const s in e)lt(e[s],t,n,r);return e}function ru(e,t){if(le===null)return e;const n=Bn(le)||le.proxy,r=e.dirs||(e.dirs=[]);for(let s=0;s{e.isMounted=!0}),$o(()=>{e.isUnmounting=!0}),e}const we=[Function,Array],Mo={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:we,onEnter:we,onAfterEnter:we,onEnterCancelled:we,onBeforeLeave:we,onLeave:we,onAfterLeave:we,onLeaveCancelled:we,onBeforeAppear:we,onAppear:we,onAfterAppear:we,onAppearCancelled:we},Ml={name:"BaseTransition",props:Mo,setup(e,{slots:t}){const n=Un(),r=Il();return()=>{const s=t.default&&No(t.default(),!0);if(!s||!s.length)return;let o=s[0];if(s.length>1){for(const p of s)if(p.type!==be){o=p;break}}const i=J(e),{mode:l}=i;if(r.isLeaving)return zn(o);const c=ps(o);if(!c)return zn(o);const a=gr(c,i,r,n);mr(c,a);const f=n.subTree,h=f&&ps(f);if(h&&h.type!==be&&!it(c,h)){const p=gr(h,i,r,n);if(mr(h,p),l==="out-in")return r.isLeaving=!0,p.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&(n.effect.dirty=!0,n.update())},zn(o);l==="in-out"&&c.type!==be&&(p.delayLeave=(y,v,I)=>{const N=Po(r,h);N[String(h.key)]=h,y[Ge]=()=>{v(),y[Ge]=void 0,delete a.delayedLeave},a.delayedLeave=I})}return o}}},Pl=Ml;function Po(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function gr(e,t,n,r){const{appear:s,mode:o,persisted:i=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:a,onEnterCancelled:f,onBeforeLeave:h,onLeave:p,onAfterLeave:y,onLeaveCancelled:v,onBeforeAppear:I,onAppear:N,onAfterAppear:K,onAppearCancelled:k}=t,g=String(e.key),_=Po(n,e),M=(T,$)=>{T&&Se(T,r,9,$)},L=(T,$)=>{const E=$[1];M(T,$),B(T)?T.every(j=>j.length<=1)&&E():T.length<=1&&E()},F={mode:o,persisted:i,beforeEnter(T){let $=l;if(!n.isMounted)if(s)$=I||l;else return;T[Ge]&&T[Ge](!0);const E=_[g];E&&it(e,E)&&E.el[Ge]&&E.el[Ge](),M($,[T])},enter(T){let $=c,E=a,j=f;if(!n.isMounted)if(s)$=N||c,E=K||a,j=k||f;else return;let A=!1;const G=T[sn]=ie=>{A||(A=!0,ie?M(j,[T]):M(E,[T]),F.delayedLeave&&F.delayedLeave(),T[sn]=void 0)};$?L($,[T,G]):G()},leave(T,$){const E=String(e.key);if(T[sn]&&T[sn](!0),n.isUnmounting)return $();M(h,[T]);let j=!1;const A=T[Ge]=G=>{j||(j=!0,$(),G?M(v,[T]):M(y,[T]),T[Ge]=void 0,_[E]===e&&delete _[E])};_[E]=e,p?L(p,[T,A]):A()},clone(T){return gr(T,t,n,r)}};return F}function zn(e){if(Gt(e))return e=et(e),e.children=null,e}function ps(e){return Gt(e)?e.children?e.children[0]:void 0:e}function mr(e,t){e.shapeFlag&6&&e.component?mr(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function No(e,t=!1,n){let r=[],s=0;for(let o=0;o1)for(let o=0;o!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function su(e){q(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:s=200,timeout:o,suspensible:i=!0,onError:l}=e;let c=null,a,f=0;const h=()=>(f++,c=null,p()),p=()=>{let y;return c||(y=c=t().catch(v=>{if(v=v instanceof Error?v:new Error(String(v)),l)return new Promise((I,N)=>{l(v,()=>I(h()),()=>N(v),f+1)});throw v}).then(v=>y!==c&&c?c:(v&&(v.__esModule||v[Symbol.toStringTag]==="Module")&&(v=v.default),a=v,v)))};return Kr({name:"AsyncComponentWrapper",__asyncLoader:p,get __asyncResolved(){return a},setup(){const y=ue;if(a)return()=>Xn(a,y);const v=k=>{c=null,qt(k,y,13,!r)};if(i&&y.suspense||Xt)return p().then(k=>()=>Xn(k,y)).catch(k=>(v(k),()=>r?oe(r,{error:k}):null));const I=se(!1),N=se(),K=se(!!s);return s&&setTimeout(()=>{K.value=!1},s),o!=null&&setTimeout(()=>{if(!I.value&&!N.value){const k=new Error(`Async component timed out after ${o}ms.`);v(k),N.value=k}},o),p().then(()=>{I.value=!0,y.parent&&Gt(y.parent.vnode)&&(y.parent.effect.dirty=!0,Nn(y.parent.update))}).catch(k=>{v(k),N.value=k}),()=>{if(I.value&&a)return Xn(a,y);if(N.value&&r)return oe(r,{error:N.value});if(n&&!K.value)return oe(n)}}})}function Xn(e,t){const{ref:n,props:r,children:s,ce:o}=t.vnode,i=oe(e,r,s);return i.ref=n,i.ce=o,delete t.vnode.ce,i}const Gt=e=>e.type.__isKeepAlive;function Nl(e,t){Fo(e,"a",t)}function Fl(e,t){Fo(e,"da",t)}function Fo(e,t,n=ue){const r=e.__wdc||(e.__wdc=()=>{let s=n;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if(jn(t,r,n),n){let s=n.parent;for(;s&&s.parent;)Gt(s.parent.vnode)&&$l(r,t,n,s),s=s.parent}}function $l(e,t,n,r){const s=jn(t,e,r,!0);Vn(()=>{Rr(r[t],s)},n)}function jn(e,t,n=ue,r=!1){if(n){const s=n[e]||(n[e]=[]),o=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;dt();const l=zt(n),c=Se(t,n,e,i);return l(),ht(),c});return r?s.unshift(o):s.push(o),o}}const Ue=e=>(t,n=ue)=>(!Xt||e==="sp")&&jn(e,(...r)=>t(...r),n),Hl=Ue("bm"),Rt=Ue("m"),jl=Ue("bu"),Vl=Ue("u"),$o=Ue("bum"),Vn=Ue("um"),Dl=Ue("sp"),Ul=Ue("rtg"),Bl=Ue("rtc");function kl(e,t=ue){jn("ec",e,t)}function ou(e,t,n,r){let s;const o=n&&n[r];if(B(e)||ne(e)){s=new Array(e.length);for(let i=0,l=e.length;it(i,l,void 0,o&&o[l]));else{const i=Object.keys(e);s=new Array(i.length);for(let l=0,c=i.length;lSn(t)?!(t.type===be||t.type===me&&!Ho(t.children)):!0)?e:null}function lu(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:hn(r)]=e[r];return n}const yr=e=>e?ti(e)?Bn(e)||e.proxy:yr(e.parent):null,Nt=ce(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>yr(e.parent),$root:e=>yr(e.root),$emit:e=>e.emit,$options:e=>Wr(e),$forceUpdate:e=>e.f||(e.f=()=>{e.effect.dirty=!0,Nn(e.update)}),$nextTick:e=>e.n||(e.n=Pn.bind(e.proxy)),$watch:e=>Ol.bind(e)}),Yn=(e,t)=>e!==ee&&!e.__isScriptSetup&&Y(e,t),Kl={get({_:e},t){const{ctx:n,setupState:r,data:s,props:o,accessCache:i,type:l,appContext:c}=e;let a;if(t[0]!=="$"){const y=i[t];if(y!==void 0)switch(y){case 1:return r[t];case 2:return s[t];case 4:return n[t];case 3:return o[t]}else{if(Yn(r,t))return i[t]=1,r[t];if(s!==ee&&Y(s,t))return i[t]=2,s[t];if((a=e.propsOptions[0])&&Y(a,t))return i[t]=3,o[t];if(n!==ee&&Y(n,t))return i[t]=4,n[t];_r&&(i[t]=0)}}const f=Nt[t];let h,p;if(f)return t==="$attrs"&&ye(e,"get",t),f(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==ee&&Y(n,t))return i[t]=4,n[t];if(p=c.config.globalProperties,Y(p,t))return p[t]},set({_:e},t,n){const{data:r,setupState:s,ctx:o}=e;return Yn(s,t)?(s[t]=n,!0):r!==ee&&Y(r,t)?(r[t]=n,!0):Y(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:s,propsOptions:o}},i){let l;return!!n[i]||e!==ee&&Y(e,i)||Yn(t,i)||(l=o[0])&&Y(l,i)||Y(r,i)||Y(Nt,i)||Y(s.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Y(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function cu(){return Wl().slots}function Wl(){const e=Un();return e.setupContext||(e.setupContext=ri(e))}function gs(e){return B(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let _r=!0;function ql(e){const t=Wr(e),n=e.proxy,r=e.ctx;_r=!1,t.beforeCreate&&ms(t.beforeCreate,e,"bc");const{data:s,computed:o,methods:i,watch:l,provide:c,inject:a,created:f,beforeMount:h,mounted:p,beforeUpdate:y,updated:v,activated:I,deactivated:N,beforeDestroy:K,beforeUnmount:k,destroyed:g,unmounted:_,render:M,renderTracked:L,renderTriggered:F,errorCaptured:T,serverPrefetch:$,expose:E,inheritAttrs:j,components:A,directives:G,filters:ie}=t;if(a&&Gl(a,r,null),i)for(const X in i){const V=i[X];q(V)&&(r[X]=V.bind(n))}if(s){const X=s.call(n,n);Z(X)&&(e.data=In(X))}if(_r=!0,o)for(const X in o){const V=o[X],$e=q(V)?V.bind(n,n):q(V.get)?V.get.bind(n,n):xe,Yt=!q(V)&&q(V.set)?V.set.bind(n):xe,tt=re({get:$e,set:Yt});Object.defineProperty(r,X,{enumerable:!0,configurable:!0,get:()=>tt.value,set:Oe=>tt.value=Oe})}if(l)for(const X in l)jo(l[X],r,n,X);if(c){const X=q(c)?c.call(n):c;Reflect.ownKeys(X).forEach(V=>{Zl(V,X[V])})}f&&ms(f,e,"c");function D(X,V){B(V)?V.forEach($e=>X($e.bind(n))):V&&X(V.bind(n))}if(D(Hl,h),D(Rt,p),D(jl,y),D(Vl,v),D(Nl,I),D(Fl,N),D(kl,T),D(Bl,L),D(Ul,F),D($o,k),D(Vn,_),D(Dl,$),B(E))if(E.length){const X=e.exposed||(e.exposed={});E.forEach(V=>{Object.defineProperty(X,V,{get:()=>n[V],set:$e=>n[V]=$e})})}else e.exposed||(e.exposed={});M&&e.render===xe&&(e.render=M),j!=null&&(e.inheritAttrs=j),A&&(e.components=A),G&&(e.directives=G)}function Gl(e,t,n=xe){B(e)&&(e=vr(e));for(const r in e){const s=e[r];let o;Z(s)?"default"in s?o=xt(s.from||r,s.default,!0):o=xt(s.from||r):o=xt(s),de(o)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>o.value,set:i=>o.value=i}):t[r]=o}}function ms(e,t,n){Se(B(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function jo(e,t,n,r){const s=r.includes(".")?Io(n,r):()=>n[r];if(ne(e)){const o=t[e];q(o)&&Ve(s,o)}else if(q(e))Ve(s,e.bind(n));else if(Z(e))if(B(e))e.forEach(o=>jo(o,t,n,r));else{const o=q(e.handler)?e.handler.bind(n):t[e.handler];q(o)&&Ve(s,o,e)}}function Wr(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:s,optionsCache:o,config:{optionMergeStrategies:i}}=e.appContext,l=o.get(t);let c;return l?c=l:!s.length&&!n&&!r?c=t:(c={},s.length&&s.forEach(a=>Cn(c,a,i,!0)),Cn(c,t,i)),Z(t)&&o.set(t,c),c}function Cn(e,t,n,r=!1){const{mixins:s,extends:o}=t;o&&Cn(e,o,n,!0),s&&s.forEach(i=>Cn(e,i,n,!0));for(const i in t)if(!(r&&i==="expose")){const l=zl[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const zl={data:ys,props:_s,emits:_s,methods:It,computed:It,beforeCreate:pe,created:pe,beforeMount:pe,mounted:pe,beforeUpdate:pe,updated:pe,beforeDestroy:pe,beforeUnmount:pe,destroyed:pe,unmounted:pe,activated:pe,deactivated:pe,errorCaptured:pe,serverPrefetch:pe,components:It,directives:It,watch:Yl,provide:ys,inject:Xl};function ys(e,t){return t?e?function(){return ce(q(e)?e.call(this,this):e,q(t)?t.call(this,this):t)}:t:e}function Xl(e,t){return It(vr(e),vr(t))}function vr(e){if(B(e)){const t={};for(let n=0;n1)return n&&q(t)?t.call(r&&r.proxy):t}}function ec(e,t,n,r=!1){const s={},o={};_n(o,Dn,1),e.propsDefaults=Object.create(null),Do(e,t,s,o);for(const i in e.propsOptions[0])i in s||(s[i]=void 0);n?e.props=r?s:il(s):e.type.props?e.props=s:e.props=o,e.attrs=o}function tc(e,t,n,r){const{props:s,attrs:o,vnode:{patchFlag:i}}=e,l=J(s),[c]=e.propsOptions;let a=!1;if((r||i>0)&&!(i&16)){if(i&8){const f=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[p,y]=Uo(h,t,!0);ce(i,p),y&&l.push(...y)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!o&&!c)return Z(e)&&r.set(e,_t),_t;if(B(o))for(let f=0;f-1,y[1]=I<0||v-1||Y(y,"default"))&&l.push(h)}}}const a=[i,l];return Z(e)&&r.set(e,a),a}function vs(e){return e[0]!=="$"&&!bt(e)}function bs(e){return e===null?"null":typeof e=="function"?e.name||"":typeof e=="object"&&e.constructor&&e.constructor.name||""}function ws(e,t){return bs(e)===bs(t)}function Es(e,t){return B(t)?t.findIndex(n=>ws(n,e)):q(t)&&ws(t,e)?0:-1}const Bo=e=>e[0]==="_"||e==="$stable",qr=e=>B(e)?e.map(Re):[Re(e)],nc=(e,t,n)=>{if(t._n)return t;const r=El((...s)=>qr(t(...s)),n);return r._c=!1,r},ko=(e,t,n)=>{const r=e._ctx;for(const s in e){if(Bo(s))continue;const o=e[s];if(q(o))t[s]=nc(s,o,r);else if(o!=null){const i=qr(o);t[s]=()=>i}}},Ko=(e,t)=>{const n=qr(t);e.slots.default=()=>n},rc=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=J(t),_n(t,"_",n)):ko(t,e.slots={})}else e.slots={},t&&Ko(e,t);_n(e.slots,Dn,1)},sc=(e,t,n)=>{const{vnode:r,slots:s}=e;let o=!0,i=ee;if(r.shapeFlag&32){const l=t._;l?n&&l===1?o=!1:(ce(s,t),!n&&l===1&&delete s._):(o=!t.$stable,ko(t,s)),i=t}else t&&(Ko(e,t),i={default:1});if(o)for(const l in s)!Bo(l)&&i[l]==null&&delete s[l]};function xn(e,t,n,r,s=!1){if(B(e)){e.forEach((p,y)=>xn(p,t&&(B(t)?t[y]:t),n,r,s));return}if(Ct(r)&&!s)return;const o=r.shapeFlag&4?Bn(r.component)||r.component.proxy:r.el,i=s?null:o,{i:l,r:c}=e,a=t&&t.r,f=l.refs===ee?l.refs={}:l.refs,h=l.setupState;if(a!=null&&a!==c&&(ne(a)?(f[a]=null,Y(h,a)&&(h[a]=null)):de(a)&&(a.value=null)),q(c))Je(c,l,12,[i,f]);else{const p=ne(c),y=de(c);if(p||y){const v=()=>{if(e.f){const I=p?Y(h,c)?h[c]:f[c]:c.value;s?B(I)&&Rr(I,o):B(I)?I.includes(o)||I.push(o):p?(f[c]=[o],Y(h,c)&&(h[c]=f[c])):(c.value=[o],e.k&&(f[e.k]=c.value))}else p?(f[c]=i,Y(h,c)&&(h[c]=i)):y&&(c.value=i,e.k&&(f[e.k]=i))};i?(v.id=-1,ge(v,n)):v()}}}let ke=!1;const oc=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",ic=e=>e.namespaceURI.includes("MathML"),on=e=>{if(oc(e))return"svg";if(ic(e))return"mathml"},ln=e=>e.nodeType===8;function lc(e){const{mt:t,p:n,o:{patchProp:r,createText:s,nextSibling:o,parentNode:i,remove:l,insert:c,createComment:a}}=e,f=(g,_)=>{if(!_.hasChildNodes()){n(null,g,_),wn(),_._vnode=g;return}ke=!1,h(_.firstChild,g,null,null,null),wn(),_._vnode=g,ke&&console.error("Hydration completed but contains mismatches.")},h=(g,_,M,L,F,T=!1)=>{const $=ln(g)&&g.data==="[",E=()=>I(g,_,M,L,F,$),{type:j,ref:A,shapeFlag:G,patchFlag:ie}=_;let fe=g.nodeType;_.el=g,ie===-2&&(T=!1,_.dynamicChildren=null);let D=null;switch(j){case Tt:fe!==3?_.children===""?(c(_.el=s(""),i(g),g),D=g):D=E():(g.data!==_.children&&(ke=!0,g.data=_.children),D=o(g));break;case be:k(g)?(D=o(g),K(_.el=g.content.firstChild,g,M)):fe!==8||$?D=E():D=o(g);break;case Ht:if($&&(g=o(g),fe=g.nodeType),fe===1||fe===3){D=g;const X=!_.children.length;for(let V=0;V<_.staticCount;V++)X&&(_.children+=D.nodeType===1?D.outerHTML:D.data),V===_.staticCount-1&&(_.anchor=D),D=o(D);return $?o(D):D}else E();break;case me:$?D=v(g,_,M,L,F,T):D=E();break;default:if(G&1)(fe!==1||_.type.toLowerCase()!==g.tagName.toLowerCase())&&!k(g)?D=E():D=p(g,_,M,L,F,T);else if(G&6){_.slotScopeIds=F;const X=i(g);if($?D=N(g):ln(g)&&g.data==="teleport start"?D=N(g,g.data,"teleport end"):D=o(g),t(_,X,null,M,L,on(X),T),Ct(_)){let V;$?(V=oe(me),V.anchor=D?D.previousSibling:X.lastChild):V=g.nodeType===3?ei(""):oe("div"),V.el=g,_.component.subTree=V}}else G&64?fe!==8?D=E():D=_.type.hydrate(g,_,M,L,F,T,e,y):G&128&&(D=_.type.hydrate(g,_,M,L,on(i(g)),F,T,e,h))}return A!=null&&xn(A,null,L,_),D},p=(g,_,M,L,F,T)=>{T=T||!!_.dynamicChildren;const{type:$,props:E,patchFlag:j,shapeFlag:A,dirs:G,transition:ie}=_,fe=$==="input"||$==="option";if(fe||j!==-1){G&&Me(_,null,M,"created");let D=!1;if(k(g)){D=qo(L,ie)&&M&&M.vnode.props&&M.vnode.props.appear;const V=g.content.firstChild;D&&ie.beforeEnter(V),K(V,g,M),_.el=g=V}if(A&16&&!(E&&(E.innerHTML||E.textContent))){let V=y(g.firstChild,_,g,M,L,F,T);for(;V;){ke=!0;const $e=V;V=V.nextSibling,l($e)}}else A&8&&g.textContent!==_.children&&(ke=!0,g.textContent=_.children);if(E)if(fe||!T||j&48)for(const V in E)(fe&&(V.endsWith("value")||V==="indeterminate")||Wt(V)&&!bt(V)||V[0]===".")&&r(g,V,null,E[V],void 0,void 0,M);else E.onClick&&r(g,"onClick",null,E.onClick,void 0,void 0,M);let X;(X=E&&E.onVnodeBeforeMount)&&Ee(X,M,_),G&&Me(_,null,M,"beforeMount"),((X=E&&E.onVnodeMounted)||G||D)&&Oo(()=>{X&&Ee(X,M,_),D&&ie.enter(g),G&&Me(_,null,M,"mounted")},L)}return g.nextSibling},y=(g,_,M,L,F,T,$)=>{$=$||!!_.dynamicChildren;const E=_.children,j=E.length;for(let A=0;A{const{slotScopeIds:$}=_;$&&(F=F?F.concat($):$);const E=i(g),j=y(o(g),_,E,M,L,F,T);return j&&ln(j)&&j.data==="]"?o(_.anchor=j):(ke=!0,c(_.anchor=a("]"),E,j),j)},I=(g,_,M,L,F,T)=>{if(ke=!0,_.el=null,T){const j=N(g);for(;;){const A=o(g);if(A&&A!==j)l(A);else break}}const $=o(g),E=i(g);return l(g),n(null,_,E,$,M,L,on(E),F),$},N=(g,_="[",M="]")=>{let L=0;for(;g;)if(g=o(g),g&&ln(g)&&(g.data===_&&L++,g.data===M)){if(L===0)return o(g);L--}return g},K=(g,_,M)=>{const L=_.parentNode;L&&L.replaceChild(g,_);let F=M;for(;F;)F.vnode.el===_&&(F.vnode.el=F.subTree.el=g),F=F.parent},k=g=>g.nodeType===1&&g.tagName.toLowerCase()==="template";return[f,h]}const ge=Oo;function cc(e){return Wo(e)}function ac(e){return Wo(e,lc)}function Wo(e,t){const n=ro();n.__VUE__=!0;const{insert:r,remove:s,patchProp:o,createElement:i,createText:l,createComment:c,setText:a,setElementText:f,parentNode:h,nextSibling:p,setScopeId:y=xe,insertStaticContent:v}=e,I=(u,d,m,b=null,w=null,S=null,O=void 0,x=null,R=!!d.dynamicChildren)=>{if(u===d)return;u&&!it(u,d)&&(b=Jt(u),Oe(u,w,S,!0),u=null),d.patchFlag===-2&&(R=!1,d.dynamicChildren=null);const{type:C,ref:P,shapeFlag:U}=d;switch(C){case Tt:N(u,d,m,b);break;case be:K(u,d,m,b);break;case Ht:u==null&&k(d,m,b,O);break;case me:A(u,d,m,b,w,S,O,x,R);break;default:U&1?M(u,d,m,b,w,S,O,x,R):U&6?G(u,d,m,b,w,S,O,x,R):(U&64||U&128)&&C.process(u,d,m,b,w,S,O,x,R,pt)}P!=null&&w&&xn(P,u&&u.ref,S,d||u,!d)},N=(u,d,m,b)=>{if(u==null)r(d.el=l(d.children),m,b);else{const w=d.el=u.el;d.children!==u.children&&a(w,d.children)}},K=(u,d,m,b)=>{u==null?r(d.el=c(d.children||""),m,b):d.el=u.el},k=(u,d,m,b)=>{[u.el,u.anchor]=v(u.children,d,m,b,u.el,u.anchor)},g=({el:u,anchor:d},m,b)=>{let w;for(;u&&u!==d;)w=p(u),r(u,m,b),u=w;r(d,m,b)},_=({el:u,anchor:d})=>{let m;for(;u&&u!==d;)m=p(u),s(u),u=m;s(d)},M=(u,d,m,b,w,S,O,x,R)=>{d.type==="svg"?O="svg":d.type==="math"&&(O="mathml"),u==null?L(d,m,b,w,S,O,x,R):$(u,d,w,S,O,x,R)},L=(u,d,m,b,w,S,O,x)=>{let R,C;const{props:P,shapeFlag:U,transition:H,dirs:W}=u;if(R=u.el=i(u.type,S,P&&P.is,P),U&8?f(R,u.children):U&16&&T(u.children,R,null,b,w,Jn(u,S),O,x),W&&Me(u,null,b,"created"),F(R,u,u.scopeId,O,b),P){for(const Q in P)Q!=="value"&&!bt(Q)&&o(R,Q,null,P[Q],S,u.children,b,w,He);"value"in P&&o(R,"value",null,P.value,S),(C=P.onVnodeBeforeMount)&&Ee(C,b,u)}W&&Me(u,null,b,"beforeMount");const z=qo(w,H);z&&H.beforeEnter(R),r(R,d,m),((C=P&&P.onVnodeMounted)||z||W)&&ge(()=>{C&&Ee(C,b,u),z&&H.enter(R),W&&Me(u,null,b,"mounted")},w)},F=(u,d,m,b,w)=>{if(m&&y(u,m),b)for(let S=0;S{for(let C=R;C{const x=d.el=u.el;let{patchFlag:R,dynamicChildren:C,dirs:P}=d;R|=u.patchFlag&16;const U=u.props||ee,H=d.props||ee;let W;if(m&&nt(m,!1),(W=H.onVnodeBeforeUpdate)&&Ee(W,m,d,u),P&&Me(d,u,m,"beforeUpdate"),m&&nt(m,!0),C?E(u.dynamicChildren,C,x,m,b,Jn(d,w),S):O||V(u,d,x,null,m,b,Jn(d,w),S,!1),R>0){if(R&16)j(x,d,U,H,m,b,w);else if(R&2&&U.class!==H.class&&o(x,"class",null,H.class,w),R&4&&o(x,"style",U.style,H.style,w),R&8){const z=d.dynamicProps;for(let Q=0;Q{W&&Ee(W,m,d,u),P&&Me(d,u,m,"updated")},b)},E=(u,d,m,b,w,S,O)=>{for(let x=0;x{if(m!==b){if(m!==ee)for(const x in m)!bt(x)&&!(x in b)&&o(u,x,m[x],null,O,d.children,w,S,He);for(const x in b){if(bt(x))continue;const R=b[x],C=m[x];R!==C&&x!=="value"&&o(u,x,C,R,O,d.children,w,S,He)}"value"in b&&o(u,"value",m.value,b.value,O)}},A=(u,d,m,b,w,S,O,x,R)=>{const C=d.el=u?u.el:l(""),P=d.anchor=u?u.anchor:l("");let{patchFlag:U,dynamicChildren:H,slotScopeIds:W}=d;W&&(x=x?x.concat(W):W),u==null?(r(C,m,b),r(P,m,b),T(d.children||[],m,P,w,S,O,x,R)):U>0&&U&64&&H&&u.dynamicChildren?(E(u.dynamicChildren,H,m,w,S,O,x),(d.key!=null||w&&d===w.subTree)&&Gr(u,d,!0)):V(u,d,m,P,w,S,O,x,R)},G=(u,d,m,b,w,S,O,x,R)=>{d.slotScopeIds=x,u==null?d.shapeFlag&512?w.ctx.activate(d,m,b,O,R):ie(d,m,b,w,S,O,R):fe(u,d,R)},ie=(u,d,m,b,w,S,O)=>{const x=u.component=bc(u,b,w);if(Gt(u)&&(x.ctx.renderer=pt),wc(x),x.asyncDep){if(w&&w.registerDep(x,D),!u.el){const R=x.subTree=oe(be);K(null,R,d,m)}}else D(x,u,d,m,w,S,O)},fe=(u,d,m)=>{const b=d.component=u.component;if(Sl(u,d,m))if(b.asyncDep&&!b.asyncResolved){X(b,d,m);return}else b.next=d,_l(b.update),b.effect.dirty=!0,b.update();else d.el=u.el,b.vnode=d},D=(u,d,m,b,w,S,O)=>{const x=()=>{if(u.isMounted){let{next:P,bu:U,u:H,parent:W,vnode:z}=u;{const gt=Go(u);if(gt){P&&(P.el=z.el,X(u,P,O)),gt.asyncDep.then(()=>{u.isUnmounted||x()});return}}let Q=P,te;nt(u,!1),P?(P.el=z.el,X(u,P,O)):P=z,U&&pn(U),(te=P.props&&P.props.onVnodeBeforeUpdate)&&Ee(te,W,P,z),nt(u,!0);const ae=Gn(u),Ae=u.subTree;u.subTree=ae,I(Ae,ae,h(Ae.el),Jt(Ae),u,w,S),P.el=ae.el,Q===null&&Tl(u,ae.el),H&&ge(H,w),(te=P.props&&P.props.onVnodeUpdated)&&ge(()=>Ee(te,W,P,z),w)}else{let P;const{el:U,props:H}=d,{bm:W,m:z,parent:Q}=u,te=Ct(d);if(nt(u,!1),W&&pn(W),!te&&(P=H&&H.onVnodeBeforeMount)&&Ee(P,Q,d),nt(u,!0),U&&Wn){const ae=()=>{u.subTree=Gn(u),Wn(U,u.subTree,u,w,null)};te?d.type.__asyncLoader().then(()=>!u.isUnmounted&&ae()):ae()}else{const ae=u.subTree=Gn(u);I(null,ae,m,b,u,w,S),d.el=ae.el}if(z&&ge(z,w),!te&&(P=H&&H.onVnodeMounted)){const ae=d;ge(()=>Ee(P,Q,ae),w)}(d.shapeFlag&256||Q&&Ct(Q.vnode)&&Q.vnode.shapeFlag&256)&&u.a&&ge(u.a,w),u.isMounted=!0,d=m=b=null}},R=u.effect=new Mr(x,xe,()=>Nn(C),u.scope),C=u.update=()=>{R.dirty&&R.run()};C.id=u.uid,nt(u,!0),C()},X=(u,d,m)=>{d.component=u;const b=u.vnode.props;u.vnode=d,u.next=null,tc(u,d.props,b,m),sc(u,d.children,m),dt(),fs(u),ht()},V=(u,d,m,b,w,S,O,x,R=!1)=>{const C=u&&u.children,P=u?u.shapeFlag:0,U=d.children,{patchFlag:H,shapeFlag:W}=d;if(H>0){if(H&128){Yt(C,U,m,b,w,S,O,x,R);return}else if(H&256){$e(C,U,m,b,w,S,O,x,R);return}}W&8?(P&16&&He(C,w,S),U!==C&&f(m,U)):P&16?W&16?Yt(C,U,m,b,w,S,O,x,R):He(C,w,S,!0):(P&8&&f(m,""),W&16&&T(U,m,b,w,S,O,x,R))},$e=(u,d,m,b,w,S,O,x,R)=>{u=u||_t,d=d||_t;const C=u.length,P=d.length,U=Math.min(C,P);let H;for(H=0;HP?He(u,w,S,!0,!1,U):T(d,m,b,w,S,O,x,R,U)},Yt=(u,d,m,b,w,S,O,x,R)=>{let C=0;const P=d.length;let U=u.length-1,H=P-1;for(;C<=U&&C<=H;){const W=u[C],z=d[C]=R?ze(d[C]):Re(d[C]);if(it(W,z))I(W,z,m,null,w,S,O,x,R);else break;C++}for(;C<=U&&C<=H;){const W=u[U],z=d[H]=R?ze(d[H]):Re(d[H]);if(it(W,z))I(W,z,m,null,w,S,O,x,R);else break;U--,H--}if(C>U){if(C<=H){const W=H+1,z=WH)for(;C<=U;)Oe(u[C],w,S,!0),C++;else{const W=C,z=C,Q=new Map;for(C=z;C<=H;C++){const _e=d[C]=R?ze(d[C]):Re(d[C]);_e.key!=null&&Q.set(_e.key,C)}let te,ae=0;const Ae=H-z+1;let gt=!1,es=0;const Lt=new Array(Ae);for(C=0;C=Ae){Oe(_e,w,S,!0);continue}let Ie;if(_e.key!=null)Ie=Q.get(_e.key);else for(te=z;te<=H;te++)if(Lt[te-z]===0&&it(_e,d[te])){Ie=te;break}Ie===void 0?Oe(_e,w,S,!0):(Lt[Ie-z]=C+1,Ie>=es?es=Ie:gt=!0,I(_e,d[Ie],m,null,w,S,O,x,R),ae++)}const ts=gt?uc(Lt):_t;for(te=ts.length-1,C=Ae-1;C>=0;C--){const _e=z+C,Ie=d[_e],ns=_e+1{const{el:S,type:O,transition:x,children:R,shapeFlag:C}=u;if(C&6){tt(u.component.subTree,d,m,b);return}if(C&128){u.suspense.move(d,m,b);return}if(C&64){O.move(u,d,m,pt);return}if(O===me){r(S,d,m);for(let U=0;Ux.enter(S),w);else{const{leave:U,delayLeave:H,afterLeave:W}=x,z=()=>r(S,d,m),Q=()=>{U(S,()=>{z(),W&&W()})};H?H(S,z,Q):Q()}else r(S,d,m)},Oe=(u,d,m,b=!1,w=!1)=>{const{type:S,props:O,ref:x,children:R,dynamicChildren:C,shapeFlag:P,patchFlag:U,dirs:H}=u;if(x!=null&&xn(x,null,m,u,!0),P&256){d.ctx.deactivate(u);return}const W=P&1&&H,z=!Ct(u);let Q;if(z&&(Q=O&&O.onVnodeBeforeUnmount)&&Ee(Q,d,u),P&6)xi(u.component,m,b);else{if(P&128){u.suspense.unmount(m,b);return}W&&Me(u,null,d,"beforeUnmount"),P&64?u.type.remove(u,d,m,w,pt,b):C&&(S!==me||U>0&&U&64)?He(C,d,m,!1,!0):(S===me&&U&384||!w&&P&16)&&He(R,d,m),b&&Qr(u)}(z&&(Q=O&&O.onVnodeUnmounted)||W)&&ge(()=>{Q&&Ee(Q,d,u),W&&Me(u,null,d,"unmounted")},m)},Qr=u=>{const{type:d,el:m,anchor:b,transition:w}=u;if(d===me){Ci(m,b);return}if(d===Ht){_(u);return}const S=()=>{s(m),w&&!w.persisted&&w.afterLeave&&w.afterLeave()};if(u.shapeFlag&1&&w&&!w.persisted){const{leave:O,delayLeave:x}=w,R=()=>O(m,S);x?x(u.el,S,R):R()}else S()},Ci=(u,d)=>{let m;for(;u!==d;)m=p(u),s(u),u=m;s(d)},xi=(u,d,m)=>{const{bum:b,scope:w,update:S,subTree:O,um:x}=u;b&&pn(b),w.stop(),S&&(S.active=!1,Oe(O,u,d,m)),x&&ge(x,d),ge(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},He=(u,d,m,b=!1,w=!1,S=0)=>{for(let O=S;Ou.shapeFlag&6?Jt(u.component.subTree):u.shapeFlag&128?u.suspense.next():p(u.anchor||u.el);let kn=!1;const Zr=(u,d,m)=>{u==null?d._vnode&&Oe(d._vnode,null,null,!0):I(d._vnode||null,u,d,null,null,null,m),kn||(kn=!0,fs(),wn(),kn=!1),d._vnode=u},pt={p:I,um:Oe,m:tt,r:Qr,mt:ie,mc:T,pc:V,pbc:E,n:Jt,o:e};let Kn,Wn;return t&&([Kn,Wn]=t(pt)),{render:Zr,hydrate:Kn,createApp:Ql(Zr,Kn)}}function Jn({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function nt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function qo(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Gr(e,t,n=!1){const r=e.children,s=t.children;if(B(r)&&B(s))for(let o=0;o>1,e[n[l]]0&&(t[r]=n[o-1]),n[o]=r)}}for(o=n.length,i=n[o-1];o-- >0;)n[o]=i,i=t[i];return n}function Go(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Go(t)}const fc=e=>e.__isTeleport,$t=e=>e&&(e.disabled||e.disabled===""),Cs=e=>typeof SVGElement<"u"&&e instanceof SVGElement,xs=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,wr=(e,t)=>{const n=e&&e.to;return ne(n)?t?t(n):null:n},dc={name:"Teleport",__isTeleport:!0,process(e,t,n,r,s,o,i,l,c,a){const{mc:f,pc:h,pbc:p,o:{insert:y,querySelector:v,createText:I,createComment:N}}=a,K=$t(t.props);let{shapeFlag:k,children:g,dynamicChildren:_}=t;if(e==null){const M=t.el=I(""),L=t.anchor=I("");y(M,n,r),y(L,n,r);const F=t.target=wr(t.props,v),T=t.targetAnchor=I("");F&&(y(T,F),i==="svg"||Cs(F)?i="svg":(i==="mathml"||xs(F))&&(i="mathml"));const $=(E,j)=>{k&16&&f(g,E,j,s,o,i,l,c)};K?$(n,L):F&&$(F,T)}else{t.el=e.el;const M=t.anchor=e.anchor,L=t.target=e.target,F=t.targetAnchor=e.targetAnchor,T=$t(e.props),$=T?n:L,E=T?M:F;if(i==="svg"||Cs(L)?i="svg":(i==="mathml"||xs(L))&&(i="mathml"),_?(p(e.dynamicChildren,_,$,s,o,i,l),Gr(e,t,!0)):c||h(e,t,$,E,s,o,i,l,!1),K)T?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):cn(t,n,M,a,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const j=t.target=wr(t.props,v);j&&cn(t,j,null,a,0)}else T&&cn(t,L,F,a,1)}zo(t)},remove(e,t,n,r,{um:s,o:{remove:o}},i){const{shapeFlag:l,children:c,anchor:a,targetAnchor:f,target:h,props:p}=e;if(h&&o(f),i&&o(a),l&16){const y=i||!$t(p);for(let v=0;v0?Le||_t:null,pc(),kt>0&&Le&&Le.push(e),e}function uu(e,t,n,r,s,o){return Yo(Zo(e,t,n,r,s,o,!0))}function Jo(e,t,n,r,s){return Yo(oe(e,t,n,r,s,!0))}function Sn(e){return e?e.__v_isVNode===!0:!1}function it(e,t){return e.type===t.type&&e.key===t.key}const Dn="__vInternal",Qo=({key:e})=>e??null,gn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ne(e)||de(e)||q(e)?{i:le,r:e,k:t,f:!!n}:e:null);function Zo(e,t=null,n=null,r=0,s=null,o=e===me?0:1,i=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Qo(t),ref:t&&gn(t),scopeId:$n,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:r,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:le};return l?(zr(c,n),o&128&&e.normalize(c)):n&&(c.shapeFlag|=ne(n)?8:16),kt>0&&!i&&Le&&(c.patchFlag>0||o&6)&&c.patchFlag!==32&&Le.push(c),c}const oe=gc;function gc(e,t=null,n=null,r=0,s=null,o=!1){if((!e||e===Ro)&&(e=be),Sn(e)){const l=et(e,t,!0);return n&&zr(l,n),kt>0&&!o&&Le&&(l.shapeFlag&6?Le[Le.indexOf(e)]=l:Le.push(l)),l.patchFlag|=-2,l}if(Sc(e)&&(e=e.__vccOpts),t){t=mc(t);let{class:l,style:c}=t;l&&!ne(l)&&(t.class=Ir(l)),Z(c)&&(vo(c)&&!B(c)&&(c=ce({},c)),t.style=Or(c))}const i=ne(e)?1:Al(e)?128:fc(e)?64:Z(e)?4:q(e)?2:0;return Zo(e,t,n,r,s,i,o,!0)}function mc(e){return e?vo(e)||Dn in e?ce({},e):e:null}function et(e,t,n=!1){const{props:r,ref:s,patchFlag:o,children:i}=e,l=t?yc(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&Qo(l),ref:t&&t.ref?n&&s?B(s)?s.concat(gn(t)):[s,gn(t)]:gn(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==me?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&et(e.ssContent),ssFallback:e.ssFallback&&et(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function ei(e=" ",t=0){return oe(Tt,null,e,t)}function fu(e,t){const n=oe(Ht,null,e);return n.staticCount=t,n}function du(e="",t=!1){return t?(Xo(),Jo(be,null,e)):oe(be,null,e)}function Re(e){return e==null||typeof e=="boolean"?oe(be):B(e)?oe(me,null,e.slice()):typeof e=="object"?ze(e):oe(Tt,null,String(e))}function ze(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:et(e)}function zr(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(B(t))n=16;else if(typeof t=="object")if(r&65){const s=t.default;s&&(s._c&&(s._d=!1),zr(e,s()),s._c&&(s._d=!0));return}else{n=32;const s=t._;!s&&!(Dn in t)?t._ctx=le:s===3&&le&&(le.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else q(t)?(t={default:t,_ctx:le},n=32):(t=String(t),r&64?(n=16,t=[ei(t)]):n=8);e.children=t,e.shapeFlag|=n}function yc(...e){const t={};for(let n=0;nue||le;let Tn,Er;{const e=ro(),t=(n,r)=>{let s;return(s=e[n])||(s=e[n]=[]),s.push(r),o=>{s.length>1?s.forEach(i=>i(o)):s[0](o)}};Tn=t("__VUE_INSTANCE_SETTERS__",n=>ue=n),Er=t("__VUE_SSR_SETTERS__",n=>Xt=n)}const zt=e=>{const t=ue;return Tn(e),e.scope.on(),()=>{e.scope.off(),Tn(t)}},Ts=()=>{ue&&ue.scope.off(),Tn(null)};function ti(e){return e.vnode.shapeFlag&4}let Xt=!1;function wc(e,t=!1){t&&Er(t);const{props:n,children:r}=e.vnode,s=ti(e);ec(e,n,s,t),rc(e,r);const o=s?Ec(e,t):void 0;return t&&Er(!1),o}function Ec(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Mt(new Proxy(e.ctx,Kl));const{setup:r}=n;if(r){const s=e.setupContext=r.length>1?ri(e):null,o=zt(e);dt();const i=Je(r,e,0,[e.props,s]);if(ht(),o(),eo(i)){if(i.then(Ts,Ts),t)return i.then(l=>{As(e,l,t)}).catch(l=>{qt(l,e,0)});e.asyncDep=i}else As(e,i,t)}else ni(e,t)}function As(e,t,n){q(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Z(t)&&(e.setupState=Co(t)),ni(e,n)}let Rs;function ni(e,t,n){const r=e.type;if(!e.render){if(!t&&Rs&&!r.render){const s=r.template||Wr(e).template;if(s){const{isCustomElement:o,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:c}=r,a=ce(ce({isCustomElement:o,delimiters:l},i),c);r.render=Rs(s,a)}}e.render=r.render||xe}{const s=zt(e);dt();try{ql(e)}finally{ht(),s()}}}function Cc(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return ye(e,"get","$attrs"),t[n]}}))}function ri(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Cc(e)},slots:e.slots,emit:e.emit,expose:t}}function Bn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Co(Mt(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Nt)return Nt[n](e)},has(t,n){return n in t||n in Nt}}))}function xc(e,t=!0){return q(e)?e.displayName||e.name:e.name||t&&e.__name}function Sc(e){return q(e)&&"__vccOpts"in e}const re=(e,t)=>ll(e,t,Xt);function Cr(e,t,n){const r=arguments.length;return r===2?Z(t)&&!B(t)?Sn(t)?oe(e,null,[t]):oe(e,t):oe(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Sn(n)&&(n=[n]),oe(e,t,n))}const Tc="3.4.21";/** +* @vue/runtime-dom v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/const Ac="http://www.w3.org/2000/svg",Rc="http://www.w3.org/1998/Math/MathML",Xe=typeof document<"u"?document:null,Ls=Xe&&Xe.createElement("template"),Lc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?Xe.createElementNS(Ac,e):t==="mathml"?Xe.createElementNS(Rc,e):Xe.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>Xe.createTextNode(e),createComment:e=>Xe.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Xe.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,o){const i=n?n.previousSibling:t.lastChild;if(s&&(s===o||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===o||!(s=s.nextSibling)););else{Ls.innerHTML=r==="svg"?`${e}`:r==="mathml"?`${e}`:e;const l=Ls.content;if(r==="svg"||r==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Ke="transition",Ot="animation",Kt=Symbol("_vtc"),si=(e,{slots:t})=>Cr(Pl,Oc(e),t);si.displayName="Transition";const oi={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};si.props=ce({},Mo,oi);const rt=(e,t=[])=>{B(e)?e.forEach(n=>n(...t)):e&&e(...t)},Os=e=>e?B(e)?e.some(t=>t.length>1):e.length>1:!1;function Oc(e){const t={};for(const A in e)A in oi||(t[A]=e[A]);if(e.css===!1)return t;const{name:n="v",type:r,duration:s,enterFromClass:o=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=o,appearActiveClass:a=i,appearToClass:f=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,v=Ic(s),I=v&&v[0],N=v&&v[1],{onBeforeEnter:K,onEnter:k,onEnterCancelled:g,onLeave:_,onLeaveCancelled:M,onBeforeAppear:L=K,onAppear:F=k,onAppearCancelled:T=g}=t,$=(A,G,ie)=>{st(A,G?f:l),st(A,G?a:i),ie&&ie()},E=(A,G)=>{A._isLeaving=!1,st(A,h),st(A,y),st(A,p),G&&G()},j=A=>(G,ie)=>{const fe=A?F:k,D=()=>$(G,A,ie);rt(fe,[G,D]),Is(()=>{st(G,A?c:o),We(G,A?f:l),Os(fe)||Ms(G,r,I,D)})};return ce(t,{onBeforeEnter(A){rt(K,[A]),We(A,o),We(A,i)},onBeforeAppear(A){rt(L,[A]),We(A,c),We(A,a)},onEnter:j(!1),onAppear:j(!0),onLeave(A,G){A._isLeaving=!0;const ie=()=>E(A,G);We(A,h),Nc(),We(A,p),Is(()=>{A._isLeaving&&(st(A,h),We(A,y),Os(_)||Ms(A,r,N,ie))}),rt(_,[A,ie])},onEnterCancelled(A){$(A,!1),rt(g,[A])},onAppearCancelled(A){$(A,!0),rt(T,[A])},onLeaveCancelled(A){E(A),rt(M,[A])}})}function Ic(e){if(e==null)return null;if(Z(e))return[Qn(e.enter),Qn(e.leave)];{const t=Qn(e);return[t,t]}}function Qn(e){return Oi(e)}function We(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Kt]||(e[Kt]=new Set)).add(t)}function st(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[Kt];n&&(n.delete(t),n.size||(e[Kt]=void 0))}function Is(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Mc=0;function Ms(e,t,n,r){const s=e._endId=++Mc,o=()=>{s===e._endId&&r()};if(n)return setTimeout(o,n);const{type:i,timeout:l,propCount:c}=Pc(e,t);if(!i)return r();const a=i+"end";let f=0;const h=()=>{e.removeEventListener(a,p),o()},p=y=>{y.target===e&&++f>=c&&h()};setTimeout(()=>{f(n[v]||"").split(", "),s=r(`${Ke}Delay`),o=r(`${Ke}Duration`),i=Ps(s,o),l=r(`${Ot}Delay`),c=r(`${Ot}Duration`),a=Ps(l,c);let f=null,h=0,p=0;t===Ke?i>0&&(f=Ke,h=i,p=o.length):t===Ot?a>0&&(f=Ot,h=a,p=c.length):(h=Math.max(i,a),f=h>0?i>a?Ke:Ot:null,p=f?f===Ke?o.length:c.length:0);const y=f===Ke&&/\b(transform|all)(,|$)/.test(r(`${Ke}Property`).toString());return{type:f,timeout:h,propCount:p,hasTransform:y}}function Ps(e,t){for(;e.lengthNs(n)+Ns(e[r])))}function Ns(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Nc(){return document.body.offsetHeight}function Fc(e,t,n){const r=e[Kt];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Fs=Symbol("_vod"),$c=Symbol("_vsh"),Hc=Symbol(""),jc=/(^|;)\s*display\s*:/;function Vc(e,t,n){const r=e.style,s=ne(n);let o=!1;if(n&&!s){if(t)if(ne(t))for(const i of t.split(";")){const l=i.slice(0,i.indexOf(":")).trim();n[l]==null&&mn(r,l,"")}else for(const i in t)n[i]==null&&mn(r,i,"");for(const i in n)i==="display"&&(o=!0),mn(r,i,n[i])}else if(s){if(t!==n){const i=r[Hc];i&&(n+=";"+i),r.cssText=n,o=jc.test(n)}}else t&&e.removeAttribute("style");Fs in e&&(e[Fs]=o?r.display:"",e[$c]&&(r.display="none"))}const $s=/\s*!important$/;function mn(e,t,n){if(B(n))n.forEach(r=>mn(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Dc(e,t);$s.test(n)?e.setProperty(ft(r),n.replace($s,""),"important"):e[r]=n}}const Hs=["Webkit","Moz","ms"],Zn={};function Dc(e,t){const n=Zn[t];if(n)return n;let r=Fe(t);if(r!=="filter"&&r in e)return Zn[t]=r;r=Ln(r);for(let s=0;ser||(qc.then(()=>er=0),er=Date.now());function zc(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;Se(Xc(r,n.value),t,5,[r])};return n.value=e,n.attached=Gc(),n}function Xc(e,t){if(B(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const Us=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Yc=(e,t,n,r,s,o,i,l,c)=>{const a=s==="svg";t==="class"?Fc(e,r,a):t==="style"?Vc(e,n,r):Wt(t)?Ar(t)||Kc(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Jc(e,t,r,a))?Bc(e,t,r,o,i,l,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Uc(e,t,r,a))};function Jc(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&Us(t)&&q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return Us(t)&&ne(n)?!1:t in e}const Bs=e=>{const t=e.props["onUpdate:modelValue"]||!1;return B(t)?n=>pn(t,n):t};function Qc(e){e.target.composing=!0}function ks(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const tr=Symbol("_assign"),hu={created(e,{modifiers:{lazy:t,trim:n,number:r}},s){e[tr]=Bs(s);const o=r||s.props&&s.props.type==="number";mt(e,t?"change":"input",i=>{if(i.target.composing)return;let l=e.value;n&&(l=l.trim()),o&&(l=ur(l)),e[tr](l)}),n&&mt(e,"change",()=>{e.value=e.value.trim()}),t||(mt(e,"compositionstart",Qc),mt(e,"compositionend",ks),mt(e,"change",ks))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:s}},o){if(e[tr]=Bs(o),e.composing)return;const i=s||e.type==="number"?ur(e.value):e.value,l=t??"";i!==l&&(document.activeElement===e&&e.type!=="range"&&(n||r&&e.value.trim()===l)||(e.value=l))}},Zc=["ctrl","shift","alt","meta"],ea={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Zc.some(n=>e[`${n}Key`]&&!t.includes(n))},pu=(e,t)=>{const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=(s,...o)=>{for(let i=0;i{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=s=>{if(!("key"in s))return;const o=ft(s.key);if(t.some(i=>i===o||ta[i]===o))return e(s)})},ii=ce({patchProp:Yc},Lc);let Vt,Ks=!1;function na(){return Vt||(Vt=cc(ii))}function ra(){return Vt=Ks?Vt:ac(ii),Ks=!0,Vt}const mu=(...e)=>{const t=na().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=ci(r);if(!s)return;const o=t._component;!q(o)&&!o.render&&!o.template&&(o.template=s.innerHTML),s.innerHTML="";const i=n(s,!1,li(s));return s instanceof Element&&(s.removeAttribute("v-cloak"),s.setAttribute("data-v-app","")),i},t},yu=(...e)=>{const t=ra().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=ci(r);if(s)return n(s,!0,li(s))},t};function li(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function ci(e){return ne(e)?document.querySelector(e):e}const _u=(e,t)=>{const n=e.__vccOpts||e;for(const[r,s]of t)n[r]=s;return n},sa="modulepreload",oa=function(e){return"/minigame-unity-webgl-transform/"+e},Ws={},vu=function(t,n,r){let s=Promise.resolve();if(n&&n.length>0){const o=document.getElementsByTagName("link"),i=document.querySelector("meta[property=csp-nonce]"),l=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));s=Promise.all(n.map(c=>{if(c=oa(c),c in Ws)return;Ws[c]=!0;const a=c.endsWith(".css"),f=a?'[rel="stylesheet"]':"";if(!!r)for(let y=o.length-1;y>=0;y--){const v=o[y];if(v.href===c&&(!a||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${c}"]${f}`))return;const p=document.createElement("link");if(p.rel=a?"stylesheet":sa,a||(p.as="script",p.crossOrigin=""),p.href=c,l&&p.setAttribute("nonce",l),document.head.appendChild(p),a)return new Promise((y,v)=>{p.addEventListener("load",y),p.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${c}`)))})}))}return s.then(()=>t()).catch(o=>{const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=o,window.dispatchEvent(i),!i.defaultPrevented)throw o})},ia=window.__VP_SITE_DATA__;function Xr(e){return io()?(Vi(e),!0):!1}function Ne(e){return typeof e=="function"?e():Eo(e)}const ai=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const la=Object.prototype.toString,ca=e=>la.call(e)==="[object Object]",Qe=()=>{},xr=aa();function aa(){var e,t;return ai&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function ua(e,t){function n(...r){return new Promise((s,o)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(s).catch(o)})}return n}const ui=e=>e();function fa(e,t={}){let n,r,s=Qe;const o=l=>{clearTimeout(l),s(),s=Qe};return l=>{const c=Ne(e),a=Ne(t.maxWait);return n&&o(n),c<=0||a!==void 0&&a<=0?(r&&(o(r),r=null),Promise.resolve(l())):new Promise((f,h)=>{s=t.rejectOnCancel?h:f,a&&!r&&(r=setTimeout(()=>{n&&o(n),r=null,f(l())},a)),n=setTimeout(()=>{r&&o(r),r=null,f(l())},c)})}}function da(e=ui){const t=se(!0);function n(){t.value=!1}function r(){t.value=!0}const s=(...o)=>{t.value&&e(...o)};return{isActive:Mn(t),pause:n,resume:r,eventFilter:s}}function ha(e){return e||Un()}function fi(...e){if(e.length!==1)return pl(...e);const t=e[0];return typeof t=="function"?Mn(fl(()=>({get:t,set:Qe}))):se(t)}function di(e,t,n={}){const{eventFilter:r=ui,...s}=n;return Ve(e,ua(r,t),s)}function pa(e,t,n={}){const{eventFilter:r,...s}=n,{eventFilter:o,pause:i,resume:l,isActive:c}=da(r);return{stop:di(e,t,{...s,eventFilter:o}),pause:i,resume:l,isActive:c}}function Yr(e,t=!0,n){ha()?Rt(e,n):t?e():Pn(e)}function bu(e,t,n={}){const{debounce:r=0,maxWait:s=void 0,...o}=n;return di(e,t,{...o,eventFilter:fa(r,{maxWait:s})})}function wu(e,t,n){let r;de(n)?r={evaluating:n}:r=n||{};const{lazy:s=!1,evaluating:o=void 0,shallow:i=!0,onError:l=Qe}=r,c=se(!s),a=i?Dr(t):se(t);let f=0;return kr(async h=>{if(!c.value)return;f++;const p=f;let y=!1;o&&Promise.resolve().then(()=>{o.value=!0});try{const v=await e(I=>{h(()=>{o&&(o.value=!1),y||I()})});p===f&&(a.value=v)}catch(v){l(v)}finally{o&&p===f&&(o.value=!1),y=!0}}),s?re(()=>(c.value=!0,a.value)):a}function yt(e){var t;const n=Ne(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Te=ai?window:void 0;function De(...e){let t,n,r,s;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,s]=e,t=Te):[t,n,r,s]=e,!t)return Qe;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const o=[],i=()=>{o.forEach(f=>f()),o.length=0},l=(f,h,p,y)=>(f.addEventListener(h,p,y),()=>f.removeEventListener(h,p,y)),c=Ve(()=>[yt(t),Ne(s)],([f,h])=>{if(i(),!f)return;const p=ca(h)?{...h}:h;o.push(...n.flatMap(y=>r.map(v=>l(f,y,v,p))))},{immediate:!0,flush:"post"}),a=()=>{c(),i()};return Xr(a),a}let qs=!1;function Eu(e,t,n={}){const{window:r=Te,ignore:s=[],capture:o=!0,detectIframe:i=!1}=n;if(!r)return Qe;xr&&!qs&&(qs=!0,Array.from(r.document.body.children).forEach(p=>p.addEventListener("click",Qe)),r.document.documentElement.addEventListener("click",Qe));let l=!0;const c=p=>s.some(y=>{if(typeof y=="string")return Array.from(r.document.querySelectorAll(y)).some(v=>v===p.target||p.composedPath().includes(v));{const v=yt(y);return v&&(p.target===v||p.composedPath().includes(v))}}),f=[De(r,"click",p=>{const y=yt(e);if(!(!y||y===p.target||p.composedPath().includes(y))){if(p.detail===0&&(l=!c(p)),!l){l=!0;return}t(p)}},{passive:!0,capture:o}),De(r,"pointerdown",p=>{const y=yt(e);l=!c(p)&&!!(y&&!p.composedPath().includes(y))},{passive:!0}),i&&De(r,"blur",p=>{setTimeout(()=>{var y;const v=yt(e);((y=r.document.activeElement)==null?void 0:y.tagName)==="IFRAME"&&!(v!=null&&v.contains(r.document.activeElement))&&t(p)},0)})].filter(Boolean);return()=>f.forEach(p=>p())}function ga(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Cu(...e){let t,n,r={};e.length===3?(t=e[0],n=e[1],r=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],r=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:s=Te,eventName:o="keydown",passive:i=!1,dedupe:l=!1}=r,c=ga(t);return De(s,o,f=>{f.repeat&&Ne(l)||c(f)&&n(f)},i)}function ma(){const e=se(!1),t=Un();return t&&Rt(()=>{e.value=!0},t),e}function ya(e){const t=ma();return re(()=>(t.value,!!e()))}function hi(e,t={}){const{window:n=Te}=t,r=ya(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let s;const o=se(!1),i=a=>{o.value=a.matches},l=()=>{s&&("removeEventListener"in s?s.removeEventListener("change",i):s.removeListener(i))},c=kr(()=>{r.value&&(l(),s=n.matchMedia(Ne(e)),"addEventListener"in s?s.addEventListener("change",i):s.addListener(i),o.value=s.matches)});return Xr(()=>{c(),l(),s=void 0}),o}const an=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},un="__vueuse_ssr_handlers__",_a=va();function va(){return un in an||(an[un]=an[un]||{}),an[un]}function pi(e,t){return _a[e]||t}function ba(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const wa={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Gs="vueuse-storage";function Jr(e,t,n,r={}){var s;const{flush:o="pre",deep:i=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:a=!1,shallow:f,window:h=Te,eventFilter:p,onError:y=E=>{console.error(E)},initOnMounted:v}=r,I=(f?Dr:se)(typeof t=="function"?t():t);if(!n)try{n=pi("getDefaultStorage",()=>{var E;return(E=Te)==null?void 0:E.localStorage})()}catch(E){y(E)}if(!n)return I;const N=Ne(t),K=ba(N),k=(s=r.serializer)!=null?s:wa[K],{pause:g,resume:_}=pa(I,()=>L(I.value),{flush:o,deep:i,eventFilter:p});h&&l&&Yr(()=>{De(h,"storage",T),De(h,Gs,$),v&&T()}),v||T();function M(E,j){h&&h.dispatchEvent(new CustomEvent(Gs,{detail:{key:e,oldValue:E,newValue:j,storageArea:n}}))}function L(E){try{const j=n.getItem(e);if(E==null)M(j,null),n.removeItem(e);else{const A=k.write(E);j!==A&&(n.setItem(e,A),M(j,A))}}catch(j){y(j)}}function F(E){const j=E?E.newValue:n.getItem(e);if(j==null)return c&&N!=null&&n.setItem(e,k.write(N)),N;if(!E&&a){const A=k.read(j);return typeof a=="function"?a(A,N):K==="object"&&!Array.isArray(A)?{...N,...A}:A}else return typeof j!="string"?j:k.read(j)}function T(E){if(!(E&&E.storageArea!==n)){if(E&&E.key==null){I.value=N;return}if(!(E&&E.key!==e)){g();try{(E==null?void 0:E.newValue)!==k.write(I.value)&&(I.value=F(E))}catch(j){y(j)}finally{E?Pn(_):_()}}}}function $(E){T(E.detail)}return I}function gi(e){return hi("(prefers-color-scheme: dark)",e)}function Ea(e={}){const{selector:t="html",attribute:n="class",initialValue:r="auto",window:s=Te,storage:o,storageKey:i="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:a,disableTransition:f=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},p=gi({window:s}),y=re(()=>p.value?"dark":"light"),v=c||(i==null?fi(r):Jr(i,r,o,{window:s,listenToStorageChanges:l})),I=re(()=>v.value==="auto"?y.value:v.value),N=pi("updateHTMLAttrs",(_,M,L)=>{const F=typeof _=="string"?s==null?void 0:s.document.querySelector(_):yt(_);if(!F)return;let T;if(f&&(T=s.document.createElement("style"),T.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),s.document.head.appendChild(T)),M==="class"){const $=L.split(/\s/g);Object.values(h).flatMap(E=>(E||"").split(/\s/g)).filter(Boolean).forEach(E=>{$.includes(E)?F.classList.add(E):F.classList.remove(E)})}else F.setAttribute(M,L);f&&(s.getComputedStyle(T).opacity,document.head.removeChild(T))});function K(_){var M;N(t,n,(M=h[_])!=null?M:_)}function k(_){e.onChanged?e.onChanged(_,K):K(_)}Ve(I,k,{flush:"post",immediate:!0}),Yr(()=>k(I.value));const g=re({get(){return a?v.value:I.value},set(_){v.value=_}});try{return Object.assign(g,{store:v,system:y,state:I})}catch{return g}}function Ca(e={}){const{valueDark:t="dark",valueLight:n="",window:r=Te}=e,s=Ea({...e,onChanged:(l,c)=>{var a;e.onChanged?(a=e.onChanged)==null||a.call(e,l==="dark",c,l):c(l)},modes:{dark:t,light:n}}),o=re(()=>s.system?s.system.value:gi({window:r}).value?"dark":"light");return re({get(){return s.value==="dark"},set(l){const c=l?"dark":"light";o.value===c?s.value="auto":s.value=c}})}function nr(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function xu(e,t,n={}){const{window:r=Te}=n;return Jr(e,t,r==null?void 0:r.localStorage,n)}function mi(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const fn=new WeakMap;function Su(e,t=!1){const n=se(t);let r=null;Ve(fi(e),i=>{const l=nr(Ne(i));if(l){const c=l;fn.get(c)||fn.set(c,c.style.overflow),n.value&&(c.style.overflow="hidden")}},{immediate:!0});const s=()=>{const i=nr(Ne(e));!i||n.value||(xr&&(r=De(i,"touchmove",l=>{xa(l)},{passive:!1})),i.style.overflow="hidden",n.value=!0)},o=()=>{var i;const l=nr(Ne(e));!l||!n.value||(xr&&(r==null||r()),l.style.overflow=(i=fn.get(l))!=null?i:"",fn.delete(l),n.value=!1)};return Xr(o),re({get(){return n.value},set(i){i?s():o()}})}function Tu(e,t,n={}){const{window:r=Te}=n;return Jr(e,t,r==null?void 0:r.sessionStorage,n)}function Au(e={}){const{window:t=Te,behavior:n="auto"}=e;if(!t)return{x:se(0),y:se(0)};const r=se(t.scrollX),s=se(t.scrollY),o=re({get(){return r.value},set(l){scrollTo({left:l,behavior:n})}}),i=re({get(){return s.value},set(l){scrollTo({top:l,behavior:n})}});return De(t,"scroll",()=>{r.value=t.scrollX,s.value=t.scrollY},{capture:!1,passive:!0}),{x:o,y:i}}function Ru(e={}){const{window:t=Te,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:r=Number.POSITIVE_INFINITY,listenOrientation:s=!0,includeScrollbar:o=!0}=e,i=se(n),l=se(r),c=()=>{t&&(o?(i.value=t.innerWidth,l.value=t.innerHeight):(i.value=t.document.documentElement.clientWidth,l.value=t.document.documentElement.clientHeight))};if(c(),Yr(c),De("resize",c,{passive:!0}),s){const a=hi("(orientation: portrait)");Ve(a,()=>c())}return{width:i,height:l}}var rr={BASE_URL:"/minigame-unity-webgl-transform/",MODE:"production",DEV:!1,PROD:!0,SSR:!1},sr={};const yi=/^(?:[a-z]+:|\/\/)/i,Sa="vitepress-theme-appearance",Ta=/#.*$/,Aa=/[?#].*$/,Ra=/(?:(^|\/)index)?\.(?:md|html)$/,Ce=typeof document<"u",_i={relativePath:"",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function La(e,t,n=!1){if(t===void 0)return!1;if(e=zs(`/${e}`),n)return new RegExp(t).test(e);if(zs(t)!==e)return!1;const r=t.match(Ta);return r?(Ce?location.hash:"")===r[0]:!0}function zs(e){return decodeURI(e).replace(Aa,"").replace(Ra,"$1")}function Oa(e){return yi.test(e)}function Ia(e,t){var r,s,o,i,l,c,a;const n=Object.keys(e.locales).find(f=>f!=="root"&&!Oa(f)&&La(t,`/${f}/`,!0))||"root";return Object.assign({},e,{localeIndex:n,lang:((r=e.locales[n])==null?void 0:r.lang)??e.lang,dir:((s=e.locales[n])==null?void 0:s.dir)??e.dir,title:((o=e.locales[n])==null?void 0:o.title)??e.title,titleTemplate:((i=e.locales[n])==null?void 0:i.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:bi(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(a=e.locales[n])==null?void 0:a.themeConfig}})}function vi(e,t){const n=t.title||e.title,r=t.titleTemplate??e.titleTemplate;if(typeof r=="string"&&r.includes(":title"))return r.replace(/:title/g,n);const s=Ma(e.title,r);return n===s.slice(3)?n:`${n}${s}`}function Ma(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function Pa(e,t){const[n,r]=t;if(n!=="meta")return!1;const s=Object.entries(r)[0];return s==null?!1:e.some(([o,i])=>o===n&&i[s[0]]===s[1])}function bi(e,t){return[...e.filter(n=>!Pa(t,n)),...t]}const Na=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,Fa=/^[a-z]:/i;function Xs(e){const t=Fa.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(Na,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const or=new Set;function $a(e){if(or.size===0){const n=typeof process=="object"&&(sr==null?void 0:sr.VITE_EXTRA_EXTENSIONS)||(rr==null?void 0:rr.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(r=>or.add(r))}const t=e.split(".").pop();return t==null||!or.has(t.toLowerCase())}function Lu(e){return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}const Ha=Symbol(),ut=Dr(ia);function Ou(e){const t=re(()=>Ia(ut.value,e.data.relativePath)),n=t.value.appearance,r=n==="force-dark"?se(!0):n?Ca({storageKey:Sa,initialValue:()=>typeof n=="string"?n:"auto",...typeof n=="object"?n:{}}):se(!1);return{site:t,theme:re(()=>t.value.themeConfig),page:re(()=>e.data),frontmatter:re(()=>e.data.frontmatter),params:re(()=>e.data.params),lang:re(()=>t.value.lang),dir:re(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:re(()=>t.value.localeIndex||"root"),title:re(()=>vi(t.value,e.data)),description:re(()=>e.data.description||t.value.description),isDark:r}}function ja(){const e=xt(Ha);if(!e)throw new Error("vitepress data not properly injected in app");return e}function Va(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Ys(e){return yi.test(e)||!e.startsWith("/")?e:Va(ut.value.base,e)}function Da(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),Ce){const n="/minigame-unity-webgl-transform/";t=Xs(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let r=__VP_HASH_MAP__[t.toLowerCase()];if(r||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",r=__VP_HASH_MAP__[t.toLowerCase()]),!r)return null;t=`${n}assets/${t}.${r}.js`}else t=`./${Xs(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let yn=[];function Iu(e){yn.push(e),Vn(()=>{yn=yn.filter(t=>t!==e)})}function Ua(){let e=ut.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=Js(e,n);else if(Array.isArray(e))for(const r of e){const s=Js(r,n);if(s){t=s;break}}return t}function Js(e,t){const n=document.querySelector(e);if(!n)return 0;const r=n.getBoundingClientRect().bottom;return r<0?0:r+t}const Ba=Symbol(),Sr="http://a.com",ka=()=>({path:"/",component:null,data:_i});function Mu(e,t){const n=In(ka()),r={route:n,go:s};async function s(l=Ce?location.href:"/"){var c,a;if(l=ir(l),await((c=r.onBeforeRouteChange)==null?void 0:c.call(r,l))!==!1){if(Ce){const f=new URL(location.href);l!==ir(f.href)&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",l),new URL(l,Sr).hash!==f.hash&&window.dispatchEvent(new Event("hashchange")))}await i(l),await((a=r.onAfterRouteChanged)==null?void 0:a.call(r,l))}}let o=null;async function i(l,c=0,a=!1){var p;if(await((p=r.onBeforePageLoad)==null?void 0:p.call(r,l))===!1)return;const f=new URL(l,Sr),h=o=f.pathname;try{let y=await e(h);if(!y)throw new Error(`Page not found: ${h}`);if(o===h){o=null;const{default:v,__pageData:I}=y;if(!v)throw new Error(`Invalid route component: ${v}`);n.path=Ce?h:Ys(h),n.component=Mt(v),n.data=Mt(I),Ce&&Pn(()=>{let N=ut.value.base+I.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!ut.value.cleanUrls&&!N.endsWith("/")&&(N+=".html"),N!==f.pathname&&(f.pathname=N,l=N+f.search+f.hash,history.replaceState(null,"",l)),f.hash&&!c){let K=null;try{K=document.getElementById(decodeURIComponent(f.hash).slice(1))}catch(k){console.warn(k)}if(K){Qs(K,f.hash);return}}window.scrollTo(0,c)})}}catch(y){if(!/fetch|Page not found/.test(y.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(y),!a)try{const v=await fetch(ut.value.base+"hashmap.json");window.__VP_HASH_MAP__=await v.json(),await i(l,c,!0);return}catch{}o===h&&(o=null,n.path=Ce?h:Ys(h),n.component=t?Mt(t):null,n.data=_i)}}return Ce&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const a=l.target.closest("a");if(a&&!a.closest(".vp-raw")&&(a instanceof SVGElement||!a.download)){const{target:f}=a,{href:h,origin:p,pathname:y,hash:v,search:I}=new URL(a.href instanceof SVGAnimatedString?a.href.animVal:a.href,a.baseURI),N=new URL(location.href);!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&!f&&p===N.origin&&$a(y)&&(l.preventDefault(),y===N.pathname&&I===N.search?(v!==N.hash&&(history.pushState(null,"",h),window.dispatchEvent(new Event("hashchange"))),v?Qs(a,v,a.classList.contains("header-anchor")):window.scrollTo(0,0)):s(h))}},{capture:!0}),window.addEventListener("popstate",async l=>{var c;await i(ir(location.href),l.state&&l.state.scrollPosition||0),(c=r.onAfterRouteChanged)==null||c.call(r,location.href)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),r}function Ka(){const e=xt(Ba);if(!e)throw new Error("useRouter() is called without provider.");return e}function wi(){return Ka().route}function Qs(e,t,n=!1){let r=null;try{r=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(s){console.warn(s)}if(r){let s=function(){!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})};const o=parseInt(window.getComputedStyle(r).paddingTop,10),i=window.scrollY+r.getBoundingClientRect().top-Ua()+o;requestAnimationFrame(s)}}function ir(e){const t=new URL(e,Sr);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),ut.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const lr=()=>yn.forEach(e=>e()),Pu=Kr({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=wi(),{site:n}=ja();return()=>Cr(e.as,n.value.contentProps??{style:{position:"relative"}},[t.component?Cr(t.component,{onVnodeMounted:lr,onVnodeUpdated:lr,onVnodeUnmounted:lr}):"404 Page Not Found"])}}),Nu=Kr({setup(e,{slots:t}){const n=se(!1);return Rt(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function Fu(){Ce&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const r=(n=t.parentElement)==null?void 0:n.parentElement;if(!r)return;const s=Array.from(r.querySelectorAll("input")).indexOf(t);if(s<0)return;const o=r.querySelector(".blocks");if(!o)return;const i=Array.from(o.children).find(a=>a.classList.contains("active"));if(!i)return;const l=o.children[s];if(!l||i===l)return;i.classList.remove("active"),l.classList.add("active");const c=r==null?void 0:r.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function $u(){if(Ce){const e=new WeakMap;window.addEventListener("click",t=>{var r;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const s=n.parentElement,o=(r=n.nextElementSibling)==null?void 0:r.nextElementSibling;if(!s||!o)return;const i=/language-(shellscript|shell|bash|sh|zsh)/.test(s.className),l=[".vp-copy-ignore",".diff.remove"],c=o.cloneNode(!0);c.querySelectorAll(l.join(",")).forEach(f=>f.remove());let a=c.textContent||"";i&&(a=a.replace(/^ *(\$|>) /gm,"").trim()),Wa(a).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const f=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,f)})}})}}async function Wa(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const r=document.getSelection(),s=r?r.rangeCount>0&&r.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),s&&(r.removeAllRanges(),r.addRange(s)),n&&n.focus()}}function Hu(e,t){let n=!0,r=[];const s=o=>{if(n){n=!1,o.forEach(l=>{const c=cr(l);for(const a of document.head.children)if(a.isEqualNode(c)){r.push(a);return}});return}const i=o.map(cr);r.forEach((l,c)=>{const a=i.findIndex(f=>f==null?void 0:f.isEqualNode(l??null));a!==-1?delete i[a]:(l==null||l.remove(),delete r[c])}),i.forEach(l=>l&&document.head.appendChild(l)),r=[...r,...i].filter(Boolean)};kr(()=>{const o=e.data,i=t.value,l=o&&o.description,c=o&&o.frontmatter.head||[],a=vi(i,o);a!==document.title&&(document.title=a);const f=l||i.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==f&&h.setAttribute("content",f):cr(["meta",{name:"description",content:f}]),s(bi(i.head,Ga(c)))})}function cr([e,t,n]){const r=document.createElement(e);for(const s in t)r.setAttribute(s,t[s]);return n&&(r.innerHTML=n),e==="script"&&!t.async&&(r.async=!1),r}function qa(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function Ga(e){return e.filter(t=>!qa(t))}const ar=new Set,Ei=()=>document.createElement("link"),za=e=>{const t=Ei();t.rel="prefetch",t.href=e,document.head.appendChild(t)},Xa=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let dn;const Ya=Ce&&(dn=Ei())&&dn.relList&&dn.relList.supports&&dn.relList.supports("prefetch")?za:Xa;function ju(){if(!Ce||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const r=()=>{n&&n.disconnect(),n=new IntersectionObserver(o=>{o.forEach(i=>{if(i.isIntersecting){const l=i.target;n.unobserve(l);const{pathname:c}=l;if(!ar.has(c)){ar.add(c);const a=Da(c);a&&Ya(a)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(o=>{const{hostname:i,pathname:l}=new URL(o.href instanceof SVGAnimatedString?o.href.animVal:o.href,o.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||o.target!=="_blank"&&i===location.hostname&&(l!==location.pathname?n.observe(o):ar.add(l))})})};Rt(r);const s=wi();Ve(()=>s.path,r),Vn(()=>{n&&n.disconnect()})}export{Zl as $,Vn as A,nu as B,Vl as C,Ua as D,eu as E,me as F,ou as G,Dr as H,Iu as I,oe as J,tu as K,yi as L,wi as M,yc as N,xt as O,Ru as P,Or as Q,Eu as R,Cu as S,si as T,Pn as U,Au as V,Mn as W,su as X,vu as Y,Su as Z,_u as _,ei as a,lu as a0,gu as a1,pu as a2,cu as a3,fu as a4,Hu as a5,Ba as a6,Ou as a7,Ha as a8,Pu as a9,Nu as aa,ut as ab,yu as ac,Mu as ad,Da as ae,ju as af,$u as ag,Fu as ah,Cr as ai,yt as aj,Xr as ak,wu as al,Tu as am,xu as an,bu as ao,Ka as ap,De as aq,$o as ar,ru as as,hu as at,de as au,au as av,Mt as aw,mu as ax,Lu as ay,Jo as b,uu as c,Kr as d,du as e,$a as f,Ys as g,se as h,Oa as i,Ce as j,re as k,Rt as l,Zo as m,Ir as n,Xo as o,Eo as p,Qa as q,iu as r,Za as s,Ja as t,ja as u,La as v,El as w,hi as x,Ve as y,kr as z}; diff --git a/assets/chunks/mp_addplugin.pe280tQx.js b/assets/chunks/mp_addplugin.pe280tQx.js new file mode 100644 index 00000000..81dcc72c --- /dev/null +++ b/assets/chunks/mp_addplugin.pe280tQx.js @@ -0,0 +1 @@ +const t="/minigame-unity-webgl-transform/assets/mp_addplugin.BtUIXUot.png";export{t as _}; diff --git a/assets/chunks/profile3.CffCZqR8.js b/assets/chunks/profile3.CffCZqR8.js new file mode 100644 index 00000000..37f1cfa0 --- /dev/null +++ b/assets/chunks/profile3.CffCZqR8.js @@ -0,0 +1 @@ +const s="/minigame-unity-webgl-transform/assets/profile1.DdUMXlC5.png",n="/minigame-unity-webgl-transform/assets/profile2.DnwO5wIf.png",t="/minigame-unity-webgl-transform/assets/profile3.Dk7R5Gjr.png";export{s as _,n as a,t as b}; diff --git a/assets/chunks/showcase25.C-ERrYO-.js b/assets/chunks/showcase25.C-ERrYO-.js new file mode 100644 index 00000000..351a2242 --- /dev/null +++ b/assets/chunks/showcase25.C-ERrYO-.js @@ -0,0 +1 @@ +const s="/minigame-unity-webgl-transform/assets/showcase25.BuEmUmjn.png";export{s as _}; diff --git a/assets/chunks/theme.DuJp6K1e.js b/assets/chunks/theme.DuJp6K1e.js new file mode 100644 index 00000000..db8b7176 --- /dev/null +++ b/assets/chunks/theme.DuJp6K1e.js @@ -0,0 +1,7 @@ +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = ["assets/chunks/VPLocalSearchBox.BANsnCko.js","assets/chunks/framework.Br2U662V.js"] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} +import{d as _,o as a,c,r as l,n as N,a as D,t as w,b as $,w as d,e as f,T as ve,_ as k,u as Ue,i as Ge,f as je,g as pe,h as I,j as J,k as g,l as z,m as v,p as i,q as B,s as H,v as j,x as ie,y as q,z as x,A as he,B as Pe,C as ze,D as qe,E as K,F as M,G as E,H as Le,I as ee,J as m,K as R,L as Ve,M as te,N as Q,O as oe,P as Ke,Q as Se,R as We,S as le,U as Re,V as Te,W as Je,X as Ye,Y as Qe,Z as we,$ as Ie,a0 as Xe,a1 as Ze,a2 as xe,a3 as et}from"./framework.Br2U662V.js";const tt=_({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(o){return(e,t)=>(a(),c("span",{class:N(["VPBadge",e.type])},[l(e.$slots,"default",{},()=>[D(w(e.text),1)])],2))}}),ot={key:0,class:"VPBackdrop"},st=_({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(o){return(e,t)=>(a(),$(ve,{name:"fade"},{default:d(()=>[e.show?(a(),c("div",ot)):f("",!0)]),_:1}))}}),nt=k(st,[["__scopeId","data-v-54a304ca"]]),L=Ue;function at(o,e){let t,s=!1;return()=>{t&&clearTimeout(t),s?t=setTimeout(o,e):(o(),(s=!0)&&setTimeout(()=>s=!1,e))}}function ce(o){return/^\//.test(o)?o:`/${o}`}function fe(o){const{pathname:e,search:t,hash:s,protocol:n}=new URL(o,"http://a.com");if(Ge(o)||o.startsWith("#")||!n.startsWith("http")||!je(e))return o;const{site:r}=L(),u=e.endsWith("/")||e.endsWith(".html")?o:o.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,r.value.cleanUrls?"":".html")}${t}${s}`);return pe(u)}const _e=I(J?location.hash:"");J&&window.addEventListener("hashchange",()=>{_e.value=location.hash});function Y({removeCurrent:o=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:s,page:n,theme:r}=L(),u=g(()=>{var p,b;return{label:(p=t.value.locales[s.value])==null?void 0:p.label,link:((b=t.value.locales[s.value])==null?void 0:b.link)||(s.value==="root"?"/":`/${s.value}/`)}});return{localeLinks:g(()=>Object.entries(t.value.locales).flatMap(([p,b])=>o&&u.value.label===b.label?[]:{text:b.label,link:rt(b.link||(p==="root"?"/":`/${p}/`),r.value.i18nRouting!==!1&&e,n.value.relativePath.slice(u.value.link.length-1),!t.value.cleanUrls)+_e.value})),currentLang:u}}function rt(o,e,t,s){return e?o.replace(/\/$/,"")+ce(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,s?".html":"")):o}const it=o=>(B("data-v-b9c0c15a"),o=o(),H(),o),lt={class:"NotFound"},ct={class:"code"},ut={class:"title"},dt=it(()=>v("div",{class:"divider"},null,-1)),vt={class:"quote"},pt={class:"action"},ht=["href","aria-label"],ft=_({__name:"NotFound",setup(o){const{site:e,theme:t}=L(),{localeLinks:s}=Y({removeCurrent:!1}),n=I("/");return z(()=>{var u;const r=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");s.value.length&&(n.value=((u=s.value.find(({link:h})=>h.startsWith(r)))==null?void 0:u.link)||s.value[0].link)}),(r,u)=>{var h,p,b,P,y;return a(),c("div",lt,[v("p",ct,w(((h=i(t).notFound)==null?void 0:h.code)??"404"),1),v("h1",ut,w(((p=i(t).notFound)==null?void 0:p.title)??"PAGE NOT FOUND"),1),dt,v("blockquote",vt,w(((b=i(t).notFound)==null?void 0:b.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),v("div",pt,[v("a",{class:"link",href:i(pe)(n.value),"aria-label":((P=i(t).notFound)==null?void 0:P.linkLabel)??"go to home"},w(((y=i(t).notFound)==null?void 0:y.linkText)??"Take me home"),9,ht)])])}}}),_t=k(ft,[["__scopeId","data-v-b9c0c15a"]]);function Ne(o,e){if(Array.isArray(o))return X(o);if(o==null)return[];e=ce(e);const t=Object.keys(o).sort((n,r)=>r.split("/").length-n.split("/").length).find(n=>e.startsWith(ce(n))),s=t?o[t]:[];return Array.isArray(s)?X(s):X(s.items,s.base)}function mt(o){const e=[];let t=0;for(const s in o){const n=o[s];if(n.items){t=e.push(n);continue}e[t]||e.push({items:[]}),e[t].items.push(n)}return e}function kt(o){const e=[];function t(s){for(const n of s)n.text&&n.link&&e.push({text:n.text,link:n.link,docFooterText:n.docFooterText}),n.items&&t(n.items)}return t(o),e}function ue(o,e){return Array.isArray(e)?e.some(t=>ue(o,t)):j(o,e.link)?!0:e.items?ue(o,e.items):!1}function X(o,e){return[...o].map(t=>{const s={...t},n=s.base||e;return n&&s.link&&(s.link=n+s.link),s.items&&(s.items=X(s.items,n)),s})}function O(){const{frontmatter:o,page:e,theme:t}=L(),s=ie("(min-width: 960px)"),n=I(!1),r=g(()=>{const C=t.value.sidebar,S=e.value.relativePath;return C?Ne(C,S):[]}),u=I(r.value);q(r,(C,S)=>{JSON.stringify(C)!==JSON.stringify(S)&&(u.value=r.value)});const h=g(()=>o.value.sidebar!==!1&&u.value.length>0&&o.value.layout!=="home"),p=g(()=>b?o.value.aside==null?t.value.aside==="left":o.value.aside==="left":!1),b=g(()=>o.value.layout==="home"?!1:o.value.aside!=null?!!o.value.aside:t.value.aside!==!1),P=g(()=>h.value&&s.value),y=g(()=>h.value?mt(u.value):[]);function V(){n.value=!0}function T(){n.value=!1}function A(){n.value?T():V()}return{isOpen:n,sidebar:u,sidebarGroups:y,hasSidebar:h,hasAside:b,leftAside:p,isSidebarEnabled:P,open:V,close:T,toggle:A}}function bt(o,e){let t;x(()=>{t=o.value?document.activeElement:void 0}),z(()=>{window.addEventListener("keyup",s)}),he(()=>{window.removeEventListener("keyup",s)});function s(n){n.key==="Escape"&&o.value&&(e(),t==null||t.focus())}}function $t(o){const{page:e}=L(),t=I(!1),s=g(()=>o.value.collapsed!=null),n=g(()=>!!o.value.link),r=I(!1),u=()=>{r.value=j(e.value.relativePath,o.value.link)};q([e,o,_e],u),z(u);const h=g(()=>r.value?!0:o.value.items?ue(e.value.relativePath,o.value.items):!1),p=g(()=>!!(o.value.items&&o.value.items.length));x(()=>{t.value=!!(s.value&&o.value.collapsed)}),Pe(()=>{(r.value||h.value)&&(t.value=!1)});function b(){s.value&&(t.value=!t.value)}return{collapsed:t,collapsible:s,isLink:n,isActiveLink:r,hasActiveLink:h,hasChildren:p,toggle:b}}function gt(){const{hasSidebar:o}=O(),e=ie("(min-width: 960px)"),t=ie("(min-width: 1280px)");return{isAsideEnabled:g(()=>!t.value&&!e.value?!1:o.value?t.value:e.value)}}const de=[];function Me(o){return typeof o.outline=="object"&&!Array.isArray(o.outline)&&o.outline.label||o.outlineTitle||"On this page"}function me(o){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const s=Number(t.tagName[1]);return{element:t,title:yt(t),link:"#"+t.id,level:s}});return Pt(e,o)}function yt(o){let e="";for(const t of o.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor")||t.classList.contains("ignore-header"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function Pt(o,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[s,n]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;o=o.filter(u=>u.level>=s&&u.level<=n),de.length=0;for(const{element:u,link:h}of o)de.push({element:u,link:h});const r=[];e:for(let u=0;u=0;p--){const b=o[p];if(b.level{requestAnimationFrame(r),window.addEventListener("scroll",s)}),ze(()=>{u(location.hash)}),he(()=>{window.removeEventListener("scroll",s)});function r(){if(!t.value)return;const h=window.scrollY,p=window.innerHeight,b=document.body.offsetHeight,P=Math.abs(h+p-b)<1,y=de.map(({element:T,link:A})=>({link:A,top:Vt(T)})).filter(({top:T})=>!Number.isNaN(T)).sort((T,A)=>T.top-A.top);if(!y.length){u(null);return}if(h<1){u(null);return}if(P){u(y[y.length-1].link);return}let V=null;for(const{link:T,top:A}of y){if(A>h+qe()+4)break;V=T}u(V)}function u(h){n&&n.classList.remove("active"),h==null?n=null:n=o.value.querySelector(`a[href="${decodeURIComponent(h)}"]`);const p=n;p?(p.classList.add("active"),e.value.style.top=p.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function Vt(o){let e=0;for(;o!==document.body;){if(o===null)return NaN;e+=o.offsetTop,o=o.offsetParent}return e}const St=["href","title"],Tt=_({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(o){function e({target:t}){const s=t.href.split("#")[1],n=document.getElementById(decodeURIComponent(s));n==null||n.focus({preventScroll:!0})}return(t,s)=>{const n=K("VPDocOutlineItem",!0);return a(),c("ul",{class:N(["VPDocOutlineItem",t.root?"root":"nested"])},[(a(!0),c(M,null,E(t.headers,({children:r,link:u,title:h})=>(a(),c("li",null,[v("a",{class:"outline-link",href:u,onClick:e,title:h},w(h),9,St),r!=null&&r.length?(a(),$(n,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}}),Ae=k(Tt,[["__scopeId","data-v-53c99d69"]]),wt=o=>(B("data-v-6b52fe58"),o=o(),H(),o),It={class:"content"},Nt={class:"outline-title",role:"heading","aria-level":"2"},Mt={"aria-labelledby":"doc-outline-aria-label"},At=wt(()=>v("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),Ct=_({__name:"VPDocAsideOutline",setup(o){const{frontmatter:e,theme:t}=L(),s=Le([]);ee(()=>{s.value=me(e.value.outline??t.value.outline)});const n=I(),r=I();return Lt(n,r),(u,h)=>(a(),c("div",{class:N(["VPDocAsideOutline",{"has-outline":s.value.length>0}]),ref_key:"container",ref:n,role:"navigation"},[v("div",It,[v("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),v("div",Nt,w(i(Me)(i(t))),1),v("nav",Mt,[At,m(Ae,{headers:s.value,root:!0},null,8,["headers"])])])],2))}}),Bt=k(Ct,[["__scopeId","data-v-6b52fe58"]]),Ht={class:"VPDocAsideCarbonAds"},Et=_({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(o){const e=()=>null;return(t,s)=>(a(),c("div",Ht,[m(i(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Ft=o=>(B("data-v-cb998dce"),o=o(),H(),o),Dt={class:"VPDocAside"},Ot=Ft(()=>v("div",{class:"spacer"},null,-1)),Ut=_({__name:"VPDocAside",setup(o){const{theme:e}=L();return(t,s)=>(a(),c("div",Dt,[l(t.$slots,"aside-top",{},void 0,!0),l(t.$slots,"aside-outline-before",{},void 0,!0),m(Bt),l(t.$slots,"aside-outline-after",{},void 0,!0),Ot,l(t.$slots,"aside-ads-before",{},void 0,!0),i(e).carbonAds?(a(),$(Et,{key:0,"carbon-ads":i(e).carbonAds},null,8,["carbon-ads"])):f("",!0),l(t.$slots,"aside-ads-after",{},void 0,!0),l(t.$slots,"aside-bottom",{},void 0,!0)]))}}),Gt=k(Ut,[["__scopeId","data-v-cb998dce"]]);function jt(){const{theme:o,page:e}=L();return g(()=>{const{text:t="Edit this page",pattern:s=""}=o.value.editLink||{};let n;return typeof s=="function"?n=s(e.value):n=s.replace(/:path/g,e.value.filePath),{url:n,text:t}})}function zt(){const{page:o,theme:e,frontmatter:t}=L();return g(()=>{var b,P,y,V,T,A,C,S;const s=Ne(e.value.sidebar,o.value.relativePath),n=kt(s),r=qt(n,U=>U.link.replace(/[?#].*$/,"")),u=r.findIndex(U=>j(o.value.relativePath,U.link)),h=((b=e.value.docFooter)==null?void 0:b.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((P=e.value.docFooter)==null?void 0:P.next)===!1&&!t.value.next||t.value.next===!1;return{prev:h?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((y=r[u-1])==null?void 0:y.docFooterText)??((V=r[u-1])==null?void 0:V.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((T=r[u-1])==null?void 0:T.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((A=r[u+1])==null?void 0:A.docFooterText)??((C=r[u+1])==null?void 0:C.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((S=r[u+1])==null?void 0:S.link)}}})}function qt(o,e){const t=new Set;return o.filter(s=>{const n=e(s);return t.has(n)?!1:t.add(n)})}const F=_({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(o){const e=o,t=g(()=>e.tag??(e.href?"a":"span")),s=g(()=>e.href&&Ve.test(e.href));return(n,r)=>(a(),$(R(t.value),{class:N(["VPLink",{link:n.href,"vp-external-link-icon":s.value,"no-icon":n.noIcon}]),href:n.href?i(fe)(n.href):void 0,target:n.target??(s.value?"_blank":void 0),rel:n.rel??(s.value?"noreferrer":void 0)},{default:d(()=>[l(n.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),Kt={class:"VPLastUpdated"},Wt=["datetime"],Rt=_({__name:"VPDocFooterLastUpdated",setup(o){const{theme:e,page:t,frontmatter:s,lang:n}=L(),r=g(()=>new Date(s.value.lastUpdated??t.value.lastUpdated)),u=g(()=>r.value.toISOString()),h=I("");return z(()=>{x(()=>{var p,b,P;h.value=new Intl.DateTimeFormat((b=(p=e.value.lastUpdated)==null?void 0:p.formatOptions)!=null&&b.forceLocale?n.value:void 0,((P=e.value.lastUpdated)==null?void 0:P.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(r.value)})}),(p,b)=>{var P;return a(),c("p",Kt,[D(w(((P=i(e).lastUpdated)==null?void 0:P.text)||i(e).lastUpdatedText||"Last updated")+": ",1),v("time",{datetime:u.value},w(h.value),9,Wt)])}}}),Jt=k(Rt,[["__scopeId","data-v-19a7ae4e"]]),Yt=o=>(B("data-v-b77f9094"),o=o(),H(),o),Qt={key:0,class:"VPDocFooter"},Xt={key:0,class:"edit-info"},Zt={key:0,class:"edit-link"},xt=Yt(()=>v("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),eo={key:1,class:"last-updated"},to={key:1,class:"prev-next"},oo={class:"pager"},so=["innerHTML"],no=["innerHTML"],ao={class:"pager"},ro=["innerHTML"],io=["innerHTML"],lo=_({__name:"VPDocFooter",setup(o){const{theme:e,page:t,frontmatter:s}=L(),n=jt(),r=zt(),u=g(()=>e.value.editLink&&s.value.editLink!==!1),h=g(()=>t.value.lastUpdated&&s.value.lastUpdated!==!1),p=g(()=>u.value||h.value||r.value.prev||r.value.next);return(b,P)=>{var y,V,T,A;return p.value?(a(),c("footer",Qt,[l(b.$slots,"doc-footer-before",{},void 0,!0),u.value||h.value?(a(),c("div",Xt,[u.value?(a(),c("div",Zt,[m(F,{class:"edit-link-button",href:i(n).url,"no-icon":!0},{default:d(()=>[xt,D(" "+w(i(n).text),1)]),_:1},8,["href"])])):f("",!0),h.value?(a(),c("div",eo,[m(Jt)])):f("",!0)])):f("",!0),(y=i(r).prev)!=null&&y.link||(V=i(r).next)!=null&&V.link?(a(),c("nav",to,[v("div",oo,[(T=i(r).prev)!=null&&T.link?(a(),$(F,{key:0,class:"pager-link prev",href:i(r).prev.link},{default:d(()=>{var C;return[v("span",{class:"desc",innerHTML:((C=i(e).docFooter)==null?void 0:C.prev)||"Previous page"},null,8,so),v("span",{class:"title",innerHTML:i(r).prev.text},null,8,no)]}),_:1},8,["href"])):f("",!0)]),v("div",ao,[(A=i(r).next)!=null&&A.link?(a(),$(F,{key:0,class:"pager-link next",href:i(r).next.link},{default:d(()=>{var C;return[v("span",{class:"desc",innerHTML:((C=i(e).docFooter)==null?void 0:C.next)||"Next page"},null,8,ro),v("span",{class:"title",innerHTML:i(r).next.text},null,8,io)]}),_:1},8,["href"])):f("",!0)])])):f("",!0)])):f("",!0)}}}),co=k(lo,[["__scopeId","data-v-b77f9094"]]),uo=o=>(B("data-v-e6f2a212"),o=o(),H(),o),vo={class:"container"},po=uo(()=>v("div",{class:"aside-curtain"},null,-1)),ho={class:"aside-container"},fo={class:"aside-content"},_o={class:"content"},mo={class:"content-container"},ko={class:"main"},bo=_({__name:"VPDoc",setup(o){const{theme:e}=L(),t=te(),{hasSidebar:s,hasAside:n,leftAside:r}=O(),u=g(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(h,p)=>{const b=K("Content");return a(),c("div",{class:N(["VPDoc",{"has-sidebar":i(s),"has-aside":i(n)}])},[l(h.$slots,"doc-top",{},void 0,!0),v("div",vo,[i(n)?(a(),c("div",{key:0,class:N(["aside",{"left-aside":i(r)}])},[po,v("div",ho,[v("div",fo,[m(Gt,null,{"aside-top":d(()=>[l(h.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":d(()=>[l(h.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":d(()=>[l(h.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":d(()=>[l(h.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":d(()=>[l(h.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":d(()=>[l(h.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),v("div",_o,[v("div",mo,[l(h.$slots,"doc-before",{},void 0,!0),v("main",ko,[m(b,{class:N(["vp-doc",[u.value,i(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),m(co,null,{"doc-footer-before":d(()=>[l(h.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),l(h.$slots,"doc-after",{},void 0,!0)])])]),l(h.$slots,"doc-bottom",{},void 0,!0)],2)}}}),$o=k(bo,[["__scopeId","data-v-e6f2a212"]]),go=_({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(o){const e=o,t=g(()=>e.href&&Ve.test(e.href)),s=g(()=>e.tag||e.href?"a":"button");return(n,r)=>(a(),$(R(s.value),{class:N(["VPButton",[n.size,n.theme]]),href:n.href?i(fe)(n.href):void 0,target:e.target??(t.value?"_blank":void 0),rel:e.rel??(t.value?"noreferrer":void 0)},{default:d(()=>[D(w(n.text),1)]),_:1},8,["class","href","target","rel"]))}}),yo=k(go,[["__scopeId","data-v-c9cf0e3c"]]),Po=["src","alt"],Lo=_({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(o){return(e,t)=>{const s=K("VPImage",!0);return e.image?(a(),c(M,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),c("img",Q({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:i(pe)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Po)):(a(),c(M,{key:1},[m(s,Q({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),m(s,Q({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}}),Z=k(Lo,[["__scopeId","data-v-ab19afbb"]]),Vo=o=>(B("data-v-b10c5094"),o=o(),H(),o),So={class:"container"},To={class:"main"},wo={key:0,class:"name"},Io=["innerHTML"],No=["innerHTML"],Mo=["innerHTML"],Ao={key:0,class:"actions"},Co={key:0,class:"image"},Bo={class:"image-container"},Ho=Vo(()=>v("div",{class:"image-bg"},null,-1)),Eo=_({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(o){const e=oe("hero-image-slot-exists");return(t,s)=>(a(),c("div",{class:N(["VPHero",{"has-image":t.image||i(e)}])},[v("div",So,[v("div",To,[l(t.$slots,"home-hero-info-before",{},void 0,!0),l(t.$slots,"home-hero-info",{},()=>[t.name?(a(),c("h1",wo,[v("span",{innerHTML:t.name,class:"clip"},null,8,Io)])):f("",!0),t.text?(a(),c("p",{key:1,innerHTML:t.text,class:"text"},null,8,No)):f("",!0),t.tagline?(a(),c("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Mo)):f("",!0)],!0),l(t.$slots,"home-hero-info-after",{},void 0,!0),t.actions?(a(),c("div",Ao,[(a(!0),c(M,null,E(t.actions,n=>(a(),c("div",{key:n.link,class:"action"},[m(yo,{tag:"a",size:"medium",theme:n.theme,text:n.text,href:n.link,target:n.target,rel:n.rel},null,8,["theme","text","href","target","rel"])]))),128))])):f("",!0),l(t.$slots,"home-hero-actions-after",{},void 0,!0)]),t.image||i(e)?(a(),c("div",Co,[v("div",Bo,[Ho,l(t.$slots,"home-hero-image",{},()=>[t.image?(a(),$(Z,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}}),Fo=k(Eo,[["__scopeId","data-v-b10c5094"]]),Do=_({__name:"VPHomeHero",setup(o){const{frontmatter:e}=L();return(t,s)=>i(e).hero?(a(),$(Fo,{key:0,class:"VPHomeHero",name:i(e).hero.name,text:i(e).hero.text,tagline:i(e).hero.tagline,image:i(e).hero.image,actions:i(e).hero.actions},{"home-hero-info-before":d(()=>[l(t.$slots,"home-hero-info-before")]),"home-hero-info":d(()=>[l(t.$slots,"home-hero-info")]),"home-hero-info-after":d(()=>[l(t.$slots,"home-hero-info-after")]),"home-hero-actions-after":d(()=>[l(t.$slots,"home-hero-actions-after")]),"home-hero-image":d(()=>[l(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Oo=o=>(B("data-v-bd37d1a2"),o=o(),H(),o),Uo={class:"box"},Go={key:0,class:"icon"},jo=["innerHTML"],zo=["innerHTML"],qo=["innerHTML"],Ko={key:4,class:"link-text"},Wo={class:"link-text-value"},Ro=Oo(()=>v("span",{class:"vpi-arrow-right link-text-icon"},null,-1)),Jo=_({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(o){return(e,t)=>(a(),$(F,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:d(()=>[v("article",Uo,[typeof e.icon=="object"&&e.icon.wrap?(a(),c("div",Go,[m(Z,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),$(Z,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),c("div",{key:2,class:"icon",innerHTML:e.icon},null,8,jo)):f("",!0),v("h2",{class:"title",innerHTML:e.title},null,8,zo),e.details?(a(),c("p",{key:3,class:"details",innerHTML:e.details},null,8,qo)):f("",!0),e.linkText?(a(),c("div",Ko,[v("p",Wo,[D(w(e.linkText)+" ",1),Ro])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),Yo=k(Jo,[["__scopeId","data-v-bd37d1a2"]]),Qo={key:0,class:"VPFeatures"},Xo={class:"container"},Zo={class:"items"},xo=_({__name:"VPFeatures",props:{features:{}},setup(o){const e=o,t=g(()=>{const s=e.features.length;if(s){if(s===2)return"grid-2";if(s===3)return"grid-3";if(s%3===0)return"grid-6";if(s>3)return"grid-6"}else return});return(s,n)=>s.features?(a(),c("div",Qo,[v("div",Xo,[v("div",Zo,[(a(!0),c(M,null,E(s.features,r=>(a(),c("div",{key:r.title,class:N(["item",[t.value]])},[m(Yo,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}}),es=k(xo,[["__scopeId","data-v-d08986ee"]]),ts=_({__name:"VPHomeFeatures",setup(o){const{frontmatter:e}=L();return(t,s)=>i(e).features?(a(),$(es,{key:0,class:"VPHomeFeatures",features:i(e).features},null,8,["features"])):f("",!0)}}),os=_({__name:"VPHomeContent",setup(o){const{width:e}=Ke({includeScrollbar:!1});return(t,s)=>(a(),c("div",{class:"vp-doc container",style:Se(i(e)?{"--vp-offset":`calc(50% - ${i(e)/2}px)`}:{})},[l(t.$slots,"default",{},void 0,!0)],4))}}),ss=k(os,[["__scopeId","data-v-d59ac166"]]),ns={class:"VPHome"},as=_({__name:"VPHome",setup(o){const{frontmatter:e}=L();return(t,s)=>{const n=K("Content");return a(),c("div",ns,[l(t.$slots,"home-hero-before",{},void 0,!0),m(Do,null,{"home-hero-info-before":d(()=>[l(t.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":d(()=>[l(t.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":d(()=>[l(t.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":d(()=>[l(t.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":d(()=>[l(t.$slots,"home-hero-image",{},void 0,!0)]),_:3}),l(t.$slots,"home-hero-after",{},void 0,!0),l(t.$slots,"home-features-before",{},void 0,!0),m(ts),l(t.$slots,"home-features-after",{},void 0,!0),i(e).markdownStyles!==!1?(a(),$(ss,{key:0},{default:d(()=>[m(n)]),_:1})):(a(),$(n,{key:1}))])}}}),rs=k(as,[["__scopeId","data-v-07b1ad08"]]),is={},ls={class:"VPPage"};function cs(o,e){const t=K("Content");return a(),c("div",ls,[l(o.$slots,"page-top"),m(t),l(o.$slots,"page-bottom")])}const us=k(is,[["render",cs]]),ds=_({__name:"VPContent",setup(o){const{page:e,frontmatter:t}=L(),{hasSidebar:s}=O();return(n,r)=>(a(),c("div",{class:N(["VPContent",{"has-sidebar":i(s),"is-home":i(t).layout==="home"}]),id:"VPContent"},[i(e).isNotFound?l(n.$slots,"not-found",{key:0},()=>[m(_t)],!0):i(t).layout==="page"?(a(),$(us,{key:1},{"page-top":d(()=>[l(n.$slots,"page-top",{},void 0,!0)]),"page-bottom":d(()=>[l(n.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(t).layout==="home"?(a(),$(rs,{key:2},{"home-hero-before":d(()=>[l(n.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":d(()=>[l(n.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":d(()=>[l(n.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":d(()=>[l(n.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":d(()=>[l(n.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":d(()=>[l(n.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":d(()=>[l(n.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":d(()=>[l(n.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":d(()=>[l(n.$slots,"home-features-after",{},void 0,!0)]),_:3})):i(t).layout&&i(t).layout!=="doc"?(a(),$(R(i(t).layout),{key:3})):(a(),$($o,{key:4},{"doc-top":d(()=>[l(n.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":d(()=>[l(n.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":d(()=>[l(n.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":d(()=>[l(n.$slots,"doc-before",{},void 0,!0)]),"doc-after":d(()=>[l(n.$slots,"doc-after",{},void 0,!0)]),"aside-top":d(()=>[l(n.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":d(()=>[l(n.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":d(()=>[l(n.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":d(()=>[l(n.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":d(()=>[l(n.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":d(()=>[l(n.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),vs=k(ds,[["__scopeId","data-v-9a6c75ad"]]),ps={class:"container"},hs=["innerHTML"],fs=["innerHTML"],_s=_({__name:"VPFooter",setup(o){const{theme:e,frontmatter:t}=L(),{hasSidebar:s}=O();return(n,r)=>i(e).footer&&i(t).footer!==!1?(a(),c("footer",{key:0,class:N(["VPFooter",{"has-sidebar":i(s)}])},[v("div",ps,[i(e).footer.message?(a(),c("p",{key:0,class:"message",innerHTML:i(e).footer.message},null,8,hs)):f("",!0),i(e).footer.copyright?(a(),c("p",{key:1,class:"copyright",innerHTML:i(e).footer.copyright},null,8,fs)):f("",!0)])],2)):f("",!0)}}),ms=k(_s,[["__scopeId","data-v-566314d4"]]);function ks(){const{theme:o,frontmatter:e}=L(),t=Le([]),s=g(()=>t.value.length>0);return ee(()=>{t.value=me(e.value.outline??o.value.outline)}),{headers:t,hasLocalNav:s}}const bs=o=>(B("data-v-0b5c97a1"),o=o(),H(),o),$s=bs(()=>v("span",{class:"vpi-chevron-right icon"},null,-1)),gs={class:"header"},ys={class:"outline"},Ps=_({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(o){const e=o,{theme:t}=L(),s=I(!1),n=I(0),r=I(),u=I();We(r,()=>{s.value=!1}),le("Escape",()=>{s.value=!1}),ee(()=>{s.value=!1});function h(){s.value=!s.value,n.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function p(P){P.target.classList.contains("outline-link")&&(u.value&&(u.value.style.transition="none"),Re(()=>{s.value=!1}))}function b(){s.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(P,y)=>(a(),c("div",{class:"VPLocalNavOutlineDropdown",style:Se({"--vp-vh":n.value+"px"}),ref_key:"main",ref:r},[P.headers.length>0?(a(),c("button",{key:0,onClick:h,class:N({open:s.value})},[D(w(i(Me)(i(t)))+" ",1),$s],2)):(a(),c("button",{key:1,onClick:b},w(i(t).returnToTopLabel||"Return to top"),1)),m(ve,{name:"flyout"},{default:d(()=>[s.value?(a(),c("div",{key:0,ref_key:"items",ref:u,class:"items",onClick:p},[v("div",gs,[v("a",{class:"top-link",href:"#",onClick:b},w(i(t).returnToTopLabel||"Return to top"),1)]),v("div",ys,[m(Ae,{headers:P.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}}),Ls=k(Ps,[["__scopeId","data-v-0b5c97a1"]]),Vs=o=>(B("data-v-2488c25a"),o=o(),H(),o),Ss={class:"container"},Ts=["aria-expanded"],ws=Vs(()=>v("span",{class:"vpi-align-left menu-icon"},null,-1)),Is={class:"menu-text"},Ns=_({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(o){const{theme:e,frontmatter:t}=L(),{hasSidebar:s}=O(),{headers:n}=ks(),{y:r}=Te(),u=I(0);z(()=>{u.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),ee(()=>{n.value=me(t.value.outline??e.value.outline)});const h=g(()=>n.value.length===0),p=g(()=>h.value&&!s.value),b=g(()=>({VPLocalNav:!0,"has-sidebar":s.value,empty:h.value,fixed:p.value}));return(P,y)=>i(t).layout!=="home"&&(!p.value||i(r)>=u.value)?(a(),c("div",{key:0,class:N(b.value)},[v("div",Ss,[i(s)?(a(),c("button",{key:0,class:"menu","aria-expanded":P.open,"aria-controls":"VPSidebarNav",onClick:y[0]||(y[0]=V=>P.$emit("open-menu"))},[ws,v("span",Is,w(i(e).sidebarMenuLabel||"Menu"),1)],8,Ts)):f("",!0),m(Ls,{headers:i(n),navHeight:u.value},null,8,["headers","navHeight"])])],2)):f("",!0)}}),Ms=k(Ns,[["__scopeId","data-v-2488c25a"]]);function As(){const o=I(!1);function e(){o.value=!0,window.addEventListener("resize",n)}function t(){o.value=!1,window.removeEventListener("resize",n)}function s(){o.value?t():e()}function n(){window.outerWidth>=768&&t()}const r=te();return q(()=>r.path,t),{isScreenOpen:o,openScreen:e,closeScreen:t,toggleScreen:s}}const Cs={},Bs={class:"VPSwitch",type:"button",role:"switch"},Hs={class:"check"},Es={key:0,class:"icon"};function Fs(o,e){return a(),c("button",Bs,[v("span",Hs,[o.$slots.default?(a(),c("span",Es,[l(o.$slots,"default",{},void 0,!0)])):f("",!0)])])}const Ds=k(Cs,[["render",Fs],["__scopeId","data-v-b4ccac88"]]),Ce=o=>(B("data-v-7df97737"),o=o(),H(),o),Os=Ce(()=>v("span",{class:"vpi-sun sun"},null,-1)),Us=Ce(()=>v("span",{class:"vpi-moon moon"},null,-1)),Gs=_({__name:"VPSwitchAppearance",setup(o){const{isDark:e,theme:t}=L(),s=oe("toggle-appearance",()=>{e.value=!e.value}),n=g(()=>e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme");return(r,u)=>(a(),$(Ds,{title:n.value,class:"VPSwitchAppearance","aria-checked":i(e),onClick:i(s)},{default:d(()=>[Os,Us]),_:1},8,["title","aria-checked","onClick"]))}}),ke=k(Gs,[["__scopeId","data-v-7df97737"]]),js={key:0,class:"VPNavBarAppearance"},zs=_({__name:"VPNavBarAppearance",setup(o){const{site:e}=L();return(t,s)=>i(e).appearance&&i(e).appearance!=="force-dark"?(a(),c("div",js,[m(ke)])):f("",!0)}}),qs=k(zs,[["__scopeId","data-v-283b26e9"]]),be=I();let Be=!1,re=0;function Ks(o){const e=I(!1);if(J){!Be&&Ws(),re++;const t=q(be,s=>{var n,r,u;s===o.el.value||(n=o.el.value)!=null&&n.contains(s)?(e.value=!0,(r=o.onFocus)==null||r.call(o)):(e.value=!1,(u=o.onBlur)==null||u.call(o))});he(()=>{t(),re--,re||Rs()})}return Je(e)}function Ws(){document.addEventListener("focusin",He),Be=!0,be.value=document.activeElement}function Rs(){document.removeEventListener("focusin",He)}function He(){be.value=document.activeElement}const Js={class:"VPMenuLink"},Ys=_({__name:"VPMenuLink",props:{item:{}},setup(o){const{page:e}=L();return(t,s)=>(a(),c("div",Js,[m(F,{class:N({active:i(j)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:d(()=>[D(w(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}}),se=k(Ys,[["__scopeId","data-v-f51f088d"]]),Qs={class:"VPMenuGroup"},Xs={key:0,class:"title"},Zs=_({__name:"VPMenuGroup",props:{text:{},items:{}},setup(o){return(e,t)=>(a(),c("div",Qs,[e.text?(a(),c("p",Xs,w(e.text),1)):f("",!0),(a(!0),c(M,null,E(e.items,s=>(a(),c(M,null,["link"in s?(a(),$(se,{key:0,item:s},null,8,["item"])):f("",!0)],64))),256))]))}}),xs=k(Zs,[["__scopeId","data-v-a6b0397c"]]),en={class:"VPMenu"},tn={key:0,class:"items"},on=_({__name:"VPMenu",props:{items:{}},setup(o){return(e,t)=>(a(),c("div",en,[e.items?(a(),c("div",tn,[(a(!0),c(M,null,E(e.items,s=>(a(),c(M,{key:s.text},["link"in s?(a(),$(se,{key:0,item:s},null,8,["item"])):(a(),$(xs,{key:1,text:s.text,items:s.items},null,8,["text","items"]))],64))),128))])):f("",!0),l(e.$slots,"default",{},void 0,!0)]))}}),sn=k(on,[["__scopeId","data-v-e42ed9b3"]]),nn=o=>(B("data-v-af5898d3"),o=o(),H(),o),an=["aria-expanded","aria-label"],rn={key:0,class:"text"},ln=["innerHTML"],cn=nn(()=>v("span",{class:"vpi-chevron-down text-icon"},null,-1)),un={key:1,class:"vpi-more-horizontal icon"},dn={class:"menu"},vn=_({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(o){const e=I(!1),t=I();Ks({el:t,onBlur:s});function s(){e.value=!1}return(n,r)=>(a(),c("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=u=>e.value=!0),onMouseleave:r[2]||(r[2]=u=>e.value=!1)},[v("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":n.label,onClick:r[0]||(r[0]=u=>e.value=!e.value)},[n.button||n.icon?(a(),c("span",rn,[n.icon?(a(),c("span",{key:0,class:N([n.icon,"option-icon"])},null,2)):f("",!0),n.button?(a(),c("span",{key:1,innerHTML:n.button},null,8,ln)):f("",!0),cn])):(a(),c("span",un))],8,an),v("div",dn,[m(sn,{items:n.items},{default:d(()=>[l(n.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),$e=k(vn,[["__scopeId","data-v-af5898d3"]]),pn=["href","aria-label","innerHTML"],hn=_({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(o){const e=o,t=g(()=>typeof e.icon=="object"?e.icon.svg:``);return(s,n)=>(a(),c("a",{class:"VPSocialLink no-icon",href:s.link,"aria-label":s.ariaLabel??(typeof s.icon=="string"?s.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,pn))}}),fn=k(hn,[["__scopeId","data-v-358b6670"]]),_n={class:"VPSocialLinks"},mn=_({__name:"VPSocialLinks",props:{links:{}},setup(o){return(e,t)=>(a(),c("div",_n,[(a(!0),c(M,null,E(e.links,({link:s,icon:n,ariaLabel:r})=>(a(),$(fn,{key:s,icon:n,link:s,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}}),ge=k(mn,[["__scopeId","data-v-e71e869c"]]),kn={key:0,class:"group translations"},bn={class:"trans-title"},$n={key:1,class:"group"},gn={class:"item appearance"},yn={class:"label"},Pn={class:"appearance-action"},Ln={key:2,class:"group"},Vn={class:"item social-links"},Sn=_({__name:"VPNavBarExtra",setup(o){const{site:e,theme:t}=L(),{localeLinks:s,currentLang:n}=Y({correspondingLink:!0}),r=g(()=>s.value.length&&n.value.label||e.value.appearance||t.value.socialLinks);return(u,h)=>r.value?(a(),$($e,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:d(()=>[i(s).length&&i(n).label?(a(),c("div",kn,[v("p",bn,w(i(n).label),1),(a(!0),c(M,null,E(i(s),p=>(a(),$(se,{key:p.link,item:p},null,8,["item"]))),128))])):f("",!0),i(e).appearance&&i(e).appearance!=="force-dark"?(a(),c("div",$n,[v("div",gn,[v("p",yn,w(i(t).darkModeSwitchLabel||"Appearance"),1),v("div",Pn,[m(ke)])])])):f("",!0),i(t).socialLinks?(a(),c("div",Ln,[v("div",Vn,[m(ge,{class:"social-links-list",links:i(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}}),Tn=k(Sn,[["__scopeId","data-v-8e87c032"]]),wn=o=>(B("data-v-6bee1efd"),o=o(),H(),o),In=["aria-expanded"],Nn=wn(()=>v("span",{class:"container"},[v("span",{class:"top"}),v("span",{class:"middle"}),v("span",{class:"bottom"})],-1)),Mn=[Nn],An=_({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(o){return(e,t)=>(a(),c("button",{type:"button",class:N(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=s=>e.$emit("click"))},Mn,10,In))}}),Cn=k(An,[["__scopeId","data-v-6bee1efd"]]),Bn=["innerHTML"],Hn=_({__name:"VPNavBarMenuLink",props:{item:{}},setup(o){const{page:e}=L();return(t,s)=>(a(),$(F,{class:N({VPNavBarMenuLink:!0,active:i(j)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,noIcon:t.item.noIcon,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:d(()=>[v("span",{innerHTML:t.item.text},null,8,Bn)]),_:1},8,["class","href","noIcon","target","rel"]))}}),En=k(Hn,[["__scopeId","data-v-08fbf4b6"]]),Fn=_({__name:"VPNavBarMenuGroup",props:{item:{}},setup(o){const e=o,{page:t}=L(),s=r=>"link"in r?j(t.value.relativePath,r.link,!!e.item.activeMatch):r.items.some(s),n=g(()=>s(e.item));return(r,u)=>(a(),$($e,{class:N({VPNavBarMenuGroup:!0,active:i(j)(i(t).relativePath,r.item.activeMatch,!!r.item.activeMatch)||n.value}),button:r.item.text,items:r.item.items},null,8,["class","button","items"]))}}),Dn=o=>(B("data-v-f732b5d0"),o=o(),H(),o),On={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},Un=Dn(()=>v("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Gn=_({__name:"VPNavBarMenu",setup(o){const{theme:e}=L();return(t,s)=>i(e).nav?(a(),c("nav",On,[Un,(a(!0),c(M,null,E(i(e).nav,n=>(a(),c(M,{key:n.text},["link"in n?(a(),$(En,{key:0,item:n},null,8,["item"])):(a(),$(Fn,{key:1,item:n},null,8,["item"]))],64))),128))])):f("",!0)}}),jn=k(Gn,[["__scopeId","data-v-f732b5d0"]]);function zn(o){const{localeIndex:e,theme:t}=L();function s(n){var A,C,S;const r=n.split("."),u=(A=t.value.search)==null?void 0:A.options,h=u&&typeof u=="object",p=h&&((S=(C=u.locales)==null?void 0:C[e.value])==null?void 0:S.translations)||null,b=h&&u.translations||null;let P=p,y=b,V=o;const T=r.pop();for(const U of r){let G=null;const W=V==null?void 0:V[U];W&&(G=V=W);const ne=y==null?void 0:y[U];ne&&(G=y=ne);const ae=P==null?void 0:P[U];ae&&(G=P=ae),W||(V=G),ne||(y=G),ae||(P=G)}return(P==null?void 0:P[T])??(y==null?void 0:y[T])??(V==null?void 0:V[T])??""}return s}const qn=["aria-label"],Kn={class:"DocSearch-Button-Container"},Wn=v("span",{class:"vp-icon DocSearch-Search-Icon"},null,-1),Rn={class:"DocSearch-Button-Placeholder"},Jn=v("span",{class:"DocSearch-Button-Keys"},[v("kbd",{class:"DocSearch-Button-Key"}),v("kbd",{class:"DocSearch-Button-Key"},"K")],-1),ye=_({__name:"VPNavBarSearchButton",setup(o){const t=zn({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(s,n)=>(a(),c("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":i(t)("button.buttonAriaLabel")},[v("span",Kn,[Wn,v("span",Rn,w(i(t)("button.buttonText")),1)]),Jn],8,qn))}}),Yn={class:"VPNavBarSearch"},Qn={id:"local-search"},Xn={key:1,id:"docsearch"},Zn=_({__name:"VPNavBarSearch",setup(o){const e=Ye(()=>Qe(()=>import("./VPLocalSearchBox.BANsnCko.js"),__vite__mapDeps([0,1]))),t=()=>null,{theme:s}=L(),n=I(!1),r=I(!1);z(()=>{});function u(){n.value||(n.value=!0,setTimeout(h,16))}function h(){const y=new Event("keydown");y.key="k",y.metaKey=!0,window.dispatchEvent(y),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||h()},16)}function p(y){const V=y.target,T=V.tagName;return V.isContentEditable||T==="INPUT"||T==="SELECT"||T==="TEXTAREA"}const b=I(!1);le("k",y=>{(y.ctrlKey||y.metaKey)&&(y.preventDefault(),b.value=!0)}),le("/",y=>{p(y)||(y.preventDefault(),b.value=!0)});const P="local";return(y,V)=>{var T;return a(),c("div",Yn,[i(P)==="local"?(a(),c(M,{key:0},[b.value?(a(),$(i(e),{key:0,onClose:V[0]||(V[0]=A=>b.value=!1)})):f("",!0),v("div",Qn,[m(ye,{onClick:V[1]||(V[1]=A=>b.value=!0)})])],64)):i(P)==="algolia"?(a(),c(M,{key:1},[n.value?(a(),$(i(t),{key:0,algolia:((T=i(s).search)==null?void 0:T.options)??i(s).algolia,onVnodeBeforeMount:V[2]||(V[2]=A=>r.value=!0)},null,8,["algolia"])):f("",!0),r.value?f("",!0):(a(),c("div",Xn,[m(ye,{onClick:u})]))],64)):f("",!0)])}}}),xn=_({__name:"VPNavBarSocialLinks",setup(o){const{theme:e}=L();return(t,s)=>i(e).socialLinks?(a(),$(ge,{key:0,class:"VPNavBarSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),ea=k(xn,[["__scopeId","data-v-ef6192dc"]]),ta=["href","rel","target"],oa={key:1},sa={key:2},na=_({__name:"VPNavBarTitle",setup(o){const{site:e,theme:t}=L(),{hasSidebar:s}=O(),{currentLang:n}=Y(),r=g(()=>{var p;return typeof t.value.logoLink=="string"?t.value.logoLink:(p=t.value.logoLink)==null?void 0:p.link}),u=g(()=>{var p;return typeof t.value.logoLink=="string"||(p=t.value.logoLink)==null?void 0:p.rel}),h=g(()=>{var p;return typeof t.value.logoLink=="string"||(p=t.value.logoLink)==null?void 0:p.target});return(p,b)=>(a(),c("div",{class:N(["VPNavBarTitle",{"has-sidebar":i(s)}])},[v("a",{class:"title",href:r.value??i(fe)(i(n).link),rel:u.value,target:h.value},[l(p.$slots,"nav-bar-title-before",{},void 0,!0),i(t).logo?(a(),$(Z,{key:0,class:"logo",image:i(t).logo},null,8,["image"])):f("",!0),i(t).siteTitle?(a(),c("span",oa,w(i(t).siteTitle),1)):i(t).siteTitle===void 0?(a(),c("span",sa,w(i(e).title),1)):f("",!0),l(p.$slots,"nav-bar-title-after",{},void 0,!0)],8,ta)],2))}}),aa=k(na,[["__scopeId","data-v-0ad69264"]]),ra={class:"items"},ia={class:"title"},la=_({__name:"VPNavBarTranslations",setup(o){const{theme:e}=L(),{localeLinks:t,currentLang:s}=Y({correspondingLink:!0});return(n,r)=>i(t).length&&i(s).label?(a(),$($e,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:i(e).langMenuLabel||"Change language"},{default:d(()=>[v("div",ra,[v("p",ia,w(i(s).label),1),(a(!0),c(M,null,E(i(t),u=>(a(),$(se,{key:u.link,item:u},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}}),ca=k(la,[["__scopeId","data-v-acee064b"]]),ua=o=>(B("data-v-844edcde"),o=o(),H(),o),da={class:"wrapper"},va={class:"container"},pa={class:"title"},ha={class:"content"},fa={class:"content-body"},_a=ua(()=>v("div",{class:"divider"},[v("div",{class:"divider-line"})],-1)),ma=_({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(o){const{y:e}=Te(),{hasSidebar:t}=O(),{frontmatter:s}=L(),n=I({});return Pe(()=>{n.value={"has-sidebar":t.value,home:s.value.layout==="home",top:e.value===0}}),(r,u)=>(a(),c("div",{class:N(["VPNavBar",n.value])},[v("div",da,[v("div",va,[v("div",pa,[m(aa,null,{"nav-bar-title-before":d(()=>[l(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":d(()=>[l(r.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),v("div",ha,[v("div",fa,[l(r.$slots,"nav-bar-content-before",{},void 0,!0),m(Zn,{class:"search"}),m(jn,{class:"menu"}),m(ca,{class:"translations"}),m(qs,{class:"appearance"}),m(ea,{class:"social-links"}),m(Tn,{class:"extra"}),l(r.$slots,"nav-bar-content-after",{},void 0,!0),m(Cn,{class:"hamburger",active:r.isScreenOpen,onClick:u[0]||(u[0]=h=>r.$emit("toggle-screen"))},null,8,["active"])])])])]),_a],2))}}),ka=k(ma,[["__scopeId","data-v-844edcde"]]),ba={key:0,class:"VPNavScreenAppearance"},$a={class:"text"},ga=_({__name:"VPNavScreenAppearance",setup(o){const{site:e,theme:t}=L();return(s,n)=>i(e).appearance&&i(e).appearance!=="force-dark"?(a(),c("div",ba,[v("p",$a,w(i(t).darkModeSwitchLabel||"Appearance"),1),m(ke)])):f("",!0)}}),ya=k(ga,[["__scopeId","data-v-338d9b48"]]),Pa=_({__name:"VPNavScreenMenuLink",props:{item:{}},setup(o){const e=oe("close-screen");return(t,s)=>(a(),$(F,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e),innerHTML:t.item.text},null,8,["href","target","rel","onClick","innerHTML"]))}}),La=k(Pa,[["__scopeId","data-v-1a934d60"]]),Va=_({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(o){const e=oe("close-screen");return(t,s)=>(a(),$(F,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:d(()=>[D(w(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),Ee=k(Va,[["__scopeId","data-v-aea78dd1"]]),Sa={class:"VPNavScreenMenuGroupSection"},Ta={key:0,class:"title"},wa=_({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(o){return(e,t)=>(a(),c("div",Sa,[e.text?(a(),c("p",Ta,w(e.text),1)):f("",!0),(a(!0),c(M,null,E(e.items,s=>(a(),$(Ee,{key:s.text,item:s},null,8,["item"]))),128))]))}}),Ia=k(wa,[["__scopeId","data-v-f60dbfa7"]]),Na=o=>(B("data-v-d2212c70"),o=o(),H(),o),Ma=["aria-controls","aria-expanded"],Aa=["innerHTML"],Ca=Na(()=>v("span",{class:"vpi-plus button-icon"},null,-1)),Ba=["id"],Ha={key:1,class:"group"},Ea=_({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(o){const e=o,t=I(!1),s=g(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function n(){t.value=!t.value}return(r,u)=>(a(),c("div",{class:N(["VPNavScreenMenuGroup",{open:t.value}])},[v("button",{class:"button","aria-controls":s.value,"aria-expanded":t.value,onClick:n},[v("span",{class:"button-text",innerHTML:r.text},null,8,Aa),Ca],8,Ma),v("div",{id:s.value,class:"items"},[(a(!0),c(M,null,E(r.items,h=>(a(),c(M,{key:h.text},["link"in h?(a(),c("div",{key:h.text,class:"item"},[m(Ee,{item:h},null,8,["item"])])):(a(),c("div",Ha,[m(Ia,{text:h.text,items:h.items},null,8,["text","items"])]))],64))),128))],8,Ba)],2))}}),Fa=k(Ea,[["__scopeId","data-v-d2212c70"]]),Da={key:0,class:"VPNavScreenMenu"},Oa=_({__name:"VPNavScreenMenu",setup(o){const{theme:e}=L();return(t,s)=>i(e).nav?(a(),c("nav",Da,[(a(!0),c(M,null,E(i(e).nav,n=>(a(),c(M,{key:n.text},["link"in n?(a(),$(La,{key:0,item:n},null,8,["item"])):(a(),$(Fa,{key:1,text:n.text||"",items:n.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Ua=_({__name:"VPNavScreenSocialLinks",setup(o){const{theme:e}=L();return(t,s)=>i(e).socialLinks?(a(),$(ge,{key:0,class:"VPNavScreenSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Fe=o=>(B("data-v-516e4bc3"),o=o(),H(),o),Ga=Fe(()=>v("span",{class:"vpi-languages icon lang"},null,-1)),ja=Fe(()=>v("span",{class:"vpi-chevron-down icon chevron"},null,-1)),za={class:"list"},qa=_({__name:"VPNavScreenTranslations",setup(o){const{localeLinks:e,currentLang:t}=Y({correspondingLink:!0}),s=I(!1);function n(){s.value=!s.value}return(r,u)=>i(e).length&&i(t).label?(a(),c("div",{key:0,class:N(["VPNavScreenTranslations",{open:s.value}])},[v("button",{class:"title",onClick:n},[Ga,D(" "+w(i(t).label)+" ",1),ja]),v("ul",za,[(a(!0),c(M,null,E(i(e),h=>(a(),c("li",{key:h.link,class:"item"},[m(F,{class:"link",href:h.link},{default:d(()=>[D(w(h.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}}),Ka=k(qa,[["__scopeId","data-v-516e4bc3"]]),Wa={class:"container"},Ra=_({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(o){const e=I(null),t=we(J?document.body:null);return(s,n)=>(a(),$(ve,{name:"fade",onEnter:n[0]||(n[0]=r=>t.value=!0),onAfterLeave:n[1]||(n[1]=r=>t.value=!1)},{default:d(()=>[s.open?(a(),c("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[v("div",Wa,[l(s.$slots,"nav-screen-content-before",{},void 0,!0),m(Oa,{class:"menu"}),m(Ka,{class:"translations"}),m(ya,{class:"appearance"}),m(Ua,{class:"social-links"}),l(s.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}}),Ja=k(Ra,[["__scopeId","data-v-57cce842"]]),Ya={key:0,class:"VPNav"},Qa=_({__name:"VPNav",setup(o){const{isScreenOpen:e,closeScreen:t,toggleScreen:s}=As(),{frontmatter:n}=L(),r=g(()=>n.value.navbar!==!1);return Ie("close-screen",t),x(()=>{J&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(u,h)=>r.value?(a(),c("header",Ya,[m(ka,{"is-screen-open":i(e),onToggleScreen:i(s)},{"nav-bar-title-before":d(()=>[l(u.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":d(()=>[l(u.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":d(()=>[l(u.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":d(()=>[l(u.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),m(Ja,{open:i(e)},{"nav-screen-content-before":d(()=>[l(u.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":d(()=>[l(u.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}}),Xa=k(Qa,[["__scopeId","data-v-7ad780c2"]]),De=o=>(B("data-v-c24f735a"),o=o(),H(),o),Za=["role","tabindex"],xa=De(()=>v("div",{class:"indicator"},null,-1)),er=De(()=>v("span",{class:"vpi-chevron-right caret-icon"},null,-1)),tr=[er],or={key:1,class:"items"},sr=_({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(o){const e=o,{collapsed:t,collapsible:s,isLink:n,isActiveLink:r,hasActiveLink:u,hasChildren:h,toggle:p}=$t(g(()=>e.item)),b=g(()=>h.value?"section":"div"),P=g(()=>n.value?"a":"div"),y=g(()=>h.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),V=g(()=>n.value?void 0:"button"),T=g(()=>[[`level-${e.depth}`],{collapsible:s.value},{collapsed:t.value},{"is-link":n.value},{"is-active":r.value},{"has-active":u.value}]);function A(S){"key"in S&&S.key!=="Enter"||!e.item.link&&p()}function C(){e.item.link&&p()}return(S,U)=>{const G=K("VPSidebarItem",!0);return a(),$(R(b.value),{class:N(["VPSidebarItem",T.value])},{default:d(()=>[S.item.text?(a(),c("div",Q({key:0,class:"item",role:V.value},Xe(S.item.items?{click:A,keydown:A}:{},!0),{tabindex:S.item.items&&0}),[xa,S.item.link?(a(),$(F,{key:0,tag:P.value,class:"link",href:S.item.link,rel:S.item.rel,target:S.item.target},{default:d(()=>[(a(),$(R(y.value),{class:"text",innerHTML:S.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),$(R(y.value),{key:1,class:"text",innerHTML:S.item.text},null,8,["innerHTML"])),S.item.collapsed!=null&&S.item.items&&S.item.items.length?(a(),c("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:C,onKeydown:Ze(C,["enter"]),tabindex:"0"},tr,32)):f("",!0)],16,Za)):f("",!0),S.item.items&&S.item.items.length?(a(),c("div",or,[S.depth<5?(a(!0),c(M,{key:0},E(S.item.items,W=>(a(),$(G,{key:W.text,item:W,depth:S.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}}),nr=k(sr,[["__scopeId","data-v-c24f735a"]]),Oe=o=>(B("data-v-4871f9f5"),o=o(),H(),o),ar=Oe(()=>v("div",{class:"curtain"},null,-1)),rr={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},ir=Oe(()=>v("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),lr=_({__name:"VPSidebar",props:{open:{type:Boolean}},setup(o){const{sidebarGroups:e,hasSidebar:t}=O(),s=o,n=I(null),r=we(J?document.body:null);return q([s,n],()=>{var u;s.open?(r.value=!0,(u=n.value)==null||u.focus()):r.value=!1},{immediate:!0,flush:"post"}),(u,h)=>i(t)?(a(),c("aside",{key:0,class:N(["VPSidebar",{open:u.open}]),ref_key:"navEl",ref:n,onClick:h[0]||(h[0]=xe(()=>{},["stop"]))},[ar,v("nav",rr,[ir,l(u.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),c(M,null,E(i(e),p=>(a(),c("div",{key:p.text,class:"group"},[m(nr,{item:p,depth:0},null,8,["item"])]))),128)),l(u.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}}),cr=k(lr,[["__scopeId","data-v-4871f9f5"]]),ur=_({__name:"VPSkipLink",setup(o){const e=te(),t=I();q(()=>e.path,()=>t.value.focus());function s({target:n}){const r=document.getElementById(decodeURIComponent(n.hash).slice(1));if(r){const u=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",u)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",u),r.focus(),window.scrollTo(0,0)}}return(n,r)=>(a(),c(M,null,[v("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),v("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:s}," Skip to content ")],64))}}),dr=k(ur,[["__scopeId","data-v-c8291ffa"]]),vr=_({__name:"Layout",setup(o){const{isOpen:e,open:t,close:s}=O(),n=te();q(()=>n.path,s),bt(e,s);const{frontmatter:r}=L(),u=et(),h=g(()=>!!u["home-hero-image"]);return Ie("hero-image-slot-exists",h),(p,b)=>{const P=K("Content");return i(r).layout!==!1?(a(),c("div",{key:0,class:N(["Layout",i(r).pageClass])},[l(p.$slots,"layout-top",{},void 0,!0),m(dr),m(nt,{class:"backdrop",show:i(e),onClick:i(s)},null,8,["show","onClick"]),m(Xa,null,{"nav-bar-title-before":d(()=>[l(p.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":d(()=>[l(p.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":d(()=>[l(p.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":d(()=>[l(p.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":d(()=>[l(p.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":d(()=>[l(p.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),m(Ms,{open:i(e),onOpenMenu:i(t)},null,8,["open","onOpenMenu"]),m(cr,{open:i(e)},{"sidebar-nav-before":d(()=>[l(p.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":d(()=>[l(p.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),m(vs,null,{"page-top":d(()=>[l(p.$slots,"page-top",{},void 0,!0)]),"page-bottom":d(()=>[l(p.$slots,"page-bottom",{},void 0,!0)]),"not-found":d(()=>[l(p.$slots,"not-found",{},void 0,!0)]),"home-hero-before":d(()=>[l(p.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":d(()=>[l(p.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":d(()=>[l(p.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":d(()=>[l(p.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":d(()=>[l(p.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":d(()=>[l(p.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":d(()=>[l(p.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":d(()=>[l(p.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":d(()=>[l(p.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":d(()=>[l(p.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":d(()=>[l(p.$slots,"doc-before",{},void 0,!0)]),"doc-after":d(()=>[l(p.$slots,"doc-after",{},void 0,!0)]),"doc-top":d(()=>[l(p.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":d(()=>[l(p.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":d(()=>[l(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":d(()=>[l(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":d(()=>[l(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":d(()=>[l(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":d(()=>[l(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":d(()=>[l(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),m(ms),l(p.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),$(P,{key:1}))}}}),pr=k(vr,[["__scopeId","data-v-d8b57b2d"]]),fr={Layout:pr,enhanceApp:({app:o})=>{o.component("Badge",tt)}};export{zn as c,fr as t,L as u}; diff --git a/assets/cm-texture1.Dy62LOjy.png b/assets/cm-texture1.Dy62LOjy.png new file mode 100644 index 00000000..681e5310 Binary files /dev/null and b/assets/cm-texture1.Dy62LOjy.png differ diff --git a/assets/compressedTexture02.BVxh_oYK.png b/assets/compressedTexture02.BVxh_oYK.png new file mode 100644 index 00000000..8de17106 Binary files /dev/null and b/assets/compressedTexture02.BVxh_oYK.png differ diff --git a/assets/contentencoding_error.BloxEjqB.png b/assets/contentencoding_error.BloxEjqB.png new file mode 100644 index 00000000..a22e7181 Binary files /dev/null and b/assets/contentencoding_error.BloxEjqB.png differ diff --git a/assets/cors_istrusted.CXIjh3Wr.png b/assets/cors_istrusted.CXIjh3Wr.png new file mode 100644 index 00000000..72731b17 Binary files /dev/null and b/assets/cors_istrusted.CXIjh3Wr.png differ diff --git a/assets/coverview_loading.BiGkOLi_.png b/assets/coverview_loading.BiGkOLi_.png new file mode 100644 index 00000000..4a402209 Binary files /dev/null and b/assets/coverview_loading.BiGkOLi_.png differ diff --git a/assets/custom_urp_case1.agZ3pgEK.jpeg b/assets/custom_urp_case1.agZ3pgEK.jpeg new file mode 100644 index 00000000..29395ff4 Binary files /dev/null and b/assets/custom_urp_case1.agZ3pgEK.jpeg differ diff --git a/assets/custom_urp_case2.DnrjlZiu.jpeg b/assets/custom_urp_case2.DnrjlZiu.jpeg new file mode 100644 index 00000000..9af3c9d1 Binary files /dev/null and b/assets/custom_urp_case2.DnrjlZiu.jpeg differ diff --git a/assets/custom_urp_pkgs.DenHdfcL.png b/assets/custom_urp_pkgs.DenHdfcL.png new file mode 100644 index 00000000..6590fe1a Binary files /dev/null and b/assets/custom_urp_pkgs.DenHdfcL.png differ diff --git a/assets/debugexception1.BCEW4Vpv.png b/assets/debugexception1.BCEW4Vpv.png new file mode 100644 index 00000000..7993f2d8 Binary files /dev/null and b/assets/debugexception1.BCEW4Vpv.png differ diff --git a/assets/debugexception2.DcBQavmG.png b/assets/debugexception2.DcBQavmG.png new file mode 100644 index 00000000..c848879c Binary files /dev/null and b/assets/debugexception2.DcBQavmG.png differ diff --git a/assets/debugexception3.BbzACAPG.png b/assets/debugexception3.BbzACAPG.png new file mode 100644 index 00000000..9f0a28c8 Binary files /dev/null and b/assets/debugexception3.BbzACAPG.png differ diff --git a/assets/debugexception4.DSUeoQnT.png b/assets/debugexception4.DSUeoQnT.png new file mode 100644 index 00000000..b4c60d77 Binary files /dev/null and b/assets/debugexception4.DSUeoQnT.png differ diff --git a/assets/debugexception5.CVudNa9e.png b/assets/debugexception5.CVudNa9e.png new file mode 100644 index 00000000..945bb0ab Binary files /dev/null and b/assets/debugexception5.CVudNa9e.png differ diff --git a/assets/debugexception6.B1QYPPoJ.png b/assets/debugexception6.B1QYPPoJ.png new file mode 100644 index 00000000..0e9d577a Binary files /dev/null and b/assets/debugexception6.B1QYPPoJ.png differ diff --git a/assets/debugexception7.DPXuZd9S.png b/assets/debugexception7.DPXuZd9S.png new file mode 100644 index 00000000..caf34f9c Binary files /dev/null and b/assets/debugexception7.DPXuZd9S.png differ diff --git a/assets/debugexception8.c2_HLQJn.png b/assets/debugexception8.c2_HLQJn.png new file mode 100644 index 00000000..d8e15dc4 Binary files /dev/null and b/assets/debugexception8.c2_HLQJn.png differ diff --git a/assets/debugexception9.W-PbBU-g.png b/assets/debugexception9.W-PbBU-g.png new file mode 100644 index 00000000..4a66ddbb Binary files /dev/null and b/assets/debugexception9.W-PbBU-g.png differ diff --git a/assets/demo-video.bmM6aW-q.mp4 b/assets/demo-video.bmM6aW-q.mp4 new file mode 100644 index 00000000..74ea196e Binary files /dev/null and b/assets/demo-video.bmM6aW-q.mp4 differ diff --git a/assets/demo1.BsKsD89o.jpeg b/assets/demo1.BsKsD89o.jpeg new file mode 100644 index 00000000..8a27caf7 Binary files /dev/null and b/assets/demo1.BsKsD89o.jpeg differ diff --git a/assets/demo2.ByJUMFjf.jpeg b/assets/demo2.ByJUMFjf.jpeg new file mode 100644 index 00000000..74c3486f Binary files /dev/null and b/assets/demo2.ByJUMFjf.jpeg differ diff --git a/assets/demo3.Bj8Y-kOy.jpeg b/assets/demo3.Bj8Y-kOy.jpeg new file mode 100644 index 00000000..c9b30733 Binary files /dev/null and b/assets/demo3.Bj8Y-kOy.jpeg differ diff --git a/assets/demo4.D7PXjFbO.jpeg b/assets/demo4.D7PXjFbO.jpeg new file mode 100644 index 00000000..ba84951d Binary files /dev/null and b/assets/demo4.D7PXjFbO.jpeg differ diff --git a/assets/demo5.jD5F1kVF.jpeg b/assets/demo5.jD5F1kVF.jpeg new file mode 100644 index 00000000..d2d9461c Binary files /dev/null and b/assets/demo5.jD5F1kVF.jpeg differ diff --git a/assets/demo6.BEnu5duc.jpeg b/assets/demo6.BEnu5duc.jpeg new file mode 100644 index 00000000..c8c36233 Binary files /dev/null and b/assets/demo6.BEnu5duc.jpeg differ diff --git a/assets/demo7.BJ_h8aov.jpeg b/assets/demo7.BJ_h8aov.jpeg new file mode 100644 index 00000000..5e6a1914 Binary files /dev/null and b/assets/demo7.BJ_h8aov.jpeg differ diff --git a/assets/detail-log.DbHrWCWi.png b/assets/detail-log.DbHrWCWi.png new file mode 100644 index 00000000..582e912f Binary files /dev/null and b/assets/detail-log.DbHrWCWi.png differ diff --git a/assets/devtools_network.CT_lQr9b.png b/assets/devtools_network.CT_lQr9b.png new file mode 100644 index 00000000..c6c64610 Binary files /dev/null and b/assets/devtools_network.CT_lQr9b.png differ diff --git a/assets/devtools_preview.BlOHG4Jk.png b/assets/devtools_preview.BlOHG4Jk.png new file mode 100644 index 00000000..4866656f Binary files /dev/null and b/assets/devtools_preview.BlOHG4Jk.png differ diff --git a/assets/enable-plugin-1.hrkbpNFb.png b/assets/enable-plugin-1.hrkbpNFb.png new file mode 100644 index 00000000..22f276ae Binary files /dev/null and b/assets/enable-plugin-1.hrkbpNFb.png differ diff --git a/assets/enable-plugin-2.gCjA-u1u.png b/assets/enable-plugin-2.gCjA-u1u.png new file mode 100644 index 00000000..d145ff80 Binary files /dev/null and b/assets/enable-plugin-2.gCjA-u1u.png differ diff --git a/assets/entrance.3drElOeY.png b/assets/entrance.3drElOeY.png new file mode 100644 index 00000000..1998dcb1 Binary files /dev/null and b/assets/entrance.3drElOeY.png differ diff --git a/assets/export.CQlpBdYZ.png b/assets/export.CQlpBdYZ.png new file mode 100644 index 00000000..56736e4c Binary files /dev/null and b/assets/export.CQlpBdYZ.png differ diff --git a/assets/extension-panel.CsEDE2eK.png b/assets/extension-panel.CsEDE2eK.png new file mode 100644 index 00000000..7c6185a2 Binary files /dev/null and b/assets/extension-panel.CsEDE2eK.png differ diff --git a/assets/file_cache.BSYo5Xk8.png b/assets/file_cache.BSYo5Xk8.png new file mode 100644 index 00000000..f7862d5e Binary files /dev/null and b/assets/file_cache.BSYo5Xk8.png differ diff --git a/assets/guide1.BFcCfH8z.png b/assets/guide1.BFcCfH8z.png new file mode 100644 index 00000000..d7fcdba3 Binary files /dev/null and b/assets/guide1.BFcCfH8z.png differ diff --git a/assets/icon.BKg32493.png b/assets/icon.BKg32493.png new file mode 100644 index 00000000..a46285f3 Binary files /dev/null and b/assets/icon.BKg32493.png differ diff --git a/assets/image-0.j3jmWdo-.png b/assets/image-0.j3jmWdo-.png new file mode 100644 index 00000000..63015a33 Binary files /dev/null and b/assets/image-0.j3jmWdo-.png differ diff --git a/assets/image-1.BvWojOYk.png b/assets/image-1.BvWojOYk.png new file mode 100644 index 00000000..c8275dd6 Binary files /dev/null and b/assets/image-1.BvWojOYk.png differ diff --git a/assets/increment-update.B83feQqF.png b/assets/increment-update.B83feQqF.png new file mode 100644 index 00000000..023d9c9a Binary files /dev/null and b/assets/increment-update.B83feQqF.png differ diff --git a/assets/index.md.C0pbrLsL.js b/assets/index.md.C0pbrLsL.js new file mode 100644 index 00000000..cb1ca745 --- /dev/null +++ b/assets/index.md.C0pbrLsL.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as i}from"./chunks/framework.Br2U662V.js";const p=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Unity/团结快适配方案","text":"基于WebGL + WebAssembly","tagline":"无需使用JavaScript重构,快速移植Unity/团结引擎游戏至微信小游戏平台解决方案。","image":{"src":"/image/vitepress/home.png","alt":"WeChatGame & Unity"},"actions":[{"theme":"brand","text":"现在开始","link":"/README"},{"theme":"alt","text":"优秀案例","link":"/Design/ShowCase"},{"theme":"alt","text":"在 GitHub 上查看","link":"https://github.com/wechat-miniprogram/minigame-unity-webgl-transform"},{"theme":"alt","text":"安装与更新日志","link":"/CHANGELOG"}]},"features":[{"title":"快速移植","details":"保持原引擎工具链与技术栈,无需重写游戏核心逻辑,支持大部分第三方插件。","icon":{"src":"/image/vitepress/feature-0.svg"},"link":"Design/Summary","linkText":"技术原理"},{"title":"高兼容性","details":"目前支持Unity2018及更新的引擎版本的接入(含团结引擎),保持较高还原度。","icon":{"src":"/image/vitepress/feature-1.svg"},"link":"Design/Evaluation","linkText":"兼容性评估"},{"title":"众多案例","details":"目前超3000款Unity游戏在微信小游戏平台发布,持续为用户带来优质的游戏体验。","icon":{"src":"/image/vitepress/feature-2.svg"},"link":"Design/ShowCase","linkText":"优秀案例"},{"title":"平台能力丰富","details":"快速接入微信平台带来的能力扩展。","icon":{"src":"/image/vitepress/feature-3.svg"},"link":"Design/WX_SDK","linkText":"微信平台能力接入"},{"title":"性能优化工具","details":"提供丰富的性能优化工具,使得重度游戏的接入也成为了现实。","icon":{"src":"/image/vitepress/feature-4.svg"},"link":"Design/PerfOptimization","linkText":"性能优化专栏"}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),a={name:"index.md"};function n(s,r,l,m,o,c){return i(),t("div")}const d=e(a,[["render",n]]);export{p as __pageData,d as default}; diff --git a/assets/index.md.C0pbrLsL.lean.js b/assets/index.md.C0pbrLsL.lean.js new file mode 100644 index 00000000..cb1ca745 --- /dev/null +++ b/assets/index.md.C0pbrLsL.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as i}from"./chunks/framework.Br2U662V.js";const p=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Unity/团结快适配方案","text":"基于WebGL + WebAssembly","tagline":"无需使用JavaScript重构,快速移植Unity/团结引擎游戏至微信小游戏平台解决方案。","image":{"src":"/image/vitepress/home.png","alt":"WeChatGame & Unity"},"actions":[{"theme":"brand","text":"现在开始","link":"/README"},{"theme":"alt","text":"优秀案例","link":"/Design/ShowCase"},{"theme":"alt","text":"在 GitHub 上查看","link":"https://github.com/wechat-miniprogram/minigame-unity-webgl-transform"},{"theme":"alt","text":"安装与更新日志","link":"/CHANGELOG"}]},"features":[{"title":"快速移植","details":"保持原引擎工具链与技术栈,无需重写游戏核心逻辑,支持大部分第三方插件。","icon":{"src":"/image/vitepress/feature-0.svg"},"link":"Design/Summary","linkText":"技术原理"},{"title":"高兼容性","details":"目前支持Unity2018及更新的引擎版本的接入(含团结引擎),保持较高还原度。","icon":{"src":"/image/vitepress/feature-1.svg"},"link":"Design/Evaluation","linkText":"兼容性评估"},{"title":"众多案例","details":"目前超3000款Unity游戏在微信小游戏平台发布,持续为用户带来优质的游戏体验。","icon":{"src":"/image/vitepress/feature-2.svg"},"link":"Design/ShowCase","linkText":"优秀案例"},{"title":"平台能力丰富","details":"快速接入微信平台带来的能力扩展。","icon":{"src":"/image/vitepress/feature-3.svg"},"link":"Design/WX_SDK","linkText":"微信平台能力接入"},{"title":"性能优化工具","details":"提供丰富的性能优化工具,使得重度游戏的接入也成为了现实。","icon":{"src":"/image/vitepress/feature-4.svg"},"link":"Design/PerfOptimization","linkText":"性能优化专栏"}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),a={name:"index.md"};function n(s,r,l,m,o,c){return i(),t("div")}const d=e(a,[["render",n]]);export{p as __pageData,d as default}; diff --git a/assets/init-cf-proj.Cam-RLFc.jpg b/assets/init-cf-proj.Cam-RLFc.jpg new file mode 100644 index 00000000..7db7b9fb Binary files /dev/null and b/assets/init-cf-proj.Cam-RLFc.jpg differ diff --git a/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2 b/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2 new file mode 100644 index 00000000..2a687296 Binary files /dev/null and b/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2 differ diff --git a/assets/inter-italic-cyrillic.D6csxwjC.woff2 b/assets/inter-italic-cyrillic.D6csxwjC.woff2 new file mode 100644 index 00000000..f6403515 Binary files /dev/null and b/assets/inter-italic-cyrillic.D6csxwjC.woff2 differ diff --git a/assets/inter-italic-greek-ext.CHOfFY1k.woff2 b/assets/inter-italic-greek-ext.CHOfFY1k.woff2 new file mode 100644 index 00000000..00218960 Binary files /dev/null and b/assets/inter-italic-greek-ext.CHOfFY1k.woff2 differ diff --git a/assets/inter-italic-greek.9J96vYpw.woff2 b/assets/inter-italic-greek.9J96vYpw.woff2 new file mode 100644 index 00000000..71c265f8 Binary files /dev/null and b/assets/inter-italic-greek.9J96vYpw.woff2 differ diff --git a/assets/inter-italic-latin-ext.BGcWXLrn.woff2 b/assets/inter-italic-latin-ext.BGcWXLrn.woff2 new file mode 100644 index 00000000..9c1b9440 Binary files /dev/null and b/assets/inter-italic-latin-ext.BGcWXLrn.woff2 differ diff --git a/assets/inter-italic-latin.DbsTr1gm.woff2 b/assets/inter-italic-latin.DbsTr1gm.woff2 new file mode 100644 index 00000000..01fcf207 Binary files /dev/null and b/assets/inter-italic-latin.DbsTr1gm.woff2 differ diff --git a/assets/inter-italic-vietnamese.DHNAd7Wr.woff2 b/assets/inter-italic-vietnamese.DHNAd7Wr.woff2 new file mode 100644 index 00000000..e4f788ee Binary files /dev/null and b/assets/inter-italic-vietnamese.DHNAd7Wr.woff2 differ diff --git a/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2 b/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2 new file mode 100644 index 00000000..28593ccb Binary files /dev/null and b/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2 differ diff --git a/assets/inter-roman-cyrillic.CMhn1ESj.woff2 b/assets/inter-roman-cyrillic.CMhn1ESj.woff2 new file mode 100644 index 00000000..a20adc16 Binary files /dev/null and b/assets/inter-roman-cyrillic.CMhn1ESj.woff2 differ diff --git a/assets/inter-roman-greek-ext.D0mI3NpI.woff2 b/assets/inter-roman-greek-ext.D0mI3NpI.woff2 new file mode 100644 index 00000000..e3b0be76 Binary files /dev/null and b/assets/inter-roman-greek-ext.D0mI3NpI.woff2 differ diff --git a/assets/inter-roman-greek.JvnBZ4YD.woff2 b/assets/inter-roman-greek.JvnBZ4YD.woff2 new file mode 100644 index 00000000..f790e047 Binary files /dev/null and b/assets/inter-roman-greek.JvnBZ4YD.woff2 differ diff --git a/assets/inter-roman-latin-ext.ZlYT4o7i.woff2 b/assets/inter-roman-latin-ext.ZlYT4o7i.woff2 new file mode 100644 index 00000000..715bd903 Binary files /dev/null and b/assets/inter-roman-latin-ext.ZlYT4o7i.woff2 differ diff --git a/assets/inter-roman-latin.Bu8hRsVA.woff2 b/assets/inter-roman-latin.Bu8hRsVA.woff2 new file mode 100644 index 00000000..a540b7af Binary files /dev/null and b/assets/inter-roman-latin.Bu8hRsVA.woff2 differ diff --git a/assets/inter-roman-vietnamese.ClpjcLMQ.woff2 b/assets/inter-roman-vietnamese.ClpjcLMQ.woff2 new file mode 100644 index 00000000..5a9f9cb9 Binary files /dev/null and b/assets/inter-roman-vietnamese.ClpjcLMQ.woff2 differ diff --git a/assets/ios_running_performance.BhKw0KAS.png b/assets/ios_running_performance.BhKw0KAS.png new file mode 100644 index 00000000..7e62f709 Binary files /dev/null and b/assets/ios_running_performance.BhKw0KAS.png differ diff --git a/assets/ios_running_performance.C2YhXpAi.png b/assets/ios_running_performance.C2YhXpAi.png new file mode 100644 index 00000000..8e94e70a Binary files /dev/null and b/assets/ios_running_performance.C2YhXpAi.png differ diff --git a/assets/ios_start_performance.COdU60g3.png b/assets/ios_start_performance.COdU60g3.png new file mode 100644 index 00000000..fa0e5044 Binary files /dev/null and b/assets/ios_start_performance.COdU60g3.png differ diff --git a/assets/ios_start_performance.DKHEzdfl.png b/assets/ios_start_performance.DKHEzdfl.png new file mode 100644 index 00000000..2917a6f9 Binary files /dev/null and b/assets/ios_start_performance.DKHEzdfl.png differ diff --git a/assets/iosoptimization1.DvZXgGEV.png b/assets/iosoptimization1.DvZXgGEV.png new file mode 100644 index 00000000..36f0f738 Binary files /dev/null and b/assets/iosoptimization1.DvZXgGEV.png differ diff --git a/assets/iosoptimization2.ydVjAkNG.png b/assets/iosoptimization2.ydVjAkNG.png new file mode 100644 index 00000000..7f72b68f Binary files /dev/null and b/assets/iosoptimization2.ydVjAkNG.png differ diff --git a/assets/iosoptimization3.wOpxID9g.png b/assets/iosoptimization3.wOpxID9g.png new file mode 100644 index 00000000..ce3a9666 Binary files /dev/null and b/assets/iosoptimization3.wOpxID9g.png differ diff --git a/assets/issueandcontact1.BeCR63tr.png b/assets/issueandcontact1.BeCR63tr.png new file mode 100644 index 00000000..27188400 Binary files /dev/null and b/assets/issueandcontact1.BeCR63tr.png differ diff --git a/assets/issueandcontact2.CMeXfzus.png b/assets/issueandcontact2.CMeXfzus.png new file mode 100644 index 00000000..04444e57 Binary files /dev/null and b/assets/issueandcontact2.CMeXfzus.png differ diff --git a/assets/issueforproduction1.bg6Fx4u1.png b/assets/issueforproduction1.bg6Fx4u1.png new file mode 100644 index 00000000..55fa1245 Binary files /dev/null and b/assets/issueforproduction1.bg6Fx4u1.png differ diff --git a/assets/issueforproduction2.DBTokemQ.png b/assets/issueforproduction2.DBTokemQ.png new file mode 100644 index 00000000..acff4873 Binary files /dev/null and b/assets/issueforproduction2.DBTokemQ.png differ diff --git a/assets/issueforproduction3.CSZPVLs2.png b/assets/issueforproduction3.CSZPVLs2.png new file mode 100644 index 00000000..164bcacf Binary files /dev/null and b/assets/issueforproduction3.CSZPVLs2.png differ diff --git a/assets/issueforproduction4.BR2EWzID.png b/assets/issueforproduction4.BR2EWzID.png new file mode 100644 index 00000000..d2f7eb09 Binary files /dev/null and b/assets/issueforproduction4.BR2EWzID.png differ diff --git a/assets/launch.DesekVa-.png b/assets/launch.DesekVa-.png new file mode 100644 index 00000000..7fa11c08 Binary files /dev/null and b/assets/launch.DesekVa-.png differ diff --git a/assets/launch1.eXb8FuyH.png b/assets/launch1.eXb8FuyH.png new file mode 100644 index 00000000..fb831ec3 Binary files /dev/null and b/assets/launch1.eXb8FuyH.png differ diff --git a/assets/loading_default.CgcqniMh.png b/assets/loading_default.CgcqniMh.png new file mode 100644 index 00000000..46e903b7 Binary files /dev/null and b/assets/loading_default.CgcqniMh.png differ diff --git a/assets/loading_demo.BSF4nkPk.jpg b/assets/loading_demo.BSF4nkPk.jpg new file mode 100644 index 00000000..715c69bf Binary files /dev/null and b/assets/loading_demo.BSF4nkPk.jpg differ diff --git a/assets/loading_design.CFXQxkuH.jpg b/assets/loading_design.CFXQxkuH.jpg new file mode 100644 index 00000000..8a760481 Binary files /dev/null and b/assets/loading_design.CFXQxkuH.jpg differ diff --git a/assets/main.CwerfU8n.png b/assets/main.CwerfU8n.png new file mode 100644 index 00000000..404c9e96 Binary files /dev/null and b/assets/main.CwerfU8n.png differ diff --git a/assets/memoryprofiler1.DqqM3hJv.png b/assets/memoryprofiler1.DqqM3hJv.png new file mode 100644 index 00000000..644f5c23 Binary files /dev/null and b/assets/memoryprofiler1.DqqM3hJv.png differ diff --git a/assets/memoryprofiler2.CO1KsCPI.png b/assets/memoryprofiler2.CO1KsCPI.png new file mode 100644 index 00000000..6c829438 Binary files /dev/null and b/assets/memoryprofiler2.CO1KsCPI.png differ diff --git a/assets/memoryprofiler3.BHNFw8hn.png b/assets/memoryprofiler3.BHNFw8hn.png new file mode 100644 index 00000000..c6ef091d Binary files /dev/null and b/assets/memoryprofiler3.BHNFw8hn.png differ diff --git a/assets/memoryprofiler4.fmpW3n4Z.png b/assets/memoryprofiler4.fmpW3n4Z.png new file mode 100644 index 00000000..736fed7e Binary files /dev/null and b/assets/memoryprofiler4.fmpW3n4Z.png differ diff --git a/assets/memoryprofiler5.BQ-2xA41.png b/assets/memoryprofiler5.BQ-2xA41.png new file mode 100644 index 00000000..9637011f Binary files /dev/null and b/assets/memoryprofiler5.BQ-2xA41.png differ diff --git a/assets/monitor-console.DO12gbRg.png b/assets/monitor-console.DO12gbRg.png new file mode 100644 index 00000000..b2f80525 Binary files /dev/null and b/assets/monitor-console.DO12gbRg.png differ diff --git a/assets/monitor-dialog.DkmXCKiX.png b/assets/monitor-dialog.DkmXCKiX.png new file mode 100644 index 00000000..865142ac Binary files /dev/null and b/assets/monitor-dialog.DkmXCKiX.png differ diff --git a/assets/mp_addplugin.BtUIXUot.png b/assets/mp_addplugin.BtUIXUot.png new file mode 100644 index 00000000..e6a85ff2 Binary files /dev/null and b/assets/mp_addplugin.BtUIXUot.png differ diff --git a/assets/network-profile.D4dnTarY.png b/assets/network-profile.D4dnTarY.png new file mode 100644 index 00000000..a7c6421e Binary files /dev/null and b/assets/network-profile.D4dnTarY.png differ diff --git a/assets/normal-assetbundle-memory.Iz7sHvbP.png b/assets/normal-assetbundle-memory.Iz7sHvbP.png new file mode 100644 index 00000000..f85951cf Binary files /dev/null and b/assets/normal-assetbundle-memory.Iz7sHvbP.png differ diff --git a/assets/o2.BiHxPfHa.png b/assets/o2.BiHxPfHa.png new file mode 100644 index 00000000..27b0a8b0 Binary files /dev/null and b/assets/o2.BiHxPfHa.png differ diff --git a/assets/open-cf.DLBm5pMO.jpg b/assets/open-cf.DLBm5pMO.jpg new file mode 100644 index 00000000..b362c92b Binary files /dev/null and b/assets/open-cf.DLBm5pMO.jpg differ diff --git a/assets/opendata.BgWhdjkg.png b/assets/opendata.BgWhdjkg.png new file mode 100644 index 00000000..17f5c246 Binary files /dev/null and b/assets/opendata.BgWhdjkg.png differ diff --git a/assets/opendataframework.2OxzAkk1.png b/assets/opendataframework.2OxzAkk1.png new file mode 100644 index 00000000..5b6de615 Binary files /dev/null and b/assets/opendataframework.2OxzAkk1.png differ diff --git a/assets/optimizationMemory1.CpSWLJ8m.png b/assets/optimizationMemory1.CpSWLJ8m.png new file mode 100644 index 00000000..0fbd6c8e Binary files /dev/null and b/assets/optimizationMemory1.CpSWLJ8m.png differ diff --git a/assets/optimizationMemory10.D-SZ1dZe.png b/assets/optimizationMemory10.D-SZ1dZe.png new file mode 100644 index 00000000..9e695992 Binary files /dev/null and b/assets/optimizationMemory10.D-SZ1dZe.png differ diff --git a/assets/optimizationMemory11.BB2iD3xR.png b/assets/optimizationMemory11.BB2iD3xR.png new file mode 100644 index 00000000..bbb40364 Binary files /dev/null and b/assets/optimizationMemory11.BB2iD3xR.png differ diff --git a/assets/optimizationMemory12.C9Wsxuea.png b/assets/optimizationMemory12.C9Wsxuea.png new file mode 100644 index 00000000..3371a250 Binary files /dev/null and b/assets/optimizationMemory12.C9Wsxuea.png differ diff --git a/assets/optimizationMemory2.aE_-ogAD.png b/assets/optimizationMemory2.aE_-ogAD.png new file mode 100644 index 00000000..d7db5a36 Binary files /dev/null and b/assets/optimizationMemory2.aE_-ogAD.png differ diff --git a/assets/optimizationMemory3.CEtq636B.png b/assets/optimizationMemory3.CEtq636B.png new file mode 100644 index 00000000..099dfb7f Binary files /dev/null and b/assets/optimizationMemory3.CEtq636B.png differ diff --git a/assets/optimizationMemory4.ymgsNGzl.png b/assets/optimizationMemory4.ymgsNGzl.png new file mode 100644 index 00000000..df480587 Binary files /dev/null and b/assets/optimizationMemory4.ymgsNGzl.png differ diff --git a/assets/optimizationMemory5.CzK1696v.png b/assets/optimizationMemory5.CzK1696v.png new file mode 100644 index 00000000..3b79874b Binary files /dev/null and b/assets/optimizationMemory5.CzK1696v.png differ diff --git a/assets/optimizationMemory6.8iXuz3Gb.png b/assets/optimizationMemory6.8iXuz3Gb.png new file mode 100644 index 00000000..c09f153d Binary files /dev/null and b/assets/optimizationMemory6.8iXuz3Gb.png differ diff --git a/assets/optimizationperformence1.CW91_65C.png b/assets/optimizationperformence1.CW91_65C.png new file mode 100644 index 00000000..1f122398 Binary files /dev/null and b/assets/optimizationperformence1.CW91_65C.png differ diff --git a/assets/optimizationperformence2.Bbu1amCi.png b/assets/optimizationperformence2.Bbu1amCi.png new file mode 100644 index 00000000..95174128 Binary files /dev/null and b/assets/optimizationperformence2.Bbu1amCi.png differ diff --git a/assets/panel.SGItx1qt.png b/assets/panel.SGItx1qt.png new file mode 100644 index 00000000..68af69d5 Binary files /dev/null and b/assets/panel.SGItx1qt.png differ diff --git a/assets/preproc.B1bs5gTC.png b/assets/preproc.B1bs5gTC.png new file mode 100644 index 00000000..74129720 Binary files /dev/null and b/assets/preproc.B1bs5gTC.png differ diff --git a/assets/profile.yCnwPQ6L.png b/assets/profile.yCnwPQ6L.png new file mode 100644 index 00000000..c5fdb58f Binary files /dev/null and b/assets/profile.yCnwPQ6L.png differ diff --git a/assets/profile1.DdUMXlC5.png b/assets/profile1.DdUMXlC5.png new file mode 100644 index 00000000..e6118036 Binary files /dev/null and b/assets/profile1.DdUMXlC5.png differ diff --git a/assets/profile2.DnwO5wIf.png b/assets/profile2.DnwO5wIf.png new file mode 100644 index 00000000..67e6d9aa Binary files /dev/null and b/assets/profile2.DnwO5wIf.png differ diff --git a/assets/profile3.Dk7R5Gjr.png b/assets/profile3.Dk7R5Gjr.png new file mode 100644 index 00000000..636aeb94 Binary files /dev/null and b/assets/profile3.Dk7R5Gjr.png differ diff --git a/assets/profile4.CDVkeqdb.png b/assets/profile4.CDVkeqdb.png new file mode 100644 index 00000000..f54846a7 Binary files /dev/null and b/assets/profile4.CDVkeqdb.png differ diff --git a/assets/reportstartupstat1.qEYJSd-a.png b/assets/reportstartupstat1.qEYJSd-a.png new file mode 100644 index 00000000..95c7697f Binary files /dev/null and b/assets/reportstartupstat1.qEYJSd-a.png differ diff --git a/assets/reportstartupstat2.A-XTyuDH.png b/assets/reportstartupstat2.A-XTyuDH.png new file mode 100644 index 00000000..e4a961c5 Binary files /dev/null and b/assets/reportstartupstat2.A-XTyuDH.png differ diff --git a/assets/reportstartupstat3.CsotQIbl.png b/assets/reportstartupstat3.CsotQIbl.png new file mode 100644 index 00000000..62f02e54 Binary files /dev/null and b/assets/reportstartupstat3.CsotQIbl.png differ diff --git a/assets/saveArea.BbgprMYb.png b/assets/saveArea.BbgprMYb.png new file mode 100644 index 00000000..ea7e6173 Binary files /dev/null and b/assets/saveArea.BbgprMYb.png differ diff --git a/assets/scene.lhTRWbUv.png b/assets/scene.lhTRWbUv.png new file mode 100644 index 00000000..dbd88599 Binary files /dev/null and b/assets/scene.lhTRWbUv.png differ diff --git a/assets/showcase23.DnIByHA1.png b/assets/showcase23.DnIByHA1.png new file mode 100644 index 00000000..1e7d184e Binary files /dev/null and b/assets/showcase23.DnIByHA1.png differ diff --git a/assets/showcase24.CPjVEBLQ.png b/assets/showcase24.CPjVEBLQ.png new file mode 100644 index 00000000..cdf2a4e5 Binary files /dev/null and b/assets/showcase24.CPjVEBLQ.png differ diff --git a/assets/showcase25.BuEmUmjn.png b/assets/showcase25.BuEmUmjn.png new file mode 100644 index 00000000..6e0e7578 Binary files /dev/null and b/assets/showcase25.BuEmUmjn.png differ diff --git a/assets/showcase26.MXwOeujv.png b/assets/showcase26.MXwOeujv.png new file mode 100644 index 00000000..8252bc13 Binary files /dev/null and b/assets/showcase26.MXwOeujv.png differ diff --git a/assets/showcase32.oc_3wbrg.png b/assets/showcase32.oc_3wbrg.png new file mode 100644 index 00000000..b7537b9a Binary files /dev/null and b/assets/showcase32.oc_3wbrg.png differ diff --git a/assets/showcase33.BLPWsQzS.png b/assets/showcase33.BLPWsQzS.png new file mode 100644 index 00000000..db7c7949 Binary files /dev/null and b/assets/showcase33.BLPWsQzS.png differ diff --git a/assets/showcase34.B1YJ7Mgk.png b/assets/showcase34.B1YJ7Mgk.png new file mode 100644 index 00000000..835ba645 Binary files /dev/null and b/assets/showcase34.B1YJ7Mgk.png differ diff --git a/assets/showcase35.zELPKZNw.jpeg b/assets/showcase35.zELPKZNw.jpeg new file mode 100644 index 00000000..8346bf47 Binary files /dev/null and b/assets/showcase35.zELPKZNw.jpeg differ diff --git a/assets/showcase36.CEaMVzaY.jpeg b/assets/showcase36.CEaMVzaY.jpeg new file mode 100644 index 00000000..7e24427f Binary files /dev/null and b/assets/showcase36.CEaMVzaY.jpeg differ diff --git a/assets/showcase37.R-rKrZ15.jpeg b/assets/showcase37.R-rKrZ15.jpeg new file mode 100644 index 00000000..a4f53e09 Binary files /dev/null and b/assets/showcase37.R-rKrZ15.jpeg differ diff --git a/assets/showcase38.BKdA-XtE.jpeg b/assets/showcase38.BKdA-XtE.jpeg new file mode 100644 index 00000000..878100f6 Binary files /dev/null and b/assets/showcase38.BKdA-XtE.jpeg differ diff --git a/assets/showcase39.BdJRJUTr.jpeg b/assets/showcase39.BdJRJUTr.jpeg new file mode 100644 index 00000000..5ea0bc13 Binary files /dev/null and b/assets/showcase39.BdJRJUTr.jpeg differ diff --git a/assets/showcase40.CU3rTbh5.jpeg b/assets/showcase40.CU3rTbh5.jpeg new file mode 100644 index 00000000..67874d0c Binary files /dev/null and b/assets/showcase40.CU3rTbh5.jpeg differ diff --git a/assets/showcase41.9V2U7_05.jpeg b/assets/showcase41.9V2U7_05.jpeg new file mode 100644 index 00000000..94189224 Binary files /dev/null and b/assets/showcase41.9V2U7_05.jpeg differ diff --git a/assets/showcase42.-UTNgrg5.jpeg b/assets/showcase42.-UTNgrg5.jpeg new file mode 100644 index 00000000..1fba0001 Binary files /dev/null and b/assets/showcase42.-UTNgrg5.jpeg differ diff --git a/assets/showcase43.D25VoWLG.jpeg b/assets/showcase43.D25VoWLG.jpeg new file mode 100644 index 00000000..2e51e3ce Binary files /dev/null and b/assets/showcase43.D25VoWLG.jpeg differ diff --git a/assets/showcase44.O3fT7nY7.jpeg b/assets/showcase44.O3fT7nY7.jpeg new file mode 100644 index 00000000..9030b52b Binary files /dev/null and b/assets/showcase44.O3fT7nY7.jpeg differ diff --git a/assets/showcase45.CJUw74WU.png b/assets/showcase45.CJUw74WU.png new file mode 100644 index 00000000..11b34b31 Binary files /dev/null and b/assets/showcase45.CJUw74WU.png differ diff --git a/assets/showcase47.DboLTkit.png b/assets/showcase47.DboLTkit.png new file mode 100644 index 00000000..b710d9d5 Binary files /dev/null and b/assets/showcase47.DboLTkit.png differ diff --git a/assets/showcase8.B0rkzu4v.png b/assets/showcase8.B0rkzu4v.png new file mode 100644 index 00000000..8f21eb07 Binary files /dev/null and b/assets/showcase8.B0rkzu4v.png differ diff --git a/assets/start-split.Bf36xgxL.png b/assets/start-split.Bf36xgxL.png new file mode 100644 index 00000000..b934058c Binary files /dev/null and b/assets/start-split.Bf36xgxL.png differ diff --git a/assets/startupop1.BD5F2llA.png b/assets/startupop1.BD5F2llA.png new file mode 100644 index 00000000..68630372 Binary files /dev/null and b/assets/startupop1.BD5F2llA.png differ diff --git a/assets/startupop2.ClyZL3O9.png b/assets/startupop2.ClyZL3O9.png new file mode 100644 index 00000000..d067cfe9 Binary files /dev/null and b/assets/startupop2.ClyZL3O9.png differ diff --git a/assets/stop.CFvG6dL8.png b/assets/stop.CFvG6dL8.png new file mode 100644 index 00000000..c7d075e3 Binary files /dev/null and b/assets/stop.CFvG6dL8.png differ diff --git a/assets/stopprofile.DmPV0U4-.png b/assets/stopprofile.DmPV0U4-.png new file mode 100644 index 00000000..347d00ac Binary files /dev/null and b/assets/stopprofile.DmPV0U4-.png differ diff --git a/assets/style.CMGOu1Ag.css b/assets/style.CMGOu1Ag.css new file mode 100644 index 00000000..1b7d5a7a --- /dev/null +++ b/assets/style.CMGOu1Ag.css @@ -0,0 +1 @@ +@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-cyrillic.CMhn1ESj.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-greek.JvnBZ4YD.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-greek-ext.D0mI3NpI.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-latin.Bu8hRsVA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-latin-ext.ZlYT4o7i.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/minigame-unity-webgl-transform/assets/inter-roman-vietnamese.ClpjcLMQ.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-cyrillic.D6csxwjC.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-greek.9J96vYpw.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-greek-ext.CHOfFY1k.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-latin.DbsTr1gm.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-latin-ext.BGcWXLrn.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/minigame-unity-webgl-transform/assets/inter-italic-vietnamese.DHNAd7Wr.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{display:inline-block;margin:auto 2px -2px}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z'/%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m5 8 6 6M4 14l6-6 2-3M2 5h12M7 2h1M22 22l-5-10-5 10M14 18h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7M14 9h7M14 15h7M14 20h7'/%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2ZM18 9l-6 6M12 9l6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}.vpi-social-discord{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418Z'/%3E%3C/svg%3E")}.vpi-social-facebook{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z'/%3E%3C/svg%3E")}.vpi-social-github{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")}.vpi-social-instagram{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.03.084c-1.277.06-2.149.264-2.91.563a5.874 5.874 0 0 0-2.124 1.388 5.878 5.878 0 0 0-1.38 2.127C.321 4.926.12 5.8.064 7.076.008 8.354-.005 8.764.001 12.023c.007 3.259.021 3.667.083 4.947.061 1.277.264 2.149.563 2.911.308.789.72 1.457 1.388 2.123a5.872 5.872 0 0 0 2.129 1.38c.763.295 1.636.496 2.913.552 1.278.056 1.689.069 4.947.063 3.257-.007 3.668-.021 4.947-.082 1.28-.06 2.147-.265 2.91-.563a5.881 5.881 0 0 0 2.123-1.388 5.881 5.881 0 0 0 1.38-2.129c.295-.763.496-1.636.551-2.912.056-1.28.07-1.69.063-4.948-.006-3.258-.02-3.667-.081-4.947-.06-1.28-.264-2.148-.564-2.911a5.892 5.892 0 0 0-1.387-2.123 5.857 5.857 0 0 0-2.128-1.38C19.074.322 18.202.12 16.924.066 15.647.009 15.236-.006 11.977 0 8.718.008 8.31.021 7.03.084m.14 21.693c-1.17-.05-1.805-.245-2.228-.408a3.736 3.736 0 0 1-1.382-.895 3.695 3.695 0 0 1-.9-1.378c-.165-.423-.363-1.058-.417-2.228-.06-1.264-.072-1.644-.08-4.848-.006-3.204.006-3.583.061-4.848.05-1.169.246-1.805.408-2.228.216-.561.477-.96.895-1.382a3.705 3.705 0 0 1 1.379-.9c.423-.165 1.057-.361 2.227-.417 1.265-.06 1.644-.072 4.848-.08 3.203-.006 3.583.006 4.85.062 1.168.05 1.804.244 2.227.408.56.216.96.475 1.382.895.421.42.681.817.9 1.378.165.422.362 1.056.417 2.227.06 1.265.074 1.645.08 4.848.005 3.203-.006 3.583-.061 4.848-.051 1.17-.245 1.805-.408 2.23-.216.56-.477.96-.896 1.38a3.705 3.705 0 0 1-1.378.9c-.422.165-1.058.362-2.226.418-1.266.06-1.645.072-4.85.079-3.204.007-3.582-.006-4.848-.06m9.783-16.192a1.44 1.44 0 1 0 1.437-1.442 1.44 1.44 0 0 0-1.437 1.442M5.839 12.012a6.161 6.161 0 1 0 12.323-.024 6.162 6.162 0 0 0-12.323.024M8 12.008A4 4 0 1 1 12.008 16 4 4 0 0 1 8 12.008'/%3E%3C/svg%3E")}.vpi-social-linkedin{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E")}.vpi-social-mastodon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E")}.vpi-social-npm{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z'/%3E%3C/svg%3E")}.vpi-social-slack{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z'/%3E%3C/svg%3E")}.vpi-social-twitter,.vpi-social-x{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/%3E%3C/svg%3E")}.vpi-social-youtube{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-54a304ca]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-54a304ca],.VPBackdrop.fade-leave-to[data-v-54a304ca]{opacity:0}.VPBackdrop.fade-leave-active[data-v-54a304ca]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-54a304ca]{display:none}}.NotFound[data-v-b9c0c15a]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-b9c0c15a]{padding:96px 32px 168px}}.code[data-v-b9c0c15a]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-b9c0c15a]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-b9c0c15a]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-b9c0c15a]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-b9c0c15a]{padding-top:20px}.link[data-v-b9c0c15a]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-b9c0c15a]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-53c99d69]{position:relative;z-index:1}.nested[data-v-53c99d69]{padding-right:16px;padding-left:16px}.outline-link[data-v-53c99d69]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-53c99d69]:hover,.outline-link.active[data-v-53c99d69]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-53c99d69]{padding-left:13px}.VPDocAsideOutline[data-v-6b52fe58]{display:none}.VPDocAsideOutline.has-outline[data-v-6b52fe58]{display:block}.content[data-v-6b52fe58]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-6b52fe58]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-6b52fe58]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-cb998dce]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-cb998dce]{flex-grow:1}.VPDocAside[data-v-cb998dce] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-cb998dce] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-cb998dce] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-19a7ae4e]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-19a7ae4e]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-b77f9094]{margin-top:64px}.edit-info[data-v-b77f9094]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-b77f9094]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-b77f9094]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-b77f9094]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-b77f9094]{margin-right:8px}.prev-next[data-v-b77f9094]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-b77f9094]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-b77f9094]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-b77f9094]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-b77f9094]{margin-left:auto;text-align:right}.desc[data-v-b77f9094]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-b77f9094]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-e6f2a212]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-e6f2a212]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-e6f2a212]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-e6f2a212]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-e6f2a212]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-e6f2a212]{display:flex;justify-content:center}.VPDoc .aside[data-v-e6f2a212]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-e6f2a212]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-e6f2a212]{max-width:1104px}}.container[data-v-e6f2a212]{margin:0 auto;width:100%}.aside[data-v-e6f2a212]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-e6f2a212]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-e6f2a212]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-e6f2a212]::-webkit-scrollbar{display:none}.aside-curtain[data-v-e6f2a212]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-e6f2a212]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-e6f2a212]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-e6f2a212]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-e6f2a212]{order:1;margin:0;min-width:640px}}.content-container[data-v-e6f2a212]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-e6f2a212]{max-width:688px}.VPButton[data-v-c9cf0e3c]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-c9cf0e3c]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-c9cf0e3c]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-c9cf0e3c]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-c9cf0e3c]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-c9cf0e3c]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-c9cf0e3c]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-c9cf0e3c]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-c9cf0e3c]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-c9cf0e3c]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-c9cf0e3c]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-c9cf0e3c]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-c9cf0e3c]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-ab19afbb]{display:none}.dark .VPImage.light[data-v-ab19afbb]{display:none}.VPHero[data-v-b10c5094]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-b10c5094]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-b10c5094]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-b10c5094]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-b10c5094]{flex-direction:row}}.main[data-v-b10c5094]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-b10c5094]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-b10c5094]{text-align:left}}@media (min-width: 960px){.main[data-v-b10c5094]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-b10c5094]{max-width:592px}}.name[data-v-b10c5094],.text[data-v-b10c5094]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-b10c5094],.VPHero.has-image .text[data-v-b10c5094]{margin:0 auto}.name[data-v-b10c5094]{color:var(--vp-home-hero-name-color)}.clip[data-v-b10c5094]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-b10c5094],.text[data-v-b10c5094]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-b10c5094],.text[data-v-b10c5094]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-b10c5094],.VPHero.has-image .text[data-v-b10c5094]{margin:0}}.tagline[data-v-b10c5094]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-b10c5094]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-b10c5094]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-b10c5094]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-b10c5094]{margin:0}}.actions[data-v-b10c5094]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-b10c5094]{justify-content:center}@media (min-width: 640px){.actions[data-v-b10c5094]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-b10c5094]{justify-content:flex-start}}.action[data-v-b10c5094]{flex-shrink:0;padding:6px}.image[data-v-b10c5094]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-b10c5094]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-b10c5094]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-b10c5094]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-b10c5094]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-b10c5094]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-b10c5094]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-b10c5094]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-b10c5094]{width:320px;height:320px}}[data-v-b10c5094] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-b10c5094] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-b10c5094] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-bd37d1a2]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-bd37d1a2]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-bd37d1a2]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-bd37d1a2]>.VPImage{margin-bottom:20px}.icon[data-v-bd37d1a2]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-bd37d1a2]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-bd37d1a2]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-bd37d1a2]{padding-top:8px}.link-text-value[data-v-bd37d1a2]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-bd37d1a2]{margin-left:6px}.VPFeatures[data-v-d08986ee]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-d08986ee]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-d08986ee]{padding:0 64px}}.container[data-v-d08986ee]{margin:0 auto;max-width:1152px}.items[data-v-d08986ee]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-d08986ee]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-d08986ee],.item.grid-4[data-v-d08986ee],.item.grid-6[data-v-d08986ee]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-d08986ee],.item.grid-4[data-v-d08986ee]{width:50%}.item.grid-3[data-v-d08986ee],.item.grid-6[data-v-d08986ee]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-d08986ee]{width:25%}}.container[data-v-d59ac166]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media (min-width: 640px){.container[data-v-d59ac166]{padding:0 48px}}@media (min-width: 960px){.container[data-v-d59ac166]{width:100%;padding:0 64px}}.vp-doc[data-v-d59ac166] .VPHomeSponsors,.vp-doc[data-v-d59ac166] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-d59ac166] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-d59ac166] .VPHomeSponsors a,.vp-doc[data-v-d59ac166] .VPTeamPage a{text-decoration:none}.VPHome[data-v-07b1ad08]{margin-bottom:96px}@media (min-width: 768px){.VPHome[data-v-07b1ad08]{margin-bottom:128px}}.VPContent[data-v-9a6c75ad]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-9a6c75ad]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-9a6c75ad]{margin:0}@media (min-width: 960px){.VPContent[data-v-9a6c75ad]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-9a6c75ad]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-9a6c75ad]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-566314d4]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-566314d4]{display:none}.VPFooter[data-v-566314d4] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-566314d4] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-566314d4]{padding:32px}}.container[data-v-566314d4]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-566314d4],.copyright[data-v-566314d4]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-0b5c97a1]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-0b5c97a1]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-0b5c97a1]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-0b5c97a1]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-0b5c97a1]{color:var(--vp-c-text-1)}.icon[data-v-0b5c97a1]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-0b5c97a1]{font-size:14px}.icon[data-v-0b5c97a1]{font-size:16px}}.open>.icon[data-v-0b5c97a1]{transform:rotate(90deg)}.items[data-v-0b5c97a1]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-0b5c97a1]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-0b5c97a1]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-0b5c97a1]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-0b5c97a1]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-0b5c97a1]{transition:all .2s ease-out}.flyout-leave-active[data-v-0b5c97a1]{transition:all .15s ease-in}.flyout-enter-from[data-v-0b5c97a1],.flyout-leave-to[data-v-0b5c97a1]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-2488c25a]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-2488c25a]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-2488c25a]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-2488c25a]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-2488c25a]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-2488c25a]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-2488c25a]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-2488c25a]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-2488c25a]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-2488c25a]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-2488c25a]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-2488c25a]{display:none}}.menu-icon[data-v-2488c25a]{margin-right:8px;font-size:14px}.VPOutlineDropdown[data-v-2488c25a]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-2488c25a]{padding:12px 32px 11px}}.VPSwitch[data-v-b4ccac88]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-b4ccac88]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-b4ccac88]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-b4ccac88]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-b4ccac88] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-b4ccac88] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-7df97737]{opacity:1}.moon[data-v-7df97737],.dark .sun[data-v-7df97737]{opacity:0}.dark .moon[data-v-7df97737]{opacity:1}.dark .VPSwitchAppearance[data-v-7df97737] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-283b26e9]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-283b26e9]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-f51f088d]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-f51f088d]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-f51f088d]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-f51f088d]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-a6b0397c]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-a6b0397c]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-a6b0397c]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-a6b0397c]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-e42ed9b3]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-e42ed9b3] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-e42ed9b3] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-e42ed9b3] .group:last-child{padding-bottom:0}.VPMenu[data-v-e42ed9b3] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-e42ed9b3] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-e42ed9b3] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-e42ed9b3] .action{padding-left:24px}.VPFlyout[data-v-af5898d3]{position:relative}.VPFlyout[data-v-af5898d3]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-af5898d3]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-af5898d3]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-af5898d3]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-af5898d3]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-af5898d3],.button[aria-expanded=true]+.menu[data-v-af5898d3]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-af5898d3]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-af5898d3]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-af5898d3]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-af5898d3]{margin-right:0;font-size:16px}.text-icon[data-v-af5898d3]{margin-left:4px;font-size:14px}.icon[data-v-af5898d3]{font-size:20px;transition:fill .25s}.menu[data-v-af5898d3]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-358b6670]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-358b6670]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-358b6670]>svg,.VPSocialLink[data-v-358b6670]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-e71e869c]{display:flex;justify-content:center}.VPNavBarExtra[data-v-8e87c032]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-8e87c032]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-8e87c032]{display:none}}.trans-title[data-v-8e87c032]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-8e87c032],.item.social-links[data-v-8e87c032]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-8e87c032]{min-width:176px}.appearance-action[data-v-8e87c032]{margin-right:-2px}.social-links-list[data-v-8e87c032]{margin:-4px -8px}.VPNavBarHamburger[data-v-6bee1efd]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-6bee1efd]{display:none}}.container[data-v-6bee1efd]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-6bee1efd]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-6bee1efd]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-6bee1efd]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-6bee1efd]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-6bee1efd]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-6bee1efd]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-6bee1efd],.VPNavBarHamburger.active:hover .middle[data-v-6bee1efd],.VPNavBarHamburger.active:hover .bottom[data-v-6bee1efd]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-6bee1efd],.middle[data-v-6bee1efd],.bottom[data-v-6bee1efd]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-6bee1efd]{top:0;left:0;transform:translate(0)}.middle[data-v-6bee1efd]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-6bee1efd]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-08fbf4b6]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-08fbf4b6],.VPNavBarMenuLink[data-v-08fbf4b6]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-f732b5d0]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-f732b5d0]{display:flex}}/*! @docsearch/css 3.6.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 1px 0 rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 1px 1px 0 rgba(3,4,9,.30196078431372547);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}.DocSearch-Button-Key--pressed{transform:translate3d(0,1px,0);box-shadow:var(--docsearch-key-pressed-shadow)}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.DocSearch-Search-Icon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke-width='1.6' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' d='m14.386 14.386 4.088 4.088-4.088-4.088A7.533 7.533 0 1 1 3.733 3.733a7.533 7.533 0 0 1 10.653 10.653z'/%3E%3C/svg%3E")}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-ef6192dc]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-ef6192dc]{display:flex;align-items:center}}.title[data-v-0ad69264]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-0ad69264]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-0ad69264]{border-bottom-color:var(--vp-c-divider)}}[data-v-0ad69264] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-acee064b]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-acee064b]{display:flex;align-items:center}}.title[data-v-acee064b]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-844edcde]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .5s}.VPNavBar[data-v-844edcde]:not(.home){background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar[data-v-844edcde]:not(.home){background-color:transparent}.VPNavBar[data-v-844edcde]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-844edcde]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-844edcde]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-844edcde]{padding:0}}.container[data-v-844edcde]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-844edcde],.container>.content[data-v-844edcde]{pointer-events:none}.container[data-v-844edcde] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-844edcde]{max-width:100%}}.title[data-v-844edcde]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-844edcde]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-844edcde]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-844edcde]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-844edcde]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-844edcde]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-844edcde]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.home.top) .content-body[data-v-844edcde]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-844edcde]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-844edcde]{column-gap:.5rem}}.menu+.translations[data-v-844edcde]:before,.menu+.appearance[data-v-844edcde]:before,.menu+.social-links[data-v-844edcde]:before,.translations+.appearance[data-v-844edcde]:before,.appearance+.social-links[data-v-844edcde]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-844edcde]:before,.translations+.appearance[data-v-844edcde]:before{margin-right:16px}.appearance+.social-links[data-v-844edcde]:before{margin-left:16px}.social-links[data-v-844edcde]{margin-right:-8px}.divider[data-v-844edcde]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-844edcde]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-844edcde]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-844edcde]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-844edcde]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.home.top) .divider-line[data-v-844edcde]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-844edcde]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-338d9b48]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-338d9b48]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-1a934d60]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-1a934d60]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-aea78dd1]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-aea78dd1]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-f60dbfa7]{display:block}.title[data-v-f60dbfa7]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-d2212c70]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-d2212c70]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-d2212c70]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-d2212c70]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-d2212c70]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-d2212c70]{transform:rotate(45deg)}.button[data-v-d2212c70]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-d2212c70]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-d2212c70]{transition:transform .25s}.group[data-v-d2212c70]:first-child{padding-top:0}.group+.group[data-v-d2212c70],.group+.item[data-v-d2212c70]{padding-top:4px}.VPNavScreenTranslations[data-v-516e4bc3]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-516e4bc3]{height:auto}.title[data-v-516e4bc3]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-516e4bc3]{font-size:16px}.icon.lang[data-v-516e4bc3]{margin-right:8px}.icon.chevron[data-v-516e4bc3]{margin-left:4px}.list[data-v-516e4bc3]{padding:4px 0 0 24px}.link[data-v-516e4bc3]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-57cce842]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-57cce842],.VPNavScreen.fade-leave-active[data-v-57cce842]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-57cce842],.VPNavScreen.fade-leave-active .container[data-v-57cce842]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-57cce842],.VPNavScreen.fade-leave-to[data-v-57cce842]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-57cce842],.VPNavScreen.fade-leave-to .container[data-v-57cce842]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-57cce842]{display:none}}.container[data-v-57cce842]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-57cce842],.menu+.appearance[data-v-57cce842],.translations+.appearance[data-v-57cce842]{margin-top:24px}.menu+.social-links[data-v-57cce842]{margin-top:16px}.appearance+.social-links[data-v-57cce842]{margin-top:16px}.VPNav[data-v-7ad780c2]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-7ad780c2]{position:fixed}}.VPSidebarItem.level-0[data-v-c24f735a]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-c24f735a]{padding-bottom:10px}.item[data-v-c24f735a]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-c24f735a]{cursor:pointer}.indicator[data-v-c24f735a]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-c24f735a],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-c24f735a],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-c24f735a],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-c24f735a]{background-color:var(--vp-c-brand-1)}.link[data-v-c24f735a]{display:flex;align-items:center;flex-grow:1}.text[data-v-c24f735a]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-c24f735a]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-c24f735a],.VPSidebarItem.level-2 .text[data-v-c24f735a],.VPSidebarItem.level-3 .text[data-v-c24f735a],.VPSidebarItem.level-4 .text[data-v-c24f735a],.VPSidebarItem.level-5 .text[data-v-c24f735a]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-c24f735a],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-c24f735a],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-c24f735a],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-c24f735a],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-c24f735a],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-c24f735a]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-c24f735a],.VPSidebarItem.level-1.has-active>.item>.text[data-v-c24f735a],.VPSidebarItem.level-2.has-active>.item>.text[data-v-c24f735a],.VPSidebarItem.level-3.has-active>.item>.text[data-v-c24f735a],.VPSidebarItem.level-4.has-active>.item>.text[data-v-c24f735a],.VPSidebarItem.level-5.has-active>.item>.text[data-v-c24f735a],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-c24f735a],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-c24f735a],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-c24f735a],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-c24f735a],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-c24f735a],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-c24f735a]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-c24f735a],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-c24f735a],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-c24f735a],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-c24f735a],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-c24f735a],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-c24f735a]{color:var(--vp-c-brand-1)}.caret[data-v-c24f735a]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-c24f735a]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-c24f735a]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-c24f735a]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-c24f735a]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-c24f735a],.VPSidebarItem.level-2 .items[data-v-c24f735a],.VPSidebarItem.level-3 .items[data-v-c24f735a],.VPSidebarItem.level-4 .items[data-v-c24f735a],.VPSidebarItem.level-5 .items[data-v-c24f735a]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-c24f735a]{display:none}.VPSidebar[data-v-4871f9f5]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-4871f9f5]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-4871f9f5]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-4871f9f5]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-4871f9f5]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-4871f9f5]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-4871f9f5]{outline:0}.group+.group[data-v-4871f9f5]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-4871f9f5]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-c8291ffa]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-c8291ffa]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-c8291ffa]{top:14px;left:16px}}.Layout[data-v-d8b57b2d]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-3dc26e1d]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPHomeSponsors[data-v-3dc26e1d]{margin:96px 0}@media (min-width: 768px){.VPHomeSponsors[data-v-3dc26e1d]{margin:128px 0}}.VPHomeSponsors[data-v-3dc26e1d]{padding:0 24px}@media (min-width: 768px){.VPHomeSponsors[data-v-3dc26e1d]{padding:0 48px}}@media (min-width: 960px){.VPHomeSponsors[data-v-3dc26e1d]{padding:0 64px}}.container[data-v-3dc26e1d]{margin:0 auto;max-width:1152px}.love[data-v-3dc26e1d]{margin:0 auto;width:fit-content;font-size:28px;color:var(--vp-c-text-3)}.icon[data-v-3dc26e1d]{display:inline-block}.message[data-v-3dc26e1d]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-3dc26e1d]{padding-top:32px}.action[data-v-3dc26e1d]{padding-top:40px;text-align:center}.VPTeamPage[data-v-a5329171]{margin:96px 0}@media (min-width: 768px){.VPTeamPage[data-v-a5329171]{margin:128px 0}}.VPHome .VPTeamPageTitle[data-v-a5329171-s]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPTeamPageSection+.VPTeamPageSection[data-v-a5329171-s],.VPTeamMembers+.VPTeamPageSection[data-v-a5329171-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-a5329171-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-a5329171-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-a5329171-s],.VPTeamMembers+.VPTeamPageSection[data-v-a5329171-s]{margin-top:96px}}.VPTeamMembers[data-v-a5329171-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-a5329171-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-a5329171-s]{padding:0 64px}}.VPTeamPageTitle[data-v-46c5e327]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-46c5e327]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-46c5e327]{padding:80px 64px 48px}}.title[data-v-46c5e327]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-46c5e327]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-46c5e327]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-46c5e327]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-3bf2e850]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-3bf2e850]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-3bf2e850]{padding:0 64px}}.title[data-v-3bf2e850]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-3bf2e850]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-3bf2e850]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-3bf2e850]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-3bf2e850]{padding-top:40px}.VPTeamMembersItem[data-v-acff304e]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-acff304e]{padding:32px}.VPTeamMembersItem.small .data[data-v-acff304e]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-acff304e]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-acff304e]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-acff304e]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-acff304e]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-acff304e]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-acff304e]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-acff304e]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-acff304e]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-acff304e]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-acff304e]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-acff304e]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-acff304e]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-acff304e]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-acff304e]{text-align:center}.avatar[data-v-acff304e]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-acff304e]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-acff304e]{margin:0;font-weight:600}.affiliation[data-v-acff304e]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-acff304e]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-acff304e]:hover{color:var(--vp-c-brand-1)}.desc[data-v-acff304e]{margin:0 auto}.desc[data-v-acff304e] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-acff304e]{display:flex;justify-content:center;height:56px}.sp-link[data-v-acff304e]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-acff304e]:hover,.sp .sp-link.link[data-v-acff304e]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-acff304e]{margin-right:8px;font-size:16px}.VPTeamMembers.small .container[data-v-bf782009]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-bf782009]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-bf782009]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-bf782009]{max-width:876px}.VPTeamMembers.medium .container[data-v-bf782009]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-bf782009]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-bf782009]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-bf782009]{max-width:760px}.container[data-v-bf782009]{display:grid;gap:24px;margin:0 auto;max-width:1152px}:root{--vp-home-hero-name-color: transparent;--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #f69f41, #fbc662, #fea649);--vp-c-brand-1: #fa9c47;--vp-c-brand-2: rgba(251, 197, 98, .95);--vp-c-brand-3: #fa9c47;--vp-sidebar-width: 295px}.VPHero.has-image .text{font-size:1.7em}@media (min-width: 960px){.VPHero.has-image .text{font-size:2.4em}}.VPLocalSearchBox[data-v-4eeb92d2]{position:fixed;z-index:100;top:0;right:0;bottom:0;left:0;display:flex}.backdrop[data-v-4eeb92d2]{position:absolute;top:0;right:0;bottom:0;left:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-4eeb92d2]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media (max-width: 767px){.shell[data-v-4eeb92d2]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-4eeb92d2]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media (max-width: 767px){.search-bar[data-v-4eeb92d2]{padding:0 8px}}.search-bar[data-v-4eeb92d2]:focus-within{border-color:var(--vp-c-brand-1)}.local-search-icon[data-v-4eeb92d2]{display:block;font-size:18px}.navigate-icon[data-v-4eeb92d2]{display:block;font-size:14px}.search-icon[data-v-4eeb92d2]{margin:8px}@media (max-width: 767px){.search-icon[data-v-4eeb92d2]{display:none}}.search-input[data-v-4eeb92d2]{padding:6px 12px;font-size:inherit;width:100%}@media (max-width: 767px){.search-input[data-v-4eeb92d2]{padding:6px 4px}}.search-actions[data-v-4eeb92d2]{display:flex;gap:4px}@media (any-pointer: coarse){.search-actions[data-v-4eeb92d2]{gap:8px}}@media (min-width: 769px){.search-actions.before[data-v-4eeb92d2]{display:none}}.search-actions button[data-v-4eeb92d2]{padding:8px}.search-actions button[data-v-4eeb92d2]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-4eeb92d2]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-4eeb92d2]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-4eeb92d2]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-4eeb92d2]{display:flex;align-items:center;gap:4px}@media (max-width: 767px){.search-keyboard-shortcuts[data-v-4eeb92d2]{display:none}}.search-keyboard-shortcuts kbd[data-v-4eeb92d2]{background:#8080801a;border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-4eeb92d2]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-4eeb92d2]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-4eeb92d2]{margin:12px;width:100%;overflow:hidden}@media (max-width: 767px){.result>div[data-v-4eeb92d2]{margin:8px}}.titles[data-v-4eeb92d2]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-4eeb92d2]{display:flex;align-items:center;gap:4px}.title.main[data-v-4eeb92d2]{font-weight:500}.title-icon[data-v-4eeb92d2]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-4eeb92d2]{opacity:.5}.result.selected[data-v-4eeb92d2]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-4eeb92d2]{position:relative}.excerpt[data-v-4eeb92d2]{opacity:75%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;opacity:.5;margin-top:4px}.result.selected .excerpt[data-v-4eeb92d2]{opacity:1}.excerpt[data-v-4eeb92d2] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-4eeb92d2] mark,.excerpt[data-v-4eeb92d2] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-4eeb92d2] .vp-code-group .tabs{display:none}.excerpt[data-v-4eeb92d2] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-4eeb92d2]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-4eeb92d2]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-4eeb92d2],.result.selected .title-icon[data-v-4eeb92d2]{color:var(--vp-c-brand-1)!important}.no-results[data-v-4eeb92d2]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-4eeb92d2]{flex:none} diff --git a/assets/summary1.B7mzdmu-.png b/assets/summary1.B7mzdmu-.png new file mode 100644 index 00000000..37d52cb4 Binary files /dev/null and b/assets/summary1.B7mzdmu-.png differ diff --git a/assets/update-dialog.6NED8STH.png b/assets/update-dialog.6NED8STH.png new file mode 100644 index 00000000..64140574 Binary files /dev/null and b/assets/update-dialog.6NED8STH.png differ diff --git a/assets/update-plugin.QaxP19qF.png b/assets/update-plugin.QaxP19qF.png new file mode 100644 index 00000000..313ed589 Binary files /dev/null and b/assets/update-plugin.QaxP19qF.png differ diff --git a/assets/upload-cf.Du3A6DMK.png b/assets/upload-cf.Du3A6DMK.png new file mode 100644 index 00000000..ff96a4c9 Binary files /dev/null and b/assets/upload-cf.Du3A6DMK.png differ diff --git a/assets/usingpreload1.Ci_fdB50.png b/assets/usingpreload1.Ci_fdB50.png new file mode 100644 index 00000000..4fb96c69 Binary files /dev/null and b/assets/usingpreload1.Ci_fdB50.png differ diff --git a/assets/wait-split.DY23j374.png b/assets/wait-split.DY23j374.png new file mode 100644 index 00000000..442ec7be Binary files /dev/null and b/assets/wait-split.DY23j374.png differ diff --git a/assets/wxassetbundle.DrADi2AS.png b/assets/wxassetbundle.DrADi2AS.png new file mode 100644 index 00000000..88d7875a Binary files /dev/null and b/assets/wxassetbundle.DrADi2AS.png differ diff --git a/assets/wxassetbundleprovider1.BrJzXZd7.png b/assets/wxassetbundleprovider1.BrJzXZd7.png new file mode 100644 index 00000000..e4dcab35 Binary files /dev/null and b/assets/wxassetbundleprovider1.BrJzXZd7.png differ diff --git a/assets/wxassetbundleprovider2.DIWHTi9X.png b/assets/wxassetbundleprovider2.DIWHTi9X.png new file mode 100644 index 00000000..2b9efff2 Binary files /dev/null and b/assets/wxassetbundleprovider2.DIWHTi9X.png differ diff --git a/hashmap.json b/hashmap.json new file mode 100644 index 00000000..e945d9f7 --- /dev/null +++ b/hashmap.json @@ -0,0 +1 @@ +{"design_customurp.md":"DO3qEFih","design_opendata.md":"LqgzEtQr","design_perfmeasure.md":"DqQ7Xs1a","design_firstsceneoptimization.md":"CcSBIIZy","design_debugandexception.md":"B6v48M9a","design_backendservicestartup.md":"BfLKGEwG","design_evaluation.md":"CSX9uvMD","design_assetdescription.md":"5qrDTdVw","design_launchopera.md":"VmxdpFyu","design_customloading.md":"CIt3rPKd","changelog.md":"Jm0i_MoD","design_wx_sdk.md":"CBaKb55h","design_transform.md":"x98sGhu_","design_issueandcontact.md":"nMr6t1S1","design_datacdn.md":"CP-7QzjN","design_profile.md":"CWCGA8rU","design_developmentqalist.md":"DTehlE5h","design_devtoolsdomain.md":"BZk7ZQVg","design_filecache.md":"DaJotKv1","design_startup.md":"__rV3b8S","design_assetoptimization.md":"DD6FAQCd","design_salon.md":"BzNSLcNw","design_showcase.md":"DonZUX3q","design_optimizationperformence.md":"CrALocpx","design_wasmsplit.md":"WxEMJpKx","design_buildtemplate.md":"BwpsT2kQ","design_symbol.md":"DCwyi1Dw","design_wxfont.md":"-W-sW9eo","design_usingmemoryprofiler.md":"Bfk-VwRy","design_summary.md":"C5Wmwk6F","design_androidprofile.md":"DdtvteaF","design_guide.md":"2Tii1bAr","design_inputadaptation.md":"CYV3Uf9j","design_usingpreload.md":"YYInpzwD","design_optimizationmemory.md":"CqTeDkzA","design_instantgameguide.md":"5__8NzkS","design_usingnetworking.md":"BwIqduoZ","design_perfoptimization.md":"C-5U97w8","design_startupoptimization.md":"DHwW9GTU","design_fixscreen.md":"9f3koYcy","design_iosoptimization.md":"CvXFzPXD","design_video.md":"DUVWhAg-","design_performance-standard_perfmeasure_20230517.md":"B5V5KI6R","design_wasmwatermark.md":"C4-A8aK7","design_performance-standard_perfmeasure_old.md":"Beja5Gk0","readme.md":"B8Z9A7kF","index.md":"C0pbrLsL","design_renderoptimization.md":"D368ru2I","design_resourcesloading.md":"BKWzKO9M","design_usingaddressable.md":"758Zr0tY","design_webgl2.md":"C7mclE2P","design_reportstartupstat.md":"CcswZlo3","design_usingloader.md":"DBMrBC_O","design_issueforproduction.md":"DIdpWfBl","design_performancemonitor.md":"GX3ElIdy","design_launchoperadocument.md":"C4QbbkY9","design_audioandvideo.md":"B1u2EDqx","design_unityversion.md":"BsPD-TKi","design_unityprofiler.md":"BWh3E1Ho","design_sdkinstaller.md":"_y_ScH2A","design_update.md":"gfZSJS5M","design_customsdk.md":"BSt-btdV","design_compressedtexture.md":"TGKkGaTi","design_usingassetbundle.md":"DHBD80cj"} diff --git a/image/1599487200648-58660e36969cdf1f.jpeg b/image/1599487200648-58660e36969cdf1f.jpeg new file mode 100644 index 00000000..c2ea022f Binary files /dev/null and b/image/1599487200648-58660e36969cdf1f.jpeg differ diff --git a/image/1599487200648-64bc73971e42c578.jpeg b/image/1599487200648-64bc73971e42c578.jpeg new file mode 100644 index 00000000..99c374a2 Binary files /dev/null and b/image/1599487200648-64bc73971e42c578.jpeg differ diff --git a/image/1599487200648-9dba73df996b86d7.png b/image/1599487200648-9dba73df996b86d7.png new file mode 100644 index 00000000..564f3155 Binary files /dev/null and b/image/1599487200648-9dba73df996b86d7.png differ diff --git a/image/1599568661120-40380fa26fb35287.png b/image/1599568661120-40380fa26fb35287.png new file mode 100644 index 00000000..79ca7472 Binary files /dev/null and b/image/1599568661120-40380fa26fb35287.png differ diff --git a/image/IOSDevicePixelRatio.png b/image/IOSDevicePixelRatio.png new file mode 100644 index 00000000..3e856e22 Binary files /dev/null and b/image/IOSDevicePixelRatio.png differ diff --git a/image/WXFont.png b/image/WXFont.png new file mode 100644 index 00000000..9abeeb48 Binary files /dev/null and b/image/WXFont.png differ diff --git a/image/WXTemplate.png b/image/WXTemplate.png new file mode 100644 index 00000000..05b7e581 Binary files /dev/null and b/image/WXTemplate.png differ diff --git a/image/addPlugin.png b/image/addPlugin.png new file mode 100644 index 00000000..f4f84e4e Binary files /dev/null and b/image/addPlugin.png differ diff --git a/image/addressable10.png b/image/addressable10.png new file mode 100644 index 00000000..521288bd Binary files /dev/null and b/image/addressable10.png differ diff --git a/image/addressable2.png b/image/addressable2.png new file mode 100644 index 00000000..1ac8197f Binary files /dev/null and b/image/addressable2.png differ diff --git a/image/addressable3.png b/image/addressable3.png new file mode 100644 index 00000000..ed1732ac Binary files /dev/null and b/image/addressable3.png differ diff --git a/image/addressable4.png b/image/addressable4.png new file mode 100644 index 00000000..387867e7 Binary files /dev/null and b/image/addressable4.png differ diff --git a/image/addressable5.png b/image/addressable5.png new file mode 100644 index 00000000..9600a3b2 Binary files /dev/null and b/image/addressable5.png differ diff --git a/image/addressable7.png b/image/addressable7.png new file mode 100644 index 00000000..2b434f9d Binary files /dev/null and b/image/addressable7.png differ diff --git a/image/addressable9.png b/image/addressable9.png new file mode 100644 index 00000000..f3b32594 Binary files /dev/null and b/image/addressable9.png differ diff --git a/image/androidprofile1.jpg b/image/androidprofile1.jpg new file mode 100644 index 00000000..b6648085 Binary files /dev/null and b/image/androidprofile1.jpg differ diff --git a/image/androidprofile1.png b/image/androidprofile1.png new file mode 100644 index 00000000..5b46c2f9 Binary files /dev/null and b/image/androidprofile1.png differ diff --git a/image/androidprofile2.png b/image/androidprofile2.png new file mode 100644 index 00000000..b1f17645 Binary files /dev/null and b/image/androidprofile2.png differ diff --git a/image/androidprofile3.png b/image/androidprofile3.png new file mode 100644 index 00000000..ba9dc03a Binary files /dev/null and b/image/androidprofile3.png differ diff --git a/image/androidprofile4.png b/image/androidprofile4.png new file mode 100644 index 00000000..bd9aa822 Binary files /dev/null and b/image/androidprofile4.png differ diff --git a/image/androidprofile5.png b/image/androidprofile5.png new file mode 100644 index 00000000..7c6a7f1f Binary files /dev/null and b/image/androidprofile5.png differ diff --git a/image/asset-optimization/asset-analysis-window.png b/image/asset-optimization/asset-analysis-window.png new file mode 100644 index 00000000..06344481 Binary files /dev/null and b/image/asset-optimization/asset-analysis-window.png differ diff --git a/image/asset-optimization/change-format.png b/image/asset-optimization/change-format.png new file mode 100644 index 00000000..1b995b82 Binary files /dev/null and b/image/asset-optimization/change-format.png differ diff --git a/image/asset-optimization/change-max-size.png b/image/asset-optimization/change-max-size.png new file mode 100644 index 00000000..93399134 Binary files /dev/null and b/image/asset-optimization/change-max-size.png differ diff --git a/image/asset-optimization/entrance.png b/image/asset-optimization/entrance.png new file mode 100644 index 00000000..1998dcb1 Binary files /dev/null and b/image/asset-optimization/entrance.png differ diff --git a/image/assetbundle/assetbundle-scene.png b/image/assetbundle/assetbundle-scene.png new file mode 100644 index 00000000..90f7cc3b Binary files /dev/null and b/image/assetbundle/assetbundle-scene.png differ diff --git a/image/assetbundle/assetbundle-unnormal-memory.png b/image/assetbundle/assetbundle-unnormal-memory.png new file mode 100644 index 00000000..c61ff3d2 Binary files /dev/null and b/image/assetbundle/assetbundle-unnormal-memory.png differ diff --git a/image/assetbundle/normal-assetbundle-memory.png b/image/assetbundle/normal-assetbundle-memory.png new file mode 100644 index 00000000..f85951cf Binary files /dev/null and b/image/assetbundle/normal-assetbundle-memory.png differ diff --git a/image/assetbundle/set-bundlename.png b/image/assetbundle/set-bundlename.png new file mode 100644 index 00000000..2104a5fb Binary files /dev/null and b/image/assetbundle/set-bundlename.png differ diff --git a/image/assetbundle/wxassetbundle.png b/image/assetbundle/wxassetbundle.png new file mode 100644 index 00000000..88d7875a Binary files /dev/null and b/image/assetbundle/wxassetbundle.png differ diff --git a/image/assets.png b/image/assets.png new file mode 100644 index 00000000..2b2b7892 Binary files /dev/null and b/image/assets.png differ diff --git a/image/assets2.png b/image/assets2.png new file mode 100644 index 00000000..0d77e11e Binary files /dev/null and b/image/assets2.png differ diff --git a/image/auth_plugin.png b/image/auth_plugin.png new file mode 100644 index 00000000..8b52b4e6 Binary files /dev/null and b/image/auth_plugin.png differ diff --git a/image/buildtemplateprocess.png b/image/buildtemplateprocess.png new file mode 100644 index 00000000..c0b7fc6f Binary files /dev/null and b/image/buildtemplateprocess.png differ diff --git a/image/cache_path.png b/image/cache_path.png new file mode 100644 index 00000000..3eed4d54 Binary files /dev/null and b/image/cache_path.png differ diff --git a/image/cf/call-cf-for-test.jpg b/image/cf/call-cf-for-test.jpg new file mode 100644 index 00000000..a792aaef Binary files /dev/null and b/image/cf/call-cf-for-test.jpg differ diff --git a/image/cf/cf-free.jpg b/image/cf/cf-free.jpg new file mode 100644 index 00000000..8bbb545a Binary files /dev/null and b/image/cf/cf-free.jpg differ diff --git a/image/cf/cf-overview.png b/image/cf/cf-overview.png new file mode 100644 index 00000000..d74762d5 Binary files /dev/null and b/image/cf/cf-overview.png differ diff --git a/image/cf/choose-env.jpg b/image/cf/choose-env.jpg new file mode 100644 index 00000000..7a8404a2 Binary files /dev/null and b/image/cf/choose-env.jpg differ diff --git a/image/cf/init-cf-proj.jpg b/image/cf/init-cf-proj.jpg new file mode 100644 index 00000000..7db7b9fb Binary files /dev/null and b/image/cf/init-cf-proj.jpg differ diff --git a/image/cf/open-cf.jpg b/image/cf/open-cf.jpg new file mode 100644 index 00000000..b362c92b Binary files /dev/null and b/image/cf/open-cf.jpg differ diff --git a/image/cf/upload-cf.png b/image/cf/upload-cf.png new file mode 100644 index 00000000..ff96a4c9 Binary files /dev/null and b/image/cf/upload-cf.png differ diff --git a/image/cm-texture1.png b/image/cm-texture1.png new file mode 100644 index 00000000..681e5310 Binary files /dev/null and b/image/cm-texture1.png differ diff --git a/image/compressedTexture01.png b/image/compressedTexture01.png new file mode 100644 index 00000000..a5bb5d23 Binary files /dev/null and b/image/compressedTexture01.png differ diff --git a/image/compressedTexture02.png b/image/compressedTexture02.png new file mode 100644 index 00000000..8de17106 Binary files /dev/null and b/image/compressedTexture02.png differ diff --git a/image/contentencoding_error.png b/image/contentencoding_error.png new file mode 100644 index 00000000..a22e7181 Binary files /dev/null and b/image/contentencoding_error.png differ diff --git a/image/cors_istrusted.png b/image/cors_istrusted.png new file mode 100644 index 00000000..72731b17 Binary files /dev/null and b/image/cors_istrusted.png differ diff --git a/image/courgette.log b/image/courgette.log new file mode 100644 index 00000000..e69de29b diff --git a/image/coverview_loading.png b/image/coverview_loading.png new file mode 100644 index 00000000..4a402209 Binary files /dev/null and b/image/coverview_loading.png differ diff --git a/image/custom_urp_case1.jpeg b/image/custom_urp_case1.jpeg new file mode 100644 index 00000000..29395ff4 Binary files /dev/null and b/image/custom_urp_case1.jpeg differ diff --git a/image/custom_urp_case2.jpeg b/image/custom_urp_case2.jpeg new file mode 100644 index 00000000..9af3c9d1 Binary files /dev/null and b/image/custom_urp_case2.jpeg differ diff --git a/image/custom_urp_pkgs.png b/image/custom_urp_pkgs.png new file mode 100644 index 00000000..6590fe1a Binary files /dev/null and b/image/custom_urp_pkgs.png differ diff --git a/image/debugexception1.png b/image/debugexception1.png new file mode 100644 index 00000000..7993f2d8 Binary files /dev/null and b/image/debugexception1.png differ diff --git a/image/debugexception2.png b/image/debugexception2.png new file mode 100644 index 00000000..c848879c Binary files /dev/null and b/image/debugexception2.png differ diff --git a/image/debugexception3.png b/image/debugexception3.png new file mode 100644 index 00000000..9f0a28c8 Binary files /dev/null and b/image/debugexception3.png differ diff --git a/image/debugexception4.png b/image/debugexception4.png new file mode 100644 index 00000000..b4c60d77 Binary files /dev/null and b/image/debugexception4.png differ diff --git a/image/debugexception5.png b/image/debugexception5.png new file mode 100644 index 00000000..945bb0ab Binary files /dev/null and b/image/debugexception5.png differ diff --git a/image/debugexception6.png b/image/debugexception6.png new file mode 100644 index 00000000..0e9d577a Binary files /dev/null and b/image/debugexception6.png differ diff --git a/image/debugexception7.png b/image/debugexception7.png new file mode 100644 index 00000000..caf34f9c Binary files /dev/null and b/image/debugexception7.png differ diff --git a/image/debugexception8.png b/image/debugexception8.png new file mode 100644 index 00000000..d8e15dc4 Binary files /dev/null and b/image/debugexception8.png differ diff --git a/image/debugexception9.png b/image/debugexception9.png new file mode 100644 index 00000000..4a66ddbb Binary files /dev/null and b/image/debugexception9.png differ diff --git a/image/default_loading.jpg b/image/default_loading.jpg new file mode 100644 index 00000000..a20a4c0a Binary files /dev/null and b/image/default_loading.jpg differ diff --git a/image/devtools_network.png b/image/devtools_network.png new file mode 100644 index 00000000..c6c64610 Binary files /dev/null and b/image/devtools_network.png differ diff --git a/image/devtools_preview.png b/image/devtools_preview.png new file mode 100644 index 00000000..4866656f Binary files /dev/null and b/image/devtools_preview.png differ diff --git a/image/evaluation1.png b/image/evaluation1.png new file mode 100644 index 00000000..fa53a7e1 Binary files /dev/null and b/image/evaluation1.png differ diff --git a/image/export.png b/image/export.png new file mode 100644 index 00000000..56736e4c Binary files /dev/null and b/image/export.png differ diff --git a/image/file_cache.png b/image/file_cache.png new file mode 100644 index 00000000..f7862d5e Binary files /dev/null and b/image/file_cache.png differ diff --git a/image/firstscene/benchmarkprofile.png b/image/firstscene/benchmarkprofile.png new file mode 100644 index 00000000..d6a82b3f Binary files /dev/null and b/image/firstscene/benchmarkprofile.png differ diff --git a/image/firstscene/chromeload.png b/image/firstscene/chromeload.png new file mode 100644 index 00000000..45a72fc8 Binary files /dev/null and b/image/firstscene/chromeload.png differ diff --git a/image/firstscene/profile.png b/image/firstscene/profile.png new file mode 100644 index 00000000..c5fdb58f Binary files /dev/null and b/image/firstscene/profile.png differ diff --git a/image/firstscene/stop.png b/image/firstscene/stop.png new file mode 100644 index 00000000..c7d075e3 Binary files /dev/null and b/image/firstscene/stop.png differ diff --git a/image/firstscene/stopprofile.png b/image/firstscene/stopprofile.png new file mode 100644 index 00000000..347d00ac Binary files /dev/null and b/image/firstscene/stopprofile.png differ diff --git a/image/guide/guide1.png b/image/guide/guide1.png new file mode 100644 index 00000000..d7fcdba3 Binary files /dev/null and b/image/guide/guide1.png differ diff --git a/image/howtodebug1.png b/image/howtodebug1.png new file mode 100644 index 00000000..8317b0e8 Binary files /dev/null and b/image/howtodebug1.png differ diff --git a/image/instantgame/20220913-174523.png b/image/instantgame/20220913-174523.png new file mode 100644 index 00000000..f7b391f4 Binary files /dev/null and b/image/instantgame/20220913-174523.png differ diff --git a/image/instantgame/20220913-174524.png b/image/instantgame/20220913-174524.png new file mode 100644 index 00000000..3970175b Binary files /dev/null and b/image/instantgame/20220913-174524.png differ diff --git a/image/instantgame/20220913-174525.png b/image/instantgame/20220913-174525.png new file mode 100644 index 00000000..e7eed38e Binary files /dev/null and b/image/instantgame/20220913-174525.png differ diff --git a/image/instantgame/20220914-110716.png b/image/instantgame/20220914-110716.png new file mode 100644 index 00000000..d1d368b2 Binary files /dev/null and b/image/instantgame/20220914-110716.png differ diff --git a/image/instantgame/20220914-114538.png b/image/instantgame/20220914-114538.png new file mode 100644 index 00000000..24aee969 Binary files /dev/null and b/image/instantgame/20220914-114538.png differ diff --git a/image/instantgame/20220914-143256.png b/image/instantgame/20220914-143256.png new file mode 100644 index 00000000..5d47e3fb Binary files /dev/null and b/image/instantgame/20220914-143256.png differ diff --git a/image/instantgame/20220914-151209.png b/image/instantgame/20220914-151209.png new file mode 100644 index 00000000..e7101f95 Binary files /dev/null and b/image/instantgame/20220914-151209.png differ diff --git a/image/instantgame/20220914-151847.png b/image/instantgame/20220914-151847.png new file mode 100644 index 00000000..5b295043 Binary files /dev/null and b/image/instantgame/20220914-151847.png differ diff --git a/image/instantgame/20220914-152444.png b/image/instantgame/20220914-152444.png new file mode 100644 index 00000000..3b2ae2d1 Binary files /dev/null and b/image/instantgame/20220914-152444.png differ diff --git a/image/instantgame/20220915-203808.png b/image/instantgame/20220915-203808.png new file mode 100644 index 00000000..a6339ee0 Binary files /dev/null and b/image/instantgame/20220915-203808.png differ diff --git a/image/instantgame/20220915-203809.png b/image/instantgame/20220915-203809.png new file mode 100644 index 00000000..b86fc93e Binary files /dev/null and b/image/instantgame/20220915-203809.png differ diff --git a/image/instantgame/20220915-203810.png b/image/instantgame/20220915-203810.png new file mode 100644 index 00000000..760b71b4 Binary files /dev/null and b/image/instantgame/20220915-203810.png differ diff --git a/image/instantgame/20220915-203811.png b/image/instantgame/20220915-203811.png new file mode 100644 index 00000000..495251e0 Binary files /dev/null and b/image/instantgame/20220915-203811.png differ diff --git a/image/iosoptimization1.png b/image/iosoptimization1.png new file mode 100644 index 00000000..36f0f738 Binary files /dev/null and b/image/iosoptimization1.png differ diff --git a/image/iosoptimization2.png b/image/iosoptimization2.png new file mode 100644 index 00000000..7f72b68f Binary files /dev/null and b/image/iosoptimization2.png differ diff --git a/image/iosoptimization3.png b/image/iosoptimization3.png new file mode 100644 index 00000000..ce3a9666 Binary files /dev/null and b/image/iosoptimization3.png differ diff --git a/image/issueandcontact1.png b/image/issueandcontact1.png new file mode 100644 index 00000000..27188400 Binary files /dev/null and b/image/issueandcontact1.png differ diff --git a/image/issueandcontact2.png b/image/issueandcontact2.png new file mode 100644 index 00000000..04444e57 Binary files /dev/null and b/image/issueandcontact2.png differ diff --git a/image/issueforproduction1.png b/image/issueforproduction1.png new file mode 100644 index 00000000..55fa1245 Binary files /dev/null and b/image/issueforproduction1.png differ diff --git a/image/issueforproduction2.png b/image/issueforproduction2.png new file mode 100644 index 00000000..acff4873 Binary files /dev/null and b/image/issueforproduction2.png differ diff --git a/image/issueforproduction3.png b/image/issueforproduction3.png new file mode 100644 index 00000000..164bcacf Binary files /dev/null and b/image/issueforproduction3.png differ diff --git a/image/issueforproduction4.png b/image/issueforproduction4.png new file mode 100644 index 00000000..d2f7eb09 Binary files /dev/null and b/image/issueforproduction4.png differ diff --git a/image/launch-opera/app-fxzg.jpeg b/image/launch-opera/app-fxzg.jpeg new file mode 100644 index 00000000..74be75fb Binary files /dev/null and b/image/launch-opera/app-fxzg.jpeg differ diff --git a/image/launch-opera/app-jhywl.jpeg b/image/launch-opera/app-jhywl.jpeg new file mode 100644 index 00000000..3919ac65 Binary files /dev/null and b/image/launch-opera/app-jhywl.jpeg differ diff --git a/image/launch-opera/app-mmdys.jpeg b/image/launch-opera/app-mmdys.jpeg new file mode 100644 index 00000000..cd1bd49a Binary files /dev/null and b/image/launch-opera/app-mmdys.jpeg differ diff --git a/image/launch-opera/demo-video.mp4 b/image/launch-opera/demo-video.mp4 new file mode 100644 index 00000000..74ea196e Binary files /dev/null and b/image/launch-opera/demo-video.mp4 differ diff --git a/image/launch-opera/image-0.png b/image/launch-opera/image-0.png new file mode 100644 index 00000000..63015a33 Binary files /dev/null and b/image/launch-opera/image-0.png differ diff --git a/image/launch-opera/image-1.png b/image/launch-opera/image-1.png new file mode 100644 index 00000000..c8275dd6 Binary files /dev/null and b/image/launch-opera/image-1.png differ diff --git a/image/launch.png b/image/launch.png new file mode 100644 index 00000000..7fa11c08 Binary files /dev/null and b/image/launch.png differ diff --git a/image/launch1.png b/image/launch1.png new file mode 100644 index 00000000..fb831ec3 Binary files /dev/null and b/image/launch1.png differ diff --git a/image/loading_default.png b/image/loading_default.png new file mode 100644 index 00000000..46e903b7 Binary files /dev/null and b/image/loading_default.png differ diff --git a/image/loading_demo.jpg b/image/loading_demo.jpg new file mode 100644 index 00000000..715c69bf Binary files /dev/null and b/image/loading_demo.jpg differ diff --git a/image/loading_design.jpg b/image/loading_design.jpg new file mode 100644 index 00000000..8a760481 Binary files /dev/null and b/image/loading_design.jpg differ diff --git a/image/maineditor.png b/image/maineditor.png new file mode 100644 index 00000000..eac04f3e Binary files /dev/null and b/image/maineditor.png differ diff --git a/image/memoryprofiler1.png b/image/memoryprofiler1.png new file mode 100644 index 00000000..644f5c23 Binary files /dev/null and b/image/memoryprofiler1.png differ diff --git a/image/memoryprofiler2.png b/image/memoryprofiler2.png new file mode 100644 index 00000000..6c829438 Binary files /dev/null and b/image/memoryprofiler2.png differ diff --git a/image/memoryprofiler3.png b/image/memoryprofiler3.png new file mode 100644 index 00000000..c6ef091d Binary files /dev/null and b/image/memoryprofiler3.png differ diff --git a/image/memoryprofiler4.png b/image/memoryprofiler4.png new file mode 100644 index 00000000..736fed7e Binary files /dev/null and b/image/memoryprofiler4.png differ diff --git a/image/memoryprofiler5.png b/image/memoryprofiler5.png new file mode 100644 index 00000000..9637011f Binary files /dev/null and b/image/memoryprofiler5.png differ diff --git a/image/monitor/detail-log.png b/image/monitor/detail-log.png new file mode 100644 index 00000000..582e912f Binary files /dev/null and b/image/monitor/detail-log.png differ diff --git a/image/monitor/monitor-console.png b/image/monitor/monitor-console.png new file mode 100644 index 00000000..b2f80525 Binary files /dev/null and b/image/monitor/monitor-console.png differ diff --git a/image/monitor/monitor-dialog.png b/image/monitor/monitor-dialog.png new file mode 100644 index 00000000..865142ac Binary files /dev/null and b/image/monitor/monitor-dialog.png differ diff --git a/image/monitor/network-profile.png b/image/monitor/network-profile.png new file mode 100644 index 00000000..a7c6421e Binary files /dev/null and b/image/monitor/network-profile.png differ diff --git a/image/mp_addplugin.png b/image/mp_addplugin.png new file mode 100644 index 00000000..e6a85ff2 Binary files /dev/null and b/image/mp_addplugin.png differ diff --git a/image/o1.png b/image/o1.png new file mode 100644 index 00000000..a11ffb76 Binary files /dev/null and b/image/o1.png differ diff --git a/image/o2.png b/image/o2.png new file mode 100644 index 00000000..27b0a8b0 Binary files /dev/null and b/image/o2.png differ diff --git a/image/o3.png b/image/o3.png new file mode 100644 index 00000000..f712b438 Binary files /dev/null and b/image/o3.png differ diff --git a/image/opendata.png b/image/opendata.png new file mode 100644 index 00000000..17f5c246 Binary files /dev/null and b/image/opendata.png differ diff --git a/image/opendata/demo1.jpeg b/image/opendata/demo1.jpeg new file mode 100644 index 00000000..8a27caf7 Binary files /dev/null and b/image/opendata/demo1.jpeg differ diff --git a/image/opendata/demo2.jpeg b/image/opendata/demo2.jpeg new file mode 100644 index 00000000..74c3486f Binary files /dev/null and b/image/opendata/demo2.jpeg differ diff --git a/image/opendata/demo3.jpeg b/image/opendata/demo3.jpeg new file mode 100644 index 00000000..c9b30733 Binary files /dev/null and b/image/opendata/demo3.jpeg differ diff --git a/image/opendata/demo4.jpeg b/image/opendata/demo4.jpeg new file mode 100644 index 00000000..ba84951d Binary files /dev/null and b/image/opendata/demo4.jpeg differ diff --git a/image/opendata/demo5.jpeg b/image/opendata/demo5.jpeg new file mode 100644 index 00000000..d2d9461c Binary files /dev/null and b/image/opendata/demo5.jpeg differ diff --git a/image/opendata/demo6.jpeg b/image/opendata/demo6.jpeg new file mode 100644 index 00000000..c8c36233 Binary files /dev/null and b/image/opendata/demo6.jpeg differ diff --git a/image/opendata/demo7.jpeg b/image/opendata/demo7.jpeg new file mode 100644 index 00000000..5e6a1914 Binary files /dev/null and b/image/opendata/demo7.jpeg differ diff --git a/image/opendataframework.png b/image/opendataframework.png new file mode 100644 index 00000000..5b6de615 Binary files /dev/null and b/image/opendataframework.png differ diff --git a/image/optimizationMemory1.png b/image/optimizationMemory1.png new file mode 100644 index 00000000..0fbd6c8e Binary files /dev/null and b/image/optimizationMemory1.png differ diff --git a/image/optimizationMemory10.png b/image/optimizationMemory10.png new file mode 100644 index 00000000..9e695992 Binary files /dev/null and b/image/optimizationMemory10.png differ diff --git a/image/optimizationMemory11.png b/image/optimizationMemory11.png new file mode 100644 index 00000000..bbb40364 Binary files /dev/null and b/image/optimizationMemory11.png differ diff --git a/image/optimizationMemory12.png b/image/optimizationMemory12.png new file mode 100644 index 00000000..3371a250 Binary files /dev/null and b/image/optimizationMemory12.png differ diff --git a/image/optimizationMemory2.png b/image/optimizationMemory2.png new file mode 100644 index 00000000..d7db5a36 Binary files /dev/null and b/image/optimizationMemory2.png differ diff --git a/image/optimizationMemory3.png b/image/optimizationMemory3.png new file mode 100644 index 00000000..099dfb7f Binary files /dev/null and b/image/optimizationMemory3.png differ diff --git a/image/optimizationMemory4.png b/image/optimizationMemory4.png new file mode 100644 index 00000000..df480587 Binary files /dev/null and b/image/optimizationMemory4.png differ diff --git a/image/optimizationMemory5.png b/image/optimizationMemory5.png new file mode 100644 index 00000000..3b79874b Binary files /dev/null and b/image/optimizationMemory5.png differ diff --git a/image/optimizationMemory6.jpg b/image/optimizationMemory6.jpg new file mode 100644 index 00000000..d4441098 Binary files /dev/null and b/image/optimizationMemory6.jpg differ diff --git a/image/optimizationMemory6.png b/image/optimizationMemory6.png new file mode 100644 index 00000000..c09f153d Binary files /dev/null and b/image/optimizationMemory6.png differ diff --git a/image/optimizationperformence1.png b/image/optimizationperformence1.png new file mode 100644 index 00000000..1f122398 Binary files /dev/null and b/image/optimizationperformence1.png differ diff --git a/image/optimizationperformence2.png b/image/optimizationperformence2.png new file mode 100644 index 00000000..95174128 Binary files /dev/null and b/image/optimizationperformence2.png differ diff --git a/image/perfmeasure1.png b/image/perfmeasure1.png new file mode 100644 index 00000000..5a6788c6 Binary files /dev/null and b/image/perfmeasure1.png differ diff --git a/image/perfmeasure2.png b/image/perfmeasure2.png new file mode 100644 index 00000000..ca02a472 Binary files /dev/null and b/image/perfmeasure2.png differ diff --git a/image/perfmeasure3.png b/image/perfmeasure3.png new file mode 100644 index 00000000..a1ea4e37 Binary files /dev/null and b/image/perfmeasure3.png differ diff --git a/image/perfmeasure4.png b/image/perfmeasure4.png new file mode 100644 index 00000000..88c95687 Binary files /dev/null and b/image/perfmeasure4.png differ diff --git a/image/performance-standard/20230517/android_running_performance.png b/image/performance-standard/20230517/android_running_performance.png new file mode 100644 index 00000000..41bd1126 Binary files /dev/null and b/image/performance-standard/20230517/android_running_performance.png differ diff --git a/image/performance-standard/20230517/android_start_performance.png b/image/performance-standard/20230517/android_start_performance.png new file mode 100644 index 00000000..6a6f4f09 Binary files /dev/null and b/image/performance-standard/20230517/android_start_performance.png differ diff --git a/image/performance-standard/20230517/ios_running_performance.png b/image/performance-standard/20230517/ios_running_performance.png new file mode 100644 index 00000000..8e94e70a Binary files /dev/null and b/image/performance-standard/20230517/ios_running_performance.png differ diff --git a/image/performance-standard/20230517/ios_start_performance.png b/image/performance-standard/20230517/ios_start_performance.png new file mode 100644 index 00000000..2917a6f9 Binary files /dev/null and b/image/performance-standard/20230517/ios_start_performance.png differ diff --git a/image/performance-standard/20240813/android_running_performance.png b/image/performance-standard/20240813/android_running_performance.png new file mode 100644 index 00000000..0f498c8f Binary files /dev/null and b/image/performance-standard/20240813/android_running_performance.png differ diff --git a/image/performance-standard/20240813/android_start_performance.png b/image/performance-standard/20240813/android_start_performance.png new file mode 100644 index 00000000..aa945d2c Binary files /dev/null and b/image/performance-standard/20240813/android_start_performance.png differ diff --git a/image/performance-standard/20240813/ios_running_performance.png b/image/performance-standard/20240813/ios_running_performance.png new file mode 100644 index 00000000..7e62f709 Binary files /dev/null and b/image/performance-standard/20240813/ios_running_performance.png differ diff --git a/image/performance-standard/20240813/ios_start_performance.png b/image/performance-standard/20240813/ios_start_performance.png new file mode 100644 index 00000000..fa0e5044 Binary files /dev/null and b/image/performance-standard/20240813/ios_start_performance.png differ diff --git a/image/profile1.png b/image/profile1.png new file mode 100644 index 00000000..e6118036 Binary files /dev/null and b/image/profile1.png differ diff --git a/image/profile2.png b/image/profile2.png new file mode 100644 index 00000000..67e6d9aa Binary files /dev/null and b/image/profile2.png differ diff --git a/image/profile3.png b/image/profile3.png new file mode 100644 index 00000000..636aeb94 Binary files /dev/null and b/image/profile3.png differ diff --git a/image/profile4.png b/image/profile4.png new file mode 100644 index 00000000..f54846a7 Binary files /dev/null and b/image/profile4.png differ diff --git a/image/rank-demo/addplugin.png b/image/rank-demo/addplugin.png new file mode 100644 index 00000000..b60c7fe9 Binary files /dev/null and b/image/rank-demo/addplugin.png differ diff --git a/image/readme_err1.jpeg b/image/readme_err1.jpeg new file mode 100644 index 00000000..8f86e1c5 Binary files /dev/null and b/image/readme_err1.jpeg differ diff --git a/image/readme_err2.jpeg b/image/readme_err2.jpeg new file mode 100644 index 00000000..8a39a6bf Binary files /dev/null and b/image/readme_err2.jpeg differ diff --git a/image/readme_err3.jpeg b/image/readme_err3.jpeg new file mode 100644 index 00000000..c5a396c8 Binary files /dev/null and b/image/readme_err3.jpeg differ diff --git a/image/reportstartupstat1.png b/image/reportstartupstat1.png new file mode 100644 index 00000000..95c7697f Binary files /dev/null and b/image/reportstartupstat1.png differ diff --git a/image/reportstartupstat2.png b/image/reportstartupstat2.png new file mode 100644 index 00000000..e4a961c5 Binary files /dev/null and b/image/reportstartupstat2.png differ diff --git a/image/reportstartupstat3.png b/image/reportstartupstat3.png new file mode 100644 index 00000000..62f02e54 Binary files /dev/null and b/image/reportstartupstat3.png differ diff --git a/image/saveArea.png b/image/saveArea.png new file mode 100644 index 00000000..ea7e6173 Binary files /dev/null and b/image/saveArea.png differ diff --git a/image/scene.png b/image/scene.png new file mode 100644 index 00000000..dbd88599 Binary files /dev/null and b/image/scene.png differ diff --git a/image/showcase1.png b/image/showcase1.png new file mode 100644 index 00000000..15cb9443 Binary files /dev/null and b/image/showcase1.png differ diff --git a/image/showcase10.png b/image/showcase10.png new file mode 100644 index 00000000..e40dc7b0 Binary files /dev/null and b/image/showcase10.png differ diff --git a/image/showcase11.png b/image/showcase11.png new file mode 100644 index 00000000..ca3d9b27 Binary files /dev/null and b/image/showcase11.png differ diff --git a/image/showcase12.png b/image/showcase12.png new file mode 100644 index 00000000..b2b70531 Binary files /dev/null and b/image/showcase12.png differ diff --git a/image/showcase13.png b/image/showcase13.png new file mode 100644 index 00000000..05a8ce13 Binary files /dev/null and b/image/showcase13.png differ diff --git a/image/showcase14.png b/image/showcase14.png new file mode 100644 index 00000000..ab0e2bf8 Binary files /dev/null and b/image/showcase14.png differ diff --git a/image/showcase15.png b/image/showcase15.png new file mode 100644 index 00000000..35c80487 Binary files /dev/null and b/image/showcase15.png differ diff --git a/image/showcase16.png b/image/showcase16.png new file mode 100644 index 00000000..96beb0a1 Binary files /dev/null and b/image/showcase16.png differ diff --git a/image/showcase17.png b/image/showcase17.png new file mode 100644 index 00000000..b7ad143e Binary files /dev/null and b/image/showcase17.png differ diff --git a/image/showcase18.png b/image/showcase18.png new file mode 100644 index 00000000..58e3a525 Binary files /dev/null and b/image/showcase18.png differ diff --git a/image/showcase19.png b/image/showcase19.png new file mode 100644 index 00000000..1ed53e90 Binary files /dev/null and b/image/showcase19.png differ diff --git a/image/showcase2.png b/image/showcase2.png new file mode 100644 index 00000000..54b0159a Binary files /dev/null and b/image/showcase2.png differ diff --git a/image/showcase20.png b/image/showcase20.png new file mode 100644 index 00000000..2d280b70 Binary files /dev/null and b/image/showcase20.png differ diff --git a/image/showcase21.png b/image/showcase21.png new file mode 100644 index 00000000..e9790a33 Binary files /dev/null and b/image/showcase21.png differ diff --git a/image/showcase22.png b/image/showcase22.png new file mode 100644 index 00000000..50799792 Binary files /dev/null and b/image/showcase22.png differ diff --git a/image/showcase23.png b/image/showcase23.png new file mode 100644 index 00000000..1e7d184e Binary files /dev/null and b/image/showcase23.png differ diff --git a/image/showcase24.png b/image/showcase24.png new file mode 100644 index 00000000..cdf2a4e5 Binary files /dev/null and b/image/showcase24.png differ diff --git a/image/showcase25.png b/image/showcase25.png new file mode 100644 index 00000000..6e0e7578 Binary files /dev/null and b/image/showcase25.png differ diff --git a/image/showcase26.png b/image/showcase26.png new file mode 100644 index 00000000..8252bc13 Binary files /dev/null and b/image/showcase26.png differ diff --git a/image/showcase27.png b/image/showcase27.png new file mode 100644 index 00000000..3d27e441 Binary files /dev/null and b/image/showcase27.png differ diff --git a/image/showcase28.png b/image/showcase28.png new file mode 100644 index 00000000..9c978078 Binary files /dev/null and b/image/showcase28.png differ diff --git a/image/showcase29.png b/image/showcase29.png new file mode 100644 index 00000000..38388198 Binary files /dev/null and b/image/showcase29.png differ diff --git a/image/showcase3.png b/image/showcase3.png new file mode 100644 index 00000000..45e83695 Binary files /dev/null and b/image/showcase3.png differ diff --git a/image/showcase30.png b/image/showcase30.png new file mode 100644 index 00000000..33095a2c Binary files /dev/null and b/image/showcase30.png differ diff --git a/image/showcase31.png b/image/showcase31.png new file mode 100644 index 00000000..faa6817d Binary files /dev/null and b/image/showcase31.png differ diff --git a/image/showcase32.png b/image/showcase32.png new file mode 100644 index 00000000..b7537b9a Binary files /dev/null and b/image/showcase32.png differ diff --git a/image/showcase33.png b/image/showcase33.png new file mode 100644 index 00000000..db7c7949 Binary files /dev/null and b/image/showcase33.png differ diff --git a/image/showcase34.png b/image/showcase34.png new file mode 100644 index 00000000..835ba645 Binary files /dev/null and b/image/showcase34.png differ diff --git a/image/showcase35.jpeg b/image/showcase35.jpeg new file mode 100644 index 00000000..8346bf47 Binary files /dev/null and b/image/showcase35.jpeg differ diff --git a/image/showcase36.jpeg b/image/showcase36.jpeg new file mode 100644 index 00000000..7e24427f Binary files /dev/null and b/image/showcase36.jpeg differ diff --git a/image/showcase37.jpeg b/image/showcase37.jpeg new file mode 100644 index 00000000..a4f53e09 Binary files /dev/null and b/image/showcase37.jpeg differ diff --git a/image/showcase38.jpeg b/image/showcase38.jpeg new file mode 100644 index 00000000..878100f6 Binary files /dev/null and b/image/showcase38.jpeg differ diff --git a/image/showcase39.jpeg b/image/showcase39.jpeg new file mode 100644 index 00000000..5ea0bc13 Binary files /dev/null and b/image/showcase39.jpeg differ diff --git a/image/showcase4.jpg b/image/showcase4.jpg new file mode 100644 index 00000000..9343a8e7 Binary files /dev/null and b/image/showcase4.jpg differ diff --git a/image/showcase40.jpeg b/image/showcase40.jpeg new file mode 100644 index 00000000..67874d0c Binary files /dev/null and b/image/showcase40.jpeg differ diff --git a/image/showcase41.jpeg b/image/showcase41.jpeg new file mode 100644 index 00000000..94189224 Binary files /dev/null and b/image/showcase41.jpeg differ diff --git a/image/showcase42.jpeg b/image/showcase42.jpeg new file mode 100644 index 00000000..1fba0001 Binary files /dev/null and b/image/showcase42.jpeg differ diff --git a/image/showcase43.jpeg b/image/showcase43.jpeg new file mode 100644 index 00000000..2e51e3ce Binary files /dev/null and b/image/showcase43.jpeg differ diff --git a/image/showcase44.jpeg b/image/showcase44.jpeg new file mode 100644 index 00000000..9030b52b Binary files /dev/null and b/image/showcase44.jpeg differ diff --git a/image/showcase45.png b/image/showcase45.png new file mode 100644 index 00000000..11b34b31 Binary files /dev/null and b/image/showcase45.png differ diff --git a/image/showcase47.png b/image/showcase47.png new file mode 100644 index 00000000..b710d9d5 Binary files /dev/null and b/image/showcase47.png differ diff --git a/image/showcase5.png b/image/showcase5.png new file mode 100644 index 00000000..c40b5f30 Binary files /dev/null and b/image/showcase5.png differ diff --git a/image/showcase6.png b/image/showcase6.png new file mode 100644 index 00000000..9e38b5a1 Binary files /dev/null and b/image/showcase6.png differ diff --git a/image/showcase7.png b/image/showcase7.png new file mode 100644 index 00000000..c2194c0e Binary files /dev/null and b/image/showcase7.png differ diff --git a/image/showcase8.png b/image/showcase8.png new file mode 100644 index 00000000..8f21eb07 Binary files /dev/null and b/image/showcase8.png differ diff --git a/image/showcase9.png b/image/showcase9.png new file mode 100644 index 00000000..ad535f23 Binary files /dev/null and b/image/showcase9.png differ diff --git a/image/startupop1.png b/image/startupop1.png new file mode 100644 index 00000000..68630372 Binary files /dev/null and b/image/startupop1.png differ diff --git a/image/startupop2.png b/image/startupop2.png new file mode 100644 index 00000000..d067cfe9 Binary files /dev/null and b/image/startupop2.png differ diff --git a/image/summary1.png b/image/summary1.png new file mode 100644 index 00000000..37d52cb4 Binary files /dev/null and b/image/summary1.png differ diff --git a/image/summary2.png b/image/summary2.png new file mode 100644 index 00000000..e50199cb Binary files /dev/null and b/image/summary2.png differ diff --git a/image/supportedplatfoerm1.png b/image/supportedplatfoerm1.png new file mode 100644 index 00000000..fe890ae9 Binary files /dev/null and b/image/supportedplatfoerm1.png differ diff --git a/image/update-dialog.png b/image/update-dialog.png new file mode 100644 index 00000000..64140574 Binary files /dev/null and b/image/update-dialog.png differ diff --git a/image/usingpreload1.png b/image/usingpreload1.png new file mode 100644 index 00000000..4fb96c69 Binary files /dev/null and b/image/usingpreload1.png differ diff --git a/image/vitepress/feature-0.svg b/image/vitepress/feature-0.svg new file mode 100644 index 00000000..4df3ee15 --- /dev/null +++ b/image/vitepress/feature-0.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/image/vitepress/feature-1.svg b/image/vitepress/feature-1.svg new file mode 100644 index 00000000..9dc5f68d --- /dev/null +++ b/image/vitepress/feature-1.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/image/vitepress/feature-2.svg b/image/vitepress/feature-2.svg new file mode 100644 index 00000000..97802313 --- /dev/null +++ b/image/vitepress/feature-2.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/image/vitepress/feature-3.svg b/image/vitepress/feature-3.svg new file mode 100644 index 00000000..ee01f230 --- /dev/null +++ b/image/vitepress/feature-3.svg @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/image/vitepress/feature-4.svg b/image/vitepress/feature-4.svg new file mode 100644 index 00000000..69d413d0 --- /dev/null +++ b/image/vitepress/feature-4.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/image/vitepress/home.png b/image/vitepress/home.png new file mode 100644 index 00000000..2923af06 Binary files /dev/null and b/image/vitepress/home.png differ diff --git a/image/vitepress/icon.png b/image/vitepress/icon.png new file mode 100644 index 00000000..38f91bbb Binary files /dev/null and b/image/vitepress/icon.png differ diff --git a/image/wasmsplit/check-version.png b/image/wasmsplit/check-version.png new file mode 100644 index 00000000..b383fb2b Binary files /dev/null and b/image/wasmsplit/check-version.png differ diff --git a/image/wasmsplit/code-split-index.png b/image/wasmsplit/code-split-index.png new file mode 100644 index 00000000..d8e467d5 Binary files /dev/null and b/image/wasmsplit/code-split-index.png differ diff --git a/image/wasmsplit/enable-plugin-1.png b/image/wasmsplit/enable-plugin-1.png new file mode 100644 index 00000000..22f276ae Binary files /dev/null and b/image/wasmsplit/enable-plugin-1.png differ diff --git a/image/wasmsplit/enable-plugin-2.png b/image/wasmsplit/enable-plugin-2.png new file mode 100644 index 00000000..d145ff80 Binary files /dev/null and b/image/wasmsplit/enable-plugin-2.png differ diff --git a/image/wasmsplit/extension-panel.png b/image/wasmsplit/extension-panel.png new file mode 100644 index 00000000..7c6185a2 Binary files /dev/null and b/image/wasmsplit/extension-panel.png differ diff --git a/image/wasmsplit/increment-update.png b/image/wasmsplit/increment-update.png new file mode 100644 index 00000000..023d9c9a Binary files /dev/null and b/image/wasmsplit/increment-update.png differ diff --git a/image/wasmsplit/incremental-split.png b/image/wasmsplit/incremental-split.png new file mode 100755 index 00000000..e17eb072 Binary files /dev/null and b/image/wasmsplit/incremental-split.png differ diff --git a/image/wasmsplit/main.png b/image/wasmsplit/main.png new file mode 100644 index 00000000..404c9e96 Binary files /dev/null and b/image/wasmsplit/main.png differ diff --git a/image/wasmsplit/preproc.png b/image/wasmsplit/preproc.png new file mode 100644 index 00000000..74129720 Binary files /dev/null and b/image/wasmsplit/preproc.png differ diff --git a/image/wasmsplit/start-split.png b/image/wasmsplit/start-split.png new file mode 100644 index 00000000..b934058c Binary files /dev/null and b/image/wasmsplit/start-split.png differ diff --git a/image/wasmsplit/update-plugin.png b/image/wasmsplit/update-plugin.png new file mode 100644 index 00000000..313ed589 Binary files /dev/null and b/image/wasmsplit/update-plugin.png differ diff --git a/image/wasmsplit/wait-split.png b/image/wasmsplit/wait-split.png new file mode 100644 index 00000000..442ec7be Binary files /dev/null and b/image/wasmsplit/wait-split.png differ diff --git a/image/wasmsplit/workflow.png b/image/wasmsplit/workflow.png new file mode 100644 index 00000000..e368270c Binary files /dev/null and b/image/wasmsplit/workflow.png differ diff --git a/image/watermark/add.png b/image/watermark/add.png new file mode 100644 index 00000000..3fa9b670 Binary files /dev/null and b/image/watermark/add.png differ diff --git a/image/watermark/icon.png b/image/watermark/icon.png new file mode 100644 index 00000000..a46285f3 Binary files /dev/null and b/image/watermark/icon.png differ diff --git a/image/watermark/panel.png b/image/watermark/panel.png new file mode 100644 index 00000000..68af69d5 Binary files /dev/null and b/image/watermark/panel.png differ diff --git a/image/wxassetbundleprovider1.png b/image/wxassetbundleprovider1.png new file mode 100644 index 00000000..e4dcab35 Binary files /dev/null and b/image/wxassetbundleprovider1.png differ diff --git a/image/wxassetbundleprovider2.png b/image/wxassetbundleprovider2.png new file mode 100644 index 00000000..2b9efff2 Binary files /dev/null and b/image/wxassetbundleprovider2.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..ab9ab0eb --- /dev/null +++ b/index.html @@ -0,0 +1,24 @@ + + + + + + 微信小游戏Unity/团结快适配 + + + + + + + + + + + + + + + + + + \ No newline at end of file