IOS不能熱更新,不是因為不能用反射,是因為
System.Reflection.Assembly.Load 無法使用
System.Reflection.Emit 無法使用
System.CodeDom.Compiler 無法使用
這三個不能用,就把傳統dotnet動態路徑坑死了
為啥“這三個不能用,就把傳統dotnet動態路徑坑死了”呢
動態載入dll或者cs的方法就這幾個, IOS 下不能動態載入dll或者cs 文件,已經編譯進去的沒事。
=========================================================
盡量只把U3D當一個渲染引擎來看待, 不然你會發現熱更資源很悲劇, 資源一定要與邏輯分開, 因為U3D用的是類的序列化, 后期改動會導致前面導出的資源不能用。就和開發AS3游戲差不多了。可以這么理解
1.prefab盡量不去綁定腳本,盡量在代碼里AddComponent<接口實現腳本>,在實例prefab的GetComponent<接口腳本>.接口操作。
2.prefab可以綁定那些不會再改動的腳本。
============================================================
插件下載地址:
http://ulua.org/
toLua下載地址:
https://github.com/topameng/CsToLua
阿萌對ULUA1.03的BUG修改文章:
http://user.qzone.qq.com/5281069/blog/1408526450?ptlang=2052&ADUIN=522414019&ADSESSION=1425950543&ADTAG=CLIENT.QQ.5396_.0&ADPUBNO=26442
蠻牛上找的關於ULUA的文章:
Unity中使用ulua的個人經驗總結
http://www.unitymanual.com/blog-27966-2568.html?_dsign=0c1fb317
==============寫LUA相關的工具==============
BabeLua-vs2012-and-vs2013插件:
設置參考http://www.cocoachina.com/bbs/read.php?tid=205043
使用技巧http://blog.csdn.net/babestudio
LuaStudio,請使用Administrator管理員權限,否則會掛死!!!
==============uLua插件導入到unity3d常見問題==============
導入uLua插件運行自帶的例子報錯問題:DllNotFoundException: 這個在其老外寫的README里已經說了如何解決。
(1)將plugins目錄放到最外面,重啟unity。
(2)真機沒有打包libulua.so進包導致,或者模擬器也有些設置不對。打包的時候把libulua.so打包進libs\armeabi-v7a
EntryPointNotFoundException: 解決方案:
EntryPointNotFoundException:這個類型錯誤不太單一,可選擇下面2中方法解決:(方案1)把除了Assets跟 ProjectSettings目錄之外的都刪除掉,重新打開工程。(方案2)如果在MAC上,選擇IOS平台,很容易出現,切換到MAC/PC平台基本 上就解決了,你不能要求在MAC下一定要運行IOS的動態庫。
0.16框架報錯解決辦法:
0.16框架基於u3d4.6,所以在老版本的u3d打開會報錯,如果是老版本的話把LuaWrap除了Base目錄外所有的Wrap cs文件刪掉,然后lua clear菜單調用下就好了。
attempt to index global 'UnityEngine':
uaScriptException: [string "define.lua"]:1: attempt to index global 'UnityEngine' (a nil value)解決:生成wrap文件。
tolua c#簡單使用方法:
打開Editor/BindLua.cs文件,在static BindType[] binds = new BindType[]變量末尾一行加入要導入的cs類,比如Resources類,保存等u3d編譯完后,選擇“Lua/Gen LuaBinding Files”編譯即可,以后就可以在lua里面使用此類了,而不要導入進來。映射public成員
C#里面有個編輯器工具類可以用Wrap映射到lua里使用
public static class LuaBinder {
public static void Bind(IntPtr L) {
ObjectWrap.Register(L);
}
}
這個等價於我們之前在lua中寫的
luanet.import_type("UnityEngine.Object")
lua腳本里在定義基礎類型的時候
Object = luanet.import_type("UnityEngine.Object")
Object = UnityEngine.Object
這兩種寫法有區別嗎,還是隨便寫哪個都行?
用后者 效率高。前者是反射
_lua_tocbuff 是阿萌自己添加的,用於xml
_luaopen_ffi 是luajit的,
_luaopen_luaXML
刪掉函數聲明即可
lua的loop庫可以正常用在ulua里嗎
看庫是否用到了c++代碼了
自己直接拿lua5.1源碼編的ulua.dll
Windows下用可以用vs編吧,我把那個lua_wrap.c也添加了
如果你的錯誤是找不到入口,就加這個宏,LUA_BUILD_AS_DLL,具體查一下readme。
加上這個_GT(typeof(JsonObject)), 點擊GEN LUA WRAPPER后unity直接就崩潰了
記得嵌套2層以上的模板就不行了,如 Dictionary>
最后發布程序的時候,會包很多錯,是由於TOLUA無法識別代碼中加了編輯器運行的條件編譯判斷,所以手動注釋掉與這相關的代碼不報錯就好,就能正常編譯打包程序了。
如何在LUA中遍歷CSharp的數組:
LuaTable mMap;Dictionary mLuaMap;
public LuaTable Map {
get {
if (mMap == null) {
mLuaMap = new Dictionary( );
mMap = TTLuaMain.Instance.luaState.NewTable( );
for (int i = 0, iMax = mVariables.Length; i < iMax; i++) {
var val = mVariables[i];
mMap[val.name] = val.val;
mLuaMap.Add(val.name, val);
}
}
return mMap;
}
}
LuaVariable 是我自定義的類型,你可以隨便傳, 這個是指我在C#里寫的數組類型
核心思想就是把你C#數組里面的東西,放入table,如果是單純的數據類型,你可以直接lua里面for 0,maxlength 如果是字典類型的,你就要轉換。
比如我這里:
通過TOLUA,把Collider2d類型注冊給ULUA,直接lua里面for 0,maxlength 遍歷。
再貼上ULUA群主寫的范例:
在lua里怎么遍歷 C#的object數組:
uLua自帶的案例
2015年3月26日 15:58:22 補充說明,升級到U3D5.0.0F4,U3D API改了很多,都得用getcomponent函數,以前直接THIS.transform已經不能用了,所以自帶的小案例會報錯。
02_CreateGameObject:
這里我先寫個最平常不過的U3D下的C#腳本
=======================ExtendMonoScript.cs================
public class ExtendMonoScript : MonoBehaviour {
void Start ( ) {
aaa( );
}
public void aaa ( ) {
Debug.Log(this + "普通的函數調用!");
}
public static void StaticMethod ( ) {
Debug.Log("公有靜態函數!!");
}
private static void PirvateStaticMethod ( ) {
Debug.Log("私有靜態函數!!");
}
public void ObjMethod ( ) {
Debug.Log("公有成員函數!!");
}
private void PrivateObjMethod ( ) {
Debug.Log("私有成員函數!!");
}
}
=======================ExtendMonoScript.cs================
=======================CreateGameObject.cs===============
using UnityEngine;
using System.Collections;
// lua
using LuaInterface;
public class CreateGameObject : MonoBehaviour {
private string script = @"
luanet.load_assembly('UnityEngine')
GameObject = luanet.import_type('UnityEngine.GameObject')
luanet.load_assembly('Assembly-CSharp')
local newGameObj = GameObject('Creat_GameObj_In_Lua')
newGameObj:AddComponent('ExtendMonoScript')
";
void Start () {
LuaState l = new LuaState();
l.DoString(script);
}
}
=======================CreateGameObject.cs===============
load_assembly加載程序集,這樣LUA才能使用其API
import_type導入類型,這樣LUA才能使用改類型
newGameObj:AddComponent('ExtendMonoScript')這里注意初學LUA,“:”與“.”的區別
DoString(script);真正使用ULUA插件時不要用這個,因為效率低下。
03_AccessingLuaVariables:
========================AccessingLuaVariables.cs==========================
using UnityEngine;
using System.Collections;
using LuaInterface;
public class AccessingLuaVariables : MonoBehaviour {
// 對象調用函數用: load_assembly是載入程序集 import_type是引入類型
// ..相當於是C#里的字符串+,就是連接字符串的意思
// local表示局部變量,沒寫都為全局變量
// {}表示TABLE,lua里數組,鏈表等等結構都使用該方式模擬出來
// table.insert表示Append,在數組最后插入一個新元素
private string script = @"
luanet.load_assembly('UnityEngine')
GameObject = luanet.import_type('UnityEngine.GameObject')
g_particles = {}
for i = 1, g_Objs2Spawn, 1 do
local newGameObj = GameObject('NewObj' .. tostring(i))
local ps = newGameObj:AddComponent('ParticleSystem')
ps:Stop()
table.insert(g_particles, ps)
end
g_var2read = 42
g_array = {}
for i = 1, 5, 1 do
table.insert(g_array, i)
end
";
void Start () {
LuaState l = new LuaState();
// 給全局變量賦值
l["g_Objs2Spawn"] = 5;
l.DoString(script);
// 取得全局變量
print("Read from lua: " + l["g_var2read"].ToString());
// Get the lua table as LuaTable object
LuaTable particles = (LuaTable)l["g_particles"];
// Typical foreach over values in table
foreach( ParticleSystem ps in particles.Values )
{
ps.Play();
}
l["g_var2read"] = 48;
Debug.Log("Read from lua: " + l["g_var2read"].ToString( ));
// Lua里數值都是當的double,動態類型,不需要強制類型轉換
//float akb = (float)l["var2read"]; // error
//int akb = (int)l["var2read"]; // error
double akb = (double)l["g_var2read"]; // ok
Debug.Log(akb);
l["g_var2read"] = "AKB48"; // ok
Debug.Log("Read from lua,賦值字符串后: " + l["g_var2read"].ToString( ));
string str = (string)l["g_var2read"]; // ok
Debug.Log("str = " + str);
LuaTable nums = (LuaTable)l["g_array"];
foreach ( double num in nums.Values ) {
Debug.Log("num = " + num);
}
foreach ( double key in nums.Keys ) {
Debug.Log("關鍵字 = " + key);
}
//Debug.Log("nums[1] = " + nums["1"].ToString()); // error
}
}
========================AccessingLuaVariables.cs==========================
群共享的小框架SimpleFramework
baseLua=橋 ,繼承baselua的c#類一般不需要導出wrap。
V0.2.0發布EXE調整:
首先直接發布EXE報錯:
直接簡單的把打包目標改成WIN,重新打包。
載入AB的資源管理腳本:
可以看到這里對路徑只寫了安卓和IOS平台的判斷,再就是是否是調試版的判斷。改完后,按GUI的提示改下常量為DEBUG模式,以拿到路徑。這樣發布EXE就正常了。
=================啟動SimpleFramework_v0.1.5的服務端問題======================
啟動 SimpleFramework_v0.1.5的服務端這個是什么問題
2014-10-12 10:46:48,573 [7128] ERROR DefaultBootstrap - Failed to create server instance ManagementServer!
System.Reflection.TargetInvocationException: 調用的目標發生了異常。 ---> System.TypeInitializationException: “SuperSocket.ServerManager.ManagementServer”的類型初始值設定項引發異常。 ---> System.IO.FileNotFoundException: 未能加載文件或程序集“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”或它的某一個依賴項。系統找不到指定的文件。
安裝。net 4,沒有找到json的dll ,已經在目錄里面有了,跟exe同目錄
把這個,Newtonsoft.Json.dll考到 debug執行文件 同目錄就可以了。
==============================================================================
TOLUA,封裝C#與LUA通信原理:
LuaDLL.lua_pushstdcallcfunction(L, IndexArray);
LuaDLL.lua_rawset(L, -3);
LuaDLL.lua_pushstring(L, "__gc");
LuaDLL.lua_pushstdcallcfunction(L, __gc);
LuaDLL.lua_rawset(L, -3);
pushstring是把toluaindex壓棧,dostring我記得是執行這段字符串,生成閉包,最后是以toluaindex為key.閉包為value存放在注冊表,這樣可以不被lua直接訪問到,如果我記得不錯的話,rawset是繞過元表直接設置table,index表示的是lua堆棧中對象的索引位置。
怎么知道index是多少呢?如這個里面的-3
-3是luanet array,就是個棧,而且第一個-3和第二個是不一樣的,理解棧,壓棧,出棧就好了,前面四句就是luanetarray[_index]=函數,settop是設置棧頂,這里為0是清空棧。
最后的-3是不是倒數第3次的push。lua_pushstdcallcfunction(L, IndexArray); 是這行的IndexArray嗎?
非也,是那個元表,rawset只是把key 和value彈出而已,元表留在棧頂,實際上這次是給這個元表加一個key為_gc,value為gc函數的鍵值。
=====================================
me for nlua小框架:
使用步驟:
//附帶地鼠資源打包教程和編輯腳本測試工程教程:
1.執行編輯器菜單 ME tools/清理緩存,讓一切重新開始。
2.執行編輯器菜單 ME tools/把Atlas目錄下的.png圖片作為圖集資源並放入Data目錄。
3.在Project窗體內 鼠標點選選中 Assets/Builds/GUI,然后 執行編輯器菜單 ME tools/獨立打包選中目錄下的各個對象並放入Data目錄。
4.執行編輯器菜單 ME tools/制作更新包:把Data目錄壓縮為一個zip包並放入StreamingAssets目錄。
通過以上步驟完成資源和升級包的制作了。
如果在編輯器進行代碼修改或者資源修改,請重復以上步驟。
如果僅僅修改 Assets/Data/lua 下的邏輯腳本,您只需要執行以上的1和4步驟
me for nlua 把plugins下面的x86和x86_64兩個文件夾刪除掉,就能發布android了。
me for nlua編譯選項推薦使用
UNITY_3D;USE_KERALUA;LUA_CORE;CATCH_EXCEPTIONS
即使用c版lua加速,也可解決打印(Debug.Log)中文日志顯示亂碼問題。
參考一下ME 游戲框架,全局就一個luastate,
ME框架的思路就是 一個GameObject 對應掛個LuaBehaviour.cs腳本,這個LuaBehaviour.cs腳本DoFile一個
lua腳本,lua腳本和LuaBehaviour.cs交互控制。全局就有一個luastate,每個腳本其實就是一個table。
============================================================
U3D5的更新:
各位使用MAC + U5 64的同學,如果遇到編輯器環境下luastate == null的情況,請下載我上傳群共享的
libulua.zip替換其底層庫,可暫時繞過此問題,將來有時間研究下