[Unity热更新]tolua# & LuaFramework(二):打包工具

时间:2021-08-29 18:39:33

1.资源的创建

[Unity热更新]tolua# & LuaFramework(二):打包工具

注意一下命名规则,一个面板及其相关的东西都放在同一个文件夹中,如果文件夹命名为xxx,则面板预制要命名为xxxPanel


2.打包

以文件夹为单位进行打包,打包类为Packager.cs。这里要打包的东西分两种,一种为图片等资源,另一种为代码资源(即lua脚本)。对lua脚本的打包已经被框架搞好了,不需要我们考虑,我们要考虑的是对前者的打包,详细的见Packager.cs的HandleExampleBundle方法,这里我做了个小工具:

using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
using System.IO;
using System.Text;

public enum SuffixEnum
{
Prefab,
Png,
Csv,
Txt,
}

public class AddBuildMapUtility : EditorWindow {

int count = 0;
List<string> bundleNameList = new List<string>();
List<SuffixEnum> suffixList = new List<SuffixEnum>();
List<string> pathList = new List<string>();

Vector2 scrollValue = Vector2.zero;

[MenuItem("LuaFramework/AddBuildMapUtility")]
static void SetAssetBundleNameExtension()
{
EditorWindow.GetWindow<AddBuildMapUtility>();
}

void OnGUI()
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("添加一项"))
{
AddItem();
}
if (GUILayout.Button("清除所有项"))
{
Clear();
}
if (GUILayout.Button("读取文件(.csv)"))
{
Clear();

string path = EditorUtility.OpenFilePanel("", Application.dataPath, "csv");
string content = File.ReadAllText(path);
string[] contents = content.Split(new string[] { "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries);

for (int i = 0; i < contents.Length; i++)
{
string[] a = contents[i].Split(',');
AddItem(a[0], StringToEnum(a[1]), a[2]);
}
}
if (GUILayout.Button("保存"))
{
string path = EditorUtility.SaveFilePanel("", Application.dataPath, "AssetBundleInfo", "csv");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++)
{
if (string.IsNullOrEmpty(bundleNameList[i])) break;
sb.Append(bundleNameList[i] + ",");
sb.Append(EnumToString(suffixList[i]) + ",");
sb.Append(pathList[i] + "\r\n");
}
File.WriteAllText(path, sb.ToString());
AssetDatabase.Refresh();
}
if (GUILayout.Button("自动填写(所有选中的)"))
{
int startIndex = count;
for (int i = 0; i < Selection.objects.Length; i++)
{
AddItem();
AutoFill(startIndex, Selection.objects[i]);
startIndex++;
}
}
EditorGUILayout.EndHorizontal();

EditorGUILayout.LabelField("注意:请以文件夹为单位进行选择!!!文件夹名即为包名!!!");

scrollValue = EditorGUILayout.BeginScrollView(scrollValue);
for (int i = 0; i < count; i++)
{
EditorGUILayout.BeginVertical();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(i.ToString() + "AB包名");
bundleNameList[i] = EditorGUILayout.TextField("", bundleNameList[i]);
suffixList[i] = (SuffixEnum)EditorGUILayout.EnumPopup("类型", suffixList[i]);
pathList[i] = EditorGUILayout.TextField("路径", pathList[i]);

if (GUILayout.Button("自动填写(单个)"))
{
AutoFill(i, Selection.objects[0]);
}
if (GUILayout.Button("输出路径"))
{
Debug.Log(pathList[i]);
}
if (GUILayout.Button("删除该项"))
{
RemoveItem(i);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndScrollView();
}

void Clear()
{
count = 0;
bundleNameList = new List<string>();
suffixList = new List<SuffixEnum>();
pathList = new List<string>();
}

void AddItem(string bundleName = "", SuffixEnum suffix = SuffixEnum.Prefab, string path = "")
{
count++;
bundleNameList.Add(bundleName);
suffixList.Add(suffix);
pathList.Add(path);
}

void RemoveItem(int index)
{
count--;
bundleNameList.Remove(bundleNameList[index]);
suffixList.Remove(suffixList[index]);
pathList.Remove(pathList[index]);
}

void AutoFill(int index, Object selectedObject)
{
string path = AssetDatabase.GetAssetPath(selectedObject);
bundleNameList[index] = path.Remove(0, path.LastIndexOf("/") + 1).ToLower() + LuaFramework.AppConst.ExtName;

string[] files = Directory.GetFiles(path);
string[] temp = files[0].Split('.');
suffixList[index] = StringToEnum("*." + temp[1]);

pathList[index] = path;
}

public static string EnumToString(SuffixEnum se)
{
switch (se)
{
case SuffixEnum.Prefab:
return "*.prefab";
case SuffixEnum.Png:
return "*.png";
case SuffixEnum.Csv:
return "*.csv";
case SuffixEnum.Txt:
return "*.txt";
default:
return "null";
}
}

public static SuffixEnum StringToEnum(string s)
{
switch (s)
{
case "*.prefab":
return SuffixEnum.Prefab;
case "*.png":
return SuffixEnum.Png;
case "*.csv":
return SuffixEnum.Csv;
case "*.txt":
return SuffixEnum.Txt;
default:
return SuffixEnum.Prefab;
}
}

}



[Unity热更新]tolua# & LuaFramework(二):打包工具


然后对HandleExampleBundle这个方法进行修改:

UGUI版本:

    static void HandleExampleBundle()
{
string resPath = AppDataPath + "/" + AppConst.AssetDir + "/";
if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath);

//AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt");
//AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message");

//AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt");
//AddBuildMap("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared");

string content = File.ReadAllText(Application.dataPath + "/AssetBundleInfo.csv");
string[] contents = content.Split(new string[] { "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < contents.Length; i++)
{
string[] a = contents[i].Split(',');
//UnityEngine.Debug.Log(a[0]); UnityEngine.Debug.Log(a[1]); UnityEngine.Debug.Log(a[2]);
AddBuildMap(a[0], a[1], a[2]);
}
}

NGUI版本:

NGUI版本有些不同,它使用的是4.x的打包方式,为了配合5.x的打包,需要修改一下:

[Unity热更新]tolua# & LuaFramework(二):打包工具

    static void HandleExampleBundle(BuildTarget target) {
Object mainAsset = null; //主素材名,单个
Object[] addis = null; //附加素材名,多个
string assetfile = string.Empty; //素材文件名

BuildAssetBundleOptions options = BuildAssetBundleOptions.UncompressedAssetBundle |
BuildAssetBundleOptions.CollectDependencies |
BuildAssetBundleOptions.DeterministicAssetBundle;
string dataPath = Util.DataPath;
if (Directory.Exists(dataPath)) {
Directory.Delete(dataPath, true);
}
string assetPath = AppDataPath + "/StreamingAssets/";
if (Directory.Exists(dataPath)) {
Directory.Delete(assetPath, true);
}
if (!Directory.Exists(assetPath)) Directory.CreateDirectory(assetPath);

/////-----------------------------生成共享的关联性素材绑定-------------------------------------
//BuildPipeline.PushAssetDependencies();

//assetfile = assetPath + "shared" + AppConst.ExtName;
//mainAsset = LoadAsset("Shared/Atlas/Dialog.prefab");
//BuildPipeline.BuildAssetBundle(mainAsset, null, assetfile, options, target);

/////------------------------------生成PromptPanel素材绑定-----------------------------------
//BuildPipeline.PushAssetDependencies();
//mainAsset = LoadAsset("Prompt/Prefabs/PromptPanel.prefab");
//addis = new Object[1];
//addis[0] = LoadAsset("Prompt/Prefabs/PromptItem.prefab");
//assetfile = assetPath + "prompt" + AppConst.ExtName;
//BuildPipeline.BuildAssetBundle(mainAsset, addis, assetfile, options, target);
//BuildPipeline.PopAssetDependencies();

/////------------------------------生成MessagePanel素材绑定-----------------------------------
//BuildPipeline.PushAssetDependencies();
//mainAsset = LoadAsset("Message/Prefabs/MessagePanel.prefab");
//assetfile = assetPath + "message" + AppConst.ExtName;
//BuildPipeline.BuildAssetBundle(mainAsset, null, assetfile, options, target);
//BuildPipeline.PopAssetDependencies();

/////-------------------------------刷新---------------------------------------
//BuildPipeline.PopAssetDependencies();


//////////////////////////////////////////////////////////////////////////////
string content = File.ReadAllText(Application.dataPath + "/AssetBundleInfo.csv");
string[] contents = content.Split(new string[] { "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < contents.Length; i++)
{
string[] a = contents[i].Split(',');
//UnityEngine.Debug.Log(a[0]); UnityEngine.Debug.Log(a[1]); UnityEngine.Debug.Log(a[2]);
AddBuildMap(a[0], a[1], a[2]);
}

string resPath = "Assets/" + "StreamingAssets";
BuildAssetBundleOptions option = BuildAssetBundleOptions.DeterministicAssetBundle |
BuildAssetBundleOptions.UncompressedAssetBundle;
BuildPipeline.BuildAssetBundles(resPath, maps.ToArray(), option, target);
maps.Clear();
}

static List<AssetBundleBuild> maps = new List<AssetBundleBuild>();
static void AddBuildMap(string bundleName, string pattern, string path)
{
string[] files = Directory.GetFiles(path, pattern);
if (files.Length == 0) return;

for (int i = 0; i < files.Length; i++)
{
files[i] = files[i].Replace('\\', '/');
}
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = bundleName;
build.assetNames = files;
maps.Add(build);
}


那么,每一次打包,先点击LuaFramework/AddBuildMapUtility,准备好AB包的信息,然后点击LuaFramework/Build xxx Resource来进行打包,在window平台下,检查Assets\StreamingAssets中的资源是否正确。还有最重要的一点,每次对lua文件或者其他资源更改后,都要点击菜单栏LuaFramework/Build xxx Resource来重新打包!



3.编写
a.在Assets\LuaFramework\Lua下的Controller和View下,模仿编写lua
b.在CtrlManager、Game、define这三个lua文件中模仿添加修改东西


4.运行

建立一个空物体,挂上Main脚本,在Canvas(UGUI版本的框架)下建一个空物体,赋予GuiCamera这个tag,将位置和宽高置0,然后拉伸宽高,然后运行,这样就可以了!



Ps:

NGUI版本注意点:

1.打包运行后可能会提示FileNotFoundException: Could not find file "c:\luaframework\shared.unity3d".这个错误,追踪错误到ResourceManager.cs中的initialize方法,如果AppConst.ExampleMode为true,则需要shared.unity3d这个AB包。因此,打包的时候需要把shared文件夹也选上哦。。

2.生成的面板会在GUI这个物体下,那么如何修改这个物体呢?找到GameManager.cs中的InitGui方法,修改一下即可。GUI这个预制体,可以在Project视图搜索即可。