Unity3D学习笔记(三十):Lua
Lua:是一个轻量级的脚本语句。不需要编译,直接运行的语言。
环境配置:
执行Lua有两种方式:
1、交互式编程(输入后能立即看到效果)
2、脚本式编程:运行lua文件,.lua为文件后缀
Lua语句结尾不需要用分号结束,写了分号也没有问题。
删除一个中文字符,需要按两下删除
注释:
单行注释:--
多行注释:--[[...]]--或--[[...--]]或--[[...]]
print("Hello World") --单行注释 --print("单行注释") --多行注释 --[[ print("多行注释1") ]] --[[ print("多行注释2") --]] --[[ print("多行注释3") ]]
变量定义:
Lua不需要写变量类型,变量名 = 值。
Lua的标识符(变量名),1个字母或下划线开头,后跟0个或多个字母、数字、下划线
Lua是区分大小写的。
变量存储什么类型的数据,就是什么类型的变量。
使用type()来获取变量的类型。
Lua的数据类型:
number:小数类型(lua没有整型和浮点的区分),对应C#的int,float,double(浮点类型不能加f)
boolean:布尔类型,true和false。Lua里把false和nil看作是假,其他的都是真。
nil:表示空数据,等同于null。对于未被定义的变量,想要使用的话得到的都是nil。
string:字符串类型,可以使用双引号,单引号,[[...]]表示。([[...]]与注释有歧义,不推荐使用)
1、在对两个字符串类型的变量,进行算数操作的时候,加减乘除求余,Lua会尝试把这两个字符串去转换成数字去做计算,如果字符串转换不成功则报错。
2、使用..来做两个字符串的连接。
3、使用#来计算字符串的长度,放在字符串的前面。
--变量定义 --C# --int a = 1; --Lua a = 1 A = 2 _ = 3 print(a) print(A) print(_) --变量赋值 b = true print(b) print(type(b)) b= 4 print(b) print(type(b)) --number类型 c = 1 d = 1.2 print(c) print(type(c)) print(d) print(type(d)) --三种打印字符串的方式 e = "Hello World" f = 'Hello World' g = [[Hello World]] print(e, f, g) --..连接字符串 x = "1" y = "2" print(x + y)--加号表示算数运算 print(x .. y) --#计算变量长度 print(#e) print(#"Hello World") print(#"你好")--汉字占两个字节
table类型:table表示一个数组的时候,默认索引是从1开始的
创建:b = {}
table并不是一个数组,实际是一个“关联数组”,关联数组的索引可以是数字,也可以是字符串
--C# int[] a = new int[]{1, 2, 3}; --Lua的table a = {1, 6, 3} print(a[1]) print(type(a)) --创建一个空表 b = {} --创建一个表,并且对表进行初始化赋值 c = {"string", true, 1, nil} --table的访问 print(c[1]) --table的修改 c[1] = 100 print(c[1]) print(#c)--能算table长度,但不一定是真实长度 --table的添加 c[5] = 200 --table的方法:数组的插入和删除(索引的连续性) --第一个参剩:表的名字 --第二个参数:插入的内容 --依次向后找,只要找到一个nil的位置就把内容插入进去 table.insert(c, "你好") print(c[4])--结果:你好 --第二个参数:要插入的位置,可以跳跃性的插入 table.insert(c, 10, "小明") print(c[10])--结果:小明 --从第三个位置的元素开始,后面的元素依次后移 table.insert(c, 3, "小红") print(c[3])--结果:小红 print(c[4])--结果:1 --删除 --删除指定索引的位置的元素,后面的元素依次前移 d = {1, 4, "你好", true} table.remove(d, 1) print(d[1])--结果:4 --删除连续索引的最后一个元素 d[6] = 10 table.remove(d) print(d[3])--结果:nil print(d[6])--结果:10
--table的索引 a = {} a[1] = 0 print(a[1]) --把字符串作为一个索引 a["a"] = "nihao" print(a["a"]) --table可以有0号索引 a[0] = 10 print(a[0]) --table可以有负号索引 a[-1] = 100 print(a[-1]) print("-----------------") b = {[2] = 10, 1, 2, 3, 5, [-1] = 30, ["nihao"] = "你好", key = "不好", c = {1, 5}} print(b[1]) print(b[2])--会被覆盖掉 print(b[3]) print(b[4]) print(b[5]) print(b[6]) print(b[7]) print(b[-1]) print(b["nihao"]) --第一种访问字符串为索引的元素 print("-----------------") print(b["nihao"]) --第二种访问字符串为索引的元素 print(b.nihao) print(b["key"]) print(b.key) print(b.c[2]) --table.insert(c, 3, "小红")--报错:只能针对数组 --table.remove(c, 2)--报错:只能针对数组 --添加字符串为索引的元素 b["key1"] = "可以" b.key2 = "不可以" d = "可不可以" print(b.key1) print(b["key2"]) print(b[d]) print(#b)--结果:4,从1号位索引开始算,一旦索引断掉,就不往后面计算 f = {[2] = 2} print(#f)
Lua中的运算符
数学运算符:+,-,*,/,%,^
Lua里没有自增自减运算符,也没有+= *=之类的
关系运算符:>,<,==,>=,<=,~=
Lua里的不等于~=
逻辑运算符:and,or,not
流程控制语句
--流程控制语句 --C# if(条件){} --Lua --if语句 --[[ if 条件 then print("if语句满足,执行") end ]]-- if true then print("if语句满足,执行") end --if else语句 if a then print("if语句满足,执行") else print("if语句不满足,执行") end --if elseif语句 if a then--一般条件后面才加then关键字 print("if语句满足,执行") elseif b then--注意elseif是连着的 print("if语句不满足,执行") end --if elseif else语句 if a then print("if语句满足,执行") elseif b then--注意elseif是连着的 print("if语句不满足,执行") else print("if语句都不满足,执行") end
循环控制语句
--循环控制语句 --C# for,while,do while --Lua --while a = 1 while a < 10 do print(a) a = a + 1 end print("-------------") --do while C#条件满足继续执行循? --repeat 循环体 until 条件 条件满足跳出循环 a = 1 repeat print(a) a = a + 1 until a < 10 print("-------------") --for 变量定义,条件,每次循环累加值 do 循环体 end --条件就是一个数,变量 <= 条件,每次累加值可以不写,不写默认为1 --对于循环,有break关键字跳出,但是没有continue关键字 for a = 1, 10, 1 do print(a) end
方法:调用方法时,一定是先定义,在调用!
--方法 function func3() func1() end --方法的定义1 function 方法名(参数) 方法体 end function func1() print("func1") end --方法的定义2 方法名 = function(参数) 方法体 end func2 = function() print("func2") end --方法的调用,先定义再调用 func1() func2() func3() print("--------有参数的方法--------") --有参数的方法 func4 = function(a, b) print(a, b) end func4()--可以不传参数,按照nil处理 func4(1)--可以少传 func4(1, 2) func4(1, 2, 3)--可以多传,只取前2个 print("--------可变参数的方法--------") --可变参数的方法,参数位置用...表示是可以传任意的参数 --通过arg来取传入的参数,arg实际就是一表表示的数组 --当调用的时候,把所有传递进来的参数存入到arg中 func5 = function(...) print(#arg) for i = 1, #arg do print(arg[i]) end end func5(1,2,3,54,6,7,8) func5(1,"nihao",true,54,6,7,false,nil) print("--------带返回值的方法--------") --带返回值的方法 func6 = function() return "func6" end a = func6() print(func6(), a) print("--------带多个返回值的方法--------") --带多个返回值的方法 --多个返回值使用多个变量去接收,每个变量之间以逗号区别 --返回值与接收变量可以数量不一致,多退少补 func7 = function() return "a", true, 1, false end r1,r2,r3,r4 = func7() print(func7()) print(r1,r2,r3,r4) func8 = function() local z = "c" end func8() print("z:", z)
类
--类 a = {1,2,3,4,5,67,78} --遍历 for i = 1, #a do print(a[i]) end for key, value in ipairs(a) do print("key", key) print("value", value) end b = {1,2,4,5,[-1] = 5, ["key"] = "key", key1 = true} --ipairs()这种方式只能比哪里出数值类型 for key, value in ipairs(b) do print("key", key) print("value", value) end --pairs()这种方式能全部遍历出键和值 for key, value in pairs(b) do print("key", key) print("value", value) end
局部变量和全局变量
一般情况下,定义的变量都是全局的变量,包括方法内定义的
如果变量前多了local关键字,那么证明该变量局部的变量
--lua8 print("开始执行Lua8") local lua8 = {} lua8.const = 10 function lua8.func1() print("func1") end lua8.func2 = function() print("lua8.func2") end function lua8.func3() print("lua8.func3") end print("结束执行Lua8") return lua8
--lua10 print("开始执行Lua10") local lua8 = {func4 = function() print("func4") end, key = 10} lua8.const = 20 function lua8.func1() print("Lua10.func1") end lua8.func2 = function() print("Lua10.func2") end function lua8.func3() print("Lua10.func3") end print("结束执行Lua10") return lua8
Lua11.lua文件,在根目录下的Lua文件夹下
--Lua11 print("开始执行Lua11")
--require("Lua8") --require('Lua8') lua10 = require'Lua10' lua8 = require'Lua8' --func() print(lua8.const) print(lua10.const) lua8.func3() lua10.func3() --package.path 里存储的都是require所能执行的lua的文件路径 --print(package.path) --package.path = package.path .. ";D:\\LuaProject\\Lua\\?.lua" --..\\上级目录,.\\文件的当前目录 package.path = package.path .. ";.\\Lua\\?.lua" print(package.path) require'Lua11'
元表:改变规则的
Setmetatable(a, b)--把b设置成a的元表
Getmetatable(a)--返回a的元素
原方法的名字
算数类:__add(加)__sub(减)__mul(乘)__div(除)__unm(相反数)__mod(取余)__pow(求幂)
访问类:__index(查询)__newindex(修改table的字段)
关系类:__eg(等于)__lt(小于)等等
tab1 = {"tab1", "111", '222'} tab2 = {"tab2", 11, true} Set = {__add = function(t1, t2)--__add原方法 for k1, v1 in pairs(t1) do print(k1, v1) end print("--------------") for k1, v1 in pairs(t2) do print(k1, v1) end return "Set" end} setmetatable(tab2, Set)--设置元表,把Set这个表设置成tab1的元表 t = tab1 + tab2 --当两个表进行相加操作时,先判断两个表是否有元表? --如果两个表都没有元表,两个表不能进行相加操作 --如果两个表任意一个表有元素 --再判断元表内是否有__add的元方法 --如果元表里没有__add的元方法,不会执行,报错 --如果有__add的元方法,那么两个表可以相加 --并且相加的结果,就是__add的返回值 --__add的参数1是加号左边的表,参数2是加号右边的表 print(t) tab = getmetatable(tab2) print(tab) print("--------------") tab3 = {key = "k1"} Set1 = {__index = function(t1, key) print(type(t1)) for k1, v1 in pairs(t1) do print(k1, v1) end print(type(key), key) return "Set1" end} setmetatable(tab3, Set1) --当你要访问一个键对应值时,先判断这个表中有没有这个键,如果有就返回这个键对应的值 --如果这个表没有这个键,先判断这个表有没有元表 --如果有元表,再判断这个元表有没有__index的元方法 --如果有,访问的值就是这个__index返回的值 --__index里的参数1:表,参数2:要访问的键名 print(tab3.key1)
补充内容
逻辑运算符:
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190212001034427-1530430846.png)
VS编译:Ctrl + Shift + B
fixedDuration:固定过渡,不许打断
public float length { get; }//动画播放时长 public float normalizedTime { get; }//动画当前规范化时间,1是动画结尾,0.5是动画中间 public bool IsName(string name); public bool IsTag(string tag);
public class SkillOverStateBehaviour : StateMachineBehaviour { // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { //PlayerController pc = animator.GetComponent<PlayerController>();//获取动画组件身上的脚本 //pc.atkID = 0;//把脚本里的atkID归零 //animator.SetInteger("skillID", 0);//把animator面板里的skillID归零 animator.SetInteger("skillID", 0); } }
using UnityEngine; using System.Collections; using System.Collections.Generic; public class PlayerControl : MonoBehaviour { Animator anim; private void Awake() { anim = GetComponent<Animator>(); } private void Start() { } private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { AnimatorStateInfo animSta = anim.GetCurrentAnimatorStateInfo(0); if (animSta.IsName("skill1") && animSta.normalizedTime > 0.3f) { anim.SetInteger("skillID", 2); } else if(animSta.IsName("skill2")) { anim.SetInteger("skillID", 3); } else if(animSta.IsName("skill3")) { anim.SetInteger("skillID", 4); } else if(animSta.IsName("skill4")) { anim.SetInteger("skillID", 5); } else if(animSta.IsName("skill5")) { anim.SetInteger("skillID", 6); } else if(animSta.IsName("skill6")) { anim.SetInteger("skillID", 0); } else { anim.SetInteger("skillID", 1); } } } }