天天看點

LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  

http://www.runoob.com/lua/lua-data-types.html    //菜鳥教程

https://blog.csdn.net/qq_39574690/article/details/80753504  //LUA注意點

https://blog.csdn.net/qq_39574690/article/details/80725308   //xLua熱更新總結

https://blog.csdn.net/qq_39574690/article/details/80773837  //uLua熱更新知識

https://github.com/wuxiongbin/XIL  //使用ILRuntime實作的類似XLUA功能的Unity3D下熱修複BUG的解決方案

http://www.cnblogs.com/slysky/p/7920694.html  //整理Lua和Unity和Lua互動文章連結

https://download.csdn.net/download/tvcctv27tv/10344318  //解決下載下傳逾時的問題

一、了解Lua

1. lua語言解決的問題:嵌入應用程式,為應用程式提供靈活的擴充和定制.

2. 特性:輕量級 可擴充  

3. 其他特性:

1》支援面向過程程式設計和函數式程式設計      2》自動記憶體管理,隻提供一種通用類型得table,用它可以實作數組,哈希表,集合,對象。    3》語言内置模式比對:閉包(closure); 函數可以看作是一個值;提供多線程支援。  5》通過閉包和table可以支援面向對象所支援的關鍵機制,eg資料抽線,虛函數,繼承,重載。

二、Lua基本文法

1. 互動式程式設計

  lua提供了互動式程式設計模式。在指令行中輸入  lua -i   即可啟用。

2. 腳本式程式設計

  <1. 通過ide去編譯執行。

  <2. 辨別符

    <1> 定義辨別符變量和函數:區分大小寫的。

    <2> 最好不要用_ABC 即下劃線加大寫字母的形式,因為Lua的保留字也是這樣的,用于Lua内部全局變量  _VERSION。

    Lua 中,字母(letter)的含義是依賴于本地環境的。

    <3. 定義的預設是全局變量; 給變量指派後預設就建立了這個全局變量 ;通路一個沒有初始化的全局變量也不會報錯,隻不過得到的結果是nil 。

       删除了全局變量隻需将變量為nil    b=nil.

三、Lua得資料類型:

1. 資料類型

 Lua是動态類型語言,變量不要類型,隻需要為變量指派。

 Lua有8種基本類型: nil、boolean、number、string、userdata、function、thread、table.

 nil: 表示一個無效值,在條件語句中相當于false; 給全局變量或table指派nil,相當于删除。

 boolean:  Lua 把 false 和 nil 看作是 false,其他的都為 true,數字 0 也是 true:

 number : 雙精度類型的實浮點數。其實隻要是實數就是雙精度類型。包括0. 

     注意 Lua 中所有的值都可以作為條件。在控制結構的條 件中除了 false 和 nil 為假,其他值都為真。是以 Lua 認為 0 和空串都是真。

 string : 由一對雙引号或單引号來表示。也可以是[[  fdasdfads  ]] 表示一塊字元串,一般是一個html字元串。

 userdata : 表示任意存儲在變量的c資料結構。

 table : 是關聯數組。數組索引可以是數字、字元串或表達式。 Lua裡,table的建立是通過構造表達式來完成,最簡單的構造表達式是{} ,建立一個空表。

 type 來測試類型: 

 print(type(10.4*3))   --> number

 print(type(print))      --> function

 type(X)=="nil"   ---> nil做比較時,加“”來比較。

2.  lua字元串的操作:

字元串使用雙引号,單字元使用單引号。模式串也是單引号。

1. 在對一個數字字元串上進行算術操作時,Lua 會嘗試将這個數字字元串轉成一個數字:

print("2"+6)   --> 8

2. 字元串拼接是 .. ;    +号是加法計算,串不能相加時,會報錯,和c#不一樣,不是連接配接字元串 ;

3. 計算字元串長度 print(#"www.runoob.com") 

3. 表table:

lua中的數組索引,key是以1開始的。

tab1={};

tab2={key1=100,key2="value"}  --鍵不能用引号引起來

--print(tab1);

--print(tab1.key);

print(tab2.key1);   --1.直接擷取key  

print(tab2["key1"]); --2.通過鍵的名字擷取

周遊:

1. for in pair do 形式 

  lua裡有break,但是沒contiue.  在lua5.2版本後,可以使用goto continue 來模拟。

for a=1,5 do
	if(a==3) then
	  goto continue
	end
	::continue::
end
           
for key,val in pairs(tab1) do
print("key",val)
end
           

2.for  do形式

for i=1,2 do
print("fddsfasd")
end
           

4.函數

<1. lua中函數可以直接指派給變量。

<2. 函數可以以匿名形式來傳遞。

5.thread

6.userdata 自定義類型

四、Lua變量:

1. 全局變量,局部變量,域

2. 指派語句

多個變量指派(函數傳回多個值)時,變量個數>值的個數,那麼多餘的指派為nil.  <值得個數,則多餘的值忽略。

3. table的索引通路

<1. 和字典的形式一樣通路。tab[2]  //此處的2是index,第幾個

<2.如果存儲的字元串,則可以使用tab.key  //設定key是字元串時才可以這樣通路,預設key是從1開始的整數。

五、六、循環語句、流程控制

while、for、repeat...unitl、循環嵌套。

break、goto

七、函數

1.可變參數:

 <1. 和c語言類似,用... 三個點表示可變參數.  lua中可以周遊參數數組。

 <2. 可變參數還可以指派給一個變量。select("#",...) 可以擷取可變參數的數量

 <3. ...  三個點來初始化一個表,再通過周遊這個表,來達到周遊參數個數。

 <4. select("#",...)   擷取可變參數的所有個數,包括nil。   

 <5. select("#",tab) 擷取tab長度時遇到參數是nil時,則停止計數,并且傳回計數。  #tab或者string  是即使有nil,也會計數。

 <5. 如果加強定參數,則固定參數必須是寫在可變參數的前邊。

function add(...)  
local s = 0  
  for i, v in ipairs{...} do   --> {...} 表示一個由所有變長參數構成的數組  
    s = s + v  
  end  
  return s  
end  
print(add(3,4,5,6,7))  --->25
           
--辨別符
b=10
print(type("hello"))
print(type(1.2))
if true then
print("wangzhe")
end


--表 table
tab1={};
tab2={key1=100,key2="value"}  --鍵不能用引号引起來
--print(tab1);
--print(tab1.key);

print(tab2.key1);   --1.直接擷取key
print(tab2["key1"]); --2.通過鍵的名字擷取

tab3={"皅qq","sss"};   --不指定key時相當于數組,索引從1開始
--print(tab3[2])
for key,val in pairs(tab3) do
print(key..":"..val);
end

--表中删除後,索引時不連續的
tab3[2]=nil;

for key,val in pairs(tab3) do
print(key..":"..val);
end
tab3=nil;  --删除整個表


--函數的傳遞
function fact(n)
	if(n==1) then
		return n;
	else
		return n*2;
	end

end

--函數當類型來使用
fact2=fact;
print(fact2(2));
--函數作為函數的參數傳遞

--匿名函數
print(function (k,v)
print("匿名函數");
end
);
           
--25   [local]function  局部函數
local function Name(num1,num2)
	if(num1>num2) then
	return num1
	else
	return num2
	end
end

--print(Name(2,3));
--函數的指派   匿名函數  函數當參數傳遞


--26  函數的可變參數
function test(...)
	local arg={...}
	res=0
	for k,v in pairs(arg) do
		res=res+v;
		--print(arg[1])  	--會把傳進來的參數封裝成一個表(arg) 這樣擷取的arg還得帶有一個參數是說明這個表的個數的  周遊表
	end
	print(res);
end

test();
test(2);
test(4,5);
test(11,5,3,9);

--輸出
0
2
9
28
           

八、運算符

1. Lua邏輯運算符

 and 、 or 、not

九、字元串

--30  字元常見操作
str="wang yan jie"
str2=string.upper(str)   --lower   --轉換成大寫,但是對原有字元不做處理

print(str,str2)

--32 Lua數組的基本特性和定義
--lua的表是鍵值對的形式,是以索引可以 負數


--33 多元數組

--34 Lua中的疊代器函數
--pairs 周遊表中所有的key和value
--ipairs 按照索引從1開始周遊,遞增周遊,遇到nil就停止周遊


--[[for  變量清單 in 疊代函數,狀态變量(預設是nil),控制變量  do
	--循環體
end
--]]

--變量清單是根據疊代器的傳回值來的,多少個傳回值就定義多少個變量清單來接受
--狀态變量指揮在第一次調用的時候指派,相當于是初始化  标注需要疊代多少次數【其實就是數組所帶的個實鬧諜】

           

十、Lua數組

1. 可以使用整數索引來通路數組元素,如果索引沒有值則傳回nil。

2. Lua 索引值是以 1 為開始,也可以指定以0或者負數為索引。

3. Lua中支援多元數組。注意指定是數組的索引值,避免出現nil,節省記憶體。

不同索引鍵的三行三列陣列多元數組:根據不同索引鍵把三維數組存入到一維數組中。

十一、Lua疊代器

疊代器:

For周遊格式:

for key=1,3,1 do  --從1疊代到3,疊代步長是1

print(square,3,key)

End

For疊代器格式:

    使用lua預設的疊代器函數ipairs

for k, v in pairs(tab) do

    print(k, v)

End

For疊代器的流程:

首先,初始化,計算 in 後面表達式的值,表達式應該傳回泛型 for 需要的三個值:疊代函數、狀态常量、控制變量.  square , 3 , 0

第二,将狀态常量和控制變量作為參數調用疊代函數(注意:對于 for結構來說,狀态常量沒有用處,僅僅在初始化時擷取他的值并傳遞給疊代函數)。

第三,将疊代函數傳回的值賦給變量清單。 (i,v)=(currentNumber, currentNumber*currentNumber)

第四,如果傳回的第一個值為nil循環結束,否則執行循環體。

第五,回到第二步再次調用疊代函數

無狀态疊代器:

優點:無狀态的疊代器是指不保留任何狀态的疊代器,是以在循環中我們可以利用無狀态疊代器避免建立閉包花費額外的代價。應該是不保留上邊的控制變量。

多狀态疊代器:

疊代器需要儲存多個狀态資訊而不是簡單的狀态常量和控制變量。

儲存多狀态的方式:

  1. 使用閉包; 
    1. 閉包解析:https://www.jb51.net/article/60866.htm

             初步看,由于建立變量i的函數 newCounter 已經傳回, 是以每次調用 func 時, 應該是超過了作用範圍。其實不然,lua使用了閉包來處理,一個 closure 就是一個函數加上該函數所需通路的所有"非局部的變量"。是以上例中 c1, c2 是同個函數所建立的兩個不同的 closure, 它們各自擁有局部變量i的獨立執行個體.

function newCounter()
        local i = 0
        func = function()
                i = i + 1
                return i
        end
        return func
end
c = newCounter()
print(c())
print(c())
           
  1. 将所有的狀态資訊封裝到 table 内,将 table 作為疊代器的狀态常量,因為這種情況下可以将所有的資訊存放在 table 内,是以疊代函數通常不需要第二個參數。
    1. 使用tab來實作多狀态:
array = {"Google", "Runoob"}
count=#array
tab={}
tab["index"]=0
function elementIterator()
      tab["index"]=tab["index"]+1
      if tab["index"] <= count then
         --  傳回疊代器的目前元素
         return array[tab["index"]]
      end
end
for key=1,2,1 do
  print(elementIterator(tab))
end
           

--39  Lua中的子產品

--對代碼做一些分? 局部函數在另一個子產品中調用時,放在全局函數中調用?

--變量,函數,封裝在一個表中,在另一個表中引用,最後傳回modle

--引用時引用的時檔案名

LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  
--40 c包

--41 元表  定義對表和表進行之間的操作  定義元方法
	--一個元表隻能作為一個表的元表  ,一般情況下元表是對普通表做的擴充,一般是不能修改的

mytable={"Lua","java"}  --普通表
mymetable={}  --元表
mytable=setmetable(mytable,mymetabe)  --此函數的傳回值是普通表

--  getmetable(mytable)   得到普通表對應的元表
--  如果元表(metatable)中存在__metatable鍵值,則setmetable會失敗,
    --當設定元表是這個鍵值對時,當輸出普通表對應的元表,則隻會輸出地__metatable的值,而得不到元表了
	--禁止使用者通路和修改元表中的成員或者修改元表



--43 元表中__index的作用:元方法
        --當通路到一個不存在的索引時起作用
	--如果__index包含一個函數的化,Lua會調用這個函數,table和鍵會作為參數傳遞給這個數
	--__index元方法檢視表中元素是否存在,如果不存在且沒有傳回值,則傳回nil,如果由傳回值則傳回這個傳回值。存在則由__index傳回結果,
	--__index後是一張表時,則在普通表中找不到時會在元表中找這個這個鍵對應的值。處理索引通路不存在的情況。
--注意:如果通路普通表中一個不存在的鍵時,則會調用元函數做一些事情


--44 元表中的__newindex的作用
--調用時機: 當我們對普通表中的一個新的索引修改時才會起作用  
	--或者給表添加新的鍵值對時起作用,調用後邊跟的函數,後邊的函數通過 rawset(table,key,value) ,來加入到這個普通表中
--如果後邊跟的時一個表,則添加新鍵值對時,則會把這個key和value 直接添加到這個後邊跟的表中。
	
--如果後邊	
	
__newindex=function(table,key,value)  --普通表  修改的key  修改成的值
end
           

Lua協程

--46  元表中的__call的作用
	--定義這個函數後,就可以把表當函數來使用時,mytable()  __call = Fuction(tab,arg1,arg2)

--47  元表中tostring元方法的作用

--48協程函數



--49  定義和啟動協程函數

--定義
--[[
co=coroutine.create(
	function (a,b)
		print(a+b)
	end
	)
--啟動
coroutine.resume(co,10,20)   --既可以啟動,又可以恢複協程程式

--]]

--[[
--第二種定義方式
co=coroutine.wrap(
	function (a,b)
		print(a+b)
	end
	)

--啟動
co(20,30)

--]]

--挂起
co=coroutine.create(
function(a,b)
	print(a+b)
	print(coroutine.status(co))
	coroutine.yield(a/b)  --暫停
	print(a-b)
	return a*b
	end
)

----協程的傳回值  傳回結果和傳回值.中間有暫停時傳回值在yiled中傳遞

result,res1= coroutine.resume(co,10,20)
print("協程啟動是否成功  ")
print(res1);
print("i am here")
print(coroutine.status(co))

--協程程式的内部和外部的交流

--狀态  函數整個執行完後就是dead狀态
--resume是處于主程式中,将外部狀态傳到協程裡面,yield是在協程内部,将資料傳回出。
           
LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  

二: Lua基本用法

Table: 如果兩個指針指向同一個位址,把其中一個釋放後,另一個位址任然在。

LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  

排序注意點:

當我們擷取 table 的長度的時候無論是使用 # 還是 table.getn 其都會在索引中斷的地方停止計數,而導緻無法正确取得 table 的長度。

可以使用以下方法來代替:

function table_leng(t)
  local leng=0
  for k, v in pairs(t) do
    leng=leng+1
  end
  return leng;
end
           

Lua 子產品與包//??

子產品其實就是已知元素組成的一個table.調用和table的調用一緻。

LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  

????????????

LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  

使用子產品方法:

-- require "子產品名"

-- require ("子產品名") --子產品名并不是表名而是檔案名,例如将上面的檔案名改為module1.lua,那麼下面的也要改為require 'module1'

require "module"  --相當于引用了整個module.lua檔案,那個檔案的内容會替換掉這句代碼,下面開始使用module表

print(module.var)

module.func1()

module.func3()

Lua元表(Metatable)//??

對兩個表進行操作  “_add”等即時字段,對應一個值(table或者方法),該值 就是“元方法”

setmetatable(mytable,mymetatable)     -- 把 mymetatable 設為 mytable 的元表 

Lua 查找一個表元素時的規則,其實就是如下 3 個步驟:

  • 1.在表中查找,如果找到,傳回該元素,找不到則繼續
  • 2.判斷該表是否有元表,如果沒有元表,傳回 nil,有元表則繼續。
  • 3.判斷元表有沒有 __index 方法,如果 __index 方法為 nil,則傳回 nil;如果 __index 方法是一個表,則重複 1、2、3;如果 __index 方法是一個函數,則傳回該函數的傳回值。

4.2 metatable元表概念

4.2.1元表的__index指定方法:

--1. funciton __index

--普通表

mytable={'C#','Java','C++'}

--元表

mymetatable={

<span style="white-space:pre;">    </span>__index=function(tab,key)  --注意:__index 是有2個'_'在前面的,不要寫成_index

<span style="white-space:pre;">        </span>print(tab[1]) --tab是元表對應的普表表

<span style="white-space:pre;">        </span>print(key)    --key是在普通表mytable沒有找到的鍵

<span style="white-space:pre;">        </span>return '1212'

<span style="white-space:pre;">    </span>end

}

--設定mytable的元表是mymetatable

mytable=setmetatable(mytable,mymetatable)

print(mytable[3]) -- 通路存在于普通表的鍵,正常輸出C++,而不會去執行元表__index指定的方法

print(mytable['a']) -- mytable['a']傳回了一個字元串'1212' 這個字元串的傳回是因為執行了__index指定的方法

-- 總結: 當普通表mytable中沒有對應的鍵值對時,會去調用mymetatable元表的__index指定的方法,輸出tab(普通表)[1]元素和找不到的鍵,并傳回'1212'字元串

C++

C#

a

212

觸發__index的方法是從普通表查不到鍵時,即這種情況也會觸發q=mytable['a']

4.2.2__index指定一個表

--2.__index mytable mymetatable

mytable={'C#','Java','Lua'}

index_table={'XLua','Unity','Hotfix','Look'}

mymetatable={

    __index=index_table    --當普通表搜不到鍵值對時會去到__index指定的表搜 ,如果還是找不到,那就傳回nil

}

mytable=setmetatable(mytable,mymetatable)

print(mytable[1])--輸出 C#

print(mytable[4])--輸出 Look (這個是在__index指定的表index_table拿到的)

C#

Look

--------------------- 

4.2.3__newindex指定一個方法

-- __newindex Function

mytable={'c#','Java','phyton'}

mymetatable={

    __newindex=function(tab,key,value)

        print('表[1]'..tab[1])

        print('新的鍵'..key)

        print('值'..value)

        --如果我要往元表插入資料

        rawset(tab,key,value)

    end

}

mytable=setmetatable(mytable,mymetatable)

mytable[1]='6'

mytable[100]='abc'

print('插入鍵值對='..mytable[100])

--當對普通表新增鍵值對時,會調用元表的__newindex指定的方法,tab是普通表,key是新增的鍵,value是新增的值

表[1]6

新的鍵100

值abc

abc

--------------

->在這裡我突發奇想,測試一下mytable[100]='abc'會不會觸發__index的方法或表

-- __newindex Function

mytable={'c#','Java','phyton'}

mymetatable={

    __index=function(tab,key)

        print('沒找到鍵='..key)

        return '__index傳回給你'

    end,

    __newindex=function(tab,key,value)

        print('表[1]'..tab[1])

        print('新的鍵'..key)

        print('值'..value)

        --如果我要往元表插入資料

        rawset(tab,key,value)

    end

}

mytable=setmetatable(mytable,mymetatable)

mytable[1]='6'

mytable[100]='abc'

表[1]6

新的鍵100

值abc

可見,Lua并不是按照一般思路去思考的,對普通表進行指派操作若新增鍵值對了,那麼會觸發__newindex指定的方法或表處理.

--------------------- 

4.2.4__newindex指定一個表

--4 __newindex table

mytable={'C#'}

table={}

mymetatable={

<span style="white-space:pre;">    </span>__newindex=table

}

mytable=setmetatable(mytable,mymetatable)

mytable[1]='6'

mytable[100]='abc'

print(mytable[1]) --輸出 6

print(mytable[100]) -- 輸出 nil

print(table[1])  -- 輸出 nil

print(table[100]) -- 輸出 abc

--總結:當對普通表新增鍵值對的操作,不會作用于普通表,而是作用于元表__newindex指定的表

6

nil

nil

abc

--------------------- 

--簡單模式檔案的讀寫
--[[
file=io.open("source.txt",r)   --傳回檔案的句柄,句柄就是控制檔案的,方向盤功能
io.input(file)		--表示下邊對檔案進行輸入了
print(io.read())
io.close(file)
--]]

--完全模式  :讀取   寫入緩沖,減少和磁盤的互動,節省性能
--[[
file=io.open("source.txt",r)
print(file:read());
file:close()
--]]

--Lua垃圾回收機制
--增量标記掃描處理器  ,一個表可以被多個變量引用。掃描有沒有被使用
--垃圾收集器間歇率  ,控制收集頻率
--垃圾收集器∽最後收集清空



--Lua面向對象
--table引用類型  對一個對象來說就是屬性 方法

--[[
person={name="Wyj",age=27}

person.eat=function(self)
	print(self.name.."在撸代碼")
end

a=person		--此處person和a都是用的指針,值類型,類似于c#的引用類型,傳遞的是引用【值類型】
--person.eat(person)
person=nil
a.eat(a)

--]]


--使用:定義的方法,則可以直接使用self,因為self就是代表目前的這個表,系統會自動指派
--:調用的對象,self代表:前邊的對象
--[[
person={name="Wyj",age=27}

function person:eat()
	print(self.name.."在寫代碼")
end
a=person
a:eat()
--]]


--面向對象的核心
--為了能使得person重複聲明對象

person={name="Wyj",age=27}

function person:eat()
	print(self.name.."在寫代碼")
end

--**************Lua通過new方法構造對象
--__index通路某個值時,如果該值不存在的時候,則會從其元表中通路
--__newindex如果對普通表進行修改時,如果普通表中該值不存在,則會設定在__newIndex對的元表中去,【如果該__newInex對的是一個函數則會調用此函數
function person:new(o)
	t= o or {}    --o等于null的北,則t={},否則t=o
	setmetatable(t,{__index=self})  --調用一個屬性時,如果t中不存在,那麼會在__index所指定的table中查找
	return t
end

person1=persson:new(nil)
print(person1.name)   --person1調用name的時候,如果t中不存在,則會從index指定的表中進行搜尋輸出


person2=persson:new({weight = 100})
person2.name="wyj"   --元表的增加值/設定值
print(person2.name)


--62 lesson
--63 繼承
Student=person:new()  --使用person構造出來,則有了person中的屬性
--再給student添加自己的屬性
Student.grade=1;
stu1=Student:new()






           

__newindex 元方法//??

__newindex 元方法用來對表更新,__index則用來對表通路 。

當你給表的一個缺少的索引指派,解釋器就會查找__newindex 元方法:如果存在則調用這個函數而不進行指派操作。

LuaLua 協同程式(coroutine)Lua 檔案 I/OLua 錯誤處理Lua 調試(Debug)Lua 垃圾回收Lua 面向對象Lua 資料庫通路                                                    Lua 程式設計:第4章   基本文法第4章   基本文法第6章  再論函數                                                  

Lua 協同程式(coroutine)

線程和協同程式差別

線程與協同程式的主要差別在于,一個具有多個線程的程式可以同時運作幾個線程,而協同程式卻需要彼此協作的運作。

在任一指定時刻隻有一個協同程式在運作,并且這個正在運作的協同程式隻有在明确的被要求挂起的時候才會被挂起。

總結: coroutine.creat方法隻要建立了一個協程 ,那麼這個協程的狀态預設就是suspend。使用resume方法啟動後,會變成running狀态;遇到yield時将狀态設為suspend;如果遇到return,那麼将協程的狀态改為dead。

coroutine.resume方法需要特别注意的一點是,這個方法隻要調用就會傳回一個boolean值。

coroutine.resume方法如果調用成功,那麼傳回true;如果有yield方法,同時傳回yield括号裡的參數;如果沒有yield,那麼繼續運作直到協程結束;直到遇到return,将協程的狀态改為dead,并同時傳回return的值。

coroutine.resume方法如果調用失敗(調用狀态為dead的協程會導緻失敗),那麼傳回false,并且帶上一句"cannot resume dead coroutine"

resume是從挂起點運作。

-- 可發現,協程的狀态是隻有在協同程式的方法裡面才是運作狀态,在外部都是處于挂起或者死亡狀态的

--菜鳥教程的案例有誤,在外部輸出coroutine.running()必然是nil (親測)

全面解析菜鳥教程的對于resume和yiled的靈活使用

Lua 檔案 I/O

Lua 錯誤處理

assert 

error (message [, level])

功能:終止正在執行的函數,并傳回message的内容作為錯誤資訊(error函數永遠都不會傳回)

通常情況下,error會附加一些錯誤位置的資訊到message頭部。

Level參數訓示獲得錯誤的位置:

  • Level=1[預設]:為調用error位置(檔案+行号)
  • Level=2:指出哪個調用error的函數的函數
  • Level=0:不添加錯誤位置資訊

pcall(protected call)

pcall(函數 , 要傳遞給後者的參數),有錯誤、無錯誤;傳回值true或者或false, errorinfo。

文法格式如下

if pcall(function_name, ….) then
-- 沒有錯誤
else
-- 一些錯誤
end
           

Lua 調試(Debug)

Lua 垃圾回收

Lua 采用了自動記憶體管理。 這意味着你不用操心新建立的對象需要的記憶體如何配置設定出來, 也不用考慮在對象不再被使用後怎樣釋放它們所占用的記憶體。

1.   垃圾收集器間歇率控制着收集器需要在開啟新的循環前要等待多久。 增大這個值會減少收集器的積極性.

2.   垃圾收集器步進倍率控制着收集器運作速度相對于記憶體配置設定速度的倍率。 增大這個值不僅會讓收集器更加積極,還會增加每個增量步驟的長度。 不要把這個值設得小于 100 , 那樣的話收集器就工作的太慢了以至于永遠都幹不完一個循環。 預設值是 200 ,這表示收集器以記憶體配置設定的"兩倍"速工作。

Lua 面向對象

Lua 資料庫通路

301 LuaInterface 學習

什麼是LuaInterface : 包含LuaInterface.dll和Luanet.dll .通過此完成c#和Lua的調用

Program p = new Program();
            //注冊普通方法
            lua.RegisterFunction("LuaMethod",p,p.GetType().GetMethod("CLRMethod"));  //參數1 注冊進lua後的函數名字  
            //注冊靜态方法
            lua.RegisterFunction("CLRStaticMethod", null, typeof(Program).GetMethod("CLRStaticMethod"));
            lua.DoString("CLRStaticMethod");
        }
        public void CLRMethod()
        {
            Console.WriteLine("wangyanjie");
        }

        public static void CLRStaticMethod()
        {
            Console.WriteLine("wangyanjie");
        }
           

在Lua中使用c#中的類:

//lesson 1
            //生成lua代碼
            //lua.DoString("num = 2");
            //lua.DoString("str=' a string '");
            //object[] values = lua.DoString(" return num,str ");
            //foreach (object obj in values)
            //{
            //    Console.WriteLine(obj);
            //}
            //lesson 2
            //執行myLua.lua腳本程式
            //myLua.lua 檔案用文本檔案編寫的話,則一定要使用ANSI格式編碼來儲存
            //lua.DoFile("myLua.lua"); 

            //lesson 3
            把c#注冊進Lua的一個全局方法
            //Program p = new Program();
            注冊普通方法  參數1 注冊進lua後的函數名字  
            //lua.RegisterFunction("LuaMethod", p, p.GetType().GetMethod("CLRMethod"));  
            注冊靜态方法
            //lua.RegisterFunction("CLRStaticMethod", null, typeof(Program).GetMethod   ("CLRStaticMethod"));
            調用注冊進Lua的方法
            //lua.DoString("LuaMethod()");
            //lua.DoString("CLRStaticMethod()");
           

在Lua中使用c#的dll和類

require "luanet"

luanet.load_assembly("System")   --已經把c#dll 引入進來了   luanet.dll一般是在lua中通路c#的,在c#過程中運作

luanet.load_assembly("LuaInterface_Study")   --加載dll庫

Int32 =  luanet.import_type("System.Int32")
--加載lua中的類,先加載命名空間
Program = luanet.import_type("LuaInterface_Study.Program")

num = Int32.Parse("3435")
print(num)

program1 = Program()
print( program1.name)
program1:TestMethod()  --調用方法

--void,strLength = program1:TestOut("taikr.com")
--print(void,strLength)

--void,count=program1:TestRef("www.taikr.com",10)

--print(void,count)

----------------------------------


c#
         //lesson 4   lua中使用c#中的類
            //lua中把c#dll 引入進來,并且執行c#dll中的方法  ,在c#過程中啟動,此時lua中就調用了c#中的方法
            lua.DoFile("script.lua");
           

17  在Lua中通路c#中的方法-特殊情況

public void TestOut(string name, out int count)
        {
            Console.WriteLine("c# : "+name);
            count = name.Length;
        }

        public void TestRef(string name, ref int count)
        {
            Console.WriteLine(name);
            Console.WriteLine(count);
            count = name.Length;
        }

--------------------------------------------------


--out  ref 的情況,有重載時先比對第一個函數
-- 在Lua中通路c#中的方法-特殊情況,當函數中有out ref,out和ref參數和函數的傳回值一起傳回,
--并且調用的時候,out參數不需要傳入。

void,strLength = program1:TestOut("taikr.com")  --傳回值第一個是null的,是以需要void來接受。第二個是out參數
print(void,strLength)

void,count=program1:TestRef("www.taikr.com",10)  --ref參數需要把值傳進來
print(void,count)
           

AssetBundle:

ManifestFileVersion: 0
CRC: 324281795      //檢驗碼
Hashes:
  AssetFileHash:
    serializedVersion: 2
    Hash: 75b1e3fba0dd26fabf8c61cb4647de4d
  TypeTreeHash:
    serializedVersion: 2
    Hash: 8fe15831e4ad8c37d6024ec822931f85
HashAppended: 0
ClassTypes:         //依賴的類
- Class: 1
  Script: {instanceID: 0}
- Class: 4
  Script: {instanceID: 0}
- Class: 21
  Script: {instanceID: 0}
- Class: 23
  Script: {instanceID: 0}
- Class: 33
  Script: {instanceID: 0}
- Class: 43
  Script: {instanceID: 0}
- Class: 48
  Script: {instanceID: 0}
- Class: 65
  Script: {instanceID: 0}
- Class: 114
  Script: {fileID: 11500000, guid: ab5eac1d15cfc104a96e6828a0ebe9f1, type: 3}
- Class: 115
  Script: {instanceID: 0}
Assets:
- Assets/Cube.prefab      //打包的資源
Dependencies:
- Assetbundle/cube1       //以來的資源【引用了另一個資源的情況】
           
string url= "file://E:/NewSystemProject/Lua/MyLua/Assetbundle/Cube";
    string assetsName= "Cube";   //

    private IEnumerator Start()
    {
        using (WWW www = new WWW(url))
        {
            yield return www;
            if (www.error != null)
            {
                Debug.Log("下載下傳出錯");
            }
            else
            {
                AssetBundle bundle = www.assetBundle;
                //此處是unity中被打包的資源名字,不是打包出的
                Object obj = bundle.LoadAsset(assetsName);  
                Instantiate(obj);
                //解除安裝資源
                bundle.Unload(false);
                //dispose()   因為在using()中,是以不需要
            }
        }
    }
           

30    UI的制作,自己打一個包,用Lua代碼加載

按住alt,在錨點界面選擇和父類大小保持一緻。

打包時,字尾要是GO.assetbundle  ,因為代碼中預設是以這個字尾來命名的。

因為,我的UI面闆用了sprite圖檔。是以要把所有的UI圖檔打包。【圖檔得考慮分包,不然用到一張圖檔,就得把是以不用的都解壓掉】

build後,把資源打包進StreamingAssets中。此處可以查找各個包得依賴。檢視打包後的資源已經在files檔案中進行管理了。

--return 所有加載得view對應得lua腳本

--根據c#得代碼執行流程,寫lua代碼

--啟動lua程式時,直接啟動lua可執行檔案就可以打開lua代碼

--如果在手機端熱更新則需要設定伺服器ip,把SuperSocket.SocketService.exe啟動

--用戶端則需要ip和DebugMode  UpdateMode   WebUrl 重新設定下,更新時把代碼記得關了

                                                    Lua 程式設計:

Chunk: 

dofile 在調試或者測試 Lua 代碼時是很友善的.可以測一下,重載指定的lua檔案,是否可行????

dofile("testLua2.lua")
local d=Add(1,2)
print(d)
           

第二章 類型和值

Number

local n = a or 0   

lua math.floor  因為這個函數是向下取整,是以lua通過這個函數來實作四舍五入:

lua 中的math.floor函數是向下取整函數。
  math.floor(5.123)  -- 5
  math.floor(5.523)   -- 5
用此特性實作四舍五入
  math.floor(5.123 + 0.5)  -- 5
  math.floor(5.523 + 0.5)  -- 6
           

String: 

local a=10 .. 20

   ..在 Lua 中是字元串連接配接符,當在一個數字後面寫..時,必須加上空格以防止被解釋 錯

盡管字元串和數字可以自動轉換,但兩者是不同的,像 10 == "10"這樣的比較永遠 都是錯的。

如果轉成數字可以使用需要顯式将 string 函數 tonumber()   [tostring],如果 string 不是正 确的數字該函數将傳回 nil。

為了避免不一緻的結果,混合比較數字和字元串,Lua 會報錯,比如:2 < "15".  "2"<"15" 則是按照字母順序比較。 2<1 比較,fasle. 

and 和 or 的運算結果不是 true 和 false,而是和它的兩個操作數相關。

************************  注意注意
a and b -- 如果 a 為 false,則傳回 a,否則傳回 b
a or b -- 如果 a 為 true,則傳回 a,否則傳回 b。 
i = i or 1  i沒有初始化過,在把i初始化為1
           

userdata :

Lua裡的三元運算符:

a ? b : c  <==>    (a and b) or c

表的構造

lua裡不推薦數組下标從 0 開始,否則很多标準庫不能使用。

第4章   基本文法

1.多值指派 : 一般用于值得交換 或 函數的傳回值。

<1. 因為lua支援多個變量的同時指派,是以如果需要交換兩個數,則可以直接使用指派來完成交換。

<2. lua和其他語言不同。如果對多個變量指派,則必須是依次指派。a,b,c=0  這種在lua是錯誤的。

2.lua使用習慣: 避免命名沖突,通路比較快。

3.for

<1. 數值for循環。

for var=exp1,exp2,exp3 do

<2. 泛型for循環。

for i,v in ipairs(a) do print(v) end

  周遊表k的例子:for k in pairs(t) do print(k) end

第4章   基本文法

1. lua函數文法:如果函數隻有一個參數,并且這個參數是字元串或者表構造的時

候, ()可以省略 。

print "Hello World" <--> print("Hello World") 
dofile 'a.lua' <--> dofile ('a.lua') 
print [[ddddd]]

function fun(par)
  print "run fun"
end
local b={1,2,3}
fun {1,2,3}
fun(b)
           

2. Lua 也提供了面向對象方式調用函數的文法,比如 o:foo(x)與 o.foo(o, x)是。

3. 可以使用()來把函數包起來,強制函數傳回一個參數.

   一個 return 語句如果使用圓括号将傳回值括起來也将導緻傳回一個值。

function foo2 () return 'a','b' end
print((foo2()))   --  a
           

4. 函數多值傳回的特殊函數 unpack

接受一個數組作為函數的輸入參數,傳回數組的所有元 素。unpack 被用來實作範型調用機制。 在 Lua 中如果你想調用可變參數的可變函數隻需要這樣:

f = string.find  --string.find (str, substr, [init, [end]])
                 --在一個指定的目标字元串中搜尋指定的内容(第三個參數為索引), 
                 --傳回其具體位置。不存在則傳回 nil。
a = {"hello", "ll"}
print(f(unpack(a))) --> 3 4 為ll的索引
           

預定義的 unpack 函數是用 C 語言實作的,我們也可以用 Lua 來完成:  

function unpack(t, i)
  i = i or 1
  if t[i] then
    return t[i], unpack(t, i + 1)
  end
end
           

5.2 可變參數

5.3 命名參數

用名字指定函數參數。lua将參數放在一個表中,把表作為函數的唯一參數傳遞。

當函數的參數很多的時候,這種函數參數的傳遞方式很友善的

tab= {old="temp.lua", new="temp1.lua"}
function fun(arg)
	print(arg.old)
	print(arg.new)
end
fun(tab)
           

第6章  再論函數

lua