UE的EULA License Grant/(A)**中明确说明了,使用UE开发并再分发的内容不得包含未Cook的源格式和基于引擎工具**开发的付费内容,本篇文章研究一下EULA里对内容分发的具体内容和从技术上怎么绕过这个限制。
There is no restriction on your Distribution of a Product made using the Licensed Technology that does not include any Engine Code or any Paid Content Distributed in uncooked source format (in each case, including as modified by you under the License) and does not require any Licensed Technology (including as modified by you under the License) to run (“Unrestricted Products”). For clarity, the foregoing does not constitute a license under any patents, copyrights, trademarks, trade secrets or other intellectual property rights, whether by implication, estoppel or otherwise.
而EULA中对于Engine Tools
的定义是:
“Engine Tools” means (a) editors and other tools included in the Engine Code; (b) any code and modules in either the Developer or Editor folders, including in object code format, whether statically or dynamically linked; and (c) other software that may be used to develop standalone products based on the Licensed Technology.
这意味着开发者无法在游戏内容中使用Editor
与Developer
下的任何模块。
用户协议是具有法律效力的协议文件,我本着要折腾一下的精神并且想顺便看一下UE是怎么实现这个限制的,仅作记录分析用,并不会对内容进行收费的二次分发或用在正式的项目中。我读了一下UBT的处理逻辑,UBT的代码只需要简单地改几处。
注意:在正式的发行版本中这么做是违反UE的EULA的,强烈不建议在正式项目中这么做。
本文代码和编译均基于UE_4.18版本(本地通过源码编译出的引擎),本文介绍的操作不适用从EpicLauncher安装的引擎,文末会写原因。
在UE中,当打包的游戏(Target is Game
)为Shipping
的时候,如果工程中中包含了Editor
/Developer
的模块,会报下列错误:
1 | UATHelper: Packaging (Windows (64-bit)): ERROR: ERROR: Non-editor build cannot depend on non-redistributable modules. C:\Users\imzlp\Documents\Unreal Projects\EULA418\Binaries\Win64\EULA418-Win64-Shipping.exe depends on 'DesktopPlatform'. |
意思就是DesktopPlatform
是不可再发行的模块,你不能在Game
中用,通过查看UBT的代码发现这个异常是在UBT的CheckForEULAViolation
中抛出的:
1 | // Source/Programs/UnrealBuildTools/Configuration/UEBuildTarget.cs |
关键的判断是IsRedistributable
这个方法(概念等同于C++里的成员函数):
1 | // Source/Programs/UnrealBuildTools/Configuration/UEBuildTarget.cs |
这里做的判断是模块是不是属于Editor
/Developer
的,是就返回true
,从而进行下面的异常抛出。为了测试我将这里直接修改为return true;
只是改了上面之后还是打包不成功,不过现在的错误变成了链接错误。继续看UBT的代码后发现还有一个地方对打包是Shipping
的模式做了判断(前后的// ...
表示省略了不相关代码):
1 | // Source/Programs/UnrealBuildTools/Configuration/UEBuildTarget.cs |
将上面关于bAllowDeveloperModules
的部分注释掉,然后直接:
1 | Directories.Add(UnrealBuildTool.EngineSourceDeveloperDirectory); |
重新编译UBT即可。
然后可以写个简单的例子测试了,比如使用Developer下的DesktopPlatform
来调用系统的选择文件。
首先在*.build.cs
中添加DesktopPlatform
模块依赖:
1 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" ,"DesktopPlatform"}); |
然后写一个简单的函数暴露给蓝图:
1 | // .h |
正常的情况下,将上面的代码打包Shipping会产生文章最开始的错误,但是我们改过之后可以打包成功并且可以正确执行,这个简单的工程和打包的内容可以在这里下载。
启动之后按下数字键1
(不是Num 1
)即可打开windows的选择文件窗口,选择之后会将选择的文件的路径显示到屏幕上。
注意:需要使用源码版引擎编译项目,如果编译时具有
noexcept
的错误,则可以在项目的*.target.cs
中添加bForceEnableExceptions = true;
。
重新编译项目会编译引擎内的模块(打开从EpicLauncher安装的引擎文件夹就可以知道,默认Editor/Developer的模块是没有编译出静态链接库的,这也是不能用从EpicLauncher安装的引擎来执行本文的操作的原因)。