Lua相关技术踩坑

打包

  1. 把meshRenderer注释掉
  2. 把Lua文件要打进Per那个路径
  3. EmmyLua插件代码提示,需要打开资源目录哦,然后pull unity api在工作区右键栏目中,还有安装另一个插件,和另一个脚本。

脚本

  1. Lua全局变量优先从外面找,所以只要没有加local就是全局变量,切莫函数一个全局对象,外面一个相同的全局对象,而且还有两个要注意的地方,一个是需要require到该模块,还有如果在函数里的全局变量,需要执行才有哦。
  2. 元表不能执行元操作,t,k,v,表示设置的时候相关,k如果查找不到就为nil,不会要你设置的key
  3. Lua类对象中数据仅仅作为初始数据使用,之后实例化后,就和类对象没有关系了,各自开辟内存空间,所以类对象数据相当于静态数据
  4. 所以如果有:的方法就为实例方法,实例方法可以调用静态方法的操作,但是涉及到自己实例需要保存待数据必须用self去搞,谁调用冒号方法,就是把谁作为self带进去调用呢
  5. 类对象中new,请问应该是实例方法,还是静态方法。应该是实例方法,因为有可能有孙子去继承这个方法,而且只需要一个方法就可以形成所有后代的继承链
  6. 可以认为new(obj),传表其实就是让其拥有一些自己的数据,考虑到实例化后要分配空间,其实也相当于拿来做初始化待,只不过不是覆盖关系,一个静态数据的age,一个实例化数据的age
  7. require可以随便使用哦,很方便
  8. 在3级以上的继承关系,我们应该清楚的认识到,实例化的儿子,可以做孙子的类对象,也可以做它父亲的子实例化对象
  9. 面向对象总结,封装可以重新返回一个table解决,我们知道一个table和其方法都不加local。继承可以通过元表,然后设置元表的元方法实现,多态:默认是可以完全复写,不过要调用父类的方法怎么调用呢,如果直接super:xx(),你会发现你其实调用的父类的静态方法。根本不是和你作为儿子有另外内存数据的实例方法呢。
  10. 上面暂时我模拟不出来,还有多态也搞不定,暂时放弃多态!,暂时都先用复制代码解决问题,之后有机会看看巧克力Lua那个网易大佬的方案
  11. lua类函数中有一大错觉,以外能够直接获取age,其实获取不到,因为现在的age是全局变量,既不是lua类的静态age,也不是self传递对象的实例age
  12. 查错debug,pcall,error,assert
  13. Lua中有个很神奇的地方:不是说用了:就是实例方法比如如下:self先调用的实例化的GG方法,之后对于self来说MainManager:GG也相当于它这个类的静态方法,因为对于MainManager自己来说,他不过是MainManager.GG(go)的另一种形式罢了,关键看传递的是啥对象,既然是MainManager,那么它就是静态方法
function MainManager:InitGameState()
    self:GG()
    MainManager:GG()
end

--
function MainManager:GG()
    print("gg")
end

--
  1. 在lua中,pairs是打印最全的,table的长度仅仅和字段有关,与“属性”无关,而且也和元表无关,如果原表的__newindex为一个table,其实就是给这个table赋值,如果为一个函数需要RawSet才行,当然了如果没有,默认就是可以赋值的。
  2. 在Lua中无论是ipair,还是pair,无论在哪里插入的字段,其中的key都是从1开始的,所以,insert默认是从#c开始的
  3. lua中变量坑,下面两种是不一样的key
    print(j.str); print(j[str]);
  4. 有些类没有被Lua给注册,需要自己注册,然后点一下生产全部即可,如果发布1.0上线之后想热更的类这上面没有还是挺麻烦的
  5. Lua中有个坑:由于是从上到下检测的,倘若调用的函数是一个local的,不会获取的,除非在调用定义!!,当然了都是全局函数,无所谓在哪里
  6. 函数内定义的函数是全局的,如果加local估计就不是了
  7. do end包裹return
  8. Lua面向对象设计个人推荐最佳实践,严格区分类和实例,严格区分类相关和实例相关,类相关叫静态数据,无论字段,方法,都应该用.,只有实例的方法和属性才能用self,并且方法是需要:的
  9. 关于Lua的隐藏,我这里没有实现封装方法,也不打算弄,我的意见就是,不要在外面直接修改字段,要用某个类,必须先实例化,不可把实例化的对象放在模块里面。使用此类的对象持有之,调用方法也是用实例化的,不能直接调用类的,而且同样不能直接修改属性,必须通过方法才可以!!!!!
  10. 如果一个类本身是静态或者单例该如何处理呢?如果是静态类方法就不需要冒号了,而且不用写继承的New方法呢,直接使用就可以了,如果有静态类字段,还是通过方法获取不要直接修改。如果是单例模式的话,单例的方法哪怕有继承,也是静态的哦,如图所示的写法:


function Algo.GetInstance()
    if Algo.ins == nil then
        Algo.ins = Algo:New()
    end
    return Algo.ins
end

  1. 由于写get,set实在麻烦,暂时放弃给lua设置两个table来保持隐秘性,而且get,set已经有一部分隐藏了。。至少隐藏了字段
  2. 冒号方法的名字,不就是类.方法吗?嗯是呢
  3. 在遍历的时候,k仅仅是字符串,不可直接拿来跟全局变量相比
  • loadstring,热加载代码,这是一个函数,必须要调用才起作用呢
  • string.gmatch()返回一个迭代器函数
  • 方法中无论引用什么变量,都用local更安全
  • LUA 中只有”nil“和”false“是false
  • error方法第二个参数是错误环境的等级
  • rawset绕过元方法
  • setfenv设置环境,作用创建命名空间,或用第三方方便,推荐用继承一旦改变了环境,变量哪怕是全局都变成局部的了,当然可以通过父亲_G回到最初的地方
  • 具名参数是通过table来完成的
  • Lua可以省略(),比如调用方法xx{},请注意这种写法在闭包函数中会有错误哦
  • 闭包
function Bibao()
    local i =0;
    return function()
        i=i+1;
        print(i);
    end;
end;
local f =Bibao();
f();
f();
f();
f();
f();
f();
local f2 =Bibao();
f2();
f2();
f2();
  • 不会引起混论,…表示多参数之外,还表示此文件的名字呢
module(...,package.seeall);
  • select表示两种意思,a是可变参数的个数,b是第几个可变参数是啥
    local a = select("#", ...)
    local b = select(2, ...)
  • 尽量别有和Mono相关联的lua类,因为这样一操作,编辑器就无法跳转了,这也太了吧
  • :和 .的方法,之间不掉用self.xx没有严格限制,所以自己根据语境一定要严格区分好哦。
  • Lua编程中规范,禁止类去调用实例方法?类可以调用静态方法,如果经手过Unity的,那么调用实例方法,必须要先找实例,如果静态方法就不需要了。。
  • 判断一个类是不是静态的类的方式是,是不是只有一个New实例方法,如果还有实例方法就是非静态类,使用一定要继承
  • TrieNode的New问题困扰我:已经解决了,是把chidren当作实例属性了,我擦!!,而且local变量可以省略self

TrieNode = {}

function TrieNode:New(obj)
    local o = {isWord = false, children = {}}
    setmetatable(o, self)
    self.__index = self
    return o
end

Trie = {
    root = {}
}

function Trie:New(obj)
    local o = {}
    setmetatable(o, self)
    self.__index = self
    return o
end

function Trie:Insert(val)
    local tempRoot = self.root

    for i = 1, #val do
        local char = string.sub(val, i, i)

        if tempRoot.children[char] == nil then
            tempRoot.children[char] = TrieNode:New()
        end
        tempRoot = tempRoot.children[char]
    end
    tempRoot.isWord = true
end

function Trie:Search(val)
    local tempRoot = self.root

    for i = 1, #val do
        local char = string.sub(val, i, i)

        if tempRoot.children[char] == nil then
            return false
        end
        tempRoot = tempRoot.children[char]
    end

    return tempRoot.isWord
end

function Trie:StartsWith(val)
    local tempRoot = self.root

    for i = 1, #val do
        local char = string.sub(val, i, i)

        if tempRoot.children[char] == nil then
            return false
        end
        tempRoot = tempRoot.children[char]
    end

    return true
end

local temp = Trie:New()
temp.root = TrieNode:New()
temp:Insert("apple")
print(temp:StartsWith("ap"));
print(temp:Search("appl"));
for key, value in pairs(temp.root.children) do
    print(key, value)
end



  • table可以做结构看看有啥问题呢
  • Lua引用就是指向同一个呢
  • 又有一个方法困扰我:后补这个方法也能看懂了,__call把一个表当作方法一样使用!!,setmetatable就是返回的第一表{10},设置了原表,再将其返回
function table_max_index(t)
    local max_index = 0
    for k, v in pairs(t) do
            if max_index < k then
                    max_index = k
            end
    end
    return max_index
end

mytable = setmetatable({10}, {
__call = function(mytable, newtable)
            sum = 0
            for i = 1, table_max_index(mytable) do
                    sum = sum + mytable[i]
            end

            for i = 1, table_max_index(newtable) do
                    sum = sum + newtable[i]
            end
            return sum
    end
})

newtable = {10, 20, 30}
print(mytable(newtable))
  • 把全局方法当作拓展方法!!
  • Lua的字段会在元表链上找,这不注意容易引起bug
  • Lua种一些不熟悉的地方,加快练习脚步
--repeat  pcall,concat,entry用法,string.format
--tostring复写,嵌套函数,闭包,实现多继承,pack
  • ToLua中__Tostring是无效的
  • 在loadstring中,里面内容相当于一个匿名函数的body,获取到这个方法后,咱们还是要调用的哦
  • unpack函数和table没有关系,拿来解包的东西
local g ={1,2,3};
local g2= unpack(g,2);
print(g2);
  • local parents = {...} 这个方法相当于插入,所以可以获取的table的长度呢
    
  • 多继承的启示,匿名函数可以常驻内存中,只要设置了元表,才可以使用元方法。元表设置,不一定就是实例和类传递,也可能是类和一个匿名的元表进行了传递。而且其实主要是看__index是啥,如果是一个函数,就没必要想类和这个匿名元表为啥不设置地图关系


function Search(k, plist)
    for i = 1, #plist do
        local v = plist[i][k]
        if v then
            return v
        end
    end
end

function CreateClass(...)
    local t = {}
    local plist = {...}

    setmetatable(
        t,
        {
            __index = function(t, k)
                return Search(k, plist)
            end
        }
    )

    t.__index =t;

     function t:New()
       local o ={}
       setmetatable(o,t);
       return o;
    end

    return t;
end

A = {}
function A:HH()
    print("hh")
end
B = {}
function B:KK()
    print("kk")
end

n1 = CreateClass(A, B)
local n1Instane =n1:New();

n1Instane:HH();
n1Instane:KK();

  • 不管函数在哪里定义的都没有问题,返回了这个类,就能用这个类的方法呢
  • 如果是table这种引用类型的,类在实例化的时候是不分配空间的,所以这点需要注意一下下,最佳实践,还是属性写在内里,特别注意的引用类型写在需要的地方,并注意之前的属性能够带下去不
  • xlua chunkName不好,断点不能命中
  • lua中存nil,自动忽略
  • lua把公共函数写在主模块上,就不用操作_G了
  • 如下图执行顺序,详解,先执行i=4,再执行和5比较是否是小于等于的情况,如果不是跳出,如果是执行方法体,然后执行-1的操作,之后循环起来的时候会忽略第一步i=4。
for i = 4,5,-1 do
    print("woaini");
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值