当前位置: 首页 > news >正文

h5网站欣赏运动鞋网站的建设风格

h5网站欣赏,运动鞋网站的建设风格,正安县网站seo优化排名,做网站怎么拿框架的原代码仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾并设定今天的主题 今天的任务是进一步优化背景资源的流式加载#xff0c;尤其是在内存管理方面。昨天#xff0c;我们实现了资源流式加载#xff0c;让游戏在加载时可以动态地加载背景#xff0c;而不是一开始就把所有资…仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾并设定今天的主题 今天的任务是进一步优化背景资源的流式加载尤其是在内存管理方面。昨天我们实现了资源流式加载让游戏在加载时可以动态地加载背景而不是一开始就把所有资源都加载完。这种做法确保了游戏在启动时可以立即进入并且随着游戏的进行逐步加载需要的背景内容。这是一个开始但目前还不完善存在一些问题特别是内存管理方面。 目前的流式加载系统缺乏一个有效的内存管理策略。当加载的艺术资源总量超过了机器的内存时系统并没有明确的应对策略。虽然现在的机器内存非常大可能所有的资源都可以适应内存但理想的情况是游戏引擎能够处理一种情况即机器内存不足以容纳所有资源。特别是当用户的机器只有4GB内存时仍然能够处理这种情况。例如游戏的未压缩资源总量可能高达32MB应该能够在4GB内存的情况下正常运行。因此我们需要改进流式加载系统使其能够适应内存不足的情况。 在实现过程中当前的系统在加载资源时存在一个主要问题没有合理的内存管理。每次调用调试位图加载debug load bitmap时都会不断地分配内存但系统并没有回收这些内存导致内存不断增长直到系统的虚拟内存耗尽游戏可能崩溃或者触发操作系统的低内存警告。这是非常不理想的。 为了解决这个问题我们需要引入一种“先进先出”FIFO的内存管理策略。这个策略就像军事中的“一进一出”规则保证在内存达到一定阈值时旧的资源会被释放以腾出空间给新的资源加载。这将是我们接下来要做的工作之一。 另外我们还需要处理一些其他问题比如修正角色漂浮问题并恢复之前删除的位移概念。尽管这些问题比较小但也需要清理和修复确保游戏中的元素都能正确对齐。 总结来说今天的目标是提高资源流式加载的质量确保它能够高效管理内存避免过多资源加载导致的崩溃问题并且继续改进游戏的内存管理策略。 黑板“One In One Out” 我们希望能够明确控制游戏加载的艺术资源的内存占用以避免因资源占用过多内存而导致系统崩溃或出现其他问题。理想情况下游戏在运行时应该有一个明确的内存限制例如设定为2GB这个数值可以根据机器的最低配置要求来调整可能会根据不同的游戏需求有所不同。 在这个内存限制内我们希望能够动态管理加载的艺术资源。假设游戏中的艺术资源在磁盘上占用了32GB但由于资源的压缩方式实际解压后的内存占用可能要大得多。为了在有限的内存内高效加载资源我们需要一个内存管理系统来控制哪些资源需要加载哪些可以被替换。 具体的策略是假设内存中最多加载2GB的艺术资源。当游戏需要加载一个新的艺术资源时如果该资源尚未加载我们希望能够从已经加载的资源中选择一个长时间未使用的资源并将其移除以腾出空间加载新的资源。这就是所谓的“逐出”策略即把不再需要的资源替换掉。 这种方式的好处是只要游戏启动时内存的初始占用符合预期我们就能确保在整个游戏运行过程中不会因为内存耗尽而导致崩溃或其他严重问题。内存管理变得更加可控资源加载也能在给定的内存范围内高效进行避免了不必要的内存溢出。 总之目标是通过合理的内存管理策略确保游戏在运行时始终保持稳定能够灵活地加载和替换艺术资源同时避免因内存不足导致的崩溃或性能问题。 黑板只加载一次 另一个需要解决的问题是确保不会在同一帧中重复加载同一个资源。这是一个相对简单的问题但仍需要解决。当前的情况是如果在同一帧中多次请求加载同一个资源比如“影子”系统可能会启动多个加载线程来加载这个资源。 例如第一个请求会启动加载线程而第二个请求也会启动另一个加载线程尽管实际上我们只需要启动一个加载线程。这种重复工作不仅浪费了处理能力还会浪费内存因为会发生内存泄漏因为第二次加载会覆盖掉第一次加载分配的内存。 解决这个问题的关键是确保只有第一个请求触发加载线程而后续的请求应该等待第一个加载线程完成避免重复加载同一资源。这需要在管理加载任务时更加小心和精确地标记资源的加载状态以避免这种无谓的重复加载和内存浪费。 虽然这个问题本身比较简单但它依然是确保游戏性能和内存管理高效的一个必要步骤。 概述我们今天的任务 首先需要按难易程度依次解决问题。首先将重新实现“TopDownAlignY”的代码部分因为在之前的实现过程中我们曾经有一部分实现了但在紧急调整时丢失了。现在需要把这部分内容恢复过来确保一切正常工作。 接着处理“只加载一次”的问题确保每个资源在同一时间只加载一次避免多次启动加载线程浪费计算资源和内存。 最后解决更为复杂的内存管理问题即确保游戏在加载资源时始终保持固定的内存占用大小。虽然问题本身并不复杂但当资源大小不确定时需要做出一些决策来合理管理内存。需要考虑如何处理这些动态资源的加载和内存分配确保系统不会因为资源过多而崩溃。 game.cpp重新引入 TopDownAlignY 为了实现“TopDownAlignY”的功能需要进行一些调整。首先暂时不替换现有的位图加载调用尽管将来可能会考虑替换。现在的目标是确保现有功能能够正常运行因此采用一种方法通过分支调用原有函数来实现并将需要的参数传递给工作任务。 具体来说需要将之前使用的两个参数存储到“加载资源任务”中这样可以确保我们能够保持和以前相同的行为。参数的类型已经确认是32位整数。还需要存储一个布尔值用于表示资源是否有对齐要求。如果资源有对齐要求任务会使用对齐如果没有对齐要求则不使用。虽然这是一个临时方案未来会清理并优化代码但目前这样做能保证功能正确。 在此过程中假设资源没有对齐要求但在后续步骤中如果资源需要对齐相关代码会进行处理和更新。通过这种方式确保原本单线程下的功能能够恢复确保我们回到最初实现时的功能完整性。 运行游戏查看正确的对齐效果 现在人物的对齐已经正确所有的功能也恢复正常。这样之前的问题已经解决角色显示的位置和对齐方式都符合预期。整体来看现阶段的调整已经使得系统更加稳定所有的元素都正常显示并且没有再出现位置错乱的问题。 game.h确保内容只加载一次 现在我们要解决的另一个问题是确保每个资源只加载一次。之前提到过加载资源时可能会出现重复加载的问题。为了解决这个问题计划引入一种“资源槽”的概念将原来的位图数据结构替换为“位图槽”。通过这种方式可以标记每个资源的加载状态以避免资源被重复加载。 具体来说在加载资源时首先要检查资源是否已经被标记为正在加载。如果资源已经被标记为正在加载那么就不再启动新的加载进程。而是等待当前加载过程完成后再返回正确的结果。通过这种机制能够确保每个资源在同一时刻只会被加载一次避免浪费内存和资源。 在实际操作中加载资源前需要检查该资源是否已经排队如果没有排队才会启动加载过程这样可以避免重复加载相同的资源。 game.cpp检查目标资产是否已加载 为了确保资源只加载一次采取了一种方法即检查资源的状态判断该资源是否已经加载或是否已经排队等待加载。如果资源已经标记为“已加载”或“已排队”则不再重复加载。如果资源的状态是“未加载”则会启动加载过程。 然而需要注意的是简单的检查和修改资源状态可能会出现问题特别是在多线程环境中。多个线程可能会同时看到资源状态为“未加载”然后同时尝试加载该资源。为了避免这种情况使用了原子操作atomic compare and exchange来确保状态的更新是安全的。 具体实现是首先检查资源的状态是否为“未加载”。如果是就尝试使用原子比较交换操作将状态从“未加载”改为“排队中”。原子操作保证了在多个线程之间不会出现竞争条件也就是说如果一个线程成功地将状态改为“排队中”其他线程就无法再看到“未加载”状态从而避免了重复加载的问题。通过这种方式可以确保资源加载的状态在多线程环境下的一致性。 game_intrinsics.h引入 AtomicCompareExchangeUInt32 在这个过程中主要是确保使用正确的原子操作来安全地更新资源的状态防止多个线程在并发环境下对同一个资源进行重复加载。为了实现这一点使用了“原子比较交换”atomic compare and exchange操作。这个操作会检查资源的当前状态并在满足特定条件时修改它。具体来说它会检查当前状态是否为“未加载”如果是就将其更新为“排队中”状态防止其他线程也开始加载相同资源。 然而使用这些原子操作时需要注意到它们是平台相关的因此不同平台需要根据其编译器来具体实现。每个平台的实现可能有所不同因此需要指定正确的参数类型和操作方式。 在实现过程中首先要确保原子操作能够接受正确的参数类型比如 u32 类型的指针并且确保每个操作的预期值和新值能正确传递到原子操作中。特别需要处理的细节包括如果操作失败即状态已经被更新需要对比并重新执行操作直到能够成功修改资源状态。 最终在确保资源状态正确更新后可以使用这些操作来保证多线程环境下的资源加载是安全的不会发生重复加载或状态不一致的情况。这些操作通过内存屏障来确保操作的顺序性避免潜在的并发问题。 编译并运行 现在基本上已经解决了多次调用的问题通过原子操作来确保资源的加载状态不会被重复修改从而避免了多线程环境下的并发问题。尽管目前还没有足够的调试可视化工具来帮助确认这一点但这将在后续工作中解决等到能够可视化更多信息时便可以更好地验证系统的正确性。 不过虽然核心的并发控制已经完成但依然存在一些需要处理的问题具体来说是一些潜在的复杂性和不太容易处理的部分这些可能会涉及到一些额外的细节或特定情况的处理。这些问题可能会在后续开发过程中逐步显现并需要进一步的解决方案。 如果要合成的位图不存在FillGroundChunk 将渲染错误 现在问题出在填充地面区块ground chunk时代码执行的逻辑上。具体来说在调用 FillGroundChunk 时它只是构建了推送缓冲区push buffer的内容并将工作任务DoTiledRenderWork放入内存中。然而这里存在一个问题在构建这些数据时所需使用的位图bitmap还没有被加载。这样当渲染时渲染结果会不正确因为会缺少某些应该插入的图像数据导致地面区块渲染不完整。 在实际的游戏帧渲染中这种情况可能不会引发严重问题因为即便出现错误最坏的情况只是短暂的闪烁或者因为流媒体加载的方式足够提前地面图像会在屏幕上显示之前加载完成所以常见的情况是不会出错。但在当前的情况中没有类似的保障一旦发生这种错误它就会被永久保留在渲染结果中从而导致反复出现错误造成非常严重的视觉问题这是不希望看到的。 解决这个问题有几种方法 保证所有使用的地面区块资源始终驻留在内存中并且无法被逐出。 这能确保渲染所需的位图始终可用不会出现渲染错误。 只允许地面区块填充在所有必要资源都加载完成的情况下进行。 这种方式可以确保只有当所有依赖资源准备好时才会进行渲染从而避免因资源缺失导致的错误。 让填充过程暂停等待资源加载完成后再继续执行。 这种方式可以使程序等待位图加载完成确保渲染时资源的完整性。 每种方法都有不同的优缺点需要根据具体情况来选择最佳解决方案。 game.cpp仅在确认填充完成后标记地面块为已填充 目前最简单的解决方案就是确保在地面区块被标记为“已填充”之前必须确认所有资源都已经加载并且没有问题。具体来说可以采取如下做法 在进行所有必要的工作之后检查渲染组中所有的位图是否有效。如果所有位图都是有效的那么就可以继续进行后续的渲染操作。 这种方法的核心思想是只有在确认所有资源特别是位图都已准备好且没有问题时才允许继续渲染地面区块从而避免因资源未加载完全而导致的渲染错误。 game_render_group.cpp引入 AllBitmapsValid (AllResourcesPresent) 为了确保资源加载完毕后再进行渲染可以通过在渲染组中增加对位图有效性的检查来避免渲染错误。具体步骤如下 首先在渲染组中调用一个名为 AllBitmapsValid 的函数。这个函数的作用是检查当前渲染组中的所有位图是否有效确保没有发生缓存未命中的情况。如果所有位图都是有效的那么渲染操作就可以继续进行。 另外还可以增加一个计数器来追踪资源的加载情况。每当需要加载一个资源时都会增加一个“缺失资源计数”。这个计数器会记录当前缺失的资源数量。在资源加载完成后当渲染操作结束时可以检查缺失资源的数量如果为零说明所有资源都已经加载完成渲染可以顺利进行。 这个方法可以帮助确保渲染操作只在资源完全准备好的情况下执行从而避免因资源未加载完成而导致的渲染错误。 向 render_group 添加 MissingResourceCount 为了确保所有必需的资源都已经加载并且准备好进行渲染可以使用一个新的检查机制叫做 “all resources present”所有资源就绪。具体实现方法是在渲染组中如果所有需要的资源都已加载并且没有缺失那么返回 true。这种方法可以通过检查当前资源缺失计数是否为零来实现。 当所有资源都存在时就表示渲染所需的资源都已经准备好可以安全地进行渲染。这样做的好处是只有当所有必需资源都存在时才允许继续填充并渲染地面块ground chunk。如果某个资源尚未加载渲染将不会进行从而避免因缺失资源导致的渲染错误或异常。 问题在单独线程上渲染的地面块可能在错误的时间被移除 为了确保所有必需的资源都已经加载并且准备好进行渲染可以使用一个新的检查机制叫做 “AllResourcePresent”所有资源就绪。具体实现方法是在渲染组中如果所有需要的资源都已加载并且没有缺失那么返回 true。这种方法可以通过检查当前资源缺失计数是否为零来实现。 当所有资源都存在时就表示渲染所需的资源都已经准备好可以安全地进行渲染。这样做的好处是只有当所有必需资源都存在时才允许继续填充并渲染地面块ground chunk。如果某个资源尚未加载渲染将不会进行从而避免因缺失资源导致的渲染错误或异常。 解决这个问题的可能方案 当前情况比较糟糕主要是考虑到资源缺失的问题。对于如何处理这种情况有几个可能的方案。 其中一个方法是“祈祷”式的解决方案也就是说依赖于资源管理策略假设资源已经加载并且被标记为“热”的状态不会很快被驱逐。这种方法的假设是如果这些资源已经标记为“热”它们在多帧之后才会被驱逐所以短期内应该不会出现问题。虽然这种方法在理论上可能可行但并不可靠也不能确保完全正确。如果采用这种方案可能会在短期内运行正常但也可能出现意外的错误尽管游戏不会频繁崩溃。 另一种方法是采取更严谨的做法通过临时锁定资源来确保资源在渲染过程中不被驱逐。每次使用资源时可以改变资源的状态标记为已使用然后在渲染完成后清理这些状态。这是一个更理论上正确的方法虽然实现起来相对简单但需要对资源缓冲区进行迭代处理这可能会带来一些额外的复杂性和性能开销。 总结来说第一种方法虽然简单但不太可靠第二种方法更为严谨和正确但可能带来性能上的一些问题需要权衡选择。 game_render_group.cpp引入 CleanupRenderGroup 考虑到资源管理的问题决定尝试编写并实施一种解决方案看看实际效果如何。核心思路是在分配渲染组资源时执行完分配操作后需要进行清理工作。清理操作虽然是必要的但它非常麻烦且容易被忽略或者因为某些原因耗时过长。问题在于清理不仅仅是直接读取内存还需要执行一些额外的步骤来确保所有的资源得以正确清理。 具体来说在渲染组分配后需要执行一个清理渲染组的操作。这时清理操作会逐个遍历资源列表和其它操作类似。遍历过程中如果某个资源需要释放例如位图资源就会标记该资源为不再使用。 然而由于渲染操作涉及到图形渲染的流程这种清理操作的实现有些复杂。尽管如此还是可以尝试实现这个清理过程看看它在实际工作中是否顺利。为了提高代码的可复用性和减少出错的可能性虽然渲染相关的操作通常较为复杂但还是可以考虑将清理功能提取为一个更易于共享的模块。这有助于多个线程或不同部分的代码共享该功能从而避免重复代码。 总的来说虽然清理工作繁琐且有一定的风险但还是需要尝试实现并观察实际效果看看是否能有效解决问题。 game_render_group.h为 render_entry_bitmap 添加 game_asset_id 在执行渲染组的清理操作时必须确保正确释放资源。对于位图资源关键在于如何正确释放已使用的资源。因此需要提供一个释放资源的方法以便在清理阶段调用。 在清理过程中首先要检查所使用的资源是否为位图。如果是位图就必须释放它。为此需要在数据结构中存储资源的 game_assets_id这样在释放时可以直接引用该 ID而不必依赖具体的位图指针。 为了实现这一点在位图结构中需要保留 game_assets_id而不一定要保留已加载的位图指针。理论上存储 game_assets_id 就足够了因为通过 ID 可以查找到资源并执行释放操作。然而在早期阶段仍然可能需要位图指针以便获取必要的信息比如位图的尺寸等。 因此虽然最终可能只需要 game_assets_id但在处理过程中仍然需要保留位图指针以确保能够正确计算相关参数。例如在某些操作中可能需要访问位图的宽度和高度而这些信息依赖于位图指针。 总之在清理过程中资源的管理方式需要进行适当的调整。存储 game_assets_id 以便于资源释放同时在需要时保留位图指针以便进行必要的计算。这样可以确保在渲染组的清理过程中既能正确释放资源又能保证渲染所需的信息完整。 game_render_group.cpp在 CleanupRenderGroup 中引入 UnlockAsset 在这里的处理逻辑是如果渲染组中的某个条目包含有效的位图资源就需要执行资源解锁操作以便释放该资源。具体来说首先检查条目中的位图是否有效如果有效就提取其 game_assets_id然后调用 ReleaseAsset 或 UnlockAsset 这样的函数来解除资源占用。 该函数需要传入渲染组的资源管理器以及 game_assets_id以便正确标记该资源为可用状态使其能够被回收或重新加载。这一操作的关键目标是确保所有已经使用的资源在渲染组不再需要它们时能够被正确释放以避免资源占用过多或者发生内存泄漏。 在实现过程中需要确保 UnlockAsset 方法能够正确识别传入的 game_assets_id 并对其进行状态修改使其不再被当前渲染组锁定。此外还需要在渲染组的适当位置调用该方法以确保资源能够被及时释放而不会影响渲染的正确性。 这一处理流程的核心思想是 在渲染组清理时检查每个条目是否持有有效的资源。如果资源有效则调用 UnlockAsset 释放资源。UnlockAsset 需要正确地与资源管理系统交互确保资源状态被正确更新。 最终这样的资源管理机制可以确保渲染组在完成渲染任务后不会占用不必要的资源同时避免因资源未正确释放导致的问题。 在 PushBitmap 中引入 LockAsset 在执行 PushBitmap 调用时需要先锁定资产因此必须调用 LockAsset。如果 LockAsset 成功执行就可以继续处理相应的位图数据。同时由于在执行 LockAsset 之后程序会重新获取位图因此可以省略之前的位图有效性检查 (if Bitmap)因为此时已经确保位图是存在的否则 PushBitmap 调用就不会被执行。 这一优化的关键点在于 确保资源可用性在 PushBitmap 之前先调用 LockAsset确保所需的位图已经被正确加载并防止它被意外释放或替换。简化逻辑由于 LockAsset 已经保证了资源的有效性因此可以省略额外的位图检查提高代码的简洁性和可维护性。确保正确的资源生命周期管理当 PushBitmap 结束后后续的流程仍需确保相应的资源在适当的时机释放以避免资源泄漏或不必要的占用。 最终这样的修改有助于提高渲染流程的稳定性同时减少不必要的冗余检查使代码逻辑更加清晰高效。 评估这个锁实现并撤销它 在实现 LockAsset 和 UnlockAsset 机制时我们发现这套系统并不理想。尽管可以通过锁计数 (LockCount) 来跟踪资源的使用情况防止其被过早释放但这样的实现方式会引入额外的复杂性使代码变得更难维护。因此最终决定放弃这个方案转而采用更简单的方法让地表块 (Ground Chunk) 的位图资源始终保持常驻内存不能被驱逐。 具体原因分析 锁机制引入了额外的同步和管理负担 LockCount 需要在 LockAsset 时执行递增操作在 UnlockAsset 时执行递减操作。需要额外确保多线程访问时的正确性避免竞态条件。仅仅为了地表块的资源管理引入这样复杂的机制显得不值得。 地表块资源数量较少始终驻留的成本可接受 参与渲染的地表块数量有限占用的内存不会很大。这些资源依然可以通过流式加载方式引入但不会被自动释放从而确保渲染时始终可用。这样可以避免在关键时刻资源丢失导致渲染出错。 减少不必要的全局复杂度 其余大部分资源并不需要 LockCount 这样的管理方式专门为地表块引入它显得过于冗余。如果仅仅为了这一小部分代码逻辑而修改整个资源管理系统得不偿失。 最终决定 直接确保地表块位图资源始终常驻 (Resident)不能被自动驱逐。移除 LockCount 方案避免引入复杂的同步逻辑。代码整体保持简洁不额外增加管理负担。 这次调整意味着在未来的开发过程中我们不需要再额外担心地表块资源的丢失问题同时也避免了复杂的锁管理逻辑让代码维护变得更加简单高效。 game.h在 asset_state 中引入 AssetState_Locked 我们决定采用锁定资源 (Locked Resource) 的概念确保某些关键资源一旦加载后就不会被流式驱逐 (Streamed Out)。相比之前尝试的 LockCount 方案这种方法更加清晰和高效避免了不必要的同步和管理复杂性。 改进方案锁定资源 引入 Locked 标志确保资源不可驱逐 资源的 AssetState 结构中增加 Locked 状态。一旦某个资源被标记为 Locked它就不会被流式系统自动移除即使内存紧张也不会受影响。这样可以确保关键资源如地表块始终可用不会在某些时刻因为资源管理导致丢失。 修改 LoadAsset 逻辑允许设置最终状态 (FinalState) 在 LoadAsset 完成资源加载时不再只是简单地标记为 Loaded而是允许设置最终状态 (FinalState)。这样可以在加载某些特定资源时将其标记为 Locked防止被错误地回收或替换。这意味着开发者可以自由选择哪些资源需要始终驻留而哪些资源仍然可以被驱逐。 比 LockCount 更简单、可靠 不需要在 LockAsset 和 UnlockAsset 之间维护计数减少复杂性和潜在的竞态问题。资源管理系统不需要额外的同步操作只需要检查 Locked 标志即可。适用于所有需要长期保留的资源而不仅仅是地表块 (Ground Chunk) 位图。 最终决定 引入 Locked 标志确保某些资源不可驱逐。修改 LoadAsset 逻辑支持 FinalState 设置让特定资源自动锁定。避免 LockCount 方案减少同步开销提高代码可读性和可维护性。 这一方案兼顾了灵活性和稳定性可以确保关键资源始终可用同时保持代码的简洁性和高效性。 为 load_asset_work 添加 asset_state FinalState game.cpp评估 DEBUGLoadBMP 的功能并考虑下一步 我们目前需要解决资源驱逐Eviction的问题但在真正处理这部分之前可能更适合先整理资源结构Structural Organization特别是位图Bitmap管理。 现状分析 当前资源加载方式 目前的 LoadBitmap 逻辑是直接读取整个文件然后分配内存加载资源并直接在分配的内存上操作。这意味着没有复杂的管理逻辑所有资源在加载后都保持可用状态系统不会自动回收或调整内存使用。问题缺乏智能管理方式无法灵活驱逐或缓存资源。 资源数量和内存占用 目前资源占用较小暂时不会面临严重的内存压力。未来游戏的资源总量可能较大特别是未压缩的高分辨率资源可能会超过 4GB需要考虑内存管理策略。低端设备可能不会加载最高质量的资源因此整体负载可能有所不同。 改进方向 优先整理资源结构 在正式实现资源驱逐前我们应该先完成资源的结构化管理使资源组织更合理。建立一张全局资源表General Resource Table用于存储所有位图的元数据Bitmap Metadata以便后续管理和查询。这样可以让资源管理更加系统化而不仅仅是简单的加载和存储。 未来内存管理优化 资源驱逐的核心在于合理的资源生命周期管理需要建立一套缓存和回收策略。可以考虑引入**LRULeast Recently Used最近最少使用**或其他缓存管理算法智能地回收不常用的资源。但在当前阶段我们暂时不急于实现这一点而是先让资源表变得更完整。 结论 短期目标先完善资源表结构确保所有位图资源有明确的存储位置和管理方式。中期目标在资源表的基础上引入缓存管理和智能驱逐策略以优化内存占用。长期目标根据实际游戏需求调整资源管理策略使其兼顾性能和灵活性。 当前我们不会立即投入资源驱逐的开发而是优先完成位图资源的结构化整理确保后续的内存管理可以基于稳固的框架进行扩展。 game.h扩展 game_asset_id 的概念使其更通用 我们目前的目标是扩展游戏资源 IDGame Asset ID的概念使其不仅适用于位图Bitmap而是成为一个更加通用的资源管理结构。 现有资源分类 目前资源大致可以分为两类 普通资源组Array-Based Assets 例如草地Grass、石头Stone、地表材质Turf等这些资源本质上是同类型资源的数组可以随机选取或循环使用。这种类型的资源需要以数组的形式进行索引和管理以便动态选择不同的变体Variations。 方向相关资源Directional Assets 例如角色Hero的位图这些资源不仅仅是一组静态图片还涉及方向Facing Direction。例如角色的朝向可能包括上、下、左、右每个方向可能还有多个帧或者不同的状态如行走、攻击等。这些资源需要有更复杂的索引方式以确保正确匹配角色的朝向和动作状态。 改进方向 重新定义 game_asset_id 结构 目前 game_asset_id 仅仅用于索引单个位图而我们希望它能够表示更通用的资源类型包括资源数组和方向关联资源。可能需要增加额外的字段例如 资源类型Type标明该资源是单一资源、数组资源还是方向相关资源。索引值Index用于区分同类资源中的不同变体。附加信息Metadata例如方向信息、动画帧编号等。 统一管理不同类别的资源 设计一套通用的资源管理结构使得数组资源和方向资源可以使用统一的方式进行管理和查询。可能的方案包括 使用哈希表Hash Table或数组Array存储资源索引加快查找速度。增加资源组Asset Group概念用于存放同类资源并支持变体切换。增加状态机支持用于管理角色等动态资源确保正确选择动画帧。 总结 我们目前的计划是扩展 game_asset_id使其不仅能表示单一位图资源还能支持数组型资源和方向型资源从而提高资源管理的灵活性和可扩展性。 引入 asset_bitmap_info 我们目前的目标是引入一个新的概念来描述特定的资源类型特别是针对草地Grass数组等类似的资源。 目标 需要一种新的结构来描述这些资源的基本属性类似于一个标签Label或标识符Descriptor。这个结构应该能够区分不同的资源类型同时保留必要的位图信息而不是直接依赖 LoadedBitmap 结构。这个新结构不会存储具体的内存信息如 Pitch 和 Memory 地址因为这些信息只与已经加载到内存中的资源相关而不是资源的基础描述。 方案 定义新的资源标识结构 可能的命名方案 asset_bitmap_infoBitmapDescriptorMapInfo 这个结构的作用是存储资源的元数据例如 宽度Width高度Height对齐方式Alignment Percentage 但它不会存储 内存 Pitch内存指针Memory Pointer 这些信息只会在资源实际加载时存在。 在 RenderGroup 中使用这个新结构 目前 RenderGroup 使用 LoadedBitmap但我们需要让它依赖更抽象的描述信息而不是直接依赖 LoadedBitmap。LoadedBitmap 只在真正需要绘制的时候才被访问而不是用于存储基础信息。 在加载过程中应用 当资源被请求时先通过新结构获取资源的描述信息。当资源实际需要加载到内存时才真正调用 LoadedBitmap。这样可以让资源管理更加清晰同时避免存储不必要的信息。 总结 我们计划引入一个新的资源描述结构用于存储资源的基本属性如尺寸、对齐方式但不包括内存相关的信息。这将使得 RenderGroup 以及整体的资源管理更加清晰和高效。 引入 asset_tag 在新的资源描述结构BitmapDescriptor 或 GameAsset_BitmapLabel中除了基本的位图属性如宽度、高度、对齐方式之外我们还需要添加一些额外的元数据特别是机械属性Mechanical Properties或标签Tags。 引入资产标签Asset Tag 为了更灵活地描述资源可以引入**资产标签Asset Tag**的概念。 资产标签可以用于分类资源或者为资源附加一些特定的游戏逻辑属性。资产标签可能以 键值对Key-Value 形式存储 标签Tag资源的属性名称如 “GroundType”、“Material”值Value该属性的具体值如 “Grass”、“Stone” 数据结构示例 为了管理这些标签我们可以在 BitmapDescriptor 中添加类似以下字段 struct BitmapDescriptor {int Width;int Height;float AlignmentPercentage;int FirstTagIndex; // 指向标签列表的索引int TagCount; // 该资源的标签数量 };同时我们需要一个全局标签存储比如 struct AssetTag {int TagID; // 资产标签的标识符int Value; // 资产标签的值 }; AssetTag AssetTagList[MAX_TAGS]; // 全局存储所有的标签这样每个 BitmapDescriptor 只需要存储索引和数量而不必直接持有所有标签数据从而减少内存占用。 使用方式 存储标签 例如我们有一个草地资源它可以带有标签 Type TerrainMaterial Grass 在 AssetTagList 中存储AssetTagList[0] { TagID_Type, Value_Terrain }; AssetTagList[1] { TagID_Material, Value_Grass };在 BitmapDescriptor 中BitmapDescriptor GrassDescriptor; GrassDescriptor.Width 128; GrassDescriptor.Height 128; GrassDescriptor.FirstTagIndex 0; GrassDescriptor.TagCount 2;查询资源标签 通过 FirstTagIndex 和 TagCount可以遍历 AssetTagList获取该资源的所有标签信息。例如for (int i GrassDescriptor.FirstTagIndex; i GrassDescriptor.FirstTagIndex GrassDescriptor.TagCount; i) {PrintTag(AssetTagList[i]); // 打印标签信息 }总结 添加了标签系统使得资源可以附带机械属性或游戏逻辑信息。使用索引存储标签避免每个资源直接持有大量数据提高管理效率。可以灵活扩展适用于不同类型的资源例如地形、角色、物品等。 讨论创建一个提供代码语义信息的资产表 想要实现的是创建一个资产表这个表可以让代码读取并了解每个资产的具体信息。目的是能够标明每个资源的类型和特征尤其是一些用于地面构建的资源。通过这种方式可以清楚地标记出哪些资源代表的是石质表面哪些是草地表面甚至为每种表面类型定义一些额外的属性。 具体来说像草地或石材这样的资源可以有不同的标记用来表示它们在游戏中的用途。比如草地资源可能需要附加一些额外信息如草的种类、高度等而石质表面则需要不同的描述。 计划的下一步是写使用代码通过这段代码可以查看如何实际操作这些资源数据并观察如何在实际使用中发挥作用。这样做的目的是确认是否可以通过这种方式来管理资产特别是通过表格方式来归类和标记不同类型的资源。 接下来的步骤是进入**地面构建Ground Chunk**的部分利用表格化的结构去验证和操作这些标记的资源看看它们如何在实际场景中应用。 game.cpp讨论世界生成代码如何使用这些语义信息 在地面构建Ground Chunk的部分代码中使用了随机种子来进行随机选择。这段代码通过随机选择的方式决定将哪些元素放入地面中。比如随机选择草地或石块或者其他装饰元素。具体来说代码通过随机种子来生成一个初始序列然后在多个选项中做出选择。 然而这样的随机选择方式可能不足以满足某些特定需求。如果我们想要更加精准地控制地面构建尤其是根据地理区域来确定选择可能就不能仅仅依赖于随机选择。例如地面上的草地类型应该根据当前区域的特点来决定如果在高草区可能就会选择高草如果是在短草区就避免选择高草。通过这种方式能够使地面构建更加符合环境的逻辑。 因此虽然目前的做法是通过随机选择来填充地面元素但可以考虑根据环境的不同而做出更合适的选择以确保地面的布局更加符合实际的自然环境。这意味着可能需要从简单的随机选择转变为根据具体条件如区域类型做出决策。 资产查看艺术资产 目前在可用的艺术资源中可能无法完全模拟所需的地面构建效果尤其是在不同草地类型的选择上。虽然可以通过缩放现有的艺术资源来模拟不同的地面元素但这种方法可能无法达到预期的效果。因此需要查看现有的资源来判断是否可以满足需求。 在处理“草丛”类资源时可能需要更多的艺术资源。目前的资源中关于“岩石”部分倒是有一些可以用作参考的素材比如平坦的岩石和一些更加圆润的岩石。这些资源可以作为模拟不同地形的基础但目前缺少的艺术资源可能会限制进一步的测试。因此可能需要寻找或创建更多的艺术资源以便更好地进行地面构建的模拟和测试。 game.cpp引入 PickBest根据给定标准对资产进行排序 为了有效地组织和处理资源首先需要对资源进行标签分类。假设所有的资产都被按某种方式组织在一个资产池中我们可以遍历这些资产并根据标签对它们进行排序。具体的实现思路是首先定义一个标签列表然后通过遍历每个资产的标签计算标签之间的差异并根据某些权重进行排序。 具体来说可以通过以下步骤 初始化标签索引对于每个资产获取其标签索引。可以通过记录标签的开始索引和结束索引来控制遍历范围。 计算标签差异对于每个标签计算标签值与目标标签值之间的差异。这个差异可以是标签值之间的直接差异也可以乘以某种权重得到加权的标签差异。 加权差异计算通过对每个标签的差异进行加权得到一个加权的差异值表示该标签与目标标签的匹配程度。 选择最优标签通过遍历所有标签计算加权差异值并找出最优的标签即差异最小的标签。 保存最优标签的索引一旦找到了最优标签就可以记录其索引并将该标签作为当前选择的标签。 这种方法通过使用加权差异来有效地对不同标签进行排序从而在大量资产中选择最合适的一个。 解释 PickBest 的工作原理 这种方法是非常缓慢的做法。基本的过程是用户会有一个特定的目标想要选择一个合适的资产。而这些资产都会通过标签进行标记这些标签代表了一些概念具体的标签数量和含义并不重要关键是代码和艺术资产都需要通过这些标签来进行标记和组织。 这些标签可以是一些特征比如“高度”然后与这些特征关联的数值可以是某个物体的高度等。为了实现这一目标代码会通过匹配向量和权重向量来进行操作。权重向量的作用是表示每个特征的重要性通常在0到1之间。特征值表示你想要匹配的目标值。之后系统会逐个检查每个资产与目标值的差距并通过权重来调整匹配的准确度。 通过这种方式系统能够选择出最符合条件的资产。具体做法是资产在加载时会附带上所有的标签系统会在加载时对这些标签进行检查。通过标签匹配系统就能知道当前要加载哪个图像或资产。 这种方法非常灵活允许我们从一组未曾见过的资产中选择最合适的一个它可以动态地根据不同条件选择匹配的资源。我没有想到其他更好的方法似乎这是一个非常有效且灵活的解决方案。 game.h引入 asset_group 在此基础上我们可以增加一些固定的区域以确保搜索过程不会太慢。具体来说我们可以设定每个纹理资源asset_group都有一些相关的属性或者甚至可以将它们分组在“资源组”中例如一个“资产组”并且每个资产组都会有一个ID类似于“英雄纹理”这样的分类。 这样资产组之间的匹配可以更加层次化这样就能更加高效地进行搜索避免不必要的遍历。例如可以给每个资产组附加一些标签然后在进行搜索时只需关注与这些标签相关的资产组而不必遍历所有的纹理资源。通过这种方式能有效地缩小搜索范围提高查找匹配资源的效率。 这种方法的核心是通过对资源进行分组和分类减少每次搜索时需要处理的数据量从而加速整个过程。 使其编译通过并暂时搁置 现在我打算先到这里因为至少目前来看我觉得还需要再深入探索一下再做决定。我们快接近直播的结束了所以我只是想先把它放到这儿然后可以在明天继续讨论。现在我们可以进入问答环节因为时间差不多了。 在 PickBest 中计算差异时是否需要其他类型的衰减 在“PickBest”过程中是否希望使用其他类型的假设来计算差异可能取决于具体情况。在某些情况下可能并不关心这些假设的差异但如果需要的话当然是可以添加其他类型的差异计算方式的。 编译为 64 位时不应该使用 _InterlockedCompareExchange64 吗 我们注意到在为64位系统编译时有人提出应该使用“InterlockedCompareExchange64”这样的原子操作但我们对此有些疑惑不太确定为什么要这样做。我们在思考这是否跟性能优化有关或者是其他原因。因为我们正在处理的值只有32位所以我们不太明白为什么需要用到64位的“InterlockedCompareExchange64”。我们感觉在这个特定的情况下32位的操作似乎就足够了但又不确定这样想是否正确。 具体来说我们的困惑有以下几点首先有人提到“InterlockedCompareExchange64”可能是为了确保在64位环境下操作的准确性或安全性但我们不清楚这背后的具体理由。其次我们考虑性能问题时觉得如果值本身只有32位使用64位操作会不会反而增加不必要的开销毕竟32位操作应该更直接、更高效。再次我们不确定这是否跟线程安全有关因为“Interlocked”系列函数通常用于多线程环境下的原子操作但我们手头的情况似乎没有明显说明需要64位操作来解决什么问题。 在你的例子中有 32 GB 未压缩资产和 2 GB 存储空间有什么技术可以判断是否会一次需要超过 2 GB 在这种情况下判断是否需要超过2GB的空间可以通过玩游戏并进行监控来实现。我们还可以通过合理保守的估计来做出判断比如对于我们的游戏来说知道它是2D游戏并且图形和过度绘制的数量是有限的我们可以大致估算出所需的空间上限。但实际上没有办法通过某种复杂的静态代码分析工具来精确证明最小或者最大需要的空间是多少以确保游戏中的任何一个帧都能够加载所有可能需要的资源。不过通常可以通过预留出足够多的空间来确保这个问题不会成为大问题。 从艺术家的角度总结一下你做了什么你是否为程序员和艺术家之间的合同增加了一点义务 从艺术家的角度来看是否有义务在编程人员和艺术家之间的合同中加入某种责任如果问题是指艺术家是否有义务一直工作到项目完成那么答案是否定的。艺术家是承包人而不是员工。如果艺术家想停止工作完全可以像员工辞职一样随时停止工作。通常情况下合同里不会要求艺术家必须在项目结束前继续工作这是很少见的。不过有时合同中会有支付条件比如完成项目后可以获得奖金或者涉及版税时只有到达一定条件才能获得版税这类情况偶尔会出现但这并不常见。因此问题所问的内容不太明确不太明白问题的真正意图是什么。 如果无法移除锁定的资源那流式加载它们的意义何在与直接预加载相比这不会限制环境多样性吗 如果不能将资源从内存中驱逐出去那么进行流式加载的意义何在而且这是否会限制环境的多样性 实际上这并不会限制环境的多样性因为这里讨论的只是地面块ground chunks。组成地面纹理的资源数量即使你有多达半个GB的纹理图流式加载依然能够很好地工作。而且地面纹理的种类数量也不会太庞大估计最多可能是256KB甚至是64MB的纹理数据都不算多。因此流式加载在这种情况下完全没有问题。而且我觉得代码的开销可能会稍微麻烦一些但这并不会成为问题。 至于为什么依然要使用流式加载而不是一次性加载所有内容是因为这样可以避免加载画面。玩游戏时我个人比较喜欢的是游戏能够立即启动而不是让玩家等着加载所有的地面块数据即使其中一半或者更多的地面数据在很长一段时间内不会用到比如玩家很久以后才会到冰雪区域这时候才需要冰雪相关的纹理。我不喜欢浪费玩家的时间让他们等待那些当前并不需要的资源。因此我希望所有的资源都能流式加载即使有些资源可能永远也不会被加载出来这样可以确保代码逻辑的正确性。 在调用 LoadAssetWork 的 PlatformAddEntry 之前不应该先完全填充 Work 吗 应该在调用平台的加载资源入口之前确保工作完全完成吗 是的确实应该确保资源加载工作已经完成再调用平台的加载入口。如果资源的文件名和将来的任务安排有关考虑到这些因素非常重要。纹理bitmap应该按正确的方式对齐以确保不出现问题。如果所有的资源都是文件形式那每个资源都应有正确的文件处理和对齐方式以确保工作顺利进行。 game.cpp在 LoadAsset 中将 PlatformAddEntry 移到 switch 语句之后 哦刚才那个错误感谢指出。那完全是错误的根本不应该发生。我没有意识到会是那样完全弄错了。那部分代码应该在下面。抱歉感谢指出这个问题我也不清楚为什么会那样可能是我在复制粘贴时弄错了。那部分肯定不应该是这样。你完全正确应该确保资源加载工作完成后再执行。 我可能错过了你现在能设置内存使用的硬性限制吗例如支持低内存机器 目前启动时只做了一次内存分配之后就不会再做其他分配因此实际上我们只使用了分配的内存量。虽然这样可以支持低内存的机器但这个限制目前并不特别有意义因为我们还没有真正的艺术资源因此即使内存被分配了实际上也并没有被大量占用。真正能够设置硬性内存使用限制的时机应该是当我们完成了资源流式加载并且能够进行资源驱逐的时候这时才可以更精确地管理和限制内存使用。 在之前的节目中你实现了双线性过滤。你会更进一步实现mipmapping和三线性过滤吗 关于是否要实现 Mipmap 和 Trilinear Filtering实际上并不需要。由于我们使用的是 2D 平面投影并没有涉及到真正的视差问题因此并不需要进行 Trilinear Filtering。只需要确保使用的是已缩放的、经过双线性过滤的纹理避免使用 Trilinear Filtering。 至于 Mipmap虽然在当前的架构中实现 Mipmap 是免费的只需要切换纹理图集的大小即可但考虑到我们通常不会大幅度缩放纹理一般不会超过 2 倍因此实现 Mipmap 对我们没有实际好处反而可能浪费内存。如果以后发现大规模缩放导致渲染质量不好我们可能会在绘制时根据目标大小选择适当的纹理版本这时就可以使用 Mipmap。 总结来说当前没有计划修改渲染管线也不会引入 Trilinear Filtering除非有特殊需求需要处理大规模的缩放问题。 从文件中加载的资产会以与地面块相同的方式存储和移除吗 目前关于是否将从文件加载的资源与地面块一起进行排序和驱逐的问题尚未明确。由于地面块的方案目前还比较粗糙驱逐机制是有人临时添加进去的因此并没有经过深入的思考和优化。未来可能会对这一部分进行更多的设计和完善但目前还不清楚具体的处理方式。 为什么只用 .bmp 目前游戏中只加载BMP格式的图像是一个临时方案。这是因为BMP格式非常容易加载方便用于演示如何使加载功能正常工作。将来所有的艺术资源都不会再以BMP格式加载而是会通过一个自定义的包文件加载。这些包文件将包含我们自己设计的图像格式并且可能会进行压缩例如使用LZ算法等。最终游戏不再使用BMP文件而是直接加载我们设计的专有格式。这种方式是为了简化资源管理提高游戏的性能和灵活性。 你做的移除工作基本上是垃圾回收吗 资源的驱逐机制与垃圾回收不同。垃圾回收是通过检测哪些资源不再使用并将其移除。而资源驱逐则是基于虚拟内存的概念目的是在内存空间有限的情况下保持最常用的资源。所有游戏中的资源都是在使用中的只是内存有限无法一次性加载所有资源。 具体来说系统会有一个虚拟的32GB位图基础然后分配2GB的物理内存空间。在这2GB空间内系统会根据当前使用的资源优先加载最可能被使用的资源。如果某个资源不再需要系统会将其从物理内存中驱逐腾出空间给其他更需要的资源。这个过程类似虚拟内存的操作目的是确保物理内存中始终存放的是当前最需要的资源而不是通过垃圾回收机制判断资源是否不再使用。 我们会使用 AMD 头发物理吗 游戏将完全以头发为基础构建所有的角色、地面、树木等都会由头发构成。主角本身就是一个由头发组成的存在整个世界也是由各种颜色的头发构建可能主角有黑色头发而敌人可能是金色头发。这种设计不仅仅是为了美观而是通过头发这一素材来传达深层的主题尤其是关于种族问题的反思。 具体来说这个设定旨在通过头发这一元素探索种族之间的差异和冲突以此作为对种族主义的回应和表达。游戏中的头发物理学即发丝的动态效果也将成为其中一个重要的机制帮助传递这一主题。虽然这个设定看似有些荒诞但其背后的目标是通过虚拟世界中的“头发”来触及和探讨更深刻的社会问题。 “AMD hair physics”指的是AMDAdvanced Micro Devices开发的一种名为 TressFX 的实时毛发物理模拟技术。这项技术主要用于视频游戏中通过利用GPU图形处理器的强大计算能力模拟和渲染角色头发或其他类似毛发的物体如毛皮或草的动态效果。简单来说它让游戏角色的头发看起来更真实能随着风、重力或角色动作自然摆动而不是像早期游戏中那样僵硬或简单地贴在模型上。 具体含义和原理 TressFX技术这是AMD推出的一种开源软件库基于DirectX 11和DirectCompute能够处理成千上万根独立发丝的物理模拟。每根发丝被建模为带有多个连接点的链条可以受到外部力量如风、重力或头部运动的影响而移动同时还包括碰撞检测确保发丝不会穿过彼此或角色的身体、衣服等固体表面。“Hair Physics”这里的“physics”物理指的是模拟头发运动时的真实物理特性比如下垂、摆动、卷曲甚至在特定环境下如雨中变湿变重的反应。这种技术极大提升了游戏画面的真实感尤其是在角色设计上。AMD的贡献AMD通过其Graphics Core Next架构优化了TressFX使其能在AMD Radeon显卡上高效运行。首个广泛应用的例子是2013年的《古墓丽影》Tomb Raider游戏中劳拉·克劳馥的头发通过TressFX实现了动态效果成为当时的技术亮点。 为什么重要 在游戏开发中头发一直是个难题。早期的游戏要么给角色戴帽子如马里奥要么用静态贴图来简化处理。而TressFX的出现让头发渲染进入实时物理模拟阶段不仅提升了视觉效果也为玩家带来更沉浸的体验。虽然它对性能有一定要求尤其在老硬件上可能会降低帧率但随着显卡性能提升这种技术逐渐普及。 与其他技术的对比 Nvidia HairWorksNvidia也推出了类似技术HairWorks作为其GameWorks套件的一部分。与TressFX相比HairWorks使用Tessellation曲面细分来增强细节但在AMD显卡上的性能不如TressFX在自家硬件上优化得好。TressFX是开源的MIT许可证而HairWorks是专有技术。应用范围TressFX后来不仅限于头发还扩展到毛皮、草等模拟版本更新如TressFX 4.0甚至支持DirectX 12进一步提升了兼容性和效率。 总结来说“AMD hair physics”就是AMD通过TressFX技术实现的游戏毛发物理效果代表了现代游戏图形技术中对真实感追求的一个重要方向。如果你是在某个游戏或技术讨论中看到这个词通常就是在说这种提升视觉和物理真实性的方法 如果通过改变像素将位图变成黑白你会有两份位图副本吗如果有两份你会删除一份吗 如果将位图通过修改像素转换为黑白图像是否会有两个副本如果有两个副本是否需要删除其中一个这种情况下位图就像是一个缓存。位图本质上可以看作是某个昂贵过程的结果它可能是手动绘制的也可能是通过复杂的程序生成的。位图就是这个过程的缓存保存了该图像应该是什么样子。 在游戏中我们可能会遇到一些需要对位图进行程序性修改的情况比如通过修改某些像素的颜色。如果这些修改非常快速可以在每帧渲染时进行那么可能不需要保存两个副本而是在渲染时实时计算。但是如果这些修改非常耗时可能会更有效率地将其缓存为新的位图并且在需要的时候加载。 具体来说例如对于英雄角色通常使用三种精灵图叠加的方式来表现可能每一帧都会重新组合这些精灵图而不需要缓存它们。相比之下地面块则更复杂需要更多的逻辑和变化因此它们通常会被缓存。这是一个关于“何时动态生成何时缓存”的决策问题通常需要通过性能分析来决定哪种方法更高效。 为什么人们这么在意垃圾回收 垃圾回收的概念对于很多人来说非常重要但在某些情况下觉得这个概念没有太大用处。垃圾回收通常是为了自动管理内存回收不再使用的资源避免内存泄漏等问题。尽管如此有些情况下开发者并不太关心垃圾回收尤其是当程序员自己能够很好地管理内存时自动垃圾回收反而可能成为不必要的复杂性。对于这些人来说垃圾回收可能看起来像是多余的因为他们可以手动控制资源的分配和释放这样反而能更精确地管理内存并优化程序性能。所以有人认为垃圾回收并不是每个项目都需要的工具。 为什么使用打包文件而不是 bmp是什么让它“更好” 使用pak文件而不是单独的文件有几个原因。首先个人更倾向于不让游戏在硬盘上生成大量的文件因为这种情况会显得很杂乱无章。只需要一个可执行文件和一个数据文件这样的结构简单清晰方便复制和管理避免了繁琐和麻烦的文件管理问题。 其次pak文件能够有效减少操作系统文件句柄的使用。如果每个资源文件都单独打开系统就需要为每个文件分配一个文件句柄而使用pak文件只需要打开一个文件句柄系统知道你将持续访问该文件而不需要反复打开和关闭文件。这样操作系统能够更好地管理资源避免了频繁的文件操作。 另外pak文件可以提高效率。它允许系统以页的形式读取文件这有助于更高效地加载和使用数据。通过pak文件的背景加载和按需读取系统可以优化资源的使用并且可以确保文件不会被意外删除或修改因为pak文件本身会锁定。 最后pak文件的索引机制也是一个很大的优势。文件中的内容是通过一个简单的表格来管理的这个表格存储了所有资源的位置和偏移量而不是像传统的文件管理那样依赖字符串来寻找资源路径。这种方式让资源的访问更加高效避免了不必要的字符串操作。 总的来说pak文件在实际使用中比单独的文件管理要好得多从文件管理、性能、数据读取到资源访问的效率都是更加优越的因此使用pak文件是一个更优的选择。 早些时候有人问为什么在操作系统虚拟内存上重新实现虚拟内存。我们这样做只是为了获得“更多”虚拟空间吗 早些时候有人问过为什么要在虚拟内存上重新发明虚拟内存原因是因为依赖虚拟内存非常不可靠。你无法预测操作系统何时会加载页面也不知道哪个线程会触发分页整个过程充满了不确定性。因此通常情况下不建议依赖操作系统的虚拟内存来进行重要的资源流式加载操作因为这样做往往会带来很多问题。 另外你甚至无法确定操作系统是否支持那么大的虚拟内存。有可能机器并没有配置足够的虚拟内存比如32GB的虚拟内存如果是这样的话程序可能就会失败。因此依赖操作系统的虚拟内存作为资源流加载的解决方案并不是一个理想的选择。 虽然可以考虑使用内存映射文件来解决这个问题但这会带来新的复杂性。内存映射文件通常是压缩过的所以你还需要第二个内存映射文件来解压数据。这样就增加了额外的复杂度而不是简单地让操作系统通过虚拟内存来处理所有的操作。因此虚拟内存分页处理涉及到解压等操作操作系统并没有处理这些额外的步骤导致这种方案变得不那么简单。 地面块在使用 GPU 时会预 这段话主要讨论了几个技术和设计决策涉及渲染、存储格式、云存储、以及如何处理游戏存档等问题。具体内容总结如下 GPU渲染与CPU渲染的比较 讨论了使用GPU渲染而非CPU渲染的优势特别是对笔记本电脑等设备来说使用GPU渲染更节能而使用CPU渲染可能会更耗电。尽管软件渲染效果不错但GPU渲染可以提供更好的性能和更低的功耗。 保存文件与资源包文件的区别 资源包文件pak file通常是只读的因此游戏的存档文件无法放在pak文件中。存档文件需要存储在可以写入的地方比如操作系统的某些目录避免与资源文件混淆。存档文件的位置选择不仅是出于平台合规的需要还为了便于云存储功能的实现。比如当使用Steam等平台时游戏存档可能需要云同步功能不能放入pak文件中。 关于DRM数字版权管理的看法 尽管对DRM持有一定反感作者并不反对在平台如Steam上发布游戏只要提供用户选择购买和存储方式的自由。他认为DRM限制了用户自由阻碍了他们按自己希望的方式获取和使用游戏。但如果平台允许禁用DRM用户依然可以自由复制和使用游戏这样就没有问题。 GPU与CPU渲染的区别 GPU渲染与CPU渲染在操作上有所不同GPU需要设置硬件管理和低级别的控制相比之下CPU渲染则是完全不同的工作流。涉及到像Vulkan和Direct3D 12等API时GPU渲染要求更复杂的操作和管理但这也能提供更高效的图形处理。 开发进度和展望 提到目前仍处于开发的初期阶段尽管软件渲染已经非常高效但最终可能会引入GPU渲染功能。随着项目的进展开发团队预计会逐渐实现更高效的渲染流程以应对未来的需求。 结束语 开发者感谢观众的参与并提到接下来的计划是继续开发资源存储格式可能会涉及到资源包文件的处理。希望在后续的更新中能够完成这部分工作尽早解决资源存储问题确保项目顺利推进。
http://www.hkea.cn/news/14484269/

相关文章:

  • 镇江市建设局网站智能免费建站
  • 网站结构优化包括什么常州微信网站建设效果
  • 东莞专业微网站建设价格域名制作网站吗
  • 雏鸟app网站推广免费建站的站点网站
  • vue使用于网站开发腾讯云网站模板
  • 西安优秀的集团门户网站建设企业推推蛙seo
  • icp网站域名怎么填写深圳哪个区最好
  • 网站设计怎么做才好看百度收录要多久
  • 网站外链多的危害ip分享网站
  • 网站开发进度安排文档建筑设计网上接单
  • 做门票的网站做网站要多少
  • 个人购物网站备案新手做站必看 手把手教你做网站
  • 国家企业信用信息系统(河南)郑州网站建设专业乐云seo
  • 全球电子商务网站排名wordpress 增加用户字段
  • 网站制作说明网站网页设计怎么收费
  • 网站建设分几个阶段html个人博客网页设计
  • 秀米网站怎么做推文二手房出售信息
  • 手机端网站建站如何用易语言做网站辅助
  • vps建设网站别人访问不了网站seo顾问
  • 泉州最好的网站建设公司ui设计app界面模板
  • 智慧团建网站首页关于网站建设的入门书
  • 南宁如何做百度的网站推广个人简历模板范文手写
  • 陇南市响应式网站建设com网站域名注册
  • wordpress建站什么意思高密做网站的价格
  • 赣州做网站设计找哪家自己怎么注册域名
  • 宅男做网站做企业网站需要收费吗
  • 做设计有必要买素材网站会员员工管理网站模板
  • 广东省著名商标在什么网站做自己写的网页怎么发布
  • 深圳网站建设一尘互联简易的建筑人才网
  • 网站备案证书黄页网页的推广网站