UE4游戏Package记录(Android)
01 Aug 2015 UE4 Package
Android的打包比Windows下要稍微麻烦一些,因为使用的编译器不同导致的问题也就多了起来。
当前使用的UE4版本为4.10.1。
基本步骤
UE4打包Android的教程官方是有提供的,可以看这里。
下面只是简单的做一下总结的感觉,首先需要进行的是相关环境的安装。android sdk、ndk以及很多其他的东西,直接使用引擎自带的安装器就可以一次性搞定了。安装器在引擎如下的目录中可以找到
[ENGINE INSTALL LOCATION]\Engine\Extras\Android\CodeWorksforAndroid-1R6u1-windows.exe
开发必备环境的设定可以看[这里]。
根据网络情况的不同,安装时间可能会比较长。
安装好之后其实就可以进行Android打包了,如果之前进行过Windows打包的话,基本不需要额外的设置。
插件问题
Android打包过程中很容易遇到的问题是插件上的,例如,如果在项目中有使用FMod的话,就需要进行一些额外的工作。
首先我们需要的是排查工具,在Android的SDK中有提供可以用于错误排查的工具。路径位于sdk的tools目录中,使用monitor.bat即可。
为了使用方便,在LogCat中添加新的过滤器
就可以方便的对UE4的输出记录进行排查了。
如果在项目中有使用FMod的话,游戏在Android上是无法直接打开的,查看输出记录可以看到
FMod的库文件没有被正确的找到,其实这是由于没有正确的按照FMod官方的配置说明进行配置导致的。在FMod的文档中其实是有说明的,不过没有到打包这一步的时候也并不需要进行配置。
当前FMod的Android打包需要对UE4的打包设置进行修改才行,首先,我们需要去GitHub上下载源码版的引擎。
并对UEDeployAndroid.cs进行修改,在CopyPluginLibs函数的末尾,添加如下的代码:
Console.WriteLine("Plugin Deployment");
List<string> PluginLibraryReferences = new List<string>();
foreach (PluginInfo Plugin in Plugins.ReadAvailablePlugins(UnrealBuildTool.GetUProjectFile()))
{
string AndroidDirectory = Path.Combine(Plugin.Directory, "Binaries/Android");
string DeployFile = Path.Combine(AndroidDirectory, "deploy.txt");
if (File.Exists(DeployFile))
{
Console.WriteLine("Using Plugin Deployment file '{0}'", DeployFile);
string DestLibraryDirectory = Path.Combine(UE4BuildPath, "libs/armeabi-v7a");
string DestJarDirectory = Path.Combine(UE4BuildPath, "libs");
foreach (string Name in File.ReadAllLines(DeployFile))
{
Console.WriteLine("Have file entry '{0}'", Name);
string PluginFileExt = Path.GetExtension(Name);
if (PluginFileExt == ".so")
{
string SourceFile = Path.Combine(AndroidDirectory, Name);
string DestFile = Path.Combine(DestLibraryDirectory, Name);
Console.WriteLine("Copying plugin .so file '{0}' to '{1}'", SourceFile, DestFile);
if (File.Exists(DestFile))
{
File.Delete(DestFile);
}
File.Copy(SourceFile, DestFile);
// Also remember it for GameActivity
PluginLibraryReferences.Add(Name);
}
else if (PluginFileExt == ".jar")
{
string SourceFile = Path.Combine(AndroidDirectory, Name);
string DestFile = Path.Combine(DestJarDirectory, Name);
Console.WriteLine("Copying plugin .jar file '{0}' to '{1}'", SourceFile, DestFile);
if (File.Exists(DestFile))
{
File.Delete(DestFile);
}
File.Copy(SourceFile, DestFile);
}
}
}
}
// Enter all .so references into GameActivity java file
if (PluginLibraryReferences.Count != 0)
{
Console.WriteLine("Adding Plugin Deployment library references");
String GameActivityFileName = Path.Combine(UE4BuildPath, "src/com/epicgames/ue4/GameActivity.java");
List<string> ActivityContents = new List<string>(File.ReadAllLines(GameActivityFileName));
int LoadLibraryIndex = -1;
for (int i = 1; i < ActivityContents.Count; ++i)
{
if (ActivityContents<i>.Contains("System.loadLibrary"))
{
LoadLibraryIndex = i;
break;
}
}
if (LoadLibraryIndex != -1)
{
// Insert in reverse order
PluginLibraryReferences.Reverse();
foreach (string Reference in PluginLibraryReferences)
{
Console.WriteLine("Adding library reference {0} at line {1}", Reference, LoadLibraryIndex);
string ShortName = Path.GetFileNameWithoutExtension(Reference);
if (ShortName.StartsWith("lib")) // Without the lib prefix
{
ShortName = ShortName.Substring(3);
}
ActivityContents.Insert(LoadLibraryIndex, String.Format("\t\tSystem.loadLibrary(\"{0}\");", ShortName));
}
}
File.WriteAllLines(GameActivityFileName, ActivityContents.ToArray());
}
// PLUGIN DEPLOYMENT END
这样一来就可以正常的进行运行工作了,不过由于使用了源码版,有时候编译时间就会比较长了。所以建议在项目打包的时候再进行设置。
FMod还有一些其他需要注意的打包事项,例如Bank文件目录等的设定,由于没有使用到那些功能所以没有进行尝试,详情可参照[FMod官方文档]。
目录访问
当前UE4在Android下默认是没有提供访问整个设备的文件的接口的,但是如果是音乐游戏之类的游戏的话,就会需要用到这样的功能。
在AndroidFile.cpp中,我们可以看到,所有的函数都有提供AllowLocal的参数,但是FAndroidPlatformFile在进行IPhysicalPlatformFile的接口实现时使用的却全部是默认的False。AllowLocal参数最终是传递给PathToAndroidPaths这个函数的,因此,直接在该函数中添加
AllowLocal = true;
强制打开本地路径访问即可。同时,这个文件中有开放两个在调试文件访问时比较实用的宏,有需要的时候可以打开
#define LOG_ANDROID_FILE 1
#define LOG_ANDROID_FILE_MANIFEST 1
另外需要注意的是,FPaths提供的一些函数在Android下并不能很好的运行,经常返回不符合预期的结果。
目前观测到的有
FPaths::ConvertRelativePathToFull需要使用IAndroidPlatformFile::GetPlatformPhysical().FileRootPath进行代替
FPaths::GetPath会对根目录返回空字符串
FPaths::IsDrive会对所有的一级目录返回True
使用的时候需要千万注意。
功能限制
UE4在移动模式下是有很多功能限制的,如果游戏是面向移动平台的话,最好在添加新功能的时候使用移动平台模拟进行测试,否则到最后就可能真的积重难返了。
目前遇到的限制有:
APEX的破碎物体无法作用
部分粒子特效无法显示
UE4对移动设备的兼容性也是需要在事先进行调查的,官方的说明在这里。
引擎自带的示例项目在没有安装第三方插件的情况下,是可以直接通过的,用来测试环境的配置是否正确非常方便。官方的TPS示例的打包结果如下:
总体而言UE4的移动端表现还是非常不错的。