3 开发注意事项¶
3.2 Android Manifest文件¶
- 添加必要的配置,默认已添加,若使用自定义AM文件需确保添加以下配置。
<meta-data android:name=”pvr.app.type” android:value=”vr” />
3.3 已知问题说明¶
- 不支持场景编辑器中的“虚拟现实预览”。

图3.1 不支持虚拟现实预览
- 勾选HDR选项,可能会出现显示模糊,转头卡顿,花屏等一系列显示异常问题,建议取消HDR勾选:

图3.2 取消勾选Mobile HDR
- Git工程管理中 .gitignore 文件建议删除 .so 、.jar 项

图3.3 删除该.so标签
SDK中含有.so和.jar文件,开发者在使用git或者其他软件进行工程维护的时候,请勿在 ignore 文件中忽略 .so 和 .jar 文件,建议删除 .so 、.jar 项
- UE4.24版本进行限帧,会出现时间流速异常:

图3.4 UE限帧界面
在4.24版本,如果勾选上图两个复选框进行限帧或者在C++代码中使用上述两种方法进行限帧,会导致游戏内时间流速异常的问题,属于4.24版本的问题,建议开发者在该版本内请勿使用上述两种方式进行限帧操作,或者选择使用其他引擎版本。
- 4.24以及之后版本已经废弃了OpenGLES2,所以建议开发者在使用4.24以及之后版本进行开发时,不要选择使用OpenGLES2进行打包,不然可能会出现一些问题。
- 4.24以及之后版本,新建场景中引擎自带的TimeOfDay场景,该场景是为展示PC端的渲染能力,不建议在移动端使用。
- 建议删除Project Settings-Android-Advanced APK Packaging下Daydream和Package for Oculus Mobile devices相关设置如下图:

图3.5 删除相关设置
- 4.26版本非Shipping模式下,添加Landscape并修改其number of component属性,会引起崩溃,属于已知问题。
- 暂不支持调制阴影,某些UE模板会默认启用,将导致阴影异常,请在定向光源的灯光属性下禁用Cast Modulated Shadows。

图3.6 禁用Directional Light Cast Modulated Shadows
- 在使用StereoLayer时,使用蓝图代码控制相机旋转会导致StereoLayer同步旋转
- 在基于Unreal 4.25使用Vulkan时(源码版本),切换关卡概率性出现崩溃,可以通过修改引擎源码规避。请将文件EngineSourceRuntimeVulkanRHIPrivateVulkanTexture.cpp的方法注释掉:
if (!CreateInfo.BulkData)
{
//if(-1 != GVulkanOverrideInitialTextureLayout && 0 == (UEFlags & (TexCreate_RenderTargetable | TexCreate_DepthStencilTargetable)))
//{
// TransitionInitialImageLayout(Device, Surface.Image, (VkImageLayout)GVulkanOverrideInitialTextureLayout, Surface.GetFullAspectMask());
//}
//else
//{
// // No initial data, so undefined
// InsertInitialImageLayout(Device, Surface.Image, VK_IMAGE_LAYOUT_UNDEFINED);
//}
InsertInitialImageLayout(Device, Surface.Image, VK_IMAGE_LAYOUT_UNDEFINED);
return;
}
- UE4.27的Vulkan下添加Splash切换关卡存在概率性崩溃的问题,若需要使用Splash功能请修改引擎源码。
//..\Engine\Source\Runtime\VulkanRHI\Private\VulkanBarriers.cpp
void FVulkanImageLayout::Set(VkImageLayout Layout, const VkImageSubresourceRange& SubresourceRange)
{
//...省略,上面代码保留
for (uint32 Layer = FirstLayer; Layer < FirstLayer + LayerCount; ++Layer)
{
for (uint32 Mip = FirstMip; Mip < FirstMip + MipCount; ++Mip)
{
if ((Layer * NumMips + Mip)<(uint32)SubresLayouts.Num())
{
SubresLayouts[Layer * NumMips + Mip] = Layout;
}
else
{
SubresLayouts.Add(Layout);
}
}
}
//...省略,下面代码保留
}
//..\Engine\Source\Runtime\VulkanRHI\Private\VulkanBarriers.h
VkImageLayout FindLayoutChecked(VkImage Image) const
{
/*const FVulkanImageLayout& Layout = Layouts.FindChecked(Image);*/
const auto* Pair = Layouts.Find(Image);
if (Pair == nullptr)
{
return VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED;
}
else
{
const FVulkanImageLayout& Layout = *Pair;
check(Layout.AreAllSubresourcesSameLayout());
return Layout.MainLayout;
}
}