前兩天做了遊戲(unity專案)中新手引導配置檔案檢查的功能,配置寫在lua指令碼中,詢問專案中的前輩後,呼叫了統一的介面載入遊戲中所有lua檔案,獲取到luatable,對其中按鈕路徑進行了檢查,主要目的是防止prefab更新後未更新配置檔案,這會導致新手引導中對應的按鈕找不到。反覆除錯檢查後,自信的提交了任務,主程來驗收後表示錯漏百出,**格式沒遵守規範,迴圈中重複載入資源,反覆呼叫得到相同結果的函式……
**風格每個人習慣不一樣沒有好壞之分就忽略他了,其他通用的記下來自省,也希望能對大家有幫助。
先上優化前**
hashtable readluatableashash()
bool checksingle(string wnd, string btn)
void main()}}
}
**執行起來是完全正確的,程式老鳥和細心的朋友應該已經發現**不對了,「」只是過載了方法,不管資料結構如何優化都是需要耗費效能的,需要重複使用的資料,只獲取一次到變數中,於是做了如下修改。
void main()
string strinterwndname = objinterwndname.tostring();
string strinterbtnpath = objinterbtnpath.tostring();
if (!checksingle(strinterwndname, strinterbtnpath))}}
}
其實這個問題很基礎,偶爾會忘記,但卻是**中常用到的,用得多了對效能影響自然也就大了。
呼叫統一介面載入lua檔案的時間有些長,而且對於檢查配置這一功能來說,這樣的操作有些浪費,所以新的需求是用讀文字的形式讀取lua檔案。
小科普
所有檔案本質上都是二進位制檔案,一堆0和1,檔案本身並沒有意義,關鍵看如何解讀。
於是把lua檔案當做純文本來解析,要解決的問題主要有兩個:
1.去除備註以及文字中luatable以外的元素
2.將luatable解析出來
這其中肯定要識別關鍵字,例如
public
static hashtable readluatable(string content)
else
}if (tempstr.replace(" ", "").replace("\t", "") == "")
#endregion
#region 檢查是否為函式,忽略他
if (tempstr.contains("function"))
else
if (tempstr.contains("end"))
}if (isfunction)
#endregion
content[i] = tempstr;
}strfinal = string.join("", content);
dicmatchlength = new hashtable();
#if log_parse_time
long elapsed = system.datetime.now.ticks - currenttime;
debug.log("預處理lua檔案消耗時長 : " + elapsed);
currenttime = system.datetime.now.ticks;
#endif
table = readluatable(strfinal.replace("\\\\", "\\"), 0) as hashtable;
#if log_parse_time
elapsed = system.datetime.now.ticks - currenttime;
debug.log("解析lua檔案消耗時長 : " + elapsed);
#endif
return table;
}
我一開始的做法顯得比較笨拙,首先讀取檔案,採用了file.readalllines()來讀取檔案,這裡會把二進位制檔案逐行讀成string,對每行string查詢關鍵字,以檢測是否為注釋或函式,這些地方會影響到之後解析luatable。解析luatable需要逐字解析,所以最後我用string.join()將陣列重新變為單個string,不難察覺,生成這麼多臨時的string並不合適,這將會占用儲存空間,且效率不高。
同時有幾個小技巧,可以進一步優化**。
1.string.indexof()與string.contains()這個函式能夠達到相同效果,當string.indexof(『,』)得到的值小於0時則當前string不存在』,』。
2.content.replace();content.substring();等函式將會生成臨時string以返回結果,盡量少用。
嗯,這幾點我當然本來也沒注意,又是主程一秒點破,於是之後重構了**。
public
static hashtable readluatable2(system.io.streamreader file)
else
if (indexofcomment == 0)
bool bemptyline = true;
for (int j = nlinestartat, jmax = nlinestartat + nsubstringlength; j < jmax; j++)
}if (bemptyline)
}#endregion
#region 檢查是否為函式,忽略他
if (!isfunction)
}else
}if (isfunction)
#endregion
}#if log_parse_time
long elapsed = system.datetime.now.ticks - currenttime;
debug.log("預處理lua檔案消耗時長 : " + elapsed);
#endif
string strfinalfinal = strfinal.tostring().replace("\\\\", "\\");
dicmatchlength = new hashtable();
#if log_parse_time
currenttime = system.datetime.now.ticks;
#endif
table = readluatable(strfinalfinal, 0) as hashtable;
#if log_parse_time
elapsed = system.datetime.now.ticks - currenttime;
debug.log("解析lua檔案消耗時長 : " + elapsed);
#endif
return table;
}
前後對比了時間,後者更穩定且一直略快於前者,第一次快20ms,多執行幾次後,前者時間越來越接近後者,應該是unity內部對string的操作進行了什麼神秘的優化,但總體來說,後者策略是要優於前者的,當然也視各位的具體情況而定。
動態載入資源,無論是遊戲本身還是類似我在寫的檢查工具都經常用到。
unityeditor.assetdatabase.loadassetatpath(path);
gameobject getassets(string path)
else
}
封裝這麼乙個方法就可以在第一次檢查之後省下載入資源的時間。
好的不喜歡說自己是萌新的萌新分享結束了,有錯誤的地方大家糾正,想要討論問題也歡迎發郵件到[email protected],之前放qq號上去發現這樣qq會加了許多平時不聯絡的人,還是郵箱來得舒服,哈哈。
c語言字串相關
在c語言中,有兩個函式可以在控制台 顯示器 上輸出字串,分別是 在c語言中,有兩個函式可以讓使用者從鍵盤上輸入字串,它們分別是 但是,scanf 和 gets 是有區別的 strcat 是 string catenate 的縮寫,意思是把兩個字串拼接在一起,語法格式為 strcat arraynam...
mysql解析json字串相關問題
很多時候,我們需要在sql裡面直接解析json字串。這裡針對mysql5.7版本的分水嶺進行區分。1.對於mysql5.7以上版本 使用mysql的內建函式json extract column,key 這個函式有兩個引數,第乙個引數column代表json列的列名 第二個引數key代表json字串...
字串相關 C 字串輸出格式
近段時間在做專案時用到了字串輸出格式方面的內容,今天來整理一下,算是筆記吧,如果能幫到部分我也是很開心噠。1 大部分開發者會選用加號鍵組合字串並輸出 string str hello string name jerry string result str name 輸出結果 2 我們還可以選用格式化...