1熏兄、委托是什么亡容,事件是委托嗎? 它們有什么區(qū)別嗤疯?
C#中委托通常是指委托類型創(chuàng)建的對(duì)象,它用于保存和調(diào)用同類型的方法萍倡,基于它可以很方便地實(shí)現(xiàn)觀察者模式身弊。事件不是委托,是委托的更安全實(shí)現(xiàn)列敲,也用于保存和調(diào)用同類型的方法阱佛,安全性體現(xiàn)在:事件對(duì)象不支持=操作符,以及只能在定義事件的類中戴而,調(diào)用事件內(nèi)所保存的方法凑术。
2、運(yùn)行string a = new string(”XYZ”)所意;代碼時(shí)淮逊,涉及幾個(gè)String對(duì)象?
2個(gè)扶踊,一個(gè)是字符串字面量"xyz"所對(duì)應(yīng)的泄鹏、駐留在一個(gè)全局共享的字符串常量池中的實(shí)例對(duì)象,另一個(gè)是通過(guò)new String(String)創(chuàng)建并初始化的秧耗、內(nèi)容與"xyz"相同的實(shí)例對(duì)象备籽。a是string類型的引用變量,非實(shí)例對(duì)象分井。
3车猬、值類型與引用類型的區(qū)別?
在C#中尺锚,基于值類型創(chuàng)建變量時(shí)珠闰,會(huì)創(chuàng)建相應(yīng)類型的對(duì)象,并用變量名進(jìn)行標(biāo)識(shí)瘫辩,可直接用于存儲(chǔ)數(shù)據(jù)伏嗜,其對(duì)象內(nèi)存一般位于棧區(qū)。
而基于引用類型創(chuàng)建變量時(shí)伐厌,其變量為引用變量阅仔,并沒(méi)有創(chuàng)建引用類型的對(duì)象。引用類型的變量弧械,需要引向堆區(qū)的引用類型對(duì)象,通過(guò)它將數(shù)據(jù)存放到堆區(qū)對(duì)象空民。
4刃唐、腳本生命周期從開(kāi)始到結(jié)束羞迷,寫(xiě)出幾種系統(tǒng)調(diào)用的方法?
Awake画饥、OnEnable衔瓮、Reset、Start抖甘、FixedUpdate热鞍、Update、LateUpdate衔彻、OnGUI薇宠、OnApplicationPause、OnApplicationQuit艰额、OnDisable澄港、OnDestroy
[if !supportLists](1)?? [endif]Awake(用于在游戲開(kāi)始之前初始化變量或游戲狀態(tài),用Awake來(lái)設(shè)置腳本間的引用柄沮,能用來(lái)執(zhí)行協(xié)同程序)
[if !supportLists](2)??[endif]Start(函數(shù)只在腳本實(shí)例被啟用時(shí)才會(huì)執(zhí)行回梧,如果游戲?qū)ο箝_(kāi)啟了,對(duì)象上綁定的腳本實(shí)例被禁用了祖搓,那么Start函數(shù)不會(huì)執(zhí)行狱意。并且Start函數(shù)只會(huì)在腳本實(shí)例首次被開(kāi)啟時(shí)才會(huì)執(zhí)行。如果是已經(jīng)開(kāi)啟過(guò)的腳本實(shí)例被關(guān)閉后再次開(kāi)啟拯欧,那么Start函數(shù)不會(huì)再次執(zhí)行)
[if !supportLists](3)?? [endif]Update(正常幀更新详囤,用于更新邏輯。每一幀都執(zhí)行哈扮,ixedUpdate比較適用于物理引擎的計(jì)算纬纪,因?yàn)槭歉繋秩居嘘P(guān)。Update就比較適合做控制滑肉。)
[if !supportLists](4)?? [endif]FixedUpdate(固定幀更新包各,其中“Fixed?Timestep”選項(xiàng)用于設(shè)置FixedUpdate()的更新頻率,更新頻率默認(rèn)為0.02)
[if !supportLists](5)?? [endif]LateUpdate:在所有Update函數(shù)調(diào)用后被調(diào)用靶庙,和fixedupdate一樣都是每一幀都被調(diào)用執(zhí)行问畅,這可用于調(diào)整腳本執(zhí)行順序,LateUpdate,在每幀Update執(zhí)行完畢調(diào)用六荒,他是在所有update結(jié)束后才調(diào)用护姆,比較適合用于命令腳本的執(zhí)行。
[if !supportLists](6)?? [endif].OnGUI:在渲染和處理GUI事件時(shí)調(diào)用掏击,每幀執(zhí)行一次卵皂。
[if !supportLists](7)?? [endif]Reset:(在用戶點(diǎn)擊檢視面板的Reset按鈕或者首次添加該組件時(shí)被調(diào)用。此函數(shù)只在編輯模式下被調(diào)用砚亭。Reset最常用于在檢視面板中給定一個(gè)默認(rèn)值灯变。)
[if !supportLists](8)?? [endif]OnDisable:(當(dāng)物體被銷毀時(shí) OnDisable將被調(diào)用殴玛,并且可用于任意清理代碼。腳本被卸載時(shí)添祸,OnDisable將被調(diào)用滚粟,OnEnable在腳本被載入后調(diào)用。注意: OnDisable不能用于協(xié)同程序刃泌。)
[if !supportLists](9)?? [endif]OnDestroy:當(dāng)MonoBehaviour將被銷毀時(shí)凡壤,這個(gè)函數(shù)被調(diào)用。OnDestroy只會(huì)在預(yù)先已經(jīng)被激活的游戲物體上被調(diào)用耙替。注意:OnDestroy也不能用于協(xié)同程序亚侠。
[if !supportLists](10) [endif]OnEnable:腳本組件被激活的時(shí)候運(yùn)行,且每次被重新激活林艘,都會(huì)運(yùn)行一次
GameObject的Activity為true盖奈,腳本的enable為true時(shí),其先后順序?yàn)椋篈wake狐援、OnEnable钢坦、Start;
GameObject
的Activity為true啥酱,腳本的enable為false時(shí),只運(yùn)行Awake爹凹;
GameObject的Activity為false時(shí),以上都不調(diào)用镶殷,OnDisable()被調(diào)用禾酱;
Awake --> OnEnable -->?Start --> Update --> FixedUpdate -->
LateUpdate -->OnGUI --> OnDisable -->OnDestroy
5、資源動(dòng)態(tài)加載的方式有哪幾種绘趋?
(1)通過(guò)Resources模塊的load方法颤陶,可以直接load并返回某個(gè)類型的Object,前提是要把這個(gè)資源放在Resource命名的文件夾下陷遮,Unity不關(guān)有沒(méi)有場(chǎng)景引用滓走,都會(huì)將其全部打入到安裝包中。
(2)通過(guò)AssetBundle的形式:即將資源打成 asset bundle 放在服務(wù)器或本地磁盤(pán)帽馋,然后使用www模塊get 下來(lái)搅方,然后從這個(gè)bundle中l(wèi)oad某個(gè)object。
(3)通過(guò)AssetDatabase.loadasset:這種方式只在editor范圍內(nèi)有效绽族,游戲運(yùn)行時(shí)沒(méi)有這個(gè)函數(shù)姨涡,它通常是在開(kāi)發(fā)中調(diào)試用的
6、ArrayList 與List<Int>的區(qū)別吧慢?
ArrayList是非泛型集合類涛漂,不是類型安全的。ArrayList在管控對(duì)象時(shí)检诗,需要保證其為object類型的子類怖喻。在使用對(duì)象時(shí)底哗,還需要將它們轉(zhuǎn)化為對(duì)應(yīng)的原類型來(lái)處理。期間锚沸,容易出現(xiàn)類型不匹配的情況。另外涕癣,在管控和使用對(duì)象時(shí)哗蜈,還可能存在了裝箱與拆箱的操作,會(huì)帶來(lái)很大的性能損耗坠韩。
List<Int>是泛型集合距潘,不存在裝箱與拆箱和類型安全的問(wèn)題,C#中推薦使用泛型集合只搁。
7音比、LOD是什么,優(yōu)缺點(diǎn)氢惋。LOD是什么洞翩,優(yōu)缺點(diǎn)?
LOD全稱是Level of Detail焰望,也就是細(xì)節(jié)層級(jí)骚亿。LOD是一個(gè)用于性能優(yōu)化的方案,它根據(jù)物體與攝像機(jī)的距離來(lái)展示這個(gè)物體不同的mesh熊赖,從而使得物體較遠(yuǎn)是使用面數(shù)比較少的mesh来屠,而距離近的時(shí)候使用面數(shù)多的mesh。
缺點(diǎn)是:需要占用更多的內(nèi)存震鹉,而且如果沒(méi)有調(diào)整好距離的話俱笛,可能會(huì)造成模擬的突變。
8传趾、哪些情況下迎膜,Unity3D 中會(huì)發(fā)生在組件上出現(xiàn)數(shù)據(jù)丟失的情況?
組件上引用的資源被刪除墨缘,常出現(xiàn)在:工程間進(jìn)行數(shù)據(jù)遷移星虹;在資源視圖誤刪資源。
9镊讼、MeshRenderer中有屬性.material,以及.sharedMaterial宽涌。兩者有什么區(qū)別?
sharedMaterial 是共用的 Material蝶棋,稱為共享材質(zhì)卸亮。修改共享材質(zhì)會(huì)改變所用使用該材質(zhì)的物體,并且編輯器中的材質(zhì)設(shè)置也會(huì)改變玩裙。
material 是獨(dú)立的 Material兼贸,返回分配給渲染器的第一個(gè)材質(zhì)段直。修改材質(zhì)僅會(huì)改變?cè)撐矬w的材質(zhì)。如果該材質(zhì)被其他的渲染器使用溶诞,將克隆該材質(zhì)并用于當(dāng)前的渲染器鸯檬。
10、當(dāng)camera距離一個(gè)模型很近螺垢,靠近攝像機(jī)的mesh出現(xiàn)部分丟失喧务,應(yīng)該如何優(yōu)化這種現(xiàn)象。
拉近攝像機(jī)的近裁剪面枉圃。
11功茴、簡(jiǎn)述Unity的協(xié)同程序,并寫(xiě)出任意一個(gè)示例程序孽亲。
unity協(xié)程是一個(gè)能暫停執(zhí)行坎穿,暫停后立即返回,直到中斷指令完成后繼續(xù)執(zhí)行的函數(shù)返劲。它類似一個(gè)子線程單獨(dú)出來(lái)處理一些問(wèn)題玲昧,性能開(kāi)銷較小,但是他在一個(gè)MonoBehaviour提供的主線程里只能有一個(gè)處于運(yùn)行狀態(tài)的協(xié)程旭等。
12.如何理解消息機(jī)制酌呆,你用過(guò)哪些消息事件系機(jī)制?請(qǐng)簡(jiǎn)單描述一下消息機(jī)制的實(shí)現(xiàn)方法搔耕。(最好用代碼或者偽代碼設(shè)計(jì)出來(lái)一個(gè)簡(jiǎn)單的消息機(jī)制)隙袁。
消息機(jī)制的主要作用是解耦和。消息的發(fā)送者不需要了解接收者的具體情況弃榨,完全零耦合菩收。可以基于事件來(lái)進(jìn)行消息的監(jiān)聽(tīng)鲸睛,內(nèi)部用Dictinary進(jìn)行保存事件和消息一一對(duì)應(yīng)娜饵,將委托添加到對(duì)應(yīng)事件的監(jiān)聽(tīng)中,發(fā)送消息時(shí)官辈,對(duì)Dictinary對(duì)應(yīng)的事件進(jìn)行調(diào)用即可箱舞。
13、你覺(jué)得在FPS里哪些東西適合使用對(duì)象池拳亿,請(qǐng)簡(jiǎn)述一下對(duì)象池晴股。
在FPS游戲中,經(jīng)常被大量創(chuàng)建的同類型對(duì)象肺魁,包括子彈电湘,敵人,粒子等,都適合使用對(duì)象池進(jìn)行管理寂呛。
unity中一些需要頻繁創(chuàng)建和銷毀的對(duì)象怎诫,在銷毀時(shí)會(huì)頻繁的調(diào)用gc,非常占用cpu時(shí)贷痪,造成性能瓶頸幻妓。這時(shí)候就需要對(duì)象池技術(shù)。使用對(duì)象池在銷毀時(shí)并不調(diào)用gc劫拢,而是僅僅將需要銷毀的obj失活涌哲,當(dāng)再次創(chuàng)建同類對(duì)象時(shí),在對(duì)象池中查找可以使用的對(duì)象進(jìn)行調(diào)用尚镰。僅僅在需要的時(shí)候調(diào)用gc進(jìn)行一次銷毀。這樣做大大減少了cpu的壓力哪廓,但是增大了內(nèi)存的消耗狗唉,通常情況這種犧牲是值得的。
14涡真、常見(jiàn)的Unity的優(yōu)化主要有哪些分俯,著重點(diǎn)是那些?
使用LOD哆料、Mipmap提供渲染速度缸剪。注意:Mipmap類似于LOD,但LOD是針對(duì)于模型來(lái)處理东亦,Mip是針對(duì)貼圖紋理來(lái)處理杏节。
對(duì)象池,提高游戲性能典阵;數(shù)據(jù)緩存層設(shè)計(jì)奋渔,提高資源加載速度;
使用光照探頭或 烘培靜態(tài)光照貼圖壮啊,提高光照渲染效率嫉鲸;
紋理圖集合并,減少DC歹啼;
恰當(dāng)使用Unity提供的靜態(tài)合并和動(dòng)態(tài)合并方式玄渗,減少DC。
在拼接或連接大量字符串時(shí)狸眼,需使用StringBuilder藤树,減少GC。
15份企、在Unity中使用線程有什么要注意的?
unity中使用c#的多線程時(shí)不能使用修改unity相關(guān)函數(shù)也榄、屬性,使用時(shí)Unity會(huì)報(bào)錯(cuò)提示。當(dāng)需要進(jìn)行修改位置甜紫,旋轉(zhuǎn)之類的操作時(shí)降宅,可以創(chuàng)建一個(gè)單例Mono類對(duì)象,開(kāi)啟協(xié)程囚霸。操作需要在Unity主線程中的操作函數(shù)時(shí)腰根,對(duì)該單例類添加一個(gè)委托,在單例類協(xié)程中持續(xù)判斷委托拓型。如果存在委托就執(zhí)行并且清空额嘿。
僅能從主線程中訪問(wèn)Unity3D的組件,對(duì)象和Unity3D系統(tǒng)調(diào)用支持劣挫。如果同時(shí)你要處理很多事情或者且與Unity的對(duì)象互動(dòng)少册养,可以用thread,否則使用coroutine。注意:C#中有l(wèi)ock這個(gè)關(guān)鍵字,用來(lái)確保只有一個(gè)線程可以在特定時(shí)間內(nèi)訪問(wèn)特定的對(duì)象压固。
16球拦、使用mipmap有什么好處和壞處?什么情況下使用帐我?
Mipmap坎炼,稱為多級(jí)漸進(jìn)紋理。為了加快渲染速度和減少紋理鋸齒拦键,貼圖被處理成由一系列被預(yù)先計(jì)算和優(yōu)化過(guò)的圖片組成的文件谣光,這樣的貼圖被稱為Mipmap。常用于:根據(jù)攝像機(jī)距離模型的遠(yuǎn)近而調(diào)整使用不同質(zhì)量的貼圖芬为。
[if !vml]
[endif]?
Mipmap寬高值不一定要相等萄金,但需要為2的n次冪,最低精度為1x1碳柱;從原始高精度的Mipmap寬高減半捡絮,逐級(jí)生成低精度的Mipmap層級(jí);所有低精度層級(jí)加起來(lái)莲镣,會(huì)增加1/3存儲(chǔ)空間的占用:A福稳、Mipmap貼圖文件占用更多硬盤(pán)空間,解決方法:使用dds進(jìn)行壓縮存儲(chǔ)瑞侮。B的圆、Mipmap紋理占用更多內(nèi)存、顯存空間半火。
17越妈、手寫(xiě)除了冒泡外的,你已知的排序算法钮糖。
常見(jiàn):快速排序梅掠,堆排序酌住,插入排序等。
18阎抒、請(qǐng)簡(jiǎn)述GC(垃圾回收)產(chǎn)生的原因酪我,并描述何如避免?
當(dāng)我用new創(chuàng)建一個(gè)對(duì)象時(shí)且叁,當(dāng)可分配的內(nèi)存不足GC就會(huì)去回收未使用的對(duì)象都哭,但是GC的操作是非常復(fù)雜的,會(huì)占用很多CPU時(shí)間逞带,對(duì)于移動(dòng)設(shè)備來(lái)說(shuō)頻繁的垃圾回收會(huì)嚴(yán)重影響性能欺矫。
下面的建議可以避免GC頻繁操作。
減少用new創(chuàng)建對(duì)象的次數(shù)展氓,在創(chuàng)建對(duì)象時(shí)會(huì)產(chǎn)生內(nèi)存碎片穆趴,這樣會(huì)造成碎片內(nèi)存不法使用
使用公用的對(duì)象(靜態(tài)成員,常量)遇汞,但是不能亂用毡代,因?yàn)殪o態(tài)成員和常量的生命周期是整個(gè)應(yīng)用程序。
在拼接大量字符串時(shí)StringBuilder勺疼。在使用注意,創(chuàng)建StringBuilder對(duì)象時(shí)要設(shè)置StringBuilder的初始大小如:StringBuilder sb1
=new StringBuilder (size);
使用object pool(對(duì)象池)
19捏鱼、時(shí)間復(fù)雜度和空間復(fù)雜度执庐,是什么?給出冒泡排序和快速排序的時(shí)間和空間復(fù)雜度
算法的時(shí)間復(fù)雜度(Time Complexity)导梆,用來(lái) 衡量算法執(zhí)行時(shí)所需“時(shí)間”轨淌,它是對(duì) 【程序基本操作重復(fù)執(zhí)行的次數(shù)與問(wèn)題規(guī)模n的函數(shù)f(n)】進(jìn)行【O()運(yùn)算】的結(jié)果,常記為T(mén)(n)
算法的空間復(fù)雜度(Space Complexity)看尼,是對(duì)一個(gè)算法在運(yùn)行過(guò)程中【臨時(shí)額外】占用存儲(chǔ)空間大小的量度递鹉,常記為 S(n) 。它是 對(duì) 【額外空間與問(wèn)題規(guī)模n的函數(shù)f(n)】 進(jìn)行【O()運(yùn)算】的結(jié)果藏斩。
?時(shí)間復(fù)雜度空間復(fù)雜度
冒泡排序O(n2)O(1)
快速排序O(n2)O(nlog2n)
直接插入O(n2)O(1)
20躏结、有兩段代碼if(go.CompareTag(“Enemy”)) 和if(go.tag==”Enemy”)有什么區(qū)別?
go.CompareTag調(diào)用一次內(nèi)部方法就完成了比較,但go.tag要先花時(shí)間調(diào)用一次getter來(lái)獲得字符串狰域,消耗的時(shí)間相比CompareTag會(huì)更多媳拴。建議,使用CompareTag替換所有的tag兆览。
21屈溉、已知道List<int> list1=new
List<int>(new int[](1,2,3,4,5)),請(qǐng)問(wèn)抬探,如果用foreach操作lst1子巾,有什么需要注意的?
使用foreach遍歷容集合時(shí),可以得到對(duì)象的標(biāo)識(shí)符或引用线梗。但是無(wú)法增加椰于、刪除,修改缠导,該集合對(duì)象所管控的元素廉羔。
22、string tmp = "你好僻造,我愛(ài)編程1锼!";髓削,請(qǐng)C#編程實(shí)現(xiàn)截出“我愛(ài)編程”竹挡;
string ret1 = tmp.Substring(3, 4); ?
//C#中char型是2個(gè)字節(jié),一個(gè)char變量可以存放一個(gè)漢字立膛。
// string類的其他常見(jiàn)方法見(jiàn) 文字課件揪罕。
23、寫(xiě)出UGUI中監(jiān)聽(tīng)事件的幾種方式
在腳本代碼中宝泵,使用代碼好啰,添加事件監(jiān)聽(tīng),比如:onClick.addListener等儿奶;
在腳本組件的檢視視圖中框往,手動(dòng)添加事件監(jiān)聽(tīng)的對(duì)象,并設(shè)置回調(diào)函數(shù)闯捎;
在腳本代碼中椰弊,繼承相關(guān)事件的接口,實(shí)現(xiàn)對(duì)事件的監(jiān)聽(tīng)瓤鼻,比如:IBeginDrag等秉版。
24、四元數(shù)的作用茬祷,四元數(shù)對(duì)歐拉角的優(yōu)點(diǎn)清焕?基于偽代碼:給出基于四元數(shù),緩慢旋轉(zhuǎn)到指定朝向(使用Vector3表示)的實(shí)現(xiàn)
四元數(shù)和歐拉角祭犯,均用于表示物體的朝向耐朴,在unity中分別使用Quaternion類和Vector3類進(jìn)行描述和實(shí)現(xiàn)。
歐拉角在表示物體朝向時(shí)盹憎,優(yōu)點(diǎn)是:容易理解和形象直觀筛峭,缺點(diǎn)是:在兩個(gè)歐拉角之間,無(wú)法做插值運(yùn)算陪每;對(duì)于一個(gè)給定的朝向影晓,表示方式不唯一镰吵;有萬(wàn)向節(jié)死鎖(Gimbal Lock)的現(xiàn)象。
四元數(shù)挂签,在表示物體朝向時(shí)葬荷,優(yōu)點(diǎn)是:可以避免萬(wàn)向節(jié)鎖現(xiàn)象催蝗,可以提供平滑插值踢关;某些情況下咐鹤,使用四元數(shù)實(shí)現(xiàn)旋轉(zhuǎn),更加高效侨核。缺點(diǎn)是:理解困難草穆,不直觀;
實(shí)現(xiàn)代碼:
????? Quaternion dstRotation =Quaternion.LookRotation(dstDirection, Vector3.up);
this.transform.rotation =Quaternion.Slerp(transform.rotation, dstRotation, Time.deltaTime * 2.0f);
25搓译、什么是渲染管道 或 渲染管線悲柱?
渲染管線是指為了在顯示器上,顯示出圖像而經(jīng)過(guò)的一系列必要操作些己。渲染管道中的很多步驟豌鸡,都要將幾何物體從一個(gè)坐標(biāo)系中變換到另一個(gè)坐標(biāo)系中去。主要步驟有:本地坐標(biāo)->視圖坐標(biāo)->背面裁剪->光照->裁剪->投影->視圖變換->光柵化段标。
[if !vml]
[endif]?
具體參見(jiàn)《Shader入門(mén)精要》涯冠。
26、談?wù)剆hader的類型和各自在什么時(shí)候使用逼庞。通常Shader中是如何將圖片變成灰度圖功偿。
Shader按管線分類一般分為固定渲染管線與可編程渲染管線。
1往堡、固定渲染管線
這是標(biāo)準(zhǔn)的幾何&光照(Transforming&Lighting)管線,功能是固定的共耍,它控制著世界虑灰、視、投影變換及固定光照控制和紋理混合痹兜。T&L管線可以被渲染狀態(tài)控制穆咐,矩陣,光照和采制參數(shù)字旭。功能比較有限对湃。基本所有的顯卡都能正常運(yùn)行遗淳。
2拍柒、可編程渲染管線
對(duì)渲染管線中的頂點(diǎn)運(yùn)算和像素運(yùn)算分別進(jìn)行編程處理,而無(wú)須象固定渲染管線那樣套用一些固定函數(shù)屈暗,取代設(shè)置參數(shù)來(lái)控制管線拆讯。
27脂男、Unity3d的三種Shader:
1、固定功能著色器(Fixed Function Shader)
固定功能著色器為固定功能渲染管線的具體表現(xiàn)种呐。功能較簡(jiǎn)單兼容比較老的機(jī)器
2宰翅、頂點(diǎn)和片段著色器(Vertex and Fragment Shader)
最強(qiáng)大的Shader類型,屬于可編程渲染管線爽室, 使用的是CG/HLSL語(yǔ)法汁讼。
3、表面著色器(Surface Shade)
Unity3d推崇的Shader類型阔墩,使用Unity預(yù)制的光照模型來(lái)進(jìn)行光照運(yùn)算嘿架。使用的也是CG/HLSL語(yǔ)法。
圖片灰度化:
修改對(duì)應(yīng)Shader中的灰色公式戈擒,設(shè)置為:Gray = R*0.299 + G*0.587 +
B*0.114眶明,即可實(shí)現(xiàn)圖片變灰的效果。比如:UGUI中彩色UI變灰色筐高,找到UI-Default.shader搜囱,復(fù)制,重命名為UI-Gray.shader, 將frag函數(shù)修改為如上參數(shù)即可柑土。
28蜀肘、Unity3D Shader分為哪幾種,有什么區(qū)別稽屏?
1扮宠、表面著色器,的抽象層次比較高狐榔,它可以輕松地以簡(jiǎn)潔方式實(shí)現(xiàn)復(fù)雜著色坛增。表面著色器可同時(shí)在前向渲染及延遲渲染模式下正常工作。
2薄腻、頂點(diǎn)片段著色器收捣,可以非常靈活地實(shí)現(xiàn)需要的效果,但是需要編寫(xiě)更多的代碼庵楷,并且很難與Unity的渲染管線完美集成罢艾。
3、固定功能管線著色器尽纽,可以作為前兩種著色器的備用選擇咐蚯,當(dāng)硬件無(wú)法運(yùn)行那些酷炫Shader的時(shí),還可以通過(guò)固定功能管線著色器來(lái)繪制出一些基本的內(nèi)容弄贿。
29春锋、在VR游戲中,前向渲染和延遲渲染應(yīng)該選擇哪一個(gè)差凹,為什么看疙?
前向渲染 提供更快的基線和更快的渲染通道豆拨,可在 VR 平臺(tái)擁有更好的性能。前向渲染不僅速度更快能庆,相較于延遲渲染器它還擁有更多抗鋸齒選項(xiàng)施禾,帶來(lái)更為清晰明快的顯示效果。
//以下了解
[if !vml]
[endif]?
Forward Rendering(正向渲染/前向渲染)是大多數(shù)渲染引擎使用的渲染技術(shù)搁胆。你給顯卡提供幾何對(duì)象弥搞,它將幾何對(duì)象分解成頂點(diǎn)送入頂點(diǎn)著色器,然后把這些頂點(diǎn)數(shù)據(jù)插值后分別送入片元/像素著色器渠旁,然后在它們被送入屏幕前做最終的渲染處理(模板測(cè)試攀例,混合等)。
[if !vml]
[endif]?
Deferred Rendering(延遲渲染)顾腊,從這個(gè)名字來(lái)看就意味著渲染是被延遲的粤铭,直到所有幾何對(duì)象都已經(jīng)通過(guò)渲染管線處理后,在最后才應(yīng)用著色(通過(guò)光照來(lái)決定最終的像素顏色)并產(chǎn)生最終的圖像杂靶。
[if !vml]
[endif]?
30梆惯、什么是drawcall?敘述下Unity3d中的drawcall合并
在使用unity的時(shí)候經(jīng)常會(huì)要求盡量降低Draw call和Batched 的數(shù)量吗垮。那么Draw call 和Batched 到底指的是什么呢垛吗?
Draw Call: Unity生成一幀的畫(huà)面的處理過(guò)程大致過(guò)程是:
引擎經(jīng)過(guò)可見(jiàn)性測(cè)試,確定攝像機(jī)可以看到的物體烁登,然后把這些物體的頂點(diǎn)(包括頂點(diǎn)位置怯屉、法線、uv 等),索引(如何組成三角形),變換(物體的位置旋轉(zhuǎn) 縮放 以及攝像機(jī)的位置)相關(guān)光源饵沧,紋理锨络,渲染方式(由材質(zhì)/Shader決定)等數(shù)據(jù)準(zhǔn)備好,然后通知圖形API(或者就簡(jiǎn)單地看作是通知GPU)開(kāi)始繪制狼牺,GPU基于這些數(shù)據(jù)經(jīng)過(guò)一些列的運(yùn)算羡儿,在屏幕上畫(huà)出組成圖形的三角形,構(gòu)成一幅畫(huà)锁右。
在unity 中每次引擎裝備數(shù)據(jù)并通知GPU的過(guò)程為一次Draw Call。
為什么要優(yōu)化DrawCall讶泰?
因?yàn)橥ㄖoGPU這個(gè)工作是由CPU來(lái)完成的咏瑟,完成每一次DrawCall都需要CPU完成很多的內(nèi)容,因此如果DrawCall很多的話CPU一定是不堪重負(fù)痪署。但對(duì)于GPU而言码泞,很多的工作都是一樣的,也就是說(shuō)很多的DrawCall是沒(méi)有意義的狼犯,可以理解為很多次的DrawCall都可以合并為一次余寥,這樣減輕了CPU的負(fù)擔(dān)领铐,同樣也可以通知GPU完成相應(yīng)的工作。因此減少DrawCall成了優(yōu)化CPU的第一要?jiǎng)?wù)宋舷。
Batched: Batched 其實(shí)是Draw Call的另外一種稱呼绪撵。你可以想象成 每一次的Draw Call 是CPU把一個(gè)Batched里的數(shù)據(jù)(物體的頂點(diǎn)數(shù)據(jù))傳輸給GPU,由GPU繪制到屏幕上祝蝠。因此Batched越多需要傳輸?shù)臄?shù)據(jù)就越多音诈,產(chǎn)生的Draw Call也會(huì)越多,也會(huì)消耗更多的性能绎狭。
Unity提供了Dynamic Batching和Static
Batching兩種方式细溅。
//具體見(jiàn)https://docs.unity3d.com/Manual/DrawCallBatching.html
31、如何優(yōu)化內(nèi)存
代碼級(jí)別優(yōu)化:
1儡嘶、連接兩個(gè)字符串的操作使用StringBuilder.Append來(lái)代替string喇聊。
2、使用gameObject.CompareTag("XXX")來(lái)代替gameObject.tag = xxx蹦狂。
3誓篱、使用ObjectPool對(duì)象池來(lái)管理對(duì)象,避免頻繁使用的Instance鸥咖,Destroy燕鸽。
//其他補(bǔ)充
//https://blog.csdn.net/wwanrong/article/details/78676275
//https://www.bbsmax.com/R/ke5jG4Xdrl/
//http://www.reibang.com/p/14b978447135
32、寫(xiě)光照計(jì)算中diffuse的計(jì)算公式
實(shí)際光照強(qiáng)度 I= 環(huán)境光 (Iambient) + 漫反射光 (Idiffuse) + 鏡面高光(Ispecular);
環(huán)境光:Iambient= Aintensity* Acolor; (Aintensity 表示環(huán)境光強(qiáng)度啼辣,Acolor 表示環(huán)境光顏色)
漫反射光:Idiffuse = Dintensity*Dcolor*N.L;
(Dintensity 表示漫反射強(qiáng)度啊研, Dcolor 表示漫反射光顏色, N 為該點(diǎn)的法向量鸥拧, L 為光源向量)
鏡面反射光:Ispecular = Sintensity*Scolor*(R.V)^n;
(Sintensity 表示鏡面光照強(qiáng)度党远, Scolor 表示鏡面光顏色, R 為光的反射向量富弦, V 為觀察者向量沟娱, n 稱為鏡面光指數(shù))
引用類型的基類System.Object
值類型的基類System.ValueType
34.Interface 與抽象類之間的不同
答:抽象類表示該類中可能已經(jīng)有一些方法的具體定義,但接口就是公公只能定義各個(gè)方法的界面腕柜,不能具體的實(shí)現(xiàn)代碼在成員方法中济似。
類是子類用來(lái)繼承的,當(dāng)父類已經(jīng)有實(shí)際功能的方法時(shí)該方法在子類中可以不必實(shí)現(xiàn)盏缤,直接引用父類的方法砰蠢,子類也可以重寫(xiě)該父類的方法。
實(shí)現(xiàn)接口的時(shí)候必須要實(shí)現(xiàn)接口中所有的方法唉铜,不能遺漏任何一個(gè)台舱。
35. 請(qǐng)簡(jiǎn)述 ArrayList 和 List 的主要區(qū)別
答: ArrayList存在不安全類型 ‘ ( ArrayList 會(huì)把所有插入其中的數(shù)據(jù)都當(dāng)做 Object 來(lái)處理)
裝箱拆箱的操作(費(fèi)時(shí))List 是接口, ArrayList 是一個(gè)實(shí)現(xiàn)了該接口的類潭流,可以被實(shí)例化竞惋。
36.Unity3D 的協(xié)程和 C# 線程之間的區(qū)別是什么柜去?
多線程程序同時(shí)運(yùn)行多個(gè)線程 ,而在任一指定時(shí)刻只有一個(gè)協(xié)程在運(yùn)行拆宛,并且這個(gè)正在運(yùn)行的協(xié)同程序只在必要時(shí)才被掛起嗓奢。除主線程之外的線程無(wú)法訪問(wèn) Unity3D 的對(duì)象、組件胰挑、方法蔓罚。 Unity3d 沒(méi)有多線程的概念,不過(guò) unity 也給我們提供了StartCoroutine (協(xié)同程序)和 LoadLevelAsync (異步加載關(guān)卡)后臺(tái)加載場(chǎng)景的方法瞻颂。StartCoroutine 為什么叫協(xié)同程序呢豺谈,所謂協(xié)同,就是當(dāng)你在 StartCoroutine 的函數(shù)體里處理一段代碼時(shí)贡这,利用 yield 語(yǔ)句等待執(zhí)行結(jié)果茬末,這期間不影響主程序的繼續(xù)執(zhí)行,可以協(xié)同工作盖矫。而LoadLevelAsync 則允許你在后臺(tái)加載新資源和場(chǎng)景丽惭,所以再利用協(xié)同,你就可以前臺(tái)用 loading 條或動(dòng)畫(huà)提示玩家游戲未卡死辈双,同時(shí)后臺(tái)協(xié)同處理加載的事宜 asynchronous[e ?? s ?? kr ? n ? s] .synchronous 同步责掏。??
37. 簡(jiǎn)述四元數(shù)的作用,四元數(shù)對(duì)歐拉角的優(yōu)點(diǎn)湃望?
答:四元數(shù)用于表示旋轉(zhuǎn)
相對(duì)歐拉角的優(yōu)點(diǎn): 1 )能進(jìn)行增量旋轉(zhuǎn) 2 )避免萬(wàn)向鎖 3 )給定方位的表達(dá)方式有兩種换衬,互為負(fù)(歐拉角有無(wú)數(shù)種表達(dá)方式)
38. 矩陣相乘的意義及注意點(diǎn)
用于表示線性變換:旋轉(zhuǎn)、縮放证芭、投影瞳浦、平移、仿射
注意矩陣的蠕變:誤差的積累
39. 向量的點(diǎn)乘废士、叉乘以及歸一化的意義叫潦?
1 )點(diǎn)乘描述了兩個(gè)向量的相似程度,結(jié)果越大兩向量越相似官硝,還可表示投影 2 )叉乘得到的向量垂直于原來(lái)的兩個(gè)向量 3 )標(biāo)準(zhǔn)化向量:用在只關(guān)系方向矗蕊,不關(guān)心大小的時(shí)候
40.為什么 dynamic font 在 unicode 環(huán)境下優(yōu)于static font
Unicode 是國(guó)際組織制定的可以容納世界上所有文字和符號(hào)的字符編碼方案。
使用動(dòng)態(tài)字體時(shí)氢架,Unity 將不會(huì)預(yù)先生成一個(gè)與所有字體的字符紋理傻咖。當(dāng)需要支持亞洲語(yǔ)言或者較大的字體的時(shí)候,若使用正常紋理达箍,則字體的紋理將非常大没龙。
41. 為什么 Unity3D 中會(huì)發(fā)生在組件上出現(xiàn)數(shù)據(jù)丟失的情況铺厨?
答:組件上綁定的對(duì)象被刪除了
42.如何安全的在不同工程間安全地遷移 asset 數(shù)據(jù)缎玫?三種方法
答:將 Assets 目錄和 Library 目錄一起遷移
導(dǎo)出包用 unity 自帶的 assets Server 功能
43.請(qǐng)描述游戲動(dòng)畫(huà)有哪幾種硬纤,以及其原理。
主要有關(guān)節(jié)動(dòng)畫(huà)赃磨、單一網(wǎng)格模型動(dòng)畫(huà) ( 關(guān)鍵幀動(dòng)畫(huà) ) 筝家、骨骼動(dòng)畫(huà)。
關(guān)節(jié)動(dòng)畫(huà)把角色分成若干獨(dú)立部分邻辉,一個(gè)部分對(duì)應(yīng)一個(gè)網(wǎng)格模型溪王,部分的動(dòng)畫(huà)連接成一個(gè)整體的動(dòng)畫(huà),角色比較靈活 Quake2 中使用了這種動(dòng)畫(huà)值骇。
單一網(wǎng)絡(luò)模型動(dòng)畫(huà)由一個(gè)完整的網(wǎng)格模型構(gòu)成莹菱,在動(dòng)畫(huà)序列的關(guān)鍵幀里記錄各個(gè)頂點(diǎn)的原位置及其改變量,然后插值運(yùn)算實(shí)現(xiàn)動(dòng)畫(huà)效果吱瘩,角色動(dòng)畫(huà)較真實(shí)道伟。
骨骼動(dòng)畫(huà),廣泛應(yīng)用的動(dòng)畫(huà)方式使碾,集成了以上兩個(gè)方式的優(yōu)點(diǎn)蜜徽,骨骼按角色特點(diǎn)組成一定的層次結(jié)構(gòu),由關(guān)節(jié)相連票摇,可做相對(duì)運(yùn)動(dòng)拘鞋,皮膚作為單一網(wǎng)格蒙在骨骼之外,決定角色的外觀矢门。皮膚網(wǎng)格每一個(gè)頂點(diǎn)都會(huì)受到骨骼的影響盆色,從而實(shí)現(xiàn)完美的動(dòng)畫(huà)。(骨骼動(dòng)畫(huà)是由關(guān)節(jié)動(dòng)畫(huà)發(fā)展而來(lái)的颅和,如今基本都使用骨骼動(dòng)畫(huà)來(lái)實(shí)現(xiàn)角色動(dòng)畫(huà))
44.兩種陰影判斷的方法工作原理
陰影由兩部分組成:本影與半影
本影:景物表面上那些沒(méi)有被光源直接照射的區(qū)域(全黑的輪廓分明的區(qū)域)
半影:景物表面上那些被某些特定光源直接照射但并非被所有特定光源直接照射的區(qū)域(半明半暗區(qū)域)
求陰影區(qū)域的方法:做兩次消隱過(guò)程
一次對(duì)每個(gè)光源進(jìn)行消隱傅事,求出對(duì)于光源而言不可見(jiàn)的區(qū)域 L ;
一次對(duì)視點(diǎn)的位置進(jìn)行消隱峡扩,求出對(duì)于視點(diǎn)而言可見(jiàn)的面S
shadow area= L ∩S
陰影分為兩種:自身陰影和投射陰影
自身陰影:因物體自身的遮擋而使光線照射不到它上面的某些可見(jiàn)面
工作原理:利用背面剔除的方法求出蹭越,即假設(shè)視點(diǎn)在點(diǎn)光源的位置。
投射陰影:因不透明物體遮擋光線使得場(chǎng)景中位于該物體后面的物體或區(qū)域受不到光照照射而形成的陰影
工作原理:從光源處向物體的所有可見(jiàn)面投射光線教届,將這些面投影到場(chǎng)景中得到投影面响鹃,再將這些投影面與場(chǎng)景中的其他平面求交得出陰影多邊形,保存這些陰影多邊形信息案训,然后再按視點(diǎn)位置對(duì)場(chǎng)景進(jìn)行相應(yīng)處理得到所要求的視圖(利用空間換時(shí)間买置,每次只需依據(jù)視點(diǎn)位置進(jìn)行一次陰影計(jì)算即可,省去了一次消隱過(guò)程)
若是動(dòng)態(tài)光源此方法就無(wú)效了强霎。
45.Vertex
Shader是什么忿项?怎么計(jì)算?
頂點(diǎn)著色器是一段執(zhí)行在GPU 上的程序,用來(lái)取代 fixed pipeline 中的transformation和 lighting 轩触, Vertex Shader 主要操作頂點(diǎn)寞酿。
Vertex Shader 對(duì)輸入頂點(diǎn)完成了從 local space 到 homogeneous space (齊次空間)的變換過(guò)程, homogeneous
space 即 projection space 的下一個(gè)space 脱柱。在這其間共有 world transformation, view transformation和 projection transformation 及l(fā)ighting幾個(gè)過(guò)程伐弹。
46.用u3d實(shí)現(xiàn)2d游戲,有幾種方式榨为?
?? 1.利用引擎自帶的GUI
?? 2.把攝像機(jī)設(shè)為 Orthographic 惨好,用面片作為 2d 元素
?? 3.利用第三方插件: NGUI 、2dToolkit
47.CharacterController和Rigidbody的區(qū)別
Rigidbody 具有完全真實(shí)物理的特性随闺,而 CharacterController 可以說(shuō)是受限的Rigidbody 日川,具有一定的物理效果但不是完全真實(shí)的。
48.u3d中矩乐,幾種施加力的方式逗鸣,描述出來(lái)
rigidbody.AddForce/AddForceAtPosition,都是 rigidbody 的成員函數(shù)
49.unity3d提供了幾種光源绰精,分別是什么
平行光:Directional Light
聚光燈:SpotLight
點(diǎn)光源:PointLight
區(qū)域光源: Area
Light (只用于烘培)
50.u3d提供了一個(gè)用于保存讀取數(shù)據(jù)的類撒璧,(playerPrefs),請(qǐng)列出保存讀取整形數(shù)據(jù)的函數(shù)
PlayerPrefs.SetInt與PlayerPrefs.GetInt
51.移動(dòng)相機(jī)動(dòng)作在哪個(gè)函數(shù)里笨使,為什么在這個(gè)函數(shù)里卿樱。
LateUpdate, ,是在所有 update 結(jié)束后才調(diào)硫椰,比較適合用于命令腳本的執(zhí)行繁调。官網(wǎng)上例子是攝像機(jī)的跟隨,都是在所有 update 操作完才跟進(jìn)攝像機(jī)靶草,不然就有可能出現(xiàn)攝像機(jī)已經(jīng)推進(jìn)了蹄胰,但是視角里還未有角色的空幀出現(xiàn)。
52.當(dāng)游戲中需要頻繁創(chuàng)建一個(gè)物體對(duì)象時(shí)奕翔,我們需要怎么做來(lái)節(jié)省內(nèi)存裕寨。
做一個(gè) pool ,游戲開(kāi)始時(shí)預(yù)先實(shí)例化足夠的數(shù)量派继,然后用的時(shí)候取不用的時(shí)候收回
53.一個(gè)場(chǎng)景放置多個(gè)camera并同時(shí)處于活動(dòng)狀態(tài)宾袜,會(huì)發(fā)生什么
實(shí)際看到的畫(huà)面由多個(gè)camera 的畫(huà)面組成,由 depth 驾窟、 Clear
Flag 庆猫、 Culling Mask都會(huì)影響最終合成效果。
54.什么叫做鏈條關(guān)節(jié)
Hinge Joint 绅络,他可以模擬兩個(gè)物體間用一根鏈條連接在一起的情況月培,能保持兩個(gè)物體在一個(gè)固定距離內(nèi)部相互移動(dòng)而不產(chǎn)生作用力嘁字,但是達(dá)到固定距離后就會(huì)產(chǎn)生拉力。(簡(jiǎn)單說(shuō)就是彈簧)
55.物體自旋轉(zhuǎn)使用的函數(shù)叫什么transform.Rotate
56.物體繞某點(diǎn)旋轉(zhuǎn)使用函數(shù)叫什么transform.RotateAround
57.什么是渲染管道杉畜?
是指在顯示器上為了顯示出圖像而經(jīng)過(guò)的一系列必要操作拳锚。 渲染管道中的很多步驟,都要將幾何物體從一個(gè)坐標(biāo)系中變換到另一個(gè)坐標(biāo)系中去寻行。
主要步驟有:
本地坐標(biāo) -> 視圖坐標(biāo) -> 背面裁剪 -> 光照-> 裁剪 -> 投影 -> 視圖變換 -> 光柵化。
58.如何優(yōu)化內(nèi)存匾荆?
1. 壓縮自帶類庫(kù)拌蜘;
2. 將暫時(shí)不用的以后還需要使用的物體隱藏起來(lái)而不是直接 Destroy 掉;
3. 釋放 AssetBundle 占用的資源牙丽;
4. 降低模型的片面數(shù)简卧,降低模型的骨骼數(shù)量,降低貼圖的大锌韭举娩;
5. 使用光照貼圖,使用多層次細(xì)節(jié) (LOD) 构罗,使用著色器 (Shader) 铜涉,使用預(yù)設(shè)(Prefab) 。
59遂唧、動(dòng)態(tài)加載資源的方式芙代?
1.Resources.Load();
2.AssetBundle
60.Animation.CrossFade命令作用是:(動(dòng)畫(huà)的淡入為其他動(dòng)畫(huà))
61.Application.loadLevel命令為:(加載關(guān)卡)
62. 使用原生 GUI 創(chuàng)建一個(gè)可以拖動(dòng)的窗口命令是什么?GUI.DragWindow();
63盖彭,在類的構(gòu)造函數(shù)前加上static會(huì)報(bào)什么錯(cuò)?為什么?
構(gòu)造函數(shù)格式為public+ 類名如果加上 static 會(huì)報(bào)錯(cuò)(靜態(tài)構(gòu)造函數(shù)不能有訪問(wèn)修飾符)
原因:靜態(tài)構(gòu)造函數(shù)不允許訪問(wèn)修飾符纹烹,也不接受任何參數(shù);??
無(wú)論創(chuàng)建多少類型的對(duì)象召边,靜態(tài)構(gòu)造函數(shù)只執(zhí)行一次铺呵;??
運(yùn)行庫(kù)創(chuàng)建類實(shí)例或者首次訪問(wèn)靜態(tài)成員之前,運(yùn)行庫(kù)調(diào)用靜態(tài)構(gòu)造函數(shù)隧熙;??
靜態(tài)構(gòu)造函數(shù)執(zhí)行先于任何實(shí)例級(jí)別的構(gòu)造函數(shù)片挂;??
顯然也就無(wú)法使用this 和 base 來(lái)調(diào)用構(gòu)造函數(shù)。