分类 Unity 下的文章

在製作地圖時為了資源的共用跟製作速度可以參考使用unity tilemap
14105-2spkdve06dd.png

首先在 Hierarchy 右鍵 / 2D Object / Tilemap / Rectangular 生成 tilemap 物件
63391-nlsbvstpftq.png

再來選擇Grid 將 Cell Size 修改成 32 x 32(如果遊戲中用到的 chunk 是 32 x32 )
10794-7n7t7xhcm0f.png

接著開啟 tilemap 資源管理器, Window / 2D / Tile Palette
04501-m66b5fapvc.png

把資源管理清單的 sprite 貼圖拖曳到 Tile Palette 中間區塊,
88419-vxqfes2twlj.png

資源更新如下
98381-i2d1cku3am.png

最上面的 tool 依序代表的是 "選擇"、"移動"、"畫筆"、"方形區域填充"、"取色"、"橡皮擦"、"填充"
26296-vbrslezmv9.png

首先在 tile palette 中選擇要使用的 tile,然後選擇"畫筆"工具,就可以直接在場景中繪製 tilemap 地塊
07789-lfef5b7b8x.png

另外,將 sprite 拖曳到 tile palette 中時發現圖素很小,繪製的 tilemap 也是顯示很小
這時候必須調整原圖的 Pixels Per Unit 為 1 ,因為原圖大小 32 x 32 需要顯示在 32 各 Unity unit 上
66725-0v34tddqzdpj.png

幀同步在服務端採用房間模式,玩家在對戰時創建對應房間並將玩家加入該房間進行對戰,對於在線遊戲玩家數超過單服務器負載上限時可以多開房間服,這樣可以有效分散帶寬壓,為了更好的遊戲體驗一般會對進行對戰遊戲匹配進入合適的房間。

幀同步保證所有客戶端在每一個frame執行後的結果是一致的,但考慮不同客戶端延遲不同使用嚴格模式必須等待所有客戶端消息收到才能廣播,一個客戶端卡會造成所有用戶都卡頓,在這我們使用樂觀鎖模式。

樂觀模式:
服務端每一個turn(frame)無須等待客戶端消息,直接將當前收集到的消息廣播給客戶端,因此卡的客戶端自己會顯示卡頓或是無效,但不會影響到其他用戶

90362-wjtypddppvg.png

我們務必保證客戶端上傳FrameData依據的關鍵幀Id是準確無誤的,也就是客戶端A在 FrameId = 233 跟客戶端B在 FrameId = 233,不能有時間差,所以保證了客戶端 Update 跟計算關鍵幀都是依據真實時間就能做到這點,這樣客戶端上傳FrameData就醫定是校時過的。

網路平滑化
當然服務端或客戶端收到對方消息可能是網路延遲過N各Frame才收到,這個就看服務端/客戶端的處理是設定平滑多少了,平滑設定間隔大了

服務端處理的是 Current FrameId - N FrameId 的消息,也因此客戶端收到消息必定也是延遲N Frame過後的數。這邊會牽涉到預判跟回滾,因為樂觀鎖不會因為消息沒收到就停止,所以客戶端必須預測目前Frame的玩家行為,但如果預測錯了就必須回滾回去。

邏輯計算要點
在邏輯運算中必須保證多端之間的運算結果是一致的,因此必須保證以下重點

  1. 使用隨機必須保證執行結果一致
    每一個房間分配一個隨機種子,根據種子計算的到結果一致
  2. 禁止使用float進行計算
    自行實現float class
  3. 客戶端刷新 entity 不可以有順序性問題,譬如判斷 entity.UserId == MyUserId 造成運算順序差異

在寫操作判斷時發現狀態的紀錄總是有問題, 有時候系統沒有keyUp事件造成了狀態殘留, 寫法如下

void FixedUpdate(){
    if (Input.GetKeyDown(KeyCode.A)){
        Log.Debug("KeyDown");
    }
    if (Input.GetKeyUp(KeyCode.A)){
        Log.Debug("KeyUp");
    }
}

後來發現 Input.GetKeyDown, Input.GetKeyUp 不能寫在 FixedUpdate 不然就會出現缺少的問題

之前使用了 Unity FixedUpdate 計時器來處理 update, 後來發現在多端之間客戶端計算結果不一致
開始查起這個問題, 查到最後發現是因為客戶端調用 update 次數不一致造成的
由於A端跟B端在FPS上有所差別, A端FPS=60, B端FPS=90, 在這個基礎上調用的 fixedUpdate 次數不一致
造成了B端的怪物行走比A端快

修改思維
(1) 如果不改變 fixedUpdate 造成的次數問題就必須把行走距離改成根據時間差來計算實際距離, 如下

movement = 120 pixels/sec
則 120/50 =2.4/Frame, 每幀需要行走2.4pixels, 
如果當前幀跟上一幀時間間距為32 minisec,
 則 32 / 20 = 1.6 * 2.4 = 3.84 pixels 為當下幀需要行走的距離

(2) 修改計時器保證每一次 update 都是 20 ms

//將 fixedUpdate 更新頻率拉高到 120 FPS
void FixedUpdate(){
    long nowt = this.GetUtcTimeMS();
    finish = false;
    while (!finish){
    if ((nowt - this.updateTs) > 20){
        this.updateTs += 20;
        //實際調用刷新函式
        this.doUpdateLogic(param);
        finish = false;
    }
}
假設客戶端在一個tick內調用3次doUpdateLogic, 底下調用不可以使用 UTC.Now 去計算時間差值, 不然3次計算
出來的差值都會是最大值

最近修改介面遇到修改後apply,結果 Image 的 Sprite 直接變成 Missing(Sprite)
69516-838q1kki6je.png

使用TexturePacker打包資源到Unity使用有時候會出現這個問題, 最乾脆的做法就是把 Sprite 名稱給換掉
81779-3uohg6x6fr6.png