<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          easyMenu 開源,讓游戲調(diào)試更簡單!

          共 11726字,需瀏覽 24分鐘

           ·

          2023-10-10 22:23


          easyMenu 簡介

          使用內(nèi)置的 UI 組件創(chuàng)建一個(gè)調(diào)試面板通常是一個(gè)緩慢而繁瑣的過程,為了解決這個(gè)問題,二喵開源了自用的調(diào)試面板 easyMenu,兼顧了實(shí)用性和美觀。

          4c5c6709b62bbfb2275b12e1e5e3b85c.webp

          這個(gè)調(diào)試面板支持批量添加菜單組件,就像使用 tween 一樣簡單。你可以快速添加多個(gè)項(xiàng)目,而且維護(hù)起來也非常方便。

          3b6bf4e49616a34d9802d1bb50a7901c.webp

          調(diào)試面板內(nèi)置了一些有用的調(diào)試模塊,下面我們來了解一下如何使用這些特性和功能, 快速定位游戲的一些性能問題。

          FPS 快捷設(shè)置

          調(diào)試面板允許我們手動(dòng)設(shè)置 FPS(每秒幀數(shù)),以便測試性能。30 FPS 的開銷和發(fā)熱會(huì)更少,但流暢度會(huì)有所降低。

                  
                     const Debug = this.menu.addGroup("Debug");
             Debug.addToggle("High FPS"(t) => { game.frameRate = t ? 60 : 30;})

          只需要 2 行代碼就可以快速添加 FPS 切換,可以點(diǎn)擊 Toggle 按鈕在 30 FPS 和 60 FPS 間快速切換。

          FPS 監(jiān)控

          提到了 FPS 切換,我們再來講下 FPS 監(jiān)控,引擎默認(rèn)只提供了當(dāng)前 FPS 數(shù)值,無法監(jiān)控 FPS 的變化。

          541892fbbe70d94c23258c1b822212c8.webp

          eMenu  提供了  eGraph  圖形監(jiān)控面板,使用簡單,可以快速監(jiān)控如 FPS 變化,場景內(nèi)敵人數(shù)量變換等,下面我們快速設(shè)置一下 FPS 監(jiān)控。

          我們首先獲取 graph 節(jié)點(diǎn)的實(shí)例,如下圖所示,代表最高數(shù)值 60,最多14段數(shù)據(jù)。

                  
                     const Debug = this.menu.addGroup("Debug");
             Debug.addGraph("FPS"null6014);
             this.graph = Debug.node.getChildByName("FPS").getComponent(eGraph);

          然后可以在  update  內(nèi)統(tǒng)計(jì)每秒內(nèi)的幀數(shù),并推送給  eGraph  面板

                  
                      time = 0;
              counter = 0;
              update(dt) {
                  this.counter += 1;
                  this.time += dt;
                  if (this.time >= 1) {
                      const graph = this.graph;
                      if (!graph) return;
                      graph.updateData(this.counter)
                      this.time -= 1;
                      graph.NameLable.string = "FPS: " + this.counter;
                      this.counter = 0;
                  }
              }

          我們還可以給 Graph 添加點(diǎn)擊事,通過點(diǎn)擊面板,可以獲取歷史的曲線節(jié)點(diǎn)數(shù)據(jù)。

          95c0b7563f02137e850ded393d1d8beb.webp

          這些數(shù)據(jù)也會(huì)復(fù)制到剪切板,方便粘貼查看。 5cade1223d38a6d77a661d963f044502.webp


          Overdraw 查看

          Overdraw 是指同一個(gè)像素點(diǎn)被渲染多次,這通常是由內(nèi)容冗余、層級混亂或邏輯錯(cuò)誤導(dǎo)致的。通過調(diào)試面板,我們可以使用代碼批量替換精靈的材質(zhì),以便更清楚地看到 overdraw 的情況。

                  
                      testOverdraw() {
                  this.overdrawMode = !this.overdrawMode;
                  const children = this.canvasNode.children;
                  const material: Material = this.overdrawMode ? this.overdrawMat : this.defaultMaterial;
                  children.forEach((child) => {
                      if (child == this.menu.node) return;
                      const sprites = child.getComponentsInChildren(Sprite);
                      sprites.forEach((sprite) => {
                          if (!this.defaultMaterial) {
                              this.defaultMaterial = new Material();
                              this.defaultMaterial.copy(sprite.material)
                          }
                          if (sprite.node.name !== this.node.name) {
                              sprite.material = material;
                          }
                      })

                  })
              }

          比如下圖的這個(gè) Banner 看起來很正常:

          b7eed9f5d08daf3f1741aec706bfdfa3.webp

          然而這個(gè) Banner 下面隱藏了很多其他精靈:

          7f1b9ccf2ed86b71ac47d9ce058ae094.webp

          在實(shí)際項(xiàng)目中,這些情況經(jīng)常發(fā)生,腳本邏輯錯(cuò)誤,或者忘記刪除測試節(jié)點(diǎn)都有可能導(dǎo)致 Overdraw,通過點(diǎn)擊 Overdraw 按鈕,我們可以查看那個(gè)像素點(diǎn)有多個(gè)精靈圖片渲染。

          752cc45f790a02e0dc7775978b2798ec.webp

          重復(fù)渲染的次數(shù)越多,紅色會(huì)越深,針對 Overdraw 的部分,我們可以通過以下方法解決。

          • 隱藏背景部分不需要渲染的精靈
          • 把大圖切割,避免中間大面積的透明像素

          養(yǎng)成查看 Overdraw 的習(xí)慣,可以降低 GPU 渲染的壓力,減輕手機(jī)的發(fā)熱情況。

          游戲速度控制

          通過重寫引擎的  tick  函數(shù),我們可以放慢全局速度,這對動(dòng)畫調(diào)試非常有幫助。并且還能用它實(shí)現(xiàn)子彈時(shí)間、慢動(dòng)作、加速回放等特殊需求。

                  
                  @ccclass('TimeScale')
          export class TimeScale extends Component {
              static scale = 1
              start () {
                  const originalTick = director.tick;
                  director.tick = (dt: number) => {
                      dt *= TimeScale.scale;
                      originalTick.call(director, dt);
                  }
              }
          }

          這里可以使用調(diào)試面板控制全局速度,方便調(diào)試動(dòng)畫和特效。

          c662428074eba2bf872bf2c45487e1a4.webp


          圖片內(nèi)存占用分析

          我們可以通過調(diào)試面板歷遍 assets 中所有的圖片資源,并按照尺寸排序,這樣就可以找出內(nèi)存開銷最高的圖片。結(jié)果會(huì)自動(dòng)復(fù)制到剪貼板內(nèi),方便進(jìn)一步分析和處理。

                  
                   getImageMemory(): string {
                  const assets = assetManager.assets;
                  let images: ImageAsset[] = [];
                  assets.forEach((asset) => {
                      if (asset instanceof ImageAsset) {
                          images.push(asset);
                      }
                  })
                  images.sort(function (a, b{
                      return b.height * b.width - a.height * a.width;
                  });
                  let output = "";
                  let total = 0;
                  /* get all imagessets mem */
                  images.forEach((image, i) => {
                      const self = image;
                      const native = self._native;
                      const url = self.url;
                      const num = Math.floor((self.width * self.height * (native.indexOf('jpg') > 0 ? 3 : 4) / 1024 / 1024) * 10000) / 10000;
                      total += num;
                      output = output + "\n" + url + "...." + num + "M";
                  })
                  total = Math.floor(total * 10000) / 10000;
                  output = "Total Image Mem...." + total + "M" + output;
                  console.log("Image Mem==", output)
                  this.copyToClipboard(output);
                  return output;
              }

          這里會(huì)支持打印所有圖片的路徑和內(nèi)存占用到剪切板。

          14f7ec8f0396993101dc9c13350725d0.webp

          我們可以通過路徑和圖片的 UUID 名字定位到開銷高的圖片,針對內(nèi)存占用高的圖片可以這么優(yōu)化。

          • JPG 格式由于沒有 Alpha 透明通道,內(nèi)存占用要比 PNG 少 25%,針對背景圖片,這里也推薦使用 JPG 格式。
          • 針對一些 1920 分辨的大圖,可以壓縮分辨率到 1280,配合 JPG 使用效果更佳。
          • 比較常用的按鈕和UI圖可以使用九宮格,切除中間區(qū)域,來減少圖片分辨率。


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

          在 3D 游戲開發(fā)中,有大量的環(huán)境變量,我們可以通過  globals  環(huán)境變量獲取大部分設(shè)置。

                          const scene = director.getScene();
                  const globals = scene.globals;
                  const light = scene.getComponentInChildren(DirectionalLight);
                  const ambientScale = globals.ambient.skyIllum / 100000;
                  const lightScale = light.illuminance / 100000;

                  this.menu
                      .addGroup("Env")
                      .addToggle("Shadow"(t) => {
                          globals.shadows.enabled = t;
                      })
                      .addToggle("IBL"(t) => {
                          globals.skybox.useIBL = t;
                      })
                      .addToggle("CSM"(t) => {
                          light.enableCSM = t;
                      })
                      .addSlider("Ambient"(p) => {
                          globals.ambient.skyIllum = p * 100000
                      }, ambientScale)
                      .addSlider("Light"(p) => {
                          light.illuminance = p * 100000
                      }, lightScale)

          通過動(dòng)態(tài)調(diào)試這些參數(shù),可以快速定位性能和畫面問題。


          免費(fèi)獲取源碼

          此外,easyMenu 也是一個(gè)非常有用的工具,可以用于快速添加菜單組件。它內(nèi)置了按鈕, list editbox slider graph  等多種組件,可以點(diǎn)擊【閱讀原文】免費(fèi)獲取源碼。

          具體的使用教程可以在商店說明頁面查看。

          Github 和 Store同步更新,方便的話可以給個(gè) Star:https://github.com/iwae/easyMenu

          謝謝大家的支持,二喵會(huì)再接再厲,輸出更多對大家有用的內(nèi)容。


          瀏覽 99
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人电影一二三区 | 天天做天天爱夜夜爽 | 内射的视频 | 国产精品扒开腿做爽爽爽A片唱戏 | 影音先锋啪啪资源 |