Lua官网
Lua官方文档
Lua5.4参考指南
Lua5.3参考手册(中文版)
Lua菜鸟教程
Lua在线编辑器
Lua基本语法
Lua数据类型
Lua变量
Lua流程控制
Lua函数
Lua运算符
Lua字符串
Lua数组
Lua迭代器
Lua table(表)
Lua模块与包
Lua元表(Metatable)
Lua协同程序(coroutine)
Lua文件I/O
Lua错误处理
Lua调试(Debug)
Lua垃圾回收
Lua面向对象
一、变量类型
--未赋值的变量为nil --声明字符串变量(单引号或双引号皆可) --声明number s = 'my age is: ' i = 16 b = true print(s, i, b) --字符串也可以这样写[[字符串内容]] s = [[s1: hello world!]] print(s1) --声明table变量(相当于字典),没key的value用索引访问(索引从1开始) tab = {web = "www.baidu.com", QQ = 123456, b = true, "no-key-value"} print("table: ", tab["web"], tab["QQ"], tab["b"], tab[1]) s = "25" i = 26 --字符串转数字,数字转字符串 print(tonumber(s), tostring(i)) --创建一个函数 function fun(name) print("my name is "..name); end fun("tom")
运行结果
>lua -e "io.stdout:setvbuf 'no'" "test.lua"
my age is: 16 true
s: hello world!
table: www.baidu.com 123456 true no-key-value
25 26
my name is tom
>Exit code: 0
局部变量 local
示例1
x = 5 for i = 1, 10000 do local x = i end print(x)
输出 5
========================================================================================
for循环
--数字for循环 for i = 0, 10, 2 do print(i) end --泛型for循环,ipairs()是数组的迭代器 arr = {"a", "b", "c", "d"} for i, v in ipairs(arr) do print("arr["..i.."]="..v) end
运行结果
>lua -e "io.stdout:setvbuf 'no'" "test.lua"0
2
4
6
8
10
arr[1]=a
arr[2]=b
arr[3]=c
arr[4]=d
>Exit code: 0
while循环
do local i = 1 local n = 10 while (i < n) do print(i) i = i + 1 end end
repeat循环
i = 1 repeat i = i + 1 --当until(真)时跳出循环 until(i > 10)
========================================================================================
数学运算操作符
支持:加、减、乘、除、取模、幂
a = 5 b = 6 c = 7 d = 8 --支持: 加、减、乘、除、取模、幂 r = (a + b) * (a - b) / c % 8 + a^(-0.5) print("r="..r)
========================================================================================
可见性规则(闭包)
a = {} local x = 20 --创建10个函数闭包 --这些闭包中的每一个都使用了不同的y变量,而它们又共享了同一份x for i=1,10 do local y = 0 a[i] = function () y=y+1; return x+y end end for i=1,10 do print(a[i]()) end
输出
21
21
21
21
21
21
21
21
21
21
==========================================================================================
实现继承
__index、setmetatable()
--示例1: 继承 local Car = {} Car.__index = Car; function Car:run() print("Car:run()") end local SuvCar = {} --SuvCar继承Car setmetatable(SuvCar, Car) print(SuvCar.run()) --示例2: 继承 local Car1 = {} function Car1:new(o) o = o or {} --o继承Car1 setmetatable(o, { __index = Car1 }) return o; end function Car1:run() print("Car1:run()") end --SuvCar1继承Car1 local SuvCar1 = Car1.new() function SuvCar1:run1() print("SuvCar1:run1()") end print(SuvCar1.run()) print(SuvCar1.run1())输出
Car:run()
Car1:run()
SuvCar1:run1()
========================================================================================
协程
function foo (a) print("foo", a) return coroutine.yield(2*a) end co = coroutine.create(function (a,b) print("co-body", a, b) local r = foo(a+1) print("co-body", r) local r, s = coroutine.yield(a+b, a-b) print("co-body", r, s) return b, "end" end) print("main", coroutine.resume(co, 1, 10)) --[[ 上句输出 co-body 1 10 foo 2 main true 4 --]] --resume方法的参数作为yield()的返回 --yield方法的参数作为resume方法的返回 print("main", coroutine.resume(co, "r")) --[[ 上句输出 co-body r main true 11 -9 --]] print("main", coroutine.resume(co, "x", "y")) --[[ 上句输出 co-body x y main true 10 end --]] print("main", coroutine.resume(co, "x", "y")) --[[ 上句输出 main false cannot resume dead coroutine --]]输出:
co-body 1 10
foo 2
main true 4
co-body r
main true 11 -9
co-body x y
main true 10 end
main false cannot resume dead coroutine
========================================================================================
错误处理
print("--------test pcall------") function test() print("hello world") error("wrong value") end --pcall,以保护模式调用函数,出错时不打印堆栈信息 print( pcall(test) ) print("--------test xpcall------") function errhander(e) print("error info: " .. e) print("stack info: " .. debug.traceback("current 2 stack: " ,2)) end function ef() error("wrong value") end --xpcall,以保护模式调用函数,出错时调用回调方法并打印堆栈信息 print( xpcall(ef,errhander) )
输出:
--------test pcall------
hello world
false D:\test.lua:4: wrong value
--------test xpcall------
error info: D:\test.lua:15: wrong value
stack info: current 2 stack:
stack traceback:
[C]: in function 'error'
D:\test.lua:15: in function 'ef'
[C]: in function 'xpcall'
D:\test.lua:18: in main chunk
[C]: in ?
false nil
========================================================================================
环境/全局变量: _ENV
--_ENV是一个普通的全局table,所有的全局变量都会放到_ENV中 --print(type(_ENV)) --定义一个全局变量 my_gobal_var = 123 --访问全局变量 print(my_gobal_var) print(_ENV.my_gobal_var) print(_ENV["my_gobal_var"]) --打印所有全局变量 for n in pairs(_ENV) do print(n) end --判断是否定义了my_gobal_var变量 if my_gobal_var ~= nil then print("exits my_gobal_var") --这里会被执行到 end --覆盖默认环境 _ENV = {print=print} if my_gobal_var == nil then print("not exits my_gobal_var") --这里会被执行到 end
输出:
123
123
123
setmetatable
os
assert
utf8
rawequal
rawset
dofile
loadfile
rawget
require
collectgarbage
my_gobal_var
io
table
pcall
math
package
coroutine
tostring
select
pairs
ipairs
rawlen
next
error
arg
type
print
tonumber
debug
xpcall
string
load
_G
getmetatable
_VERSION
bit32
exits my_gobal_var
not exits my_gobal_var
========================================================================================
table.maxn()
返回table中最大正数索引
t = {t1="a", t2="b", "c", "d", "e", "f", t3="g", "h"} --连接table中的索引元素 --concat(table, 分隔符, 起始位置, 结束位置) tab = table.concat(t, "-", 2, 3); print(tab) --输出 d-e print(_VERSION) if _VERSION == "Lua 5.3" then print("lua version is 5.3") --lua5.3已经移除了maxn函数,需要自己实现 --函数功能: 返回tabel中最大的正数索引 table.maxn = function(tab) local n = 0 for k,v in pairs(tab) do if type(k) == "number" and k > n then n = k end end return n end end local n = table.maxn(t) table.insert(t, n+1, "i") for k,v in pairs(t) do print(k,v) end print("maxn="..table.maxn(t))
输出:
d-e
Lua 5.3
lua version is 5.3
1 c
2 d
3 e
4 f
5 h
6 i
t3 g
t1 a
t2 b
maxn=6
========================================================================================
table.remove()
删除指定位置的元素
t = {t1="a", t2="b", "c", "d", "e", "f", t3="g", nil, "h", "i", nil} print("maxn="..#t) --删除索引为1的元素,后面的元素会自动往前移 table.remove(t, 1) --删除索引最大的元素 table.remove(t, #t) --删除t2 t.t2 = nil for k,v in pairs(t) do print(k,v) end --安全删除所有以数字索引为key的元素,必须从后往前删 --只会删除找到的第一段连续索引元素 for i = #t, 1, -1 do table.remove(t, i) end print("deleted all index element") for k,v in pairs(t) do print(k,v) end
输出
maxn=7
1 d
2 e
5 h
6 i
t1 a
t3 g
deleted all index element
5 h
6 i
t1 a
t3 g
========================================================================================
table.pack()、table.unpack()
t = table.pack(1,"a",2,3) --打包 print("#t="..#t) print("t.n="..t.n) for k,v in pairs(t) do print(k,v) end print("----unpack----") local a,b,c,d = table.unpack(t) --解包 print(a,b,c,d) print(table.unpack(t, 2)) print(table.unpack(t, 2, 3))
输出
#t=4
t.n=4
1 1
2 a
3 2
4 3
n 4
----unpack----
1 a 2 3
a 2 3
a 2
========================================================================================
table.move()、table.sort()
t1 = {1, 2, 3, k1="abc"} t2 = {4, 5, 6, k2="def", 7} --将t1中的全部索引元素复制到t2中 table.move(t1, 1, #t1, #t2+1, t2) for k, v in pairs(t2) do print(k, v) end --注意: 比较函数实际上是重载了<号,所以当>=时都要返回false才行 table.sort(t2, function(a, b) --if(a < b) then return true end --升序 if(a > b) then return true end --降序 return false end ) print("--------sort-------") for k, v in pairs(t2) do print(k, v) end
输出
1 4
2 5
3 6
4 7
5 1
6 2
7 3
k2 def
--------sort-------
1 7
2 6
3 5
4 4
5 3
6 2
7 1
k2 def
========================================================================================
utf8
os.execute("chcp 936") --cmd中设置代码页为GBK --os.execute("chcp 65001") --cmd中设置代码页为UTF-8 --每个中文字符占3个字节, Unicode码写法"\u{4E2D}\u{6587}" local input = "中文Engish" --等效于local input = "\u{4E2D}\u{6587}Engish" print("len="..utf8.len(input)) print("---------utf8.codes-------") --遍历字符串中的所有字符 for p, c in utf8.codes(input) do print(p, c, utf8.char(c))--打印出字符中Unicode码 end print("---------utf8.codepoint----") --获取并打印前两个中文字符(总共占6字节) print(utf8.codepoint(input, 1, 6)) print("---------utf8.offset----") --返回第2个字符的开始位置(按字节数),从第1个位置开始统计 print(utf8.offset(input, 2, 1)) print("---------utf8.charpattern----") --打印所有匹配的UTF-8字符 for c in string.gmatch(input, utf8.charpattern) do print(c) end
输出
活动代码页: 936
len=8
---------utf8.codes-------
1 20013 涓
4 25991 鏂
7 69 E
8 110 n
9 103 g
10 105 i
11 115 s
12 104 h
---------utf8.codepoint----
20013 25991
---------utf8.offset----
4
---------utf8.charpattern----
涓
鏂
E
n
g
i
s
h
========================================================================================
string
local s = "Helo,World" local s1 = "from=world, to=lua" --打印每个字符的ANSI码 print("byte:", string.byte(s, 1, -1)) --ANSI码转字符串 print("char:", string.char(string.byte(s, 1, -1))) --搜索第一个匹配的标点符号,第四个参数为true会关闭模式匹配 print("find:", string.find(s, "%p", 1, false)) --格式化字符串 print("format:", string.format('%s,%g,%i', "input-string", 0.5, 1)) --搜寻所有匹配的子串 for k, v in string.gmatch(s1, "(%w+)=(%w+)") do print("gmatch:", k, v) end --查找并替换 local repl = {name="lua", version="5.3"} print("gsub", string.gsub("$name-$version.tar.gz", "%$(%w+)", repl)) --替换全部匹配项 print("gsub", string.gsub("$name-$version.tar.gz", "%$(%w+)", repl, 1)) --替换第1个匹配项 print("gsub", string.gsub(s, "(%w+),(%w+)", "%2,%1"))--%1~%9代表匹配到的子项,%0代表这里的s local s = string.gsub(s, "^%s*(.-)%s*$", "%1") --去除s左右空白字符 --查找匹配 print("match:", string.match(s, "%w+"), 1)--返回第一个匹配串及开始位置 --字符串长度 print("len", string.len(s)) --转成小写 print(string.lower(s)) --转成大写 print(string.upper(s)) --以小端方式打包参数 local fmt = "<I4I4s4f" --格式化参数详见文档 local p = string.pack(fmt, 100, 200, "hello", 0.1) print("packsize:", string.packsize(p))--输出字节数 print("unpack:", string.unpack(fmt, p, 1)) --解包 --用指定分割符连接字符串 print("rep:", string.rep("ss", 5, "-")) --反转字符串 print("reverse:", string.reverse(s)) --返回子串 print("sub:", string.sub(s, 1, 5)) --序列化与反序列化函数 function fun() print("string.dump test") end --将函数序列化为二进制,false代表包含调试信息 local b = string.dump(fun, false) --对函数反序列化 local f = load(b) f()
输出
byte: 72 101 108 111 44 87 111 114 108
100
char: Helo,World
find: 5 5
format: input-string,0.5,1
gmatch: from world
gmatch: to lua
gsub lua-5.3.tar.gz 2
gsub lua-$version.tar.gz 1
gsub World,Helo 1
match: Helo 1
len 10
helo,world
HELO,WORLD
packsize: 8
unpack: 100 200 hello 0.10000000149012 22
rep: ss-ss-ss-ss-ss
reverse: dlroW,oleH
sub: Helo,
string.dump test
========================================================================================
__pairs
local t = {1, 2, nil, 3} print("------ipairs------") --ipairs遇到nil就会停止迭代 for k, v in ipairs(t) do print("ipairs:", k, v) end print("------pairs------") --pairs会跳过nil继续迭代 for k, v in pairs(t) do print("pairs:", k, v) end --自定义表的迭代函数 local pairsfunc = function(tbl, key) local nk, nv = next(tbl, key) --返回下一对k-v if nk then nv = tbl[nk] end return nk, tostring(nv)..'p' --对返回的值做点改变 end local mt = {} mt.__pairs = function(tbl, key) return pairsfunc, tbl, nil end setmetatable(t, mt) --给t设置元表 print("------__pairs------") --会调用t的元表中的__pairs函数 for k, v in pairs(t) do print("pairs:", k, v) end
输出
------ipairs------
ipairs: 1 1
ipairs: 2 2
------pairs------
pairs: 1 1
pairs: 2 2
pairs: 4 3
------__pairs------
pairs: 1 1p
pairs: 2 2p
pairs: 4 3p
========================================================================================
rawequal()、rawget()、rawlen()、select()
local t = {1, 2, nil, 3} local t1 = t local s = "hello,world" local s1 = "hello,world" print("rawequal:", rawequal(t, t1)) --表比较引用 print("rawequal:", rawequal(s, s1)) --字符串比较值 print("rawget:", rawget(t, 1)) --获取元素 print("rawlen:", rawlen(t), rawlen(s)) --获取长度 rawset(t, "k", "v") --设值 local params_count = select("#", 1, 2, 3, 4, 5, "p") --返回参数个数 print("select:", params_count) local param = select(6, 1, 2, 3, 4, 5, "p") --返回第6个参数 print("select:", param)
输出
rawequal: true
rawequal: true
rawget: 1
rawlen: 4 11
select: 6
select: p
========================================================================================
collectgarbage()
print("isrunning:", collectgarbage("isrunning")) print("stop:", collectgarbage("stop")) print("isrunning:", collectgarbage("isrunning")) print("restart:", collectgarbage("restart")) print("isrunning:", collectgarbage("isrunning")) print("count:", tostring(collectgarbage("count")).."kb") print("step:", collectgarbage("step", 10)) print("step:", collectgarbage("step", 10)) --获取lua占用的内存数(单位kb) print("count:", tostring(collectgarbage("count")).."kb") --设置步进倍率为内存分配的2倍速度 print("setstepmul:", collectgarbage("setstepmul", 200)) --设置间歇率,当总使用内存达到之前的2倍时开始新的一轮收集 print("setpause:", collectgarbage("setpause", 200)) --做一次完整的垃圾收集循环,collect是默认选项 print("collect:", collectgarbage("collect")) --步长设置大点希望一步就执行完收集工作 print("step:", collectgarbage("step", 60))
输出
isrunning: true
stop: 0
isrunning: false
restart: 0
isrunning: true
count: 25.9775390625kb
step: false
step: true
count: 24.50390625kb
setstepmul: 200
setpause: 200
collect: 0
step: true
========================================================================================
函数
--定义全局函数 function gfun() end --定义局部函数 local function locfun() end local Foo = {} Foo.name = "Job" --定义局部函数 function Foo.fun(...) local tbl = {...} --以参数为内容创建一张表 print(tbl[1]) local p1 = select(1, ...) --获取第1个参数 print("Foo.fun:", p1, ...) return ... end --定义局部函数 Foo.fun1 = function(...) print("fun1") end --定义局部函数,self参数是个隐藏参数,会自动传入 function Foo:fun2(x, y) print("fun2:", "x="..tostring(x), "y="..tostring(y), "name="..self.name) end --定义局部函数 function Foo.fun3(self, x, y) print("fun3:", "x="..tostring(x), "y="..tostring(y), "name="..self.name) end print("Foo.fun: return ", Foo.fun(1, 2, 3)) --把函数调用括起来只接收返回的第一个值 print("(Foo.fun): return ", (Foo.fun(1, 2, 3))) --函数写在前面只会返回一个值 local a, b, c, d = Foo.fun(1,2,3), 4 print("return1:", a, b, c, d) --函数会返回所有值 local a, b, c, d = 4, Foo.fun(1,2,3) print("return2:", a, b, c, d) --调用冒号定义的函数 Foo.fun2(Foo, 10, 20) --必须显示传入self Foo:fun2(10, 20) --会自动隐式传入self --调用点号定义的函数 Foo.fun3(Foo, 10, 20) --必须显示传入self
输出
1
Foo.fun: 1 1 2 3
Foo.fun: return 1 2 3
1
Foo.fun: 1 1 2 3
(Foo.fun): return 1
1
Foo.fun: 1 1 2 3
return1: 1 4 nil nil
1
Foo.fun: 1 1 2 3
return2: 4 1 2 3
fun2: x=10 y=20 name=Job
fun2: x=10 y=20 name=Job
fun3: x=10 y=20 name=Job
========================================================================================
UpValue
function fun1() local a = 1 --外层变量就是内嵌函数的UpValue local fun2 = function() a = a + 1 return a end return fun2 end --内嵌函数脱离外层函数时依然可以访问UpValue local f1 = fun1() print("f1:", f1()) print("f1:", f1()) -- local f2 = fun1() print("f2:", f2()) print("f2:", f2())
输出
f1: 2
f1: 3
f2: 2
f2: 3
示例
string = "Lua Tutorial"-- 查找字符串 print(string.find(string,"Tutorial")) reversedString = string.reverse(string) print("新字符串为",reversedString)
示例
string = "Lua Tutorial"-- 查找字符串 print(string.find(string,"Tutorial")) reversedString = string.reverse(string) print("新字符串为",reversedString)
5 12 新字符串为 lairotuT auL
日历
最新文章
随机文章
热门文章
分类
存档
- 2025年1月(1)
- 2024年12月(5)
- 2024年11月(5)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
- Open CASCADE
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号