使用Node.js搭建AssestBundle服务器并验证AB包热更新
一、服务器部分
使用NodeJs作为服务器, 使用Express为基础网页模版。 当然, 使用其他的FTP,http服务器也可以, 基础逻辑是存放资源的位置。
1.下载Node.js
下载地址:https://nodejs.cn/download/
2.安装NodeJs软件
下一步,下一步,下一步安装即可
3.创建目录:
由于我们需要为AssestBundle建立一个服务器, 因此我们需要再本地创建一个目录来存放相关的内容。
当然, 也可以在Unity中与Assest目录的平级目录
中创建WebServer目录。你可以自定义WebServer的文件夹路径 然后再WebServer中创建一个WWW_Root的目录,用来专门存放我们需要进行热更新的AB包。
4.创建express模版
使用NodeJs创建express静态网页模版。
在当前目录中,即WebServer的目录中打开cmd或者PowerShell
。 你也可以直接打开cmd控制台窗口,然后切换到WebServer的目录中。下图中红色部分是标记了路径, 你只需要切换到对应的路径即可。然后输入 npm install express
进行安装express。
npm install express
5.编写NodeJs服务器启动脚本
安装完毕后express后, 编写服务器的启动脚本, 创建一个main.js的文件。
然后粘贴如下代码,
var express = require("express");
var path = require("path");
var app = express();
// http://127.0.0.1:8888/AssetBundles/Win64/Test/building.ab
// 该路径是我们前面打好包的路径==>服务器的地址
app.use("/", express.static(path.join(process.cwd(), "WWW_Root")));
// 端口号
app.listen(8888);
6.启动NodeJs服务器
在cmd或者powerShell中输入node ./main.js
启动服务器。 不要关闭该窗口。
7.验证服务器是否启动成功。
打开浏览器,输入地址:端口号以及文件组成的一个完整的url地址。
例如,我将打好包的AB包放在了我的根目录, 这里需要和第二部分Unity中的打AB包的位置一致。
H:\UnityProjects\2022_ResMgr\WebServer\WWW_Root\AssetBundles\Win64\Test
由于上面写的main.js文件中的js代码是将WWW_Root
映射为当前Nodejs的工作目录(cwd=current work directory), 因此,我们在浏览器中访问的路径为127.0.0.1:8888/AssetBundles/Win64/Test/house.ab
。 这里的端口和图上的有点不一样, 按照实际你设置的端口为准。
127.0.0.1:8888/AssetBundles/Win64/Test/house.ab
如果你输入后的结果和上图一样, 你能保存文件,就代表着你的NodeJs服务器是启动好了的。
二、Unity部分
1.打AB包
Unity中配置AB包, 注意资源的位置。我这里是将一个房子的预制体打AB包, ab包的包名为house, 后缀名为ab。如果下图所示。 所以完整的包名为house.ab
2.拷贝ab包到服务器上
构建AB包后, 将打好的AB包放到我们前面提到的文件夹下, 也就是服务器中的目录。如下图所示, 你可以根据你点击浏览的目录来找到你需要存放的AB包。 在实际开发中,建议将ab包拷贝到StreamingAssests
中, 方便进行测试。
3.使用下载并使用AB包
在Unity端口, 如何下载并使AB包呢。
思考一下, Unity需要联网, 因此,我们可以使用WWW
类或者UnityWebRequest
来请求一个服务器来下载文件。
当然, 如果WWW在代码中提示过时, 你应该使用UnityWebRequest
来下载。需要注意的是, 下载的文件是直接加载内存中的, 因此你无法在项目的文件夹目录中找到你使用 UnityWebRequest 或者WWW
下载的AB包。 下面是测试代码
代码如下:
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
public class GameLanch : MonoBehaviour
{
AssetBundle ab;
// ab包对应服务器的位置or文件夹
string resUrl = "http://127.0.0.1:8888/AssetBundles/Win64/Test/house.ab";
void Start()
{
// 资源检测和更新
StartCoroutine(CheckRes());
}
IEnumerator CheckRes()
{
// 构建请求的AB包的 UnityWebRequest
UnityWebRequest uwr = UnityWebRequestAssetBundle。GetAssetBundle(resUrl);
yield return uwr.SendWebRequest();
if (uwr.result != UnityWebRequest.Result.Success)
{
Debug.LogError(uwr.error);
}
else
{
Debug.Log("Download success!");
// 获取下载内容
ab = DownloadHandlerAssetBundle.GetContent(uwr);
if (ab != null)
{
// 从包中加载预制体
GameObject housePrefab = ab.LoadAsset<GameObject>("Assets/Arts/AssetsPakage/maps/level1/House_D_3.prefab");
if (housePrefab != null)
{
GameObject.Instantiate(housePrefab);
}
else
{
Debug.Log("mapPrefab is null");
}
}
// 卸载AB包
ab.Unload(false);
}
}
}
4.测试效果
将脚本挂载在场景中的物体上, 为了检验是否能够加载我们下载的AB包, 我们将原来存放的预制体删除。然后运行代码。下面是测试结果