今天主要就是在繼續核心戰鬥的開發。遊戲的玩法很傳統,就是帶一隊英雄在2D橫版副本上,能夠劃線拖動,以及釋放技能刷怪。對戰我但願能夠作成多人實時的,但因爲涉及到玩家的操做,想要作到很平滑的體驗,狀態同步加簡單的渲染層預測依然是不夠的。多人實時對戰的,以前用unity作手遊時,探索過幀同步+ECS+渲染層預測回滾的解決方案。可是幀同步對於小團隊開發太耗心力了,其它的不說,光是輔助的調試工具以及大規模的測試都是小團隊難以勝任的,更況且是採用Js的H5呢。不過我仍是使用Js實現過一個幀同步的版本,由於開發H5才又去學習的Js,而後開發過程發現Js的number數據類型沒法區分整型和浮點,雖說動態語言彷佛都是不區分整型和浮點的,可是像Lua這種我還能夠嵌入C模塊,可Js要跑在瀏覽器裏面,目前就個人瞭解,是沒法嵌入C模塊的。這樣就使得定點數的實現很是困難。後來仍是找了個BigInteger.js,內部直接用字符數組來模擬整數運算的去實現定點數運算,可是性能堪憂。
由於這個緣由,同步方案成了個人一塊心病,有一天忽然想到,其實狀態同步也是能夠和ECS、狀態回滾很好地結合在一塊兒的。輕io競技的這種,參與的玩家通常是3V3或是5V5左右,而玩法通常也不會太複雜,地圖上不會像RTS或是MOBA那種出現大量的做戰單位,所以相較於幀同步,須要同步的數據量並不會多多少。核心的邏輯依然獨立出來,每幀計算出單獨的數據副本,渲染層輪循核心邏輯層做插值展示。服務器的話,也同時跑一樣一套核心邏輯,在檢測到不一樣幀的狀態數據有改變時,則將改變的數據按幀同步到客戶端便可。若是客戶端的演算超前於同步狀態幀的話,則只須要以服務器的狀態幀爲準,重置先前的邏輯幀,而且從重置幀從新向後演算便可。渲染層由於是插值演算,在網絡抖動不是很大的狀況下,重置後依然能夠保持平滑的體驗。因爲是以服務器狀態爲準,兩邊客戶端的本地演算出現誤差也沒有關係,並且一些關鍵的數據(好比玩家或怪物死亡等)必然會被檢測到並同步到客戶端,所以即便客戶端演算與服務端演算出現誤差,出現服務器認爲沒有變更而客戶端演算認爲變更的數據,致使畫面的展示與服務器狀態不是徹底一致,也不會對用戶體驗形成多大的影響。更況且這種不一致原本就是小几率事件。
對於數據變更的檢測,在服務端,只須要每幀之間對全部entities的components作一個對比,蒐集變更的數據並打包下發到客戶端便可。固然,這也是歸功於ECS(Entity-Component-System)的設計思路,不只使得數據與行爲徹底分離,中間狀態的計算與回滾成爲可能,也使得可以擺脫類型的束縛,以一種統一的方式來處理對象各屬性的數據。數組