融合
请参阅常见融合问题。
崩溃现象
问:我们的游戏发生以下错误后会出现永久崩溃现象:OutOfMemory(内存溢出)和 DriverInternalError(驱动器内部错误)。我们现在使用的是内存为 768MB 的 NVidia 视频卡。还有其他问题吗?
答 :对于 Windows…
在您的根驱动器(通常是 C: 盘)的根目录中 放置一个名为 Boot.ini 的文件。如果您还没有取消隐藏 Windows 系统文件,那么您将需要取消隐藏才能打开它。如果您在您的 Boot.ini 文件中设置了 /3Gb,那么尝试将其去除。
默认情况下,任何进程只有 2Gb:1Gb 供堆使用,1Gb 供栈使用(从 0x00000000 到 0x7FFFFFFF)。Kernel 保留了从 0x80000000 到 0xFFFFFFFF 的 2Gb。
添加 /3Gb 到您的 boot.ini 文件中将堆扩展为 2Gb(同时减少 kernel 的虚拟内存)。视频卡设置为 768Mb 会可以将您的虚拟内存减少为 1,280Mb(实际上要比 1,280Mb 还少一些,因为您的系统有多个驱动器,所以可以有一个供视频卡使用)。即使您有 8Gb 的物理内存。
如果您是在 Vista 上运行,这里也有供内存溢出崩溃现象使用的 Microsoft 修补程序:http://support.microsoft.com/kb/940105。
NVidia 会发现这个问题并相应地更新驱动器。请参阅最小指标页面了解最新的要求。
虚幻脚本
问:为什么会将我的变量导出到一个与我所声明的大小写不同的 .h 文件?
答 :假设是以下变量声明:
class TestA extends Actor;
native(Test);
var bool Foo;
和…
class TestB extends Actor;
native(Test);
var bool FOO;
将属性名存储为 FName 值,存储到区分大小写字符串的表格的索引中。使用相同的 FName 值存储属性 Foo
和 FOO
。引擎将使用它遇到的第一个大写字母(例如, Foo
)。会将两个属性都导出到 native 类头文件中,例如 Foo
。
最简单的解决方案是将所有出错变量重新命名为与所使用的变量大小写一致,例如,Foo
。
要在整个系统强制执行大小写,请将该字符串添加到 UnNames.h。
请参阅大小写区分 FNames 和脚本 (ue3bugs) 邮件列表主题了解更多信息。
引用:Compiling Native Classes(编译 Native 类)
问:为什么这一行代码在 defaultproperties(默认属性)中不能正常工作。
Thing = (X = 1.0, Y = 1.0)
答 :该 defaultproperties(默认属性)解析代码十分模糊。一般情况,您应该避免在 defaultproperties(默认属性)中使用空格。
问:我有包含一个第一项为枚举值的 native 结构,而我将会得到杜撰出来的值或崩溃现象。
答 :在这种情况下打包有一个已知问题,您应该避免将枚举值放在 native 结构中的第一项。
问:脚本为什么总是在一个 Perforce 中的全新同步后过期?
答 :如果您的标题脚本包(.U 文件)会在仓库内的 Development(开发)分支 前* 显示,而没有直接参与代码开发的美术人员及其他人员 *还没有 遮住(过滤掉) Perforce 中的 Development(开发)分支,然后创建一个情况,在其中将脚本包(.U 文件)从仓库中复制到 UnrealScript(.uc 文件)前的本地机器。因为本地 UnrealScript(.uc 文件)与脚本包(.U 文件)相比更新,所以该游戏会认为该脚本包(.U 文件)过期并提示要编译它们。不需要那些没有直接参与代码开发的人员(例如,非程序员)同步到“Development(开发)”分支。这些用户应该在 Perforce clientspec 中遮住(过滤)//depot/UnrealEngine3/Development/…。
问:重新编译脚本时,我会收到错误信息“未解析类的无效引用”。
答 :这意味着您要尝试引用稍后在 ..Engine.ini 文件的编辑包列表里显示的包中的一个类。
问:我有一个(非组件)对象类 FooClass 并添加一个对 Actor 类中的其中一个类的引用,同时使用 BEGIN OBJECT 语法在其 defaultproperties(默认属性)中创建一个对象。但是当我将该 Actor 放置在关卡中时,指针会指代 FooClass 的默认对象,而不是一个新的实例。
答 :这个问题是这个对象没有进行‘深层复制’ – 它像您会用于贴图或网格物体的一样是浅层引用。所以当您放置 Actor 时,它将会使该引用指向 .u 文件中的子对象,而不是创建一个新的实例。c 将关键字 ‘instanced’ 添加到属性中应该可以解决这个问题(与以前的语法 ‘editinline export’ 不完全一样)。那么您的 Actor 类应该会有这样一行:
var() instanced FooClass MyFoo;
问:我在结构属性内部有一个 editinline export 属性,而且在我重复或复制粘贴这个 actor 时没有对它进行深层复制。
答 :不幸的是,现在它不支持这项功能,假设 .t3d 导出器(在复制/粘贴和克隆过程中使用的导出器)会处理与深层复制的导出对象相结合的导出结构。
问:我可以使用 BEGIN OBJECT 语法在另一个 Actor 内部创建 Actor 吗?
答 :不可以。
问:我可以安全更改脚本序列化结构的数组内部吗?
答 :不可以,更改脚本序列化的结构的数组类型是不安全的。常见的解决方法是重新命名这个变量。
问:Kistmet SequenceAction 类看上去还没使用处理器功能。为什么?
答 :这些类有一个供指定操作使用的处理器功能名称( HandlerName
,在 SequenceAction.uc 中进行定义)。如果没有设置这个名称,那么这个类名称通常会自动生成一个(请参阅 UnSequence.cpp 中的 USequenceAction::Activated()
和 GetHandlerName
)。例如,名为 SeqAct_DoSomething
的类会将它的 HandlerName
设置为 OnDoSomething
。
问:我可以声明布尔型的动态数组吗?
答 :不可以。
类
问:我已经添加了一个新的 native 类,但是现在我收到了一个连接警告,内容为‘未解析的外部符号’。
答 :当我添加一个新的 native 类时,您需要确保您在 .cpp 文件某处添加了一个对应的 IMPLEMENT_CLASS 。
问:我刚刚创建了一个新的 C++ 专用(‘内部’)UObject 类,但是在我迭代所有 UClass 对象后,我无法找到它。
答 :这是在创建诸如 UFactory 类型时的常见问题。您必须将新的类添加到 AUTO_INITIALIZE_REGISTRANTS_… 块中的 ..Classes.h 文件,然后在引擎发现这个类之前编译 C++。这之后,通常会将其添加到生成该头文件的这部分。
问:我认为在 C++ 和 UnrealScript 类定义中存在匹配不当的情况 – 有办法可以检查它吗?
答 :打开 UnBuild.h 并将以下行:
#ifndef CHECK_NATIVE_CLASS_SIZES
#define CHECK_NATIVE_CLASS_SIZES 0
#endif
改变为:
#define CHECK_NATIVE_CLASS_SIZES 1
这样它应该就会在您启动程序时自动为您检查这里。
问:我可以在类的 cpptext 部分中添加一个新的变量吗?
答 :不可以! UnrealScript 和类的 C++ 定义必须精确匹配,而在 C++ 部分中添加变量会破坏精确匹配。您应该将其添加到脚本类,然后使其自动生成包含新变量的 C++ 头文件。
问:我只是向 native 类添加了一个新的脚本变量,编译脚本并导出头文件后,我这边发生了崩溃现象,我改怎么办?
答 :此时,脚本会认为您的类比 C++ 大,所以您必须使用新导出的头文件重新编译 C++ 以便修复匹配不当的情况。 然后您将必须再次重新编译脚本,因为它第一次没有完成编译,但是它不会重新导出头文件。
C++
问:我如何将对象实例放置到 TArray 中?
答 :如下所示:
UObject* SomeUObjectDerivedClass = new(SomeArray) SomeUObjectDerivedClass();
编译
问:我已经将项目添加到依靠我的自定义游戏项目的虚幻引擎 3 解决方案,而且我会收到有关预编译的头文件 (.pch)
答 :请参阅创建自定义项目页面如何创建依赖项目。
调试
问:我如何浏览调试器中的 FStrings、TArrays 或 FNames?
答 :请参阅该页面调试工具以及该主题https://udn.epicgames.com/lists/showpost.php?list=unprog3&id=6072。
问:使用 UDE 进行调试时,我收到诸如“已接收对 UpdateStack 的调用,但是栈不同步”的错误信息。
答 :这通常表示您的某些 .u 文件是在没有使用调试信息的情况下进行编译的。
编辑器
问:我如何运行编辑器? 我只能看到 MyGame.exe。
答 :它是 MyGame.exe 的一部分。您只需在末尾添加 ‘editor’ 选项,如下所示:
mygame editor
问:我如何将资源从一个包移至另一个包?
答 :在通用浏览器中右击这个包,然后选择 Rename(重新命名)。然后将这个新的 包/组 输入到您想要将其移至的地方。移动资源时会在它原来的位置留下‘重定向器’。这样,那些目前还没有加载但是引用该资源的包会知道到哪里能够找到它的新位置。
问:当我在浏览器中重新命名一个对象时,我不可以使用与原来的对象相同的名称创建一个新的对象。
答 :当您重新命名一个对象时,它会创建一个可以从原位置指向新位置的 ‘Redirector’ 对象。这样任何现有的内容都可以找到资源。但是您不可以使 Redirector 与资源的名称相同,这就是为什么不允许创建名称相同的对象的原因。您可以通过在 rename(重新命名)上勾选‘不创建 Redirector’框避免这个问题,但是您应该只可以在您确定没有内容引用该对象的情况下进行这项操作。另一种修复它的方法是在常规的基础上运行 ‘fixupredirects’ 命令行开关。它会尽可能多地进行处理(所以它不要求勾选每个包中的每一项)。此外,如果没有内容引用它,它会清理 __Trashcan 目录中的包。
问:我在关卡编辑器或 kismet 中复制和粘贴某个对象时 – 它应该会将新对象放置在以前对象的位置,然后移动新对象。
答 :当您在编辑器中粘贴时,它会为正在进行创建的新对象保留名称。这样,如果您粘贴的是 2 个通过名称互相引用的对象,那么粘贴后情况仍然如此。但是因为每个对象必须有一个唯一的名称,所以需要重新命名现有对象为新对象让路。这样,如果您所复制的对象名为 Foo。当您粘贴它时,会将新对象命名为 Foo,并将现有的对象重新命名为诸如 Foo_1 这样的名称。
问:我如何在一个位于关卡中的 Prefab(预制)内部选择单独的 Actors?
答 :在主要编辑器工具栏上,有一个标有 ‘P’ 图标可以启动‘prefab lock(预制锁定)’的按钮。 启用预制锁定(默认情况)时,无法选择预制的单独元素。更确切地说,选择一个单独的预制 actor 就会选择整个预制。
问:可以将反向缩放比例应用到一个对象以便可以横穿某个轴‘翻转’它吗?
答 :可以,引擎可以全面支持这项操作。
问:BSP“光照贴图分辨率属性框”中的值代表什么?
答 :它代表每光照贴图贴图像素的虚幻单位数。
问:在不需要键入名称的情况下,我如何才能将一个 Actor 设置为指向其他 Actor?
答 :您只需使用顶部的挂锁按钮‘锁定’这个属性窗口。然后在关卡中选择 Actor,并使用属性旁边的绿色箭头指定它。
问:在 AnimSet(动画集)编辑器中,在 AnimSequence 选项卡下只可以对 AnimationCompressionAlgorithm 进行一次设置。
答 :在 AnimSequence 选项卡中可见的属性并不表示可以直接进行编辑。恰恰相反,修改序列的压缩设置的正确方法是通过AnimationCompressionDialog(动画压缩对话框)。
渲染
*问:使用特定法线贴图时,我的游戏中会显示黑色正方体。
答 :当您在屏幕上看到黑色正方体时,那是由于一些有问题的数据扰乱了后期特效系统造成的。这种现象最常见的原因是在您的法线贴图中有 0 像素。这会使像素着色器中被 0 划分,最终出现这样的问题。确保您的法线贴图其中没有任何灰色区域。
问:我如何更改每个实例中骨架或静态网格物体的材质呢?
答 :您想要在 MeshComponent(网格物体组件)中修改 Materials(材质)数组中对应的插槽。您在 StaticMesh Editor(静态网格物体)或 AnimSet Viewer(动画集查看器)中设置的材质都是“默认值”,但是 Materials(材质)数组允许您在每个实例中覆盖这些默认值。
问:除非在无光照的情况下,否则半透明材质不会显示。 为什么?
答 :自从变更列表 130935(第一个 Gemini QA 版本)开始已经删除了对带光照的半透明物体的支持。 在这个版本之前,使用的是深层剥离对其进行渲染,而且与 UE3 的其他渲染功能正交:像素级光照和阴影、雾、光源函数、景深等等。但是,它的消耗太高以致于除了最简单的场景外的任何地方都不实际。 与其继续在 Gemini 中一个不切实际的代码路径,我们倒不如决定通过忽略带光照半透明物体材质简化/优化不透明光照代码路径。 我们计划试验支持可以不使用深度剥离在一个单独的渲染中带光照半透明物体的有限案例,但是还没有安排计划。
问:我放置了一个 decal(贴花),但是它没有在编辑器或游戏中显示。 我缺少什么步骤吗?
答 :将视口设置为‘带光照’视图模式(如果没有光照贴花不会显示)。 请确保贴花在与接收者相同的关卡中(或将其复制到每个关卡中以防需要映在多个关卡中的接收者)。 请确保 bAceeptsDecals 在接收的网格物体组件上的值为 TRUE(真)。 并检查贴花是否具有合适的 bProjectsOnBSP/StaticMeshes/etc 雾设置。 此外,请确保贴花在其贴花过滤器中没有任何内容。
问:模块化的阴影会遮住自发光材质,有什么解决方法吗?
答 :这是模块化阴影的局限性。 请参阅模块化阴影了解更多详细信息。
问:我已经认定动态阴影是造成我的游戏中性能瓶颈的主要原因,我该从什么地方开始?
答 :关卡优化指南是开始的最合适地方。 此外,请务必查看[[ShadowingReference][ShadowingReference]阴影引用]、模块化的阴影、光照环境以及阴影缓冲过滤选项。
问:为什么创建静态网格物体的光照贴图后 Normal(法线)阴影没有投射在它们上面?
答 :这是因为 Normal(法线)阴影的局限性。 考虑使用模块化阴影替换,这种方法会投射在所有几何体上。
问:模块化阴影会投射整个几何体。 我怎么才能解决这个问题?
答 :请参阅光照环境。
问:这里提供有关在 UE3 中调试着色器的文档说明吗?
答 :请参阅着色器主页。
问:我收到了一个错误的编译着色器,错误信息为“无法绑定非可选的着色器参数 InvMaxTesselationLEvel_Zscale”,这是什么意思?
答 :有时,这会在周围有一个陈旧的临时着色器时发生。 进入 引擎/着色器,并确保没有将文件 Material.usf 和 VertexFactory.usf 标记为只读。 您可能也想要尝试删除这些临时文件。
动画
问:我正在使用 Matinee 在编辑器中制作 Actor 动画,但是在游戏中看上去好像没有任何效果。
答 :首先,检查 Actor 类不是一个‘静态’类。例如,PointLight 是一个静态类,而且无法在运行时进行修改,但是 PointLightMovable 类可以修改。然后,检查 Actor 的 Physics(物理)模式是否是 PHYS_Interpolating,如果不是它将不会按照 Matinee 操作通知它的内容进行操作。
问:我有一个骨架网格物体,其中在网格物体边界盒外部制作某个骨骼的动画。 但是只要边界在视图范围外,其中的对象就不会进行渲染,即使有一些骨骼仍然在视图范围内,
答 :如果您使用 PhAT 为您的网格物体创建一个 PhysicsAsset,并将其指定为 SkeletalMeshComponent,那么它会用该选项更新使用骨骼的碰撞形状的边界盒每一帧。因为这样边界就会更精确,网格物体通常应该正确地描画。
问:我已经在某些骨骼上使用平移导入了一个动画,但是它好像并没有应用于我的骨架。
答 :默认情况下,bAnimRotationOnly 标记在 AnimSet(动画集)属性中进行设置。这会通知引擎在动画数据中获取骨骼的旋转量,而不是从网格物体的参考姿势中的平移量(适用于除根骨骼外的所有骨骼)。这很有用,因为它允许您在不同大小的骨架上播放相同的动画,但是会丢弃动画数据中的所有平移信息。您可以关闭该标志,您将会看到所应用的平移量,或者您可以使用 UseTranslationBoneNames 数组指定应该从动画数据中获取它们的平移量的特定骨骼��
玩家物理
问:我的 pawn 无法始终如一地穿过他本应该适于穿过(使用 PHYS_Walking)的洞。
答 :使用 PHYS_Walking 时,pawns 会通过 MaxStepHeight 走近超出障碍物。 有时,甚至微小的碰撞凹凸(就像可能由 BSP 分割引起的凹凸)也会使 pawn 走近。 为了保证可以持续具有穿越洞的技能,它应该比 pawn 高出 MaxStepHeight + MAXFLOORDIST(在 unphysic.h 中定义)。
碰撞
问:我怎样使玩家可以将每个骨骼与骨架网格物体碰撞?
答 :首先,您需要将 PhysicsAsset 指定为 SkeletalMeshComponent。当前,我们只支持针对于边界盒图元的边界盒扫描曲面测试(供 Unrealplayer(虚幻玩家)物理使用),所以如果您想要阻挡玩家,您必须使用这些选项。然后,您需要勾选一些选项 – 首先,确保 Actor 上的 bCollideActors 和 bBlockActors 勾选的是 true(真),然后 SkeletalMeshComponent 上的 CollideActors、BlockActors 和 BlockNonZeroExtent 也勾选的是 true(真)。
问:为什么 Touch() 脚本事件没有检测到某些碰撞?
答 :Touch() 事件仅适用于没有互相阻挡的 Actors。而互相阻挡的 Actors 会接受 Bump() 事件。
请参阅碰撞参考指南页面深入了解有关碰撞的参考信息。
音频
问:OpenAL 使用什么坐标系统?
答 :请参阅音频系统页面获取相关说明。
统计数据
问:有任何有关各种统计数据 xxx 命令结果的文档说明吗?
答 :统计数据命令输出在统计数据描述中进行说明。
其他
问:虚幻引擎 3 可以在 Windows NT/2000 上运行吗?
答 :我们没有使用 Windows 2000 / NT 上做过测试,不期待可以像支持用户平台一样支持它,所以现在可能会有多个中断区域(以后会有更多引起的未能检测到的中断区域)。
问:我如何才能知道我使用的是哪一个版本的引擎?
答 :您可以在您的 UnrealEngine3\Development\Src\Core\UnObjVer.cpp 版本中查看引擎版本号,然后将其与 Perforce 中的版本历史记录进行对比。然后,查看已经迁入到与您的引擎版本相同的版本中的变更列表,您很有可能具有您已经同步到的变更列表号。
*问:我如何才能找到定位画面以外的窗口?以及我如何才能重置它的位置?
答 :按下 SHIFT+ALT+SPACE+M。后来,您应该可以使用您的箭头键将其推回原位。如果这不起作用,那么尝试在不点击的情况下移动鼠标,然后它应该会显示在屏幕上。
问:我如何才能捕获引擎中的视频?
答 :您可以使用命令行上的 “-dumpmovie -benchmark”,不���这样您将获取不到声音。如果您的回放是确定性的(matinee 序列),那么您可以单独录制它,尽管真实的游戏过程片段录制最好的方式是使用 HDTV 捕获设备/录像机 以及真正功能强大的 SLI 机器。
问:我如何才能在游戏中得到一张屏幕截图?
答 :您可以使用 “shot” 控制台命令将当前的画面截取保存为 .bmp 文件。默认情况下,该命令的快捷键应该是 F9。它会将屏幕截图放入在您的 ..Engine.ini 文件中由 ScreenShotPath 选项指定的目录中,它默认情况下是在您的游戏目录中名为“Screenshots(屏幕截图)”的目录。
问:玩游戏时有调整 Actor 属性的简便方法吗?
答 :这里会提供一些方法。一种方法是在 .uc 文件中将属性指定为 ‘config’。这意味着它们在 .ini 文件中读取它们的值,这样设计师就可以在不需要程序员的情况下调整它们。另一种方法是将变量指定为可编辑属性,然后在游戏过程中使用 ‘editactor’ 控制台命令编辑属性。如果您键入的是:
editactor class=myclass
在游戏中,它会为类 ‘myclass’ 的最近 Actor 弹出一个属性窗口,然后您可以进行调整。使用特殊语法可以将 .uc 文件中的变量添加到属性页面:”var FLOAT EnemyDetectionRadius” 将会出现在属性窗口中,而 “var(Detection) FLOAT EnemyDetectionRadius” 将会出现在“Detection(检测)”组下面的属性窗口中。
最后,现在它使用 RemoteControl(远程控制)窗口可以调整位于关卡中的 actors。
在玩游戏过程中,您随时可以按下 ctrl-esc(或者某些其他案件组合)再次获取鼠标光标,然后单击 RemoteControl(远程控制)中的 Actors 选项卡,并查找您的 actor 实例。在选中的 actor 实例附近会出现一个边界盒。接下来,您可以单击 RemoteControl(远程控制)窗口工具栏中的 Properties(属性)图标编辑 actor 的属性(假设您使用的是上面描述的用于 editactor 命令的特殊语法)。注意:生成的 actors 当前不会出现在 RemoteControl(远程控制)”Actors” 选项卡中,但是对于这些 actors,您仍然可以使用上面的 “editactor”。
请记住,在使用 editactor 命令或 RemoteControl(远程控制)编辑属性时,退出游戏后会丢失其中进行的更改。您需要在退出之前从属性窗口中将它们复制出来(使用 PropertyWindow(属性窗口)工具栏复制更改,然后将它们粘贴到一个安全的目标地址)。
问:我可以将 actor 作为子对象(通过 editinlinenew 或在代码中)吗?
答 :不可以! 这是因为子对象(在脚本代码中)或通过编辑器中的 editinlinenew 属性创建对象都不是使用合适的创建方法创建的。Actors 只 可以通过 Spawn(脚本)和 SpawnActor (C++) 函数进行创建。所有 actors 都需要在世界内部进行创建,而不是在其他对象中创建,同时它们需要一个位置并需要将其添加到各种引擎结构,例如 octree 等等。子对象和 editinlinenew 对象没有在其上面运行任何这样的特殊代码。
融合
请参阅常见融合问题。
崩溃现象
问:我们的游戏发生以下错误后会出现永久崩溃现象:OutOfMemory(内存溢出)和 DriverInternalError(驱动器内部错误)。我们现在使用的是内存为 768MB 的 NVidia 视频卡。还有其他问题吗?
答 :对于 Windows…
在您的根驱动器(通常是 C: 盘)的根目录中 放置一个名为 Boot.ini 的文件。如果您还没有取消隐藏 Windows 系统文件,那么您将需要取消隐藏才能打开它。如果您在您的 Boot.ini 文件中设置了 /3Gb,那么尝试将其去除。
默认情况下,任何进程只有 2Gb:1Gb 供堆使用,1Gb 供栈使用(从 0x00000000 到 0x7FFFFFFF)。Kernel 保留了从 0x80000000 到 0xFFFFFFFF 的 2Gb。
添加 /3Gb 到您的 boot.ini 文件中将堆扩展为 2Gb(同时减少 kernel 的虚拟内存)。视频卡设置为 768Mb 会可以将您的虚拟内存减少为 1,280Mb(实际上要比 1,280Mb 还少一些,因为您的系统有多个驱动器,所以可以有一个供视频卡使用)。即使您有 8Gb 的物理内存。
如果您是在 Vista 上运行,这里也有供内存溢出崩溃现象使用的 Microsoft 修补程序:http://support.microsoft.com/kb/940105。
NVidia 会发现这个问题并相应地更新驱动器。请参阅最小指标页面了解最新的要求。
虚幻脚本
问:为什么会将我的变量导出到一个与我所声明的大小写不同的 .h 文件?
答 :假设是以下变量声明:
class TestA extends Actor;
native(Test);
var bool Foo;
和…
class TestB extends Actor;
native(Test);
var bool FOO;
将属性名存储为 FName 值,存储到区分大小写字符串的表格的索引中。使用相同的 FName 值存储属性 Foo
和 FOO
。引擎将使用它遇到的第一个大写字母(例如, Foo
)。会将两个属性都导出到 native 类头文件中,例如 Foo
。
最简单的解决方案是将所有出错变量重新命名为与所使用的变量大小写一致,例如,Foo
。
要在整个系统强制执行大小写,请将该字符串添加到 UnNames.h。
请参阅大小写区分 FNames 和脚本 (ue3bugs) 邮件列表主题了解更多信息。
引用:Compiling Native Classes(编译 Native 类)
问:为什么这一行代码在 defaultproperties(默认属性)中不能正常工作。
Thing = (X = 1.0, Y = 1.0)
答 :该 defaultproperties(默认属性)解析代码十分模糊。一般情况,您应该避免在 defaultproperties(默认属性)中使用空格。
问:我有包含一个第一项为枚举值的 native 结构,而我将会得到杜撰出来的值或崩溃现象。
答 :在这种情况下打包有一个已知问题,您应该避免将枚举值放在 native 结构中的第一项。
问:脚本为什么总是在一个 Perforce 中的全新同步后过期?
答 :如果您的标题脚本包(.U 文件)会在仓库内的 Development(开发)分支 前* 显示,而没有直接参与代码开发的美术人员及其他人员 *还没有 遮住(过滤掉) Perforce 中的 Development(开发)分支,然后创建一个情况,在其中将脚本包(.U 文件)从仓库中复制到 UnrealScript(.uc 文件)前的本地机器。因为本地 UnrealScript(.uc 文件)与脚本包(.U 文件)相比更新,所以该游戏会认为该脚本包(.U 文件)过期并提示要编译它们。不需要那些没有直接参与代码开发的人员(例如,非程序员)同步到“Development(开发)”分支。这些用户应该在 Perforce clientspec 中遮住(过滤)//depot/UnrealEngine3/Development/…。
问:重新编译脚本时,我会收到错误信息“未解析类的无效引用”。
答 :这意味着您要尝试引用稍后在 ..Engine.ini 文件的编辑包列表里显示的包中的一个类。
问:我有一个(非组件)对象类 FooClass 并添加一个对 Actor 类中的其中一个类的引用,同时使用 BEGIN OBJECT 语法在其 defaultproperties(默认属性)中创建一个对象。但是当我将该 Actor 放置在关卡中时,指针会指代 FooClass 的默认对象,而不是一个新的实例。
答 :这个问题是这个对象没有进行‘深层复制’ – 它像您会用于贴图或网格物体的一样是浅层引用。所以当您放置 Actor 时,它将会使该引用指向 .u 文件中的子对象,而不是创建一个新的实例。c 将关键字 ‘instanced’ 添加到属性中应该可以解决这个问题(与以前的语法 ‘editinline export’ 不完全一样)。那么您的 Actor 类应该会有这样一行:
var() instanced FooClass MyFoo;
问:我在结构属性内部有一个 editinline export 属性,而且在我重复或复制粘贴这个 actor 时没有对它进行深层复制。
答 :不幸的是,现在它不支持这项功能,假设 .t3d 导出器(在复制/粘贴和克隆过程中使用的导出器)会处理与深层复制的导出对象相结合的导出结构。
问:我可以使用 BEGIN OBJECT 语法在另一个 Actor 内部创建 Actor 吗?
答 :不可以。
问:我可以安全更改脚本序列化结构的数组内部吗?
答 :不可以,更改脚本序列化的结构的数组类型是不安全的。常见的解决方法是重新命名这个变量。
问:Kistmet SequenceAction 类看上去还没使用处理器功能。为什么?
答 :这些类有一个供指定操作使用的处理器功能名称( HandlerName
,在 SequenceAction.uc 中进行定义)。如果没有设置这个名称,那么这个类名称通常会自动生成一个(请参阅 UnSequence.cpp 中的 USequenceAction::Activated()
和 GetHandlerName
)。例如,名为 SeqAct_DoSomething
的类会将它的 HandlerName
设置为 OnDoSomething
。
问:我可以声明布尔型的动态数组吗?
答 :不可以。
类
问:我已经添加了一个新的 native 类,但是现在我收到了一个连接警告,内容为‘未解析的外部符号’。
答 :当我添加一个新的 native 类时,您需要确保您在 .cpp 文件某处添加了一个对应的 IMPLEMENT_CLASS 。
问:我刚刚创建了一个新的 C++ 专用(‘内部’)UObject 类,但是在我迭代所有 UClass 对象后,我无法找到它。
答 :这是在创建诸如 UFactory 类型时的常见问题。您必须将新的类添加到 AUTO_INITIALIZE_REGISTRANTS_… 块中的 ..Classes.h 文件,然后在引擎发现这个类之前编译 C++。这之后,通常会将其添加到生成该头文件的这部分。
问:我认为在 C++ 和 UnrealScript 类定义中存在匹配不当的情况 – 有办法可以检查它吗?
答 :打开 UnBuild.h 并将以下行:
#ifndef CHECK_NATIVE_CLASS_SIZES
#define CHECK_NATIVE_CLASS_SIZES 0
#endif
改变为:
#define CHECK_NATIVE_CLASS_SIZES 1
这样它应该就会在您启动程序时自动为您检查这里。
问:我可以在类的 cpptext 部分中添加一个新的变量吗?
答 :不可以! UnrealScript 和类的 C++ 定义必须精确匹配,而在 C++ 部分中添加变量会破坏精确匹配。您应该将其添加到脚本类,然后使其自动生成包含新变量的 C++ 头文件。
问:我只是向 native 类添加了一个新的脚本变量,编译脚本并导出头文件后,我这边发生了崩溃现象,我改怎么办?
答 :此时,脚本会认为您的类比 C++ 大,所以您必须使用新导出的头文件重新编译 C++ 以便修复匹配不当的情况。 然后您将必须再次重新编译脚本,因为它第一次没有完成编译,但是它不会重新导出头文件。
C++
问:我如何将对象实例放置到 TArray 中?
答 :如下所示:
UObject* SomeUObjectDerivedClass = new(SomeArray) SomeUObjectDerivedClass();
编译
问:我已经将项目添加到依靠我的自定义游戏项目的虚幻引擎 3 解决方案,而且我会收到有关预编译的头文件 (.pch)
答 :请参阅创建自定义项目页面如何创建依赖项目。
调试
问:我如何浏览调试器中的 FStrings、TArrays 或 FNames?
答 :请参阅该页面调试工具以及该主题https://udn.epicgames.com/lists/showpost.php?list=unprog3&id=6072。
问:使用 UDE 进行调试时,我收到诸如“已接收对 UpdateStack 的调用,但是栈不同步”的错误信息。
答 :这通常表示您的某些 .u 文件是在没有使用调试信息的情况下进行编译的。
编辑器
问:我如何运行编辑器? 我只能看到 MyGame.exe。
答 :它是 MyGame.exe 的一部分。您只需在末尾添加 ‘editor’ 选项,如下所示:
mygame editor
问:我如何将资源从一个包移至另一个包?
答 :在通用浏览器中右击这个包,然后选择 Rename(重新命名)。然后将这个新的 包/组 输入到您想要将其移至的地方。移动资源时会在它原来的位置留下‘重定向器’。这样,那些目前还没有加载但是引用该资源的包会知道到哪里能够找到它的新位置。
问:当我在浏览器中重新命名一个对象时,我不可以使用与原来的对象相同的名称创建一个新的对象。
答 :当您重新命名一个对象时,它会创建一个可以从原位置指向新位置的 ‘Redirector’ 对象。这样任何现有的内容都可以找到资源。但是您不可以使 Redirector 与资源的名称相同,这就是为什么不允许创建名称相同的对象的原因。您可以通过在 rename(重新命名)上勾选‘不创建 Redirector’框避免这个问题,但是您应该只可以在您确定没有内容引用该对象的情况下进行这项操作。另一种修复它的方法是在常规的基础上运行 ‘fixupredirects’ 命令行开关。它会尽可能多地进行处理(所以它不要求勾选每个包中的每一项)。此外,如果没有内容引用它,它会清理 __Trashcan 目录中的包。
问:我在关卡编辑器或 kismet 中复制和粘贴某个对象时 – 它应该会将新对象放置在以前对象的位置,然后移动新对象。
答 :当您在编辑器中粘贴时,它会为正在进行创建的新对象保留名称。这样,如果您粘贴的是 2 个通过名称互相引用的对象,那么粘贴后情况仍然如此。但是因为每个对象必须有一个唯一的名称,所以需要重新命名现有对象为新对象让路。这样,如果您所复制的对象名为 Foo。当您粘贴它时,会将新对象命名为 Foo,并将现有的对象重新命名为诸如 Foo_1 这样的名称。
问:我如何在一个位于关卡中的 Prefab(预制)内部选择单独的 Actors?
答 :在主要编辑器工具栏上,有一个标有 ‘P’ 图标可以启动‘prefab lock(预制锁定)’的按钮。 启用预制锁定(默认情况)时,无法选择预制的单独元素。更确切地说,选择一个单独的预制 actor 就会选择整个预制。
问:可以将反向缩放比例应用到一个对象以便可以横穿某个轴‘翻转’它吗?
答 :可以,引擎可以全面支持这项操作。
问:BSP“光照贴图分辨率属性框”中的值代表什么?
答 :它代表每光照贴图贴图像素的虚幻单位数。
问:在不需要键入名称的情况下,我如何才能将一个 Actor 设置为指向其他 Actor?
答 :您只需使用顶部的挂锁按钮‘锁定’这个属性窗口。然后在关卡中选择 Actor,并使用属性旁边的绿色箭头指定它。
问:在 AnimSet(动画集)编辑器中,在 AnimSequence 选项卡下只可以对 AnimationCompressionAlgorithm 进行一次设置。
答 :在 AnimSequence 选项卡中可见的属性并不表示可以直接进行编辑。恰恰相反,修改序列的压缩设置的正确方法是通过AnimationCompressionDialog(动画压缩对话框)。
渲染
*问:使用特定法线贴图时,我的游戏中会显示黑色正方体。
答 :当您在屏幕上看到黑色正方体时,那是由于一些有问题的数据扰乱了后期特效系统造成的。这种现象最常见的原因是在您的法线贴图中有 0 像素。这会使像素着色器中被 0 划分,最终出现这样的问题。确保您的法线贴图其中没有任何灰色区域。
问:我如何更改每个实例中骨架或静态网格物体的材质呢?
答 :您想要在 MeshComponent(网格物体组件)中修改 Materials(材质)数组中对应的插槽。您在 StaticMesh Editor(静态网格物体)或 AnimSet Viewer(动画集查看器)中设置的材质都是“默认值”,但是 Materials(材质)数组允许您在每个实例中覆盖这些默认值。
问:除非在无光照的情况下,否则半透明材质不会显示。 为什么?
答 :自从变更列表 130935(第一个 Gemini QA 版本)开始已经删除了对带光照的半透明物体的支持。 在这个版本之前,使用的是深层剥离对其进行渲染,而且与 UE3 的其他渲染功能正交:像素级光照和阴影、雾、光源函数、景深等等。但是,它的消耗太高以致于除了最简单的场景外的任何地方都不实际。 与其继续在 Gemini 中一个不切实际的代码路径,我们倒不如决定通过忽略带光照半透明物体材质简化/优化不透明光照代码路径。 我们计划试验支持可以不使用深度剥离在一个单独的渲染中带光照半透明物体的有限案例,但是还没有安排计划。
问:我放置了一个 decal(贴花),但是它没有在编辑器或游戏中显示。 我缺少什么步骤吗?
答 :将视口设置为‘带光照’视图模式(如果没有光照贴花不会显示)。 请确保贴花在与接收者相同的关卡中(或将其复制到每个关卡中以防需要映在多个关卡中的接收者)。 请确保 bAceeptsDecals 在接收的网格物体组件上的值为 TRUE(真)。 并检查贴花是否具有合适的 bProjectsOnBSP/StaticMeshes/etc 雾设置。 此外,请确保贴花在其贴花过滤器中没有任何内容。
问:模块化的阴影会遮住自发光材质,有什么解决方法吗?
答 :这是模块化阴影的局限性。 请参阅模块化阴影了解更多详细信息。
问:我已经认定动态阴影是造成我的游戏中性能瓶颈的主要原因,我该从什么地方开始?
答 :关卡优化指南是开始的最合适地方。 此外,请务必查看[[ShadowingReference][ShadowingReference]阴影引用]、模块化的阴影、光照环境以及阴影缓冲过滤选项。
问:为什么创建静态网格物体的光照贴图后 Normal(法线)阴影没有投射在它们上面?
答 :这是因为 Normal(法线)阴影的局限性。 考虑使用模块化阴影替换,这种方法会投射在所有几何体上。
问:模块化阴影会投射整个几何体。 我怎么才能解决这个问题?
答 :请参阅光照环境。
问:这里提供有关在 UE3 中调试着色器的文档说明吗?
答 :请参阅着色器主页。
问:我收到了一个错误的编译着色器,错误信息为“无法绑定非可选的着色器参数 InvMaxTesselationLEvel_Zscale”,这是什么意思?
答 :有时,这会在周围有一个陈旧的临时着色器时发生。 进入 引擎/着色器,并确保没有将文件 Material.usf 和 VertexFactory.usf 标记为只读。 您可能也想要尝试删除这些临时文件。
动画
问:我正在使用 Matinee 在编辑器中制作 Actor 动画,但是在游戏中看上去好像没有任何效果。
答 :首先,检查 Actor 类不是一个‘静态’类。例如,PointLight 是一个静态类,而且无法在运行时进行修改,但是 PointLightMovable 类可以修改。然后,检查 Actor 的 Physics(物理)模式是否是 PHYS_Interpolating,如果不是它将不会按照 Matinee 操作通知它的内容进行操作。
问:我有一个骨架网格物体,其中在网格物体边界盒外部制作某个骨骼的动画。 但是只要边界在视图范围外,其中的对象就不会进行渲染,即使有一些骨骼仍然在视图范围内,
答 :如果您使用 PhAT 为您的网格物体创建一个 PhysicsAsset,并将其指定为 SkeletalMeshComponent,那么它会用该选项更新使用骨骼的碰撞形状的边界盒每一帧。因为这样边界就会更精确,网格物体通常应该正确地描画。
问:我已经在某些骨骼上使用平移导入了一个动画,但是它好像并没有应用于我的骨架。
答 :默认情况下,bAnimRotationOnly 标记在 AnimSet(动画集)属性中进行设置。这会通知引擎在动画数据中获取骨骼的旋转量,而不是从网格物体的参考姿势中的平移量(适用于除根骨骼外的所有骨骼)。这很有用,因为它允许您在不同大小的骨架上播放相同的动画,但是会丢弃动画数据中的所有平移信息。您可以关闭该标志,您将会看到所应用的平移量,或者您可以使用 UseTranslationBoneNames 数组指定应该从动画数据中获取它们的平移量的特定骨骼��
玩家物理
问:我的 pawn 无法始终如一地穿过他本应该适于穿过(使用 PHYS_Walking)的洞。
答 :使用 PHYS_Walking 时,pawns 会通过 MaxStepHeight 走近超出障碍物。 有时,甚至微小的碰撞凹凸(就像可能由 BSP 分割引起的凹凸)也会使 pawn 走近。 为了保证可以持续具有穿越洞的技能,它应该比 pawn 高出 MaxStepHeight + MAXFLOORDIST(在 unphysic.h 中定义)。
碰撞
问:我怎样使玩家可以将每个骨骼与骨架网格物体碰撞?
答 :首先,您需要将 PhysicsAsset 指定为 SkeletalMeshComponent。当前,我们只支持针对于边界盒图元的边界盒扫描曲面测试(供 Unrealplayer(虚幻玩家)物理使用),所以如果您想要阻挡玩家,您必须使用这些选项。然后,您需要勾选一些选项 – 首先,确保 Actor 上的 bCollideActors 和 bBlockActors 勾选的是 true(真),然后 SkeletalMeshComponent 上的 CollideActors、BlockActors 和 BlockNonZeroExtent 也勾选的是 true(真)。
问:为什么 Touch() 脚本事件没有检测到某些碰撞?
答 :Touch() 事件仅适用于没有互相阻挡的 Actors。而互相阻挡的 Actors 会接受 Bump() 事件。
请参阅碰撞参考指南页面深入了解有关碰撞的参考信息。
音频
问:OpenAL 使用什么坐标系统?
答 :请参阅音频系统页面获取相关说明。
统计数据
问:有任何有关各种统计数据 xxx 命令结果的文档说明吗?
答 :统计数据命令输出在统计数据描述中进行说明。
其他
问:虚幻引擎 3 可以在 Windows NT/2000 上运行吗?
答 :我们没有使用 Windows 2000 / NT 上做过测试,不期待可以像支持用户平台一样支持它,所以现在可能会有多个中断区域(以后会有更多引起的未能检测到的中断区域)。
问:我如何才能知道我使用的是哪一个版本的引擎?
答 :您可以在您的 UnrealEngine3\Development\Src\Core\UnObjVer.cpp 版本中查看引擎版本号,然后将其与 Perforce 中的版本历史记录进行对比。然后,查看已经迁入到与您的引擎版本相同的版本中的变更列表,您很有可能具有您已经同步到的变更列表号。
*问:我如何才能找到定位画面以外的窗口?以及我如何才能重置它的位置?
答 :按下 SHIFT+ALT+SPACE+M。后来,您应该可以使用您的箭头键将其推回原位。如果这不起作用,那么尝试在不点击的情况下移动鼠标,然后它应该会显示在屏幕上。
问:我如何才能捕获引擎中的视频?
答 :您可以使用命令行上的 “-dumpmovie -benchmark”,不���这样您将获取不到声音。如果您的回放是确定性的(matinee 序列),那么您可以单独录制它,尽管真实的游戏过程片段录制最好的方式是使用 HDTV 捕获设备/录像机 以及真正功能强大的 SLI 机器。
问:我如何才能在游戏中得到一张屏幕截图?
答 :您可以使用 “shot” 控制台命令将当前的画面截取保存为 .bmp 文件。默认情况下,该命令的快捷键应该是 F9。它会将屏幕截图放入在您的 ..Engine.ini 文件中由 ScreenShotPath 选项指定的目录中,它默认情况下是在您的游戏目录中名为“Screenshots(屏幕截图)”的目录。
问:玩游戏时有调整 Actor 属性的简便方法吗?
答 :这里会提供一些方法。一种方法是在 .uc 文件中将属性指定为 ‘config’。这意味着它们在 .ini 文件中读取它们的值,这样设计师就可以在不需要程序员的情况下调整它们。另一种方法是将变量指定为可编辑属性,然后在游戏过程中使用 ‘editactor’ 控制台命令编辑属性。如果您键入的是:
editactor class=myclass
在游戏中,它会为类 ‘myclass’ 的最近 Actor 弹出一个属性窗口,然后您可以进行调整。使用特殊语法可以将 .uc 文件中的变量添加到属性页面:”var FLOAT EnemyDetectionRadius” 将会出现在属性窗口中,而 “var(Detection) FLOAT EnemyDetectionRadius” 将会出现在“Detection(检测)”组下面的属性窗口中。
最后,现在它使用 RemoteControl(远程控制)窗口可以调整位于关卡中的 actors。
在玩游戏过程中,您随时可以按下 ctrl-esc(或者某些其他案件组合)再次获取鼠标光标,然后单击 RemoteControl(远程控制)中的 Actors 选项卡,并查找您的 actor 实例。在选中的 actor 实例附近会出现一个边界盒。接下来,您可以单击 RemoteControl(远程控制)窗口工具栏中的 Properties(属性)图标编辑 actor 的属性(假设您使用的是上面描述的用于 editactor 命令的特殊语法)。注意:生成的 actors 当前不会出现在 RemoteControl(远程控制)”Actors” 选项卡中,但是对于这些 actors,您仍然可以使用上面的 “editactor”。
请记住,在使用 editactor 命令或 RemoteControl(远程控制)编辑属性时,退出游戏后会丢失其中进行的更改。您需要在退出之前从属性窗口中将它们复制出来(使用 PropertyWindow(属性窗口)工具栏复制更改,然后将它们粘贴到一个安全的目标地址)。
问:我可以将 actor 作为子对象(通过 editinlinenew 或在代码中)吗?
答 :不可以! 这是因为子对象(在脚本代码中)或通过编辑器中的 editinlinenew 属性创建对象都不是使用合适的创建方法创建的。Actors 只 可以通过 Spawn(脚本)和 SpawnActor (C++) 函数进行创建。所有 actors 都需要在世界内部进行创建,而不是在其他对象中创建,同时它们需要一个位置并需要将其添加到各种引擎结构,例如 octree 等等。子对象和 editinlinenew 对象没有在其上面运行任何这样的特殊代码。