diff --git a/images/apple-worldwide-developer-relations-certificate-fix/expired-certificate.png b/images/apple-worldwide-developer-relations-certificate-fix/expired-certificate.png new file mode 100644 index 0000000..9ca5a5f Binary files /dev/null and b/images/apple-worldwide-developer-relations-certificate-fix/expired-certificate.png differ diff --git a/images/apple-worldwide-developer-relations-certificate-fix/invalid-issuer.png b/images/apple-worldwide-developer-relations-certificate-fix/invalid-issuer.png new file mode 100644 index 0000000..2e09a2e Binary files /dev/null and b/images/apple-worldwide-developer-relations-certificate-fix/invalid-issuer.png differ diff --git a/images/apple-worldwide-developer-relations-certificate-fix/show-expired-certificates.png b/images/apple-worldwide-developer-relations-certificate-fix/show-expired-certificates.png new file mode 100644 index 0000000..84f85d1 Binary files /dev/null and b/images/apple-worldwide-developer-relations-certificate-fix/show-expired-certificates.png differ diff --git a/images/unity-crash-report/activate-game-performance.png b/images/unity-crash-report/activate-game-performance.png new file mode 100644 index 0000000..4e04e27 Binary files /dev/null and b/images/unity-crash-report/activate-game-performance.png differ diff --git a/images/unity-crash-report/create-new-project.png b/images/unity-crash-report/create-new-project.png new file mode 100644 index 0000000..6bccb21 Binary files /dev/null and b/images/unity-crash-report/create-new-project.png differ diff --git a/images/unity-crash-report/exception.png b/images/unity-crash-report/exception.png new file mode 100644 index 0000000..7c30b7e Binary files /dev/null and b/images/unity-crash-report/exception.png differ diff --git a/images/unity-crash-report/getting-started.png b/images/unity-crash-report/getting-started.png new file mode 100644 index 0000000..0250107 Binary files /dev/null and b/images/unity-crash-report/getting-started.png differ diff --git a/images/unity-crash-report/install.png b/images/unity-crash-report/install.png new file mode 100644 index 0000000..34eede8 Binary files /dev/null and b/images/unity-crash-report/install.png differ diff --git a/images/unity-foreach/unity-4.7.png b/images/unity-foreach/unity-4.7.png new file mode 100644 index 0000000..a2431ca Binary files /dev/null and b/images/unity-foreach/unity-4.7.png differ diff --git a/images/unity-foreach/unity-5.png b/images/unity-foreach/unity-5.png new file mode 100644 index 0000000..46e0c05 Binary files /dev/null and b/images/unity-foreach/unity-5.png differ diff --git a/index.html b/index.html index 75ee9d7..d3d0cee 100644 --- a/index.html +++ b/index.html @@ -103,7 +103,7 @@

2017

2017-12-29 - + 使用 ReSharper 或 Rider 在編輯器裡執行 Unity 元件測試 @@ -114,7 +114,7 @@

2017

2017-03-26 - + Asset、Object 與序列化 @@ -125,7 +125,7 @@

2017

2017-03-26 - + AssetBundle 與 Resources 指南 @@ -136,7 +136,7 @@

2017

2017-03-09 - + Apple iOS 審查與動態更新 @@ -147,7 +147,7 @@

2017

2017-02-07 - + 一窩蜂驅動開發 @@ -158,7 +158,7 @@

2017

2017-02-02 - + 在 macOS Sierra 透過 Wine 執行日文 Windows 遊戲 @@ -169,7 +169,7 @@

2017

2017-01-18 - + Super Mario Run @@ -183,7 +183,7 @@

2016

2016-10-23 - + 電玩開發者的浪漫求婚 @@ -194,7 +194,7 @@

2016

2016-07-14 - + Unity 2D 繪圖最佳化概論 @@ -205,7 +205,7 @@

2016

2016-06-18 - + Android GPU Profiler @@ -216,7 +216,7 @@

2016

2016-06-11 - + Unity 手機遊戲最佳化雜談 – 內建 Profiling 工具 @@ -227,7 +227,7 @@

2016

2016-06-06 - + ADB TCP Mode @@ -238,7 +238,7 @@

2016

2016-06-05 - + Unity 手機遊戲最佳化雜談 – 概論 @@ -249,7 +249,7 @@

2016

2016-04-23 - + 為什麼要參加 Game Developers Conference @@ -260,21 +260,54 @@

2016

2016-03-19 - + Game Developers Conference + +
+ + 2016-02-15 + + + + 修復 Apple 開發憑證 + + +
+ +
+ + 2016-01-05 + + + + Unity 的 foreach + + +

2015

+
+ + 2015-12-09 + + + + Unity CrashReport + + +
+
2015-11-07 - + Unity on iOS9 @@ -285,7 +318,7 @@

2015

2015-11-01 - + Unity 在 Android 6.0 (Android M) 的權限問題 @@ -296,7 +329,7 @@

2015

2015-09-26 - + 使用 PostProcessBuild 設定 Unity 產生的 Xcode Project @@ -307,7 +340,7 @@

2015

2015-07-26 - + 一個龜兔賽跑(?)的寓言 @@ -318,7 +351,7 @@

2015

2015-07-05 - + 第一步 @@ -329,7 +362,7 @@

2015

2015-06-23 - + Extra Credits – 前期準備的問題 @@ -340,7 +373,7 @@

2015

2015-02-04 - + Extra Credits – 做出你的第一個遊戲: 最小可行產品 @@ -354,7 +387,7 @@

2014

2014-11-06 - + New Day, New Life @@ -365,7 +398,7 @@

2014

2014-10-28 - + 搬家 @@ -379,7 +412,7 @@

2013

2013-02-20 - + 所以你想出國唸遊戲程式設計… @@ -393,7 +426,7 @@

2012

2012-10-20 - + Awkward silence @@ -404,7 +437,7 @@

2012

2012-09-16 - + Hello world! @@ -415,7 +448,7 @@

2012

2012-08-22 - + 荒野工程師求生秘笈(二) @@ -426,7 +459,7 @@

2012

2012-08-22 - + 荒野中的工程師求生記錄(一) @@ -437,7 +470,7 @@

2012

2012-02-19 - + Bet on it @@ -451,7 +484,7 @@

2011

2011-12-17 - + One and half year passed. And you should never look back. @@ -462,7 +495,7 @@

2011

2011-09-16 - + 求學經驗 @@ -473,7 +506,7 @@

2011

2011-07-13 - + 所以 Bug 要怎麼 De @@ -484,7 +517,7 @@

2011

2011-07-12 - + 這個國家的學生都在做甚麼呢? @@ -495,7 +528,7 @@

2011

2011-07-12 - + 跟老師們的面談 July 2011 @@ -506,7 +539,7 @@

2011

2011-05-18 - + Pittsburgh 行 @@ -517,7 +550,7 @@

2011

2011-04-28 - + Engineering Entrepreneurship @@ -528,7 +561,7 @@

2011

2011-04-04 - + GDC Follow Up @@ -539,7 +572,7 @@

2011

2011-03-15 - + 台灣 Computer Science 教育界的討論 @@ -550,7 +583,7 @@

2011

2011-03-12 - + GDC Day 3 : IGF / GDCA 頒獎典禮 @@ -561,7 +594,7 @@

2011

2011-03-10 - + GDC Day 3 @@ -572,7 +605,7 @@

2011

2011-03-10 - + GDC Day 1~2 @@ -583,7 +616,7 @@

2011

2011-03-09 - + GDC Prologue @@ -597,7 +630,7 @@

2010

2010-09-02 - + 開學日 @@ -608,7 +641,7 @@

2010

2010-09-02 - + 遠征 diff --git a/index.xml b/index.xml index 7ef8891..f0f48d7 100644 --- a/index.xml +++ b/index.xml @@ -149,6 +149,44 @@ <p>現在是美國西岸的 3/18 星期五的晚上,Game Developer Conference 16 應該是正式的告一段落了。自從回來台灣之後就再也沒回過美國了,自然最近幾屆 GDC 也都沒有參加。今天下午睡覺又被樓上鄰居吵起來之後,想趁這個時間寫寫我自己關於 GDC 的雜談。</p> + + 修復 Apple 開發憑證 + https://chunfuchao.com/posts/apple-worldwide-developer-relations-certificate-fix/ + Mon, 15 Feb 2016 17:15:55 +0000 + + https://chunfuchao.com/posts/apple-worldwide-developer-relations-certificate-fix/ + 2/14 過後,舊有的 WWDR (Worldwide Developer Relations) 憑證就失效了。因為所有開發用的憑證使用的 issuer 都是這張憑證,所以現在你的開發憑證應該會長這樣(This certificate has an invalid issuer + + + + Unity 的 foreach + https://chunfuchao.com/posts/unity-foreach/ + Tue, 05 Jan 2016 11:38:43 +0000 + + https://chunfuchao.com/posts/unity-foreach/ + <p><strong>Update 8/10 2016 : Unity 5.3.5p8 導入了 Mono Compiler 的初步更新解決了這個問題,如果你的專案可以升級到 5.3.6 或是 5.4 之後的版本的話以下描述的問題就不會再發生了。</strong></p> +<p><strong>官方公告:</strong></p> +<p><strong><a href="https://forum.unity.com/threads/upgraded-c-compiler-on-5-3-5p8.417363/">https://forum.unity.com/threads/upgraded-c-compiler-on-5-3-5p8.417363/</a></strong></p> +<p>因為最近有討論區的朋友提到 foreach 的 Garbage Collection 問題,所以想寫一篇為什麼 foreach 會有 Garbage Collection 的文章。這篇文章比較無趣一些,TD;LR 的話就是問題是 <code>IDisposable</code> 不是 <code>IEnumerator&lt;T&gt;</code>。</p> + + + + Unity CrashReport + https://chunfuchao.com/posts/unity-crash-report/ + Wed, 09 Dec 2015 15:37:12 +0000 + + https://chunfuchao.com/posts/unity-crash-report/ + <p>之前一直苦於收到客服信說遊戲閃退了,但是沒有什麼研究資料完全推斷不出到底發生什麼事情的窘況。雖然 Google Play 跟 iTunes Connect 後台會收集 Crash Dump,但是一個是收集 Java 一個是 il2cpp 看到也不知道對應到腳本的哪裡,沒有什麼實用價值。</p> +<p>在 Google 的時候看到很多做 App 的人在推 Crashlytics ,不過 Crashlytics for Unity 還在 beta 然後我的測試資格一直沒下來。這禮拜不經意看到有人提到 Unity CrashReport API,試用了一下覺得不難整合,在這裡分享一下心得。</p> +<h1 id="heading">注意事項:</h1> +<ol> +<li>之前有人回報安裝 CrashReport 後遊戲會在初始時閃退,官方在論壇上說已經修正。但是最近被人在 5.2.3 上面重開 issue ,如果不放心的話可能要再觀察一下。相關討論在:<br> +<a href="http://forum.unity3d.com/threads/crash-initializing-the-reporting-system-on-android.311618/">http://forum.unity3d.com/threads/crash-initializing-the-reporting-system-on-android.311618/</a></li> +<li>目前不支援以 il2cpp 編譯的 iOS ,il2cpp 編譯的版本一遇到 unhandled exception 就會閃退讓 Crash Report 沒時間上傳。我自己有實驗過拿 Mono 編譯的可以上傳,但是 Mono 根本就不能上架 App Store。所以這篇文章先不會介紹 iOS 上面的設定,等到 Unity 官方解決問題後再說。相關討論在:<br> +<a href="http://forum.unity3d.com/threads/getting-reports-on-android-but-not-ios.368421/">http://forum.unity3d.com/threads/getting-reports-on-android-but-not-ios.368421/</a></li> +</ol> + + Unity on iOS9 https://chunfuchao.com/posts/unity-on-ios9/ diff --git a/posts/apple-worldwide-developer-relations-certificate-fix/index.html b/posts/apple-worldwide-developer-relations-certificate-fix/index.html new file mode 100644 index 0000000..44328f4 --- /dev/null +++ b/posts/apple-worldwide-developer-relations-certificate-fix/index.html @@ -0,0 +1,188 @@ + + + + + + 修復 Apple 開發憑證 - Northern Wind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+ +
+ + +
+
+
+
+
+

2/14 過後,舊有的 WWDR (Worldwide Developer Relations) 憑證就失效了。因為所有開發用的憑證使用的 issuer 都是這張憑證,所以現在你的開發憑證應該會長這樣(This certificate has an invalid issuer):

+

Invalid Issuer

+

修復方式是刪除舊的 WWDR 憑證,然後安裝新的 WWDR 憑證,新的憑證可以在這裡找到:
+https://developer.apple.com/support/certificates/expiration/

+

所有人應該都會有這張舊的 WWDR 憑證,但是我在一些機器上找不到,後來發現原因有兩個:

+
    +
  1. 它不一定在 login keychain 裡面
  2. +
  3. 你的 Keychain Access 可能被設定成隱藏過期的憑證
  4. +
+

解除隱藏的選項在:View / Show Expired Certificates

+

Show Expired Certificates

+

過期的 WWDR 現在看應該會長這樣,這台機器上是被放到 System keychain:

+

Expired Certificate

+

刪除、安裝新的憑證即可解決問題。

+

參考資料:

+

http://stackoverflow.com/questions/35390072/this-certificate-has-an-invalid-issuer-apple-push-services/35400712#35400712

+ +
+
+
+ + + + + + + + +
+
+ +
+ + + +
+ +
+ +
+
+ + + + + + + + + + + + + + diff --git a/posts/index.html b/posts/index.html index a3f3751..7b51497 100644 --- a/posts/index.html +++ b/posts/index.html @@ -265,10 +265,43 @@

2016

+ +
+ + 02-15 + + + + 修復 Apple 開發憑證 + + +
+ +
+ + 01-05 + + + + Unity 的 foreach + + +

2015

+
+ + 12-09 + + + + Unity CrashReport + + +
+
11-07 diff --git a/posts/index.xml b/posts/index.xml index e2b1985..518faf4 100644 --- a/posts/index.xml +++ b/posts/index.xml @@ -149,6 +149,44 @@ <p>現在是美國西岸的 3/18 星期五的晚上,Game Developer Conference 16 應該是正式的告一段落了。自從回來台灣之後就再也沒回過美國了,自然最近幾屆 GDC 也都沒有參加。今天下午睡覺又被樓上鄰居吵起來之後,想趁這個時間寫寫我自己關於 GDC 的雜談。</p> + + 修復 Apple 開發憑證 + https://chunfuchao.com/posts/apple-worldwide-developer-relations-certificate-fix/ + Mon, 15 Feb 2016 17:15:55 +0000 + + https://chunfuchao.com/posts/apple-worldwide-developer-relations-certificate-fix/ + 2/14 過後,舊有的 WWDR (Worldwide Developer Relations) 憑證就失效了。因為所有開發用的憑證使用的 issuer 都是這張憑證,所以現在你的開發憑證應該會長這樣(This certificate has an invalid issuer + + + + Unity 的 foreach + https://chunfuchao.com/posts/unity-foreach/ + Tue, 05 Jan 2016 11:38:43 +0000 + + https://chunfuchao.com/posts/unity-foreach/ + <p><strong>Update 8/10 2016 : Unity 5.3.5p8 導入了 Mono Compiler 的初步更新解決了這個問題,如果你的專案可以升級到 5.3.6 或是 5.4 之後的版本的話以下描述的問題就不會再發生了。</strong></p> +<p><strong>官方公告:</strong></p> +<p><strong><a href="https://forum.unity.com/threads/upgraded-c-compiler-on-5-3-5p8.417363/">https://forum.unity.com/threads/upgraded-c-compiler-on-5-3-5p8.417363/</a></strong></p> +<p>因為最近有討論區的朋友提到 foreach 的 Garbage Collection 問題,所以想寫一篇為什麼 foreach 會有 Garbage Collection 的文章。這篇文章比較無趣一些,TD;LR 的話就是問題是 <code>IDisposable</code> 不是 <code>IEnumerator&lt;T&gt;</code>。</p> + + + + Unity CrashReport + https://chunfuchao.com/posts/unity-crash-report/ + Wed, 09 Dec 2015 15:37:12 +0000 + + https://chunfuchao.com/posts/unity-crash-report/ + <p>之前一直苦於收到客服信說遊戲閃退了,但是沒有什麼研究資料完全推斷不出到底發生什麼事情的窘況。雖然 Google Play 跟 iTunes Connect 後台會收集 Crash Dump,但是一個是收集 Java 一個是 il2cpp 看到也不知道對應到腳本的哪裡,沒有什麼實用價值。</p> +<p>在 Google 的時候看到很多做 App 的人在推 Crashlytics ,不過 Crashlytics for Unity 還在 beta 然後我的測試資格一直沒下來。這禮拜不經意看到有人提到 Unity CrashReport API,試用了一下覺得不難整合,在這裡分享一下心得。</p> +<h1 id="heading">注意事項:</h1> +<ol> +<li>之前有人回報安裝 CrashReport 後遊戲會在初始時閃退,官方在論壇上說已經修正。但是最近被人在 5.2.3 上面重開 issue ,如果不放心的話可能要再觀察一下。相關討論在:<br> +<a href="http://forum.unity3d.com/threads/crash-initializing-the-reporting-system-on-android.311618/">http://forum.unity3d.com/threads/crash-initializing-the-reporting-system-on-android.311618/</a></li> +<li>目前不支援以 il2cpp 編譯的 iOS ,il2cpp 編譯的版本一遇到 unhandled exception 就會閃退讓 Crash Report 沒時間上傳。我自己有實驗過拿 Mono 編譯的可以上傳,但是 Mono 根本就不能上架 App Store。所以這篇文章先不會介紹 iOS 上面的設定,等到 Unity 官方解決問題後再說。相關討論在:<br> +<a href="http://forum.unity3d.com/threads/getting-reports-on-android-but-not-ios.368421/">http://forum.unity3d.com/threads/getting-reports-on-android-but-not-ios.368421/</a></li> +</ol> + + Unity on iOS9 https://chunfuchao.com/posts/unity-on-ios9/ diff --git a/posts/unity-crash-report/index.html b/posts/unity-crash-report/index.html new file mode 100644 index 0000000..32e37ac --- /dev/null +++ b/posts/unity-crash-report/index.html @@ -0,0 +1,231 @@ + + + + + + Unity CrashReport - Northern Wind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+ +
+ + +
+
+
+
+
+

之前一直苦於收到客服信說遊戲閃退了,但是沒有什麼研究資料完全推斷不出到底發生什麼事情的窘況。雖然 Google Play 跟 iTunes Connect 後台會收集 Crash Dump,但是一個是收集 Java 一個是 il2cpp 看到也不知道對應到腳本的哪裡,沒有什麼實用價值。

+

在 Google 的時候看到很多做 App 的人在推 Crashlytics ,不過 Crashlytics for Unity 還在 beta 然後我的測試資格一直沒下來。這禮拜不經意看到有人提到 Unity CrashReport API,試用了一下覺得不難整合,在這裡分享一下心得。

+

注意事項:

+
    +
  1. 之前有人回報安裝 CrashReport 後遊戲會在初始時閃退,官方在論壇上說已經修正。但是最近被人在 5.2.3 上面重開 issue ,如果不放心的話可能要再觀察一下。相關討論在:
    +http://forum.unity3d.com/threads/crash-initializing-the-reporting-system-on-android.311618/
  2. +
  3. 目前不支援以 il2cpp 編譯的 iOS ,il2cpp 編譯的版本一遇到 unhandled exception 就會閃退讓 Crash Report 沒時間上傳。我自己有實驗過拿 Mono 編譯的可以上傳,但是 Mono 根本就不能上架 App Store。所以這篇文章先不會介紹 iOS 上面的設定,等到 Unity 官方解決問題後再說。相關討論在:
    +http://forum.unity3d.com/threads/getting-reports-on-android-but-not-ios.368421/
  4. +
+

需要元件

+
    +
  1. Unity 5 Pro License
    +雖然 Unity 4 也可以接 Crash Report ,但好像後台申請要 5 的 License
  2. +
  3. 對應手機平台的 Pro License
  4. +
+

首先先用你的 Unity 帳號登入:

+

https://perf.cloud.unity3d.com

+

登入後會看到歡迎頁面,點 Create New Project 開始

+

Create New Project

+

創完 Project 之後點進去選擇 Activate Game Performance

+

Activate Game Performance

+

一開始沒有資料的狀態長這樣:

+

Getting Started

+

Update: Unity 5.4 之後 Crash Reporting 已經是 Unity Game Performance Reporting Service 的一部分,不需要再安裝這個 Package ,而是從 Unity Service Menu 直接開啟即可。如果先前有安裝的要移除掉否則會發生衝突。Unity Game Performance Reporting Service 的說明請參考:

+

http://unity3d.com/cn/services/performance-reporting

+

選擇 Getting Started 之後會有安裝教學。應該只有 Unity 4 需要安裝那個 Package ,Unity 5 的 UnityEngine namespace 已經有定義 CrashReport 。依照 Unity 寫的教學,在遊戲初始化的地方呼叫 CrashReporting.Init 填入 UPID 。版本號可以不填但是應該要填,不填的話所有版本的資料都會混在一起。

+

Install

+

然後就可以試著會爆炸的 code 推到 Android 機器上面實驗,可以故意弄出 NullReferenceException 或是直接 throw new Exception,實驗成功的話應該會看到像這樣:

+

Exception

+

包含 Exception 內容,C# 的 Stack Trace ,我們設定的版本號,機器種類跟發生次數的資料都有,這樣子以後要 debug 就不會那麼鬼打牆了。

+

可惜的是目前 iOS 還不能用,到 iOS 能用的時候我會再發 iOS 版的教學。如果想要追蹤這個功能的最新情報,官方的 FAQ thread 在這裡:

+

http://forum.unity3d.com/threads/game-performance-reporting-preview-faq.305997/#post-2156685

+
+
+
+ + + + + + + + +
+
+ +
+ + + +
+ +
+ +
+
+ + + + + + + + + + + + + + diff --git a/posts/unity-foreach/index.html b/posts/unity-foreach/index.html new file mode 100644 index 0000000..dd14807 --- /dev/null +++ b/posts/unity-foreach/index.html @@ -0,0 +1,353 @@ + + + + + + Unity 的 foreach - Northern Wind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+ +
+ + +
+
+
+
+
+

Update 8/10 2016 : Unity 5.3.5p8 導入了 Mono Compiler 的初步更新解決了這個問題,如果你的專案可以升級到 5.3.6 或是 5.4 之後的版本的話以下描述的問題就不會再發生了。

+

官方公告:

+

https://forum.unity.com/threads/upgraded-c-compiler-on-5-3-5p8.417363/

+

因為最近有討論區的朋友提到 foreach 的 Garbage Collection 問題,所以想寫一篇為什麼 foreach 會有 Garbage Collection 的文章。這篇文章比較無趣一些,TD;LR 的話就是問題是 IDisposable 不是 IEnumerator<T>

+

Garbage Collection

+

Unity 在使用 foreach 的時候會產生 24 bytes 的 GC 這個問題已經傳很久了。可以用個簡單的小程式去測試:

+
+ +
+
1
+2
+3
+4
+5
+6
+7
+8
+
+
class ForEachTest : MonoBehaviour
+{
+   private readonly List<int> list = new List<int> { 1, 2, 3 };
+   void Update()
+   {
+       foreach (var element in list) { }
+   }
+}
+
+
+

隨便掛在一個 GameObject 下面的執行結果,在 Unity 4.7.0f1

+

Unity 4.7

+

現在最新的 Unity 5.3.1f1 上面的結果好像更糟了:

+

Unity 5

+

兇手是誰?

+

我一直以為是因為 System.Collections.Generic 底下所有的容器的 Enumerator 都被宣告成 struct ,然後 foreach 在操作的時候卻是對 IEnumerator<T> 操作 IEnumerator<T>.Current 跟 IEnumerator<T>.MoveNext() 造成了 boxing 。這周末心血來潮把 Unity 建置出來的 dll 放進 ILSpy 裡面看看,才發現以往的認知是錯的。

+
+

System.Collections.Generic 底下所有的容器的 Enumerator 都被宣告成 struct 的原因可以看 Eric Lippert(C# Compiler Team 的成員的解釋) :
+http://stackoverflow.com/questions/3168311/why-do-bcl-collections-use-struct-enumerators-not-classes/3168435#3168435
+基本上是效能考量

+
+

以下是範例程式

+
+ +
+
1
+2
+3
+4
+5
+
+
List<int> list = new List<int> { 1, 2, 3 };
+foreach(var item in list)
+{
+    Debug.Log(item);
+}
+
+
+

ILSpy 反組譯的結果

+
+ +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+
+
List<int> list = new List<int>();
+list.Add(1);
+list.Add(2);
+list.Add(3);
+List<int> list2 = list;
+using (List<int>.Enumerator enumerator = list2.GetEnumerator())
+{
+    while (enumerator.MoveNext())
+    {
+        int current = enumerator.get_Current();
+        Debug.Log(current);
+    }
+}
+
+
+

可以看到實際上 Unity 其實正確地使用 List<int>.Enumerator 來承接 list.GetEnumerator() 的回傳值。所以那個 boxing 到底在哪裡呢?

+

有了這條線索後,Google 了一下發現已經有人找到了真正的問題。

+

https://www.reddit.com/r/Unity3D/comments/34s0je/c_memory_and_performance_tips_for_unity/cqyf5yk/

+

要看到問題要把 ILSpy 的展示模式從 C# 換成 IL 模式。

+
+ +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
+
IL_001e: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
+IL_0023: stloc.2
+.try
+{
+    IL_0024: br IL_003c
+    // loop start (head: IL_003c)
+        IL_0029: ldloca.s 2
+        IL_002b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
+        IL_0030: stloc.1
+        IL_0031: ldloc.1
+        IL_0032: box [mscorlib]System.Int32
+        IL_0037: call void [UnityEngine]UnityEngine.Debug::Log(object)
+        IL_003c: ldloca.s 2
+        IL_003e: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
+        IL_0043: brtrue IL_0029
+    // end loop
+    IL_0048: leave IL_0059
+} // end .try
+finally
+{
+    IL_004d: ldloc.2
+    IL_004e: box valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
+    IL_0053: callvirt instance void [mscorlib]System.IDisposable::Dispose()
+    IL_0058: endfinally
+} // end handler
+
+
+

可以看到 box 出現在 IL_004e 行 finally 區塊裡,結果是舊版的 Mono 對有實作 IDisposable 的 struct 呼叫 Dispose 的時候(using 關鍵字觸發的)用了 IDisposable 去 box ,這跟我之前以為的不一樣。

+

然後更冤的可以看一下 List<T>.Enumerator 的 Dispose 實作:

+

http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,d3661cf752ff3f44

+

因為 List<T>.Enumerator 是 value type ,所以根本就不需要特別處理。這個 Dispose 是空函式,整個 boxing 是 100% 的浪費。

+

Mono 對於這個 bug 的 issue 在這裡:

+

https://bugzilla.novell.com/show_bug.cgi?id=571010

+

可以看到  Mono 本家已經在 2010 6/1 修正了了這個問題,但是 Unity 還是沒有 merge 這個修正。考慮到 Unity 自己有 Mono 的 fork (https://github.com/Unity-Technologies/mono),很有可能 Unity 有對 Mono 做修改,改動到現在合併有困難。否則大家喊很久的 Mono 升級或是改用 Roslyn ,為什麼 Unity 一直無法從善如流。

+

我自己對於 foreach 的態度就是雖然效能較差還有少量 GC 問題,但是做取捨我還是會選 foreach 取其可讀性。要小心的是如果 foreach 放在其他的 loop 裡面的情況,累積起來還是有可能會造成問題。

+

參考資料:

+

C# memory and performance tips for Unity

+

原文:

+

http://www.somasim.com/blog/2015/04/csharp-memory-and-performance-tips-for-unity/

+

Reddit 討論:

+

https://www.reddit.com/r/Unity3D/comments/34s0je/c_memory_and_performance_tips_for_unity/

+

C# Memory Management for Unity Developers (part 1 of 3)

+

https://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php

+

Why do BCL Collections use struct enumerators, not classes?

+

http://stackoverflow.com/questions/3168311/why-do-bcl-collections-use-struct-enumerators-not-classes/3168435#3168435

+

ILSpy

+

http://ilspy.net/

+
+
+
+ + + + + + + + +
+
+ +
+ + + +
+ +
+ +
+
+ + + + + + + + + + + + + + diff --git a/sitemap.xml b/sitemap.xml index 1469774..539ecd9 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -86,6 +86,21 @@ 2016-03-19T11:00:02+00:00 + + https://chunfuchao.com/posts/apple-worldwide-developer-relations-certificate-fix/ + 2016-02-15T17:15:55+00:00 + + + + https://chunfuchao.com/posts/unity-foreach/ + 2016-01-05T11:38:43+00:00 + + + + https://chunfuchao.com/posts/unity-crash-report/ + 2015-12-09T15:37:12+00:00 + + https://chunfuchao.com/posts/unity-on-ios9/ 2015-11-07T16:37:30+00:00