1. 程式人生 > >Unity Bug解決分析思路

Unity Bug解決分析思路

前言

一般來說,新手遇到bug會很苦惱,而且打擊自己的學習積極性。我在看完一套學習視訊後,自己關掉,然後看自己能不能完完全全的再寫出來,並且盡力讓他趨於完美。其實這樣的話,我相當於把程式碼寫了兩遍,看視訊的時候跟著敲了一遍,自己又寫了一遍。雖然苦,但是樂在其中

異常分類

  • 我將異常分為四種
  1. 在控制檯上雙擊可以定位的異常
    • 這種異常也許是由於上下文引起的
    • 也有可能屬於蝴蝶效應,間接引發的
  2. 無法定位的異常
    • 用二分法進行註釋,然後排查是哪句話出現的錯誤,結合錯誤型別進行定位
  3. 沒有任何報錯,但就是實現不了想要的功能
    • 首先將功能所涉及的函式全部Log,檢視是否全部執行
    • 將函式中所涉及的關鍵變數Log出來,檢視其變化
    • 根據變數所顯現出來的問題,進一步鎖定出現問題的程式碼
    • 然後將程式碼打上斷點,執行此處,檢視變數的情況。做到這一步基本就可以解決問題了
  4. 邏輯錯誤
    • 這種錯誤最低階也最致命,沒有解決辦法,只能多思考

下面的異常我將按照不同種類給予不同的標誌數字

1-空引用異常

  • 當時我對程式碼進行了重構,該刪的刪,該加的加,該移的移動
  • 當我執行的時候 ,果然出現了很多bug
  • 最常出現的是空引用異常
  • 雙擊定位到程式碼位置,打上斷點,開始除錯,然後檢視這個語句的所有變數值,看哪個為null
  • 或者在語句的上面Log輸出每一個變數值,檢視哪一個為空
  • 結果是我定義了一個集合,錯誤的把初始化語句給刪除了,所以為空

1-2 物品顯示與隱藏異常

  • 這個出現的空引用異常是最匪夷所思的,但是明白原理之後發現情有可原
  • unity 是無法搜尋被隱藏的物件的
  • 父物件由於切換功能的需要,在一開始例項化出來後就要全部禁用,這樣的話它的子物件在查詢自身或者子物件就會報錯空引用
  • 程式碼如下:
     GameObject tempCenter = GameObject.Instantiate<GameObject>(myView.Center, myView.CenterParent);
        CenterController tempS = tempCenter.GetComponent<CenterController>();
        //進行資料傳輸
        tempS.InitData(mapId, myView.CenterSlot, myModel.GetCenterItem(mapId), myModel.GetMapNum(mapId), myView.CenterItemDic);
        //加入字典當中
        centerDic.Add(mapId, tempS);
        tempCenter.SetActive(false); //禁用語句
  • 這個異常並沒有很複雜,關鍵是要知道有這麼一個bug,並且怎麼解決
  • 我在解決的時候,就在想要把SetActive(false)放在哪裡
    • 我認為禁用語句屬於自身控制語句,應該放置在它自己的腳本里,就放置在了Awake語句中,結果明顯不行
    • 我又想,乾脆在子物件的初始化語句後面加上啟用語句,結果還是不行

2- 1KeyNotFound 異常

  • 這個異常幾乎耗了我一個上午
  • 依然是重構完的事情,這個異常雙擊之後無法定位。所以我就很煩惱,到底是哪裡出了問題
  • 在控制檯下面,有關於這個語句的詳細分析,是在哪個腳本里面
  • 我將在start裡面執行的函式一一註釋,最後確定問題是在哪個函式裡面
  • 然後將函式裡面的語句根據功能進行註釋,然後執行,最後將問題鎖定到其中一個語句上面
  • 最後發現,我將Model層的字典直接以屬性的形式返回出來,在獲取value的時候,沒有進行key檢查
  • 原因是,我以前一直將字典封裝,根據key返回value,用tryGetValue方法,可以返回null,如果key不存在。所以沒有在意這個問題

3 異常

  • 實時物品檢測功能
  • 這個異常是我程式碼都全部寫好了,控制檯也沒有報錯,但沒有實現我的功能。
  • 這種異常是最棘手的。
函式之間的關係
  • 函式之間有這麼幾種關係
  • A呼叫B
  • A呼叫上層B
  • A呼叫下層B
  • 單例模式之間的呼叫

注意事項

  • 在指令碼內寫新的功能程式碼的時候,每寫完一個函式,需要對自身的輸出進行Debug測試,是否輸出自己想要的資料
  • 如果以上那幾種函式呼叫關係,呼叫函式的簽名確定以後,先在函式裡面進行Debug,傳遞的引數是否正常,符合預期,函式是否執行到這裡,
    • 每寫一句程式碼都要思考,如果不這樣的話會怎麼樣?
    • 例如SendMessaagesUp,我在子物件的方法構建完畢後,進行了測試,因為這時候父物件的方法還沒有構思,因此裡面的sendMessageUp沒有測試,在後面的時候發現傳遞過去的引數不符合預期

感言

  • 良好的程式碼書寫習慣很重要,可以避免浪費很多時間
  • 學習過程中需要適時的總結歸納
  • 以前在學校上課,這個過程被老師替代了,自學的話就需要自己來做