Unity Editor v4.3.1f1 源码编译笔记
2018-05-21 18:00:000x00 前言
Unity
是“手游时代”的最热门的游戏开发引擎,很多团队使用 Unity
进行开发,市面上使用 Unity
开发的热门游戏更是数不胜数,甚至暴雪的《炉石传说》也使用 Unity
开发,可见 Unity
是一款很强大的引擎。然而对于一些求知欲旺盛的开发者,Unity
有一个缺点,就是它的核心部分是不开放源码的,现在国内一些大公司也陆续购买了 Unity
的源码进行二次开发,可惜我供职的公司还仅仅在计划购买,等到真的拿到代码还不知道要多久时间。一次偶然的机会在论坛上看到有人分享了一份 Unity
代码,虽然只是几年前的 4.x
版本,但也多少能窥出一点端倪,于是有了这篇笔记所记录的 Unity Editor v4.3.1f1
的编译过程。
0x01 源码获取
unity-source-4.3.1f1-e1ff3bcdcd18-pcmac_android_ios.zip 【略】
0x02 准备工作
庆幸的是源码压缩包中还带有文档,通过简单的阅读得知,这个版本的源码建议使用 Windows 7 SP1
+ Visual Studio 2010 SP1
。我的电脑里已经装了 vs2015
和 vs2017
了。不想把全家桶都装上,于是干脆 hyper-v
创建了一个虚拟机,干干净净,也免去了很多麻烦。步骤简单记录如下:
Hyper-V
全新安装Windows
(en_windows_10_consumer_editions_version_1803_updated_march_2018_x64_dvd_12063379.iso)- 安装
Visual Studio 2010
(en_visual_studio_2010_ultimate_x86_dvd_509116.iso) - 安装
Visual Studio 2010 SP1
(VS10SP1-KB983509.exe) - 安装
Active Perl
(ActivePerl-5.22.4.2205-MSWin32-x86-64int-403863.exe) - 解压源码包
有几个地方需要注意:
- 最好安装英文系统,如果你使用的中文系统又不打算安装虚拟机,那么在编译之前修改
Projects\Jam\Editor.jam
文件,在 360 行插入/wd4819
(当然你也可以用其他的方法解决4819错误,比如把报错的源文件另存为指定的unicode
格式) - 一定要安装
Visual Studio 2010 SP1
,否则编译CPUInfo.cpp
时会报错,找不到_xgetbv
方法 最好安装x86
版本的Perl
- 解压的时候注意最终路径名不要过长,否则下一步解压依赖库的时候会报错,如果是
X:\unity
最好
0x03 解压依赖库&生成vs工程文件
在解压出来的 Unity
源码路径下运行:
perl build.pl --prepare
此时会在 Projects\JamGenerated\_workspace.vs2010_
目录下生成 solution
文件,如果你仅仅只想更方便的阅读源码,那么到这一步就可以了 (Projects\Sublime
下面有 Sublime
的工程,习惯使用 Sublime
的可以直接打开)
0x04 处理许可管理相关代码
这一步其实理论上可以略过,因为 Unity 4.x
也还是可以运行的,证明激活服务器还在运行,但是我尝试过不修改任何管理 License
的代码,总是会弹出一个 ssl peer certificate or ssh remote key was not ok
的 warning
。
最干净的办法是修改 Editor\Src\LicenseInfo.cpp
,把所有用到 LicenseManger
的地方全部替换掉,代码如下:
// some include...
LicenseInfo* gSingleton = NULL;
LicenseInfo::LicenseInfo()
{
InitializeProtection();
}
void LicenseInfo::InitializeProtection()
{
gSingleton = this;
m_Tokens = 1; // make token 1 cause some places check if token is zero
}
void LicenseInfo::SetRXValue(const char* value) {}
void LicenseInfo::SignalUserClosedWindow() {}
void LicenseInfo::GenericErrorDialog(const char* title) {}
void LicenseInfo::UnknownErrorDialog(const char* title) {}
void LicenseInfo::DisplayErrorDialog(const char* title, const char* url) {}
void LicenseInfo::ReloadEditorUI () {}
void LicenseInfo::Tick() {}
void LicenseInfo::ShowUpdateFeedbackDialog(bool success) {}
bool LicenseInfo::GetLargeFlag(LicenseInfoFlag f) { return false; }
string LicenseInfo::GetLicenseString () { return "Cracked for study"; }
bool LicenseInfo::OngoingServerCommunication() { return true; }
string LicenseInfo::GetMachineID() { return ""; }
string LicenseInfo::GetAuthToken () { return ""; }
UInt64 LicenseInfo::GetRawFlags ()
{
return m_Tokens;
}
void LicenseInfo::Reauthorize() {}
LicenseInfo::~LicenseInfo()
{
if (gSingleton == this)
gSingleton = NULL;
}
LicenseInfo* LicenseInfo::Get ()
{
if(gSingleton == NULL)
gSingleton = new LicenseInfo();
return gSingleton;
}
void LicenseInfo::Cleanup ()
{
delete gSingleton;
gSingleton = NULL;
}
string LicenseInfo::GetDisplaySerialNumber () { return ""; }
int LicenseInfo::SaveLicenseFile ( string licenseData ) { return 0; }
void LicenseInfo::ReturnLicense () {}
bool LicenseInfo::IsLicenseUpdated () { return true; }
void LicenseInfo::CallActivationServer () {}
void LicenseInfo::CallActivationServer (string TX_RX_IDS) {}
void LicenseInfo::QueryLicenseUpdate (bool forceCheck) {}
void LicenseInfo::SignalServerError() {}
void LicenseInfo::NewActivation () {}
void LicenseInfo::ManualActivation () {}
const std::string LicenseInfo::GetLicenseURL() { return ""; }
bool LicenseInfo::UnknownStatus() { return false; }
void LicenseLog (const char* format, ...) {}
然后修改 Editor\Src\LicenseInfo.h
,把 LicenseInfo::Flag
这个方法的实现修改如下:
static bool Flag (LicenseInfoFlag f)
{
return true;
}
这样就会默认所有功能都是开启的,也不会检查本地是否有 license
文件了。
如同解题的方法永远不止一个,我们也有很多其他的方法来解决这个问题。比如在 WinMain
函数里把 LicenseInfo
的相关调用注释掉,但是因为还有很多其他地方使用 LicenseInfo
,所以不如把 LicenseInfo
的实现改掉更快。也可以通过离线激活的方式,从 Unity
官网通过上传 Unity_v4.3.1f1.alf
再下载一个 Unity_v4.x.ulf
导入编辑器来激活。但是我在使用这个方式的时候遇到从 ulf
文件中读取 StopDate
时崩溃,需要修改 Editor\Src\LicenseManager.cpp
的 1709 行为 std::string stopString = "2112-01-27T08:00:00";//GetDate("StopDate", doc);
来绕过。
0x05 编译
做了这么久的准备,总算可以编译代码了。其实这一步最简单!
在 Unity
源码路径下运行:
perl build.pl build --target=WindowsEditor
当然你也可以在 target
中加入 WindowsStandalonePlayer
等其他的平台,记得用逗号隔开就好。
等待大约10分钟。
等待时间插播一个其他话题。Unity
的代码量其实并不大,Runtime
部分30w行代码,Editor
代码14w行。相对于 Unreal 4
的150+80w代码已经相形见绌。Lumberyard
的代码因为分布较散,不好统计,但印象中比 Unreal
更多,毕竟塞进来了整个 CryENGINE
,而且 AzCore AzFramework LmbrCentral
也不小,更何况还有繁杂的各类 Gems
。
Unity:
λ cloc Runtime\
1842 text files.
1841 unique files.
219 files ignored.
https://github.com/AlDanial/cloc v 1.66 T=6.72 s (258.9 files/s, 68280.3 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C++ 708 46572 16649 230438
C/C++ Header 904 21755 10788 110499
C# 105 2117 1365 12547
Assembly 10 545 646 1918
CSS 2 99 13 756
C 2 174 253 713
MSBuild script 4 0 21 375
HLSL 2 42 18 231
DOS Batch 1 26 0 56
Perl 1 6 0 42
-------------------------------------------------------------------------------
SUM: 1739 71336 29753 357575
-------------------------------------------------------------------------------
λ cloc Editor\Src\
602 text files.
601 unique files.
33 files ignored.
https://github.com/AlDanial/cloc v 1.66 T=1.88 s (318.0 files/s, 103003.2 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C++ 304 24339 17044 128097
C/C++ Header 295 5252 2827 16445
-------------------------------------------------------------------------------
SUM: 599 29591 19871 144542
-------------------------------------------------------------------------------
Unreal 4
λ cloc Engine\Source\Runtime\
7644 text files.
7640 unique files.
1108 files ignored.
https://github.com/AlDanial/cloc v 1.66 T=51.05 s (148.4 files/s, 43955.9 lines/s)
-----------------------------------------------------------------------------------
Language files blank comment code
-----------------------------------------------------------------------------------
C++ 3044 216871 110840 1103798
C/C++ Header 4366 144631 208261 452020
C# 160 850 316 5195
XML 2 58 10 331
JavaScript 1 58 64 261
Windows Resource File 2 37 46 129
-----------------------------------------------------------------------------------
SUM: 7575 362505 319537 1561734
-----------------------------------------------------------------------------------
λ cloc Engine\Source\Editor\
4650 text files.
4648 unique files.
480 files ignored.
https://github.com/AlDanial/cloc v 1.66 T=31.38 s (148.0 files/s, 39353.6 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C++ 2038 143587 65619 752908
C/C++ Header 2498 57829 69772 136169
C# 105 951 812 7208
MSBuild script 2 0 14 109
-------------------------------------------------------------------------------
SUM: 4643 202367 136217 896394
-------------------------------------------------------------------------------
0x06 最后
编译之后的可执行文件在 build\WindowsEditor\Unity.exe
编译完就可以开心的断点看代码了。其实我在不能断点的情况下靠着强大的 Resharper C++
也阅读了一些代码,在这里也安利一下,如果还在用 Visual Assist
的可以考虑换这个工具,静态分析更加强大。
以后有时间再把看到的 Unity
中的一些代码总结到这里,给自己挖个坑,想填了再来填。(P.S. Lumberyard
的坑还没填的)