解決package.path問(wèn)題
Unity版本:2019.3.4f1
SLua版本:1.7.0
.NET : 4.7.1
初始化
- 解壓SLua源碼赋兵,把Assets的Plugins和Slua兩個(gè)文件夾拷貝到Unity工程的Assets下即可,然后執(zhí)行Slua->All->Make搔预,即可生成Slua導(dǎo)出的C#文件霹期。
這里會(huì)提示checkParams錯(cuò)誤,原因是缺少了Vector4[]的checkParams函數(shù)拯田,又無(wú)法通過(guò)模板函數(shù)轉(zhuǎn)換历造,所以只需要在 LuaObject_overload.cs 里拷貝以下Vector2[]的checkParams代碼,改成了Vector4[]就好了勿锅。
package.path問(wèn)題
1.SLua默認(rèn)是從Resources加載lua文件的帕膜,而且lua文件后綴必須是txt,這樣約束太大溢十。作者的回答
2.作者提供了LoaderDelegate垮刹,以方便定制lua加載策略。
方案:
1.指定初始化的package.path张弛,指向main.lua目錄即可荒典。
2.定義一個(gè)FileUtils工具類酪劫,主要負(fù)責(zé):1.處理文件的讀取 2.判斷文件是否存在
3.定義一個(gè)LoaderDelegate,賦值給LuaSvr.mainState.loaderDelegate
步驟1
在LuaState.cs init()中添加寺董,至于getSearchPath就因工程目錄設(shè)計(jì)而異了覆糟,反正指向main.lua就好了
LuaDLL.lua_getglobal(L, "package");
LuaDLL.lua_pushstring(L, getSearchPath());
LuaDLL.lua_setfield(L, -2, "path");
LuaDLL.lua_pop(L, 1);
步驟2
FilUtils:(主要處理Win、安卓和iOS遮咖,安卓是利用AndroidJNI(未在真機(jī)驗(yàn)證)
參考: unity3d 在安卓平臺(tái)通過(guò)Native接口直接讀取apk中assets目錄下的文件
]
using UnityEngine;
using System.IO;
using System;
using SLua;
public class FileUtils
{
private static FileUtils Instance;
#if UNITY_ANDROID
AndroidJavaObject assetManager
#endif
private FileUtils()
{
#if UNITY_ANDROID
var activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
//從Activity取得AssetManager實(shí)例
assetManager = activity.Call<AndroidJavaObject>("getAssets");
#endif
}
public static FileUtils GetInstance()
{
if (Instance == null)
{
Instance = new FileUtils();
}
return Instance;
}
public bool isFileExist(string filePath)
{
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_IPHONE
return File.Exists(filePath);
#elif UNITY_ANDROID
var stream = assetManager.Call<AndroidJavaObject>("open", filePath);
if(stream)
{
stream.Call("close");
stream.Dispose();
return true;
}
return false;
#endif
}
public bool getContents(string filePath, out byte[] bytes, out int len)
{
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_IPHONE
FileStream stream = new FileStream(filePath, FileMode.Open);
bool ret = false;
bytes = null;
len = 0;
if (null != stream)
{
len = (int)stream.Length;
bytes = new byte[len];
int readLend = stream.Read(bytes, 0, len);
stream.Flush();
stream.Close();
ret = readLend == len;
}
return ret;
#elif UNITY_ANDROID
//打開(kāi)文件流
var stream = assetManager.Call<AndroidJavaObject>("open", filePath);
if(stream == null)
return fasle;
//獲取文件長(zhǎng)度
var availableBytes = stream.Call<int>("available");
//取得InputStream.read的MethodID
var clsPtr = AndroidJNI.FindClass("java.io.InputStream");
var METHOD_read = AndroidJNIHelper.GetMethodID(clsPtr, "read", "([B)I");
//申請(qǐng)一個(gè)Java ByteArray對(duì)象句柄
var byteArray = AndroidJNI.NewByteArray(availableBytes);
//調(diào)用方法
int readCount = AndroidJNI.CallIntMethod(stream.GetRawObject(), METHOD_read, new[] { new jvalue() { l = byteArray } });
//從Java ByteArray中得到C# byte數(shù)組
var bytes = AndroidJNI.FromByteArray(byteArray);
//刪除Java ByteArray對(duì)象句柄
AndroidJNI.DeleteLocalRef(byteArray);
//關(guān)閉文件流
stream.Call("close");
stream.Dispose();
//返回結(jié)果
return bytes;
#endif
}
public bool getLuaFileFullPath(IntPtr L, string fileName, out string fullPath)
{
LuaDLL.lua_getglobal(L, "package");
LuaDLL.lua_getfield(L, -1, "path");
string searchpath = LuaDLL.lua_tostring(L, -1);
LuaDLL.lua_pop(L, 2);
int begin = 0;
int next = 0;
bool found = false;
fullPath = string.Empty;
do
{
next = searchpath.IndexOf(";", begin);
if (next == -1)
next = searchpath.Length;
string prefix = searchpath.Substring(begin, next - begin);
if (!string.IsNullOrEmpty(prefix))
{
fullPath = prefix.Replace("?", fileName);
if (isFileExist(fullPath))
{
found = true;
break;
}
}
begin = next + 1;
} while (begin < searchpath.Length);
return found;
}
}
步驟3
在初始化腳本里滩字,設(shè)置一下Loader
public class Init : MonoBehaviour
{
LuaSvr l;
// Use this for initialization
void Start()
{
l = new LuaSvr();
setLoader(LuaSvr.mainState);
l.init(null, () =>
{
l.start("main");
});
}
void setLoader(LuaState state)
{
state.loaderDelegate = (string fn, ref string absoluteFn) =>
{
string strFullPath;
bool found = FileUtils.GetInstance().getLuaFileFullPath(state.L, fn, out strFullPath);
if(found)
{
byte[] bytes = null;
int len = 0;
if (FileUtils.GetInstance().getContents(strFullPath, out bytes, out len))
return bytes;
}
return null;
};
}
}
總結(jié):
至此,就可以往packaget.path里添加多個(gè)搜索路徑御吞,而不受Resource約束麦箍。