美文网首页奇哥Unity
Unity+SLua的一些小零碎(1)

Unity+SLua的一些小零碎(1)

作者: 慢慢来比较快_ | 来源:发表于2020-04-08 15:51 被阅读0次

    解决package.path问题

    Unity版本:2019.3.4f1
    SLua版本:1.7.0
    .NET : 4.7.1

    初始化
    1. 解压SLua源码,把Assets的Plugins和Slua两个文件夹拷贝到Unity工程的Assets下即可,然后执行Slua->All->Make,即可生成Slua导出的C#文件。
      这里会提示checkParams错误,原因是缺少了Vector4[]的checkParams函数,又无法通过模板函数转换,所以只需要在 LuaObject_overload.cs 里拷贝以下Vector2[]的checkParams代码,改成了Vector4[]就好了。
    package.path问题

    1.SLua默认是从Resources加载lua文件的,而且lua文件后缀必须是txt,这样约束太大。作者的回答
    2.作者提供了LoaderDelegate,以方便定制lua加载策略。

    方案:

    1.指定初始化的package.path,指向main.lua目录即可。
    2.定义一个FileUtils工具类,主要负责:1.处理文件的读取 2.判断文件是否存在
    3.定义一个LoaderDelegate,赋值给LuaSvr.mainState.loaderDelegate

    步骤1

    在LuaState.cs init()中添加,至于getSearchPath就因工程目录设计而异了,反正指向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(未在真机验证
    参考: unity3d 在安卓平台通过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实例
            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
            //打开文件流
            var stream = assetManager.Call<AndroidJavaObject>("open", filePath);
            if(stream == null)
                return fasle;
            //获取文件长度
            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");
    
            //申请一个Java ByteArray对象句柄
            var byteArray = AndroidJNI.NewByteArray(availableBytes);
            //调用方法
            int readCount = AndroidJNI.CallIntMethod(stream.GetRawObject(), METHOD_read, new[] { new jvalue() { l = byteArray } });
            //从Java ByteArray中得到C# byte数组
            var bytes = AndroidJNI.FromByteArray(byteArray);
            //删除Java ByteArray对象句柄
            AndroidJNI.DeleteLocalRef(byteArray);
            //关闭文件流
            stream.Call("close");
            stream.Dispose();
            //返回结果
            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

    在初始化脚本里,设置一下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;
            };
        }
    }
    

    总结:

    至此,就可以往packaget.path里添加多个搜索路径,而不受Resource约束。

    相关文章

      网友评论

        本文标题:Unity+SLua的一些小零碎(1)

        本文链接:https://www.haomeiwen.com/subject/ktptmhtx.html