面試

本來想寫一個系列的,一半是抨擊現在面試之水,要人之奸,用大哥的話說,要走新手是做螺絲釘和抹布用的。另一半是對出出學校的或者是自廢武功轉3d的朋友們提供一個比較有價值的參考。不過我時間實在倉促。沒有保證,寫一點算一點吧。
先識別一下,你到了公司會讓你幹什麼:
1.UI(面試題會偏向NGUI等ui操作,會考到一些簡單的排序算法,數據結構,問題處理思路等)
2.數據邏輯層(會考到數據結構的搭配,配置表的構造等)
3.遊戲控制流程(會考到狀態機的設計,與服務器協議的設計,以及少量lua或python腳本編寫內容)
4.項目架構(主程內容。。你懂得。反正我還不夠格面這個。。)

UI的沒什麼好說的,去了之後天天layout,毫無樂趣,但是吧,新手都得虐過一次,纔可以。數據邏輯層,也就是統籌整個遊戲的後臺運算數據,依照網絡模塊給予的數據,維護整個數據基的穩定和swift。這個工作與unity基本無關,但是是必不可少的,一般簡歷上寫過什麼acm之類的,會讓你搞這個吧。遊戲控制流程,至此開始進入高級程序員的行列,你會接觸很多unity相關的內容,比如技能釋放,角色換裝,角色狀態控制等等有趣的內容,通常如果你不是自廢武功轉3d或者再原來公司本來就幹這個,只是幹膩了跳槽而已,是不會讓新手幹這個的。項目架構這個略掉,我沒資格談這個。

說道這裏本來應該結束廢話的,但是可能引導大家對UI有了新的看法)——它不值得去做。其實不是的,UI這東西雖然無聊,但是是新手接觸引擎,熟悉代碼的最佳通道,同時也是所有公司願意開放給各位新手的一個免費培訓通道吧,因爲UI代碼很不值錢,你走了誰都能接上,所以他們願意用新手。

下面來談談,如果我時面試出卷子的那個【sb】,我會問什麼。這些問題都是項目中坑過我,害過我,讓我哭讓我痛得問題。
UI方面:
1.你覺得爲什麼UI攝像機和場景攝像機能協同工作,而且工作的這麼盡如人意呢?
答案:UI攝像機和場景攝像機分別屬於兩個渲染層(Layer),所以它們之間的渲染互不干擾。它們工作得盡如人意(沒有發生先後錯亂,UI永遠位於場景之上層)的原因就是因爲攝像機深度(depth)控制的好。

2.你覺得怎麼防止UI控件被點穿(如何過濾掉點擊事件)。
答案:使用一個可渲染的物體或者pannel,綁定boxcollider組件即可。如果你單用一個不可渲染的物體(這裏點cao一下UIwiget),即使設定了大小和boxcollider,也是無法屏蔽的。(坑在這裏)。
3.關於UIGrid問題
答案:我基本不會使用UIGrid,我會直接在代碼裏設置localpos等等。(這個控件是很坑的)。

4.你對UI功能模塊之間相互通信有什麼好看法。(或者問成Broadcast和sendMes的看法)
(這道題目是我被面的一道題目,相當精髓,後來問我這道題目的人成爲了我得同事,多謝他不計較我當時回答的很操蛋,而且現在他仍舊如老師一般幫助我。)
答案:UI模塊之間儘量解耦合,使用BroadCast機智或者delegate機智。由於Unity自身的BroadCast和SendMsg效率是很低的,(務必百度一下這倆的區別,都有,我懶得複製粘貼了。)所以推薦使用NGUI自帶的那個消息機智。具體的使用方法,下載任何一款NGUI3.5左右的版本,都能清楚的看到。更或者自己實現一個msgerpool也可以,思路是使用泛型寫法+字典+delegate,效率也很高。

5.衆裏尋他千百度,你怎麼樣能迅速找到某一個UI控件。
答案:分情況處理,這是一個優化策略的題目。首先如果這個控件我在awake的時候能知道,那麼我會把它存成一個private變量,代碼中使用的時候直接使用即可。如果不行,這個子物體是動態生成的(他可能有或者沒有),那儘量使用FindChild,得到之後加以判斷。如果不得不全局找一個東西(比如找到角色物體),纔會用Find。

6.你對遮擋關係有什麼好的策略。
答案:這種問題的誕生是由於Ngui2採用了一種zorder+depth方式處理遮擋關係造成的,已經在ngui3裏完全屏蔽掉了。只要維護depth即可。

7.你對屏幕適配有什麼好主意。
答案:屏幕適配根本沒有完美的解決方案,如果是全屏模塊,那麼鎖定目標機型,將目標機型做成滿屏,其他機型充滿寬或高後留白(也叫留黑邊)處理即可。如果是屏幕模塊(比如戰鬥界面,主城界面等等,你會看到下邊的場景那種),需要採用Anchor來解決。NGUI2 Anchor有獨立的控件,NGUI3Anchor已經被搞到Wighet和Pannel中,這個自己下去好好研究研究吧。
UI的就這麼多,如果問了,你回答的不錯,想感謝我,請多來蠻牛看看~

數據邏輯層方面
1.請簡述一下你對數據結構的選取有什麼看法
答案:批量取,經常遍歷的數據,會採取List來存儲,經常查找的會採取字典存儲。同時如果多個字段比較重要(比如一份配置表經常會id索引以及name索引),我會開闢多個字典進行存儲,犧牲空間換取逆向查找效率。

2.請把這份配置文件解析成你想要的數據結構,給我看看
答案:這份配置文件如果是xml或者json,那麼它肯定會被先轉換成HashTable,然後你根據配置表的可能擁有的字段(比如有一個物體,它有“使用後增加體力”這個字段,有的沒有,你要用ContainsKey來檢測是否有字段),挨個拆出並且存入你想要的數據結構中,如果你想要的數據結構是字典,需要注意的是在加入key的時候,應該詢問是否包含了這個key,如果包含,則修改,如果不包含,則添加,,大家智力都沒有問題。。試一試就會很清楚。
如果這個配置文件爲excell,那麼它將會被轉化成一個string數組,數組的每一個元素,都是一個字段數據,按照配置表的順序挨個取出來存入你得數據結構中即可。

3.請簡述一下C#中,結構體和class的用法
(再次鳴謝面試我得那位同事,容忍了我回答的很爛)
答案:如果你是自廢武功,從C++轉到C#,這倆東西會讓你大跌眼鏡。C++中結構體和類幾乎沒有區別。C#中,結構體屬於對象,而類屬於引用,結構體不需要new出來,類必須new出來。這是個巨大的坑。比如你搞了一個結構體鏈表:
List<structA> structtestlist = new List<structA>();
然後給這個鏈表中注入數據,注入數據之後,你想更改其中的一個鏈節,你是這麼做得
structA structlink = structtestlist[2];
structlink.data = 3;
這樣做,根本沒有修改到structtestlist中得值!因爲聲明structlink那一句話,是個對象,並不是指向那個(鏈節)的“指針”!
但是如果是class,你這麼做毫無煩惱。
這個東西建議大家試試。很坑比。

4.接受到網絡發來的數據,你會怎麼辦
答案:着手做項目之前,會搞一個txt,客戶端內部消息協議羅列到上邊,這個消息協議是網絡協議的處理映射。比如網絡協議告訴我,“因爲你剛纔吃了一個藥,吃成功了,現在你得給我刷新,讓用戶大大能夠看到”,我就必須通知所牽連的模塊:“你得數據被刷新了,再老地方重新取一次,刷新界面給用戶大大看”。牽連到得模塊,比如就是戰鬥UI,它要把血條給加上去,還有character信息的數據基,更改當前血量數據等等。這些模塊收到協議之後,改變自己的值:比如UI就會從數據基裏取,而數據基會從網絡包或者配置表裏取等等。

遊戲控制流程:
1.你對資源加載有什麼看法。
答案:首先資源加載這個東西,就是老大難,用戶一遍遍的吐槽加載的慢,但是誰也不願意讓加載的少導致後邊必須加載而變得卡頓。對於比較耗費的加載,屬於IO操作,在遊戲剛登陸的時候,進行初始化加載。強制加載一些重要模塊,比如登陸窗口(用戶輸入用戶名密碼的地方)等等。選擇性加載一些必要的模塊:如果這人需要新手引導,則加載新手引導模塊,否則不加載,反之亦然。這些用戶一定會用(或者一定不用)的模塊,在登陸時候處理好。對於應用模塊:比如我打開一個很龐大的UI,這個怎麼加載,如果這個模塊很吸金,用戶用得概率很大,那麼必須在登陸時加載,否則那隻能用戶打開的時候加載了,加載的時候要轉圈提示用戶。。關於場景加載更加的莫衷一是。既然大家被面到這一步了,相信也不需要我廢話了,一個程序有一個程序的活法不是嗎?

2.請給我設計一個狀態機,完成一個簡單的xxxx情景。
答:狀態機並不是單純的switch結構,如果你是新手,你說switch我可以容忍,如果你幹了好些年2Dx,然後想自廢武功搞U3d了,再說switch就直接pass了。可以去搜一下相關資料,水不是很深,但篇幅有限。大概意思就是,每個對象都維護自己的狀態機,狀態機的狀態改變,靠狀態觸發器。所有的狀態(不是狀態機。。狀態機是一個主管它負責調度各種狀態,狀態是各種。。。狀態。。哎不可言傳啊。。),都會重寫begin,excute,end這三個函數,本來敲了一大堆。。發現說也說不清楚,大家自己去看看吧還是。畢竟這隻提供一種面試方式而已。。

3.角色換裝,技能釋放你會怎麼做。
角色換裝這個,各有各的活法,屍塊換裝,紙娃娃貼圖等,這個莫衷一是,可以自己百度去,找一個自己喜歡的實現一下試試吧。技能釋放水是很深的,這個能答就答,答不上來也不丟人。估計被面這些的,肯定都比我強,也就不需要我比比什麼的了。。

4.動態更新有什麼看法。
答:這個題牽扯到assetbundle問題。其中assetbundle面對資源的處理方法是截然不同的。比如對於prefab,可以很好的搞上去,對於二進制文件,也能搞得不錯,但是對於代碼這個東西,往往是大家爭論的焦點——畢竟代碼這個東西,iosAppStore是肯定不讓你搞得,因爲unity本身也不受蘋果待見,所以它怕被秒殺,也不給用戶提供更新腳本的功能。這就導致比如你更新了一個prefab,沒法使用它上邊掛的腳本!那更新有個jb用。。。提供一下解決代碼更新的一點看法,現在我再嘗試搞這一塊,一孔之見,輕噴
安卓上可以使用unityreflaction機制進行編譯後代碼的動態更新,這個廣大google開發者肯定是知道的。但是問題就是,這種機制會導致很龐大的開發成本——從代碼層面完全跟ios搞了個大分支,如果是想跨平臺的,這恐怕是不可取的吧。。
第二就是可以採用lua腳本無縫編寫方法,因爲unity腳本並不是真正的腳本,真正腳本的威力是它可以動態編譯到宿主上,這點太牛逼了。lua就是這種牛逼腳本。所以你可以無縫換lua。。。這個沒問題。所以立項就應該想好是lua還是什麼的。。別回來做了一半,想改lua了,那就sb了。。
這兩種機制在App Store上肯定是不讓你搞的,第一種,越獄平臺也不讓搞,因爲unity不讓你搞。。
其實還有神祕的第三種做法,這第三種做法,就不分享了,畢竟還沒有實驗,說出來怕坑殺大家。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章