2022年Unity 面试题 |五萬字 二佰道| Unity面试题大全,面试题总结【全网最全,收藏一篇足够面试】
目錄
- 📢前言
- 🎬Unity面試題大全
- ??C#基礎
- 1. 重載和重寫的區別
- 2.面向對象的三大特點
- 3.簡述值類型和引用類型有什么區別
- 4.請簡述private,public,protected,internal的區別
- 5.C#中所有引用類型的基類是什么
- 6.請簡述ArrayList和 List的主要區別
- 7.請簡述GC(垃圾回收)產生的原因,并描述如何避免?
- 8. 請描述Interface與抽象類之間的不同
- 9.請簡述關鍵字Sealed用在類聲明和函數聲明時的作用
- 10. 反射的實現原理?
- 11. .Net與 Mono 的關系?
- 12. 在類的構造函數前加上static會報什么錯?為什么?
- 13.C# String類型比 stringBuilder 類型的優勢是什么?
- 14.C#函數 Func(string a, string b)用 Lambda 表達式怎么寫?
- 15. 數列1,1,2,3,5,8,13...第 n 位數是多少?用 C#遞歸算法實現
- 16. 冒泡排序(手寫代碼)
- 17. C#中有哪些常用的容器類,各有什么特點。
- 18. C#中常規容器和泛型容器有什么區別,哪種效率高?
- 19. 有哪些常見的數值類?
- 20. C#中委托 和 接口有什么區別?各用在什么場合?
- 21. C#中unsafe關鍵字是用來做什么的?什么場合下使用?
- 22. C#中ref和out關鍵字有什么區別?
- 23. For,foreach,Enumerator.MoveNext的使用,與內存消耗情況
- 24. 函數中多次使用string的+=處理,會產生大量內存垃圾(垃圾碎片),有什么好的方法可以解決。
- 25. 當需要頻繁創建使用某個對象時,有什么好的程序設計方案來節省內存?
- 26. JIT和AOT區別
- 27. 給定一個存放參數的數組,重新排列數組
- 28. Foreach循環迭代時,若把其中的某個元素刪除,程序報錯,怎么找到那個元素?以及具體怎么處理這種情況?(注:Try.....Catch捕捉異常,發送信息不可行)
- 29. GameObject a=new GameObject() GameObject b=a 實例化出來了A,將A賦給B,現在將B刪除,問A還存在嗎?
- 30. C#中 委托和事件的區別
- 31. 結構體和類有何區別?
- 32. C#的委托是什么?有何用處?
- 33. foreach迭代器遍歷和for循環遍歷的區別
- 34. C#和C++的區別?
- 35. C#引用和C++指針的區別
- 36. 堆和棧的區別?
- 37. Heap與Stack有何區別?
- 38. Mock和Stub有何區別?
- 39. 為什么dynamic font 在 unicode環境下優于 staticfont(字符串編碼)
- 40. 簡述StringBuilder和String的區別?(字符串處理)
- 41. string、stringBuilder、stringBuffer
- 42. 字典Dictionary的內部實現原理
- 43. 泛型是什么
- 44. Mathf.Round和Mathf.Clamp和Mathf.Lerp含義?
- 45. 能用foreach遍歷訪問的對象需要實現______接?或聲明_________?法的類型(C#遍歷)
- 46. 什么是里氏替換原則?(C#多態)
- 47. 反射的實現原理?
- 48. 概述c#中代理和事件?
- 49. 哈希表與字典對比
- 50. C#中四種訪問修飾符是哪些?各有什么區別?
- 51. 下列代碼在運行中會發生什么問題?如何避免?
- 52. 什么是裝箱拆箱,怎樣減少操作
- 53. MVC
- 🧡Unity基礎知識
- 1. Image和RawImage的區別
- 2. Unity3D中的碰撞器和觸發器的區別?
- 3. 物體發生碰撞的必要條件?
- 4. 簡述四元數Quaternion的作用,四元數對歐拉角的優點?
- 5. 如何安全的在不同工程間安全地遷移asset數據?三種方法
- 6. OnEnable、Awake、Start運行時的發生順序?哪些可能在同一個對象周期中反復的發生?
- 7. MeshRender中material和sharedmaterial的區別?
- 8. TCP/IP協議棧各個層次及分別的功能?
- 9. Unity提供了幾種光源,分別是什么?
- 10. 簡述一下對象池,你覺得在FPS里哪些東西適合使用對象池?
- 11. CharacterController和Rigidbody的區別?
- 12. 移動相機動作在哪個函數里,為什么在這個函數里?
- 13. 簡述prefab的用處
- 14. GPU的工作原理?
- 15. 什么是渲染管道?
- 16. 如何優化內存?
- 18. 動態加載資源的方式?
- 19. 使用Unity3d實現2d游戲,有幾種方式?
- 20. 在物體發生碰撞的整個過程中,有幾個階段,分別列出對應的函數 三個階段
- 21. Unity3d的物理引擎中,有幾種施加力的方式,分別描述出來
- 22. 什么叫做鏈條關節?
- 23. 物體自身旋轉使用的函數?
- 24. Unity3d提供了一個用于保存和讀取數據的類(PlayerPrefs),請列出保存和讀取整形數據的函數
- 25. Unity3d腳本從喚醒到銷毀有著一套比較完整的生命周期,請列出系統自帶的幾個重要的方法。
- 26. 物理更新一般放在哪個系統函數里?
- 27. 在場景中放置多個Camera并同時處于活動狀態會發生什么?
- 28. 如何銷毀一個UnityEngine.Object及其子類?
- 29. 請描述游戲動畫有哪幾種,以及其原理?
- 30. 請描述為什么Unity3d中會發生在組件上出現數據丟失的情況
- 31. alpha blend工作原理?
- 32. 寫出光照計算中的diffuse的計算公式?
- 33. LOD是什么,優缺點是什么?
- 33. 兩種陰影判斷的方法、工作原理?
- 34. Vertex Shader是什么,怎么計算?
- 35. MipMap是什么,作用?
- 36. 請描述Interface與抽象類之間的不同
- 37. .Net與Mono的關系?
- 38. 簡述Unity3D支持的作為腳本的語言的名稱?
- 39. Unity3D是否支持寫成多線程程序?如果支持的話需要注意什么?
- 40. 如何讓已經存在的GameObject在LoadLevel后不被卸載掉?
- 41. U3D中用于記錄節點空間幾何信息的組件名稱,及其父類名稱
- 42. 向量的點乘、叉乘以及歸一化的意義?
- 43. 矩陣相乘的意義及注意點?
- 44. 當一個細小的高速物體撞向另一個較大的物體時,會出現什么情況?如何避免?
- 45. 為何大家都在移動設備上尋求U3D原生GUI的替代方案
- 46. 請簡述如何在不同分辨率下保持UI的一致性
- 47. 請簡述OnBecameVisible及OnBecameInvisible的發生時機,以及這一對回調函數的意義?
- 48. 什么叫動態合批?跟靜態合批有什么區別?
- 49. Unity提供了幾種光源,分別是什么?
- 50. 什么是LightMap?
- 51. Unity和cocos2d的區別
- 52. Unity3D Shader分哪幾種,有什么區別?
- 53. 獲取、增加、刪除組件的命令分別是什么?
- 54. Unity中,照相機的Clipping Planes的作用是什么?調整 Near、Far兩個值時,應該注意什么?
- 55. 簡述prefab的用處
- 56. 請描述為什么Unity3d中會發生 在組件上出現數據丟失的情況
- 57. 如何在Unity3D中查看場景的面數,頂點數和Draw Call數?如何降低Draw Call數?
- 58. 請問alpha test在何時使用?能達到什么效果?
- 60. 四元數有什么作用?
- 61. 將Camera組件的ClearFlags選項選成Depth only是什么意思?有何用處?
- 62. 如何讓已經存在的GameObject在LoadLevel后不被卸載掉?
- 63. 在編輯場景時將GameObject設置為Static有何作用?
- 64. 有A和B兩組物體,有什么辦法能夠保證A組物體永遠比B組物體先渲染?
- 65. 將圖片的TextureType選項分別選為Texture和Sprite有什么區別
- 66. 問一個Terrain,分別貼3張,4張,5張地表貼圖,渲染速度有什么區別?為什么?
- 67. 什么是DrawCall?DrawCall高了又什么影響?如何降低DrawCall?
- 68. 實時點光源的優缺點是什么?
- 69. 簡述四元數的作用,四元數對歐拉?的優點?
- 70. Addcomponent后哪個生命周期函數會被調用
- 72. 層剔除
- 73. 分別解釋頂點著色器和像素著色器是什么
- 74. 畫布的三種模式.縮放模式
- 75. FSM有限狀態機
- 76. 使用過哪些Unity插件
- 💛物理系統
- 1. CharacterController和Rigidbody的區別
- 2. 射線檢測碰撞物的原理是?
- 3. 什么叫做鏈條關節?
- 4. 物體發生碰撞的必要條件?
- 5. 在物體發生碰撞的整個過程 中,有幾個階段,分別列出對 應的函數 三個階段
- 6. Unity3d中的碰撞器和觸發器的 區別?
- 7. 射線檢測碰撞物的原理是?
- 8. Unity3d的物理引擎中,有幾種 施加力的方式,分別描述出來
- 9. 當一個細小的高速物體撞向另一個較大的物體時,會出現什么情況?如何避免?
- 10. 射線Raycast原理
- 💚UI & 2D 部分
- 1. UGUI 合批的一些問題
- 2. Image和RawImage的區別
- 3. 使用Unity3d實現2d游戲,有幾種方式?
- 4. 將圖片的TextureType選項分別選為Texture和Sprite有什么區別
- 5. 請簡述如何在不同分辨率下保 持UI的一致性
- 💙動畫系統
- 1. 請描述游戲動畫有哪幾種,以及其原理?
- 2. Avator的作用
- 3. 反向旋轉動畫的方法是什么?
- 4. Animation.CrossFade 是什么?
- 5. 寫出 Animation 的五個方法
- 6. 簡述 SkinnedMesh 的實現原理
- 7. 動畫層(Animation Layers)的作用是什么?
- 💜協程
- 1. Unity 協程 Coroutine 的作用
- 2. 什么是協同程序?
- 3. Unity3D的協程和C#線程 之間的區別是什么?
- 4. 協同程序的執行代碼是什么?有何用處,有何缺點?
- 🤎數據持久化 & 資源管理
- 1. unity常用資源路徑有哪些
- 2. 如何安全的在不同工程間安全 地遷移asset數據?三種方法
- 3. unity 提供了一個用于保存讀取數據的類,(playerPrefs),請列出保存讀取整形數據的函數
- 4. 動態加載資源的方式?
- 5. AssetsBundle 打包
- 6. AssetBundle加載
- 7. AssetBundle卸載流程
- 🖤Lua語言和Xlua熱更
- 1. Lua如何調用C#
- 2. 資源如何打包?依賴項列表如何生成?
- 3. 如何解析版本文件?如何加載AB包資源?具體流程是怎么樣的?
- 4. 熱更新方案有哪些?以及具體熱更流程
- 5. 簡述Lua實現面向對象的原理
- 6. 簡述Lua有哪8個類型?簡述用途
- 🤍網絡
- 1. 客戶端與服務器交互方式有幾種?
- 2. 概述序列化
- 3. UDP/TCP含義,區別
- 4. TCP/IP協議棧各個層次及分別的功能?
- 5. 寫出WWW的幾個方法
- 6. Socket粘包
- 7. Socket的封包、拆包
- 8. Socket 客戶端 隊列 的問題
- 💖渲染 & Shader
- 1. 什么是LightMap?
- 2. MipMap是什么,作用?
- 3. 請問alpha test在何時使用?能達到什么效果?
- 4. 一個Terrain,分別貼3張,4張,5張地表貼圖,渲染速度有什么區別?為什么?
- 5. 實時點光源的優缺點是什么?
- 6. 簡述水面倒影的渲染原理?
- 7. MeshRender中material和 sharedmaterial的區別?
- 8. 什么是渲染管道?
- 9. 如何在Unity3D中查看場景的面數,頂點數和DrawCall數?如何降低DrawCall數?
- 10. 寫出光照計算中的diffuse的計算公式
- 11. 兩種陰影判斷的方法、工作原理。
- 12. 有A和B兩組物體,有什么辦法能夠保證A組物體永遠比B組物體先渲染?
- 13. Unity的Shader中,Blend SrcAlpha OneMinusSrcAlpha這句話是什么意思?
- 14. Vertex Shader是什么,怎么計算?
- 15. Unity3D Shader分哪?種,有什么區別?
- 💘優化部分
- 1. 簡述?下對象池,你覺得在FPS里哪些東西適合使用對象池?
- 2. 什么是DrawCall?DrawCall高了又什么影響?如何降低DrawCall?
- 3. UI優化小知識
- 4. LOD是什么,優缺點是什么?
- 5. 什么叫動態合批?跟靜態合批有什么區別?
- 6. 如何優化內存?
- 7. 請簡述GC(垃圾回收)產生的原因,并描述如何避免?
- 8. 貼圖透明通道分離,壓縮格式設為ETC/PVRTC
- 9. 關閉貼圖的讀寫選項
- 10. Unity 在移動設備上的?些優化資源的方法
- 11. CPU端性能優化小知識點
- 12. GPU端性能優化小知識點
- 13. 內存優化小知識點
- 💞算法
- 1. 請寫出求斐波那契數列任意一位的值得算法
- 2. 下列代碼在運行中會產生幾個臨時對象?
- 3. 冒泡排序(手寫代碼)
- 👥總結
📢前言
- 正所謂 金三銀四 ,又到了找工作的大好時機了,不知道大家有沒有意向找一份更好的工作呢~
- 之前寫了很多Unity的學習和實例文章,但是面試題部分還沒有一個系統的整理。
- 那本篇文章就來整理一下Unity中一些常見的面試題,說不準就會面試的時候就會遇到!
- 本篇文章會將Unity所有方面的面試資料都融會貫通,絕對是2022年Unity面試領域最實用的文章啦!
- 為了方便大家可以重點復習某個方面,所以大致分為下面幾個模塊方便學習
- 看完記得 點贊 + 收藏 一波哦,過了這村可就找不到這家店了!
- 勵志做2022Unity最全的面試題整理!
本文將整理的面試題大致分為以下幾個模塊,方便針對性學習和背題!
由于大部分常用的面試題在網上基本上已經有比較標準的答案了,所以說面試題類的文章基本上大同小異。
所以本篇文章中的部分內容也是直接從網上摘選來的
如果有不對的地方也歡迎指正(盡力不會出現這種情況),某個模塊的內容不夠也歡迎在評論區指出,我去重新添加上。
- C#基礎
- 計算機基礎
- Unity基礎
- 物理系統
- UI部分 & 2D
- 協程
- 動畫系統
- 數據持久化 & 資源管理
- Lua語言和Xlua熱更
- 網絡
- 渲染 & Shader
- 優化部分
- 算法
本文部分內容參考文章如下:
https://blog.csdn.net/u014361280/article/details/100135129
https://blog.csdn.net/u014361280/article/details/121499143
https://blog.csdn.net/u014361280/article/details/121534764
https://blog.csdn.net/qq_21407523/article/details/108814300
🎬Unity面試題大全
??C#基礎
1. 重載和重寫的區別
2.面向對象的三大特點
3.簡述值類型和引用類型有什么區別
值類型:包含了所有簡單類型(整數、浮點、bool、char)、struct、enum。
繼承自System.ValueTyoe
引用類型包含了string,object,class,interface,delegate,array
繼承自System.Object
變?存放的則是數據的地址,即對象的引?。
型的變量把實際數據的地址保存在堆棧中。
4.請簡述private,public,protected,internal的區別
- public:對任何類和成員都公開,無限制訪問
- private:僅對該類公開
- protected:對該類和其派生類公開
- internal:只能在包含該類的程序集中訪問該類
- protected internal:protected + internal
5.C#中所有引用類型的基類是什么
引用類型的基類是System.Object值類型的基類是 System.ValueType
同時,值類型也隱式繼承自System.Object
6.請簡述ArrayList和 List的主要區別
- ArrayList 不帶泛型 數據類型丟失
- List 帶泛型 數據類型不丟失
- ArrayList 需要裝箱拆箱 List不需要
ArrayList存在不安全類型(ArrayList會把所有插 ?其中的數據都當做Object來處理)裝箱拆箱的 操作(費時)IList是接?,ArrayList是?個實現了 該接?的類,可以被實例化
List類是ArrayList類的泛型等效類。它的大部分用法都與ArrayList相似,因為List類也繼承了IList接口。最關鍵的區別在于,在聲明List集合時,我們同時需要為其聲明List集合內數據的對象類型。
7.請簡述GC(垃圾回收)產生的原因,并描述如何避免?
GC為了避免內存溢出而產生的回收機制
避免:
1)減少 new 產生對象的次數
2)使用公用的對象(靜態成員)
3)將 String 換為 StringBuilder
8. 請描述Interface與抽象類之間的不同
9.請簡述關鍵字Sealed用在類聲明和函數聲明時的作用
類聲明時可防止其他類繼承此類,在方法中聲明則可防止派生類重寫此方法。
10. 反射的實現原理?
可以在加載程序運行時,動態獲取和加載程序集,并且可以獲取到程序集的信息反射即在運行期動態獲取類、對象、方法、對象數據等的一種重要手段
主要使用的類庫:System.Reflection
核心類:
通過以上核心類可在運行時動態獲取程序集中的類,并執行類構造產生類對象,動態獲取對象的字段或屬性值,更可以動態執行類方法和實例方法等。
11. .Net與 Mono 的關系?
.Net是一個語言平臺,Mono為.Net提供集成開發環境,集成并實現了.NET的編譯器、CLR 和基礎類庫,使得.Net既可以運行在windows也可以運行于 linux,Unix,Mac OS 等。
12. 在類的構造函數前加上static會報什么錯?為什么?
構造函數格式為public+類名如果加上 static 會報錯(靜態構造函數不能有訪問、型的對象,靜態構造函數只執行一次;
運行庫創建類實例或者首次訪問靜態成員之前,運行庫調用靜態構造函數;
靜態構造函數執行先于任何實例級別的構造函數;
顯然也就無法使用this和 base 來調用構造函數。
一個類只能有一個靜態函數,如果有靜態變量,系統也會自動生成靜態函數
13.C# String類型比 stringBuilder 類型的優勢是什么?
如果是處理字符串的話,用string中的方法每次都需要創建一個新的字符串對象并且分配新的內存地址,而 stringBuilder 是在原來的內存里對字符串進行修改,所以在字符串處理
方面還是建議用stringBuilder這樣比較節約內存。但是 string 類的方法和功能仍然還是比 stringBuilder 類要強。
string類由于具有不可變性(即對一個 string 對象進行任何更改時,其實都是創建另外一個 string 類的對象),所以當需要頻繁的對一個 string 類對象進行更改的時候,建議使用StringBuilder 類,StringBuilder 類的原理是首先在內存中開辟一定大小的內存空間,當對此 StringBuilder 類對象進行更改時, 如果內存空間大小不夠, 會對此內存空間進行擴充,而不是重新創建一個對象,這樣如果對一個字符串對象進行頻繁操作的時候,不會造成過多的內存浪費,其實本質上并沒有很大區別,都是用來存儲和操作字符串的,唯一的區別就在于性能上。
String主要用于公共 API,通用性好、用途廣泛、讀取性能高、占用內存小。
StringBuilder主要用于拼接 String,修改性能好。
不過現在的編譯器已經把String的 + 操作優化成 StringBuilder 了, 所以一般用String 就可以了
String是不可變的,所以天然線程同步。
StringBuilder可變,非線程同步。
14.C#函數 Func(string a, string b)用 Lambda 表達式怎么寫?
(a,b) => {};15. 數列1,1,2,3,5,8,13…第 n 位數是多少?用 C#遞歸算法實現
public int CountNumber(int num) {if (num == 1 || num == 2) {return 1;} else {return CountNumber(num -1) + CountNumber(num-2);}}16. 冒泡排序(手寫代碼)
public static void BubblingSort(int[]array) {for (int i = 0; i < array.Length; i++){for (int j = array.Length - 1; j > 0; j--){if (array[j] < array[i]) {int temp = array[j];array[j] = array[j-1];array[j - 1] = temp;}}}}17. C#中有哪些常用的容器類,各有什么特點。
List,HashTable,Dictionary,Stack,Queue
- Stack棧:先進后出,入棧和出棧,底層泛型數組實現,入棧動態擴容2倍
- Queue隊列:先進先出,入隊和出隊,底層泛型數組實現,表頭表尾指針,判空還是滿通過size比較
Queue和Stack主要是用來存儲臨時信息的 - Array數組:需要聲明長度,不安全
- ArrayList數組列表:動態增加數組,不安全,實現了IList接口(表示可按照索引進行訪問的非泛型集合對象),Object數組實現
- List列表:底層實現是泛型數組,特性,動態擴容,泛型安全
將泛型數據(對值類型來說就是數據本身,對引用類型來說就是引用)存儲在一個泛型數組中,添加元素時若超過當前泛型數組容量,則以2倍擴容,進而實現List大小動態可變。(注:大小指容量,不是Count) - LinkList鏈表
1、數組和List、ArrayList集合都有一個重大的缺陷,就是從數組的中間位置刪除或插入一個元素需要付出很大的代價,其原因是數組中處于被刪除元素之后的所有元素都要向數組的前端移動。
2、LinkedList(底層是由鏈表實現的)基于鏈表的數據結構,很好的解決了數組刪除插入效率低的問題,且不用動態的擴充數組的長度。
3、LinkedList的優點:插入、刪除元素效率比較高;缺點:訪問效率比較低。 - HashTable哈希表(散列表)
概念:不定長的二進制數據通過哈希函數映射到一個較短的二進制數據集,即Key通過HashFunction函數獲得HashCode
裝填因子:α=n/m=0.72 ,存儲的數據N和空間大小M
然后通過哈希桶算法,HashCode分段,每一段都是一個桶結構,一般是HashCode直接取余。
桶結構會加劇沖突,解決沖突使用拉鏈法,將產生沖突的元素建立一個單鏈表,并將頭指針地址存儲至Hash表對應桶的位置。這樣定位到Hash表桶的位置后可通過遍歷單鏈表的形式來查找元素。
1、Key—Value形式存取,無序,類型Object,需要類型轉換。
2、Hashtable查詢速度快,而添加速度相對慢
3、Hashtable中的數據實際存儲在內部的一個數據桶里(bucket結構體數組),容量固定,根據數組索引獲取值。
性能排序:
- 插入性能: LinkedList > Dictionary > HashTable > List
- 遍歷性能:List > LinkedList > Dictionary > HashTable
- 刪除性能: Dictionary > LinkedList > HashTable > List
18. C#中常規容器和泛型容器有什么區別,哪種效率高?
不帶泛型的容器需要裝箱和拆箱操作速度慢所以泛型容器效率更高數據類型更安全
19. 有哪些常見的數值類?
簡單值類型:包括 整數類型、實數類型、字符類型、布爾類型
復合值類型:包括 結構類型、枚舉類型
20. C#中委托 和 接口有什么區別?各用在什么場合?
**接口(interface)**是約束類應該具備的功能集合,約束了類應該具備的功能,使類從千變萬化的具體邏輯中解脫出來,便于類的管理和擴展,同時又合理解決了類的單繼承問題。
C#中的委托 是約束方法集合的一個類,可以便捷的使用委托對這個方法集合進行操作。
在以下情況中使用接口:
1.無法使用繼承的場合
2.完全抽象的場合
3.多人協作的場合
以上等等
在以下情況中使用委托:多用于事件處理中
21. C#中unsafe關鍵字是用來做什么的?什么場合下使用?
非托管代碼才需要這個關鍵字一般用在帶指針操作的場合。
項目背包系統的任務裝備欄使用到
22. C#中ref和out關鍵字有什么區別?
ref修飾引用參數。參數必須賦值,帶回返回值,又進又出
out修飾輸出參數。參數可以不賦值,帶回返回值之前必須明確賦值,
引用參數和輸出參數不會創建新的存儲位置
如果ref參數是值類型,原先的值類型數據,會隨著方法里的數據改變而改變,
如果ref參數值引用類型,方法里重新賦值后,原對象堆中數據會改變,如果對引用類型再次創建新對象并賦值給ref參數,引用地址會重新指向新對象堆數據。方法結束后形參和新對象都會消失。實參還是指向原始對象,值不夠數據改變了
23. For,foreach,Enumerator.MoveNext的使用,與內存消耗情況
for循環可以通過索引依次進行遍歷,foreach和Enumerator.MoveNext通過迭代的方式進行遍歷。
內存消耗上本質上并沒有太大的區別。
但是在Unity中的Update中,一般不推薦使用foreach 因為會遺留內存垃圾。
24. 函數中多次使用string的+=處理,會產生大量內存垃圾(垃圾碎片),有什么好的方法可以解決。
通過StringBuilder那進行append,這樣可以減少內存垃圾
25. 當需要頻繁創建使用某個對象時,有什么好的程序設計方案來節省內存?
設計單例模式進行創建對象或者使用對象池
26. JIT和AOT區別
Just-In-Time -實時編譯
執行慢安裝快占空間小一點
Ahead-Of-Time -預先編譯
執行快安裝慢占內存占外存大
27. 給定一個存放參數的數組,重新排列數組
void SortArray(Array arr){Array.Sort(arr);}
28. Foreach循環迭代時,若把其中的某個元素刪除,程序報錯,怎么找到那個元素?以及具體怎么處理這種情況?(注:Try…Catch捕捉異常,發送信息不可行)
foreach不能進行元素的刪除,因為迭代器會鎖定迭代的集合,解決方法:記錄找到索引或者key值,迭代結束后再進行刪除。
29. GameObject a=new GameObject() GameObject b=a 實例化出來了A,將A賦給B,現在將B刪除,問A還存在嗎?
存在,b刪除只是將它在棧中的內存刪除,而A對象本身是在堆中,所以A還存在
30. C#中 委托和事件的區別
大致來說,委托是一個類,該類內部維護著一個字段,指向一個方法。事件可以被看作一個委托類型的變量,通過事件注冊、取消多個委托或方法。
○ 委托就是一個類,也可以實例化,通過委托的構造函數來把方法賦值給委托實例
○ 觸發委托有2種方式: 委托實例.Invoke(參數列表),委托實例(參數列表)
○ 事件可以看作是一個委托類型的變量
○ 通過+=為事件注冊多個委托實例或多個方法
○ 通過-=為事件注銷多個委托實例或多個方法
○ EventHandler就是一個委托
31. 結構體和類有何區別?
結構體是一種值類型,而類是引用類型。(值類型、引用類型是根據數據存儲的?度來分的)就是值類型用于存儲數據的值,引用類型用于存儲對實際數據的引用。
那么結構體就是當成值來使用的,類則通過引用來對實際數據操作
32. C#的委托是什么?有何用處?
委托類似于一種安全的指針引用,在使用它時是 當做類來看待而不是一個方法,相當于對一組方 法的列表的引用。
用處:使用委托使程序員可以將方法引用封裝在 委托對象內。然后可以將該委托對象傳遞給可調 用所引用方法的代碼,而不必在編譯時知道將調 用哪個方法。與C或C++中的函數指針不同,委托 是面向對象,而且是類型安全的。
33. foreach迭代器遍歷和for循環遍歷的區別
如果集合需要foreach遍歷,是否可行,存在一定問題
foreach中的迭代變量item是的只讀,不能對其進行修改,比如list.Remove(item)操作
foreach只讀的時候記錄下來,在對記錄做操作,或者直接用for循環遍歷
foreach對int[]數組循環已經不產生GC,避免對ArrayList進行遍歷
for語句中初始化變量i的作用域,循環體內部可見。
通過索引進行遍歷,可以根據索引對所遍歷集合進行修改
unity中for循環使用lambda表達式注意閉包問題
foreach遍歷原理
任何集合類(Array)對象都有一個GetEnumerator()方法,該方法可以返回一個實現了 IEnumerator接口的對象。
這個返回的IEnumerator對象既不是集合類對象,也不是集合的元素類對象,它是一個獨立的類對象。
通過這個實現了 IEnumerator接口對象A,可以遍歷訪問集合類對象中的每一個元素對象
對象A訪問MoveNext方法,方法為真,就可以訪問Current方法,讀取到集合的元素。
34. C#和C++的區別?
簡單的說:C# 與C++ 比較的話,最重要的特性 就是C# 是一種完全面向對象的語言,而C++ 不 是,另外C# 是基于IL 中間語言
和.NET Framework CLR 的,在可移植性,可維 護性和強壯性都比C++ 有很大的改進。C# 的設 計目標是用來開發快速穩定可擴展的應用程序, 當然也可以通過Interop和Pinvoke 完成一些底層操作
具體對比:
35. C#引用和C++指針的區別
C#不支持指針,但可以使用Unsafe,不安全模式,CLR不檢測
C#可以定義指針的類型、整數型、實數型、struct結構體
C#指針操作符、C#指針定義
使用fixed,可以操作類中的值類型
相同點:都是地址
指針指向一塊內存,它的內容是所指內存的地址;而引用則是某塊內存的別名。
不同點:
指針是個實體,引用是個別名。
sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身的大小;
引用是類型安全的,而指針在不安全模式下
36. 堆和棧的區別?
通常保存著我們代碼執行的步驟,如在代碼段1中 AddFive()方法,int pValue變量,int result變量等等。 而堆上存放的則多是對象,數據等。(譯者注:忽略編 譯器優化)我們可以把棧想象成一個接著一個疊放在 一起的盒子。當我們使用的時候,每次從最頂部取走 一個盒子。棧也是如此,當一個方法(或類型)被調 用完成的時候,就從棧頂取走(called a Frame,譯 注:調用幀),接著下一個。堆則不然,像是一個倉 庫,儲存著我們使用的各種對象等信息,跟棧不同的 是他們被調用完畢不會立即被清理掉。
37. Heap與Stack有何區別?
38. Mock和Stub有何區別?
Mock與Stub的區別:Mock:關注行為驗證。細粒度的 測試,即代碼的邏輯,多數情況下用于單元測試。 Stub:關注狀態驗證。粗粒度的測試,在某個依賴系 統不存在或者還沒實現或者難以測試的情況下使用, 例如訪問文件系統,數據庫連接,遠程協議等。
39. 為什么dynamic font 在 unicode環境下優于 staticfont(字符串編碼)
Unicode是國際組織制定的可以容納世界上所有?字和符號的字符編碼?案。
使?動態字體時,Unity將不會預先?成?個與所有字體的字符紋理。
當需要?持亞洲語?或者較?的字體的時候,若使?正常紋理,則字體的紋理將?常?。
40. 簡述StringBuilder和String的區別?(字符串處理)
String是字符串常量。StringBuffer是字符串變量 ,線程安全。StringBuilder是字符串變量,線程不安全。
String類型是個不可變的對象,當每次對String進?改變時都需要?成?個新的String對象,然后將指針指向?個新的對象,如果在?個循環??,不斷的改變?個對象,就要不斷的?成新的對象,所以效率很低,建議在不斷更改String對象的地?不要使?String類型。
StringBuilder對象在做字符串連接操作時是在原來的字符串上進?修改,改善了性能。這?點我們平時使?中也許都知道,連接操作頻繁的時候,使?StringBuilder對象。
41. string、stringBuilder、stringBuffer
-
String不變性,字符序列不可變,對原管理中實例對象賦值,會重新開一個新的實例對象賦值,新開的實例對象會等待被GC。
string拼接要重新開辟空間,因為string原值不會改變,導致GC頻繁,性能消耗大 -
StringBuffer是字符串可變對象,可通過自帶的StringBuffer.方法來改變并生成想要的字符串。對原實例對象做拼接的實例,不會生成新的實例對象。
拼接使用StringBuilder和StringBuffer,只開辟一個內存空間,這是性能優化的點。 -
StringBuilder是字符串可變對象,基本和StringBuilder相同。
唯一的區別是StringBuffer是線程安全,相關方法前帶synchronized關鍵字,一般用于多線程
StringBuilder是非線程安全,所以性能略好,一般用于單線程
三者性能比較 StringBuilder>StringBuffer>String
42. 字典Dictionary的內部實現原理
泛型集合命名空間using System.Collections.Generic;
任何鍵都必須是唯一
該類最大的優點就是它查找元素的時間復雜度接近O(1),實際項目中常被用來做一些數據的本地緩存,提升整體效率。
實現原理
43. 泛型是什么
多個代碼對 【不同數據類型】 執行 【相同指令】的情況
泛型:多個類型共享一組代碼
泛型允許類型參數化,泛型類型是類型的模板
5種泛型:類、結構、接口、委托、方法
類型占位符 T 來表示泛型
泛型類不是實際的類,而是類的模板
從泛型類型創建實例
聲明泛型類型》通過提供【真實類型】創建構造函數類型》從構造類型創建實例
類<T1,T2> 泛型類型參數
性能:泛型不會強行對值類型進行裝箱和拆箱,或對引用類型進行向下強制類型轉換,所以性能得到提高
安全:通過知道使用泛型定義的變量的類型限制,編譯器可以在一定程度上驗證類型假設,所以泛型提高了程序的類型安全。
44. Mathf.Round和Mathf.Clamp和Mathf.Lerp含義?
- Mathf.Round:四舍五入
- Mathf.Clamp:左右限值
- Mathf.Lerp:插值
45. 能用foreach遍歷訪問的對象需要實現______接?或聲明_________?法的類型(C#遍歷)
IEnumerable;GetEnumerator
List和Dictionary類型可以用foreach遍歷,他們都實現了IEnumerable接口,申明了GetEnumerator方法。
46. 什么是里氏替換原則?(C#多態)
里氏替換原則(Liskov Substitution Principle LSP)?向對象設計的基本原則之?。
- 里氏替換原則中說,任何基類可以出現的地?,?類?定可以出現,作??便擴展功能能
- 子類可以實現父類的抽象方法,但是不能覆蓋父類的非抽象方法。
- 子類中可以增加自己特有的方法。
- 當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬松。
- 當子類的方法實現父類的抽象方法時,方法的后置條件(即方法的返回值)要比父類更嚴格。
47. 反射的實現原理?
可以在加載程序運行時,動態獲取和加載程序集,并且可以獲取到程序集的信息反射即在運行期動態獲取類、對象、方法、對象數據等的一種重要手段
主要使用的類庫:System.Reflection
核心類:
通過以上核心類可在運行時動態獲取程序集中的類,并執行類構造產生類對象,動態獲取對象的字段或屬性值,更可以動態執行類方法和實例方法等。
審查元數據并收集關于它的類型信息的能?。
實現步驟: 1. 導?using System.Reflection; 2. Assembly.Load("程序集")加載程序集,返回類型是 ?個Assembly 3. foreach (Type type in assembly.GetTypes()){string t = type.Name;} 得到程序集中所有類的名稱 4. Type type = assembly.GetType("程序集.類名");獲取 當前類的類型 5. Activator.CreateInstance(type); 創建此類型實例 6. MethodInfo mInfo = type.GetMethod("?法名");獲取 當前?法 7. mInfo.Invoke(null,?法參數);48. 概述c#中代理和事件?
代理就是?來定義指向?法的引?。
C#事件本質就是對消息的封裝,?作對象之間的通信;發送?叫事件發送器,接收?叫事件接收器;
49. 哈希表與字典對比
字典:內部用了Hashtable作為存儲結構
- 如果我們試圖找到一個不存在的鍵,它將返回 / 拋出異常。
- 它比哈希表更快,因為沒有裝箱和拆箱,尤其是值類型。
- 僅公共靜態成員是線程安全的。
- 字典是一種通用類型,這意味著我們可以將其與任何數據類型一起使用(創建時,必須同時指定鍵和值的數據類型)。
- Dictionay 是 Hashtable 的類型安全實現, Keys和Values是強類型的。
- Dictionary遍歷輸出的順序,就是加入的順序
哈希表:
- 如果我們嘗試查找不存在的鍵,則返回 null。
- 它比字典慢,因為它需要裝箱和拆箱。
- 哈希表中的所有成員都是線程安全的,
- 哈希表不是通用類型,
- Hashtable 是松散類型的數據結構,我們可以添加任何類型的鍵和值。
- HashTable是經過優化的,訪問下標的對象先散列過,所以內部是無序散列的
50. C#中四種訪問修飾符是哪些?各有什么區別?
屬性修飾符:
Serializable:按值將對象封送到遠程服務器。
STATread:是單線程套間的意思,是?種線程模型。
MATAThread:是多線程套間的意思,也是?種線程模
型。
存取修飾符:
public:存取不受限制。
private:只有包含該成員的類可以存取。
internal:只有當前?程可以存取。
protected:只有包含該成員的類以及派?類可以存
取。
類修飾符:
abstract:抽象類。指示?個類只能作為其它類的基
類。
sealed:密封類。指示?個類不能被繼承。理所當
然,密封類不能同時?是抽象類,因為抽象總是希望
被繼承的。
成員修飾符:
abstract:指示該?法或屬性沒有實現。
sealed:密封?法。可以防?在派?類中對該?法的
override(?載)。不是類的每個成員?法都可以作為
密封?法密封?法,必須對基類的虛?法進??載,
提供具體的實現?法。所以,在?法的聲明中,
sealed修飾符總是和override修飾符同時使?。
delegate:委托。?來定義?個函數指針。C#中的事
件驅動是基于delegate + event的。
const:指定該成員的值只讀不允許修改。
event:聲明?個事件。
extern:指示?法在外部實現。
override:?寫。對由基類繼承成員的新實現。
readonly:指示?個域只能在聲明時以及相同類的內
部被賦值。
static:指示?個成員屬于類型本身,?不是屬于特定
的對象。即在定義后可不經實例化,就可使?。
virtual:指示?個?法或存取器的實現可以在繼承類中
被覆蓋。
new:在派?類中隱藏指定的基類成員,從?實現?
寫的功能。 若要隱藏繼承類的成員,請使?相同名稱
在派?類中聲明該成員,并? new 修飾符修飾它。
51. 下列代碼在運行中會發生什么問題?如何避免?
List<int> ls = new List<int>(new int[]{ 1, 2, 3, 4, 5 });foreach (int item in ls){Console.WriteLine(item * item);ls.Remove(item);}會產?運?時錯誤,因為foreach是只讀的。不能?邊遍歷?邊修改。
使用For循環遍歷可以解決。
52. 什么是裝箱拆箱,怎樣減少操作
C#裝箱是將值類型轉換為引用類型;
拆箱是將引用類型轉換為值類型。
牽扯到裝箱和拆箱操作比較多的就是在集合中,例如:ArrayList或者HashTable之類。
53. MVC
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范。
用一種業務邏輯、數據、界面顯示分離的方法,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用于映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。
- Model(模型)是應用程序中用于處理應用程序數據邏輯的部分。
通常模型對象負責在數據庫中存取數據。 - View(視圖)是應用程序中處理數據顯示的部分。
通常視圖是依據模型數據創建的。 - Controller(控制器)是應用程序中處理用戶交互的部分。
通常控制器負責從視圖讀取數據,控制用戶輸入,并向模型發送數據
🧡Unity基礎知識
微信搜索:呆呆敲代碼的小Y 后臺回復:白嫖 免費獲取很多的編程資料哦!1. Image和RawImage的區別
- Imgae比RawImage更消耗性能
- Image只能使用Sprite屬性的圖片,但是RawImage什么樣的都可以使用
- Image適合放一些有操作的圖片,裁剪平鋪旋轉什么的,針對Image Type屬性
- RawImage就放單獨展示的圖片就可以,性能會比Image好很多
2. Unity3D中的碰撞器和觸發器的區別?
答:碰撞器是觸發器的載體,而觸發器只是碰撞器身上的一個屬性。
當Is Trigger=false時,碰撞器根據物理引擎引發碰撞,產生碰撞的效果,可以調用OnCollisionEnter/Stay/Exit函數;
當Is Trigger=true時,碰撞器被物理引擎所忽略,沒有碰撞效果,可以調用OnTriggerEnter/Stay/Exit函數。
如果既要檢測到物體的接觸又不想讓碰撞檢測影響物體移動或要檢測一個物件是否經過空間中的某個區域這時就可以用到觸發器。
3. 物體發生碰撞的必要條件?
答:兩個物體都必須帶有碰撞器Collider,其中一個物體還必須帶有Rigidbody剛體。
4. 簡述四元數Quaternion的作用,四元數對歐拉角的優點?
答:四元數用于表示旋轉
相對歐拉角的優點:能進行增量旋轉、避免萬向鎖、給定方位的表達方式有兩種,互為負(歐拉角有無數種表達方式)
5. 如何安全的在不同工程間安全地遷移asset數據?三種方法
6. OnEnable、Awake、Start運行時的發生順序?哪些可能在同一個對象周期中反復的發生?
答:Awake–>OnEnable->Start
OnEnable在同一周期中可以反復地發生!
7. MeshRender中material和sharedmaterial的區別?
答:修改sharedMaterial將改變所有物體使用這個材質的外觀,并且也改變儲存在工程里的材質設置。 不推薦修改由sharedMaterial返回的材質。如果你想修改渲染器的材質,使用material替代。
8. TCP/IP協議棧各個層次及分別的功能?
網絡接口層:這是協議棧的最低層,對應OSI的物理層和數據鏈路層,主要完成數據幀的實際發送和接收。
網絡層:處理分組在網絡中的活動,例如路由選擇和轉發等,這一層主要包括IP協議、ARP、ICMP協議等。
傳輸層:主要功能是提供應用程序之間的通信,這一層主要是TCP/UDP協議。
應用層:用來處理特定的應用,針對不同的應用提供了不同的協議,例如進行文件傳輸時用到的FTP協議,發送email用到的SMTP等。
9. Unity提供了幾種光源,分別是什么?
四種。
- 平行光:Directional Light
- 點光源:Point Light
- 聚光燈:Spot Light
- 區域光源:Area Light
10. 簡述一下對象池,你覺得在FPS里哪些東西適合使用對象池?
對象池就存放需要被反復調用資源的一個空間
比如游戲中要常被大量復制的對象,子彈,敵人,以及任何重復出現的對象。
特點:用內存換取cpu的優化
11. CharacterController和Rigidbody的區別?
Rigidbody具有完全真實物理的特性,而CharacterController可以說是受限的的Rigidbody,具有一定的物理效果但不是完全真實的。
12. 移動相機動作在哪個函數里,為什么在這個函數里?
LateUpdate,是在所有的Update結束后才調用,比較適合用于命令腳本的執行。
官網上例子是攝像機的跟隨,都是所有的Update操作完才進行攝像機的跟進,不然就有可能出現攝像機已經推進了,但是視角里還未有角色的空幀出現。
13. 簡述prefab的用處
在游戲運行時實例化,prefab相當于一個模板,對你已經有的素材、腳本、參數做一個默認的配置,以便于以后的修改,同事prefab打包的內容簡化了導出的操作,便于團隊的交流。
14. GPU的工作原理?
簡而言之,GPU的圖形(處理)流水線完成如下的工作:(并不一定是按照如下順序)。
頂點處理:這階段GPU讀取描述3D圖形外觀的頂點數據并根據頂點數據確定3D圖形的形狀及位置關系,建立起3D圖形的骨架。在支持DX8和DX9規格的GPU中,這些工作由硬件實現的Vertex Shader(定點著色器)完成。
光柵化計算:顯示器實際顯示的圖像是由像素組成的,我們需要將上面生成的圖形上的點和線通過一定的算法轉換到相應的像素點。把一個矢量圖形轉換為一系列像素點的過程就稱為光柵化。例如,一條數學表示的斜線段,最終被轉化成階梯狀的連續像素點。
紋理帖圖:頂點單元生成的多邊形只構成了3D物體的輪廓,而紋理映射(texture mapping)工作完成對多變形表面的帖圖,通俗的說,就是將多邊形的表面貼上相應的圖片,從而生成“真實”的圖形。TMU(Texture mapping unit)即是用來完成此項工作。
像素處理:這階段(在對每個像素進行光柵化處理期間)GPU完成對像素的計算和處理,從而確定每個像素的最終屬性。在支持DX8和DX9規格的GPU中,這些工作由硬件實現的Pixel Shader(像素著色器)完成。
最終輸出:由ROP(光柵化引擎)最終完成像素的輸出,1幀渲染完畢后,被送到顯存幀緩沖區。
總結:GPU的工作通俗的來說就是完成3D圖形的生成,將圖形映射到相應的像素點上,對每個像素進行計算確定最終顏色并完成輸出。
15. 什么是渲染管道?
是指在顯示器上為了顯示出圖像而經過的一系列必要操作。 渲染管道中的很多步驟,都要將幾何物體從一個坐標系中變換到另一個坐標系中去。
主要步驟有: 本地坐標->視圖坐標->背面裁剪->光照->裁剪->投影->視圖變換->光柵化。
16. 如何優化內存?
18. 動態加載資源的方式?
- instantiate:最簡單的一種方式,以實例化的方式動態生成一個物體。
- Assetsbundle:即將資源打成 asset bundle 放在服務器或本地磁盤,然后使用WWW模塊get 下來,然后從這個bundle中load某個object,unity官方推薦也是絕大多數商業化項目使用的一種方式。
- Resource.Load:可以直接load并返回某個類型的Object,前提是要把這個資源放在Resource命名的文件夾下,Unity不管有沒有場景引用,都會將其全部打入到安裝包中
- AssetDatabase.loadasset :這種方式只在editor范圍內有效,游戲運行時沒有這個函數,它通常是在開發中調試用的。
19. 使用Unity3d實現2d游戲,有幾種方式?
20. 在物體發生碰撞的整個過程中,有幾個階段,分別列出對應的函數 三個階段
答:OnCollisionEnter、 OnCollisionStay、 OnCollisionExit
21. Unity3d的物理引擎中,有幾種施加力的方式,分別描述出來
- rigidbody.AddForce
- rigidbody.AddForceAtPosition
22. 什么叫做鏈條關節?
Hinge Joint,可以模擬兩個物體間用一根鏈條連接在一起的情況,能保持兩個物體在一個固定距離內部相互移動而不產生作用力,但是達到固定距離后就會產生拉力。
23. 物體自身旋轉使用的函數?
Transform.Rotate()
24. Unity3d提供了一個用于保存和讀取數據的類(PlayerPrefs),請列出保存和讀取整形數據的函數
PlayerPrefs.SetInt()、 PlayerPrefs.GetInt()
25. Unity3d腳本從喚醒到銷毀有著一套比較完整的生命周期,請列出系統自帶的幾個重要的方法。
答:Awake——>Start——>Update——>FixedUpdate——>LateUpdate——>OnGUI——>OnDisable——>OnDestroy
主要執行順序
編輯器->初始化->物理系統->輸入事件->游戲邏輯->場景渲染->GUI渲染->物體激活或禁用->銷毀物體->應用結束
主要函數介紹
- Reset 是在用戶點擊檢視面板的Reset按鈕或者首次添加該組件時被調用。此函數只在編輯模式下被調用。Reset最常用于在檢視面板中給定一個最常用的默認值。
- Awake 用于在游戲開始之前初始化變量或游戲狀態。在腳本整個生命周期內它僅被調用一次.Awake在所有對象被初始化之后調用,所以你可以安全的與其他對象對話或用諸如 GameObject.FindWithTag 這樣的函數搜索它們。每個游戲物體上的Awke以隨機的順序被調用。因此,你應該用Awake來設置腳本間的引用,并用Start來傳遞信息 ,Awake總是在Start之前被調用。它不能用來執行協同程序。
- OnDisable 不能用于協同程序。當對象變為不可用或非激活狀態時此函數被調用。
- Start 在behaviour的生命周期中只被調用一次。它和Awake的不同是Start只在腳本實例被啟用時調用。你可以按需調整延遲初始化代碼。Awake總是在Start之前執行。這允許你協調初始化順序。
- FixedUpdate 當MonoBehaviour啟用時,其在每一幀被調用。處理Rigidbody時,需要用FixedUpdate代替Update。例如:給剛體加一個作用力時,你必須應用作用力在FixedUpdate里的固定幀,而不是Update中的幀。(兩者幀長不同)。
- OnTriggerEnter 可以被用作協同程序,在函數中調用yield語句。當Collider(碰撞體)進入trigger(觸發器)時調用OnTriggerEnter。
- OnCollisionEnter 相對于OnTriggerEnter,傳遞的是Collision類而不是Collider。Collision包含接觸點,碰撞速度等細節。如果在函數中不使用碰撞信息,省略collisionInfo參數以避免不必要的運算。注意如果碰撞體附加了一個非動力學剛體,只發送碰撞事件。可以被用作協同程序。
當鼠標在GUIElement(GUI元素)或Collider(碰撞體)上點擊時調用OnMouseDown。 - Update 是實現各種游戲行為最常用的函數。
- yield 一個協同程序在執行過程中,可以在任意位置使用yield語句。yield的返回值控制何時恢復協同程序向下執行。協同程序在對象自有幀執行過程中堪稱優秀。協同程序在性能上沒有更多的開銷。StartCoroutine函數是立刻返回的,但是yield可以延遲結果。直到協同程序執行完畢。
- LateUpdate 是在所有Update函數調用后被調用。這可用于調整腳本執行順序。例如:當物體在Update里移動時,跟隨物體的相機可以在LateUpdate里實現。
渲染和處理GUI事件時調用。這意味著你的OnGUI程序將會在每一幀被調用。要得到更多的GUI事件的信息查閱Event手冊。如果Monobehaviour的enabled屬性設為false,OnGUI()將不會被調用。 - OnApplicationQuit,當用戶停止運行模式時在編輯器中調用。當web被關閉時在網絡播放器中被調用。
26. 物理更新一般放在哪個系統函數里?
FixedUpdate,每固定幀繪制時執行一次,和Update不同的是FixedUpdate是渲染幀執行,如果你的渲染效率低下的時候FixedUpdate調用次數就會跟著下降。
FixedUpdate比較適用于物理引擎的計算,因為是跟每幀渲染有關。 Update就比較適合做控制。
27. 在場景中放置多個Camera并同時處于活動狀態會發生什么?
游戲界面可以看到很多攝像機的混合。
28. 如何銷毀一個UnityEngine.Object及其子類?
使用Destroy()方法;
29. 請描述游戲動畫有哪幾種,以及其原理?
主要有關節動畫、骨骼動畫、單一網格模型動畫(關鍵幀動畫)。
-
關節動畫:把角色分成若干獨立部分,一個部分對應一個網格模型,部分的動畫連接成一個整體的動畫,角色比較靈活,Quake2中使用這種動畫;
-
骨骼動畫,廣泛應用的動畫方式,集成了以上兩個方式的優點,骨骼按角色特點組成一定的層次結構,有關節相連,可做相對運動,皮膚作為單一網格蒙在骨骼之外,決定角色的外觀;
-
單一網格模型動畫由一個完整的網格模型構成,在動畫序列的關鍵幀里記錄各個頂點的原位置及其改變量,然后插值運算實現動畫效果,角色動畫較真實。
30. 請描述為什么Unity3d中會發生在組件上出現數據丟失的情況
一般是組件上綁定的物體對象被刪除了
31. alpha blend工作原理?
Alpha Blend 實現透明效果,不過只能針對某塊區域進行alpha操作,透明度可設。
32. 寫出光照計算中的diffuse的計算公式?
diffuse = Kd x colorLight x max(N*L,0);Kd 漫反射系數、colorLight 光的顏色、N 單位法線向量、L 由點指向光源的單位向量、其中N與L點乘,如果結果小于等于0,則漫反射為0。
33. LOD是什么,優缺點是什么?
LOD(Level of detail)多層次細節,是最常用的游戲優化技術。
它按照模型的位置和重要程度決定物體渲染的資源分配,降低非重要物體的面數和細節度,從而獲得高效率的渲染運算。
缺點:增加了內存
LOD簡單示例:【100個 Unity踩坑小知識點】| Unity 的 LOD技術(多細節層次)
33. 兩種陰影判斷的方法、工作原理?
本影和半影:
- 本影:景物表面上那些沒有被光源直接照射的區域(全黑的輪廓分明的區域)。
- 半影:景物表面上那些被某些特定光源直接照射但并非被所有特定光源直接照射的區域(半明半暗區域) 工作原理:從光源處向物體的所有可見面投射光線,將這些面投影到場景中得到投影面,再將這些投影面與場景中的其他平面求交得出陰影多邊形,保存這些陰影多邊形信息,然后再按視點位置對場景進行相應處理得到所要求的視圖(利用空間換時間,每次只需依據視點位置進行一次陰影計算即可,省去了一次消隱過程)
34. Vertex Shader是什么,怎么計算?
頂點著色器 是一段執行在GPU上的程序,用來取代fixed pipeline中的transformation和lighting,Vertex Shader主要操作頂點。
Vertex Shader對輸入頂點完成了從local space到homogeneous space(齊次空間)的變換過程,homogeneous space即projection space的下一個space。在這其間共有world transformation, view transformation和projection transformation及lighting幾個過程。
35. MipMap是什么,作用?
MipMapping:在三維計算機圖形的貼圖渲染中有常用的技術,為加快渲染進度和減少圖像鋸齒,貼圖被處理成由一系列被預先計算和優化過的圖片組成的文件,這樣的貼圖被稱為MipMap。
36. 請描述Interface與抽象類之間的不同
語法不同處:
用法不同處:
37. .Net與Mono的關系?
mono是.net的一個開源跨平臺工具,就類似java虛擬機,java本身不是跨平臺語言,但運行在虛擬機上就能夠實現了跨平臺。
.net只能在windows下運行,mono可以實現跨平臺編譯運行,可以運行于Linux,Unix,Mac OS等。
38. 簡述Unity3D支持的作為腳本的語言的名稱?
Unity的腳本語言基于Mono的.Net平臺上運行,可以使用.NET庫,這也為XML、數據庫、正則表達式等問題提供了很好的解決方案。
Unity里的腳本都會經過編譯,他們的運行速度也很快。這三種語言實際上的功能和運行速度是一樣的,區別主要體現在語言特性上。
Unity支持的語言:C#,JavaScrip(不在使用)
39. Unity3D是否支持寫成多線程程序?如果支持的話需要注意什么?
支持:如果同時你要處理很多事情或者與Unity的對象互動小可以用thread,否則使用coroutine。
Unity3d沒有多線程的概念,不過unity也給我們提供了StartCoroutine(協同程序)和LoadLevelAsync(異步加載關卡)后臺加載場景的方法。
注意:僅能從主線程中訪問Unity3D的組件,對象和Unity3D系統調用。C#中有lock這個關鍵字,以確保只有一個線程可以在特定時間內訪問特定的對象
40. 如何讓已經存在的GameObject在LoadLevel后不被卸載掉?
DontDestroyOnLoad(transform.gameObject);41. U3D中用于記錄節點空間幾何信息的組件名稱,及其父類名稱
Transform 父類是 Component
42. 向量的點乘、叉乘以及歸一化的意義?
- 叉乘 幾何意義:得到一個與這兩個向量都垂直的向量,這個向量的模是以兩個向量為邊的平行四邊形的面積
- 點乘 幾何意義:可以用來表征或計算兩個向量之間的夾角,以及在b向量在a向量方向上的投影
43. 矩陣相乘的意義及注意點?
用于表示線性變換:旋轉、縮放、投影、平移、仿射
注意矩陣的蠕變:誤差的積累
44. 當一個細小的高速物體撞向另一個較大的物體時,會出現什么情況?如何避免?
穿透(碰撞檢測失敗)(例如CS射擊游戲,可以使用開槍時發射射線,射線碰撞到則掉血擊中)
45. 為何大家都在移動設備上尋求U3D原生GUI的替代方案
不美觀,OnGUI很耗費時間,使用不方便
46. 請簡述如何在不同分辨率下保持UI的一致性
多屏幕分辨率下的UI布局一般考慮兩個問題:
為了解決這兩個問題,在Unity GUI體系中有兩個組件可以來解決問題,分別是布局元素的Rect Transform和Canvas的Canvas Scaler組件。
47. 請簡述OnBecameVisible及OnBecameInvisible的發生時機,以及這一對回調函數的意義?
當物體是否可見切換之時。可以用于只需要在物體可見時才進行的計算。
48. 什么叫動態合批?跟靜態合批有什么區別?
如果動態物體共用著相同的材質,那么Unity會自動對這些物體進行批處理。
動態批處理操作是自動完成的,并不需要你進行額外的操作。
區別:動態批處理一切都是自動的,不需要做任何操作,而且物體是可以移動的,但是限制很多。靜態批處理:自由度很高,限制很少,缺點可能會占用更多的內存,而且經過靜態批處理后的所有物體都不可以再移動了。
49. Unity提供了幾種光源,分別是什么?
四種。
平?光:Directional Light
點光源:Point Light
聚光燈:Spot Light
區域光源:Area Light
50. 什么是LightMap?
LightMap:就是指在三維軟件里實現打好光,然后渲染把場景各表面的光照輸出到貼圖上,最后又通過引擎貼到場景上,這樣就使物體有了光照的感覺。
51. Unity和cocos2d的區別
Unity3D支持C#、javascript等,cocos2d-x 支持c++、Html5、Lua等。
cocos2d 開源 并且免費
Unity3D支持iOS、Android、Flash、Windows、Mac、Wii等平臺的游戲開發,cocos2d-x支持iOS、Android、WP等。
52. Unity3D Shader分哪幾種,有什么區別?
53. 獲取、增加、刪除組件的命令分別是什么?
- 獲取:GetComponent
- 增加:AddComponent
- 刪除:Destroy
54. Unity中,照相機的Clipping Planes的作用是什么?調整 Near、Far兩個值時,應該注意什么?
剪裁平面 。從相機到開始渲染和停止渲染之間的 距離。
55. 簡述prefab的用處
在游戲運行時實例化,prefab相當于一個模板, 對你已經有的素材、腳本、參數做一個默認的配 置,以便于以后的修改,同時prefab打包的內容 簡化了導出的操作,便于團隊的交流。
56. 請描述為什么Unity3d中會發生 在組件上出現數據丟失的情況
剪裁平面 。從相機到開始渲染和停止渲染之間的距離。
57. 如何在Unity3D中查看場景的面數,頂點數和Draw Call數?如何降低Draw Call數?
在Game視圖右上角點擊Stats。降低Draw Call 的技術是Draw Call Batching
58. 請問alpha test在何時使用?能達到什么效果?
Alpha Test,中文就是透明度測試。
簡而言之就是V&F shader中最后fragment函數輸出的該點顏色值(即上一講frag的輸出half4)的alpha值與固定值進行比較。Alpha Test語句通常于Pass{}中的起始位置。Alpha Test產生的效果也很極端,要么完全透明,即看不到,要么完全不透明。
60. 四元數有什么作用?
對旋轉角度進行計算時用到四元數
61. 將Camera組件的ClearFlags選項選成Depth only是什么意思?有何用處?
僅深度,該模式用于對象不被裁剪。
62. 如何讓已經存在的GameObject在LoadLevel后不被卸載掉?
void Awake() {DontDestroyOnLoad(transform.gameObject); }63. 在編輯場景時將GameObject設置為Static有何作用?
設置游戲對象為Static將會剔除(或禁用)網格對象當這些部分被靜態物體擋住而不可見時。因此,在你的場景中的所有不會動的物體都應該標記為Static。
64. 有A和B兩組物體,有什么辦法能夠保證A組物體永遠比B組物體先渲染?
把A組物體的渲染對列大于B物體的渲染隊列
65. 將圖片的TextureType選項分別選為Texture和Sprite有什么區別
Sprite作為UI精靈使用,Texture作用模型貼圖使用。
66. 問一個Terrain,分別貼3張,4張,5張地表貼圖,渲染速度有什么區別?為什么?
答:沒有區別,因為不管幾張貼圖只渲染一次。
67. 什么是DrawCall?DrawCall高了又什么影響?如何降低DrawCall?
Unity中,每次引擎準備數據并通知GPU的過程稱為一次Draw Call。DrawCall越高對顯卡的消耗就越大。降低DrawCall的方法:
- Dynamic Batching
- Static Batching
- 高級特性Shader降級為統一的低級特性的Shader。
68. 實時點光源的優缺點是什么?
可以有cookies – 帶有 alpha通道的立方圖(Cubemap )紋理。點光源是最耗費資源的。
69. 簡述四元數的作用,四元數對歐拉?的優點?
四元數?于表示旋轉,對旋轉?度進?計算時?到四元數
相對歐拉?的優點:
1)能進?增量旋轉
2)避免萬向鎖
3)給定?位的表達?式有兩種,互為負(歐拉?有?
數種表達?式)
70. Addcomponent后哪個生命周期函數會被調用
對于AddComponent添加的腳本,其Awake,Start,OnEnable是在Add的當前幀被調用的
其中Awake,OnEnable與AddComponent處于同一調用鏈上
Start會在當前幀稍晚一些的時候被調用,Update則是根據Add調用時機決定何時調用:如果Add是在當前幀的Update前調用,那么新腳本的Update也會在當前幀被調用,否則會被延遲到下一幀調用。
72. 層剔除
用layermask ,通過位運算的方式去設置
在代碼中使用時如何開啟某個Layers?
LayerMask mask = 1 << 你需要開啟的Layers層。
LayerMask mask = 0 << 你需要關閉的Layers層。
舉幾個例子:
LayerMask mask = 1 << 2; 表示開啟Layer2。LayerMask mask = 0 << 5;表示關閉Layer5。LayerMask mask = 1<<2|1<<8;表示開啟Layer2和Layer8。LayerMask mask = 0<<3|0<<7;表示關閉Layer3和Layer7。73. 分別解釋頂點著色器和像素著色器是什么
頂點著?器是?段執?在GPU上的程序,?來取代 fixed pipeline中的transformation和lighting,Vertex Shader主要操作頂點。‘’
像素著色器實際上就是對每一個像素進行光柵化的處理期間,在GPU上運算的一段程序。
不同與頂點著色器,像素著色器不會以軟件的形式來模擬像素著色器。
像素著色器實質上是取代了固定功能流水線中多重紋理的環節,而且賦予了我們訪問單個像素以及訪問每一個像素紋理坐標的能力
74. 畫布的三種模式.縮放模式
- 屏幕空間-覆蓋模式(Screen Space-Overlay),Canvas創建出來后,默認就是該模式,該模式和攝像機無關,即使場景內沒有攝像機,UI游戲物體照樣渲染
- 屏幕空間:電腦或者手機顯示屏的2D空間,只有x軸和y軸
- 覆蓋模式:UI元素永遠在3D元素的前面
- 屏幕空間-攝像機模式(Screen Space-Camera),設置成該模式后需要指定一個攝像機游戲物體,指定后UGUI就會自動出現在該攝像機的“投射范圍”內,和NGUI的默認UI Root效果一致,如果隱藏掉攝像機,UGUI當然就無法渲染
- 世界空間模式(WorldSpace),設置成該模式后UGUI就相當于是場景內的一個普通的“Cube 游戲模型”,可以在場景內任意的移動UGUI元素的位置,通常用于怪物血條顯示和VR開發
縮放模式:
| UI Scale Mode | Canvas中UI元素的縮放模式 |
| Constant Pixel Size | 使UI保持自己的尺寸,與屏幕尺寸無關。 |
| Scale With Screen Size | 屏幕尺寸越大,UI越大 |
| Constant Physical Size | 使UI元素保持相同的物理大小,與屏幕尺寸無關。 |
| Constant Pixel Size、Constant Physical Size實際上他們本質是一樣的,只不過 Constant Pixel Size 通過邏輯像素大小調節來維持縮放,而 Constant Physical Size 通過物理大小調節來維持縮放。 |
75. FSM有限狀態機
FSM是一種數據結構,它由以下幾個部分組成:
為什么要用FSM?
因為它編程快速簡單,易于調試,性能高,與人類思維相似從而便于梳理,靈活且容易修改
FSM的描述性定義:
一個有限狀態機是一個設備,或是一個模型,具有有限數量的狀態。它可以在任何給定時間根據輸入進行操作,使得系統從一個狀態轉換到另一個狀態,或者是使一個輸出或者一種行為的發生,一個有限狀態機在任何瞬間只能處于一種狀態。
State 狀態基類,定義了基本的Enter,Update,Exit三種狀態行為,通常在這三種狀態行為的方法里會寫一些邏輯。每個State都會有StateID(狀態id,可以是枚舉等),FSMControl(控制該狀態的狀態控制器的引用),Check方法(用來進行狀態判斷,并返回StateID,通過FSMControl驅動)
FSMControl,包含了一下FSMMachine,封裝層。
FSMMachine,驅動它的State列表,Update方法調用當前State的Check方法來獲得StateID,當currentState的Check方法返回的StateID和當前StateID不同,則切換狀態。
這是一個簡單的FSM狀態機系統,根據需要自己寫個Control繼承FSMControl來驅動狀態。因為Check是State的職責,所以每一個不同對象的行為如Human的Idle和Dog的Idel區分肯定也不同。因此需要分別去寫HumanIdleState和DogIdleState。如果還有Cat,Fish,可想而知代碼量會有多么龐大。
因此我將FSMControl抽象為一個公共基類,把State的Check具體實現作為FSMControl的Virtual方法。這樣在IdleState里的Check方法就不用寫具體的狀態切換判斷邏輯,而是調用它FSMControl子類(自己寫的繼承自FSMControl的Control類)的重寫方法
這樣每次添加的新對象只要有Idle這個狀態,就可以用一個公用的StateIdle,狀態切換的邏輯差異放在Control層
76. 使用過哪些Unity插件
因人而異,可以去簡單了解一下要說的插件,沒用過也可以,至少你知道這個插件了!
| shader graph | 制作shader光影效果 |
| cinemachine+timeline+postprocessingstack | 制作過場動畫 |
| nodecanvas | 制作怪物ai |
| easytouch | 手游觸摸控制 |
| DoTween | 動畫插件 |
| Fungus | 對話插件 |
| 3D WebView | 瀏覽器插件 |
| Vectrosity | 劃線插件 |
| AVPro Video | 視頻播放插件 |
💛物理系統
1. CharacterController和Rigidbody的區別
Rigidbody具有完全真實物理的特性,?CharacterController可以說是受限的
Rigidbody,具有?定的物理效果但不是完全真實的。
2. 射線檢測碰撞物的原理是?
答:射線是3D世界中一個點向一個方向發射的一條無終點的線,在發射軌跡中與其他物體發生碰撞時,它將停止發射 。
3. 什么叫做鏈條關節?
Hinge Joint,可以模擬兩個物體間用一根鏈條連 接在一起的情況,能保持兩個物體在一個固定距 離內部相互移動而不產生作用力,但是達到固定 距離后就會產生拉力。
4. 物體發生碰撞的必要條件?
兩個物體都必須帶有碰撞器Collider,其中一個物體還必須帶有Rigidbody剛體
5. 在物體發生碰撞的整個過程 中,有幾個階段,分別列出對 應的函數 三個階段
6. Unity3d中的碰撞器和觸發器的 區別?
碰撞器是觸發器的載體,而觸發器只是碰撞器身 上的一個屬性。
當Is Trigger=false時,碰撞器根據物理引擎引發 碰撞,產生碰撞的效果,可以調用 OnCollisionEnter/Stay/Exit函數;
當Is Trigger=true時,碰撞器被物理引擎所忽略, 沒有碰撞效果,可以調用OnTriggerEnter/Stay/ Exit函數。
如果既要檢測到物體的接觸又不想讓碰撞檢測影 響物體移動或要檢測一個物件是否經過空間中的 某個區域這時就可以用到觸發器
7. 射線檢測碰撞物的原理是?
射線是3D世界中一個點向一個方向發射的一條無 終點的線,在發射軌跡中與其他物體發生碰撞 時,它將停止發射 。
8. Unity3d的物理引擎中,有幾種 施加力的方式,分別描述出來
rigidbody.AddForce/AddForceAtPosition,都在 rigidbody系列函數中。
9. 當一個細小的高速物體撞向另一個較大的物體時,會出現什么情況?如何避免?
穿透(碰撞檢測失敗)
10. 射線Raycast原理
從一個起點向一個方向發射一條物理射線,返回碰撞到的物體的碰撞信息
💚UI & 2D 部分
1. UGUI 合批的一些問題
簡單來說在一個Canvas下,需要相同的material,相同的紋理以及相同的Z值。例如UI上的字體Texture使用的是字體的圖集,往往和我們自己的UI圖集不一樣,因此無法合批。還有UI的動態更新會影響網格的重繪,因此需要動靜分離。
2. Image和RawImage的區別
- Imgae比RawImage更消耗性能
- Image只能使用Sprite屬性的圖片,但是RawImage什么樣的都可以使用
- Image適合放一些有操作的圖片,裁剪平鋪旋轉什么的,針對Image Type屬性
- RawImage就放單獨展示的圖片就可以,性能會比Image好很多
3. 使用Unity3d實現2d游戲,有幾種方式?
4. 將圖片的TextureType選項分別選為Texture和Sprite有什么區別
Sprite作為UI精靈使用,Texture作用模型貼圖使用。
5. 請簡述如何在不同分辨率下保 持UI的一致性
屏幕分辨率的自適應 性,原理就是計算出屏幕的寬高比跟原來的預設 的屏幕分辨率求出一個對比值,然后修改攝像機 的size。
💙動畫系統
1. 請描述游戲動畫有哪幾種,以及其原理?
主要有關節動畫、?骼動畫、單一網格模型動畫(關鍵 幀動畫)。
- 關節動畫:把?色分成若干獨立部分,一個 部分對應一個網格模型,部分的動畫連接成一個整體 的動畫,?色比較靈活,Quake2中使用這種動畫;
- ?骼動畫,廣泛應用的動畫方式,集成了以上兩個方 式的優點,?骼按?色特點組成一定的層次結構,有 關節相連,可做相對運動,皮膚作為單一網格蒙在? 骼之外,決定?色的外觀;
- 單一網格模型動畫由一個完整的網格模型構成,在動 畫序列的關鍵幀里記錄各個頂點的原位置及其改變量,然后插值運算實現動畫效果,?色動畫較真實。
2. Avator的作用
用戶提供的模型骨架和Unity的骨架結構進行適配,是一種骨架映射關系。
方便動畫的重定向
AnimationType有三種類型
Humanoid人型:可以動畫重定向,游戲對象掛載animator,子類原始模型+重定向模型,設置原始模型和使用模型的AnimationType為Humanoid類型
Generic非人型
Legacy舊版
Avator Mask身體遮罩,身體某一部分是否受到動畫影響
反向動力學 IK,通過手或腳來控制身體其他部分
3. 反向旋轉動畫的方法是什么?
4. Animation.CrossFade 是什么?
動畫淡入淡出
5. 寫出 Animation 的五個方法
- AddClip 將 clip 添加到名稱為 newName 的動畫中。
- Blend 在后續 time 秒中將名稱為 animation 的動畫向 targetWeight 混合。
- CrossFade 在后續 time 秒的時間段內,使名稱為 animation 的動畫淡入,使其他動畫淡出。
- CrossFadeQueued 使動畫在上一個動畫播放完成后交叉淡入淡出。
- IsPlaying 名稱為 name 的動畫是否正在播放?
- PlayQueued 在先前的動畫播放完畢后再播放動畫。
- RemoveClip 從動畫列表中移除剪輯。
- Sample 對當前狀態的動畫進行采樣。
- Stop 停止所有使用該動畫啟動的正在播放的動畫。
6. 簡述 SkinnedMesh 的實現原理
SkinnedMesh蒙皮網格動畫
分為骨骼和蒙皮兩部分
骨骼是一個層次結構,存儲了骨骼的Transform數據
蒙皮是mesh頂點附著在骨骼之上,頂點可以被多個骨骼影響,決定了其權重等,
還有將頂點從Mesh空間變換到骨骼空間~
7. 動畫層(Animation Layers)的作用是什么?
動畫分層
身體部位動畫分層,比如我只想動動頭,身體其他部分不發生動畫,可以方便處理動畫區分
💜協程
1. Unity 協程 Coroutine 的作用
協程Coroutine在Unity中一直扮演者重要的角色。
可以實現簡單的計時器、將耗時的操作拆分成幾個步驟分散在每一幀去運行等等,而盡量不阻塞主線程運行。
2. 什么是協同程序?
在主線程運行時同時開啟另一段邏輯處理,來協助當前程序的執行。
換句話說,開啟協程就是開啟一個線程。可以用來控制運動、序列以及對象的行為。
3. Unity3D的協程和C#線程 之間的區別是什么?
多線程程序同時運行多個線程 ,而在任一指定時刻只 有一個協程在運行,并且這個正在運行的協同程序只 在必要時才被掛起。
除主線程之外的線程無法訪問Unity3D的對象、組件、 方法。
Unity3d沒有多線程的概念,不過unity也給我們提供了 StartCoroutine(協同程序)和LoadLevelAsync(異步 加載關卡)后臺加載場景的方法。
StartCoroutine為什 么叫協同程序呢,所謂協同,就是當你在 StartCoroutine的函數體里處理一段代碼時,利用yield 語句等待執行結果,這期間不影響主程序的繼續執 行,可以協同工作。
4. 協同程序的執行代碼是什么?有何用處,有何缺點?
官方案例) function Start() { // - After 0 seconds, prints "Starting 0.0" // - After 0 seconds, prints "Before WaitAndPrint Finishes 0.0" // - After 2 seconds, prints "WaitAndPrint 2.0" // 先打印"Starting 0.0"和"Before WaitAndPrint Finishes 0.0"兩句,2秒后打印"WaitAndPrint 2.0" print ("Starting " + Time.time ); // Start function WaitAndPrint as a coroutine. And continue execution while it is running // this is the same as WaintAndPrint(2.0) as the compiler does it for you automatically // 協同程序WaitAndPrint在Start函數內執行,可以視 同于它與Start函數同步執行. StartCoroutine(WaitAndPrint(2.0)); print ("Before WaitAndPrint Finishes " + Time.time ); } function WaitAndPrint (waitTime : float) { // suspend execution for waitTime seconds // 暫停執行waitTime秒 yield WaitForSeconds (waitTime); print ("WaitAndPrint "+ Time.time ); }作用:一個協同程序在執行過程中,可以在任意位置使
用yield語句。yield的返回值控制何時恢復協同程序向 下執行。協同程序在對象自有幀執行過程中堪稱優 秀。協同程序在性能上沒有更多的開銷。 缺點:協同程序并非真線程,可能會發生堵塞。
更多協程內容:Unity零基礎到入門 ??| 小萬字教程 對 Unity 中的 協程 ??全面解析+實戰演練??
🤎數據持久化 & 資源管理
1. unity常用資源路徑有哪些
//獲取的目錄路徑最后不包含 / //獲得的文件路徑開頭包含 / Application.dataPath; //Asset文件夾的絕對路徑 //只讀 Application.streamingAssetsPath; //StreamingAssets文件夾的絕對路徑(要先判斷是否存在這個文件夾路徑) Application.persistentData ; //可讀寫//資源數據庫 (AssetDatabase) 是允許您訪問工程中的資源的 API AssetDatabase.GetAllAssetPaths; //獲取所有的資源文件(不包含meta文件) AssetDatabase.GetAssetPath(object) //獲取object對象的相對路徑 AssetDatabase.Refresh(); //刷新 AssetDatabase.GetDependencies(string); //獲取依賴項文件Directory.Delete(p, true); //刪除P路徑目錄 Directory.Exists(p); //是否存在P路徑目錄 Directory.CreateDirectory(p); //創建P路徑目錄AssetDatabase //類庫,對Asset文件夾下的文件進行操作,獲取相對路徑,獲取所有文件,獲取相對依賴項 Directory //類庫,相關文件夾路徑目錄進行操作,是否存在,創建目錄,刪除等操作2. 如何安全的在不同工程間安全 地遷移asset數據?三種方法
3. unity 提供了一個用于保存讀取數據的類,(playerPrefs),請列出保存讀取整形數據的函數
PlayerPrefs類是一個本地持久化保存與讀取數據的類
PlayerPrefs類支持3中數據類型的保存和讀取,浮點型,整形,和字符串型。
分別對應的函數為:
SetInt();保存整型數據;GetInt();讀取整形數據;
SetFloat();保存浮點型數據; GetFlost();讀取浮點型數據;
SetString();保存字符串型數據; GetString();讀取字符串型數據;
4. 動態加載資源的方式?
- instantiate:最簡單的一種方式,以實例化的方式動態生成一個物體。
- Assetsbundle:即將資源打成 asset bundle 放在服務器或本地磁盤,然后使用WWW模塊get 下來,然后從這個bundle中load某個object,unity官方推薦也是絕大多數商業化項目使用的一種方式。
- Resource.Load:可以直接load并返回某個類型的Object,前提是要把這個資源放在Resource命名的文件夾下,Unity不管有沒有場景引用,都會將其全部打入到安裝包中
- AssetDatabase.loadasset :這種方式只在editor范圍內有效,游戲運行時沒有這個函數,它通常是在開發中調試用的。
5. AssetsBundle 打包
using UnityEditor; using System.IO;public class CreateAssetBundles //進行AssetBundle打包 {[MenuItem("Assets/Build AssetBundles")]static void BuildAllAssetBundles(){string dir = "AssetBundles";if (Directory.Exists(dir) == false){Directory.CreateDirectory(dir);}BuildPipeline.BuildAssetBundles(dir, //路徑必須創建BuildAssetBundleOptions.ChunkBasedCompression, //壓縮類型***BuildTarget.StandaloneWindows64);//平臺***} }| UncompressedAssetBundle | Don’t compress the data when creating the asset bundle.(不壓縮,解壓快) |
| ChunkBasedCompression | Use chunk-based LZ4 compression when creating the AssetBundle. |
(壓縮率比LZMA低,解壓速度接近無壓縮)|
6. AssetBundle加載
第一種
IEnumerator Start() {string path = "AssetBundles/wall.unity3d";AssetBundleCreateRequest request =AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));yield return request;AssetBundle ab = request.assetBundle;GameObject wallPrefab = ab.LoadAsset<GameObject>("Cube");Instantiate(wallPrefab); }第二種
IEnumerator Start() { string path = "AssetBundles/wall.unity3d";AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path);yield return request;AssetBundle ab = request.assetBundle;GameObject wallPrefab = ab.LoadAsset<GameObject>("Cube");Instantiate(wallPrefab); }第三種
IEnumerator Start() {string uri = @"http://localhost/AssetBundles/cubewall.unity3d";UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);yield return request.Send();AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);GameObject wallPrefab = ab.LoadAsset<GameObject>("Cube");Instantiate(wallPrefab); }第四種WWW(無依賴)
private IEnumerator LoadNoDepandenceAsset(){string path = "";if (loadLocal){ #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WINpath += "File:///"; #endif #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSXpath += "File://"; #endifpath += assetBundlePath + "/" + assetBundleName;//www對象WWW www = new WWW(path);//等待下載【到內存】yield return www;//獲取到AssetBundleAssetBundle bundle = www.assetBundle;//加載資源GameObject prefab = bundle.LoadAsset<GameObject>(assetRealName);//Test:實例化Instantiate(prefab);}第四種WWW(有依賴)
using System.Collections; using System.IO; using UnityEngine; using UnityEngine.Networking;public class LoadAssetsDemo : MonoBehaviour {[Header("版本號")]public int version = 1;[Header("加載本地資源")]public bool loadLocal = true;[Header("資源的bundle名稱")]public string assetBundleName;[Header("資源的真正的文件名稱")]public string assetRealName;//bundle所在的路徑private string assetBundlePath;//bundle所在的文件夾名稱private string assetBundleRootName;private void Awake(){assetBundlePath = Application.dataPath + "/OutputAssetBundle";assetBundleRootName = assetBundlePath.Substring(assetBundlePath.LastIndexOf("/") + 1);Debug.Log(assetBundleRootName);}IEnumerator LoadAssetsByWWW(){string path=""; //判斷是不是本地加載if(loadLocal)// loadLocal=true為本地資源{ #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WINpath+="File:///"; #endif #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSXpath+="File://"; #edif}//獲取要加載的資源路徑【bundle的總說明文件】path+=assetBundle+"/"+assetBundleRootName;//加載WWW www=WWW.LoadFromCacheOrDownload(path,version);yield return www;//拿到其中的bundleAssetBundle manifestBundle=www.assetsBundle;//獲取到說明文件AssetBundleManifest manifest=manifest.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//獲取資源的所有依賴string[] dependencies=manifest.GetAllDependencies(assetBundleName);//卸載Bubdle和解壓出來的manifest對象manifestBundle.Unload(true);//獲取到相對路徑path =path.Remove(path.LastIndexOf("/")+1);//聲明依賴的Bundle數組AssetBundle[] depAssetBundle=new AssetBundle[dependencies.Length];//遍歷加載所有的依賴for(int i=0;i<dependencies.Length;i++) { //獲取到依賴Bundle的路徑string depPath=path+ dependencies[i];//獲取新的路徑進行加載www=WWW.LoadFromCacheOrDownload(depPath,version);yield return www;//將依賴臨時保存depAssetBundles[i]=www.assetsBundle;}//獲取路徑path+=assBundleName;//加載最終資源www=WWW.LoadFromCacheOrDownload(path,version);//等待下載yield return www;//獲取到真正的AssetBundleAssetBundle realAssetBundle=www.assBunle;//加載真正的資源GameObject prefab=realAssetBundle.LoadAsset<GameObject>(assetBundle);//生成Instantiate(prefab);//卸載依賴for(int i-0;i<depAssetBundle.Length;i++) {depAssetBundle[i].Unload(true); }realAssetBundle.Unload(true); }}7. AssetBundle卸載流程
AssetBundle.Unload(bool),T
true卸載所有資源
false只卸載沒使用的資源,而正在使用的資源與AssetBundle依賴關系會丟失,調用Resources.UnloadUnusedAssets可以卸載。
或者等場景切換的時候自動調用Resources.UnloadUnusedAssets。
🖤Lua語言和Xlua熱更
1. Lua如何調用C#
三種方式
第一種:官方不推薦
第二種:如果Resource文件下的Lua文件,使用Lua的Require函數即可
第三種:如果Lua文件是下載的,使用自定義Loader可滿足
2. 資源如何打包?依賴項列表如何生成?
- Directory.GetFile(資源路徑)
- 新建AssetBundleBuild對象
- 獲取資源名稱,并賦值對應AB名稱
- 獲取各個資源的依賴項:通過UnityEditor.AssetDataBase類獲取各個資源的依賴項
- BuildPipeLine.BuildAssetBundles(輸出AB包路徑)
- File.WriteAllLines(將依賴項寫入文件里)
3. 如何解析版本文件?如何加載AB包資源?具體流程是怎么樣的?
- File.ReadAllLines(讀取文件列表資源路徑URL)
- 獲取資源名稱,獲取AB包名稱,獲取依賴項,字典容器存儲
- 獲取Lua文件
- 異步加載資源AB包,AssetBundleRequest請求,AssetBundle.LoadFromFileAsync
- 先檢查依賴項,再異步加載AB包依賴項
- 加載成功后都有對應的回調方法,將資源作為參數傳入
4. 熱更新方案有哪些?以及具體熱更流程
——策略:完整更新資源放在包里
——優點:首次更新少
——缺點:安裝包下載時間長,首次安裝久
——策略:少部分資源放在包里,大部分更新資源存放在更新資源器中
——優點:安裝包小,安裝時間短,下載快
——缺點:首次更新下載解壓縮包時間舊
——海外游戲大部分是使用分包策略,平臺規定
——國內游戲大部分是使用整包策略
——Application.streamingAssestsPath 只讀目錄
——Application.persistentDatapath 可讀寫目錄
——資源服務器地址URL
——NetWorking.UnityWebRequest獲取URL , HTTP GET , 連接資源服務器
——獲取到downloadHander的文件數據Data,完成后會回調方法,將文件Data作為參數傳出
5. 簡述Lua實現面向對象的原理
6. 簡述Lua有哪8個類型?簡述用途
- nil 空——可以表示無效值,全局變量(默認賦值為nil),賦值nil ,使其被刪除
- number 整數
- table 表 ——
- string 字符
- userdata 自定義
- function 函數
- bool 布爾
- thread線程
🤍網絡
1. 客戶端與服務器交互方式有幾種?
socket通常也稱作"套接字",實現服務器和客戶端之間的物理連接,并進行數據傳輸,主要有UDP和TCP兩個協議。Socket處于網絡協議的傳輸層。
協議傳輸的主要有http協議 和基于http協議的Soap協議(web service),常見的方式是 http 的post 和get 請求,web 服務。
2. 概述序列化
序列化 簡單理解成把對象轉換為容易傳輸的格式的過程。
?如,可以序列化?個對象,然后使?HTTP通過Internet在客戶端和服務器端之間傳輸該對象
3. UDP/TCP含義,區別
UDP協議全稱是用戶數據報協議
TCP協議全稱是傳輸控制協議是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。三次握手、四次揮手
TCP:
4. TCP/IP協議棧各個層次及分別的功能?
網絡接口層:這是協議棧的最低層,對應OSI的物理層和數據鏈路層,主要完成數據幀的實際發送和接收。
網絡層:處理分組在網絡中的活動,例如路由選擇和轉發等,這一層主要包括IP協議、ARP、ICMP協議等。
傳輸層:主要功能是提供應用程序之間的通信,這一層主要是TCP/UDP協議。
應用層:用來處理特定的應用,針對不同的應用提供了不同的協議,例如進行文件傳輸時用到的FTP協議,發送email用到的SMTP等。
5. 寫出WWW的幾個方法
- WWW.LoadFromCacheOrDownload:可被用于將Assets Bundles自動緩存到本地磁盤
- WWW.Dispose :釋放現有的 WWW 對象。
- WWW.isDone:是否完成下載?(只讀)
- WWW.progress:下載進度(只讀)。
6. Socket粘包
什么是粘包?
答:顧名思義,其實就是多個獨立的數據包連到一塊兒。
什么情況下需要考慮粘包?
答:實際情況如下:
1)”good good study”
2)”day day up”
那這樣的話,如果發送方連續發送這個兩個包出去,接收方一次接收可能會是”good good studyday day up” 這樣接收方就傻了,因為協議沒有規定這么奇怪的字符串,所以要把它分包處理,至于怎么分也需要雙方組織一個比較好的包結構,所以一般可能會在頭加一個數據長度之類的包,以確保接收。
所以說:Tcp連續發送消息的時候,會出現消息一起發送過來的問題,這時候需要考慮粘包的問題。
粘包出現的原因 (在流傳輸中,UDP不會出現粘包,因為它有消息邊界。)
解決粘包
注:要記住這一點:TCP對上層來說是一個流協議,所謂流,就是沒有界限的一串數據.大家可以想想河里的流水,是連成一片的,其間是沒有分界線的,也就是沒有包的概念。所以我們必須自己定義包長或者分隔符來區分每一條消息。
7. Socket的封包、拆包
答:TCP是流協議,所謂流,就是沒有界限的一串數據。但是程序中卻有多種不同的數據包,那就很可能會出現如上所說的粘包問題,所以就需要在發送端封包,在接收端拆包。
答:封包就是給一段數據加上包頭或者包尾。比如說我們上面為解決粘包所使用的兩種方法,其實就是封包與拆包的具體實現。
8. Socket 客戶端 隊列 的問題
項目中采用了socket通信,通過TCP發送數據給服務器端,因為項目需要,要同時開啟大量的線程去發送不同的數據給服務器端,然后服務器端返回不同的數據。由于操作頻繁,經常會阻塞,或沒有接收到服務器端返回的數據;
因此考慮到使用一個隊列:將同一ip下的數據存入一個隊列中,通過隊列協調發送;當第一條數據發送出去沒有收到服務器端返回的數據時,讓第二條數據插入隊列中排隊,當第三條數據也發送出來后,繼續排隊,以此類推;
如果當第四條數據發出來的時候,存入隊列中,第一條數據收服務器端返回數據后,隊列中的第二條第三條數據就扔掉,直接發送第四條數據
💖渲染 & Shader
1. 什么是LightMap?
LightMap:就是指在三維軟件?實現打好光,然后渲染把場景各表?的光照輸出到貼圖上,最后?通過引擎貼到場景上,這樣就使物體有了光照的感覺。
2. MipMap是什么,作用?
MipMapping:在三維計算機圖形的貼圖渲染中有常?的技術,為加快渲染進度和減少圖像鋸?,貼圖被處理成由?系列被預先計算和優化過的圖?組成的?件,這樣的貼圖被稱為MipMap。
3. 請問alpha test在何時使用?能達到什么效果?
Alpha Test,中文就是透明度測試。
簡而言之就是V&F shader中最后fragment函數輸出的該點顏色值(即上一講frag的輸出half4)的alpha值與固定值進行比較。Alpha Test語句通常于Pass{}中的起始位置。Alpha Test產生的效果也很極端,要么完全透明,即看不到,要么完全不透明。
4. 一個Terrain,分別貼3張,4張,5張地表貼圖,渲染速度有什么區別?為什么?
沒有區別,因為不管幾張貼圖只渲染一次。
5. 實時點光源的優缺點是什么?
可以有cookies – 帶有 alpha通道的立方圖(Cubemap )紋理。點光源是最耗費資源的。
6. 簡述水面倒影的渲染原理?
原理就是對水面的貼圖紋理進行擾動,以產生波光玲玲的效果。用shader可以通過GPU在像素級別作擾動,效果細膩,需要的頂點少,速度快
7. MeshRender中material和 sharedmaterial的區別?
修改sharedMaterial將改變所有物體使用這個材質 的外觀,并且也改變儲存在工程里的材質設置。
不推薦修改由sharedMaterial返回的材質。如果你 想修改渲染器的材質,使用material替代。
8. 什么是渲染管道?
是指在顯示器上為了顯示出圖像?經過的?系列必要 操作。 渲染管道中的很多步驟,都要將?何物體從?個坐標系中變換到另?個坐標系中去。
主要步驟有: 本地坐標->視圖坐標->背?裁剪->光照->裁剪->投影-> 視圖變換->光柵化。
GPU工作流程:頂點處理、光柵化、紋理貼圖、像素處理
- 頂點處理:這階段GPU讀取描述3D圖形外觀的頂點數 據并根據頂點數據確定3D圖形的形狀及位置關系,建 ?起3D圖形的?架。
- 光柵化:把?個??圖形轉換為 ?系列像素點的過程就稱為光柵化
- 紋理貼圖:就是將多邊形的表?貼 上相應的圖?,從??成“真實”的圖形。
- 像素處理:這階段(在對每個像素進?光柵化處理期 間)GPU完成對像素的計算和處理,從?確定每個像 素的最終屬性。
- 最終輸出:由ROP(光柵化引擎)最終完成像素的輸 出,1幀渲染完畢后,被送到顯存幀緩沖區。
總結:GPU的?作通俗的來說就是完成3D圖形的?成,將圖形映射到相應的像素點上,對每個像素進? 計算確定最終顏?并完成輸出。
9. 如何在Unity3D中查看場景的面數,頂點數和DrawCall數?如何降低DrawCall數?
在Game視圖右上?點擊Stats。降低Draw Call 的技術是Draw Call Batching
10. 寫出光照計算中的diffuse的計算公式
diffuse = Kd x colorLight x max(N*L,0);
Kd 漫反射系數、colorLight 光的顏?、N 單位法線向量、L 由點指向光源的單位向量、其中N與L點乘,如果結果?于等于0,則漫反射為0。
11. 兩種陰影判斷的方法、工作原理。
本影和半影:
本影:景物表?上那些沒有被光源直接照射的區域
(全?的輪廓分明的區域)。
半影:景物表?上那些被某些特定光源直接照射但并?被所有特定光源直接照射的區域(半明半暗區域)
?作原理:從光源處向物體的所有可??投射光線,將這些?投影到場景中得到投影?,再將這些投影?與場景中的其他平?求交得出陰影多邊形,保存這些陰影多邊形信息,然后再按視點位置對場景進?相應處理得到所要求的視圖(利?空間換時間,每次只需依據視點位置進??次陰影計算即可,省去了?次消隱過程)
12. 有A和B兩組物體,有什么辦法能夠保證A組物體永遠比B組物體先渲染?
把A組物體的渲染對列?于B物體的渲染隊列。
13. Unity的Shader中,Blend SrcAlpha OneMinusSrcAlpha這句話是什么意思?
作用就是Alpha混合。公式:最終顏色 = 源顏色源透明值 + 目標顏色(1 - 源透明值)
14. Vertex Shader是什么,怎么計算?
頂點著?器是?段執?在GPU上的程序,?來取代fixed pipeline中的transformation和lighting,Vertex Shader主要操作頂點。
Vertex Shader對輸?頂點完成了從local space到homogeneous space(?次空間)的變換過程,homogeneous space即projection space的下?個space。
在這其間共有world transformation, view transformation和projection transformation及lighting?個過程
15. Unity3D Shader分哪?種,有什么區別?
表?著?器 的抽象層次?較?,它可以輕松地以簡潔?式實現復雜著?。表?著?器可同時在前向渲染及延遲渲染模式下正常?作。
頂點?段著?器可以?常靈活地實現需要的效果,但是需要編寫更多的代碼,并且很難與Unity的渲染管線完美集成。
固定功能管線著?器可以作為前兩種著?器的備?選擇,當硬件?法運?那些酷炫Shader的時,還可以通過固定功能管線著?器來繪制出?些基本的內容。
💘優化部分
微信搜索:呆呆敲代碼的小Y 回復:白嫖 免費獲取很多的編程資料哦!更多優化知識學習文章:【Unity 優化篇】 | 優化專欄《導航帖》,全面學習Unity優化技巧,讓我們的Unity技術上升一個檔次
1. 簡述?下對象池,你覺得在FPS里哪些東西適合使用對象池?
對象池就存放需要被反復調?資源的?個空間,?如游戲中要常被大量復制的對象,?彈,敵?,以及任何重復出現的對象。
2. 什么是DrawCall?DrawCall高了又什么影響?如何降低DrawCall?
Unity中,每次引擎準備數據并通知GPU的過程稱為一次Draw Call。DrawCall越高對顯卡的消耗就越大。降低DrawCall的方法:
- Dynamic Batching
- Static Batching
- 高級特性Shader降級為統一的低級特性的Shader。
3. UI優化小知識
4. LOD是什么,優缺點是什么?
LOD(Level of detail)多層次細節,是最常用的游 戲優化技術。
它按照模型的位置和重要程度決定 物體渲染的資源分配,降低非重要物體的面數和 細節度,從而獲得高效率的渲染運算。
5. 什么叫動態合批?跟靜態合批有什么區別?
如果動態物體共用著相同的材質,那么Unity會自動對 這些物體進行批處理。動態批處理操作是自動完成 的,并不需要你進行額外的操作。
區別:動態批處理一切都是自動的,不需要做任何操 作,而且物體是可以移動的,但是限制很多。
靜態批 處理:自由度很高,限制很少,缺點可能會占用更多 的內存,而且經過靜態批處理后的所有物體都不可以 再移動了。
6. 如何優化內存?
有很多種方式,例如
7. 請簡述GC(垃圾回收)產生的原因,并描述如何避免?
GC垃圾回收機制,避免堆內存溢出,定期回收那些沒有有效引用的對象內存
GC優化,就是優化堆內存,減少堆內存,即時回收堆內存
GC歸屬于CLR
避免:
更多GC內容可查看本篇文章:
Unity零基礎到進階 ??| Unity中的 GC及優化 超級全面解析 ☆(ゝω・)v 建議收藏!
8. 貼圖透明通道分離,壓縮格式設為ETC/PVRTC
最初我們使用了DXT5作為貼圖壓縮格式,希望能減小貼圖的內存占用,但很快發現移動平臺的顯卡是不支持的。因此對于一張1024x1024大小的RGBA32貼圖,雖然DXT5可將它從4MB壓縮到1MB,但系統將它送進顯卡之前,會先用CPU在內存里將它解壓成4MB的RGBA32格式(軟件解壓),然后再將這4MB送進顯存。于是在這段時間里,這張貼圖就占用了5MB內存和4MB顯存;而移動平臺往往沒有獨立顯存,需要從內存里摳一塊作為顯存,于是原以為只占1MB內存的貼圖實際卻占了9MB!
所有不支持硬件解壓的壓縮格式都有這個問題。經過一番調研,我們發現安卓上硬件支持最廣泛的格式是ETC,蘋果上則是PVRTC。但這兩種格式都是不帶透明(Alpha)通道的。因此我們將每張原始貼圖的透明通道都分離了出來,寫進另一張貼圖的紅色通道里。這兩張貼圖都采用ETC/PVRTC壓縮。渲染的時候,將兩張貼圖都送進顯存。同時我們修改了NGUI的shader,在渲染時將第二張貼圖的紅色通道寫到第一張貼圖的透明通道里,恢復原來的顏色:
fixed4 frag (v2f i) : COLOR fixed4 col; col.rgb = tex2D(_MainTex, i.texcoord).rgb; col.a = tex2D(_AlphaTex, i.texcoord).r; return col * i.color; fixed4 frag (v2f i) : COLOR{fixed4 col;col.rgb = tex2D(_MainTex, i.texcoord).rgb;col.a = tex2D(_AlphaTex, i.texcoord).r;return col * i.color;}9. 關閉貼圖的讀寫選項
Unity中導入的每張貼圖都有一個啟用可讀可寫(Read/Write Enabled)的開關,對應的程序參數是TextureImporter.isReadable。
選中貼圖后可在Import Setting選項卡中看到這個開關。只有打開這個開關,才可以對貼圖使用Texture2D.GetPixel,讀取或改寫貼圖資源的像素,但這就需要系統在內存里保留一份貼圖的拷貝,以供CPU訪問。
一般游戲運行時不會有這樣的需求,因此我們對所有貼圖都關閉了這個開關,只在編輯中做貼圖導入后處理(比如對原始貼圖分離透明通道)時打開它。
這樣,上文提到的1024x1024大小的貼圖,其運行時的2MB內存占用又可以少一半,減小到1MB。
10. Unity 在移動設備上的?些優化資源的方法
制到200m之內,同時也可以實現資源的在線更新
獻者,降低頂點數到8萬以下,fps穩定到了30幀左右
粒?系統是cpu上的?頭
animator也是?個效率奇差的地?
animation,控制?骼數?在30根以下
animator)
collider )運動
NUGI的代碼效率很差,基本上runtime的時候對cpu的
貢獻和render不相上下
計算
11. CPU端性能優化小知識點
- 邏輯和表現盡可能分離開,這樣邏輯層的更新頻率可以適當降低些.
- 對于一些熱點函數,如mmo的實體更新、實例化,使用分幀處理,分攤單幀時間消耗.
- 做好同屏實體數量、特效數量、距離顯隱等優化.
- 完善日志輸出,避免沒必要的日志輸出,同時警惕日志字符串拼接.
- 使用骨骼烘焙 + GPUSkinning + Instance 降低CPU蒙皮骨骼消耗和drawcall.
- 開啟模型的Optimize GameObjects減少節點數量和蒙皮更新消耗.
- UI拼預制做好動靜分離,對于像血條名字這種頻繁變動的ui,做好適當的分組.
- 減少C#和lua的頻繁交互,盡量精簡兩者傳遞的參數結構.
- 使用stringbuilder優化字符串拼接的gc問題.
- 刪除非必要的腳本功能函數,特別是Update/LateUpdate類高頻執行函數,因為會產生C++到C#層的調用開銷. 對于Update里需要用到的組件、節點等提前Cache好.
- 場景里頻繁使用的資源或數據結構做好資源復用和對象池.
- 對于頻繁顯示隱藏的UI,可以先移出到屏幕外,如果長時間不顯示再進行Deactive.
- 合理拆分UI圖集,區分共用圖集和非共用圖集,共用圖集可以常駐內存,非共用圖集優先按功能分類,避免資源冗余.
使用IL2CPP, 編譯成C++版本能極大的提升整體性能. - 避免直接使用Material.Setxxx/Getxxx 等調用,這些調用會觸發材質實例化消耗,可以考慮使用 SharedMaterial / MaterialPropertyBlock代替.
- 合并Shader里的Uniform變量.
12. GPU端性能優化小知識點
- 合理規劃好渲染順序,避免不必要的overdraw,如:地形(容易被其他物件遮擋)、天空盒放到較后渲染.
- 分辨率縮放,對于填充率出現瓶頸時,這個是最簡單高效的.
- 避免使用GrabPass抓屏,不是所有硬件都支持,加之數據回拷和沒法控制分辨率性能很差,可考慮使用CommandBuffer.blit去優化.
- 控制好地形的Blend層數,控制在4層以內,考慮到地形一般屏占面積大、貼圖采樣次數多,對于中低畫質考慮不用normalmap.
- 做好物件、樹、角色的LOD.
- 避免使用RenderWithShader類方式來定制DepthTexture,可以考慮Camera的 public void SetTargetBuffers(RenderBuffer colorBuffer, RenderBuffer depthBuffer);進行優化.
- 檢查Shader的VertexInput 和 VertexOutput是否存在冗余數據.如:頂點色、多套UV.
- 警惕項目里非必要的雙面材質,對于需要局部雙面的地方通過加面解決.
- Shader里使用fixed、half代替float,理論上除position、uv、一些涉及depth相關計算使用float外,其他都應該使用fixed(主要是顏色值)、half.
- 對于角色皮膚這種不是特別明顯的效果,考慮使用預積分這種低成本的方案.
- 對于frag里的計算過程,如果可以抽出來放到CPU應用層、頂點階段的優先放這里計算. 需要注意放到頂點階段引起的平滑過渡問題. 如: eyeVec導致高光過渡問題.
- 鏡面反射類效果避免使用反射相機+RT的實現,考慮使用SSR、CubeMap類實現.
- 避免使用實時陰影,如若使用要合理控制下分辨率和陰影距離. 考慮使用Projector.
- 使用統一的后處理框架代替多個Image Effect,可以共用模糊函數,減少blit操作. 另外Unity自帶的Postprocessing V2 支持Volume,性能還是不錯的.
- Shader里避免使用分支、循環,sin、tan、pow、log等復雜數學運算.
- Unity自帶的遮擋剔除因為CPU消耗和內存占用較高,加之不能Instancing,不太適合移動平臺,可以考慮靜態預計算(缺點是不支持動態物體)、Hi-Z等優化方案.
- 減少alpha test材質的使用,如若使用注意減小面積、控制渲染順序.
13. 內存優化小知識點
- 警惕配置表的內存占用.
- 檢查ShaderLab內存占用:
- 避免使用Standard材質,做好相應的variant skip.
- 排查項目冗余的Shader.
- 使用shader_feature替代multi_compile,這樣只會收集項目里真正使用的變體組合,避免變體翻倍.
- 檢查紋理資源的尺寸、格式、壓縮方式、mipmap、Read & Write選項使用是否合理.
- 檢查Mesh資源的Read & Write選項、頂點屬性使用是否合理.
代碼級別的檢查,如Cache預分配空間、容器的Capacity、GC等. - 使用Profiler定位下GC,特別是Update類函數里的. 如:字符串拼接、濫用容器等.
- 合理控制RenderTexture的尺寸.
優化動畫Animation的壓縮方式、浮點精度、去除里面的Scale曲線數據. - 減少場景GameObject節點的數量,最好支持工具監控.
💞算法
1. 請寫出求斐波那契數列任意一位的值得算法
static int Fn(int n) { if (n <= 0) { throw new ArgumentOutOfRangeException(); } if (n == 1||n==2) { return 1; } return checked(Fn(n - 1) + Fn(n - 2)); // when n>46 memory will overflow }2. 下列代碼在運行中會產生幾個臨時對象?
string a = new string("abc"); a = (a.ToUpper() +"123").Substring(0,2);實在C#中第??是會出錯的(Java中倒是可?)。
應該這樣初始化:
三個臨時對象:abc、ABC、AB
3. 冒泡排序(手寫代碼)
public static void BubblingSort(int[]array) {for (int i = 0; i < array.Length; i++){for (int j = array.Length - 1; j > 0; j--){if (array[j] < array[i]) {int temp = array[j];array[j] = array[j-1];array[j - 1] = temp;}}}}👥總結
- 2022年全網最全的Unity面試題都在這里了,希望本篇文章能夠讓你在面試關卡如魚得水得到自己想要的工作。
- 有幾個模塊內的內容有重復的,因為考慮到某個問題會涉及不同的模塊就多寫了一遍,就當作知識強化了。
- 看完覺得有用別忘了點贊收藏哦,如果覺得哪個方面的內容不夠豐富歡迎在評論區指出!
- 如果你的Unity基礎知識還不夠熟練,也歡迎來 『Unity精品學習專欄??』 繼續學習哦!
- 如果你還有更好的面試題,歡迎在評論區提出,我整理到文章中去哦!!!
專欄推廣
-
🎬 博客主頁:https://xiaoy.blog.csdn.net
-
🎥 本文由 呆呆敲代碼的小Y 原創,首發于 CSDN🙉
-
🎄 學習專欄推薦:👑Unity系統學習專欄👑
-
🌲 游戲制作專欄推薦:👑游戲制作👑
-
🏅 歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!
-
📆 未來很長,值得我們全力奔赴更美好的生活?
-
------------------??分割線??-------------------------
Unity專欄簡介
以Unity引擎為基礎,介紹關于Unity的各種文章學習,共同進步!Unity是一款跨平臺的專業游戲引擎,用它創建的游戲可以在PC端、移動設備等常見平臺上運行。
資料白嫖,技術互助
| 🧡 Unity系統學習專欄 🧡 | 入門級 | 本專欄從Unity入門開始學習,快速達到Unity的入門水平 |
| 💛 Unity實戰類項目 💛 | 進階級 | 計劃制作Unity的 100個實戰案例!助你進入Unity世界,爭取做最全的Unity原創博客大全。 |
| ?? 游戲制作專欄 ?? | 難度偏高 | 分享學習一些Unity成品的游戲Demo和其他語言的小游戲! |
| 💚 游戲愛好者九萬人社區💚 | 互助/吹水 | 九萬人游戲愛好者社區,聊天互助,白嫖獎品 |
| 💙 Python零基礎到入門 💙 | Python初學者 | 針對沒有經過系統學習的小伙伴,核心目的就是讓我們能夠快速學習Python的知識以達到入門 |
溫馨提示: 點擊下面卡片可以獲取更多編程知識,包括各種語言學習資料,上千套PPT模板和各種游戲源碼素材等等資料。更多內容可自行查看哦!
總結
以上是生活随笔為你收集整理的2022年Unity 面试题 |五萬字 二佰道| Unity面试题大全,面试题总结【全网最全,收藏一篇足够面试】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab内置函数subs使用方法
- 下一篇: 数据结构练习题【哈夫曼树、图、排序、散列