- 为Editor增加“创建Asset Bundle包”的选项
using System.IO;
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string dir = "AssetBundles";
if (Directory.Exists(dir) == false)
{
Directory.CreateDirectory(dir);
}
//BuildTarget 选择build出来的AB包要使用的平台
BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);
}
}
其中BuildPipeline.BUildAssetBundles的参数
BuildAssetBundleOptions:
None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦它被下载了之后,它会使用LZ4算法保存到本地上。
UncompressedAssetBundle: 不要所,包更大,加载更快
ChunkBasedCompression:LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。
WebGL下一般选择ChunkBasedCompression
BuildTarget:根据平台选择,我这里选择WebGL
- 资源打包
关于这点有很多文章都详细的讲解了资源分类打包的优点,此处不赘述。只简单的说一下。
step1. 选择要打包的资源(预制体,材质,shader等),默认布局(Layout-Default)下,Editor窗口右下角会显示资源的预览,最下面的一行有“AssetBundle”的一行,有两个下拉,分别对应AssetBundle包的文件名与后缀。
step2. 点击长一点的下拉,会显示已经存在的AssetBundle名称和(没有则是None)New...与Remove...两个选项。点击短一点的下拉,会显示已存在的AssetBundle后缀与“None”和“New...”两个选项。根据实际情况为资源设置打包后的文件名与后缀。 AssetBundle名称与后缀相同的资源会被打包到一起。
step3. 设置好文件名后,按Editor下脚本的配置(我这里是在”Assets/Build Asset Bundles“)点击创建包的按钮,等待创建完成。即可在脚本中定义的目录里看到已经打包好的文件了
- 资源下载
我使用的Unity版本是2020.3.23.f1c1。这个版本下www已被弃用。所以我选择UnityWebRequest
基本的调用代码如下
using (UnityWebRequest request = UnityWebRequest.Get(SceneInfo.SkyboxUrl))
{
yield return request.SendWebRequest();
if (request.error != null)
{
Debug.Log(request.error);
}
else
{
if (request.isDone)
{
Debug.Log("download complate.");
byte[] results = request.downloadHandler.data;
//results即为下载的结果。
AssetBundle ab = AssetBundle.LoadFromMemory(results);
}
}
}
之类的Download Handler可以根据要下载的资源的不同更换成其他的(比如DownloadHandlerAssetBundle或DownloadHandlerTexture)等...
AssetBundle用过之后记得卸载使用Asset Bundle.Unload方法,参数写false。选择true的话,会将生成的实例一起卸载。
- 下载AssetBundle内物体的实例化与组件的绑定
为物体添加组件的代码必须放在下载物体的实例化之后,如果全在Start中调用,组件绑定会在物体实例化前调用,此时会因为找不到物体而绑定失败。
这里我将组件绑定放进了Update中,并增加了几个参数用于判断Asset Bundle内物体是否已经完成实例化。
private int downloadCount=0;
private bool isloaded=false;
IEnumerator GetObjects(string url, string goname, string rename, ... Action callback)
{
downloadCount+=1;
using (UnityWebRequest uwr = UnityWebRequest.Get(url))
{
yield return uwr.SendWebRequest();
if (uwr.error != null)
throw new Exception("download had an error" + uwr.error);
//判断当请求结束后执行
if (uwr.isDone)
{
//获取AssetBundle
//从AB中读取物体
//配置物体参数与组件
//实例化物体
if(callback != null)
callback();
}
}
}
void releaseGetObject()
{
//获取物体的时计数+1
//调用回调表示获取物体的方法执行完成,计数-1
//当计数重新归零,表示加载完所有物体
cCount -= 1;
}
void Update()
{
if(downloadCount==0){
if(!isloaded){
isloaded=true;
//循环绑定组件并加载资源
}
}
}
在update中,先判断DownloadCount是否归0,再判断是否是首次加载。判断都成立时会循环绑定组件组件内的资源
- 天空盒
直接修改天空盒的代码很简单,只有一句话:
RenderSettings.skybox = sky;
这里的Sky的类型是Material这里还需要另外调整,不是随便拿一张图片就行的。
我这里仅说一下我的实现过程
1. 首先要有一张用于制作天空盒的全景图。
2. 将它的Texture Shape设置为Cube,在Project选单下图片的预览就从上面的样子变成了这样:
3.把这个图片拖入Scene中,会看到图片直接替换了当前场景的天空盒
4. 这时候图片路径下会生成一个文件夹”Materials“,这里面放着的就是自动生成的天空盒的material文件了(后缀为.mat),
ex. 接下来就像对待其他资源那样,把这个天空盒打包成Asset Bundle,上传到服务器端。需要使用的时候,下载对应Assetbundle文件,从中加载对应名称的Material类资源即可取出这个天空盒。这时候的天空盒就可以直接想RenderSettings.Skybox赋值了。