日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

加密 lua_三、Lua相关知识

發布時間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 加密 lua_三、Lua相关知识 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、lua語言基礎

1、metatable

2、pairs、ipairs、table.sort

3、table的內存(數組結構和哈希結構)

4、字符串緩存(字符串常量是共享的。這個5.3版本有調整,40字節一下的短字符串才是共享的,長字符串還是保持獨立內存)。所以配置文件中存在大量重復的字符串并不是很耗內存。

  反而是配置中存在大量的數字或者是嵌套的table的時候,非常耗內存。

5、lua本身的協程不支持常用的 WaitForSeconds 的功能。xlua通過Coroutine_Runner.cs 這個文件實現了這個功能。

二、lua和C#如何進行交互

1、通過lua state堆棧進行交互。

2、C#通過 lua_pushnumber 、lua_pushboolean、lua_pushstring、lua_pushlstring等接口傳遞參數。然后通過lua_pcall 調用函數。

3、lua調用C#,在C#的wrap函數中,通過lua_tonumber、lua_tostring等接口獲取參數。執行后的結果可以通過lua_pushXXX 返回給lua。

4、lua_pushstring 傳遞一個字符串給lua。內部會使用strlen計算字符串長度。0結尾。

  lua_pushlstring 傳遞一個buffer給lua。指定長度。

5、userdata。C#或者C++的類對象傳遞給lua,使用的是userdata。在XLua中ObjectTranslator就負責維護這些userdata。

6、C#怎么導出類型給lua的。

  通過Registry (注冊表,LUA_REGISTRYINDEX)。這是一個全局table。只能被C代碼訪問。xlua把CS這個對象放在LUA_REGISTRYINDEX上,并通過生成的wrap文件,把所有C#類型都放在CS對象上。于是lua中就可以通過 http://CS.XXX訪問C#的對象了。比如CS.UnityEngine.GameObject或者CS.Actor。

7、C#怎么調用lua的函數。

  函數應該通過字符串名字獲取到,或者通過lua使用參數傳遞過來。這個LuaFunction對象可以保存起來。

  通過lua_getref把函數放到棧頂,通過lua_pushXXX把參數壓棧,然后通過lua_pcall執行函數。如果有返回值則通過lua_toXXX在-1(棧頂位置)獲取到lua的返回值,在xlua中返回的一般都是TResult對象。最后通過lua_settop恢復棧頂。

8、通過luaState.AddBuildin接口,可以添加C模塊或者自定義模塊。

三、lua面向對象

1、通過metatable實現class

2、lua訪問一個table會先看有沒有對應的字段(可以是變量或者函數),如果沒有的話,會查找metable的__index。這個索引可以是一個function,也可以是一個table。如果__index也無法取到對應的變量則返回nil。

  另外一個是__newindex。它會在給table中不存在的字段賦值的時候調用。

3、class會返回一個table。它的metatable會指定為父類類型。這個返回的table就是一個lua中定義的類型了,我們會給它添加各種函數定義。

  當new的時候,會返回一個新的table,它的metatable會設置為class返回的這個類型table。這樣當訪問一個函數的時候,就會從當前對象的table--》類型table--》父類的table,這樣的順序去查找函數。從而實現面向對象中常用的多態(override)。

4、另外需要注意,我們只有函數是放在類型table上的,這個是所有對象共用的。而變量字段是通過ctor的遞歸調用直接賦值到對象table上的。也就是說變量是歸對象的,函數是歸類型的。

  這么設計符合直覺,有利于減少內存,也不用擔心父子類之間變量沖突。

5、調用父類的正確寫法。比如 Hero 繼承自 Player 繼承自 Animal

  self.super.Move(self, x, y, z)。而不能直接 self.super:Move(x, y, z)。因為后者由于lua的語法糖,傳遞給Move的參數是super,而實際上這個時候我們期望傳遞的是self。

  當有三層繼承的調用的時候,上述寫法也是有問題的。因為第二層調用依然是self.super.Move,會形成死循環。這個時候正確的調用方式是使用類型名調用。比如 Player.Move(self, x, y, z)。

四、實際項目經驗

1、使用luajit2.1的版本。luajit性能很高,比lua可能高5~10倍。但是也要小心極端情況下可能會有jit失效的問題。這個時候代碼無法jit,而又重復嘗試jit,反而會導致性能降低。

2、luajit對應的lua版本是5.1。支持少量5.2的功能。不支持5.3的int。不支持_Env。

3、luajit在iOS下沒有開啟jit功能。因為蘋果政策問題,關鍵api沒有權限調用。不過多數情況luajit依然要比lua快,所以在iOS下我們也是使用luajit。

4、ios下編譯的是64位bytecode。不兼容32位的cpu。所以iPad1,iPhone5及以下的機型要么舍棄掉。要么同時再編譯一份32位的bytecode,運行時根據機器cpu決定讀取哪個腳本文件。我們的選擇是放棄iPad1這樣的老舊設備。

5、編輯器下使用luajit,總是會導致編輯器崩潰。原因未知。換成lua5.1的版本就好了。

  也就是說我們對外發布使用的是luajit,編輯器下使用的是lua5.1。

6、我們lua代碼做了幾層加密。luajit編譯為bytecode是一層,aes加密是一層,lz4壓縮是一層。

  因為aes和lz4都是非常快的算法,尤其是在讀取的時候,所以性能上問題不大。

7、我們之前的lua代碼傾向是打包在固定的幾個文件的ab包內。不過后來隨著代碼量的逐漸增大,gui.ab、config.ab和logic.ab越來越大。更新一個版本補丁最小也要八九兆。后面這三個目錄還是按照子目錄打包。目的是減少更新補丁的大小。

8、隨著代碼量增大,我們打包的時候編譯lua可能要占用三分鐘時間。所以打包的時候維護了一個當前lua.bytes的緩存,記錄了每個lua文件的md5。如果md5一致的話,就不重新編譯。這樣節約了打包的時間。

五、Lua代碼熱加載(Hot Reload)

1、熱加載不同于熱更新,服務器可以用來不關服修正線上問題(動態更新),客戶端主要方便開發時不關閉游戲就重載更新后的代碼,提高開發效率。

2、檢測哪些文件發生改變(被修改了),這個原本使用的是C#的FileSystemWatcher,不過貌似很不穩定。經常導致Unity卡死,原因未知。

  也考慮過做一個VSCode的插件,然后使用socket通知Unity,不過感覺方案比較復雜,別人使用起來也比較復雜。

  最后的解決方案是使用Go(或其他語言)實現一個獨立的監控文件改變的進程。Unity開啟新進程監控文件變化。進程之間通過stdout的返回值進行通信。最終可以準確識別的文件的改變,也不會導致Unity卡死。

3、獲取到的變化文件列表,不要在子線程處理。統一丟到主線程通知lua處理。

4、package.loaded[xxx] = nil。先把已加載文件的緩存清空。

5、重新require文件,替換保存的upvalue。

6、最終達成的效果是,某個函數添加了日志或者修改了邏輯,會自動修改生效,而不用重啟游戲。

7、補充說明的是,只有全局變量有這么處理的必要。像我們的界面是local變量,那么只要關掉界面的時候把 package.loaded 置空,再次打開界面就可以重新加載修改后的文件。

六、Lua的調試

1、不同的IDE插件(VSCode+luaidelite,或者IDEA+EmmyLua),有不同的LuaDebug.lua的代碼。

  但是本質上都是游戲運行時開啟一個socket,設置斷點的時候就直接sleep掉主線程。等插件繼續運行游戲的時候,就是socket通知游戲,取消sleep。

2、各種變量信息可以通過 debug.getinfo 獲取。

七、Lua的性能分析

1、推薦 Miku-LuaProfiler。提供了可視化的Unity窗口界面,看著非常直觀。

2、本質上是使用 debug.sethook 監控函數的執行,在開始和結束的位置打點,最后統計分析哪些是耗時函數。

3、內存分析

3.1、善用 collectgarbage("count"),獲取當前的lua內存。

3.2、做內存分析之前,先執行 collectgarbage("stop"),停止GC,否則運行過程中可能觸發gc導致數據不準確。

3.3、在切換場景或者其他必要情景,執行 collectgarbage("collect"),進行gc。

總結

以上是生活随笔為你收集整理的加密 lua_三、Lua相关知识的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。