故障排除

本部分介绍了使用 Unity 时可能出现的常见问题。按照平台分别在下方列出。

平台故障排除

Desktop

OSX 10.6.4 中的 Geforce 7300GT

  • OSX10.6.4 中的 Geforce 7300 不能正确显示材质,延迟渲染被禁用。这是因为视频卡驱动程序存在错误。

在 Windows x64 上,当脚本抛出 NullReferenceException 时,Unity 崩溃。

脚本编辑

有没有办法让 MonoDevelop 不显示欢迎页面?

  • 有。在 MonoDevelop 首选项跳转到视觉风格 (Visual Style) 部分,取消选中“启动时加载欢迎页面 (Load welcome page on startup)"。

为什么我已经选择 Visual Studio 作为脚本编辑器,脚本依然在 MonoDevelop 中打开?

  • 这主要出现在 VS 报告无法打开您的脚本时。这一现象最常见的原因是外部插件(例如 Resharper)在启动时弹出对话框,请求用户输入 - 这将导致 VS 报告无法打开脚本。

图形

低帧率和/或视觉瑕疵。

  • 可能是由于视频卡驱动程序没有更新至最新版本。请确保已经从视频卡厂商获得最新的官方驱动 。

阴影

我完全看不到阴影!

  • 阴影是 Unity Pro 的特有功能,因此,没有 Unity Pro 自然也无法取得阴影。当然,简单的阴影方法依旧可用,如使用投影仪 (Projector)
  • 阴影也需要某些图形硬件支持,查阅质量设置 (Quality Settings) 中是否完全禁用了阴影。
  • 目前 Android 和 iOS 移动平台不支持阴影。

某些对象不投射或接受阴影

对象的渲染必须启用接受阴影 (Receive Shadows) 才能在物体表面渲染阴影。同时,对象必须启用投射阴影 (Cast Shadows) 以便在其他对象上投射阴影(默认为启用这两种功能)。

只有不透明的对象才能投射和接受阴影。这意味着使用内置透明或颗粒阴影的对象将不会投射阴影。大部分情况下,可以使用透明抠图 (Transparent Cutout) 着色器处理围栏、植被等对象。如使用自定义编写的几何渲染队列。使用顶点光照 (VertexLit) 着色器的对象不接受阴影,但可以投射阴影。

只有像素发光 (Pixel lights) 能投射阴影。如果需要确定无论在场景中使用多少种其他灯光,灯光始终投射阴影,可以将其设置为 Force Pixel 渲染模式(请参阅灯光 (Light) 参考页)。

iOS

iOS 设备故障排除

对于 iOS 来说,在某些情况下,游戏可以在 Unity 编辑器中完美运行,但在实际设备上却无法运行甚至不能启动。这些问题通常是由代码或内容质量引起的。本部分将介绍最常见的几种情况。

游戏停止响应一段时间后,Xcode 状态栏显示"中断 (interrupt)"。

导致这一现象有多种原因,主要原因包括:

  1. 脚本错误,如使用未初始化的变量等。
  2. 使用第三方 Thumb 编译本地库。这种库在 iOS SDK 连接器中触发已知问题并可能产生随机崩溃。
  3. 使用具有值类型的泛型类型作为参数(例如, List<int>、List<SomeStruct>、List<SomeEnum> 等)用于序列化的脚本属性。
  4. 在启用当托管代码剥离 (managed code stripping) 时,使用反射。
  5. 本机插件接口出错(托管代码的方法签名不匹配本机代码的函数签名)。

XCode 调试控制台的信息有助于检测此类故障(Xcode 菜单:查看 (View) > 调试区 (Debug Area) > 激活控制台 (Activate Console))。

Xcode 控制台显示 "Program received signal: “SIGBUS” 或 EXC_BAD_ACCESS 错误

此消息通常在应用程序收到 NullReferenceException 时出现在 iOS 设备。有两种方式找出发生错误的位置:

托管堆栈跟踪:

从 3.4 版开始 Unity 包含基于软件的空引用 (NullReferenceException) 处理。AOT 编译器包含每次访问对象的一种方法或变量时,快速查看所有空引用。这一功能影响了脚本的性能,这也是为什么只在开发构建中启用该功能的原因(在基础版许可证书中,用户可以在构建设置 (Build Setting) 对话框中打开“开发构建 (development build)” 选项,但 iOS 专业版许可证书用户需要另外启用“脚本调试 (script debugging)” 选项)。 如果上述内容都正确,而错误实际出现在 .NET 代码中,那么您将不会再看到 EXC_BAD_ACCESS, 相反,.NET 异常文本将要 Xcode 控制台中显示(或者代码在 "catch" 语句处理)。典型的输出可能是:

Unhandled Exception: System.NullReferenceException: A null value was found where an object instance was required.
  at DayController+$handleTimeOfDay$121+$.MoveNext () [0x0035a] in DayController.js:122 

这表明错误发生在 DayController 类的 handleTimeOfDay 方法中,是一个协同程序。 此外,如果它是脚本代码,就会提示出错误所在的行号(例如:"DayController.js:122 ")。问题语句可能如下:

 Instantiate(_imgwww.assetBundle.mainAsset);

如果脚本在没有首先检查下载是否正确的前提下访问资源包,可能发生这种错误。

本机堆栈跟踪:

本机堆栈跟踪对于故障调查是一项更为强大的工具,但是,使用它需要一些专业技术。通常在发生此类本机(硬件内存访问)故障之后通常不能继续。要进行本机堆栈跟踪需要在 Xcode 调试控制台输入 bt all。仔细检查显示的堆栈跟踪,它们可能包括了错误来源信息。您可能会看到这样的信息:

...
Thread 1 (thread 11523): 
#0 0x006267d0 in m_OptionsMenu_Start () 
#1 0x002e4160 in wrapper_runtime_invoke_object_runtime_invoke_void__this___object_intptr_intptr_intptr () 
#2 0x00a1dd64 in mono_jit_runtime_invoke (method=0x18b63bc, obj=0x5d10cb0, params=0x0, exc=0x2fffdd34) at /Users/mantasp/work/unity/unity-mono/External/Mono/mono/mono/mini/mini.c:4487
#3 0x0088481c in MonoBehaviour::InvokeMethodOrCoroutineChecked ()
...

首先应该找到 "Thread 1" 的堆栈跟踪,这是主线程。堆栈跟踪的第一行将指向发生错误的位置。在这个示例中,跟踪显示 NullReferenceException 发生在 "OptionsMenu" 脚本中的 "Start" 方法。仔细查看这一方法实现便可发现故障的原因。很明显,NullReferenceExceptions 发生在 Start 方法,对初始化顺序做出了错误的假设。 在某些情况下,调试控制台中只可以看到一小部分堆栈跟踪:

Thread 1 (thread 11523): 
#0 0x0062564c in start ()

这表明在应用程序发布期间,已经去除本地符号。通过以下步骤可获得完整的堆栈跟踪信息:

  • 在设备上删除应用程序。
  • 清除所有目标。
  • 构建并运行。
  • 再次获得如上所述的堆栈跟踪信息。

将外部库链接到 Unity iOS 应用程序时,EXC_BAD_ACCESS 开始发生。

这通常在外部库由ARM Thumb 指令集编译时发生。目前这种库不兼容 Unity。不用 Thumb 指令重新编译库,即可轻松解决这一问题。库的 Xcode 工程重新编译可使用以下步骤:

  • 在 Xcode, 从菜单中选择 "查看 (View)" > "导航器 (Navigators)" > "显示工程导航器 (Show Project Navigator)"
  • 选择 "Unity-iPhone" 工程,激活"构建设置 (Build Settings)" 选项卡
  • 在搜索字段输入:"Other C Flags"
  • 在此处添加 -mno-thumb 标志并重新构建库。

如果该库的源不可用,应联络提供 商,取得库的 non-thumb 版本。

Xcode 控制台显示 "WARNING -> applicationDidReceiveMemoryWarning()",应用程序随即崩溃

(有时会看到 Program received signal: