Questions tagged «memory-efficiency»

一种组织和存储信息的方法,以使其占用尽可能少的内存,同时仍保留其全部用处。


8
他们是如何做到的:Terraria中的数百万块瓷砖
我一直在开发类似于Terraria的游戏引擎,这主要是一个挑战,尽管我已经弄清了其中的大部分内容,但我似乎并没有真正为它们如何处理数百万个可交互/可收割的图块而费心游戏一次完成。在我的引擎中,创建约500.000个图块,这是Terraria可能生成的图块的1/20,导致帧速率从60下降到约20,即使我仍然只在视图中渲染图块。请注意,我没有对磁贴做任何事情,只是将其保留在内存中。 更新:添加代码以显示我的操作方式。 这是类的一部分,它处理并绘制图块。我猜想罪魁祸首是“ foreach”部分,该部分会迭代所有内容,甚至是空索引。 ... public void Draw(SpriteBatch spriteBatch, GameTime gameTime) { foreach (Tile tile in this.Tiles) { if (tile != null) { if (tile.Position.X < -this.Offset.X + 32) continue; if (tile.Position.X > -this.Offset.X + 1024 - 48) continue; if (tile.Position.Y < -this.Offset.Y + 32) continue; if (tile.Position.Y > -this.Offset.Y …

6
我们如何解决2D游戏中大视频存储需求?
我们如何解决2D游戏中大视频存储需求? 我们正在开发使用Allegro C / C ++的2D游戏(Factorio),并且随着游戏内容的增加,我们面临视频存储需求增加的问题。 目前,我们收集了有关将首先使用的图像的所有信息,尽可能地裁剪所有这些图像,并尽可能紧密地将它们组织成大图册。这些地图集存储在视频内存中,视频内存的大小取决于系统限制。目前,它通常是2张图像,最高可达8192x8192,因此它们需要256Mb至512Mb的视频内存。 这个系统对我们来说非常不错,因为通过一些自定义优化以及拆分渲染和更新线程,我们能够以60 fps的速度在屏幕上绘制成千上万的图像。我们在屏幕上有许多对象,因此允许大缩放是一项关键要求。由于我们要添加更多内容,因此视频内存要求会出现一些问题,因此该系统无法容纳。 我们想要尝试的一件事是拥有一张包含最常见图像的地图集,而第二幅则作为缓存。图像将根据需要从内存位图移到那里。这种方法有两个问题: 从内存位图到视频位图的绘制速度非常缓慢。 在Allegro中,除了主线程之外,无法使用视频位图,因此实际上是不可用的。 这是我们还有的一些其他要求: 游戏必须是确定性的,因此性能问题/加载时间永远不能改变游戏状态。 游戏是实时的,并且很快也会成为多人游戏。我们需要不惜一切代价避免甚至最小的结结巴。 游戏的大部分是一个连续的开放世界。 该测试包括批量绘制1万个精灵,大小从1x1到300x300,每种配置几次。我在Nvidia Geforce GTX 760上进行了测试。 当源位图在各个位图之间没有变化时(图集变体),视频位图到视频位图的绘制每个子图花费0.1us。大小没关系 视频位图到视频位图图形,而源位图在图形之间切换(非图集变体),每个子图形花费0.56us;大小也没关系。 内存位图到视频位图的绘制确实令人怀疑。从1x1到200x200的大小每个位图要花0.3us,所以速度并不是那么慢。对于较大的尺寸,时间开始急剧增加,201x201的时间为9us,291x291的时间为3116us。 使用Atlas可将性能提高5倍以上。如果我有10ms的渲染时间,则使用Atlas将每帧限制为100000个精灵,如果没有它,则限制为20000个精灵。这将是有问题的。 我还试图找到一种方法来测试阴影的位图压缩和1bpp位图格式,但是我无法找到在Allegro中执行此操作的方法。


2
即使障碍物在移动,A *还是有效的吗?
我刚刚开始学习路径查找,并且一直在研究A *算法,而我主要担心的是,我所看到的所有示例都显示了围绕它进行计算的静态障碍。 如果我有移动障碍物,例如说其他角色,也要四处走动,以确保角色必须找到自己的位置,我假设我必须在每一帧都运行算法,但是我担心这样做会变得很昂贵硬件为每个活动演员处理每个帧。 那么,A *是否仍然足够有效,以便在障碍物也移动时也可以使用,或者还有另一种寻路方法能够更有效地处理障碍物?

1
为什么我总是要考虑创建和使用对象池,而不是即时实例化新对象?
我已经多次(从最佳实践的角度)了解过这种模式: 内存分配:始终考虑创建和使用对象池,而不是即时实例化新对象。这将有助于减少内存碎片,并减少垃圾收集器的工作。 但是,我不知道这实际上意味着什么。我该如何实施? 例如,我可以实例化一个GameObject使用InstantiateUnity 的方法吗? Instantiate(prefab, new Vector3(2.0F, 0, 0), Quaternion.identity); 不鼓励这种用法吗?还有什么意思?


3
您如何为内存不足情况做准备?
对于范围界定明确的游戏而言,这可能很容易,但是问题是关于沙盒游戏,允许玩家创建和构建任何东西。 可能的技术: 使用上限的内存池。 删除不再需要的对象。 在开始时分配额外的内存,以便以后可以将其作为恢复机制释放。我会说大约2-4 MB。 这在移动/控制台平台上更可能发生,在该平台上,内存通常受到限制,与您的16 GB PC不同。我假设您完全控制了内存分配/释放,并且不涉及垃圾回收。这就是为什么要将其标记为C ++。 请注意,我并不是在谈论有效的C ++项目7“为内存不足的情况做准备”,尽管这很相关,但我希望看到一个与游戏开发更相关的答案,您通常会对游戏开发有更多的控制权发生。 总而言之,当您针对内存控制台/移动设备有限的平台时,如何为沙盒游戏的内存不足情况做准备?

1
以两倍的速度导出音频文件有什么弊端,然后游戏引擎以一半的速度回放吗?
我想减少游戏的文件大小,音乐和SFX占了很大一部分。 如果我以120bpm的速度制作歌曲或声音效果,然后使用DAW或独立程序应用速度和音调加倍,然后录制新的双倍速音频文件,则其最终大小为原始文件大小的一半(因为现在的歌曲长度为减半)。然后,我使用游戏引擎(Unity)以半速播放240bpm音频文件,因此现在听起来很正常。没有伪影或失真。 因此,这里的问题是:我是否为了半速播放而牺牲了诸如处理能力之类的东西?我正在加载一半大小的文件,因此必须在某处进行某种权衡吗?我觉得他们的头脑中没有人会这样做,但是为什么不呢?

4
动态内存分配和内存管理
在普通游戏中,场景中有成百上千个对象。通过默认的new()动态地为所有对象(包括枪击(子弹))分配内存是否完全正确? 我应该为动态分配创建任何内存池,还是不必为此烦恼?如果目标平台是移动设备怎么办? 请在手机游戏中需要一个内存管理器吗?谢谢。 使用的语言:C ++;当前在Windows下开发,但计划在以后移植。

2
处理屏幕外AI的好方法?
例如,缘故: 假设世界上有10个房间。 假设世界上居住着10个实体。 每个实体都有自己的“例行程序”,在该例行程序中它在房间中执行某些操作,并且还可以在房间之间进行导航。 假设玩家一次只能进入一个房间,那么跟踪其他实体在屏幕外其他房间正在执行的动作的好方法是什么? 最直接的选择是检查每一帧上的10个实体中的每个实体,检查它们的位置/状态,并确定该实体在任何给定时间是否应位于玩家所在的房间中。 (但是,这确实感觉资源很丰富,尤其是随着房间/实体数量的增加。) 另一种选择是跟踪自游戏开始以来所经过的时间,然后每个实体检查其模式是否与玩家所在的房间相交,并且是否按照时间检查是否已实体应该在此特定时间位于同一房间中,其图案不与玩家所在的当前房间相交的实体直到玩家进入其图案相交的房间并且仅在该点才计算不执行任何操作他们应该渲染。(但是,如果他们与房间互动,那么他们将必须始终检查与路线相交的房间的状态,以便确定在该时间点的位置,这并不是那么好。) 我要做的第三个选择是,首先仅查看与玩家位置相交的路线(如前所述),其次进入房间后,检查玩家是否在该房间内,如果不是,则仅检查房间的状态,以及进入下一房间需要多长时间。例如,一个看门人NPC进入房间,检查房间的状态,查看玩家是否有溢出物,计算清理该清理所花费的时间以及该路径需要花费多长时间等。时间是进入下一个房间的时间,我们只会检查玩家是否在房间里。用于渲染目的的NPC的确切位置仅在玩家进入房间时计算。 经过一番集思广益后,我想到了第三个选择,但我想知道是否存在一种已知或更好的方法来处理此类问题?

3
是否有任何文档比较/对比C ++标准库的实现?[关闭]
关闭。这个问题是题外话。它当前不接受答案。 想改善这个问题吗? 更新问题,使其成为话题成为Game Development Stack Exchange。 4年前关闭。 (这本身不是游戏编程,但是我确定如果我这样问我,即使历史告诉我们每个大型游戏最终都担心这些事情,我还是被告知不要过早优化。) 是否有文档可以总结不同C ++标准库实现之间的性能差异,尤其是内存使用情况?一些实现的细节受到NDA的保护,但是即使是STLport与libstdc ++,libc ++与MSVC / Dinkumware(相对于EASTL)之间的比较似乎也非常有用。 我特别在寻找以下问题的答案: 标准容器有多少内存开销? 什么容器(如果有的话)仅通过声明进行动态分配? std :: string是否在写时复制?短字符串优化?绳索? std :: deque使用环形缓冲区还是废话?

1
如何从实体组件系统游戏引擎中的cpu缓存中受益?
我经常阅读ECS游戏引擎文档,这是明智使用cpu缓存的良好架构。 但是我不知道如何从cpu缓存中受益。 如果将组件保存在连续内存中的数组(或池)中,则只有在顺序读取组件的情况下,才是使用cpu缓存BUT的好方法。 当我们使用系统时,它们需要实体列表,这些列表是具有特定类型组件的实体列表。 但是这些列表以随机的方式而不是顺序地提供了组件。 那么如何设计ECS以最大化缓存命中率呢? 编辑: 例如,物理系统需要具有RigidBody和Transform组件的实体的实体列表(有一个RigidBody池和一个Transform组件池)。 因此,其更新实体的循环将如下所示: for (Entity eid in entitiesList) { // Get rigid body component RigidBody *rigidBody = entityManager.getComponentFromEntity<RigidBody>(eid); // Get transform component Transform *transform = entityManager.getComponentFromEntity<Transform>(eid); // Do something with rigid body and transform component } 问题在于,entity1的RigidBody组件可以在其池的索引2处,而entity1的Tranform组件在其池的索引0处(因为某些实体可以具有某些组件,而其他组件不能具有其他组件,并且是因为添加/删除了实体/组件)。 因此,即使组件在内存中是连续的,也会随机读取它们,因此它将有更多的缓存未命中,不是吗? 除非有一种方法可以预取循环中的下一个组件?

1
glDrawArrays和glDrawElements的区别
在刷新OpenGL ES的想法时,我遇到了glDrawArrays和glDrawElements。 我了解它们的用法,并有点理解它们为何与众不同。 我似乎不明白的是,我看不到如何glDrawElements保存绘图调用(保存绘图调用是我所读过的大多数书籍都提到的描述,因此我在这里提到了)。 想象一个简单的场景,其中我尝试使用2个三角形绘制一个正方形。 使用glDrawArrays时glDrawElements,我需要使用6个顶点的集合,除了具有6个元素的索引数组之外,我只需要4 个顶点。 鉴于以上所述,这是我不了解的内容: glDrawElements如果仍然需要使用索引数组(在正方形的情况下为6个索引)来索引具有4个元素(6次)的顶点数组,如何保存绘图调用?换句话说,这glDrawElements是否仍意味着总共需要进行6次抽签glDrawArrays? glDrawElements如果一个仍然需要2个数组,即一个用于顶点,一个用于索引,该如何节省空间? 为了从2个三角形绘制一个正方形,为简单起见,分别需要多少次绘制调用glDrawElements(顶点数组中4个项目,而索引数组中glDrawArrays6个项目)和(顶点数组中仅6个项目)? 谢谢。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.