unity-web端h5记录
unity-web端h5记录
前篇
- 5款常用的html5游戏引擎以及优缺点分析 - https://imgtec.eetrend.com/blog/2022/100557792.html
- Unity WebGL 开发指北(完全篇, 好文) - https://zhuanlan.zhihu.com/p/475307249
- unity开发h5游戏(wasm) - https://www.gameweibo.com/article-520003.html
- Unity Webgl 常见问题总结 - https://zhuanlan.zhihu.com/p/480758156
web 端使用 tolua (不成熟, 不可用)
- unity webgl Tolua/Ulua - https://zhuanlan.zhihu.com/p/486826570
平台适配
文件 io 适配
- web 请求资源, 全都需要异步加载
构建和运行 WebGL 项目
- 构建和运行 WebGL 项目 - https://docs.unity3d.com/cn/2021.2/Manual/webgl-building.html
Build 文件夹详解
Build
文件夹包含以下文件([ExampleBuild]
表示目标构建文件夹的名称):
文件名 | 包含 |
---|---|
[ExampleBuild].loader.js |
网页需要用来加载 Unity 内容的 JavaScript 代码。 |
[ExampleBuild].framework.js |
JavaScript 运行时和插件。 |
[ExampleBuild].wasm |
WebAssembly 二进制文件。 |
[ExampleBuild].mem |
用于初始化播放器堆内存的二进制映像文件。Unity 仅针对多线程 WebAssembly 构建生成此文件。 |
[ExampleBuild].data |
资源数据和场景。 |
[ExampleBuild].symbols.json |
调试错误堆栈跟踪所需的调试符号名称。仅当启用 Debug Symbols 选项时 (File > Build Settings > Player Settings),才会为 Release 构建生成此文件。 |
[ExampleBuild].jpg |
在构建加载时显示的背景图像。仅当在 Player Settings (File > Build Settings > Player Settings > Splash Image) 中提供了背景图像时,才会生成此文件。有关更多信息,请参阅启动画面页面。 |
如果对构建启用某种压缩方法,Unity 会识别与压缩方法对应的扩展名,并将此扩展名添加到 Build 子文件夹中的文件的名称中。如果启用 Decompression Fallback,Unity 将扩展名 .unityweb
附加到构建文件名。否则,Unity 为 Gzip 压缩方法附加扩展名 .gz
,或者为 Brotli 压缩方法附加扩展名 .br
。 有关更多信息,请参阅 WebGL:压缩构建和服务器配置。
包体优化
- 提升Unity WebGL游戏启动速度 - https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/StartupOptimization.md
- 说说Unity发布WebGL的那些事儿-优化篇 - https://blog.csdn.net/u010075086/article/details/120075582
压缩配置
https://docs.unity3d.com/cn/2021.3/Manual/webgl-deploying.html
压缩格式
压缩方法 描述 gzip 这是默认选项。gzip 文件比 Brotli 文件更大,但构建速度更快,且所有浏览器都基于 HTTP 和 HTTPS 实现此格式的本机支持。 Brotli Brotli 压缩提供最佳压缩比。Brotli 压缩文件小于 gzip,但需要更长的压缩时间,因此会增加发布版本的迭代时间。Chrome 和 Firefox 仅原生支持基于 HTTPS 的 Brotli 压缩。 Disabled 禁用压缩。如果要在后期处理脚本中实现您自己的压缩,请使用此选项。如果计划在托管服务器上使用静态压缩,也应该使用此选项。
剥离引擎代码
打开“ 其他设置”以访问“ 剥离引擎代码”选项。默认情况下会选中此选项以启用WebGL的代码剥离。选中此选项后,Unity不会包含您不使用的任何类的代码。例如,如果您不使用任何物理组件或功能,则整个物理引擎
,从您的构建中删除。有关详细信息,请参阅下面的“剥离”部分。
分包
- 将引擎编译的和自己的代码分离出来, 这样多个游戏包就可以引用同一个引擎代码, 浏览器就会使用缓存
预加载
- 将不同游戏的 wasm 预加载到本地, 进入游戏时就会很快了
使用 nginx 作为文件服务器
- 下载地址: http://nginx.org/en/download.html
- 配置参考: WebGL:服务器配置代码示例 - https://docs.unity3d.com/cn/2021.2/Manual/webgl-server-configuration-code-samples.html
- WebGL:压缩构建和服务器配置 - https://docs.unity3d.com/cn/2021.2/Manual/webgl-deploying.html
使用
启动
1
2
3C:\server\nginx-1.0.2>start nginx
or
C:\server\nginx-1.0.2>nginx.exe停止
1
2
3C:\server\nginx-1.0.2>nginx.exe -s stop
或
C:\server\nginx-1.0.2>nginx.exe -s quit重新载入配置
1
C:\server\nginx-1.0.2>nginx.exe -s reload
重新打开日志文件
1
C:\server\nginx-1.0.2>nginx.exe -s reopen
查看版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14C:\server\nginx-1.0.2>nginx -v
---
### 平台判断
- 编译宏 https://docs.unity3d.com/Manual/PlatformDependentCompilation.html
```json
#if UNITY_WEBGL
LogUtil.D("--- UNITY_WEBGL ");
#endif运行时
1
Application.platform == RuntimePlatform.WebGLPlayer
http
使用 best http, 版本最新即可, 如: 2.8.2
websocket
使用 best http, 版本最新即可, 如: 2.8.2
- Unity下使用BestHTTP插件进行Http和WebSocket通信 - https://blog.csdn.net/foupwang/article/details/104725423
调试
查看调用栈
想要在浏览器查看到调用栈, 需要打开开发模式
开启后, 包体将会很大, 打包时间也变长, 发布时一定要关掉 !!!
发布设置
平台打包
禁用浏览器缓存
F12 打开开发者工具, 在 Network 中, 勾选 disable cache
这样每次就会从服务器拉取资源, 而不是用 indexedDB 中的缓存资源
- transferred: 是实际传输的大小
- resources: 是传输后解压后的大小 (因为开 gzip 之类的, 浏览器会进行解压)
强刷浏览器
按 F12 打开开发者模式
然后才能在 刷新 按钮右键 -> 清空缓存并硬性重新加载
http 请求跨域
nginx 允许跨域配置
- 暂无
临时解决方案, 禁止掉浏览器的跨域检测
解决Chrome浏览器的跨域问题 - https://juejin.cn/post/7019171779478290463
找到快捷方式, 右击打开属性,找到
目标
字段,并在目标字段后面加上参数:1
--disable-web-security --user-data-dir=D:\ChromeData\MyChromeDevUserData
其中
D:\ChromeData\MyChromeDevUserData
为跨域浏览器数据存储的地方,可以根据需要修改。双击打开浏览器, 出现不安全提示就表示禁用了 跨域检测
使用模板
- 官方
使用
项目的
Assets
文件夹并创建一个名为WebGLTemplates
的文件夹, 然后在WebGLTemplates
目录下, 每一个子目录是一个模板, 可以将引擎预制的模板 (模板存储在<Unity Installation>/PlaybackEngines/WebGLSupport/BuildTools/WebGLTemplates/
下) 拷出来放进去, 重新打开 player settings 页面就会出现可选择模板目录(这里我将缩略图随便涂了点红色方便辨认)
然后就可以在自定义的模板里加入自己的脚本逻辑了.
与 js 交互
- 参考: unity-与js交互.md
注意事项
不能使用多线程
在 WebGL 平台上使用 AssetBundle 时的注意事项:
- 在 AssetBundle 中使用未在主构建中使用的类类型时,Unity 可能会从构建中剥离这些类的代码。尝试从 AssetBundle 加载资源时,这可能会导致失败。请使用 BuildPlayerOptions.assetBundleManifestPath 修复该问题,或参阅下面有关*剥离*的部分以了解其他选项。
- WebGL 不支持线程,但 http 下载内容仅在下载完成后才可用。因此,在下载完成时,Unity WebGL 构建需要在主线程上解压缩 AssetBundle 数据,而这会阻止主线程。为避免这种中断,LZMA AssetBundle 压缩不可用于 WebGL 上的 AssetBundle。此情况下使用 LZ4 对 AssetBundle 进行压缩,这种压缩格式可非常高效地按需进行解压缩。如果所需的压缩大小比 LZ4 能够提供的压缩大小更小,可将 Web 服务器配置为对 AssetBundle 使用 gzip 或 Brotli 压缩(基于 LZ4 压缩)。请参阅有关部署压缩构建的文档以详细了解如何执行此操作。
- WebGL supports AssetBundle caching with UnityWebRequestAssetBundle.GetAssetBundle. This method uses the IndexedDB API from your browser to store a cache on the user’s device. Some browsers might have limited support for IndexedDB and any browsers might request the user’s authorization to store data on the disk. For more information, see WebGL browser compatibility.
- 不支持多线程,因为 JavaScript 不支持多线程,所以
System.Threading
命名空间下的类不要使用; - 不能在 VS 中进行断点调试,后面会介绍如何进行调试;
- 不能直接使用 Socket,包括
System.Net
下的任何类型,以及System.Net.Sockets
下的部分类型,以及UnityEngine.Network
,如果需要在 WebGL 平台使用网络功能,可以使用WWW
或者UnityWebRequest
这些都是基于Http
协议的实现,如要需要高实时性,可以选择WebSockets
或者WebRTC
; - WebGL 1.0是基于 OpenGL ES 2.0,WebGL 2.0基于 OpenGL ES 3.0,所以存在相应的限制;
- WebGL 音频是基于自定义的后台,只具备基本的音频功能;
- WebGL 是 AOT(ahead of time,即静态编译平台,因此不能使用
System.Reflection.Emit
下的类型进行代码生成,IL2CPP和 iOS 也是如此。 - webgl 不支持 LZMA 压缩, 只能用 LZ4
- 内置的video player 无法播放。(可以使用AVPro 播放)
- 不支持ComputeShader: SystemInfo.supportsComputeShaders
解决显示不支持移动端
浏览器运行时提示:
WebGL builds are not supported on mobile devices.
在构建出来包里的 index.html 的提示去掉即可
包体大小优化
- unity开发h5游戏(wasm) - https://www.gameweibo.com/article-520003.html
持久化数据
使用 PlayerPrefs 相关 api 即可.
1
PlayerPrefs.SetString("Name", "hello");
手动清除浏览器缓存, 会将它清除掉; 如果是强制刷新重新加载页面, 则不会清除掉.
Unity WebGL 将所有持久化数据(PlayerPrefs、缓存)都保存到浏览器的 IndexedDB 中,在开发者工具中,可以通过
Application
标签页查看,这一API 是异步的,所以不知道什么时候能够完成。
踩坑
未开启 gz
报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116Unable to parse Build/aaa.framework.js.gz! This can happen if build compression was enabled but web server hosting the content was misconfigured to not serve the file with HTTP Response Header "Content-Encoding: gzip" present. Check browser Console and Devtools Network tab to debug.
官方推荐的是 使用 nginx, 参考: https://docs.unity3d.com/cn/2021.2/Manual/webgl-server-configuration-code-samples.html
- 在
```json
http {
# 增加一个 server 配置
server {
listen 8811;
server_name localhost;
root C:/Users/wilker/Desktop/aaa; # unity 打出的 h5 包
index index.html
# location / {
# root html;
# index index.html index.htm;
# }
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
########################################
# Add the following config within http server configuration
# ...
# On-disk Brotli-precompressed data files should be served with compression enabled:
location ~ .+\.(data|symbols\.json)\.br$ {
# Because this file is already pre-compressed on disk, disable the on-demand compression on it.
# Otherwise nginx would attempt double compression.
gzip off;
add_header Content-Encoding br;
default_type application/octet-stream;
}
# On-disk Brotli-precompressed JavaScript code files:
location ~ .+\.js\.br$ {
gzip off; # Do not attempt dynamic gzip compression on an already compressed file
add_header Content-Encoding br;
default_type application/javascript;
}
# On-disk Brotli-precompressed WebAssembly files:
location ~ .+\.wasm\.br$ {
gzip off; # Do not attempt dynamic gzip compression on an already compressed file
add_header Content-Encoding br;
# Enable streaming WebAssembly compilation by specifying the correct MIME type for
# Wasm files.
default_type application/wasm;
}
# On-disk gzip-precompressed data files should be served with compression enabled:
location ~ .+\.(data|symbols\.json)\.gz$ {
gzip off; # Do not attempt dynamic gzip compression on an already compressed file
add_header Content-Encoding gzip;
default_type application/octet-stream;
}
# On-disk gzip-precompressed JavaScript code files:
location ~ .+\.js\.gz$ {
gzip off; # Do not attempt dynamic gzip compression on an already compressed file
add_header Content-Encoding gzip;
default_type application/javascript;
}
# On-disk gzip-precompressed WebAssembly files:
location ~ .+\.wasm\.gz$ {
gzip off; # Do not attempt dynamic gzip compression on an already compressed file
add_header Content-Encoding gzip;
# Enable streaming WebAssembly compilation by specifying the correct MIME type for
# Wasm files.
default_type application/wasm;
}
}
}
---
#### 移动设备不支持
- 报错
```json
WebGL builds are notsupported on mobile devices.
据说不用管这个
---
#### 中文显示
- a
---
#### http 请求
##### 原生端旧的 best http 插件报错
```json
Invoking error handler due to
ReferenceError: Runtime is not defined
at XMLHttpRequest.http_onload (http://localhost:8811/Build/aaa.framework.js.gz:3:85864)解决办法: 升级 best http 插件到 2.8.2+ 即可.
UnityWebRequest 请求报错
1 | exception thrown: TypeError: Cannot set properties of undefined (setting '1'),TypeError: Cannot set properties of undefined (setting '1') |
- 参考: https://forum.unity.com/threads/cannot-set-properties-of-undefined-setting-1-when-running-a-unitywebrequest.1248445/
- 暂时不去解决, 采用升级 best http 插件的办法
edge, firefox 运行异常
报错:
http response header content-type configured incorrectly on the server for file
参考: https://forum.unity.com/threads/http-response-header-content-type-configured-incorrectly.1206946/
实际问题产生原因可能是安装了 IDM 下载工具, 导致浏览器中该工具的下载插件识别到了文件导致变成文件下载
解决办法: 在浏览器中将该插件禁用即可.
不要使用阻塞代码
不要是阻塞代码来等待 WWW 或 WebRequest 完成,比如下面代码:
1 | while(!www.isDone){} |
因为 WebGL 是单线程,而 XMLHttpRequest 又是异步方法,整个一直执行 while 循环,而不能更新 XMLHttpRequest 响应信息,可以使用协程和 yield 来等待下载完成。