青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

戰(zhàn)魂小筑

討論群:309800774 知乎關(guān)注:http://zhihu.com/people/sunicdavy 開源項目:https://github.com/davyxu

   :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  257 隨筆 :: 0 文章 :: 506 評論 :: 0 Trackbacks

2018年11月30日 #

近期在游戲demo中試驗ECS, 深入研究Unity官方的ECS框架和第三方Entitas框架, 分享下使用ECS的心得。


Unity在2018版中加入了ECS系統(tǒng), 但處于小白鼠階段。默認(rèn)不是Unity的一部分, 需要手動下載代碼并導(dǎo)入Packages(新特性)。官方提供海豚例子, 但除此之外例子和資料非常少。所以完全無法,也不敢在demo中貿(mào)然引入這種系統(tǒng),所以放棄官方ECS系統(tǒng)。


第三方的Entitas(https://github.com/sschmid/Entitas-CSharp)ECS框架從2015年就開始在各地演講中介紹。整體框架基于代碼生成, 能解決一部分的代碼爆炸問題, 而且性能也要好一些。例子,介紹非常豐富,例子雖然基于不同版本的Entitas,特性支持和最新版差不太多, 只是寫法有細(xì)微差異, 對于理解來說無礙。


經(jīng)過1~2天的改造, 終于將demo從傳統(tǒng)Unity寫法改造為ECS標(biāo)準(zhǔn)寫法,新增了46個文件, 而傳統(tǒng)邏輯一共只有16個文件,大概對比下ECS的特點和差異。


Entitas的ECS系統(tǒng)

1. 本來在一個對象中添加一個類字段的過程,ECS需要添加一個類代表Component,并且代碼生成。

這個字段一般用于描述對象的資源,處理顯示的GameObject, 表示對象的類型等。


2. 本來一個對象的業(yè)務(wù)邏輯處理過程直接用方法解決的, ECS需要新加一個System,而操作對象需要使用Filter或Group查詢獲得。


3. 一系列的操作, 需要拆分為多個System和Component拆分處理。如果System順序不對, 會造成一些詭異的bug。


4. Component不僅僅是Model承載體, 也可以是參數(shù)的數(shù)據(jù)結(jié)構(gòu)。參數(shù)Component通過Entity傳遞到System處理。 例如: 通過ECS創(chuàng)建一個方塊的過程,使用CreateTileComponent,包含創(chuàng)建Tile的位置, 創(chuàng)建Entity并添加CreateTileComponent, 在CreateTileSystem中處理就創(chuàng)建了Tile,處理完成時, 需要將傳入的Entity.Destroy掉。


6. Entity上修改Component的過程, 會觸發(fā)事件。修改的過程需要使用RelaceXXX,XXX表示組件名。組件可以頻繁修改, 不用擔(dān)心添加和刪除組件過程的性能, Entitas底層處理性能只相當(dāng)于指針賦值的性能。


ECS像什么?

1. ECS中的System類似觸發(fā)器系統(tǒng)(Event-Condition-Action),其中,Event對應(yīng)Entitas的GetTrigger+Collector,表示觸發(fā)事件。Condition對應(yīng)Filter表示在事件來源對象中找到需要的對象。 Action對應(yīng)Execute,表示實際的操作。

2. ECS中的Component類似不用lua擴(kuò)展的Redis或者不用存儲過程的MySQL, 純粹純數(shù)據(jù), 而不能對數(shù)據(jù)有任何封裝操作。沒有l(wèi)ua和存儲過程支持的db寫起來還是比較費勁的,但ECS就是那么的純。


3. ECS中的Entity很尷尬,因為Component是按類別連續(xù)存儲的以保證性能。 邏輯又需要Entity組合成邏輯需要的復(fù)合對象。 兩邊都要照顧,所以這種設(shè)計就讓代碼量巨增,可讀性下降。



ECS企圖用一套框架滅掉設(shè)計模式

1. 單件(Singleton)在Entitas用Unique標(biāo)簽標(biāo)記Component, 在Context中就是唯一的, 其實也就是Singleton。


2. ECS干掉了傳統(tǒng)的工廠模式,底層統(tǒng)一對對象(Entity)和屬性(Component)統(tǒng)一管理。需要按Component中的值找回Entity時, 可以使用EntityIndex。


3. Entity攜帶不同的組件時,整個創(chuàng)建和銷毀過程被記錄并恢復(fù),其實就是Command模式


ECS適合做UI框架(類似MVVM,MVC,MVP)么?

ECS不是專用的UI框架,但是可以對不同系統(tǒng)和數(shù)據(jù)間解耦。傳統(tǒng)代碼中數(shù)據(jù)修改后的Callback,ECS也可以用Listener做, 但Listener因為能保存數(shù)據(jù), 就需要用Component保存。 所以你需要面對的是,一個Button,響應(yīng)創(chuàng)建一個參數(shù)用的Component和System,還要為數(shù)據(jù)改變寫一套ListenComponent和Listener處理的System,酸爽吧?


Minecraft適合ECS來做么?

可以,性能應(yīng)該能提升不少,但是代碼會更繁瑣,特別像Java這種啰嗦語言配上ECS這種啰嗦框架,估計代碼量翻翻還是很輕松的。MC屬于特殊類型的游戲,適合特殊領(lǐng)域特別優(yōu)化,也就是專門為方塊做出特別的設(shè)計來做優(yōu)化。ECS屬于通用框架,即便性能OK,但是代碼未必能有良好的可讀性。


體量小的游戲適合用ECS來做么?

可以,但不建議。特別是只有幾個人維護(hù)的工程,貿(mào)然上ECS系統(tǒng),會讓系統(tǒng)變的極為復(fù)雜。當(dāng)然你會說,如果開發(fā)到后期,傳統(tǒng)開發(fā)模式會導(dǎo)致代碼會亂,ECS會好些吧。掌握ECS也不是一天兩天的事情,不熟悉ECS的程序員設(shè)計出來的系統(tǒng)獲得的優(yōu)勢可能還不如用傳統(tǒng)設(shè)計方法好呢。

架構(gòu)解決的是人的問題, 人都有問題,用什么框架都沒辦法。


到底什么項目適合用ECS?

1. 大量的小個體不斷的生成和銷毀以及顯示,例如: 攻城戰(zhàn)中,要體現(xiàn)每個角色的移動,戰(zhàn)斗。

2. 多于5個人編寫核心戰(zhàn)斗邏輯。互相協(xié)作和模塊切分,需要一個大家都能信服的框架,ECS可以選擇。


P.S.

不要造ECS的輪子!

很多同學(xué)看了ECS基本原理,在沒有深入使用過任何ECS系統(tǒng)時馬上操刀造輪子。ECS系統(tǒng)確實看起來簡單。實際造下來你會發(fā)現(xiàn),性能非常糟糕以及不知道一些邏輯如何用ECS來解決。


總結(jié):

1. ECS確實為性能而生,沒有并發(fā)加持性能的ECS都是耍流氓,要快就要快到極致。

2. Unity中,ECS并發(fā)能擴(kuò)展CPU的利用率,但是GPU的性能依然還是DrawCall優(yōu)化那一套,別期望ECS會顛覆Unity,性能也不會快到飛起,關(guān)鍵還是要看具體的項目和人。

3. ECS是萬能框架,但不全能。傳統(tǒng)架構(gòu)和設(shè)計思想也不是一無是處,熟啥用啥,怎么快怎么來!

無恥的廣告鏈接,請各位支持

《Go語言從入門到進(jìn)階實戰(zhàn)(視頻教學(xué)版)》(徐波)【摘要 書評 試讀】- 京東圖書

posted @ 2018-11-30 18:01 戰(zhàn)魂小筑 閱讀(3324) | 評論 (0)編輯 收藏

2018年8月29日 #

為了編寫基于cellnet的新一代游戲服務(wù)器框架,最近深入研究微服務(wù),ServiceMesh等概念。研究過程中對Web和游戲兩種服務(wù)器架構(gòu)設(shè)計有一些心得,編寫并記錄下來。(下文中,Game表示游戲服務(wù)器,Web表示W(wǎng)eb服務(wù)器) ``
狀態(tài)緩存
所謂狀態(tài)緩存,就是在內(nèi)存而非專業(yè)數(shù)據(jù)緩存服務(wù)器(如redis)中保存和處理邏輯數(shù)據(jù),手動編寫此過程較為繁瑣但是效率較高,但隨著狀態(tài)邏輯復(fù)雜性和并發(fā)、擴(kuò)容問題提出,狀態(tài)同步會變得越來越復(fù)雜。
Game:
強(qiáng)交互性的服務(wù)器類型需要在服務(wù)器做緩存,邏輯編寫也較為容易,無需處理事務(wù)并發(fā)問題。例如:組隊,匹配,戰(zhàn)斗邏輯。服務(wù)器不能隨意重啟。
弱交互性的服務(wù)器類型可配合redis做成無狀態(tài)服務(wù)器,例如:養(yǎng)成,技能升級,領(lǐng)取物品等。服務(wù)器隨時支持重啟。
游戲服務(wù)器為了提高性能,早期所有服務(wù)器都是使用狀態(tài)緩存寫法編寫,特別是MMORPG這類強(qiáng)交互的游戲服務(wù)器尤為嚴(yán)重。
Web:
均為無狀態(tài)服務(wù)器,弱交互。使用事務(wù)方式處理并發(fā)邏輯,例如:交易,下單等。
推送,單獨發(fā)送
這里提到的所謂推送,單獨發(fā)送是與RPC區(qū)別的通訊方法。RPC要求請求必須有回應(yīng)。而推送單獨發(fā)送則更像是通知和廣播,無需目的方返回任何消息。
Game:
找到服務(wù)器的Session,直接Send
通過中轉(zhuǎn)服務(wù)器,或稱為中心服務(wù)器進(jìn)行注冊/廣播
客戶端的model數(shù)據(jù)需要更新時,服務(wù)器會主動推送消息。
游戲服務(wù)器沒有嚴(yán)格的RPC設(shè)計需求,推送和單獨發(fā)送較Web服務(wù)器更多。而且游戲服務(wù)器多使用長連接,所以主動推送也比Web服務(wù)器來的方便一些。
Web:
將推送做成專有的服務(wù),并做排隊和并發(fā)處理。
可用性
聽說過游戲停服更新,支付寶服務(wù)器在刷二維碼時停服了可一定被罵慘吧。Web對服務(wù)器高可用性要求很高,游戲雖然也注重服務(wù)器穩(wěn)定性和可用性,但是由于版本迭代更新頻繁,停服更新反而能獲得玩家接受。
Game:
游戲?qū)捎眯砸蟛桓摺?/span>
游戲大版本更新時需要停服更新。支持熱更新技術(shù)的服務(wù)器(例如Erlang,Skynet)僅使用熱更新修復(fù)bug,很少直接更新新版本。
不是所有的游戲服務(wù)器支持動態(tài)添加服務(wù)器。
Web:
極高的可用性,服務(wù)不允許停服更新,使用藍(lán)綠及灰度方式更新服務(wù)器。
隨時可以橫向擴(kuò)展服務(wù)器,提高服務(wù)器容量和承載。
連接及傳輸
均使用TCP傳輸協(xié)議,游戲服務(wù)器注重性能,自有協(xié)議及二進(jìn)制協(xié)議使用較多。
Web注重兼容和接口友好,使用JSON格式較多。
Game:
使用長連接,需要從邏輯層維護(hù)連接狀態(tài)及處理服務(wù)器不在線情況
使用自有封包格式,大部分使用protobuf或二進(jìn)制流格式。
Web:
微服務(wù)大部分使用短連接,grpc支持http2長連接
使用json編碼方便調(diào)試和版本兼容。
流量限制
人數(shù)多了,任何服務(wù)器都扛不住,流量限制和登入限制能有效保護(hù)服務(wù)器穩(wěn)定。
Game:
單服有人數(shù)限制,可以通過GM后臺設(shè)置擋墻,超過無法進(jìn)入
Web:
限流器中間件,可以精確到服務(wù)控制流量
斷流,防止雪崩
Game:
游戲沒有,也不需要這種概念,游戲請求不會突然升高,即便有,也通過GM后臺人為控制
Web:
斷流器中間件
服務(wù)發(fā)現(xiàn)
如何找到服務(wù)器地址。
服務(wù)有變化時,通過Watch系統(tǒng)通知訂閱者更新本地緩存
服務(wù)器沒有變化時,使用本地緩存找到服務(wù)地址
Game:
游戲服務(wù)器互相依賴復(fù)用只在很小的范圍內(nèi),因此無需在不同語言不同進(jìn)程服務(wù)間獲得地址,大部分在配置文件中填寫各服務(wù)的IP及地址即可互相訪問。
早期游戲自己編寫服務(wù)器狀態(tài)及地址發(fā)現(xiàn)服務(wù)。
有用redis做服務(wù)發(fā)現(xiàn)
Web:
使用服務(wù)發(fā)現(xiàn)系統(tǒng),分布式部署。無需依賴配置文件
網(wǎng)關(guān)需求
Game:
網(wǎng)關(guān)處理客戶端上下線通知,心跳,維持連接,轉(zhuǎn)發(fā),廣播上下行封包
Web:
根據(jù)請求地址路由,無上下線概念,無心跳。廣播通過消息推送系統(tǒng)完成
由于筆者從事游戲行業(yè),對Web服務(wù)器概念在逐漸熟悉中,若有錯誤和不足請各位大佬指出。
本人新書《Go語言從入門到進(jìn)階實戰(zhàn)》,生動的語言,例子帶有各種彩蛋,輕松了解Go語言特性,更有cellnet框架剖析解密
https://search.jd.com/Search?keyword=go%E8%AF%AD%E8%A8%80%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E8%BF%9B%E9%98%B6%E5%AE%9E%E6%88%98&enc=utf-8&suggest=1.def.0.V02&wq=Go%E8%AF%AD%E8%A8%80%E4%BB%8E&pvid=145d55a92cab4b07b71326f8beb1700b
posted @ 2018-08-29 11:16 戰(zhàn)魂小筑 閱讀(2726) | 評論 (0)編輯 收藏

2017年12月19日 #

嵌套git庫的管理
使用git作為源代碼管理時,經(jīng)常需要在一個git代碼庫中從外網(wǎng)獲取新的git庫,也就是在git庫下嵌套另外一個git庫。而同時維護(hù)兩個git庫的過程就變的非常復(fù)雜。
submodule的弊端
常見的做法是使用git 提供的submodule功能。但submodule的管理嵌套git庫的結(jié)果往往不是我們期望的結(jié)果。假設(shè)有一個git庫叫project,在project的某個子目錄下還包含一個叫3rd的目錄,是另外一個git庫。
D:.
└─project
└─3rd
mytext.txt
假設(shè)甲和乙都取了project的代碼,由于時間差異,甲通過submodule取到V1版,而乙取到了V2版本。甲乙同時在不同的3rd庫下進(jìn)行開發(fā),勢必會造成不同的運行結(jié)果。也許你認(rèn)為可以在獲取submodule時指定版本,但這個獲取過程很難控制。
一般說來,第三方庫應(yīng)由主程序進(jìn)行更新及維護(hù),一般情況下,項目沒有特殊需求時,不會隨便更新第三方庫到最新版本,因此submodule更新嵌套的git庫并不是理想的解決方案。
嵌套git庫的修改可見性
前面的例子中,project git庫下的3rd的git庫中如果有文件發(fā)生修改,此時在project目錄下,使用sourceTree等git管理工具無法識別3rd下的文件修改。
也就是說,無法將3rd下的修改提交到project的git庫中。
終極解決方案
此時,將3rd目錄下的.git目錄暫時移出project和3rd目錄,此時,在project目錄用sourceTree查看時,將可以看到3rd下的文件修改,提交修改到project庫中。再將剛移出去的3rd的.git目錄移回3rd目錄下,在3rd目錄下使用git status,將可看到3rd目錄的修改,提交時,會將修改提交到3rd目錄。
posted @ 2017-12-19 22:04 戰(zhàn)魂小筑 閱讀(3565) | 評論 (0)編輯 收藏

2017年11月27日 #

越來越多的人選擇用Mac或者Linux環(huán)境進(jìn)行跨平臺項目開發(fā)。但是仍然有大部分人習(xí)慣于在Windows環(huán)境下進(jìn)行開發(fā),畢竟Windows在各方面使用還是較為方便,特別像文件版本管理(Git,SVN等)

在跨平臺下開發(fā)游戲或軟件,就需要有一套方便的自動化工具。Windows下需要使用批處理,雖然有PowerShell加持,但這東西學(xué)了也不靠譜,只有一個平臺能用。大家還是習(xí)慣Linux Shell。連Mac平臺都可以用Shell,Windows上要做自動化腳本就顯得非常尷尬。

我曾經(jīng)在項目中使用go編寫了一套將配置轉(zhuǎn)為批處理和Linux Shell的工具。使用過程較為復(fù)雜,但是能跨平臺進(jìn)行表格導(dǎo)出和協(xié)議編譯等工作。

但是,這個工具還是需要對不同的平臺編寫多套模板進(jìn)行代碼生成,非常繁瑣。如果有一套跨平臺的Shell,編寫一次就可以跨平臺運行那該多好。

查閱資料后,一共有幾個方案:

  1. 使用Python作為自動化工具 這個方案其實就是使用python把批處理和Shell干的事情用代碼來解決。但前提是要重新學(xué)習(xí)Python,也需要一部分熟悉簡單的Python語法,人為學(xué)習(xí)成本較高,也比較費事。

  2. 自己編寫一套獨立的自動化工具 這個方案需要長時間的適配過程,差什么指令補(bǔ)什么指令,對項目進(jìn)度有一定干擾。

  3. 自己編寫Linux Shell的解釋器 這個就更難了,要做到100%兼容,基本不可能。

  1. 使用Cygwin和Mingw 需要一個微型運行時進(jìn)行Linux Shell的解釋,msys大概是18M左右,可行性較高。

在研究Cygwin和Mingw如何整合的過程中,我誤操作點擊了一個sh后綴的Linux Shell,這是我希望讓Mingw運行的Shell。結(jié)果呢,sh后綴的文件居然能在Windows下運行。我馬上編寫了一系列的例子,發(fā)現(xiàn)幾乎完全兼容常用的Shell指令。 經(jīng)過研究,我發(fā)現(xiàn)Windows下能運行sh文件是由Git自帶的msys2提供的。MSYS2 (Minimal SYStem 2, http://www.msys2.org/) 是一個MSYS的獨立改寫版本,主要用于 shell 命令行開發(fā)環(huán)境。同時它也是一個在Cygwin (POSIX 兼容性層) 和 MinGW-w64(從"MinGW-生成")基礎(chǔ)上產(chǎn)生的,追求更好的互操作性的 Windows 軟件。

那就是說,只要安裝了Git(https://git-scm.com/),那么就可以在Windows下直接運行Linux Shell,只需要將文件后綴命名為sh即可

問過周邊友人是否知道這一功能,都說知道,只是沒有廣播而已,害我研究很久……

posted @ 2017-11-27 15:15 戰(zhàn)魂小筑 閱讀(5445) | 評論 (3)編輯 收藏

2017年7月6日 #

本文主要研究游戲服務(wù)器帶狀態(tài)的熱更新需求 http的無狀態(tài)熱更新需求已經(jīng)有成熟方案, 故不在本文描述范圍

基本概念

  • Golang的熱更新采用什么機(jī)制?

    使用go1.8提供的plugin包機(jī)制實現(xiàn)

  • plugin包本身設(shè)計的目的是熱更新么?

    plugin包其實只是支持將代碼分別編譯為多個動態(tài)庫,動態(tài)加載后運行 并不能完全支持類似C/C++的動態(tài)庫方式處理代碼

  • 帶狀態(tài)的進(jìn)程熱更新的基本概念及范圍是什么?

    數(shù)據(jù)部分(model)不更新, 只更新邏輯部分(函數(shù))

  • 表格和配置更新算熱更新么?

    算, 但不是本文描述范圍

  • 熱更新能在windows上使用么?

    不支持

代碼及結(jié)構(gòu)

  • 我能將原來一個exe的代碼編譯為so提供給plugin使用么?

    可以, 但是必須仍然保留main包作為插件入口, 并在main包內(nèi)添加提供給plugin調(diào)用入口.

  • 如果動態(tài)庫中沒有main包, 編譯出的so能用么?

    不能, 包必須包含main, 否則輸出的是.a的文件, plugin包加載會報錯

  • 動態(tài)庫中, 非main包的的代碼修改能做熱更新么?

    不能!(崩潰了吧, 我提了一個issue: https://github.com/golang/go/issues/20554)

    如果確實做了修改, 底層會報錯: plugin was built with a different version of package

    解決方法: 修改plugin包底層實現(xiàn)并重新編譯 打開runtime/plugin.go, 注釋以下代碼 for _, pkghash := range md.pkghashes { if pkghash.linktimehash != *pkghash.runtimehash { return "", nil, pkghash.modulename } } 執(zhí)行/usr/local/go/run.bash 重編譯+測試

  • 代碼中哪些可以被更新? 方法可以被更新么? 閉包呢?

    只能更新?lián)碛徐o態(tài)地址的結(jié)構(gòu).例如: 包級別函數(shù)(類似于靜態(tài)函數(shù))

    例如: svc_0.so里有一個Foo函數(shù), svc_1.so修改了Foo函數(shù)實現(xiàn), 熱更新可實現(xiàn)

    閉包=函數(shù)+捕獲變量, 實際上是一個動態(tài)結(jié)構(gòu), 沒有靜態(tài)地址, 無法被更新

    各種包級別變量, 結(jié)構(gòu)體變量, 結(jié)構(gòu)體方法, 局部變量均不能被熱更新, 但是變量值不會被影響

    新增結(jié)構(gòu)可以被運行

  • 使用結(jié)構(gòu)體方法調(diào)用了包級別函數(shù), 包級別函數(shù)能被更新么?

    可以, 雖然方法不能被更新, 但方法被調(diào)用的包級別函數(shù)的地址是固定的, 所以可以被熱更新

  • init包初始化函數(shù)能用么? 能被熱更新么?

    官方這樣描述:

    When a plugin is first opened, the init functions of all packages not already part of the program are called. The main function is not run. A plugin is only initialized once, and cannot be closed

    插件第一次被打開時, 其關(guān)聯(lián)的, 沒有成為程序的一部分的所有的包的init函數(shù)將被調(diào)用. 插件的main函數(shù)不會被調(diào)用. 插件只會被初始化一次, 不能被關(guān)閉

    因此, 需要手動將init函數(shù)改成自己的函數(shù), 統(tǒng)一在so的main包里調(diào)用

編譯

  • 如何編譯獲得plugin包支持的動態(tài)庫

    SVCNAME=$1 SVCVER=$2 TIMESTAMP=`date '+%Y%m%d_%H%M%S'` go build -v -buildmode=plugin --ldflags="-pluginpath=${SVCNAME}_${TIMESTAMP}" -o ${SVCNAME}_${SVCVER}.so ${SVCNAME}

    -buildmode=plugin是重要參數(shù)

    --ldflags里的-pluginpath的作用是: 每次編譯的內(nèi)部識別路徑都是不同的, 避免重復(fù)加載的警告

    參考: https://github.com/golang/go/issues/19004

posted @ 2017-07-06 12:47 戰(zhàn)魂小筑 閱讀(8605) | 評論 (0)編輯 收藏

2017年4月20日 #

使用Visual Studio Code調(diào)試Golang工程

關(guān)鍵字

  • 最簡單的調(diào)試攻略
  • 多項目調(diào)試, 適用個人開發(fā)和項目開發(fā)
  • 無需修改系統(tǒng)環(huán)境變量

準(zhǔn)備VSCode

在官網(wǎng)下載最新版的VSCode:

https://code.visualstudio.com/

安裝Golang插件

  • 打開擴(kuò)展面板

    VSCode->查看->擴(kuò)展

  • 找到Go插件 在搜索框里輸入Go, 找到第二行寫有 Rich Go language support for Visual Studio Code的插件, 點擊安裝

    注意不是排名最高的

  • 重啟編輯器

配置啟動項

  • 打開調(diào)試面板

    VSCode->查看->調(diào)試

  • 添加調(diào)試目標(biāo)

    在"沒有調(diào)試"的下拉框中點擊"添加配置.."

  • 添加目標(biāo)調(diào)試配置

    例子:

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Launch",
                "type": "go",
                "request": "launch",
                "mode": "debug",
                "remotePath": "",
                "port": 2345,
                "host": "127.0.0.1",
                "program": "${fileDirname}",
                "env": {
                    "GOPATH":"D:/Develop/vscodegolang"
                },
                "args": [],
                "showLog": true
            }
        ]
    }

其中: "port", "host"都是go插件自動生成的

"env"為設(shè)置環(huán)境變量, 設(shè)置為你的工程目錄就可以(包含bin, src的文件夾)

準(zhǔn)備調(diào)試插件

此時找到main.go按F5, 會報錯提示:

Failded to continue:"Cannot find Delve debugger. Install from https://github.com/derekparker/delve & ensure it is in your "GOPATH/bin" or "PATH"

我們使用go命令行編譯調(diào)試器

go get github.com/derekparker/delve/cmd/dlv

將dlv調(diào)試器放在GOPATH(工程目錄)的bin目錄下

開始調(diào)試

選中要調(diào)試的main.go, 點擊F5, 既可以開始調(diào)試

調(diào)試快捷鍵和Visual Studio系一致

  • F9 切換斷點
  • F10 Step over
  • F11 Step in
  • Shift+F11 Step out

注意點

  • 某些結(jié)構(gòu)體成員無法直接顯示時, 可以直接選中變量名, 添加到監(jiān)視, 或者右鍵點擊: "調(diào)試:求值"

多項目調(diào)試

在launch.json中可以添加多組調(diào)試入口, 通過調(diào)試面板中選中對應(yīng)的配置開啟不同目標(biāo)的調(diào)試

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "client",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "remotePath": "",
            "port": 2345,
            "host": "127.0.0.1",
            "program": "${fileDirname}",
            "env": {
                "GOPATH":"D:/Develop/vscodegolang"
            },
            "args": [],
            "showLog": true
        },

        {
            "name": "server",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "remotePath": "",
            "port": 2345,
            "host": "127.0.0.1",
            "program": "${workspaceRoot}/src/server",
            "env": {
                "GOPATH":"D:/Develop/vscodegolang"
            },
            "args": [],
            "showLog": true
        }
    ]
}

"program"中的"${fileDirname}"是以當(dāng)前選中文件作為啟動點

更建議使用"program"的"${workspaceRoot}", 以包名作為啟動點的方式進(jìn)行配置

參考鏈接

https://code.visualstudio.com/Docs/editor/debugging

posted @ 2017-04-20 12:52 戰(zhàn)魂小筑 閱讀(8319) | 評論 (0)編輯 收藏

2017年4月8日 #

相位技術(shù)

相位技術(shù)大規(guī)模出現(xiàn)在魔獸世界WLK版本, 現(xiàn)在應(yīng)用已經(jīng)廣泛應(yīng)用在各種MMORPG游戲中. 下面對相位技術(shù)的做法進(jìn)行簡單歸納匯總

表現(xiàn)分類

副本相位

早期副本的出現(xiàn), 避免搶怪問題. 所以, 副本其實本身就是一種相位技術(shù). 只不過實現(xiàn)時, 我們一般會將小隊和怪物直接預(yù)分配在獨立的一個副本實例中(所以副本原文也是實例的意思)

分線相位

相位技術(shù)還沒有正式命名時, 同一個場景, 玩家進(jìn)到不同的分線看到的玩家不一樣, 也是屬于相位的一種. 當(dāng)然, 如果是組隊玩家, 服務(wù)器默認(rèn)會分配所有隊伍玩家在同一個線(位面)

真相位

副本相位和分線相位其實都是靜態(tài)相位, 一旦進(jìn)入, 中途不會有切換或者混合查看的過程. 真相位可以在一個場景中,動態(tài)切換相位, 相位內(nèi)和相位外所以不同

我們常見的真相位表現(xiàn)為: 相位中的角色+玩家+隊伍成員

在護(hù)送任務(wù)時, 還會在上面所見角色中疊加世界中的所有角色, 也就是說, 你和隊伍成員可以看到的角色, 其他人看不到, 其他人也看不到你和你的隊伍成員


為了清晰的簡單的描述, 我為相位創(chuàng)建如下概念與名詞

相位客體

表現(xiàn)為除玩家外的角色(怪物,交互物體與相位可見場景)

私有客體

這是最常見的一種相位內(nèi)角色

  • 持有變量

    取PhasingID時,為PhasingTargetID

  • 生成規(guī)則

    當(dāng)玩家開啟相位后, 在玩家相位內(nèi)生成的角色為私有客體.

    此時, 將 PhasingTargetID設(shè)置為相位生成者的實例ID

  • 刪除規(guī)則

    如果玩家退出相位, 私有客體會存在一段時間或按照需求刪除

公共客體

一般指提前放置在場景中, 世界內(nèi)不可見, 但是能被同相位玩家可見,且同相位玩家都可以互相可見 比如: 只要接了同一個任務(wù)的玩家, 都可以看到的NPC

  • 持有變量

    取PhasingID時,為PublicPhasingID

  • 生成規(guī)則

    通過場景編輯器, 放置角色時, 設(shè)置其可被觀察到的任務(wù)ID

    角色被加載后, 將任務(wù)ID設(shè)置到StaticPhasingID

  • 刪除規(guī)則

    場景刪除, 角色刪除

相位主體

包含玩家與同隊伍玩家

  • 開啟相位后, 可見私有客體+公有客體

  • 隊長視為相位主體, 單人時, 自己為隊長

  • 隊伍其他成員共享隊長的私有相位客體

  • 隊伍其他成員根據(jù)自己的PublicPhasingID匹配目標(biāo)對象的PublicPhasingID時可互相可見

  • 持有變量

相位開啟時, 取PhasingID時, 為角色實例ID

相位關(guān)閉時, 取PhasingID時, 為0

PublicPhasingID

可見規(guī)則

當(dāng)兩個角色的PhasingID相等時, 主體與私有客體互相可見

當(dāng)兩個角色的PublicPhasingID相等時, 主體與公有客體互相可見

可以通過開關(guān)設(shè)置, 是否在可見的相位客體基礎(chǔ)上, 疊加世界角色(護(hù)送任務(wù))

約束

  • 玩家同時只能看見1個相位
posted @ 2017-04-08 14:41 戰(zhàn)魂小筑 閱讀(21330) | 評論 (0)編輯 收藏

2016年12月1日 #

Golang中沒有設(shè)計構(gòu)造函數(shù). 取而代之的, 設(shè)計Golang的大師希望你用普通函數(shù)去實現(xiàn)構(gòu)造的任務(wù). 
一直只是覺得這只是體現(xiàn)Golang這門新語言的精簡設(shè)計之道, 直到自己實現(xiàn)編譯器后才發(fā)現(xiàn)構(gòu)造函數(shù)的設(shè)計本身是值得商榷的

我們先看下構(gòu)造函數(shù)的規(guī)則

構(gòu)造函數(shù)調(diào)用規(guī)則

構(gòu)造參數(shù)量: 0表示沒有構(gòu)造函數(shù), 1表示有構(gòu)造函數(shù)0個參數(shù)

本類構(gòu)造父類構(gòu)造處理方法
00不處理
10調(diào)本類ctor
01調(diào)父類ctor
11調(diào)本類ctor, 本類ctor調(diào)父類ctor
21調(diào)本類ctor, 本類ctor調(diào)父類ctor
12報錯, 手動調(diào)父類ctor
22報錯, 手動調(diào)父類ctor

普通函數(shù)重載規(guī)則

實際只用考慮最典型的一種行為: 實例化子類, 轉(zhuǎn)為父類調(diào)用方法, 這個時候

如果方法是override, 調(diào)用的是子類

如果方法是virutal或者不指明, 調(diào)用的是父類

整個重載過程, 子類絕對不會隱式調(diào)用父類的行為

需要構(gòu)造函數(shù)么?

構(gòu)造函數(shù)的優(yōu)點

  • 本身屬于一種特殊的成員函數(shù)
  • 編譯器幫你自動傳導(dǎo)調(diào)用父級

構(gòu)造函數(shù)的缺點

  • 隱式的調(diào)用規(guī)則
  • 雖然屬于成員函數(shù), 但是與其他成員函數(shù)調(diào)用規(guī)則完全不同, 需要特殊記憶
  • 帶參數(shù)的構(gòu)造函數(shù), 在父類參數(shù)多于子類時, 需要引用復(fù)雜語法來實現(xiàn)父級構(gòu)造調(diào)用

其實我們對初始化函數(shù)的需求只有1條: 自定義

所以, 可以理解Golang不加入構(gòu)造函數(shù)的設(shè)計是正確的 
即: 簡單, 清晰, 有規(guī)律

posted @ 2016-12-01 10:45 戰(zhàn)魂小筑 閱讀(3369) | 評論 (0)編輯 收藏

2016年11月2日 #

append, map, len不是關(guān)鍵字

他們其實還是類庫功能, 都在buildin包里的, 系統(tǒng)默認(rèn)給你做了個

  1. import(
  2. . "buildin"
  3. )

將buildin的包內(nèi)容都映射到全局而已, 其實你也可以用自己的包這么做

打印的另一種寫法

想跟腳本一樣調(diào)試打印數(shù)據(jù)么?

  1. println("hello world")

無需包含任何包, 因為它在buildin包里

iota不是黑科技

這是在buildin包里的定義

  1. // iota is a predeclared identifier representing the untyped integer ordinal
  2. // number of the current const specification in a (usually parenthesized)
  3. // const declaration. It is zero-indexed.
  4. const iota = 0 // Untyped int.

其實go是有泛型概念的

想想map和數(shù)組的定義 
只是泛型沒有開放給用戶用而已(只許XX放火,不許XX點燈)

map是支持多個key的, 而且很方便

還在為多個key轉(zhuǎn)id的復(fù)雜算法而頭疼么?

  1. type myKey struct{
  2. number int
  3. str string
  4. }
  5. func main(){
  6. t := map[ myKey] int {
  7. myKey{ 2, "world"}: 1,
  8. }
  9. fmt.Println(t[myKey{2, "world"}])
  10. }
  11. 輸出: 1

枚舉是可以轉(zhuǎn)成string的

默認(rèn)定義一個枚舉

  1. type MyConst int
  2. const (
  3. MyConst_A MyConst = iota
  4. MyConst_B MyConst = iota
  5. )
  6. func main(){
  7. fmt.Println(MyConst_A)
  8. }

輸出: 0 
如果我們想自動化輸出MyConst_A字符串時 
就需要使用golang的一個工具鏈:golang.org/x/tools/cmd/stringer 
將其下載, 編譯成可執(zhí)行工具后, 對代碼進(jìn)行生成 
生成的代碼會多出一個xx_string.go 
里面就是枚舉的String()string 函數(shù)

臨時轉(zhuǎn)換一個接口并調(diào)用的方法

  1. type love struct{
  2. }
  3. func (self*love)foo(){
  4. fmt.Println("love")
  5. }
  6. func main(){
  7. var chaos interface{} = new(love)
  8. chaos.(interface{
  9. foo()
  10. }).foo()
  11. }

Golang的receiver實際上就是this的變種實現(xiàn)

  1. func( self*MyStruct) foo( p int ){
  2. }

寫不慣receiver的寫法? 如果這樣改下呢?

  1. func foo( self *MyStruct, p int ){
  2. }

所以為什么說Golang還是一個C語言嘛

關(guān)于內(nèi)存分配…

  • new 傳入Type類型, 返回*Type類型
  • make 可以在分配數(shù)組時設(shè)置預(yù)分配大小, new不可以
  • make 能分配數(shù)組,map, 但不能分配結(jié)構(gòu)體和原始類型
  • new 能分配數(shù)組, map, 結(jié)構(gòu)體和原始類型等的所有類型
  • &Type等效于new
  • 切片不需要分配內(nèi)存(make,new), 直接聲明就可以了…

Golang的反射無法通過一個類型名, 創(chuàng)建其實例

C#有Assembly概念, 可以在一個Assembly里搜索, 創(chuàng)建實例

Golang是靜態(tài)類型語言, 如果需要, 只能注冊你需要創(chuàng)建的結(jié)構(gòu)體, 然后將注冊好的map用于創(chuàng)建

Golang可以替換Python來進(jìn)行復(fù)雜的工具流程處理

如果你需要跨平臺的工具流程處理, 對Python不熟悉, 可以使用

  1. go run yourcode.go 參數(shù)1 參數(shù)2

方式來進(jìn)行工具處理 
覺得慢, 可以編譯成可執(zhí)行文件

這樣做的好處: 如果有些類庫本身就是go寫的, Python想使用是很麻煩的, 而Golang來寫則輕而易舉

例子: 通過go的protobuf庫, 對一些文件進(jìn)行處理

Golang可以自動持有方法的接收者實例

  1. type myType struct{
  2. }
  3. func (self*myType) foo( p int){
  4. fmt.Println("hello", p )
  5. }
  6. func main(){
  7. var callback func( int )
  8. ins := new(myType)
  9. callback = ins.foo
  10. callback( 100 )
  11. }

做過lua的C++代碼綁定的童鞋都清楚: lua只支持外部靜態(tài)或者全局函數(shù)調(diào)用 
如果要進(jìn)行C++類成員函數(shù)調(diào)用時, 要自己處理this和成員函數(shù) 
這種技巧因為早起編譯器的虛表不同平臺實現(xiàn)細(xì)節(jié)不統(tǒng)一需要專門處理 
后面跨平臺虛表統(tǒng)一后, 類成員函數(shù)的調(diào)用寫法也是很惡心復(fù)雜的 
但是Golang的小白式用法, 直接吊打C++, 甚至C#復(fù)雜的delegate

LiteIDE篇: 多開秘籍

  • 找到 菜單->查看->選項->通用->存儲->存儲設(shè)置到本地ini文件

  • 關(guān)閉LiteIDE

  • 復(fù)制LiteIDE整個目錄, 命名文件夾為你的工程名

  • 每個工程所在的LiteIDE的配置將是獨立的, 不會互相干擾

LiteIDE篇: 測試程序也是可以調(diào)試的

別以為程序一定要是main開始的才可以調(diào)試

Golang的測試程序雖然都是一個個Test開頭的函數(shù),但執(zhí)行g(shù)o test時, 還是有main入口

在LiteIDE中, 可以在 調(diào)試->開始調(diào)試測試程序里進(jìn)行測試程序調(diào)試

LiteIDE篇: 在Windows上可以輸出linux可執(zhí)行文件

go的工具鏈默認(rèn)支持交叉編譯 
在LiteIDE中, 可以通過切換輸出平臺, 輸出不同平臺的可執(zhí)行文件

posted @ 2016-11-02 11:09 戰(zhàn)魂小筑 閱讀(23268) | 評論 (1)編輯 收藏

2016年9月3日 #

Google官方為Golang的調(diào)試?yán)幽J(rèn)使用了gdb

然而, 使用gdb調(diào)試go程序會遇到goroutine的各類問題, 因為gdb不懂go

因此, 這里使用delve黑科技來進(jìn)行Golang的程序調(diào)試

純命令行調(diào)試方法在網(wǎng)上很容易搜索到, 本文主要以LiteIDE來進(jìn)行程序調(diào)試

關(guān)閉編譯器優(yōu)化

正常go build/install出的go程序是完全優(yōu)化過的, 強(qiáng)行使用調(diào)試器掛接調(diào)試時, 某些local變量/lamda表達(dá)式捕獲的變量會直接進(jìn)入寄存器, 無法使用調(diào)試器查看

刪掉所有的pkg, 為build或install參數(shù)加入關(guān)閉編譯器優(yōu)化的參數(shù) -gcflags "-N -l"

例如:

  1. go install -gcflags "-N -l" svc\gamesvc

delve調(diào)試器安裝方法

LiteIDE自帶了gdb, 但是沒有delve調(diào)試器, 需要自行安裝, 命令如下

  1. go get github.com/derekparker/delve/cmd/dlv

delve調(diào)試器會被放到你的GOPATH/bin下

LiteIDE中的delve調(diào)試器配置

選擇調(diào)試器

在LiteIDE菜單中選擇 調(diào)試->debugger/delve

delve環(huán)境變量設(shè)置

這個時候, LiteIDE依然找不到delve, 因為它不在環(huán)境變量PATH中, 這里無需修改環(huán)境變量, 只需要LiteIDE的環(huán)境配置

在LiteIDE菜單中選擇 查看->編輯當(dāng)前環(huán)境, 在彈出的文檔中修改

  1. PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH%;c:\your\path\to\delve

去掉PATH前的注釋#, 在%PATH%添加分號, 然后和你到delve調(diào)試器的路徑

開始調(diào)試

選擇你的工程, 點擊F5, 進(jìn)入調(diào)試模式

調(diào)試器顯示變量值

LiteIDE使用delve調(diào)試時, 無法在 變量 監(jiān)視等窗口中正確捕捉delve調(diào)試返回數(shù)據(jù)(因為格式太復(fù)雜了…)

沒關(guān)系, 我們使用命令行配合顯示即可

LiteIDE控制臺或調(diào)試輸出窗口在delve調(diào)試時, 實際上是一個標(biāo)準(zhǔn)命令行 
命令如下

  • p 變量名可以查看變量值

  • locals查看局部變量

  • ls可查看當(dāng)前文件

  • stack查看棧

  • help可以查看各種幫助

調(diào)試外部程序

如果你的程序是外部程序, 或者使用go install安裝到GOPATH/bin目錄的程序, 那么使用delve調(diào)試器啟動程序時, 可能會碰到啟動路徑錯誤的問題

使用LiteIDE菜單 調(diào)試->調(diào)試其他應(yīng)用程序… 填入你要調(diào)試程序的路徑以及工作目錄, 可以解決這個問題

posted @ 2016-09-03 18:12 戰(zhàn)魂小筑 閱讀(5593) | 評論 (0)編輯 收藏

僅列出標(biāo)題  下一頁
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一区二区三区免费网站| 亚洲高清在线| 欧美影院成年免费版| 99国产精品| 亚洲天堂av在线免费| 亚洲一区二区三区四区中文| 亚洲一区日本| 欧美中文字幕久久| 玖玖国产精品视频| 欧美国产视频在线| 欧美国产第一页| 99精品国产一区二区青青牛奶| 久久影院午夜论| 香蕉av777xxx色综合一区| 久久国产精品久久久久久电车 | 久久九九国产精品| 久久久999| 伊人久久综合| 日韩一二三区视频| 久久精品久久99精品久久| 欧美国产精品久久| 亚洲伦理在线| 欧美一区二区成人6969| 免费在线国产精品| 国产精品一区二区三区观看| 亚洲电影天堂av| 亚洲欧美日韩国产一区| 免费成人高清在线视频| 一区二区三区视频免费在线观看| 小嫩嫩精品导航| 欧美不卡视频一区| 99精品福利视频| 麻豆九一精品爱看视频在线观看免费| 欧美日韩一区二区在线视频| 影音先锋亚洲精品| 亚洲影视综合| 亚洲第一精品福利| 亚洲人成人99网站| 久久综合狠狠综合久久综合88| 国产精品国产三级国产普通话三级| 国产综合婷婷| 亚洲男人的天堂在线观看| 亚洲高清毛片| 欧美一区二区三区婷婷月色| 国产精品二区三区四区| 亚洲三级影片| 美日韩精品视频免费看| 午夜精品久久久久久99热软件| 欧美日韩不卡合集视频| 亚洲激情视频在线| 欧美成人精品在线视频| 亚洲欧美日韩人成在线播放| 欧美成人午夜激情| 欧美与黑人午夜性猛交久久久| 国产精品久久久久久久久久直播 | 欧美国产欧美亚洲国产日韩mv天天看完整 | 国产精品久在线观看| 在线视频你懂得一区二区三区| 亚洲成人在线视频播放 | 欧美日韩亚洲另类| 亚洲欧洲另类| 欧美激情视频一区二区三区免费 | 国产精品综合| 久久99伊人| 午夜视频在线观看一区二区| 国产精品视频成人| 欧美一区二区视频在线| 亚洲综合首页| 国内精品久久久久影院色| 精久久久久久久久久久| 欧美一区二区三区四区在线观看地址| 亚洲视频欧美在线| 国产欧美精品在线| 久久综合久色欧美综合狠狠| 久久久最新网址| 亚洲人在线视频| 亚洲精品一级| 国产欧美日韩另类一区| 蜜臀91精品一区二区三区| 欧美成人免费全部| 亚洲深夜av| 小嫩嫩精品导航| 亚洲人体偷拍| 午夜精品福利电影| 亚洲日韩第九十九页| 一区二区欧美激情| 国内精品久久久久影院优| 亚洲国产精品一区二区三区| 国产精品sm| 欧美阿v一级看视频| 欧美视频在线观看一区二区| 欧美中文在线字幕| 欧美经典一区二区| 久久精品国产清高在天天线| 欧美激情精品久久久六区热门| 亚洲女ⅴideoshd黑人| 久久九九国产精品| 一区二区三区国产盗摄| 久久国产精品99精品国产| 一本色道88久久加勒比精品| 欧美影院成年免费版| 亚洲午夜影视影院在线观看| 久久久久久夜精品精品免费| 亚洲中字黄色| 欧美国产成人在线| 欧美va日韩va| 国产欧美日韩亚洲| av72成人在线| 亚洲毛片一区| 久久久国产视频91| 欧美一区二区高清| 欧美日韩亚洲综合| 欧美aaaaaaaa牛牛影院| 国产精品美女久久久免费| 亚洲国产午夜| 伊人久久综合97精品| 午夜宅男久久久| 午夜一区二区三区在线观看| 欧美日韩精品福利| 亚洲国产精品电影| 亚洲国产成人久久综合一区| 欧美在线观看视频一区二区三区 | 亚洲第一狼人社区| 国产主播精品| 欧美主播一区二区三区| 亚洲欧洲av一区二区| 欧美日韩天堂| 亚洲精品一区在线观看香蕉| 亚洲伦理在线| 欧美激情久久久| 亚洲福利视频二区| 亚洲欧洲一区二区在线观看 | 欧美一区二区三区喷汁尤物| 欧美激情精品久久久久久| 亚洲午夜极品| 狠狠色丁香久久综合频道| 亚洲一区高清| 午夜精品福利一区二区三区av| 久久久久看片| 蜜桃精品一区二区三区| 尤物九九久久国产精品的特点 | 久久久久免费视频| 久久久综合免费视频| 国产欧美日韩激情| 亚洲欧美成人一区二区在线电影 | 欧美一区二区三区视频| 欧美性大战久久久久久久| 亚洲最新合集| 亚洲欧美成人网| 国产精品一区二区三区成人| 欧美一区二区私人影院日本| 羞羞答答国产精品www一本 | 亚洲一区二区视频在线| 欧美日韩网址| 亚洲欧美国产77777| 久久久午夜精品| 怡红院精品视频在线观看极品| 久久夜色撩人精品| 亚洲精品国久久99热| 欧美日韩一区综合| 亚洲一区日韩在线| 久久综合久久88| 亚洲精品一区二区三区福利| 欧美午夜一区二区| 久久精品人人做人人爽电影蜜月 | 久久精品国产免费| 亚洲精华国产欧美| 欧美视频在线观看| 久久久视频精品| 亚洲免费观看视频| 性欧美超级视频| 尤物yw午夜国产精品视频明星| 欧美日韩国产小视频| 欧美一级午夜免费电影| 亚洲精华国产欧美| 欧美在线视频全部完| 亚洲精品无人区| 国产一区999| 欧美日韩精品一区二区| 久久久国产成人精品| 一区二区三区色| 亚洲国产综合视频在线观看| 久久精品亚洲一区二区三区浴池| 日韩写真在线| 在线免费精品视频| 国产精品大片| 欧美精品一区二区三区高清aⅴ| 欧美在线3区| 国产精品99久久久久久久久久久久 | 久久久91精品国产一区二区三区 | 亚洲一区二区三区四区五区午夜| 久久久久网址| 国外成人在线| 国产精品免费一区二区三区观看| 亚欧美中日韩视频| 久久久一区二区| av成人免费在线观看| 国产区欧美区日韩区| 欧美肥婆在线| 久久aⅴ乱码一区二区三区|