首页 广告策划营销 元宇宙链游系统开发搭建技术

元宇宙链游系统开发搭建技术

发布时间 2023-05-19 收藏 分享
价格 面议
区域 全国
来源 广州杰肯狸网络科技有限公司

详情描述:

META FORCE系统属于我们的社区,并且是完全的去中心化,这意味着它是透明的,安全的,技术唯【Congge420】并且能够抵抗外部影响。

三个步骤:

 

  加载lua代码到vm中,对应api-luaL_loadbuffer

 

  luaL_loadbuffer会同时在栈上压入代码块的指针

 

  执行lua代码,对应api-lua_pcall

 

  lua_pcall会从栈上依次弹出{nargs}个数据作为函数参数,再弹出函数进行执行,并将结果压入栈

 

  如果lua代码有返回值,那么通过lua_toXXX相关api从栈上获取结果

 

  完整的代码如下:

 

  private bool DoLuaCode(System.IntPtr L,string luaCode){

  //加载lua代码

 

  if(Lua.luaL_loadbuffer(L,luaCode,"")==0){

  //执行栈顶的函数

 

  if(Lua.lua_pcall(L,0,1,0)==0){

  //函数执行完成后,返回值会依次依次押入栈

 

  return true;

 

  }else{

  Debug.LogError("pcall failed!");

 

  return false;

 

  }

 

  }else{

  Debug.LogError("load buffer failed");

 

  return false;

 

  }

 

  }

 

  假如我们有一段lua代码:

 

  return'hello,i am from lua'

 

  这段lua仅仅返回一段字符串,那么利用DoLuaCode去执行就是:

 

  //lua代码

 

  string luaCode="return'hello,i am from lua'";

 

  if(DoLuaCode(L,luaCode)){

  Debug.Log(Lua.lua_tostring(L,-1));

 

  //lua_toXXX不会出栈,需要lua_pop才能出栈

 

  Lua.lua_pop(L,1);

 

  }

 

  由于此处lua代码返回的是字符串,因此使用lua_tostring(L,-1)来将栈顶的元素转为字符串并返回,相应的我们还能看到有lua_tonumber,lua_toboolean等等.

 

  4.c#调用lua全局函数

 

  接下来的例子将说明一下c#端如何执行lua中的全局函数。

 

  假设现在我们有一段lua代码如下:

 

  function addSub(a,b)

 

  return a b,a-b;

 

  end

 

  通过DoLuaCode来运行以上的lua代码,就得到了一个全局的addSub函数,这个函数会返回a,b相加和相减的结果。

 

  为了在c#端执行以上的lua函数,需要按以下步骤进行:

 

  将全局函数压入栈中,对应api-lua_getglobal

 

  将函数所需的参数依次压入栈中,对应api-lua_pushnumber

 

  执行栈中函数,对应api-lua_pcall

 

  获取函数返回结果,对应api-lua_tonumber

 

  完整c#代码如下:

 

  //从全局表里读取addSub函数,并压入栈

 

  Lua.lua_getglobal(L,"addSub");

 

  //压入参数a

 

  Lua.lua_pushnumber(L,101);

 

  //压入参数b

 

  Lua.lua_pushnumber(L,202);

 

  //2个参数,2个返回值

 

  Lua.lua_pcall(L,2,2,0);

 

  //pcall会让参数和函数指针都出栈

 

  //pcall执行完毕后,会将结果压入栈

 

  Debug.Log(Lua.lua_tonumber(L,-2));

 

  Debug.Log(Lua.lua_tonumber(L,-1));

 

  Lua.lua_pop(L,2);

 

  5.lua注册并调用c#静态函数

 

  首先,想要被Lua调用的c#函数,都必须满足以下的格式:

 

  public delegate int LuaCSFunction(System.IntPtr luaState);

 

  同时需要加上特性:

 

  MonoPInvokeCallback(typeof(LuaCSFunction))

 

  我们可以通过以下方式,将一个LuaCSFunction注册到lua中:

 

  static void RegisterCSFunctionGlobal(System.IntPtr L,string funcName,LuaCSFunction func){

  //将LuaCSFunction压入栈中

 

  Lua.lua_pushcfunction(L,func);

 

  //lua_setglobal会弹出栈顶元素,并按给定的名字作为key将其加入到全局表

 

  Lua.lua_setglobal(L,funcName);

 

  }

 

  那么,当我们在lua中执行c#注册的函数时,其交互过程如下:

 

  LuaVM会临时分配一个局部栈结构(这里要区分开始通过luaL_newstate创建的全局栈,两者是独立的)

 

  LuaVM会将lua侧的函数参数压入这个临时栈,然后将栈指针传给LuaCSFunction

 

  LuaCSFunction在实现上需要从这个栈中读取lua侧压入的参数,然后执行真正的相关逻辑,并将终结果压入栈中

 

  LuaCSFunction需要返回一个int值,表示往栈中压入了多少个返回值

 

  Lua从栈中获取C#侧压入的0/1/多个返回值

 

  官方说明文档可以参考-Calling C from Lua

 

  接下来要将演示如何将一个c#静态函数Print注入到lua中,实现lua中调用c#端的日志输出功能。

 

  我们定义一个c#静态函数如下:

 

  [MonoPInvokeCallback(typeof(LuaCSFunction))]

 

  private static int Print(System.IntPtr localL){

  //获取栈中元素个数

 

  var count=Lua.lua_gettop(localL);

 

  System.Text.StringBuilder s=new System.Text.StringBuilder();

 

  for(var i=1;i<=count;i ){

  //依次读取print的每个参数,合并成一个string

 

  s.Append(Lua.lua_tostring(localL,i));

 

  s.Append('');

 

  }

 

  Debug.Log(s);

 

  //print函数没有返回值

 

  return 0;

 

  }

 

  lua_gettop可以获取栈中的元素个数,此处代表了lua端压入栈中的函数参数个数

 

  然后我们通过以下方式将这个c#侧的Print注册到lua中,命名为print。

 

  //将LuaCSFunction压入栈中

 

  Lua.lua_pushcfunction(L,Print);

 

  //lua_setglobal会弹出栈顶元素,并按给定的名字作为key将其加入到全局表

 

  Lua.lua_setglobal(L,"print");

 

  接下来我们执行以下的lua代码:

 

  print('hello','csharp')

 

  就能看到编辑器中输出

 

  hello csharp

 

  6.lua注册c#类型

 

  通常我们使用lua中的table来模拟c#中的类。一般类的注册思路如下:

 

  在lua中创建一个与c#类同名的表

 

  将c#类的静态函数都注册到lua的这个同名表里

 

  下面演示一下如何将Unity中的Debug类注册到lua中:

 

  Lua.lua_createtable(L,0,1);

 

  Lua.lua_setglobal(L,"Debug");

 

  其实很简单:

 

  lua_createtable会创建一个table,压入栈顶

 

  lua_setglobal会弹出栈顶元素,并将其加到全局表里

 

  这样我们在lua里就有了一个名为Debug的表可供全局访问。但目前这个表是空空如也的,我们还需要为其添加静态函数。(tips:实际上完整的设计中,还需要为class table设置metatable,增加一些限制性,但这里先不表)

 

  6.1注入类的静态函数

 

  首先我们定义一个符合LuaCSFunction形式的c#函数如下:

 

  [MonoPInvokeCallback(typeof(LuaCSFunction))]

 

  private static int Debug_Log(System.IntPtr L){

  string msg=Lua.lua_tostring(L,1);

 

  Debug.Log(msg);

 

  return 0;

 

  }

 

  这个c#函数是对Debug.Log的一个封装。

 

  然后可以通过以下方式将这个c#函数注册到lua中的Debug表中:

 

  Lua.lua_createtable(L,0,1);

 

  //往栈中压入字符串'Log'

 

  Lua.lua_pushstring(L,"Log");

 

  //往栈中压入函数Debug_Log

 

  Lua.lua_pushcfunction(L,Debug_Log);

 

  //从栈中弹出一个元素作为key,再弹出一个元素作为value,作为pair赋值到index指定的table

 

  Lua.lua_settable(L,1);

 

  Lua.lua_setglobal(L,"Debug");

联系人 罗聪
13138494301
2813729063@qq.com
上一条 下一条
电话联系