只记录学习,这些类和操作比较繁琐,一定要仔细,一定要仔细,一定要仔细!!!
既然是要打包,那这里写一个类打包,这个类比较特殊,熟练运用后,可以写插件。
这个脚本需要放在Assets下建一个Editor文件里面
引入命名空间:using UnityEditor;
和文件留的命名空间:using System.IO;
这里会创建一个文件夹streamingAssets,将打包后的文件都放在这个文件夹下面
using UnityEditor;
using System.IO;
public class TextEditor : Editor
{
//写插件
[MenuItem("NewItem/Cube")]
public static void Create()
{
//资源打包
string path=Application.streamingAssetsPath;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);//创建streamingAssets文件夹
}
//打包
BuildPipeline.BuildAssetBundles(path,
BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
}
}
这个脚本不需要挂载 会出现在工具栏中每次打包 都需要重新执行
这里创建了一个文件 并给上了包名,你所有要打包的东西这里都要给上包名,这里我只截下一个,在原脚本那种还有一个球的预制体也打包了
加载文件有3中方法
public class TestAB : MonoBehaviour
{
string path=Application.streamingAssetsPath+"/qiu";//qiu:打包后的预设文件
void Start()
{
StartCoroutine(LoadFromMemory(path));//1
LoadFile();//2
StartCoroutine(LoadFromServer());//3
}
//1.重内存中异步加载
IEnumerator LoadFromMemory(string name)
{
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(name));//打包后的预设
yield return request;
AssetBundle ab=request.assetBundle;
GameObject go = ab.LoadAsset<GameObject>("qiu");//qiu 原文件
Instantiate(go);
ab.Unload(false);//卸载资源和资源包
}
//2.从本地加载
void LoadFile()
{
AssetBundle ab = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "qiu"));//打包后的预设
GameObject qiu= ab.LoadAsset<GameObject>("qiu");//qiu 原文件
Instantiate(qiu);
ab.Unload(false);//卸载资源和资源包
}
//3.重服务器上加载
IEnumerator LoadFromServer()
{
string path = "file:///" + Application.streamingAssetsPath + "/qiu";//打包后的预设
UnityWebRequest request=UnityWebRequestAssetBundle.GetAssetBundle(path);
yield return request.SendWebRequest();
AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
GameObject qiu = ab.LoadAsset<GameObject>("qiu");//qiu 原文件
Instantiate(qiu);
ab.Unload(false);//卸载资源和资源包
}
void Update()
{
}
}
这里还有一个方法可以找出对应的文件 他的所有一栏关系文件
public class TestAB : MonoBehaviour
{
string path=Application.streamingAssetsPath+"/qiu";//qiu:打包后的预设文件
//加载配置文件
void LoadManifest()
{
AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/StreamingAssets");
AssetBundleManifest abm = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] s = abm.GetAllDependencies("qiu");//qiu 材质包的名字 找出他所有的依赖关系
foreach (var item in s)
{
print(item);
}
ab.Unload(false);//卸载资源和资源包
}
}
下面就是把打包后的文件上传服务器,因为这里我是记录学习我在这里建立一个Server作为服务器,Client作为客户端
我们需要把打包后的文件手动复制一份到Server文件下面
下面我们将用代码将文件上传到客户端,并用热更新实现更新
using UnityEngine.Networking;
using System.IO;
public class DownLoad : MonoBehaviour
{
public AssetBundle ab;
void Start()
{
StartCoroutine(Load());
}
//从服务器上加载文件到客户端
IEnumerator Load()
{
string path = "file:///" + Application.dataPath + "/Server/qiu";//Server 服务器端
UnityWebRequest request= UnityWebRequestAssetBundle.GetAssetBundle(path);
yield return request.SendWebRequest();
ab = DownloadHandlerAssetBundle.GetContent(request);
TextAsset ta = ab.LoadAsset<TextAsset>("qiu.lua.txt");//配置文件
string newPath = Application.dataPath + "/Client/qiu.lua.txt";//Client 客户端
File.WriteAllText(newPath, ta.text);
}
}
接下来是热更新,需要注意的是这里不是Lua文件而是txt文件
首先写一个允许热更新的类 挂载在摄像机上
using XLua;
[Hotfix]
public class Test : MonoBehaviour
{
private GameObject cube;
void Start()
{
cube = Resources.Load<GameObject>("Cube");
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Instantiate(cube);
}
}
}
写一个热更新文件
这里通过代码去获取摄像机上的脚本
通过脚本去获取客户端上的ab包,去对类进行热更新
engine=CS.UnityEngine
xlua.hotfix(CS.Test,'Update',
function(self)
if engine.Input.GetMouseButtonDown(0) then
camera=engine.GameObject.Find('Main Camera')
download=camera:GetComponent('DownLoad')
ab=download.ab
qiu=ab:LoadAsset('qiu')
engine.GameObject.Instantiate(qiu)
end
end
)
下面是一个打开和关闭文件的类,单独写成一个类,方便后面调用(当然,如果你只是实验打包操作,只要调用一次,就可以不用)这个类写成单例,以后需要打开文件可以直接调用这个类的方法,就不用每次去写打开和关闭文件操作了(这也算一个简单的框架,方便调用)
需要注意的是,你的文件后缀名,有多个不同的后缀名时,协程多个方法即可
using System.IO;
using XLua;
public class XLuaManager
{
//调用lua文件的简单框架
//单例
private XLuaManager() { }
private static XLuaManager instance=null;
public static XLuaManager Instance
{
get
{
if(instance == null)
{
instance = new XLuaManager();
Init();
}
return instance;
}
}
public static LuaEnv lua;
static void Init()//初始化lua文件
{
lua=new LuaEnv();
lua.AddLoader(FileLoader);
}
static byte[] FileLoader(ref string fileName)
{
string path = Application.dataPath + "/Lua/" + fileName + ".lua.txt";
return File.ReadAllBytes(path);
}
public void Dostring(string str)
{
lua.DoString(str);
}
public void Dispose()//释放资源
{
lua.Dispose();
}
}
现在是实现热更新的最后一步,调用文件
public class TestLua : MonoBehaviour
{
void Start()
{
XLuaManager.Instance.Dostring("require('qiu')");
}
}
这里就实现了框架的好处,当你需要打开文件时,只需要调用方法,将你需要打开的文件名作为参数传进去即可。