游戏开发者需要注意的4个内存使用问题
从销售角度考虑,全新的手机游戏应适配当下大多数用户使用的设备。“大多数设备”这一概念或许会让开发者感到意外。截至2015年1月,全球手机用户数量已达36亿。因此,开发者的任务是让游戏或应用能够适应这些设备的各种硬件限制。在开发如游戏这类内存消耗较大的软件时,开发者需要进行更深入的思考。撰写本文,旨在帮助一些非技术背景的人士更好地理解内存问题,这些问题也是2D游戏项目开发中需要考虑的要点。
1. 内存泄露
内存泄露是指已分配的内存块未被释放。
为了更形象地理解内存泄露,我们可以进行如下类比:假设你身处一个有3个方形储物柜的房间。
- 第一步,John和Danny都需要存放自己的装备,每人使用一个储物柜即可。此时,有2个储物柜被占用,1个闲置。
- 第二步,John需要存放他的头盔,且不再需要之前存放的装备。理想情况下,他应取出之前的装备,将头盔放入该储物柜。但他却向管理员申请了一个新的储物柜来放置头盔。这样一来,所有储物柜都被占满,而John也遗忘了他存放在第一个储物柜中的装备。
- 第三步,Danny需要存放2个头盔,需要2个储物柜。他拿出自己的装备,空出1个储物柜,然后向管理员申请一个新的储物柜,但由于所有储物柜都已满,申请被拒绝。
在这个例子中,即便John取出了无用的装备,Danny也无法使用多出的存储空间,这就如同内存泄露,未释放的内存无法被重新利用。
2. 相同纹理的多个实例
一个纹理占用的存储空间为宽度×高度×4(红色、绿色、蓝色和透明度各占1个字节)。例如,一张512×512规格的图像将占用1.05兆的内存。若存在3个相同的纹理实例,则会占用3倍的存储空间,即3.15兆。所以,如果要将这些图像用作纹理,就需要额外准备3倍的内存。
我们通过一个贴纸的例子来类比:假设有一张印有你最喜欢角色“buttman”的方形贴纸,且该贴纸不能无限次使用。你需要将这个新角色展示给3个人。此时有两种方式:
- 方式一,你获取2张相同的贴纸,准备3个木质框架,将贴纸贴在框架上,然后把框架交给这3个人。
- 方式二,让这3个人各自准备木质框架,然后将贴纸贴在框架上。
显然,第二种方式更优,因为可以反复使用同一张贴纸。在软件程序中也是如此,大家可以同时关联到“buttman”,避免了重复存储相同纹理带来的内存浪费。
3. 不必要的迭代
在资源处理中,使用for/while循环一次性处理多个任务,比多次调用更高效。
我们以间谍执行任务为例:你是一名间谍,需要向3个不同且距离较远的场所运送包裹,并从这3个场所的不同老板那里收集重要的秘密信息。由于任务来自不同老板,你有两种任务分配方式:
- 方式一,按照老板分配任务。你先驾车前往3个场所完成老板A分配的任务,然后再次驾车前往这3个场所完成老板B分配的任务,依此类推。
- 方式二,按照场所分配任务。你先驾车前往第一个场所,递交包裹并获取信息,然后前往下一个场所。
如果采用第一种方式,就如同一个愚蠢的间谍,因为完成相同的任务需要花费更多的时间和资源。在程序开发中,不必要的迭代会增加系统开销,降低性能。
4. 在内存中保留未使用的对象
在任何时候,只有一定数量的对象会被使用或显示在屏幕上。由于内存空间有限,任何留在内存中的额外对象都会消耗资源。
我们用推马车的例子来理解:你需要将一辆马车从A点推到B点。如果马车空载或负载最轻的物品,这是一项相对轻松的任务。但由于你喜欢啤酒,你选择用马车装载一桶啤酒,这无疑增加了任务的难度。
因此,最佳的解决方案是放弃那桶啤酒。在游戏开发中,应及时清理内存中未使用的对象,以节省资源。
这里列出的问题远不止一篇文章所能涵盖的内容。作为开发者,应尽快识别这些问题,并采用有效的解决方案。在克服这些挑战后再发布产品,才是真正令人兴奋的游戏开发过程。每个人每天只有24小时,玩家愿意花费这些宝贵的时间来体验我们开发的游戏,这就是推动我们不断前行的最大动力。