• UE4编译模块系统


    模块(Module)是构成Unreal Engine的基本元素,每个Module(build.cs)封装和实现了一组功能,并且可以供其他的Module使用。

    整个Unreal Engine就是靠各个Module组合来构成一个插件(uplugin)、项目(uproject)和目标(Target.cs)。

    build.cs

    一个模块是UE4的一个编译块,在windows编辑器中对应一个dll模块,在mac编辑器中对一个dylib模块

    每个模块有一个build.cs文件,控制的是Module编译过程,由它来控制所属Module的对其他Module的依赖、文件包含、链接、宏定义等相关的操作

    开发人员通过编写该文件来定义不同平台下模块的编译选项(如:头文件查找目录,预编译宏,依赖模块列表等)

    如Protobuf.Build.cs的配置内容如下:

    using UnrealBuildTool;
    using System;
    using System.IO;
    
    public class Protobuf : ModuleRules  // ModuleRules类型详见:ModuleRules.cs
    {
        public Protobuf(ReadOnlyTargetRules Target) : base(Target)
        {
            PCHUsage = PCHUsageMode.NoSharedPCHs;
    
            string MFProtobufHeadDir = Path.Combine(ModuleDirectory, "Public");
            PublicSystemIncludePaths.Add(MFProtobufHeadDir);
    
            bEnableUndefinedIdentifierWarnings = false;
    
            Definitions.AddRange(
                    new string[]
                    {
                        "HAVE_PTHREAD",
                        "PROTOBUF_INLINE_NOT_IN_HEADERS=1",
                        "GOOGLE_PROTOBUF_NO_RTTI"
                    });
    
    
            if (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64)
            {
                Definitions.Add("PROTOBUF_USE_DLLS");
                Definitions.Add("_CRT_SECURE_NO_WARNINGS");
            }
    
            PublicDependencyModuleNames.AddRange(new string[] {
                "Core",
            });
        }
    }

    Definitions:存放所有定义的宏。这些宏会被写入Intermediate\Build\Win64\UE4Editor\Debug\<Module>\Definitions.h中

                        编译器在编译每个c/cpp文件时,会带上/FI "Intermediate\Build\Win64\UE4Editor\Debug\<Module>\Definitions.h"参数,将在c/cpp文件的第一行上#include该文件

    每个模块中必须定义一个从IModuleInterface派生的类:

    /*** UnrealEngine\Engine\Source\Runtime\Core\Public\Modules\ModuleInterface.h  ***/
    class IModuleInterface
    {
    
    public:
    
        // 析构函数
        virtual ~IModuleInterface()
        {
        }
    
        // 模块加载创建时被调用
        virtual void StartupModule()
        {
        }
    
        // 模块卸载前被调用
        virtual void PreUnloadCallback()
        {
        }
    
        // 模块加载后被调用
        virtual void PostLoadCallback()
        {
        }
    
        // 模块销毁前被嗲用
        virtual void ShutdownModule()
        {
        }
    
        // 模块在运行时是否支持动态加载和卸载
        virtual bool SupportsDynamicReloading()
        {
            return true;
        }
    
        // 进程退出时,模块是否也自动Shutdown
        virtual bool SupportsAutomaticShutdown()
        {
            return true;
        }
    
        // 是否为Gameplay的模块
        virtual bool IsGameModule() const
        {
            return false;
        }
    };

    并通过IMPLEMENT_MODULE宏(或IMPLEMENT_GAME_MODULE宏,注:两个宏为同一个东西)来创建该类的实例

    /*** UnrealEngine\Engine\Source\Runtime\Core\Public\Modules\ModuleManager.h ***/
    #if
    IS_MONOLITHIC // Monolithic,宏IS_MONOLITHIC为1,即:代码会编译到一个模块中 如:cook后的pc和手机版本 // If we're linking monolithically we assume all modules are linked in with the main binary. #define IMPLEMENT_MODULE( ModuleImplClass, ModuleName ) \ /** Global registrant object for this module when linked statically */ \ static FStaticallyLinkedModuleRegistrant< ModuleImplClass > ModuleRegistrant##ModuleName( TEXT(#ModuleName) ); \ /* Forced reference to this function is added by the linker to check that each module uses IMPLEMENT_MODULE */ \ extern "C" void IMPLEMENT_MODULE_##ModuleName() { } \ PER_MODULE_BOILERPLATE_ANYLINK(ModuleImplClass, ModuleName) #else // 非Monolithic,宏IS_MONOLITHIC为0,即:代码会编译到多个dll中 如:在编辑器或standalone下 #define IMPLEMENT_MODULE( ModuleImplClass, ModuleName ) \ \ /**/ \ /* InitializeModule function, called by module manager after this module's DLL has been loaded */ \ /**/ \ /* @return Returns an instance of this module */ \ /**/ \ extern "C" DLLEXPORT IModuleInterface* InitializeModule() \ { \ return new ModuleImplClass(); \ // 创建模块对象的实例 } \ /* Forced reference to this function is added by the linker to check that each module uses IMPLEMENT_MODULE */ \ extern "C" void IMPLEMENT_MODULE_##ModuleName() { } \ PER_MODULE_BOILERPLATE \ PER_MODULE_BOILERPLATE_ANYLINK(ModuleImplClass, ModuleName) #endif //IS_MONOLITHIC

    如:Protobuf\Protobuf.cpp

    #include "Protobuf.h"
    #include "Modules/ModuleManager.h"
    
    IMPLEMENT_GAME_MODULE(FDefaultGameModuleImpl, Protobuf);

    模块的加载逻辑在FModuleManager::LoadModule函数中。FModuleManager类详见:

    /*** UnrealEngine\Engine\Source\Runtime\Core\Public\Modules\ModuleManager.h  ***/
    class CORE_API FModuleManager
        : private FSelfRegisteringExec  // 自动注册Exec函数来支持控制台命令
    {
        // 析构函数
        ~FModuleManager();
    
    public:
    
        // 获取FModuleManager单例
        static FModuleManager& Get( );
    
        // 销毁FModuleManager单例
        static void TearDown();
    
        // 抛弃模块
        void AbandonModule( const FName InModuleName );
    
        // 添加模块
        void AddModule( const FName InModuleName );
    
    #if !IS_MONOLITHIC
        void RefreshModuleFilenameFromManifest(const FName InModuleName);
    #endif    // !IS_MONOLITHIC
    
        // 得到指定模块指针
        IModuleInterface* GetModule( const FName InModuleName );
    
        // 指定模块是否加载
        bool IsModuleLoaded( const FName InModuleName ) const;
    
        // 加载指定模块
        IModuleInterface* LoadModule( const FName InModuleName );
    
        // 加载指定模块,并check检查它是否加载成功
        IModuleInterface& LoadModuleChecked( const FName InModuleName );
    
        // 加载指定模块,并调用该模块的PostLoadCallback函数
        bool LoadModuleWithCallback( const FName InModuleName, FOutputDevice &Ar );
    
        // 加载指定模块,如果失败则返回原因
        IModuleInterface* LoadModuleWithFailureReason( const FName InModuleName, EModuleLoadResult& OutFailureReason );
    
        // 查询指定模块的信息
        bool QueryModule( const FName InModuleName, FModuleStatus& OutModuleStatus ) const;
    
        // 查询指定多个模块的信息
        void QueryModules( TArray<FModuleStatus>& OutModuleStatuses ) const;
    
        // 卸载指定模块
        bool UnloadModule( const FName InModuleName, bool bIsShutdown = false );
    
         // 卸载或抛弃指定模块,在此之前调用PreUnloadCallback函数
        void UnloadOrAbandonModuleWithCallback( const FName InModuleName, FOutputDevice &Ar);
    
        // 抛弃指定模块,在此之前调用PreUnloadCallback函数
        void AbandonModuleWithCallback( const FName InModuleName );
    
        // 增加额外的搜索路径
        void AddExtraBinarySearchPaths();
    
        // 获取指定模块,并对它进行check检查
        template<typename TModuleInterface>
        static TModuleInterface& GetModuleChecked( const FName ModuleName )
        {
            FModuleManager& ModuleManager = FModuleManager::Get();
    
            checkf(ModuleManager.IsModuleLoaded(ModuleName), TEXT("Tried to get module interface for unloaded module: '%s'"), *(ModuleName.ToString()));
            return static_cast<TModuleInterface&>(*ModuleManager.GetModule(ModuleName));
        }
    
    private:
        static IModuleInterface* GetModulePtr_Internal(FName ModuleName);
    
    public:
    
        // 获取指定模块
        template<typename TModuleInterface>
        static FORCEINLINE TModuleInterface* GetModulePtr( const FName ModuleName )
        {
            return static_cast<TModuleInterface*>(GetModulePtr_Internal(ModuleName));
        }
    
        // 加载指定模块,并check检查它是否加载成功
        template<typename TModuleInterface>
        static TModuleInterface& LoadModuleChecked( const FName InModuleName)
        {
            IModuleInterface& ModuleInterface = FModuleManager::Get().LoadModuleChecked(InModuleName);
            return static_cast<TModuleInterface&>(ModuleInterface);
        }
    
        // 加载指定模块
        template<typename TModuleInterface>
        static TModuleInterface* LoadModulePtr( const FName InModuleName)
        {
            return static_cast<TModuleInterface*>(FModuleManager::Get().LoadModule(InModuleName));
        }
    
        // 使用通配符来查找模块
        void FindModules( const TCHAR* WildcardWithoutExtension, TArray<FName>& OutModules ) const;
    
        // 模块名的模块是否存在
        bool ModuleExists(const TCHAR* ModuleName) const;
    
        // 当前加载的模块数
        int32 GetModuleCount( ) const;
    
        // 关闭进程时卸载模块
        void UnloadModulesAtShutdown( );
    
    
        // ... ...// FSelfRegisteringExec interface. 控制台命令执行函数
        virtual bool Exec( UWorld* Inworld, const TCHAR* Cmd, FOutputDevice& Ar ) override;
    
    
        // ... ...
    
        /**
         * Information about a single module (may or may not be loaded.)
         */
        class FModuleInfo
        {
        public:
    
            /** The original file name of the module, without any suffixes added */
            FString OriginalFilename;
    
            /** File name of this module (.dll file name) */
            FString Filename;
    
            /** Handle to this module (DLL handle), if it's currently loaded */
            void* Handle;
    
            /** The module object for this module.  We actually *own* this module, so it's lifetime is controlled by the scope of this shared pointer. */
            TUniquePtr<IModuleInterface> Module;
    
            /** True if this module was unloaded at shutdown time, and we never want it to be loaded again */
            bool bWasUnloadedAtShutdown;
    
            /** True if this module is full loaded and ready to be used */
            TAtomic<bool> bIsReady;
    
            /** Arbitrary number that encodes the load order of this module, so we can shut them down in reverse order. */
            int32 LoadOrder;
    
            /** static that tracks the current load number. Incremented whenever we add a new module*/
            static int32 CurrentLoadOrder;
    
        public:
    
            /** Constructor */
            FModuleInfo()
                : Handle(nullptr)
                , bWasUnloadedAtShutdown(false)
                , bIsReady(false)
                , LoadOrder(CurrentLoadOrder++)
            { }
    
            ~FModuleInfo()
            {
            }
        };
    
        // ... ...
    };

    每个模块的c++代码中都可以使用 {全大写的模块名}_API的宏来在本模块中导出类和函数给其他模块使用

    进行动态链接库类型(dll, dylib)编译时,UBT会将当前模块的宏定义为DLLEXPORT来导出模块的类或函数,将非当前模块的宏定义为DLLIMPORT来导入其他模块的类或函数

    DLLEXPORTDLLIMPORT在不同的平台会被定义为如下内容:

    系统平台

    #include"HAL/Platform.h"

    宏定义

    windows

    见“WIndowsPlatform.h”

    #define DLLEXPORT __declspec(dllexport)
    #define DLLIMPORT __declspec(dllimport)

    Unix/Linux

    见“UnixPlatform.h”

    #define DLLEXPORT __attribute__((visibility("default")))
    #define DLLIMPORT __attribute__((visibility("default")))

    Mac

    见“MacPlatform.h”

    #define DLLEXPORT
    #define DLLIMPORT

    Android

    见“AndroidPlatform.h”

    #define DLLEXPORT __attribute__((visibility("default")))
    #define DLLIMPORT __attribute__((visibility("default")))

    iOS

    见“IOSPlatform.h”

    #define DLLEXPORT
    #define DLLIMPORT

    uproject、plugin

    游戏可以有多个模块(需配置在MyTest1.uproject),插件也可以有多个模块(需配置在plugin文件中)。

    游戏和插件中定义了其内部的模块及依赖的第三方plugin,并能拥有自己独立的资源(放在Content目录中)和配置文件(放在Config目录中)。

    另外,plugin还能拥有自己独立的着色器文件(放在Shaders目录中)和编辑器资源(放在Resources目录中)。

    插件可在plugin文件中设置自己缺省是否启用。   注1:设置EnabledByDefault为false,表示缺省不启用插件   注2:如果没有显示设置EnabledByDefault的值,为引擎插件则不启用,为项目插件则启用

    也可以在项目的MyTest1.uproject和项目的其他plugin文件中将某个Plugin关闭。

    "Plugins": [
        {
            "Name": "MyPlugin",
            "Enabled": false
        }
    ]

    注1:即使将plugin文件EnabledByDefault配置为false,当该plugin中module被其他的module引用到,插件会自动被启用

    注2:项目的MyTest1.uproject或plugin依赖某个Plugin时,可以不用显示地配置在uproject或Plugin文件中,但在对应Module的build.cs中必须配置好依赖的外部Module

    MyTest1.uproject对应ProjectDescriptor类型(见UnrealBuildTool中的ProjectDescriptor.cs文件),其配置内容如下:

    {
        "FileVersion": 3, // Descriptor version number.
        "EngineAssociation": "{CDEC017E-4B01-7570-44D6-02937BB1A0A4}", // The engine to open this project with.
        "Category": "", // Category to show under the project browser
        "Description": "", // Description to show in the project browser
        "Modules": [ // List of all modules associated with this project
            {
                "Name": "MyTest1",
                "Type": "Runtime",
                "LoadingPhase": "Default",
                "AdditionalDependencies": [
                    "Engine",
                    "CoreUObject"
                ]
            }
        ],
        "Plugins": [ // List of plugins for this project (may be enabled/disabled)
            {
                "Name": "MobilePatchingUtils",
                "Enabled": true
            },
            {
                "Name": "Wwise",
                "Enabled": true
            },
            {
                "Name": "GooglePAD",
                "Enabled": false
            }
        ],
    
        // A hash that is used to determine if the project was forked from a sample
        "EpicSampleNameHash": 125662,
        // Indicates if this project is an Enterprise project
        "IsEnterpriseProject": false,
        // Indicates that enabled by default engine plugins should not be enabled unless explicitly enabled by the project or target files.
        "DisableEnginePluginsByDefault": false,
    
        // Steps to execute before building targets in this project
        "PreBuildSteps": {
            "Win64": [
                "\"$(PluginDir)\\Source\\AkAudio\\WwisePostBuildSteps.bat\" \"$(EngineDir)\\Binaries\\Win64\\UE4Editor-cmd.exe\" \"$(ProjectFile)\" $(TargetType) -run=AkPluginActivator -platform=$(TargetPlatform) -configuration=Profile -targetconfig=$(TargetConfiguration)"
            ],
            "Mac": [
                "\"$(PluginDir)/Source/AkAudio/WwisePostBuildSteps.sh\" \"$(EngineDir)/Binaries/Mac/UE4Editor.app/Contents/MacOS/UE4Editor\" \"$(ProjectFile)\" $(TargetType) -run=AkPluginActivator -platform=$(TargetPlatform) -configuration=Profile -targetconfig=$(TargetConfiguration)"
            ]
        },
    
        // Steps to execute after building targets in this project
        "PostBuildSteps": {
            "Win64": [
                "\"$(PluginDir)\\Source\\AkAudio\\WwisePostBuildSteps.bat\" \"$(EngineDir)\\Binaries\\Win64\\UE4Editor-cmd.exe\" \"$(ProjectFile)\" $(TargetType) -run=AkPluginActivator -platform=$(TargetPlatform) -configuration=Profile -targetconfig=$(TargetConfiguration)"
            ],
            "Mac": [
                "\"$(PluginDir)/Source/AkAudio/WwisePostBuildSteps.sh\" \"$(EngineDir)/Binaries/Mac/UE4Editor.app/Contents/MacOS/UE4Editor\" \"$(ProjectFile)\" $(TargetType) -run=AkPluginActivator -platform=$(TargetPlatform) -configuration=Profile -targetconfig=$(TargetConfiguration)"
            ]
        },
    
        "AdditionalRootDirectories": [ // Array of additional root directories
            "MyRoot/Dir1", // -->D:\svn\MyTest1\MyRoot\Dir1
            "MyRoot/Dir2" // -->D:\svn\MyTest1\MyRoot\Dir2
        ],
        "AdditionalPluginDirectories": [ // List of additional plugin directories to scan for available plugins
            "MyPluginRoot/Dir1", // -->D:\svn\MyTest1\MyPluginRoot\Dir1
            "MyPluginRoot/Dir2" // -->D:\svn\MyTest1\MyPluginRoot\Dir1
        ],
        "TargetPlatforms": [ //Array of platforms that this project is targeting
            "Win64",
            "Android",
            "IOS",
            "Mac",
            "Linux"
        ]
    } 

    MyTest1.uplugin对应PluginDescriptor类型(见UnrealBuildTool中的PluginDescriptor.cs文件)。如:引擎的WebMMoviePlayer.uplugin插件:

    {
        "FileVersion": 3,
        "Version": 1,
        "VersionName": "1.0",
        "FriendlyName": "Movie Player for WebM files",
        "Description": "Movie Player for WebM files",
        "Category": "Movie Players",
        "CreatedBy": "Epic Games, Inc.",
        "CreatedByURL": "http://epicgames.com",
        "DocsURL": "",
        "MarketplaceURL": "",
        "SupportURL": "",
        "EnabledByDefault": true,
        "CanContainContent": false,
        "IsBetaVersion": false,
        "Installed": false,
        "Modules": [
            {
                "Name": "WebMMoviePlayer",
                "Type": "RuntimeNoCommandlet",
                "LoadingPhase": "PreLoadingScreen",
                "WhitelistPlatforms": [
                    "Win64",
                    "Linux",
                    "Mac"
                ],
                "BlacklistTargets": [
                    "Server"
                ]
            }
        ],
        "Plugins": [
            {
                "Name": "WebMMedia",
                "Enabled": true
            }
        ]
    }

    MyTest1.uproject和MyTest1.uplugin中Modules配置的Module,见UnrealBuildTool中的ModuleDescriptor.cs文件:

    /// <summary>
    /// The type of host that can load a module
    /// </summary>
    public enum ModuleHostType
    {
        /// <summary>
        /// 
        /// </summary>
        Default,
    
        /// <summary>
        /// Any target using the UE4 runtime
        /// </summary>
        Runtime,
    
        /// <summary>
        /// Any target except for commandlet
        /// </summary>
        RuntimeNoCommandlet,
    
        /// <summary>
        /// Any target or program
        /// </summary>
        RuntimeAndProgram,
    
        /// <summary>
        /// Loaded only in cooked builds
        /// </summary>
        CookedOnly,
    
        /// <summary>
        /// Loaded only in uncooked builds
        /// </summary>
        UncookedOnly,
    
        /// <summary>
        /// Loaded only when the engine has support for developer tools enabled
        /// </summary>
        Developer,
    
        /// <summary>
        /// Loads on any targets where bBuildDeveloperTools is enabled
        /// </summary>
        DeveloperTool,
    
        /// <summary>
        /// Loaded only by the editor
        /// </summary>
        Editor,
    
        /// <summary>
        /// Loaded only by the editor, except when running commandlets
        /// </summary>
        EditorNoCommandlet,
    
        /// <summary>
        /// Loaded by the editor or program targets
        /// </summary>
        EditorAndProgram,
    
        /// <summary>
        /// Loaded only by programs
        /// </summary>
        Program,
    
        /// <summary>
        /// Loaded only by servers
        /// </summary>
        ServerOnly,
    
        /// <summary>
        /// Loaded only by clients, and commandlets, and editor....
        /// </summary>
        ClientOnly,
    
        /// <summary>
        /// Loaded only by clients and editor (editor can run PIE which is kinda a commandlet)
        /// </summary>
        ClientOnlyNoCommandlet,
    }
    
    /// <summary>
    /// Indicates when the engine should attempt to load this module
    /// </summary>
    public enum ModuleLoadingPhase
    {
        /// <summary>
        /// Loaded at the default loading point during startup (during engine init, after game modules are loaded.)
        /// </summary>
        Default,
    
        /// <summary>
        /// Right after the default phase
        /// </summary>
        PostDefault,
    
        /// <summary>
        /// Right before the default phase
        /// </summary>
        PreDefault,
    
        /// <summary>
        /// Loaded as soon as plugins can possibly be loaded (need GConfig)
        /// </summary>
        EarliestPossible,
    
        /// <summary>
        /// Loaded before the engine is fully initialized, immediately after the config system has been initialized.  Necessary only for very low-level hooks
        /// </summary>
        PostConfigInit,
    
        /// <summary>
        /// The first screen to be rendered after system splash screen
        /// </summary>
        PostSplashScreen,
    
        /// <summary>
        /// After PostConfigInit and before coreUobject initialized. used for early boot loading screens before the uobjects are initialized
        /// </summary>
        PreEarlyLoadingScreen,
    
        /// <summary>
        /// Loaded before the engine is fully initialized for modules that need to hook into the loading screen before it triggers
        /// </summary>
        PreLoadingScreen,
    
        /// <summary>
        /// After the engine has been initialized
        /// </summary>
        PostEngineInit,
    
        /// <summary>
        /// Do not automatically load this module
        /// </summary>
        None,
    }
    
    
    /// <summary>
    /// Class containing information about a code module
    /// </summary>
    [DebuggerDisplay("Name={Name}")]
    public class ModuleDescriptor
    {
        /// <summary>
        /// Name of this module
        /// </summary>
        public readonly string Name;
    
        /// <summary>
        /// Usage type of module
        /// </summary>
        public ModuleHostType Type;
    
        /// <summary>
        /// When should the module be loaded during the startup sequence?  This is sort of an advanced setting.
        /// </summary>
        public ModuleLoadingPhase LoadingPhase = ModuleLoadingPhase.Default;
    
        /// <summary>
        /// List of allowed platforms
        /// </summary>
        public List<UnrealTargetPlatform> WhitelistPlatforms;
    
        /// <summary>
        /// List of disallowed platforms
        /// </summary>
        public List<UnrealTargetPlatform> BlacklistPlatforms;
    
        /// <summary>
        /// List of allowed targets
        /// </summary>
        public TargetType[] WhitelistTargets;
    
        /// <summary>
        /// List of disallowed targets
        /// </summary>
        public TargetType[] BlacklistTargets;
    
        /// <summary>
        /// List of allowed target configurations
        /// </summary>
        public UnrealTargetConfiguration[] WhitelistTargetConfigurations;
    
        /// <summary>
        /// List of disallowed target configurations
        /// </summary>
        public UnrealTargetConfiguration[] BlacklistTargetConfigurations;
    
        /// <summary>
        /// List of allowed programs
        /// </summary>
        public string[] WhitelistPrograms;
    
        /// <summary>
        /// List of disallowed programs
        /// </summary>
        public string[] BlacklistPrograms;
    
        /// <summary>
        /// List of additional dependencies for building this module.
        /// </summary>
        public string[] AdditionalDependencies;
    }

    Target.cs

    Target.cs控制的是生成的可执行程序。如:生成的是什么Type(Game/Client/Server/Editor/Program),开不开启 RTTI (bForceEnableRTTI),CRT 使用什么方式链接 (bUseStaticCRT)等等。

    不同Target(MyTest1.Target.cs、MyTest1Editor.Target.cs、MyTest1Server.Target.cs)中配置当前项目下属于自己Target的模块列表。

    MyTest1Target.cs

    using UnrealBuildTool;
    using System.Collections.Generic;
    using Tools.DotNETCommon;
    using System;
    using System.IO;
    
    public class MyTest1Target : TargetRules
    {
        public MyTest1Target(TargetInfo Target) : base(Target)
        {
            // Enable PSO Collection miss report
            if(Target.Platform == UnrealTargetPlatform.Android ||
                Target.Platform == UnrealTargetPlatform.IOS)
            {
                System.Environment.SetEnvironmentVariable("ENABLE_PSO_REPORT", "FALSE");
            }
    
            Type = TargetType.Game;
    
            ExtraModuleNames.AddRange( new string[] {
                "MyCommon",
                "MyGame",
            } );
    
            if (Configuration == UnrealTargetConfiguration.Shipping
             || Configuration == UnrealTargetConfiguration.Test)
            {
                bUseLoggingInShipping = true;
            }
        }
    }

     MyTest1EditorTarget.cs

    using UnrealBuildTool;
    using System.Collections.Generic;
    
    public class MyTest1EditorTarget : TargetRules
    {
        public MyTest1EditorTarget(TargetInfo Target) : base(Target)
        {
            Type = TargetType.Editor;
    
            ExtraModuleNames.AddRange( new string[] {
                "MyCommon",
                "MyGame",
                "MyGameEditor",
            } );
    
            bUseUnityBuild = true;
            bUsePCHFiles = true;
    
            //for debugging on a different machine
            bUseFastPDBLinking = false;
    
            bCompileForSize = false;
            bAllowLTCG = false;
    
            //Win64开启变量初始化顺序约束,会引发编译引擎和编译项目的参数不同,导致重新编译,放到引擎里面导致引擎通用化减弱,先关闭
            if (Target.Platform == UnrealTargetPlatform.Win64)
            {
                //bOverrideBuildEnvironment = true;
                //AdditionalLinkerArguments += " /release";
                //AdditionalCompilerArguments += " /we5038";
            }
        }
    }

    MyTest1ServerTarget.cs

    using UnrealBuildTool;
    using System.Collections.Generic;
    
    public class MyTest1ServerTarget : TargetRules
    {
        public MyTest1ServerTarget(TargetInfo Target) : base(Target)
        {
            Type = TargetType.Server;
    
            ExtraModuleNames.AddRange( new string[] {
                "MyCommon",
                "MyGame",
            });//for debugging on a different machine
            bUseFastPDBLinking = false;
    
            if (Configuration == UnrealTargetConfiguration.Shipping
             || Configuration == UnrealTargetConfiguration.Test)
            {
                bUseLoggingInShipping = true;
            }
    
            // enable push model
            bWithPushModel = true;
    
            LinuxPlatform.bEnableThinLTO = false;
        }
    }

    参考

    虚幻引擎模块

    如何在虚幻引擎中创建Gameplay模块

    虚幻编译工具

    UE Build System:Target and Module

    Build flow of the Unreal Engine4 project

    UE4 Modules:Load and Startup 

    UE4 Modules:Find the DLL and load it 

  • 相关阅读:
    Tomcat 配置支持APR
    javascript 字符串去空格
    cordova 跨平台APP版本升级
    cordova-ios 升级到4.4.0 无法真机跑iOS8 报错: dyld`dyld_fatal_error: -> 0x120085088 <+0>: brk #0x3
    iOS 项目架构tabbarController 嵌套 navbarController
    iOS + Node + MySQL
    angularjs中的单选框绑定数据注意事项
    angular2新建的项目上传github
    ionic 下拉选择框中默认显示传入的参数
    JavaScript学习笔记
  • 原文地址:https://www.cnblogs.com/kekec/p/10604221.html
Copyright © 2020-2023  润新知