Lua初学者笔记2

1.lua编译环境配置
下载lua编译环境“SciTE”,直接安装,在SciTE中即可直接编译lua文件。
地址:https://code.google.com/archive/p/luaforwindows/downloads
或者使用lua studio。
2.lua基本语法
2.1全局变量和局部变量
Lua的全局变量不需要声明,给一个全局变量赋值的同时就创建了一个全局变量。没有加local声明的变量都是全局变量。

局部变量定义是需要加local关键字。

2.2 变量赋值
普通变量赋值与其他语言类似。但lua可以进行多变量同时赋值,多变量赋值的特点:
①先计算右边的值再赋值给左边
②当左右变量数不一致时,左边多,补nil,右边多,舍去。

2.3 逻辑运算符

3.lua的基本类型
Lua有8种基本类型,nil、boolean、number、string、userdata、function、thread、table。
3.1 nil
Lua中特殊的类型,它只有一个值:nil,一个全局变量没有被赋值以前默认值为nil,给全局变量赋值nil可以删除该变量。

3.2 boolean
两个取值false和true。
Ps:在判断条件中false和nil为假,其余所有值都为真。
3.3 number
Lua中不区分浮点数和整数、在保存时同一使用number。
3.4 string
①表示:可以使用“”(不能换行)或[[]](可以换行)。

②当字符串为纯数字时,可直接进行运算

③#可计算字符串的长度

④字符串连接使用..

3.5 table
由于lua中的table是一个“关联数组”,是lua中唯一的数据结构,可以代表队列、链表等各种数据结构。table在使用前必须创建。

由于lua库函数中与table相关的函数的数字索引下标为从1开始,所以建议table的数字下标也从1开始。
3.6 function
在lua中,函数被看作“第一类值”,与number、string同级,可以赋值给变量。

3.7 thread
线程拥有自己独立的栈、局部变量和指令指针。
Lua中特有的协同程序也是一种thread。
3.8 userdata
用户自定义类型,用于表示c/c++中的数据类型。
4.循环语句
4.1 while和repeat
使用和c++类似,不详细介绍。

4.2 数值型for循环

4.3 泛型for循环
泛型for循环通过一个迭代器函数遍历所有值,类似Java的foreach循环。
ipairs遍历从索引1开始的顺序的元素。
pairs遍历所有元素。

5.函数与闭包
5.1 函数定义

optional:可选参数,未设置时为全局函数,为local时为局部函数
name:函数名
a1…an:函数参数,可为可变参数

body:函数体,函数要做的事情
value: 可以返回一个或多个值,返回多值时,变量接受规则和多变量赋值相同。也可以返回函数,返回函数时可能构成闭包。
5.2 闭包
闭包是lua中一个重要的概念。
首先明白几个定义
①词法定界:当函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征称为词法定结。
②upvalue:内部函数可访问的外部函数的局部变量称为upvalue。就像是只针对这个内部函数来说的静态变量。
简单的来说,一个函数和他的upvalue构成了一个闭包。
一个简单的例子:

当有多个内部函数时,它们共享upvalue:

嵌套的函数可以共享upvalue:

5.3 尾调用
如果函数f的在return处返回了一个函数g,f在返回g后不会做任何事情,那么这就是一个尾调用。Lua对于尾调用的函数f,会在调用g时将f的内容出栈,防止循环调用的爆栈。
6.迭代器
6.1 泛型for循环

泛型for的执行过程:
首先,初始化,计算in后面表达式的值,表达式应该返回范性for需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用nil补足,多出部分会被忽略。
第二,将状态常量和控制变量作为参数调用迭代函数
第三,将迭代函数返回的值赋给变量列表。
第四,如果返回的第一个值为nil循环结束,否则执行循环体。
第五,回到第二步再次调用迭代函数
6.2 无状态的迭代器
无状态的迭代器是指不保留任何状态的迭代器,所以在循环中我们可以利用无状态迭代器避免创建闭包,传递table话费的额外时间。
这个无状态可有有些误导,这里指的是除了状态常量和控制变量,没有其他的变量需要传递,而不是一个变量都不需要传递。
每一次迭代,迭代函数只使用状态常量和控制变量两个参数,不使用额外参数,这种迭代器就是无状态的迭代器。
比如ipairs:

6.3多状态的迭代器
除了状态常量和控制变量外需要其他状态才能获取下一个值的迭代器是多状态迭代器,这时需要闭包或一个table来传递参数。
闭包:

这里除了需要传递三个变量collection、index、count,所以需要用到闭包。
table:

7.模块
模块类似于一个封装库,可以把一些公用代码放在一个文件里,以API接口的形式在其他地方调用,有利于代码的重用和降低代码的耦合度。
模块由变量、函数、已知元素组成的table构成。把需要使用的变量、函数放在一个table中然后返回这个table就可以了。
模块通过require函数在其他程序中调用。
定义一个模块b,在a中调用:

8.元表
Lua中的每个值都有一套预定义的操作,比如数字可以相加、字符串可以相减,但是两个table,则不能直接进行相加的操作。
lua的table没有这些预定义操作,需要通过添加元表来定义这些预操作。可以理解为元表就是table的+、-、*、/、=等操作的集合,元表中的元方法就分别对应这些操作。
通过把b设置为a的元表。
一个元表中包含的元方法:

元表中的元方法都需要自己定义函数,否则nil。
①__add方法

类似于加法的二元元方法的调用过程:
1.对于二元操作符,如果第一个操作数有元表,并且元表中有所需要的字段定义,比如我们这里的__add元方法定义,那么Lua就以这个字段为元方法,而与第二个值无关。
2.对于二元操作符,如果第一个操作数有元表,但是元表中没有所需要的字段定义,比如我们这里的__add元方法定义,那么Lua就去查找第二个操作数的元表。
3.如果两个操作数都没有元表,或者都没有对应的元方法定义,Lua就引发一个错误。
②__index方法

__indexf方法调用过程:
1.访问table的一个索引时,如果table有这个索引,直接返回对应值。
2.若table没有该索引,查看table是否有元表,有则尝试调用元表的__index,否则返回nil。
3.若__index方法存在,调用__index方法,返回__index方法的返回值,若__index为一个table,则查找__index的索引,若__index中有这个索引,返回对应元素,否则返回nil。
③__newindex方法

__newindex用于更新table中的数据,调用过程如下
1.Lua解释器先判断这个table是否有元表;
2.如果有了元表,就查找元表中是否有__newindex元方法;如果没有元表,就直接添加这个索引,然后对应的赋值;
3.如果有这个__newindex元方法,Lua解释器就执行它,而不是执行赋值;
4.如果这个__newindex对应的不是一个函数,而是一个table时,Lua解释器就在这个table中执行赋值,而不是对原来的table。
Ps:如果在__newindex中又对一个table中不存在的键赋值,会发生循环调用__newindex,导致爆栈。
④__metatable方法

设置了一个元表的__metatable后,那么对使用这个元表的table进行setmetatable时会报错,使用getmetatable后会返回__metatable的值。

环境
--lua将所有的全局变量保存在一个_G的Table就是“环境”
_G
setfenv()

a=5
function f1()
    a=10--定义一个f1环境中的变量a=10
    _G.print(a)--输出f1环境中的a ----> 10
    _G.print(_G.a)--输出全局环境中的a---> 5
end
setfenv(f1,{_G=_G})--设置f1的环境
f1()
--setfenv的第一个参数可以是当前幻术调用栈中的层数
a=5

function f1( ... )
    setfenv(1,{_G=_G})--设置当前函数的环境,也就是f1
    a=10--定义一个f1环境中的变量a=10
    _G.print(a)--输出f1环境中的a ---> 10
    _G.print(a)--输出全局环境中的a---> 5
end
f1()



--lua  的面向对象程序设计
Account={balance=0}--定义一个表(表示账户类)

  --第一种:使用 . 来定义
function Account.withDraw(v)--理解为定义一个扣款的方法
    Account.balance=Account.balance-v
end
Acount.withDraw(10)
print(Account.balance)

--第二种:使用 :来定义,治安方法定义中添加一个隐藏参数self
--在参数出入时多传入了一个调用这个函数的变量
function Account:withDraw(v)--理解为定义一个扣款的方法
    self.balance=self.balance-v
end
Account:withDraw(10)
print(Account.balance)


--第二种定义完全等价于
function Account.withDraw(self,v)
        self.balance=self.balance-v
end 
Account.withDraw(Account,10)
print(Account.balance)
--只是简便了一点,这种定义方式在面向对象中的十分常用。
--举个例子
function Account.withDraw( v )
    Account.balance=Account.balance-v
end
a=Account
Account=nil
a.withdraw(10)
--会报错因为Account=nil后,a.withdraw就不能用了。
--但是如果使用了:来定义和调用,用self代替Account就不会有问题。

--类在c++中是个模板,不是真实存在的对象。但在lua中类被当作模板使用,但是实际上是一个实例化的对象。
--类就是真实存在的表,透过原方法__index来实例化这个类。

--实现一个简单的类;
local Account = {balance=10}--定义一个类
function Account:withdraw(v)--定义一个类中的一个方法,实际上是定义一个函数保存子啊Account表中
    self.balance=self.balance-v
end

--创建类的函数,可以理解为构造函数
function Account:new (o)
    o=o or {}--创建出的类的实例,实际上还是用一个表来模拟的,o是用来模拟类的实例的一个表。设置元表后o可以获取Account中所有函数和变量。
    --下面两句相当于setmetatable(o,{__index=self})
    setmetatable(o,self)
    self.__index=self
    return o
end
--一个用Account实例化的类a
a=Account:new ()


--lua 中的继承,
--实例化一个列的过程其实也是一次继承。

--定义一个类和他的方法
local Account ={balance=10}
function Account:withDraw(v)
        self,balance-self.balance-v
end
--a是Account的一个实例,也可以说a继承Account
a={}
setmetotable (a,{__index=Account})
--重写Account的函数
function a:withDraw( v )
        self.balance=self.balance+v
end


--实例化一个a
b={}
setmetotable(b,{__index=a})

b:withDraw(10)
print(b.balance)--输出20
print(a.balance)--输出为10
print(Account.balance)--输出10


--使用new的版本;
--定义一个列和他的方法
local Account={balance=10}
function AccountwithDraw(v)
    self.balance=self.balance-v
end
--创建类的函数

function Account:new (o)
    o=o or {}
    setmetotable(o,self)
self.__index=self
return o
end 
--一个用Account实例化的类a,同时也是继承

a=Account:new ()
function a:withdraw( v )
    self.balance=self.balance+v
end

b=a:new ()
b:withDraw(5)
print(b.balance)
print(a.balance)
print(Account.balance)

--使用new的话,整个程序结构更加清晰。

[Unity]使用Slua框架开发创建Unity引擎中的对象

主要的内容包括
LuaSvr环境对象初始化LuaState状态机对象
Lua中的import关键字脚本中导入UnityEngine设置游戏对象组件属性
Lua中的require关键字导入自定义模块module

创建新的Unity工程并且导入SLua框架

AppDelegate.cs

  using UnityEngine;
  using System.Collections;
  using SLua;

  public class Main : MonoBehaviour
  {

      private LuaSvr lua_svr;
      // Use this for initialization
      void Start()
      {
          //创建一个已经注入UnityEngine的状态机对象..
          lua_svr = new LuaSvr();

          //通过Resources文件夹下的main.txt(lua)文件内的main函数启动程序
          //当然也可以通过修改LuaState.loaderDelegate来修改默认的路径
          lua_svr.start("main");
      }
  }

main.txt

  funcion main()
      print("Hello LuaSvr...")
  end

在main.txt文件内导入UnityEngine包并且创建游戏对象

  import "UnityEngine"

  function main()
      -- 创建Cube对象
      local cube=UnityEngine.GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Cube)
  end
在main.txt文件内导入UnityEngine包并且创建空游戏对象

  import "UnityEngine"

  function main()
      -- 创建空物体对象
      local empty=UnityEngine.GameObject("HHEmptyObject")
  end

操作游戏对象上的组件

获取Transform组件

  import "UnityEngine"

  function main()
      -- 创建Cube对象
      local cube=UnityEngine.GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Cube)

      -- 获取transform组件上的position属性
      local pos = cube.transform.position
      pos.x = 10

      -- 修改transform组件的position属性
      cube.transform.position = pos
  end

添加Rigidbody组件
导入import “UnityEngine”
添加刚体组件cube:AddComponent(Rigidbody)
获取指定类型的组件,例如BoxCollider
导入import "UnityEngine"
自定类型字符串获取local collider = cube:GetComponent("BoxCollider")
由于使用Lua编写Unity项目时,无法与C#相比的是对象函数或者对象属性的智能提示不够健全.
所以在此贴出Slua框架中注入LuaState状态机对象内的一些UnityEngine的函数和属性.

UnityEngine.GameObject对象在LuaState中注入的内容

static public void reg(IntPtr l) {
      getTypeTable(l,"UnityEngine.GameObject");--添加的命名空间
      addMember(l,GetComponent);
      addMember(l,GetComponentInChildren);
      addMember(l,GetComponentInParent);
      addMember(l,GetComponents);
      addMember(l,GetComponentsInChildren);
      addMember(l,GetComponentsInParent);
      addMember(l,SetActive);
      addMember(l,CompareTag);
      addMember(l,SendMessageUpwards);
      addMember(l,SendMessage);
      addMember(l,BroadcastMessage);
      addMember(l,AddComponent);
      addMember(l,CreatePrimitive_s);
      addMember(l,FindGameObjectWithTag_s);
      addMember(l,FindWithTag_s);
      addMember(l,FindGameObjectsWithTag_s);
      addMember(l,Find_s);
      addMember(l,"transform",get_transform,null,true);
      addMember(l,"layer",get_layer,set_layer,true);
      addMember(l,"activeSelf",get_activeSelf,null,true);
      addMember(l,"activeInHierarchy",get_activeInHierarchy,null,true);
      addMember(l,"isStatic",get_isStatic,set_isStatic,true);
      addMember(l,"tag",get_tag,set_tag,true);
      addMember(l,"gameObject",get_gameObject,null,true);
      createTypeMetatable(l,constructor, typeof(UnityEngine.GameObject),typeof(UnityEngine.Object));
  }
只有函数指针位置的部分,在Lua中定义成了Table变量内的函数,例如:`cube:AddCommponent`
 在函数指针名的末尾部分以`_s`结尾的,在Lua中定义成了元表变量内的函数,例如:`GameObject.CreatePrimitive`
 在添加成员时,包含了类似于`"transform"`字符串的,在Lua中定义成了Table变量内的键值对属性,例如:`cube.transform`

UnityEngine.Transform对象在LuaState中注入的内容

 static public void reg(IntPtr l) {
      getTypeTable(l,"UnityEngine.Transform");
      addMember(l,SetParent);
      addMember(l,Translate);
      addMember(l,Rotate);
      addMember(l,RotateAround);
      addMember(l,LookAt);
      addMember(l,TransformDirection);
      addMember(l,InverseTransformDirection);
      addMember(l,TransformVector);
      addMember(l,InverseTransformVector);
      addMember(l,TransformPoint);
      addMember(l,InverseTransformPoint);
      addMember(l,DetachChildren);
      addMember(l,SetAsFirstSibling);
      addMember(l,SetAsLastSibling);
      addMember(l,SetSiblingIndex);
      addMember(l,GetSiblingIndex);
      addMember(l,Find);
      addMember(l,IsChildOf);
      addMember(l,FindChild);
      addMember(l,GetChild);
      addMember(l,"position",get_position,set_position,true);
      addMember(l,"localPosition",get_localPosition,set_localPosition,true);
      addMember(l,"eulerAngles",get_eulerAngles,set_eulerAngles,true);
      addMember(l,"localEulerAngles",get_localEulerAngles,set_localEulerAngles,true);
      addMember(l,"right",get_right,set_right,true);
      addMember(l,"up",get_up,set_up,true);
      addMember(l,"forward",get_forward,set_forward,true);
      addMember(l,"rotation",get_rotation,set_rotation,true);
      addMember(l,"localRotation",get_localRotation,set_localRotation,true);
      addMember(l,"localScale",get_localScale,set_localScale,true);
      addMember(l,"parent",get_parent,set_parent,true);
      addMember(l,"worldToLocalMatrix",get_worldToLocalMatrix,null,true);
      addMember(l,"localToWorldMatrix",get_localToWorldMatrix,null,true);
      addMember(l,"root",get_root,null,true);
      addMember(l,"childCount",get_childCount,null,true);
      addMember(l,"lossyScale",get_lossyScale,null,true);
      addMember(l,"hasChanged",get_hasChanged,set_hasChanged,true);
      createTypeMetatable(l,null, typeof(UnityEngine.Transform),typeof(UnityEngine.Component));
  }

文/肖浩呗(简书作者)
原文链接:http://www.jianshu.com/p/fadb5dd59352
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lua 教程 lua Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。 Lua 是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组于 1993 年开发的,该小组成员有:Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo。 设计目的 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。 Lua 特性 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。 其它特性: 支持面向过程(procedure-oriented)编程和函数式编程(functional programming); 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象; 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持; 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。 Lua 应用场景 游戏开发 独立应用脚本 Web 应用脚本 扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench 安全系统,如入侵检测系统
lua中文教程,原名:programming in lua 目录 版权声明..............i 译序..i 目录iii 第一篇语言.......1 第0章序言.......1 0.1 序言..........1 0.2 Lua的使用者................2 0.3 Lua的相关资源............3 0.4 本书的体例.................3 0.5 关于本书...3 0.6 感谢..........4 第1章起点.......5 1.1 Chunks.......5 1.2 全局变量...7 1.3 词法约定...7 1.4 命令行方式.................7 第2章类型和值9 2.1 Nil..............9 2.2 Booleans....9 2.3 Numbers...10 2.4 Strings......10 2.5 Functions.12 2.6 Userdata and Threads.12 第3章表达式..13 3.1 算术运算符...............13 3.2 关系运算符...............13 3.3 逻辑运算符...............13 3.4 连接运算符...............14 3.5 优先级.....15 3.6表的构造..15 第4章基本语法................18 4.1 赋值语句.18 4.2 局部变量与代码块(block)......19 4.3 控制结构语句...........20 Programming in Lua iv Copyright ® 2005, Translation Team, www.luachina.net 4.4 break和return语句......23 第5章函数......24 5.1 返回多个结果值.......25 5.2可变参数..27 5.3 命名参数.28 第6章再论函数................30 6.1 闭包........32 6.2 非全局函数...............34 6.3 正确的尾调用(Proper Tail Calls)...36 第7章迭代器与泛型for....40 7.1 迭代器与闭包...........40 7.2 范性for的语义...........42 7.3 无状态的迭代器.......43 7.4 多状态的迭代器.......44 7.5 真正的迭代器...........45 第8章编译·运行·调试47 8.1 require函数.................49 8.2 C Packages.................50 8.3 错误........51 8.4 异常和错误处理.......52 8.5 错误信息和回跟踪(Tracebacks)....53 第9章协同程序................56 9.1 协同的基础...............56 9.2 管道和过滤器...........58 9.3 用作迭代器的协同...61 9.4 非抢占式多线程.......63 第10章完整示例..............68 10.1 Lua作为数据描述语言使用........68 10.2 马尔可夫链算法.....71 第二篇 tables与objects........75 第11章数据结构..............76 11.1 数组......76 11.2 阵和多维数组.........77 11.3 链表......78 11.4 队列和双端队列.....78 11.5 集合和包.................80 11.6 字符串缓冲.............80 第12章数据文件与持久化..................84 12.1 序列化...86 Programming in Lua v Copyright ® 2005, Translation Team, www.luachina.net 第13章 Metatables and Metamethods...92 13.1 算术运算的Metamethods............92 13.2 关系运算的Metamethods............95 13.3 库定义的Metamethods................96 13.4 表相关的Metamethods................97 第14章环境..103 14.1 使用动态名字访问全局变量...103 14.2声明全局变量........104 14.3 非全局的环境.......106 第15章 Packages.............109 15.1 基本方法...............109 15.2 私有成员(Privacy)................111 15.3 包与文件................112 15.4 使用全局表............113 15.5 其他一些技巧(Other Facilities)...115 第16章面向对象程序设计.................118 16.1 类.........119 16.2 继承.....121 16.3 多重继承...............122 16.4 私有性(privacy)...................125 16.5 Single-Method的对象实现方法127 第17章 Weak表...............128 17.1 记忆函数...............130 17.2 关联对象属性.......131 17.3 重述带有默认值的表...............132 第三篇标准库134 第18章数学库................135 第19章 Table库...............136 19.1数组大小................136 19.2 插入/删除..............137 19.3 排序.....137 第20章 String库..............140 20.1 模式匹配函数.......141 20.2 模式.....143 20.3 捕获(Captures).146 20.4 转换的技巧(Tricks of the Trade)151 第21章 IO库..157 21.1 简单I/O模式..........157 21.2 完全I/O 模式........160 Programming in Lua vi Copyright ® 2005, Translation Team, www.luachina.net 第22章操作系统库........165 22.1 Date和Time............165 22.2 其它的系统调用...167 第23章 Debug库..............169 23.1 自省(Introspective)..............169 23.2 Hooks...173 23.3 Profiles.174 第四篇 C API..177 第24章 C API纵览..........178 24.1 第一个示例程序...179 24.2 堆栈.....181 24.3 C API的错误处理..186 第25章扩展你的程序....188 25.1 表操作.189 25.2 调用Lua函数.........193 25.3 通用的函数调用...195 第26章调用C函数..........198 26.1 C 函数..198 26.2 C 函数库................200 第27章撰写C函数的技巧..................203 27.1 数组操作...............203 27.2 字符串处理...........204 27.3 在C函数中保存状态.................207 第28章 User-Defined Types in C........212 28.1 Userdata.................212 28.2 Metatables..............215 28.3 访问面向对象的数据...............217 28.4 访问数组...............219 28.5 Light Userdata........220 第29章资源管理............222 29.1 目录迭代器...........222 29.2 XML解析...............225
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值