最近公司要求做一个在VR里面的模型商店,自然就绕不开资源打包了,研究了一下Unity最新的Addressable,发现了这玩意是相当好用,只要有配置好bundle包的Json文件路径地址,就可以通过资源的Address轻松加载出资源,开发者不需要管资源之间的各种联系。工程准备的话肯定是要从unity的Package Manager中下载Addressable,下载完之后,对工程做一下简单设置:在Window->AssetMangement->Addressables,添加一个Addressable,在左上角的Profile中,选中Inspect Profile Setting .
这里主要是要打包的时候,把Catalog也要一起生成到指定路径,我这里是生成到本地打包的路径,因为这个路径是固定的,方便后续对打包的文件做压缩操作。
整个程序的工作流程是:①把预制体制作好,拖入组中(一开始组名是Default Group)②更改组名(由于组名相同,打包过程中容易发生混淆,这里为了避免发生不必要的错误,组名使用时间戳保证每次上传的包组名不重复)③运行程序在UI中添加模型必要的信息。④点击上传
UI界面如下:
笔者写了两个编辑器函数去做更改组名和bundle包路径文件的清除:
/****************************************************
文件:AddressableEditor.cs
作者:Paul 邮箱: 794451358@qq.com
日期:2020/7/23 15:23:1
功能:编辑器扩展函数
*****************************************************/
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using System;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
namespace AddressOperation
{
public class AddressableEditor : Editor
{
[MenuItem("Daschow/1.ChangeGroupName",priority =1)]
public static void ChangeGroupName()
{
AddressableAssetSettingsDefaultObject.Settings.DefaultGroup.Name = GetTimeStamp();
AddressableAssetSettings.BuildPlayerContent();
EditorApplication.isPlaying = true;
}
[MenuItem("Daschow/2.DeleBundleFiles", priority = 2)]
public static void DeleBundlePathFiles()
{
FileUtil.DeleteFileOrDirectory(ProjectConst.BundlePath);
}
public static string GetTimeStamp()
{
//TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
//DateTime.Now.ToString()
return DateTime.Now.ToString("yyyyMMddhhmmss");
}
}
}
#endif
在点击文件上传的时候,程序会利用ICSharpCode.SharpZipLib.Zip工具包把Addressable生成的三个文件(一个记录资源信息的Catalog Json文件,一个bundle包,一个hash文件)压缩成一个Zip压缩包,然后把这个压缩包文件以二进制的格式放入上传表单,上传到服务器。和压缩包一起上传的还有封面图片(这张封面图片是主程序加载模型时UI选择的Icon)、模型的名字(不同于模型的Address,这个是显示给玩家看的模型名字)、资源描述、资源类型还有商品价格。这些必要信息再主程序加载时的必要信息。
附上上传面板的代码:
/****************************************************
文件:AssetInfoPanel.cs
作者:Paul 邮箱: 794451358@qq.com
日期:2020/7/23 12:15:21
功能:资源信息面板
*****************************************************/
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using PFarmeWork;
using DG.Tweening;
using UnityEngine.UI;
using WebGLPage;
using UniRx;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
#endif
namespace AddressOperation
{
public class AssetInfoPanel : BasePanel
{
public static string AssetName = "";
private Text Text_GroupName;
private Text Text_AssetName;
private Text Text_LabelName;
private RawImage Image_Cover;
private Button Btn_UpLoad;
private Camera m_ShotCamera;
private UpLoadFile m_UpLoader;
private Slider Sld_CoverProgress;
private Text Text_CoverProgress;
private Slider Sld_ZipProgress;
private Text Text_ZipProgress;
private InputField Input_Des;
private InputField Input_ObjName;
private Dropdown Drop_ObjType;
private InputField Input_Cost;
private static string ms_ImgPath = "";
private static string ms_PhoneNum = "";
public string PhoneNum { set { value = ms_PhoneNum; } }
private void Awake()
{
Text_GroupName = transform.Find("Text_GroupName").GetComponent<Text>();
Text_AssetName = transform.Find("Text_AssetName").GetComponent<Text>();
Text_LabelName = transform.Find("Text_LabelName").GetComponent<Text>();
Image_Cover = transform.Find("Image_Cover").GetComponent<RawImage>();
Btn_UpLoad = transform.Find("Btn_UpLoad").GetComponent<Button>();
m_ShotCamera = GameObject.Find("ShotCamera").GetComponent<Camera>();
Sld_CoverProgress = transform.Find("Sld_Progress").GetComponent<Slider>();
Sld_ZipProgress = transform.Find("Sld_ZipProgress ").GetComponent<Slider>();
Text_CoverProgress = Sld_CoverProgress.transform.Find("Text_Progress").GetComponent<Text>();
Text_ZipProgress = Sld_ZipProgress.transform.Find("Text_Progress").GetComponent<Text>();
Input_Des = transform.Find("Input_Des").GetComponent<InputField>();
Input_ObjName = transform.Find("Input_ObjName").GetComponent<InputField>();
Drop_ObjType = transform.Find("Drop_ObjType").GetComponent<Dropdown>();
Input_Cost = transform.Find("Input_Cost").GetComponent<InputField>();
AddListener<float>(MEventType.CoverUpLoadProgress, OnCoverProChange);
AddListener<float>(MEventType.BundleUpLoadProgress, OnZipProChange);
}
public override void OnEnter()
{
m_UpLoader = GetComponentInParent<UpLoadFile>();
Drop_ObjType.OnValueChangedAsObservable().
Subscribe(value =>
{
m_UpLoader.Type = value.ToString();
});
this.ShowGo();
GetComponent<CanvasGroup>().DOFade(1, 1f);
#if UNITY_EDITOR
Text_GroupName.text = AddressableAssetSettingsDefaultObject.Settings.DefaultGroup.Name;
foreach (var item in AddressableAssetSettingsDefaultObject.Settings.DefaultGroup.entries)
{
Text_AssetName.text = item.address.ToString();
AssetName = item.address.ToString();
foreach (var m_item in item.labels)
{
Text_LabelName.text = m_item;
}
}
Image_Cover.texture = Resources.Load<RenderTexture>("RenderTexture/ShotTexture") as RenderTexture;
Btn_UpLoad.onClick.AddListener(OnBtnUpLoadDown);
#endif
}
public override void OnExit()
{
this.HideGo();
GetComponent<CanvasGroup>().DOFade(0, 1f);
}
public override void OnPause()
{
base.OnPause();
}
public override void OnResume()
{
base.OnResume();
}
public void OnBtnUpLoadDown()
{
ms_ImgPath = ProjectConst.StreamingAssetsPath + Text_AssetName.text + ProjectConst.PNG;
CameraShot.SaveShot(m_ShotCamera, ms_ImgPath);
Compress();
m_UpLoader.Des = Input_Des.text;
m_UpLoader.ObjName = Input_ObjName.text;
m_UpLoader.Cost = Input_Cost.text;
m_UpLoader.UpLoad(ms_ImgPath);
}
public void OnDropdownChange()
{
print(Drop_ObjType.value);
}
public void OnCoverProChange(float progress)
{
Sld_CoverProgress.value = progress;
Text_CoverProgress.text = Mathf.Floor(progress*100).ToString() + "%";
}
public void OnZipProChange(float progress)
{
Sld_ZipProgress.value = progress;
Text_ZipProgress.text = Mathf.Floor(progress * 100).ToString() + "%";
}
private void Compress()
{
PFarmeWork. FileUtil.CreateFolder(ProjectConst.ZipDesFolder);
string[] fileList;
bool isExits = PFarmeWork.FileUtil.GetDiectoryFilesList(ProjectConst.BundlePath, out fileList);
if (isExits)
{
ZipOperation.ZipFiles(fileList, ProjectConst.ZipDesFileName);
//m_UpLoader.UpLoadZip(ProjectConst.ZipDesFileName);
}
}
private void OnDestroy()
{
RemoveListener<float>(MEventType.CoverUpLoadProgress,OnCoverProChange);
RemoveListener<float>(MEventType.BundleUpLoadProgress, OnZipProChange);
}
}
}