者按 在游戲制作時,UI界面設計是非常重要的工作,不僅僅是考慮排版布局、美術(shù)風格,還要考慮到玩家的交互行為。另外,采取哪種實現(xiàn)方案也是需要慎重考慮的,一個好方案讓我們在保質(zhì)保量的前提下,能快速高效地完成。筆者將為大家介紹業(yè)界常用的UI解決方案,并對它們做簡單地分析對比。同時,也歡迎大家留言,分享你在UI設計時所積累的經(jīng)驗,或是遇到的困難,咱們共同成長進步。
作者:W
筆者自14年畢業(yè)參加工作以來,一直使用Unity引擎來開發(fā)各種項目,如兒童啟蒙教育類繪本、大型3D網(wǎng)絡海戰(zhàn)、三消、視頻VR以及NBA體育競技等,大部分工作內(nèi)容是與UI界面相關(guān)。使用過的UI系統(tǒng)插件包括Unity原始的GUI、第3方插件NGUI、Unity進階版的UGUI以及第3方的UI編輯器FairyGUI。另外,經(jīng)網(wǎng)上了解還有EZ GUI、IGUI等第3方插件,以及Unity近推出的高階版UIToolkit。這些偏冷門的或者新出爐的,筆者暫沒在公司項目中使用過。你知道的,公司項目對穩(wěn)定性有較高的要求,不會一味地追求新技術(shù)。讀者不用驚訝,有公司還在使用Unity 4.x或者5.x舊版本的呢,哈哈!
經(jīng)過前面介紹,這么多種實現(xiàn)方案,我們在實際項目中應該如何做選擇呢?有木有最佳方案?通吃的那種?答案是否定的。每種方案都有其適用性,需要結(jié)合項目本身以及開發(fā)者自身情況綜合來考量。那在選擇方案時,有木有一些具體的參考點呢?這個是有的,筆者歸結(jié)為以下2點:
1)可視化程度:Unity原始的UI系統(tǒng),需要在運行時才能顯示,這給我們搭建UI界面時帶來很多不便。正因為此,許多像NGUI一樣的高度可視化的插件陸續(xù)誕生。搭建UI界面時,只需將對應組件拖入場景即可顯示和調(diào)整,達到所見即所得的目的。另外,像是否支持圖文混排、虛擬列表等組件以及對策劃美術(shù)是否友好等問題,也都可以歸結(jié)為插件的可視化程度高不高的體現(xiàn)。
2)性能:DrawCall,每次CPU準備數(shù)據(jù)并通知GPU的過程。這個操作是比較好性能的,原則上我們是希望它越少越好的。影響它的因素:一方面表現(xiàn)為UI資源的管理方式,這主要與程序猿技術(shù)能力有關(guān),知道啥時候加載,又啥時候卸載,什么類型資源共享,什么類型資源進行九宮格。另一方面表現(xiàn)為與UI系統(tǒng)本身的渲染原理相關(guān),這是UI方案的“硬傷”,關(guān)于UI方案的硬傷,對于熟知該UI渲染原理的程序猿來說,他知道該怎么去做,一定程度“規(guī)避”產(chǎn)生太多DrawCall。嘻嘻,這很考驗咱程序猿功底咯!如果UI方案本身這方面就做的很好,那豈不是更好,哈哈。
限于篇幅,我不能對這些UI方案深入展開,希望簡短的介紹能講清楚它們各自特點。至于具體怎么使用,我會附上官網(wǎng)或?qū)W習地址,那里通常配有技術(shù)文檔、教程幫助上手。
2.1 Unity原始GUI
因性能和可視化方面都不足,自打好用的如NGUI等第3方插件問世后,Unity的原始GUI系統(tǒng),基本不會用于游戲運行模式時的UI設計中;一般只是在編輯器工具擴展時使用。但現(xiàn)如今Unity又推出新的UIElement框架,可用于編輯器工具的擴展,原生GUI系統(tǒng)會越來越失寵,究其最終原因就是性能差且不好用。目前來看,原始GUI在編輯器工具擴展領域的地位應該不太可能迅速被UIElement取代,因為擴展工具時,原始GUI還是可以勝任的,且很多開發(fā)者應該已經(jīng)習慣用它來編寫工具和擴展。其實,程序猿也是有情懷的,哈哈!
2.2 NGUI
資源地址:https://assetstore.unity.com/packages/tools/gui/ngui-next-gen-ui-2413#description
其特點如下:
1) 圖集:需要自己規(guī)劃好后,手動打開圖集。
2) 渲染原理:先根據(jù)Panel的Depth排序,Panel面板內(nèi)部再根據(jù)Depth排序。將相同材質(zhì)的Widget進行Mesh合并。
3) 支持圖文混排。
4) 支持循環(huán)列表組件。
2.3 Unity進階版UGUI
學習地址:http://c.biancheng.net/view/2712.html
UGUI是在NGUI之后Unity官方推出的,一定程度上借鑒了NGUI的設計理念,在某些方面做了改進優(yōu)化,如自適應、圖集等。其特點如下:
1)圖集:圖集概念不重,會自動打包成圖集。要注意的是,放在Resources文件夾下的貼圖不會被打入圖集;
2)渲染原理:根據(jù)Hierarchy的順序來排序,越下面渲染在越頂層。Canvas與NGUI的UIPanel類似,每個Canvas將優(yōu)化合并為1個Mesh或多個SubMesh;
3)不支持圖文混排,需要自己實現(xiàn);
4)不支持循環(huán)列表組件,需要自己實現(xiàn);
5)有錨點,方便屏幕自適應。
2.4 FairyGUI
官網(wǎng)地址:https://www.fairygui.com/download
它是獨立的UI編輯器,且對美術(shù)、策劃都友好。其特點如下:
1)目前主流的游戲開發(fā)引擎都支持;
2)渲染原理:沒有采取Mesh合并的策略,而是基于類似于Unity的Dynamic Batching技術(shù),對DrawCall進行優(yōu)化。它在不改變顯示效果的前提下,盡可能的把相同材質(zhì)的物體調(diào)整到連續(xù)的RenderingOrder值上,以促使它們能夠被Unity DynamicBatching優(yōu)化;
3)支持圖文混排;
4)支持虛擬列表,即使數(shù)量巨大的列表也不會感覺太卡頓。
2.5 其他方案
因為筆者未在實際項目中使用過,所以這里不做評述了,讀者可以根據(jù)貼出的鏈接跳轉(zhuǎn)過去瞅一瞅哈!
1)Unity高階版UIToolkit
學習地址:https://docs.unity3d.com/cn/2020.1/Manual/UIElements.html
是Unity新推出的新一代UI系統(tǒng),既支持游戲編輯模式也支持運行時模式。但目前還不夠完善。讀者可以嘗嘗鮮,試用一下。
2)EZGUI
資源地址:https://assetstore.unity.com/packages/tools/ez-gui-32
【注:官方資源下架 已購買可以繼續(xù)使用】
3)IGUI
資源地址:https://assetstore.unity.com/packages/tools/gui/igui-basic-1946
【注:官方資源下架 已購買可以繼續(xù)使用】
本篇主要介紹了Unity項目比較流行的UI解決方案,筆者在這里只是做一個匯總概述,并沒有去深究。至于讀者該如何選擇,仁者見仁,智者見智。一句話總結(jié):沒有最好的,只有最適合的!
參考資料
1、Unity官網(wǎng):https://unity.cn/
2、Siki學院:http://www.sikiedu.com/course/explore/unity?subCategory=&selectedthirdLevelCategory=&filter%5Btype%5D=all&filter%5Bprice%5D=all&filter%5BcurrentLevelId%5D=all&orderBy=hotSeq&from_flag=baidu_unity
本教程中,我們來學習一下如何使用Array.splice()方法將數(shù)組等分,還會講一下,Array.splice() 和 Array.slice() 它們之間的不同之處。
我們可以分兩步將數(shù)組分成兩半:
Math.ceil() 函數(shù)返回大于或等于一個給定數(shù)字的最小整數(shù)。
const list = [1, 2, 3, 4, 5, 6];
const middleIndex = Math.ceil(list.length / 2);
const firstHalf = list.splice(0, middleIndex);
const secondHalf = list.splice(-middleIndex);
console.log(firstHalf); // [1, 2, 3]
console.log(secondHalf); // [4, 5, 6]
console.log(list); // []
Array.splice() 方法通過刪除,替換或添加元素來更改數(shù)組的內(nèi)容。而 Array.slice() 方法會先對數(shù)組一份拷貝,在操作。
在這兩個操作結(jié)束時,由于我們已經(jīng)從數(shù)組中刪除了所有元素,所以原始數(shù)組是空的。
另請注意,在上述情況下,元素數(shù)為偶數(shù),如果元素數(shù)為奇數(shù),則前一半將有一個額外的元素。
const list = [1, 2, 3, 4, 5];
const middleIndex = Math.ceil(list.length / 2);
list.splice(0, middleIndex); // returns [1, 2, 3]
list.splice(-middleIndex); // returns [4, 5]
有時我們并不希望改變原始數(shù)組,這個可以配合 Array.slice() 來解決這個問題:
const list = [1, 2, 3, 4, 5, 6];
const middleIndex = Math.ceil(list.length / 2);
const firstHalf = list.slice().splice(0, middleIndex);
const secondHalf = list.slice().splice(-middleIndex);
console.log(firstHalf); // [1, 2, 3]
console.log(secondHalf); // [4, 5, 6]
console.log(list); // [1, 2, 3, 4, 5, 6];
我們看到原始數(shù)組保持不變,因為在使用Array.slice()刪除元素之前,我們使用Array.slice()復制了原始數(shù)組。
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const threePartIndex = Math.ceil(list.length / 3);
const thirdPart = list.splice(-threePartIndex);
const secondPart = list.splice(-threePartIndex);
const firstPart = list;
console.log(firstPart); // [1, 2, 3]
console.log(secondPart); // [4, 5, 6]
console.log(thirdPart); // [7, 8, 9]
簡單解釋一下上面做了啥:
現(xiàn)在,我們來看一看 Array.splice() 更多用法,這里因為我不想改變原數(shù)組,所以使用了 Array.slice(),如果智米們想改變原數(shù)組可以進行刪除它。
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
獲取數(shù)組的第一個元素
list.slice().splice(0, 1) // [1]
獲取數(shù)組的前5個元素
list.slice().splice(0, 5) // [1, 2, 3, 4, 5]
獲取數(shù)組前5個元素之后的所有元素
list.slice().splice(5) // 6, 7, 8, 9]
獲取數(shù)組的最后一個元素
list.slice().splice(-1) // [9]
獲取數(shù)組的最后三個元素
list.slice().splice(-3) // [7, 8, 9]
作者:Ashish Lahoti 譯者:前端小智 來源:jamesknelson
原文:https://codingnconcepts.com/javascript/how-to-divide-array-in-equal-parts-in-javascript/
10 年 JavaScript 都會發(fā)生一次改朝換代式的變革。在我看來,JavaScript 當前正處于一次快速變革的開始,而這段時期未來可能會被稱為 JavaScript 第三紀元。
本文最初發(fā)布于 shawn swyx wang 博客,經(jīng)原作者授權(quán)由 InfoQ 中文站翻譯并分享。
JS 的第一紀元(從 1997 至 2007) 堪稱虎頭蛇尾。大家都知道 Brendan Eich 的故事,但是關(guān)于 ES4 是如何與諸如 Flash/Actionscript 之類的封閉生態(tài)系統(tǒng)艱難地進行激烈競爭的故事卻鮮為人知。我推薦大家讀讀《JavaScript:20 年發(fā)展史》來了解 JS 起源的前前后后,我認為這本書是一個非常合適的選擇, 因為該書是由 JS 的主要作者 Brendan Eich 和 Allen Wirfs-Brock 聯(lián)手發(fā)布的。
JS 的第二紀元(從 2009 至 2019) 是從關(guān)鍵的 2009 年開始的,這一年誕生了 npm,Node.js 和 ES5。隨著 Doug Crockford 在 《JavaScript 精粹》 一書中向我們展示了 JS 的精妙之后,JS 的使用者們創(chuàng)造出了一大堆的 JS 構(gòu)建工具 和庫,并將 JS 的應用范圍擴展到了臺式機和新型智能手機。到了 2019 年,我們甚至看見,在手機端出現(xiàn)了諸如 Facebook 的 Hermes 之類的定制 JS 運行時系統(tǒng),以及諸如 Svelte 3 之類的預編譯前端框架。
譯者注:
《JavaScript 精粹》,這本書的作者是 Doug Crockford,書中他主要從以 JS 的語法、對象、函數(shù)、繼承、數(shù)組、正則表達式、編碼格式以及一些優(yōu)秀的功能等方面,向大家展示 JS 的精妙之處,同時也指出了 JS 的很多缺陷。
Hermes,是 Facebook 推出的一款運行在安卓系統(tǒng)中的 JS 引擎,該引擎對運行在安卓系統(tǒng)中的 React Native 應用做了性能優(yōu)化,該引擎最大的特點是,會提前對代碼進行靜態(tài)優(yōu)化和字節(jié)碼壓縮。
Svelte,是一個全新理念的前端框架,該框架最主要的 2 大特性是:
第一,將諸如代碼檢查、狀態(tài)管理、動畫等功能都做了封裝;
第二,構(gòu)建時會將源碼直接轉(zhuǎn)換為目標運行代碼,而不是在運行時再處理(這里大家可以回想下在使用 webpack 構(gòu)建的過程中,那個在運行時處理代碼的 runtimechunk.js)。
2020 年感覺像是一個新紀元的開始。如果說第一個紀元是關(guān)于一個語言的誕生,第二紀元是關(guān)于人們對這個語言的探索和擴展,那么第三紀元則是與摒棄歷史觀念和工具層級折疊相關(guān)。
注:作者早期提出過 層級折疊 的觀點
在當前的 JS 生態(tài)里,如果我們希望將編寫的代碼投入目標環(huán)境(例如瀏覽器環(huán)境)運行的話,大部分代碼都需要通過幾層工具的轉(zhuǎn)換,如 TS 編譯器、ESLint/JSLint、Less/Scss 、Babel、uglify 等,那么作者認為未來的趨勢是,這些處理層會被盡可能的折疊。
首當其沖要摒棄的歷史觀念是:JS 生態(tài)需要依賴 CommonJS 模塊系統(tǒng),這種觀念是不斷妥協(xié)的結(jié)果。ES Modules 作為替代者已經(jīng)伺機而動很久了,只是缺少一個一蹴而就的機會,主要的原因是,當前在使用中的工具雖然慢但是“已經(jīng)夠用”,于是大家缺乏更換的動力。在前端,現(xiàn)代瀏覽器雖然已經(jīng)具備了處理一些 ES Modules 功能的能力,但一些重要的細節(jié)依然沒有得到很好的解決。
譯者注:
由于這些重要的細節(jié)沒有解決,所以 V8 官方建議大家,在現(xiàn)代瀏覽器上使用 ES Modules 功能時,依然通過諸如 webpack、Rollup 之類的構(gòu)建工具對源代碼進行構(gòu)建。
Pika 的 Snowpack 項目希望通過提供一個外觀模式(facade)來加快 ES Modules 功能的提前應用,該模式會隨著 ES Modules 的完善而逐步消失。最后來點鼓舞人心的消息,IE11 從今年開始至 2029 年將逐步結(jié)束其緩慢的發(fā)展歷程。
另一個要摒棄的歷史觀念是:必須使用 JavaScript 構(gòu)建 JavaScript 工具。 在熱路徑中,類型安全性和 性能提升(10 到 100 倍) 的潛力太大了,不容忽視。這種“只使用 JS 為 JS 構(gòu)建工具”的想法,隨著 TypeScript 幾乎完全接管了 JavaScript 而逐漸消失,同時最近嶄露頭角的 Deno 和 Relay 也進一步證明了,人們將會通過學習 Rust 來向 JS 核心工具庫做貢獻。Brandon Dail 預測這種轉(zhuǎn)變(工具的構(gòu)建形式)將會在 2023 年完成。不過大部分使用中的非核心工具,由于其易用性相對性能更加重要,因此我們將依然會使用 JavaScript 和 TypeScript 進行編寫。以前我們考慮的是“功能內(nèi)核,命令式 Shell”,而現(xiàn)在我們應該考慮的是“系統(tǒng)內(nèi)核,腳本 Shell”。
注:上面的觀點也是有爭議的。Python 的解析器 PyPy 就表明這不是一個既定的結(jié)論。
層級也在以有趣的方式進行折疊。Deno 采取了激進的方式,它編寫了一個全新的運行時,同時將諸如測試、格式化、代碼校驗和打包等一堆常用的任務工具折疊到一個二進制文件中,針對 TypeScript 甚至直接包含了一個 標準庫。而 Rome 則采用了不同的方式,它還是基于 Node.js 將這些層折疊了起來(據(jù)我所知,這些使用起來很簡單)。
10 年前,諸如 AWS、Azure、GCP 等公有云都還不存在,但是今天,它們已經(jīng)是生活的一部分了。JavaScript 和云之間的關(guān)系非常微妙,以至于我都很難清晰的表述出來。云平臺的開發(fā)者不會直接使用 JS,但是 JS 卻又是他們最大的客戶。AWS Lambda 第一個推出對 JS 的支持,它的一個明顯變化是,折疊了 IDE 層和云服務層,移除了中間那個令人討厭的筆記本電腦。許多諸如 Glitch、Repl.it、Codesandbox、GitHub Codespaces、Stackblitz 的 云服務發(fā)行者 都在利用 JS 來探索這個領域。與此同時,像 Netlify 和 Vercel 一樣,JAMstack 從 PoV 開始,合并了 CI/CD 層和 CDN 層,移除了其間令人厭煩的運行時服務。
即使在前端框架中,層級折疊的發(fā)展同樣鼓舞人心。從動畫到狀態(tài)管理,Svelte 將所有的事情都折疊到了編譯器里。React 也在探索 元框架 和 客戶端與服務端集成 的方案,同時 Vue 正在致力于開發(fā)一個稱為 Vite 的“無需打包”的開發(fā)服務項目。
總結(jié):
在 JS 第三紀元中,其構(gòu)建工具的發(fā)展將會是下面幾個方面:
所有這些工作,最終都是促使開發(fā)體驗(更快的構(gòu)建,行業(yè)標準的工具化)和用戶體驗(更小的構(gòu)建包,更快的功能交付)變得更好。這是 JavaScript 從腳本編程語言到完整應用平臺的最終蛻變。
如果 Gary Bernhardt 的預言成真,那么第三紀元將是 JavaScript 的最后一個發(fā)展紀元(Gary Bernhardt 給出的時間結(jié)點是 2035 年)。Web Assembly 總是在 JavaScript 的周圍若隱若現(xiàn),甚至連 Brendan Eich 都改變了他的名言稱:“永遠押寶在 JS 和 WASM”,他最初認為 JS 可能是“通用虛擬機”,但是曾經(jīng)有人告訴我,現(xiàn)在 WASM 就是這個想法的最終實現(xiàn)。
如果真如上面所說,那么我們現(xiàn)在正處于 JavaScript 消亡的邊緣。
大約到 2030 年的時候,JavaScript 的第三紀元接近尾聲,那時 JavaScript 將會有什么樣的發(fā)展?請在下面評論區(qū)說出你的預測:
參考閱讀: https://www.swyx.io/writing/js-third-age/
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。