zoukankan      html  css  js  c++  java
  • Unity3D游戏开发之Lua的技能培训

          下面我们开始今天的Unity3D技能培训。 我们学习Unity3D培训目标:让U3D初学者可以更快速的掌握U3D技术,自行制作修改素材,可以独立完成2D、3D小规模游戏及网页游戏开发。

            好了,下面我们就来一起学习在Unity3D项目中如何使用Lua语言吧,Unity3D基于Mono虚拟机,所以理论上.NET的类库是可以直接在Unity3D中使用的。可是考虑到Unity3D跨平台的需要,我们选择的工具必须在各个平台获得良好的支持。在前文中提到的LuaInterface理论上是可以在Unity3D中使用的,可是由于IOS不支持反射机制,所以这个类库我们无法直接在Unity3D中使用的。。好了,我们,现在来创建一个简单地Unity项目:

            第一步是下载UniLua:http://github.com/xebecnan/UniLua。将UniLua引用到项目中有两种方法,一种是将该项目中的UniLua编译成dll然后在Unity项目中使用,一种是将该项目中的UniLua直接复制到Unity 项目中,我们这里使用第二种方法,因为博主比较懒,呵呵。将UniLua的命名空间添加到我们项目中,我们就可以开始动手写程序了。不过这里,博主想说的是Mono可能会导致的一个错误,估计是阿楠在写这个项目的时候使用了.NET4.0以上的版本,而在.NET4.0以上的版本是支持默认参数的构造函数的。可是由于Mono默认使用的是.NET3.5,所以在编译项目的时候就会报错,我们可以通过Project->Assembly-CSharp->Build->General将.NET的目标框架设为4.0,这样就可以解决这个问题了。好了,下面我们开始写代码啦,首先创建一个InvokeScript.cs的脚本:

    [csharp] view plaincopyprint?
     
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using UniLua;  
    4.   
    5. public class InvokeScript : MonoBehaviour {  
    6.       
    7.     //Lua脚本文件,我们将在C#调用该脚本  
    8.     public TextAsset LuaFile;  
    9.     //Lua虚拟机  
    10.     private ILuaState mLua;  
    11.   
    12.     void Start()  
    13.     {  
    14.         //初始化Lua虚拟机  
    15.         mLua=LuaAPI.NewState();  
    16.         //加载Lua标准库  
    17.         mLua.L_OpenLibs();  
    18.         //引用一个静态地C#库  
    19.         mLua.L_RequireF(CSharpLib.CLASSNAME,CSharpLib.InitLib,false);   
    20.   
    21.         //执行Lua脚本  
    22.         mLua.L_DoString(LuaFile.text);  
    23.     }  
    24.   
    25.     void OnGUI()  
    26.     {  
    27.         if(GUILayout.Button("调用Lua脚本",GUILayout.Height(30)))  
    28.         {  
    29.             InvokeLua();  
    30.         }  
    31.         if(GUILayout.Button("调用C#脚本",GUILayout.Height(30)))  
    32.         {  
    33.             InvokeCSharp();  
    34.         }  
    35.     }  
    36.  
    37.     #region 调用C#脚本  
    38.     void InvokeCSharp()  
    39.     {  
    40.         //获取方法并传入参数  
    41.         mLua.GetGlobal("SumAndSub");  
    42.         mLua.PushInteger(12);  
    43.         mLua.PushInteger(8);  
    44.         mLua.PCall(2,4,0);  
    45.     }  
    46.     #endregion  
    47.      
    48.     #region 调用Lua脚本  
    49.     void InvokeLua()  
    50.     {  
    51.         //获取Lua脚本中的arg1参数  
    52.         mLua.GetGlobal("arg1");  
    53.         //输出arg1  
    54.         Debug.Log("Lua脚本中的变量arg1="+mLua.L_ToString(-1));  
    55.   
    56.         //获取Lua脚本中的arg2参数  
    57.         mLua.GetGlobal("arg2");  
    58.         //输出arg2  
    59.         Debug.Log("Lua脚本中的变量arg2="+mLua.L_ToString(-1));  
    60.   
    61.         //获取Lua脚本中的Printf方法  
    62.         mLua.GetGlobal("Printf");  
    63.         //调用Lua脚本中的Printf方法  
    64.         mLua.PCall(0,0,0);  
    65.   
    66.         //获取Lua脚本中的Sum方法  
    67.         mLua.GetGlobal("Sum");  
    68.         //传入参数12和25  
    69.         mLua.PushInteger(12);  
    70.         mLua.PushInteger(25);  
    71.         //调用此方法  
    72.         mLua.PCall(2,3,0);  
    73.         //获取传入的两个参数及求和结果  
    74.         int a=mLua.ToInteger(-3);  
    75.         int b=mLua.ToInteger(-2);  
    76.         int sum=mLua.ToInteger(-1);  
    77.         //输出  
    78.         Debug.Log("调用Lua脚本中的Sum方法:"+a+"+"+b+"="+sum);  
    79.     }  
    80.     #endregion  
    81.       
    82. }  
    [csharp] view plaincopyprint?
     
    1.   

    在这段脚本中,我们首先初始化了Lua环境,这一点和我们在C++中使用Lua是一样的,因为UniLua在设计API的时候在命名上和LuaAPI保持了高度的一致,如果你对Lua API足够熟悉的话,那么现在这一切对你而言应该会很简单的。接下来,我们通过Require的形式引入了我们编写的一个C#库,它是一个静态库,目的是封装C#方法以便于Lua脚本来调用,这一部分我们稍后会讲到。接下来,我们通过Unity的AssetText加载了一个Lua脚本文件,该脚本的文件的扩展名是.txt,因为我们只需要Lua脚本的内容。在脚本中我们定义了两个方法InvokeLua和InvokeSharp来分别调用Lua脚本和C#脚本。好了,接下来,我们重点来讲Lua调用C#脚本的这部分,因为UniLua在调用函数这块儿和LuaInterface不太一样,所以我们不能再用原来的先注册C#方法然后再像Lua脚本方法一样,不过这里的原理是一样的,不过UniLua提供了更好的方法绑定机制,我们来看下面的脚本:

    [csharp] view plaincopyprint?
     
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using UniLua;  
    4.   
    5. public static class CSharpLib  
    6. {  
    7.     //当前类文件名称,我们将在Lua脚本中使用这个名称  
    8.     public const string CLASSNAME="CSharpLib.cs";  
    9.   
    10.     //C#库初始化  
    11.     public static int InitLib(ILuaState lua)  
    12.     {  
    13.         NameFuncPair[] define=new NameFuncPair[]  
    14.         {  
    15.             new NameFuncPair("SumAndSub",SumAndSub),  
    16.         };  
    17.         lua.L_NewLib(define);  
    18.           
    19.         return 1;  
    20.     }  
    21.   
    22.     //我们在C#中定义一个求和差的方法  
    23.     public static int SumAndSub(ILuaState lua)  
    24.     {  
    25.         //第一个参数  
    26.         int a=lua.L_CheckInteger(1);  
    27.         //第二个参数  
    28.         int b=lua.L_CheckInteger(2);  
    29.         //计算和  
    30.         int c=a+b;  
    31.         //计算差  
    32.         int d=a-b;  
    33.           
    34.         //将参数及计算结果压入栈  
    35.         lua.PushInteger(a);  
    36.         lua.PushInteger(b);  
    37.         lua.PushInteger(c);  
    38.         lua.PushInteger(d);  
    39.           
    40.         //有四个返回值, 尽管在C#中不支持返回多个值,可是在Lua中这样是支持的  
    41.         return 4;  
    42.     }  
    43. }  

    大家一定注意到这里有个NameFuncPair类吧,这就是在UniLua中用来将一个C#方法和Lua方法进行绑定的方法,我们首先构造这样一个NameFuncPair数组,然后将其加入到lua_L_NewLib()的参数中,这样相当于是注册了一个库,我觉得应该就是注册了一个方法集合吧.而CLASSNAME是一个表示当前类名称的常量,可以取任意字符,这里我们使用该类的文件名我们将在Lua脚本是用这个值来查找当前类.接下来,我们可以看到博主构造了一个求和差的C#方法,这个方法和Lua API中定义的方法是一致的,即我们需要指定该方法会返回的值得数目.如果我们需要返回一个值,就要把它通过push系列的方法压入栈中.这里我们返回了四个值,大家一定会问好是C#还支持返回多个值啊,其实呢,这是Lua语言提供给我们的一个福利啊,比如我们需要返回一个物体在3D世界里的坐标,通常情况下,我们需要用三个赋值语句才能获取吧,可是你用Lua的话,一行代码就可以搞定啦.好,现在我们回到InvokeScript脚本的Start方法中,大家可以注意到这里有一个L_RequireF()的方法,前面只是轻描淡写地说它引入了一个库,那么现在我们看看它具体做了什么吧,第一个参数表示这个类的名字,指向我们定义好的CLASSNAME,第二个参数是这个类的初始化方法指向InitLib()方法,第三个参数是是否要在全局空间中使用这个库,这里我们选在false.好了,这样,我们就完成了C#脚本的编写.好了,下面我们在项目中创建一个纯文本文件,我们输入如下代码:

    [plain] view plaincopyprint?
     
    1. local csharplib=require"CSharpLib.cs"  
    2. arg1="Unity3D"  
    3. arg2="Unreal"  
    4. arg3="Coco2dX"  
    5.   
    6. function Printf()  
    7.   print("This is the methods invoked in Lua")  
    8. end  
    9.   
    10. function Sum(a,b)  
    11.   return a,b,a+b  
    12. end  
    13.   
    14. function SumAndSub(a,b)  
    15.   print(csharplib.SumAndSub(a,b))  
    16. end  

    第一行代码同样是一个require的方法,这是Lua脚本中引用一个库的方法,该方法可以引用Lua的标准库,同样可以引用我们定义的外部库,大家注意到这里的名字和我们之前定义的CLASSNAME是一样的,因为我们就是通过这个名字来查询这个库的,我们在Lua环境中注册了这个库,所以现在才可以引用这个库.在这段脚本中我们定义了几个字符型的变量,两个Lua方法,一个用Lua包装的C#方法.好了,现在我们将这个文本文件指定到InvokeScript的LuaFile字段,我们通过LuaFille的text获取脚本内容,然后通过DoString()方法来执行脚本中的内容,注意这里要先对C#库进行注册,然后再执行脚本中的内容,否则会出现错误.好了,最后,我们来一起看看运行效果吧:

    大家可以看到C#调用的Lua脚本中我们获取了脚本中的两个变量arg1、arg2,调用了Lua中定义的两个方法,而最后一个方法,如我们所愿,它返回了四个值,这正是我们所希望的结果.这里顺便说一下啊,在Lua中的print方法和return在Call以后是可以直接在Debug中输出结果的,无需我们再去做Log。更多精彩unity3d技术文章请点击 http://www.gopedu.com/article

  • 相关阅读:
    Spring集成MyBatis
    UpdatePanel的简单用法(转)
    updatePanel导致JS失效的解决办法(转)
    sql面试题(学生表_课程表_成绩表_教师表)
    javascript深入理解js闭包
    T-SQL利用Case When Then多条件判断
    T-SQL排名函数
    DataTable字符串类型的数字,按照数字类型排序
    Sql 行转列问题总结
    行转列:SQL SERVER PIVOT与用法解释
  • 原文地址:https://www.cnblogs.com/Unity3Dqishituan/p/4026427.html
Copyright © 2011-2022 走看看