包含9節(jié)視頻教程
關(guān)注16.4萬次
從零開始講解MotionBuilder的詳細(xì)教程,配合朱峰社區(qū)的模型詳細(xì)講解如何進(jìn)行運(yùn)動(dòng)捕捉的動(dòng)作裝配
19號(hào),也就是中國時(shí)間20日凌晨,虛幻4放出了“訂閱制”這個(gè)重磅炸彈,估計(jì)出乎大多數(shù)人的想象,已經(jīng)不止一個(gè)同事表示“自己的引擎這下沒用了”。
筆者前天搞定了付款,下載,編譯和運(yùn)行。
基本就是只要有一張visa或者M(jìn)asterCard的信用卡,官網(wǎng)www.unrealengine.com注冊(cè)一下,填寫支付信息,地址什么的隨便寫個(gè)或者硬寫中國的地址,然后去github開通一個(gè)賬號(hào),最后在官網(wǎng)賬戶設(shè)置里把官網(wǎng)賬號(hào)和這個(gè)git賬號(hào)關(guān)聯(lián)一下,就可以從github下到代碼了。
下完后如果短時(shí)間內(nèi)不升級(jí)可以考慮退訂,這樣只是不能更新,沒有其他問題。
所以說到時(shí)候開通中國區(qū)付款后這里取消訂閱再重新訂閱就好了,辦張雙幣信用卡,不必糾結(jié)付費(fèi)的問題。
下載主要是git代碼,30兆左右,然后要按著git頁面上的提示(付費(fèi)后才可見),去release頁面下載dependencies包,總共3個(gè):
先解壓1of2和2of2,Optional是2012編譯所需的,2013可以無視,筆者用的2013 express,就沒有試。
最后把解壓后的dependencies拷到代碼文件夾里即可。
然后運(yùn)行根目錄的bat,即可在根目錄生成2013的UE4.sln文件,如果出錯(cuò),可能是目錄沒考對(duì),對(duì)應(yīng)提示來看看什么問題就好。
進(jìn)入后,生成配置選擇developer editor就可以開擼了,筆者的Surface Pro用了大概40分鐘才擼好,要有心理準(zhǔn)備。
如果用的是2013 Express,可能會(huì)有個(gè)atlbase.h找不到,編譯不過的問題,是因?yàn)?013本身是不帶ATL/MFC的,去官網(wǎng)下個(gè)ATL/MFC,然后在工程里設(shè)置一下ATL / MFC的頭文件和Lib路徑即可。
編譯完畢后,UE4工程設(shè)為啟動(dòng)項(xiàng)目,F(xiàn)5之,啟動(dòng)后可以選擇載入一些游戲模板或者建立空?qǐng)鼍,這時(shí)候可在其他目錄里建立游戲相關(guān)的工程(游戲工程和引擎工程可以分開了,不需要再像UE3那樣綁一起了),默認(rèn)不選目錄的話會(huì)在我的文檔下開一個(gè)Unreal Projects文件夾來存工程。
新建項(xiàng)目
筆者已經(jīng)建立的項(xiàng)目
項(xiàng)目文件夾,可以跟引擎文件夾分離。
建立工程后會(huì)自動(dòng)打開這個(gè)游戲工程的Sln,后面要開工的時(shí)候打開這個(gè)Sln,運(yùn)行項(xiàng)目工程(不是UE4)即可,如果不是建立新的工程的話,不需要再打開UE4.sln了。
工程文件夾里會(huì)包括一些配置、初始資源、代碼以及工程Sln,見上面的項(xiàng)目文件夾圖。
MarketPlace里有很多示例:
第一次點(diǎn)擊會(huì)提示您安裝,最好裝到個(gè)大點(diǎn)的盤,目前發(fā)現(xiàn)它這個(gè)東西下載時(shí)是會(huì)寫到安裝路徑下。幾個(gè)GB的資源,未來有可能更多,小盤的話后面杯具。官網(wǎng)有人發(fā)帖表示后面拷貝到新的路徑還得重下資源,所以爭取一步到位吧。
安裝后,第一次要下載更新包更新,這一步看人品,身邊有不少人都遇到了卡81的問題:
卡在81這里老半天,最后報(bào)個(gè):
官網(wǎng)正在討論這個(gè)的解決方案:
https://answers.unrealengine.com/questions/14683/launcher-update-stuck-on-downloading.html
筆者自己是一直不斷關(guān)了重開,試了20幾回,不知道怎么有一次就好了……所以說很看人品……如果您也遇到了這個(gè)問題,可以多試幾次,也可以看看上面的鏈接最新到什么程度了。
好了的話,“正版用戶”就基本上可以下載了:
這個(gè)沒節(jié)操的……Bird發(fā)現(xiàn)!
盜版用戶這里怎樣我也不清楚,不過這次Epic已經(jīng)是非常有誠意了,希望大家能支持一下正版,畢竟引擎越做越好用,實(shí)際最終受益的是我們所有開發(fā)者。
初步感覺變化還是有點(diǎn)大的,后面慢慢展開,希望我能完成這個(gè)系列。
打開UE4,短暫的興奮過后,開始大概掃一掃UE4的編輯器,整個(gè)界面比UE3更有現(xiàn)代氣息:
之前看其他人寫的文章,虛幻4最重要的改動(dòng)集中在下面幾個(gè)方向上:
跨平臺(tái):
WIN和MAC平臺(tái)都能使用,這就意味著必須使用兩個(gè)平臺(tái)都能接受的方案。
界面:
由于上述的原則,WPF界面雖然很酷,不支持MONO就只能跟好評(píng)無緣了(順便吐槽一下微軟,基于NET做了那么多東西,卻總是虎頭蛇尾)。因此虛幻這回是自己搞了個(gè)界面系統(tǒng)出來……而且更喪心病狂的是這個(gè)界面可以用在游戲里……
C++化:
不知道是因?yàn)閁nreal Script在移動(dòng)平臺(tái)上的性能表現(xiàn)不給力,還是因?yàn)樽约壕S護(hù)一套Script成本稍顯浪費(fèi),無論如何,UE4開始,之前負(fù)責(zé)連接工具和邏輯、內(nèi)容提供者和解決方案提供者的Unreal Script讓位給了"格式化"的C++。
這個(gè)改動(dòng)并不是孤立的,相應(yīng)的,整個(gè)解決方案更明晰地劃分為了核心層、插件、邏輯層,一方面也提高了跨平臺(tái)方面的能力。
同時(shí),圍繞著這個(gè)特性,最重要的應(yīng)該就是熱更新功能了吧?邏輯層代碼由于已經(jīng)獨(dú)立于核心層,所以C++編撰的邏輯層代碼修改,不需要退出編輯器,就可以在編輯器中自然而然地編譯并重新載入——參與過實(shí)際項(xiàng)目的戰(zhàn)友們應(yīng)該都明白這意味著什么。
另一方面來說,國內(nèi)不少戰(zhàn)友拿到這種國外的引擎往往是一種暴殄天物的用法,把這些引擎改得亂七八糟。所以筆者個(gè)人感覺Unity重新定義了國內(nèi)的引擎用法——沒代碼引擎變相的"好處"——人們不再是關(guān)注與技術(shù)細(xì)節(jié),而是關(guān)注與Workflow了,而后者才是國外引擎現(xiàn)在真正的核心和強(qiáng)大之處。筆者本人現(xiàn)在就深陷于一個(gè)由于改造了國外原本優(yōu)秀引擎而導(dǎo)致滿地大坑的項(xiàng)目中……不過想來未來會(huì)越來越好——國內(nèi)的開發(fā)者如果現(xiàn)在再準(zhǔn)備把引擎改得亂七八糟,是要被策劃和美術(shù)同學(xué)鄙視的——人家本身這么牛逼的特性,你一弄,沒了,咋回事兒?給個(gè)解釋唄?
Blue Print:
其實(shí)就是之前的Kismet的強(qiáng)化升級(jí)版,UE3單用Kismet能做出游戲,升級(jí)版的Blue Print應(yīng)該只強(qiáng)不差。
UPK:
不見了,資源單文件存儲(chǔ):爭議滿滿的UPK終于離開歷史舞臺(tái)了,所有資源現(xiàn)在以.uassert的后綴名分散在Content文件夾下的各種場合。這也意味著之前資源包升級(jí)和DLC最大的一個(gè)攔路虎沒有了?碙auncher本身就做了自動(dòng)更新,想來自動(dòng)更新應(yīng)該是引擎本身就可以支持了吧?
大概用了用,瀏覽了一下它的一些例子,感覺都很不錯(cuò)。
如果想開始制作自己的游戲的話最好先看看Content Examples:介紹虛幻4的基本特性和用法。從頭到尾瀏覽一遍基本上這個(gè)引擎的使用方法就都清楚了,未來這塊兒的工作應(yīng)該主要是美術(shù)和策劃的工作,程序大體應(yīng)該了解一下,特別是如果還沒有接觸過虛幻的同事們,這個(gè)可以讓你很快明白虛幻的整個(gè)工作流。
基本上,除了藍(lán)圖(虛幻3里KISMET的增強(qiáng)版)、地形有些變化外,其它內(nèi)容部分相對(duì)UDK并無太大變化,虛幻3玩家應(yīng)該能很快就上手。
其他例子多是一些手機(jī)版的游戲例子,不過例子不在多在完整。順便說一句,Strategy Game這個(gè)可以關(guān)注一下。當(dāng)年跟很多人爭辯說虛幻能用來做RTS沒人信,這個(gè)例子雖然不完全是一個(gè)RTS,但是基本上可以改變"虛幻只能用來做FPS和TPS"的印象了吧?
自己建立一個(gè)例子工程,隨便找了個(gè)Third Person的模板,帶BP的模板是指純Blue Print,不帶任何代碼的。筆者創(chuàng)建的是帶代碼的版本
Binaries顧名思義,這個(gè)例子最后會(huì)生成一個(gè)DLL在Binaries里,然后編輯器會(huì)重新加載這個(gè)DLL。熱更新的具體代碼還沒看,但是應(yīng)該是這個(gè)路數(shù)沒跑。
Config跟UE3的Config一樣,項(xiàng)目級(jí)別的系統(tǒng)設(shè)置,后面詳細(xì)展開,一般來說,如果要改設(shè)置的話是改這里的Config。
Content就是原來UE3的Content,美術(shù)、策劃資源全在這里,不解釋。
DerivedDataCache還不知道是做什么的,后面看看吧。
Intermediate是生成的臨時(shí)文件,包括工程、中間文件。
Saved包括一些運(yùn)行時(shí)會(huì)創(chuàng)建并維護(hù)的內(nèi)容:備份、日志、運(yùn)行期的Config,跟UE3的方法一樣:這個(gè)Config不需要去改,改動(dòng)的應(yīng)該是根目錄Config下的內(nèi)容。
Source不用說就是代碼了。
會(huì)自動(dòng)生成SLN,打開這個(gè)SLN就可以開工了,就像Unity會(huì)自動(dòng)幫你建立一個(gè)Mono Develop工程一樣。
如前所述,虛幻引擎所使用的是C++,而不是C#、Java代碼。有人總覺得C++會(huì)導(dǎo)致虛幻上手難度變高,筆者個(gè)人感覺還好,因?yàn)槟阌玫降腃++是帶有一定限制的,這些C++類是需要考慮與引擎其它部分的關(guān)系,以及考慮與編輯器的關(guān)系的,再加上虛幻自己實(shí)現(xiàn)了垃圾回收,所以整個(gè)調(diào)用并不會(huì)比C#麻煩太多——當(dāng)然,LINQ什么的特殊語法就罷了。
生成的代碼包括:
ThirdPerson:模塊文件,似乎是定義這個(gè)DLL模塊的,追溯了一下感覺像是DLL Entry這樣的東西。
ThirdPersonCharacter:第三人稱模式下,控制器操作的對(duì)象。目前里面寫了很多跟輸入消息綁定的語句。
ThridPersonGameMode:Game Mode是UE3帶過來的概念了,當(dāng)前第三人稱游戲的一些設(shè)置,目前這里面定義了當(dāng)前游戲控制器的操作對(duì)象:
// set default pawn class to our Blueprinted character
static ConstructorHelpers::FObjectFinder<UClass> PlayerPawnBPClass(TEXT("Class'/Game/Blueprints/MyCharacter.MyCharacter_C'"));
if (PlayerPawnBPClass.Object != NULL)
{
DefaultPawnClass = PlayerPawnBPClass.Object;
}
注意這里,不是直接注冊(cè)的ThirdPersonCharacter,那ThirdPersonCharacter還有什么用?
別急,我們先看看:
Class'/Game/Blueprints/MyCharacter.MyCharacter_C'
這個(gè)意思是從Content/下的Blueprints里加載MyCharacter.MyCharacter_C,并把它認(rèn)成一個(gè)Class。
我們?nèi)ベY源里找這個(gè)BluePrint:
打開:
解釋一下就是這個(gè)BluePrint是從ThirdPersonCharacter派生的……OMG
所以,寫在ThirdPersonCharacter代碼里的那些與輸入消息的綁定才有用:因?yàn)槭沁@個(gè)MyCharacter是從這個(gè)C++腳本派生的嘛。
但是這么一來,MyCharacter一方面可以集成程序提供的基本操作方案,另一方面,策劃可以通過BluePrint為其設(shè)計(jì)一些特殊的連線流程,兩全其美!
有些東西,不想給策劃弄的,或者策劃弄不了的,比如AI底層,程序來集成就好了。想給策劃弄的,這么一來你自己Blue Print去吧。
這塊兒筆者真心給跪了。Orz
過去的UE3的Kismet也不是不能跟對(duì)象一起用,但那如果在編輯器里操作,就是得用Prefab,本身Prefab沒有任何跟代碼相關(guān)的概念,基本類似于一個(gè)各種對(duì)象放一起的大組。從某類繼承?對(duì)不起,沒這個(gè)概念。
所以UE3里,這種情況就得自己用Unreal Script寫個(gè)UC類,然后在代碼里自己手動(dòng)拼各個(gè)組成組件的空間關(guān)系……加上Kismet互操作的代碼來進(jìn)行Kismet的互操作。
現(xiàn)在這Blue Print完全超越了Prefab這個(gè)概念,相當(dāng)于把原來Unreal Script的這個(gè)工作用圖形化的方式接管過來了……難怪Unreal Script被徹底拋棄。
點(diǎn)
開始運(yùn)行,享受了一番,在ThirdPersonCharacter的方法里斷點(diǎn)調(diào)試了一下,與猜測(cè)基本無差。
最牛逼的是,我們把代碼里Move Right代碼注了,
編譯,然后再跑,不關(guān)編輯器,角色的向右移動(dòng)就被我們給斃掉了,只能向前沖。
這個(gè)過程稍微有點(diǎn)危險(xiǎn),筆者致掛一次,記得保存改動(dòng)先。
還想繼續(xù)整整,到上班點(diǎn)了,最近公司工作較忙,只能先放放后面弄了。
筆者現(xiàn)在進(jìn)行的其實(shí)就是UE3以上、UE4未滿的工作:策劃通過圖表完成自己的想法。在一個(gè)老企業(yè)中推行這種其實(shí)已經(jīng)不算新,但在國內(nèi)特別是北京圈還不算非常能讓人接受的做法。希望這次UE4的出現(xiàn)能讓各位大爺們好好冷靜下來想想。不要老說"國內(nèi)這么做游戲是有理由的",我想說的是國外的游戲做的比你好,也是有理由的!
筆者有幸參與過兩個(gè)UE3項(xiàng)目,完全不同的使用方法,總共用了5、6年。引擎學(xué)習(xí)最好還是能參與項(xiàng)目,自己看的話往往容易糾結(jié)到一些細(xì)節(jié)上去,而引擎之所以是引擎,重要的恰恰是在容易被人忽視的工作流上。單從細(xì)節(jié)上看,UE3的代碼很多地方并不完美,甚至有些奇怪,但是一旦做到工作流上,就會(huì)發(fā)現(xiàn)整個(gè)UE3工作流的強(qiáng)大之處。
先回顧一下UE3系統(tǒng)的一些結(jié)構(gòu)要點(diǎn),權(quán)當(dāng)做個(gè)記錄,看看UE4在這些方面有什么不同,作為我們接下來讀碼的突破口。
如果真心想要學(xué)習(xí)這個(gè)引擎,最好還是能用它來做做項(xiàng)目,項(xiàng)目不分大小,只論完整程度,筆者短時(shí)間內(nèi)看來是沒機(jī)會(huì)了。
從UE3到UE4
1、BuildTools
UE4除了工具和插件外,本體不分工程了,UE3的核心部分最后分了Core、Engine、Editor、WinDrv、Network、Renderer等十?dāng)?shù)個(gè)工程,UE4就一個(gè)UE4工程。但工程歸工程,編譯時(shí)還是分得很開的。
而且這個(gè)工程猜測(cè)是靠BuildTools來生成出來的(一開始那個(gè)bat)。看起來,散落在各個(gè)文件夾下的.cs文件就像CMakeList.txt那樣,它們才是整個(gè)工程的組織核心。
事實(shí)上從UE3時(shí)代,就可以完全脫離Visual Studio IDE來工作了,UE3的工程本身都已經(jīng)不再是典型的VC工程,代碼編完后,實(shí)際上最后執(zhí)行的是Build.bat、調(diào)用UnrealBuildTools.exe來編譯,所以要改工程設(shè)置,也是需要去修改UnrealBuildTools工程的。
** 估計(jì),如果要改工程組織結(jié)構(gòu),增加文件什么的,也需要維護(hù)這個(gè).cs文件吧。這個(gè)可能得等做做才知道了。
不過應(yīng)該可以看出來,UE4這里是為了支持項(xiàng)目和引擎分離而進(jìn)行的。
2、Core
個(gè)人觀點(diǎn),UE3的Core重點(diǎn)是下面幾個(gè)部分:
作為整個(gè)虛幻構(gòu)架基礎(chǔ)的UObject和由一大堆宏和各種Classes.h這套組織結(jié)構(gòu)反射系統(tǒng)——圍繞它的包括GC、UObject與UnrealScript的互操作性、與編輯器的互操作性、自動(dòng)序列化、對(duì)象克隆等。這個(gè)非常重要,整個(gè)虛幻體系的核心就是這一套東西,如果前面不注意的話,后面遲早會(huì)在這里栽點(diǎn)跟頭。
序列化和統(tǒng)一具名訪問:ULinkLoader,起這個(gè)名字可能主要是因?yàn)榧虞d的時(shí)候,它會(huì)自動(dòng)分析Object的引用鏈,并且根據(jù)需要繼續(xù)往下加載。另外,所有虛幻的Object都會(huì)有自己獨(dú)一無二的具名路徑,例如xxx.umap:persistentLevel.Pawn_0,xx.Material.Material_0,任何時(shí)候,只要使用LoadObject、FindObject并傳入這些名字,就可以訪問到對(duì)應(yīng)的對(duì)象。這個(gè)在編輯器的維護(hù)中是相當(dāng)方便的一個(gè)底層特性。甚至,這個(gè)具名路徑還可以訪問到腳本中的類、內(nèi)置模板資源等等。
MakeCommandlet和UC腳本核心:Core中間編碼了整個(gè)Unreal Script的編譯和運(yùn)行時(shí)環(huán)境。Unreal Script編譯過程中會(huì)生成相應(yīng)工程的Unreal Script/C++互操作文件:xClasses.h以及一堆自動(dòng)生成的方法和調(diào)用。編譯后的結(jié)果是.u文件,其實(shí)同時(shí)就是跟.upk資源文件一樣的格式——虛幻2不清楚,但至少從虛幻3時(shí)代開始,資源和腳本就被當(dāng)作是同一個(gè)東西,腳本是可執(zhí)行的資源,資源是不可執(zhí)行的腳本。另外與此相關(guān)的就是一套調(diào)試器——很多人用了半天虛幻3卻不知道虛幻腳本是可以調(diào)試的……AutoDebug命令行或者ToggleDebugger指令搜一下,印象中調(diào)試器的核心接口是基于UDebuggerCore還是UDebuggerInterface這個(gè)類。VS裝nFringe插件后、或者自帶的UDE都可以對(duì)腳本進(jìn)行調(diào)試。
狀態(tài)機(jī):腳本的特殊語法,狀態(tài)機(jī)是在腳本類內(nèi)部的概念,每個(gè)狀態(tài)可以重載腳本類某些函數(shù)的實(shí)現(xiàn),這樣當(dāng)狀態(tài)切換到這個(gè)狀態(tài)的時(shí)候,就只是執(zhí)行狀態(tài)內(nèi)的函數(shù)而非腳本類的函數(shù)本身。Actor和Controller里大量用到。
Latent:腳本的特殊語法,基本類似于不通過連線的Kismet,latent類似于Erlang這樣的Coroutine語言,每個(gè)語句都是步驟而非過程,步驟可能會(huì)花很多幀去執(zhí)行,執(zhí)行完畢后接著進(jìn)行下個(gè)步驟,傳統(tǒng)語言的過程只能當(dāng)前幀執(zhí)行完畢。
其它就是一系列的數(shù)學(xué)庫、內(nèi)存管理、輔助函數(shù)。內(nèi)存管理比較有意思,一開始看總覺得問題較大,當(dāng)時(shí)組里的內(nèi)存專家Aman Jiang老師實(shí)際打出來報(bào)告后發(fā)現(xiàn)這塊兒管的還是很不錯(cuò)的,碎片率遠(yuǎn)低于我們的預(yù)期。
3、Engine
相當(dāng)龐大的集合,個(gè)人觀點(diǎn),重點(diǎn)在于:
Actor-Component體系:組件化結(jié)構(gòu)的虛幻版,組件化現(xiàn)在應(yīng)該是大多數(shù)引擎的標(biāo)配了吧?這塊兒可以說中規(guī)中矩,主要組件還是得花心思去看看,否則極易在接口調(diào)用順序亂掉的情況下發(fā)生問題。渲染器與游戲上層邏輯通過Component來接口,提供新的渲染技術(shù)后,只需要做一個(gè)對(duì)應(yīng)的Component就可以了——SpeedTree什么的就是這么集成進(jìn)來的。
Game-Player-Controller體系:Game Mode決定了當(dāng)前關(guān)卡的游戲玩法,一個(gè)關(guān)卡可以有不同的游戲玩法——對(duì)于FPS你可以想象虛幻競技場中的很多地圖都同時(shí)支持Free for all、奪旗、Team計(jì)分。對(duì)于網(wǎng)絡(luò)游戲,你可以想象一個(gè)關(guān)卡資源可以用來做戰(zhàn)場、也可以用來做副本。Player是所有IO的總?cè)肟,一般一個(gè)游戲只有一個(gè)Player,就是Local Player。主機(jī)游戲可以設(shè)計(jì)同時(shí)存在兩個(gè)Player的場合,可以用分屏顯示來分離各自的IO。進(jìn)入地圖后,會(huì)針對(duì)當(dāng)前地圖生成Controller,來實(shí)際從Player截獲輸入和部分輸出操作,并真正影響到游戲中。相應(yīng)的概念還包括View(實(shí)際上的攝像機(jī))、ClientViewport(游戲和編輯器窗口)。
Controller-Pawn體系:Pawn是可以被Controller控制的東西,Controller把IO和UI消息轉(zhuǎn)化為對(duì)Pawn的操作,通知Pawn完成其功能,并把這些功能執(zhí)行過程反饋給IO和UI。在游戲中可以切換Controller內(nèi)部的不同狀態(tài),例如根據(jù)Pawn是在走還是在爬墻,把輸入消息轉(zhuǎn)化為對(duì)Pawn不同的指令。還可以切換Controller,比如進(jìn)載具了,Controller一換就Ok。甚至技能中也可以切換Controller,比較經(jīng)典的例子就是虛幻競技場3里的榴彈炮:普通架起來的狀態(tài)下打出的是一般炮彈,炮彈飛行過程中鼠標(biāo)可以一直控制其方向,右鍵可以把這個(gè)炮彈展開使其定位在空中,然后你的視角一直停留在這個(gè)炮彈上,鼠標(biāo)變成在地面選擇一個(gè)區(qū)域,火炮變成一門發(fā)射榴散彈的大殺器,把致命散彈砸向這個(gè)區(qū)域。筆者接觸過不少游戲的游戲系統(tǒng)了——不幸的是這個(gè)流程很少有系統(tǒng)能夠不加大改地實(shí)現(xiàn)。AI也是一種Controller,操縱的是Bot這個(gè)特殊的Pawn,這塊兒有興趣也可以研究一下。
World-Level-Actor體系:World里存一堆Level,Level里存一堆Actor, Build后的光照跟Level走,Level是關(guān)卡部分的資源單位。但場景圖根是World里的Hash,虛幻3里是個(gè)八叉樹實(shí)現(xiàn)。World里實(shí)現(xiàn)了基本的場景功能,角色的走跑、懸崖邊緣的檢測(cè)、走到碰撞體前被擋住、碰撞體位置變化時(shí)導(dǎo)致自己上面放置的其它碰撞體變化……你如果有自己的場景需求,可以修改World里面的這個(gè)部分。注意,在虛幻3里場景和物理雖然有關(guān),但是本質(zhì)上還是分離的,引擎提供了默認(rèn)的整合方式,但你可以在Actor里重新控制這種整合。
資源體系:沒什么好說的,Material、Texture、各種Mesh、Particle。Material連線球很贊,但是跟渲染Stage有較深的關(guān)聯(lián),筆者試圖做過一個(gè)自以為比他更好的,跟Stage可以一定程度脫耦的材質(zhì)連線球系統(tǒng)——但是最終發(fā)現(xiàn)材質(zhì)這東西根本上還是離不開渲染Stage,什么都想控制的結(jié)局一定是什么都控制不過來。
渲染體系:就不說什么了吧,Deferred Lighting的Stage體系,網(wǎng)上的文章海了去了,做圖形的這個(gè)早就拋腦后了吧。最近一兩年的版本支持了Deferred Shading。這套Stage的低端化替換還是很方便的——畢竟現(xiàn)在需要考慮到游戲可能更多是會(huì)在intel HD 3000/4000這種顯卡上跑的可能性了。
4、UnrealEd
編輯器……怎么說呢,這個(gè)沒法按體系來了,太多了,有些精品也有些糟粕,反正編輯器這東西,沒法說,需要擴(kuò)展的時(shí)候自己去改吧。
注意屬性編輯器是如何發(fā)揮反射的強(qiáng)大效力的。
有些細(xì)節(jié)問題,實(shí)際做了可能會(huì)遇到:拷貝對(duì)象時(shí),有些屬性是引用的(一般的Object屬性不加任何描述),有些是復(fù)制的(editinlinenew、instance和duplicate),有些是舍棄的(transient)。還有就是虛幻比較喜歡用Prototype + Clone的方式來實(shí)現(xiàn)Template-Instance這種需求,典型的例子是Animation Tree和Prefab,實(shí)例都是直接從資源拷貝出來的。主要是因?yàn)閁E3的反射外圍有一個(gè)比較強(qiáng)大的Clone系統(tǒng),但是前提是您得對(duì)剛剛列舉的那些關(guān)鍵字比較熟悉,否則為這些系統(tǒng)擴(kuò)展時(shí)就比較容易遇到問題。
多說一句:編輯器選物體用的是把物體的ID渲到一張Render Target上再去這個(gè)Render Target上查找鼠標(biāo)點(diǎn)Id的做法,叫HitProxy,如果你的游戲想支持像素點(diǎn)選,可以參考這個(gè)東西,很容易就能把這個(gè)Stage集成到游戲Stage里。
5、其他工程
就沒什么好說的了:
渲染器:Renderer,DX9、DX10、DX11、OpenGL的實(shí)現(xiàn)都有,DX10只有一個(gè)版本曇花一現(xiàn)。
平臺(tái)庫:以XXXDrv為名,例如WinDrv。主要提供平臺(tái)方法,沒什么好說的。
網(wǎng)絡(luò)庫:IpDrv、Channel什么的,也沒什么好說的。
網(wǎng)游的開發(fā)者很喜歡自己構(gòu)造上層,我參與的第一個(gè)UE項(xiàng)目就是這么做的,實(shí)際上最后做出來的上層后來看來比虛幻的整個(gè)上層體系差的太遠(yuǎn)。第二個(gè)項(xiàng)目筆者就一直推動(dòng)著在虛幻框架上的小修小改。最后能實(shí)現(xiàn)什么呢?能實(shí)現(xiàn)在編輯器里根服務(wù)器通信,編輯器調(diào)整完Kismet連線圖、資源、布怪點(diǎn)后,不用退出,直接就可以啟動(dòng)開發(fā)服務(wù)器,然后在編輯器內(nèi)測(cè)試剛剛自己做的東西對(duì)不對(duì),可惜因?yàn)橘Y金原因沒做下去,兩年前這個(gè)級(jí)別的工具集成,不知道有多少人做到了?至少我現(xiàn)在在這個(gè)項(xiàng)目里還沒能推廣到,也不可能推廣到那個(gè)程度(筆者鼻子翹起來了~*^_^*)。不過未來不需要再弄了——看看虛幻4的Blueprint,可以考慮這個(gè)級(jí)別的集成了。
筆者一直認(rèn)為,虛幻3強(qiáng)大的地方不在于他的圖形,而是在于這套強(qiáng)大而穩(wěn)固的結(jié)構(gòu)和迅速的工作流,而當(dāng)你握這套結(jié)構(gòu)和工作流后,筆者發(fā)現(xiàn)所有引擎在自己的面前索然無味,圖形雖然還在追求,但已經(jīng)退居次席了,而自己重新去做引擎的沖動(dòng)則不斷降低,直至完全消失。
用虛幻一定要首先明白一個(gè)原則,就是這是個(gè)解決方案式引擎,不是OGRE那樣的圖形工具庫,所以你的所有改動(dòng)一定要符合虛幻的基本結(jié)構(gòu)假設(shè),否則你只是在給自己找麻煩。但是,相信我,符合這些基本的結(jié)構(gòu)假設(shè)一點(diǎn)不會(huì)讓你的自由度降低,你的控制能力把控能力還是相當(dāng)強(qiáng)的——不信你看,筆者上面列舉的框架部分,有哪個(gè)是會(huì)影響你的發(fā)揮的?M——World-Actor、V——Player、C——Controller,哪一環(huán)是可以省略的?當(dāng)然,如果您的體系結(jié)構(gòu)設(shè)計(jì)的比這個(gè)還好,那真的很恭喜您了,一山更比一山高,筆者只能感嘆于自己的時(shí)運(yùn)不濟(jì)了……
這兩天還是在看例子,看幾個(gè)Blueprint的例子,順便回想一下UE3的那些事兒。最近的緊張局面可能會(huì)延續(xù)到4月中旬,屆時(shí)才有可能有更多時(shí)間來看UE4。目前感覺變化還是挺大的,不過,喜在框架方面的改動(dòng)似乎很有限。
從另一個(gè)方面,也證明了UE3的這套游戲上層邏輯框架,是多么地穩(wěn)固和強(qiáng)大。
前文說到UE3開始,虛幻就使用了UnrealBuildTool(以下簡稱UBT)來編譯和生成代碼。
為什么這么做而不是使用VS是很好理解的:因?yàn)閂S跨平臺(tái)會(huì)比較麻煩。像虛幻這樣體量的工程,單為工程做一次VS配置就基本是一天的時(shí)間
而且UE4還不像UE3那樣就十幾個(gè)工程,把所有uproject都看做工程的話,得幾十了。依賴關(guān)系復(fù)雜度幾何增長,用VS的工具去維護(hù)……而且要維護(hù)各個(gè)平臺(tái)和配置……再加上維護(hù)完后Mac、Linux還得維護(hù)一遍……
但是為什么不使用成熟的CMAKE呢,私以為可能是因?yàn)閁BT里有一系列錯(cuò)綜復(fù)雜的規(guī)則,用CMAKE制作出來,即便可讀性O(shè)K,調(diào)試也比較麻煩。而且CMAKE對(duì)引擎使用者提出了一定的要求,而UBT則相對(duì)簡單——只要你不糾結(jié)它如何實(shí)現(xiàn)。
官網(wǎng)的這篇文章詳細(xì)解釋了為什么要做一個(gè)Build Tool出來:
https://docs.unrealengine.com/latest/INT/Programming/UnrealBuildSystem/ProjectFileGenerator/index.html
What are the advantages of generating project files?
可以先看看UBT的基本規(guī)則:
https://docs.unrealengine.com/latest/INT/Programming/UnrealBuildSystem/index.html
目前說來,虛幻的所有代碼集中在下面幾個(gè)文件夾里:
<Root>的Source,這個(gè)文件夾里主要是引擎代碼。
其中:
Source/Runtime里主要是引擎的核心代碼。
Source/Developer里似乎主要是一些工具工程。
Source/Editor里是編輯器相關(guān)代碼。
Source/Programs里是引擎使用中需要用到的工具。比如UBT、UnrealHeaderTool、Swarm(分布式光照計(jì)算系統(tǒng))等等。
Source/ThirdParty里是各種第三方庫。
<Root>的Plugin,這個(gè)文件夾里有各式各樣的Plugin實(shí)現(xiàn)。特殊的是Plugin的組織中需要多一個(gè)uplugin,可能是Plugin下可能會(huì)有一些資源什么的吧。我們后面再來看uplugin。
<工程項(xiàng)目>的Source,如果是代碼工程的話。
UBT目前只認(rèn)這幾個(gè)文件夾,也就是說,如果你要為引擎擴(kuò)展功能,您只能在這些文件夾里創(chuàng)建自己的工程。這一點(diǎn)是在UBT里寫死的,有代碼的可以關(guān)注一下UBT工程的FindAllRulesSourceFiles這個(gè)方法。
在這些文件夾里,您可以搜索到大量的*.Build.cs文件,這些Build.cs就是虛幻的工程組織核心,基本上,每個(gè)Build文件都可以被視為一個(gè)工程文件,而Build文件所在的文件夾可以被視為此工程的根目錄。接下來,我們不妨稱這些擁有Build.cs的文件夾為工程。UBT一開始會(huì)先去找所有的Build.cs,把它們放在一起生成一個(gè)臨時(shí)的dll。然后基于它們逐個(gè)進(jìn)行一系列的代碼分析工作,最后調(diào)用命令行進(jìn)行編譯和連接過程。
對(duì)于每個(gè)工程而言,代碼一般都散落在下面幾個(gè)文件夾:
Classes:如果你在工程根目錄下寫了個(gè)Classes,就相當(dāng)于告訴UBT這些文件是要用UnrealHeaderTool來生成運(yùn)行時(shí)反射信息的。所以,這個(gè)文件夾里頭文件的寫法必須符合可反射類的寫法規(guī)范。
還記得虛幻的哪些類是可反射的嗎?對(duì)了,所有UObject的派生類包括AActor的派生類。具體是否有所驗(yàn)證還沒看,不過最好是按照這個(gè)節(jié)奏來。
規(guī)范上無非主要就是USTRUCT、UCLASS這些宏,抄幾個(gè)就能找到感覺,或者用編輯器的類生成功能也可。
看起來,虛幻引擎發(fā)布時(shí)(不是通過編譯生成,而是通過Launcher下載的那種),這些Classes文件是隨引擎發(fā)布的,方便不具備全代碼的Mod愛好者和BluePrint開發(fā)者們來制作游戲。
Public:公共頭文件,跟Classes一樣隨著引擎發(fā)布而發(fā)布,所以這里一般都是些比較開放的接口,比如模塊入口、功能核心接口什么的;旧线@些接口沒有廢話,很清晰,跟實(shí)現(xiàn)相關(guān)的細(xì)節(jié)隱藏得非常好。與Classes相同,如果你的工程里有Public,那么里面的.h就會(huì)被當(dāng)作Public來。
Private:這個(gè)文件夾似乎不是虛幻定死的,也就是似乎可以不用Private的名字,或者多來幾個(gè)文件夾什么的。除了UHT中有一段代碼與之有一定關(guān)聯(lián)之外,UBT里是完全沒有跟這個(gè)有關(guān)的東西。它里面基本上就是各種實(shí)現(xiàn)代碼,以及要在實(shí)現(xiàn)間共享的頭文件。你也可以創(chuàng)建其他類似的文件夾,只需要Build.cs里寫上相應(yīng)的文件夾名即可:
此外還有需要注意的地方是Source根目錄下的Target.cs文件,Target的最終目標(biāo)一般都是可執(zhí)行文件,可以說,Target是整個(gè)生成期的入口,生成會(huì)首先從找到Target開始,如果沒有Target或者找不到,就會(huì)直接失敗。
此外,需要注意的是,Target.cs里面寫的類的類名,必須是Target.cs的文件名加Target,例如:Sample.Target.cs,其類名必須是SampleTarget。UBT的GetTargetTypeAndRulesInstance方法里印證了這一點(diǎn)。
UBT里面還是有不少限定用法的,Target就是其中之一,虛幻是一個(gè)比較強(qiáng)調(diào)命名的引擎,改名有很多麻煩,最好是能夠一步到位。
今天抽空看了看文檔,大概跟了跟UBT的流程,明天繼續(xù)。
行文匆匆,有些不太明白的地方評(píng)論里有補(bǔ)充,現(xiàn)在這里抱歉了!
半年多沒有維護(hù)博客了,一方面是媳婦懷孕,另一方面是公司年中有一個(gè)版本……
最近閑暇時(shí)間一直在研究虛幻,目前鋪開了大概六七個(gè)原型在做,做的過程中學(xué)到了不少東西,有一些新的想法。
本來這些都是準(zhǔn)備展開來說的,但是現(xiàn)在看來,每個(gè)話題展開都是需要大把的精力,所以還是先寫到這里。有些已經(jīng)有一些結(jié)論,有些還沒有展開研究,就當(dāng)是挖個(gè)坑吧,在后面幾個(gè)月陸續(xù)填。
目前博主所用的版本是4.4,有些結(jié)論未必在未來還繼續(xù)有效,如果發(fā)現(xiàn)有變化,后面會(huì)單起博客說明的。
總論:
仍在發(fā)展中,如果是準(zhǔn)備用來做短期商業(yè)項(xiàng)目的,請(qǐng)合理評(píng)估風(fēng)險(xiǎn)。用來進(jìn)行長期商業(yè)項(xiàng)目、或者覺得目前的功能已經(jīng)可用、或者以研究為目的的,可以考慮介入。
優(yōu)點(diǎn)是開發(fā)架構(gòu)和框架體系成熟,國內(nèi)策劃不做腳本不做原型的開發(fā)模式可能確實(shí)相對(duì)不易適應(yīng)。說程序用BP不習(xí)慣的恭喜您說出了一句正確的令人發(fā)指的廢話,BP是設(shè)計(jì)給策劃和關(guān)卡設(shè)計(jì)師用的,不是給你程序員用的——話說回來,也就在中國需要去把策劃的想法翻譯成代碼的程(Fan一聲)序(Yi四聲)員(Gong一聲)。
再次重申,如果您希望什么事兒都是程序給吃下來,或者您的項(xiàng)目被迫處于這種態(tài)勢(shì),而不是由策劃負(fù)責(zé)腳本和內(nèi)容的制作,那么請(qǐng)出門左轉(zhuǎn),找CE、Unity(大霧)或者其它引擎,虛幻這種跟歐美式開發(fā)方式深度綁定的引擎絕對(duì)不適合您。相信我,您只是在給自己找麻煩,然后回過頭來大罵這是一個(gè)垃圾引擎——其實(shí)只是您項(xiàng)目的開發(fā)模式不是原型開發(fā)模式,僅此而已。
沒有程序基礎(chǔ)的,看幾個(gè)例子應(yīng)該也可以自己用BP動(dòng)手做點(diǎn)原型了,我現(xiàn)在基本主要游戲邏輯都用BP做,C++給BP寫節(jié)點(diǎn)和第三方庫的整合插件。BP用熟悉了,比手寫代碼的開發(fā)效率高多了(編譯和部署時(shí)間、調(diào)試更直觀方便、而且本身拖圖的效率就不比手寫差太遠(yuǎn),有些情況下反而比手寫高)。
此外開放代碼,比較深坑的地方可以自己修改,也可以隨意整合各種C++庫進(jìn)來,許多細(xì)節(jié)的實(shí)現(xiàn)比較有參考意義,比如WeakPtr之類的。論壇里有許多C++庫的整合項(xiàng)目的通知,可以隨時(shí)關(guān)注。
缺點(diǎn)是上手需要一定成本,此外,平臺(tái)上不支持PSV、PS3、Xbox360這些平臺(tái),手機(jī)平臺(tái)不完全支持,希望全機(jī)種支持的要注意,目前只能考慮Unity或者M(jìn)onoGame。
升級(jí)快一方面也是一種缺點(diǎn),舊版本還在玩得不亦樂乎,新版本又添了一堆新東西,這不,博主還在頭疼于自己擴(kuò)展的自細(xì)分地表渲染插件在4.4下表現(xiàn)超級(jí)糟糕的問題,4.5出來直接這個(gè)問題沒有了……沒~有~了~,我那廢寢忘食地搞了一個(gè)周末是圖個(gè)啥……圖~個(gè)~啥~?!……所以,換句話說,專業(yè)的事情,交給專業(yè)的團(tuán)隊(duì)去就好了。重新發(fā)明輪子這種事兒,十年前是時(shí)尚,十年后就是愚蠢了。
工程部分:
Module不能出現(xiàn)重名。
Build.cs和Build類名必須一致。
可以創(chuàng)建獨(dú)立的Win32工程了,虛幻3是獨(dú)立Exe,如果想用到虛幻的功能,要么是需要把虛幻按照dll模式編譯加載,要么是整合在整個(gè)Launcher里,虛幻4可以創(chuàng)建獨(dú)立的Win32工程,工程里可以只用到虛幻的某些個(gè)子集。具體可參考引擎Solution里的那些Win32工程,此外,早期版Win32的工程設(shè)置和后期版的Win32工程設(shè)置不完全一樣?筛鶕(jù)自己的需要選擇最合適的模式。
多個(gè)項(xiàng)目間共享的功能,最好建立plugin工程。也可以修改UBT,添加自己的文件夾。
目前沒有找到能在獨(dú)立路徑下建立plugin的途徑,似乎只能放到項(xiàng)目的Plugins文件夾里或者引擎Source下的Plugins文件夾里。
發(fā)布Plugin給發(fā)布版用,4.3似乎是需要先找到發(fā)布版的Version.h文件,用這個(gè)文件覆蓋對(duì)應(yīng)Release版本Git庫中的對(duì)應(yīng)文件,然后再編譯和發(fā)布Release。
所有虛幻的Plugin是有加載順序的,有依賴關(guān)系的插件要注意,可以通過設(shè)定Plugin的加載階段和Dependency來解決這個(gè)問題。
一個(gè)工程(Plugin或者游戲工程)里可以包括多個(gè)模塊(Module),注意最好把核心部分和編輯器部分分開,否則發(fā)布游戲時(shí)發(fā)現(xiàn)依賴了一堆不需要的庫,太浪費(fèi)了?梢岳斫釶lugin和工程是一個(gè)打包單元,但Module是一個(gè)組織單元。
Object Core
反射實(shí)現(xiàn)很經(jīng)典,不一定優(yōu)美,但是很實(shí)用。博主之前試圖實(shí)現(xiàn)過一個(gè)C++版的反射,template絕對(duì)用得比它好(從boost mpl繼承過來的),就是因?yàn)槿绷怂莻(gè)分析代碼得到Meta數(shù)據(jù)的東西,導(dǎo)致維護(hù)Meta起來太復(fù)雜了……再次說明牛逼的技術(shù)不是在那里玩技術(shù)玩語法,而是在玩工作流……
類和模塊改名了,導(dǎo)致之前做的資源失效?Config文件中的redirector可以幫助你。
但不是萬能的,BP重命名要小心,似乎BP類名改過來了,但是里面的內(nèi)容沒有改過來……
資源更換文件夾后,本地仍然留有一個(gè)1k左右的"尾巴"?這也是redirector的"功勞"。請(qǐng)使用fix up清理。
虛幻的各個(gè)Ptr的實(shí)現(xiàn)很精彩。RefCount對(duì)象可走SharedPtr,此外還有WeakPtr等。
官方推薦瑣碎而單位時(shí)間比較小的異步功能,可以考慮TaskGraph。時(shí)間較長的異步功能可以自己寫Runnable。TaskGraph還沒太搞明白怎么回事。
Actor - Component
Movement拆出去了,UE3的Movement是整合在Actor體系內(nèi)的,重新實(shí)現(xiàn)不同的Movement會(huì)比較費(fèi)勁,F(xiàn)在好了,重新做一新的Movement就好,還可以在不同的工程之間重用。
Component具有父子關(guān)系了!不僅僅是SkeletalMesh對(duì)其它Component的父子關(guān)系,其它所有的Component都有父子關(guān)系了。
Actor的Tick貌似現(xiàn)在是多線程了,具體還沒有跟。
Player – Controller
輸入現(xiàn)在多了一個(gè)InputComponent,輸入消息由Controller截獲后,有可能會(huì)先發(fā)給激活的Pawn的InputComponent和其它InputComponent?梢赃\(yùn)行時(shí)動(dòng)態(tài)切換輸入所操控的對(duì)象。UE3只能由PlayerController發(fā)布所有的指令消息。
Component掛接,UE3的Attach/Detach已經(jīng)改名為Register/Unregister,在Register之前,需要先把root設(shè)置好。與UE3稍微有點(diǎn)不太一樣的是,Actor沒有顯式Register接口(FinishAndRegister做了一些附加的邏輯,調(diào)用前需要先評(píng)估是不是自己需要的),Register All什么的在Component數(shù)量多的時(shí)候非常昂貴。目前對(duì)部分Component的Register操作,經(jīng)實(shí)驗(yàn)是可以使用的。
渲染核心
Renderer現(xiàn)在有兩個(gè):ForwardShadingRenderer和DeferredShadingRenderer,4.5的變化還未跟蹤。
默認(rèn)是不開遠(yuǎn)裁剪面的,如有需求得自己主動(dòng)在View里面設(shè)置遠(yuǎn)裁剪面。
雖然多線程的調(diào)用型改了,但主體流程與UE3的渲染線程模型基本沒有變化,UE3的所有渲染擴(kuò)展方式,仍然基本可用,主要需要注意的是對(duì)其他設(shè)備的向下兼容性(主要關(guān)注Shader里的那些宏即可)。
Blueprint
目前主要用來開發(fā)原型,幾個(gè)版本的細(xì)節(jié)修改還是挺多的。
總而言之,首先需要提醒的是,用BP做項(xiàng)目,目前一定要記得多備份,最好自己架SVN服務(wù)器,改一點(diǎn)測(cè)一下就上傳一次,特別是跟接口和改名相關(guān)的場合。博主為此浪費(fèi)了兩天左右的時(shí)間。
目前Blueprint創(chuàng)建的Actor基類,其基類中指定的Component是無法被子類修改的,而且其屬性無法直接作為Actor的參數(shù)來修改。解決方法是在Actor中增加對(duì)應(yīng)屬性,并在Construct圖中,修正Actor的對(duì)應(yīng)屬性。
不帶函數(shù)返回值的BP函數(shù),重載時(shí)需要在Event Graph里進(jìn)行操作。帶函數(shù)返回值的BP函數(shù),則是右鍵重載。修改函數(shù)原型時(shí),要注意有可能會(huì)發(fā)生修改前是個(gè)右鍵函數(shù)重載,修改后是個(gè)Event圖重載。
修改與BP合作的Interface調(diào)用型的時(shí)候,BP的重載實(shí)現(xiàn)有可能會(huì)發(fā)生找不到或是其他情況,要小心,改之前記得備份。
全局方法和靜態(tài)方法怎么辦?可以做到BPFunctionLibrary里。
讀表雖然有DataTable什么的支持,但需要代碼介入,感覺不是很舒服,推薦自己整合讀表、讀文件功能到BP中,一勞永逸,代碼可以參考它Json解析和Csv解析部分。
UI
類似WPF,熟悉WPF的人應(yīng)該非常容易上手,數(shù)據(jù)綁定什么的基本都是WPF那套概念,對(duì)我這種WPF的鐵桿支持者簡直是如沐甘露。數(shù)據(jù)綁定也是那種上手很困難,但一旦上手就覺得其它所有UI系統(tǒng)都好Low啊這樣的東西……當(dāng)然,這玩意兒對(duì)性能的負(fù)面影響也是客觀存在的。一定程度下,性能跟系統(tǒng)的擴(kuò)展和方便程度成反比,永遠(yuǎn)不要想著魚與熊掌都能兼得,要能的話,早有人做出來了。
并非唯一選擇,Coherent UI什么的也有插件提供了,而且Coherent也支持Unity和CE3,商業(yè)項(xiàng)目可以考慮。
朱峰社區(qū)網(wǎng)頁版(手機(jī)掃描-分享-添加到屏幕)
朱峰社區(qū)微信公眾號(hào)(微信掃一掃-關(guān)注)
未知用戶
2005-2025 朱峰社區(qū) 版權(quán)所有 遼ICP備2021001865號(hào)-1
2005-2025 ZhuFeng Community All Rights Reserved
VIP