热更新
Editor目录下CreateAssetBundle.cs
/*
* created by shenjun
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Networking;
namespace shenjun
{
public class CreateAssetBundle : EditorWindow
{
public static string createAssetPath{ get { return Application.dataPath + "/LessonXLua_shenjun/04_Examples/02_HotUpdate/AssetBundle/Build/"; }}
static CreateAssetBundle window;
int platformSelect = 0;
string[] platformName = { "Windows", "Mac OS", "IOS", "Android", "All" };
string assetbundlePath = "";
string Path
{
set {
assetbundlePath = value;
}
get
{
if(string.IsNullOrEmpty(assetbundlePath))
{
assetbundlePath = createAssetPath;
}
return assetbundlePath;
}
}
[MenuItem("AssetBundle/CreateAssetBundleTools")]
static void ShowWindow()
{
if (window == null)
{
window = EditorWindow.GetWindow<CreateAssetBundle>(true, "AssetBundle Tools");
window.minSize = new Vector2(800, 600);
}
window.Show();
}
void OnGUI()
{
platformSelect = GUILayout.SelectionGrid(platformSelect, platformName, platformName.Length);
GUILayout.BeginHorizontal();
GUILayout.Label("打包路径:");
GUILayout.Label(Path);
if(GUILayout.Button("选择路径", GUILayout.MaxWidth(100)))
{
Path = EditorUtility.OpenFolderPanel("选择文件夹", Application.dataPath, Path);
}
GUILayout.EndHorizontal();
if (GUILayout.Button("打包"))
{
CreateBundle(platformSelect);
EditorUtility.DisplayDialog("资源打包信息提示", "打包完成", "确定");
}
}
void CreateBundle(int plat)
{
string combinePath = "";
BuildTarget target = BuildTarget.NoTarget;
switch(plat)
{
case 0:
combinePath = Path + "Windows";
target = BuildTarget.StandaloneWindows;
break;
case 1:
combinePath = Path + "Mac OS";
target = BuildTarget.StandaloneOSX;
break;
case 2:
combinePath = Path + "IOS";
target = BuildTarget.iOS;
break;
case 3:
combinePath = Path + "Android";
target = BuildTarget.Android;
break;
case 4:
for (int i = 0; i < 4; i++)
{
CreateBundle(i);
}
return;
}
if (!System.IO.Directory.Exists(combinePath))
{
System.IO.Directory.CreateDirectory(combinePath);
}
CreateBundle(combinePath, target);
}
void CreateBundle(string path ,BuildTarget target)
{
BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.ForceRebuildAssetBundle, target);
AssetDatabase.Refresh();
}
[MenuItem("AssetBundle/资源清理(删除本地及远程数据)")]
public static void ClearDirectory()
{
string[] clearPath = { LoadHotUpdate.localAssetPath, LoadHotUpdate.remoteAssetPath };
for (int i = 0; i < clearPath.Length; i++)
{
string[] fileNames = System.IO.Directory.GetFiles(clearPath[i]);
for (int j = 0; j < fileNames.Length; j++)
{
System.IO.File.Delete(fileNames[j]);
}
}
AssetDatabase.Refresh();
}
}
}
HotUpdateLua.cs
/*
* created by shenjun
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.EventSystems;
using XLua;
namespace shenjun
{
public class HotUpdateLua : MonoBehaviour, IPointerDownHandler {
[CSharpCallLua]
public delegate void AwakeSet(HotUpdateLua self);
[CSharpCallLua]
public delegate void OnPanelClick(PointerEventData eventData);
LuaEnv luaEnv = new LuaEnv();
AwakeSet awake;
Action start;
Action update;
Action destroy;
OnPanelClick panelClick;
void Awake()
{
AssetBundle bundle = AssetBundle.LoadFromFile(LoadHotUpdate.localAssetPath + "luahotupdate_lua.ab");
TextAsset luaAsset = bundle.LoadAsset<TextAsset>("LuaHotUpdate.lua.txt");
luaEnv.DoString(luaAsset.text);
awake = luaEnv.Global.Get<AwakeSet>("Awake");
start = luaEnv.Global.Get<Action>("Start");
update = luaEnv.Global.Get<Action>("Update");
destroy = luaEnv.Global.Get<Action>("OnDestroy");
panelClick = luaEnv.Global.Get<OnPanelClick>("OnPanelClick");
if (awake != null) awake(this);
}
void Start () {
if (start != null) start();
}
void Update () {
if (update != null) update();
}
void OnDestroy()
{
awake = null;
start = null;
update = null;
if (destroy != null)
{
destroy();
destroy = null;
}
panelClick = null;
luaEnv.Dispose();
}
public void OnPointerDown(PointerEventData eventData)
{
if (panelClick != null) panelClick(eventData);
}
}
}
LoadHotUpdate.cs
/*
* created by shenjun
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using UnityEngine.Networking;
using UnityEngine.UI;
namespace shenjun
{
public class LoadHotUpdate : MonoBehaviour
{
static Dictionary<string, AssetBundle> bundleCaches = new Dictionary<string, AssetBundle>();
static AssetBundleManifest manifest = null;
public static string localAssetPath
{
get
{
// FIXME : 移动平台的路径不一样
// 移动平台的话 请使用路径(具有可读写权限): Application.persistentDataPath
return Application.dataPath + "/LessonXLua_shenjun/04_Examples/02_HotUpdate/AssetBundle/Local/";
//#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
//#elif UNITY_IOS
//#elif UNITY_ANDROID
//#endif
}
}
public static string remoteAssetPath
{
get
{
// FIXME : 移动平台的路径不一样 同 localAssetPath
return Application.dataPath + "/LessonXLua_shenjun/04_Examples/02_HotUpdate/AssetBundle/Remote/";
}
}
void Start()
{
// 从服务器 下载配置文件列表 配置文件格式:txt json xml cvs
// 和本地配置文件对比 版本号、资源校验码等 不同的则更新
// 更新
// 运行程序
StartCoroutine(LoadRemoteProfile(LoadAsset));
}
void Update()
{
}
private void OnDestroy()
{
bundleCaches.Clear();
AssetBundle.UnloadAllAssetBundles(true);
}
IEnumerator LoadRemoteProfile(Action<string> onFinished)
{
//Caching.ClearCache();
//while (!Caching.ready)
//yield return null;
string url =
#if UNITY_STANDALONE_WIN
"file:///" +
#elif UNITY_STANDALONE_OSX
"file://" +
#endif
remoteAssetPath + "luahotupdate_profile.ab";
AssetBundle bundle = null;
// 1、WWW.LoadFromCacheOrDownload 加载
//using(WWW www = WWW.LoadFromCacheOrDownload(url, 0))
//{
// yield return www;
// if (!string.IsNullOrEmpty(www.error))
// {
// Debug.Log(www.error);
// yield break;
// }
// bundle = www.assetBundle;
//}
// 2、UnityWebRequest.GetAssetBundle 加载
UnityWebRequest webRequest = UnityWebRequest.GetAssetBundle(url);
yield return webRequest.SendWebRequest();
if (!string.IsNullOrEmpty(webRequest.error))
{
Debug.Log(webRequest.error);
yield break;
}
bundle = DownloadHandlerAssetBundle.GetContent(webRequest);
// 3、AssetBundle.LoadFromFile 加载
//bundle = AssetBundle.LoadFromFile(remoteAssetPath + "luahotupdate_profile.ab");
// 4、AssetBundle.LoadFromFileAsync 加载
//AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(remoteAssetPath + "luahotupdate_profile.ab"));
//yield return request;
//bundle = request.assetBundle;
TextAsset profile = bundle.LoadAsset<TextAsset>("file");
onFinished(profile.text);
}
void LoadAsset(string remoteVersion)
{
AssetBundle.UnloadAllAssetBundles(true);
// 加载本地配置文件
string profilePath = localAssetPath + "luahotupdate_profile.ab";
if (!File.Exists(profilePath))
{
// 加载服务器文件列表
LoadRemoteAsset();
}
else
{
// 加载本地列表并比较
AssetBundle bundle = AssetBundle.LoadFromFile(profilePath);
TextAsset profile = bundle.LoadAsset<TextAsset>("file");
float localVersion, removeVersion;
if (float.TryParse(profile.text, out localVersion) && float.TryParse(remoteVersion, out removeVersion))
{
if (removeVersion > localVersion)
{
// 加载服务器文件列表
LoadRemoteAsset();
}
}
}
LoadPanel();
}
// 加载服务器文件列表
void LoadRemoteAsset()
{
if (Directory.Exists(localAssetPath))
{
string[] oldFiles = Directory.GetFiles(localAssetPath);
for (int i = 0; i < oldFiles.Length; i++)
{
File.Delete(oldFiles[i]);
}
Directory.Delete(localAssetPath);
Directory.CreateDirectory(localAssetPath);
}
string[] files = Directory.GetFiles(remoteAssetPath);
for (int i = 0; i < files.Length; i++)
{
string fileName = files[i].Substring(files[i].LastIndexOf("/", StringComparison.Ordinal) + 1);
File.Copy(remoteAssetPath + fileName, localAssetPath + fileName);
}
}
// 加载UI
void LoadPanel()
{
LoadAssetBundleInstance("luahotupdate_ui.ab", "Panel", transform);
}
public static GameObject LoadAssetBundleInstance(string bundleName, string objName, Transform parent = null)
{
AssetBundle bundle = LoadAssetBundle(bundleName);
GameObject obj = bundle.LoadAsset<GameObject>(objName);
return Instantiate(obj, parent);
}
// 加载AssetBundle包以及依赖文件
public static AssetBundle LoadAssetBundle(string bundleName)
{
if (manifest == null)
{
string platStr = "";
#if UNITY_STANDALONE_WIN
platStr = "Windows";
#elif UNITY_STANDALONE_OSX
platStr = "Mac OS";
#elif UNITY_IOS
platStr = "IOS";
#elif UNITY_ANDROID
platStr = "Android";
#endif
AssetBundle platBundle = AssetBundle.LoadFromFile(localAssetPath + platStr);
manifest = platBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
if (bundleCaches.ContainsKey(bundleName))
{
return bundleCaches[bundleName];
}
else
{
AssetBundle bundle = AssetBundle.LoadFromFile(localAssetPath + bundleName);
bundleCaches[bundleName] = bundle;
// 注意:GetAllDependencies会返回直接和间接关联的AssetBundle
string[] depends = manifest.GetAllDependencies(bundleName);
for (int i = 0; i < depends.Length; i++)
{
if (!bundleCaches.ContainsKey(depends[i]))
{
AssetBundle depAB = AssetBundle.LoadFromFile(localAssetPath + depends[i]);
bundleCaches[depends[i]] = depAB;
}
}
return bundle;
}
}
}
}
🔚