? 欧美人与动XXXXZ0OZ视频,无码专区一码二码三码
聯(lián)系我們

給我們留言

聯(lián)系我們

地址:福建省晉江市青陽街道洪山路國際工業(yè)設(shè)計園納金網(wǎng)

郵箱:info@narkii.com

電話:0595-82682267

(周一到周五, 周六周日休息)

當前位置:主頁 > 3D教程 > 圖文教程

UnrealEngine4版本兼容的工作原理以及一些可優(yōu)化項

來源: 納金網(wǎng) | 責任編輯:傳說的落葉 | 發(fā)布時間: 2019-06-13 08:36 | 瀏覽量:

Unreal Engine 4 —— 版本兼容的工作原理以及一些可優(yōu)化項

 
這篇文章講解了在UE4中涉及到版本之間識別、切換的工作原理以及一些可優(yōu)化項的介紹。
 
本文章翻譯自Robert Throughton的UE4: Package Versioning… How It Works… And An Optimization,傳送門。
 
這篇文章的翻譯已征得原作者同意。
 
This post is translated from English. You can find the original English language version here: http://coconutlizard.co.uk/blog/ue4/ue4-package-versioning
 
UE4的版本迭代
 
Unreal Engine 在確保Editor以及cooked內(nèi)容可以在多個不同的引擎版本之間通用這一塊有很不錯的表現(xiàn)。而且為了讓程序員能夠在這些不同的版本之間很方便的更改數(shù)據(jù)結(jié)構(gòu),Unreal Engine也提供了一些機制。這篇博客將通過GetLinkerUE4Version()及其相關(guān)的函數(shù)來分析版本之間相關(guān)的內(nèi)容。
 
首先,我們需要了解引擎有哪些不同種類的版本:
 
UE4Version: 每當Epic在原來的代碼之上做了一些修改后,這個數(shù)字便會增加。 
這個版本號只能由Epic來進行改動。
UE4LicenseeVersion: 當代碼改動后,這個數(shù)字同樣會增加。但是這是一個“安全的”版本號,這意味著你(開發(fā)者)可以在這個基礎(chǔ)之上進行代碼的更改。 
這個數(shù)字可以通過開發(fā)者(Licensees)進行更改。
CustomVersion: 這個版本號可以用于在不同的工程師之間進行迭代而不引起沖突。
如何使用UE4的版本迭代
 
通常來說,我們通常使用GetLinkerUE4Version()函數(shù)和GetLinkerLicenseeUE4Version()來處理不同版本之間的問題。
 
接下來我將給出一個Epic使用GetLinkerUE4Version()函數(shù)來修正一些內(nèi)容的例子:
 
在這段時間內(nèi),某個人增加了一個用于設(shè)定Visibility的Blueprint變量。但是很蛋疼的是,他們犯了一個錯誤,丟失了一個visibility中的第三個’i’。
 
后來,某個人發(fā)現(xiàn)了這個問題,因此他們在UWidgetBlueprint::PostLoad()函數(shù)中加入如下的函數(shù),用于修正這個錯誤:
 

[代碼]:

01 if ( GetLinkerUE4Version() < VER_UE4_RENAME_WIDGET_VISIBILITY )
02 {
03     static const FName Visiblity(TEXT("Visiblity"));
04     static const FName Visibility(TEXT("Visibility"));
05  
06     for ( FDelegateEditorBinding& Binding : Bindings )
07     {
08         if ( Binding.PropertyName == Visiblity )
09         {
10             Binding.PropertyName = Visibility;
11         }
12     }
13 }
 
然后他們在ObjectVersion.h頭文件中增加了一個針對于這個修改的宏:
 

[代碼]:

1 // Rename Visiblity on widgets to Visibility
2 VER_UE4_RENAME_WIDGET_VISIBILITY,
 
因此,整個的工作流程如下:
 
當一個比較老版本的有拼寫錯誤的包被載入時,這個包的版本號會比VER_UE4_RENAME_WIDGET_VISIBILITY更小。
此時,上面的代碼會被激活,用于修正拼寫錯誤。
如果這個包被保存了,它會使用正確的拼寫,并且把版本號設(shè)定為最新的版本號。
這種做法在很多地方都有使用,例如:
 
在類里面增加/廢除一些新的變量。
增加一些我們想要改變的Patch.
版本號對應(yīng)宏
 
在頭文件ObjectVersion.h中,記錄了Epic是如何處理版本迭代的,首先是EUnrealEngineObjectUE4Version:
 
 

[代碼]:

01 enum EUnrealEngineObjectUE4Version
02 {
03     VER_UE4_OLDEST_LOADABLE_PACKAGE = 214,
04  
05     // Removed restriction on blueprint-exposed variables from being read-only
06     VER_UE4_BLUEPRINT_VARS_NOT_READ_ONLY,
07     // Added manually serialized element to UStaticMesh (precalculated nav collision)
08     VER_UE4_STATIC_MESH_STORE_NAV_COLLISION,
09     // Changed property name for atmospheric fog
10     VER_UE4_ATMOSPHERIC_FOG_DECAY_NAME_CHANGE,
11 ...
12  
13     // -----<new versions="" can="" be="" added="" before="" this="" line="">-------------------------------------------------
14     // - this needs to be the last line (see note below)
15     VER_UE4_AUTOMATIC_VERSION_PLUS_ONE,
16     VER_UE4_AUTOMATIC_VERSION = VER_UE4_AUTOMATIC_VERSION_PLUS_ONE - 1
17 };</new>
 
同樣的,還有EUnrealEngineObjectLicenseeUE4Version,也在同一個頭文件中:
 

[代碼]:

1 enum EUnrealEngineObjectLicenseeUE4Version
2 {
3     VER_LIC_NONE = 0,
4     // - this needs to be the last line (see note below)
5     VER_LIC_AUTOMATIC_VERSION_PLUS_ONE,
6     VER_LIC_AUTOMATIC_VERSION = VER_LIC_AUTOMATIC_VERSION_PLUS_ONE - 1
7 };
 
EUnrealEngineObjectLicenseeUE4Version有如下的注意事項:
 
就如同上面提到的,licensees**只能**在EUnrealEngineObjectLicenseeUE4Version列表中進行迭代
只能在該列表的最下面進行添加
當使用例如Perforce之類的代碼管理工具時,務(wù)必注意針對于包被保存后進行處理,否則這個包容易被玩壞。針對于這種情況,最簡單的解決方案就是當版本號改變的時候,不允許check in
我們?yōu)楹沃荒苡肬E4LicenseeVersion呢?考慮如下的狀況:
 
一個項目使用UE4.11開始
我們對于UE4Version進行了迭代,加了一些我們覺得很酷的功能
我們merge了UE4.12,然后發(fā)現(xiàn)我們出現(xiàn)了一個沖突 —— Epic也在4.12迭代了這一塊的功能…在此情況下,我們只能: 
把Epic的新版本號插入到列表里面的最后而將我們自己的迭代版本號設(shè)為不變 - 這樣就意味著我們可以使用我們自己的內(nèi)容,但是Epic提供的一些新的功能應(yīng)該都用不了了。
把我們的版本號移到最后 - 但是這樣先前所做的功能便會出很大問題。
以上所出現(xiàn)的問題很可能是致命的,我們當初在UE3里面也犯過這種錯誤,我們花了好一陣時間進行re-patch。所以我再次提醒 —— 只使用UE4LicenseeVersion.
 
當版本號出現(xiàn)問題
 
在這么久的開發(fā)生涯中,我經(jīng)歷了不少的由于版本號沖突而導致的崩潰,我希望這些問題能夠帶給讀者一些啟發(fā)。
 
要弄懂這些問題到底從何二來,我們首先要了解版本號是如何運作的?,F(xiàn)在假如說我們有一個包使用了很久以前的版本號256來進行儲存,而現(xiàn)在的版本號是259.當這個包被載入的時候,它需要經(jīng)過257、258和259三個版本的迭代處理。
 
以下是我總結(jié)出的最可能導致版本號出現(xiàn)問題的狀況:
 
Merge了其他的迭代邏輯,但是還沒有提交版本控制的邏輯。而團隊的其他程序員還沒有merge其他的迭代邏輯。 
在本地測試,沒有任何問題。
對于其他的開發(fā)者,就開始抱怨崩潰了。 
其他開發(fā)者已經(jīng)更新了迭代的邏輯。
在其他開發(fā)者的版本中,這個迭代就有了一個不同的版本號。
但是你已經(jīng)將自己的迭代放到了list的末尾,系統(tǒng)現(xiàn)在出現(xiàn)混亂。
當這個包被載入的時候,引擎認為你自己的迭代已經(jīng)載入(但是實際上沒有)。
你從Epic那里integrate了一個新的版本迭代,并且在版本列表中加入了一個新的宏定義。 
然而,在Epic的ObjectVersion.h頭文件中,在你integrate的地方之前之后,Epic做了一些新的改動。
你之后進行了一個full integration,把Epic添加的額外宏定義進行了添加。 
Crashes/bugs開始出現(xiàn),因為有一些patch現(xiàn)在的順序已經(jīng)亂了。
看來似乎唯一“正確”的方法只有添加那些你integrate之后的東西了。 
但是這依然會出事,只要Epic提供的官方內(nèi)容在其他的地方被保存了,那么這個包依然可能出現(xiàn)問題。
我們發(fā)現(xiàn)的一些可優(yōu)化項
 
當項目的內(nèi)容被cook完后,Saved文件夾下的內(nèi)容中,所有的包的版本號都會被設(shè)為最大。因此我才有了這個優(yōu)化的想法。
 
即使游戲是在載入已被cooked的內(nèi)容,引擎也不會默認它是最新的。這樣可以使得當你改變一些包的版本號時,不需要重新cook所有的東西。但是,頻繁的檢查內(nèi)容是否需要更新的操作是很昂貴的。尤其對于Shipping的包,這也并非必要。所以我們進行一些假設(shè):
 
Shipping包只在被cooked的內(nèi)容下工作。
Shipping包中只會有完全被cooked到最新版本的內(nèi)容。
如果這些假設(shè)成立,那么我們便可以進行優(yōu)化,告訴編譯器我們不需要去運行patching代碼。
 
也就是說,我們需要告訴編譯器讓它的每一次檢查例如:if ( GetLinkerUE4Version() < VER_…之類的代碼都會失敗,而且每一次檢查例如:if ( GetLinkerUE4Version() >= VER_…之類的代碼都會成功。因此最簡單的方法就是讓每個Get—Version()類型的函數(shù)都返回當前最新的版本號。
 
因此我們在頭文件中進行處理,來確保編譯器可以將其設(shè)為內(nèi)聯(lián)。
 
所以……我們是這樣進行操作的:
 
我們在UObjectBaseUtility.h頭文件的最開頭: 
#define ASSUME_UE4VERSIONS_ARE_LATEST (UE_BUILD_SHIPPING && !WITH_EDITORONLY_DATA)
 
需要注意的是,我們在項目中的設(shè)定是Shipping包只能在運行cooked builds里面運行,針對于不同的項目你需要進行調(diào)整。
 
在GetLinkerUE4Version()前,你應(yīng)該加入如下代碼:
 

[代碼]:

1 #if ASSUME_UE4VERSIONS_ARE_LATEST
2   FORCEINLINE int32 GetLinkerUE4Version() const return VER_LATEST_ENGINE_UE4; }
3   FORCEINLINE int32 GetLinkerLicenseeUE4Version() const return VER_LATEST_ENGINE_LICENSEEUE4; }
4   FORCEINLINE int32 GetLinkerCustomVersion(FGuid CustomVersionKey) const  return MAX_int32; }
5 #else // ASSUME_UE4VERSIONS_ARE_LATEST
6   /**
7    * Returns the UE4 version of the linker for this object.
 
在GetLinkerCustomVersion()后面,加入如下代碼:
 

[代碼]:

1   int32 GetLinkerCustomVersion(FGuid CustomVersionKey) const;
2 #endif // ASSUME_UE4VERSIONS_ARE_LATEST
 
現(xiàn)在我們開始重寫版本控制函數(shù)的cpp代碼,我們需要在ObjectBaseUtility.cpp文件開頭,在include 語句之后加入如下代碼:
 

[代碼]:

1 #include "CoreUObjectPrivate.h"
2 #if !ASSUME_UE4VERSIONS_ARE_LATEST
 
在文件末尾加入:
 

[代碼]:

1 #endif // !ASSUME_UE4VERSIONS_ARE_LATEST
 
這些就是所有的了,現(xiàn)在編譯器應(yīng)該能夠完全去掉patching代碼,這樣一來整個代碼簡潔很多。
 
其他的意見(給Epic)
 
我見過了太多l(xiāng)icensees會直接在EUnrealEngineObjectUE4Version中加入自己的宏定義了… 還是盡量避免這樣吧。如果是我的話我會加入一些注釋,把:
 
 

[代碼]:

1 // -----<new versions="" can="" be="" added="" before="" this="" line="">-------------------------------------------------
2  // - this needs to be the last line (see note below)
3  VER_UE4_AUTOMATIC_VERSION_PLUS_ONE,
4  VER_UE4_AUTOMATIC_VERSION = VER_UE4_AUTOMATIC_VERSION_PLUS_ONE - 1
5 };</new>

 
改為:
 
 

[代碼]:

1 // LICENSEES SHOULD NOT ADD CODE HERE!
2  // PLEASE USE EUnrealEngineObjectLicenseeUE4Version INSTEAD!
3  // ADDING CODE HERE WILL MAKE FUTURE INTEGRATIONS HARD!
4  // -----<new versions="" can="" be="" added="" before="" this="" line="">-------------------------------------------------
5  VER_UE4_AUTOMATIC_VERSION_PLUS_ONE,
6  VER_UE4_AUTOMATIC_VERSION = VER_UE4_AUTOMATIC_VERSION_PLUS_ONE - 1
7 };</new>

 
另外,如下的代碼也可以更改,讓其從:
 
 

[代碼]:

1 enum EUnrealEngineObjectLicenseeUE4Version
2  {
3    VER_LIC_NONE = 0,
4    // - this needs to be the last line (see note below)
5    VER_LIC_AUTOMATIC_VERSION_PLUS_ONE,
6    VER_LIC_AUTOMATIC_VERSION = VER_LIC_AUTOMATIC_VERSION_PLUS_ONE - 1
7  };

 
改為:
 

[代碼]:

1 enum EUnrealEngineObjectLicenseeUE4Version
2 {
3   VER_LIC_NONE = 0,
4   // -----<new versions="" can="" be="" added="" before="" this="" line="">-------------------------------------------------
5   VER_LIC_AUTOMATIC_VERSION_PLUS_ONE,
6   VER_LIC_AUTOMATIC_VERSION = VER_LIC_AUTOMATIC_VERSION_PLUS_ONE - 1
7 };</new>
 
還有可以嘗試對版本控制之類的名字估計可以從EUnrealEngineObjectUE4Version重命名為EUnrealEngineObjectPleasePleaseOnlyForEpicChangesUE4Version之類的。請務(wù)必讓用戶了解到直接更改這一塊的危害!我甚至見過非常有經(jīng)驗的開發(fā)者在這里栽過跟頭。
 

相關(guān)文章
網(wǎng)友評論

您需要登錄后才可以發(fā)帖 登錄 | 立即注冊

關(guān)閉

全部評論:0條

推薦
熱門