C++读取游戏共享内存时lapTimeInSeconds值异常变动的解决求助
解决圈速值异常变动的问题
核心问题分析
- 浮点数精确比较的陷阱:
graphic.normalizedCarPosition == 1几乎无法精准命中,往往会在圈完成后、游戏重置计时的下一轮循环才触发判断,此时读取到的iCurrentTime已经被重置。 - 共享内存的实时更新:游戏进程会持续修改共享内存中的数据,从计算
lapTimeInSeconds到触发圈完成判断的这段时间里,iCurrentTime可能已经被游戏重置。
解决方案
1. 替换浮点数精确比较为范围判断
用接近1.0的区间来检测圈完成,确保在计时未被重置的第一时间触发逻辑:
if (graphic.normalizedCarPosition >= 0.999f && graphic.normalizedCarPosition <= 1.001f)
2. 提前保存圈速快照
在判断圈完成前,把当前计算好的圈速值存入临时变量,确保后续文件名生成等操作使用的是固定值,不受共享内存更新影响:
// 在判断圈完成前,先保存当前圈速的快照 float finalLapTime = lapTimeInSeconds;
3. 增加防重复触发标志(可选)
避免同一圈多次触发保存逻辑,添加一个全局/静态标志位:
static bool lapCompletedFlag = false; // 在循环开头重置标志(当车辆回到起点时) if (graphic.normalizedCarPosition <= 0.001f) { lapCompletedFlag = false; } // 圈完成判断 if (!lapCompletedFlag && graphic.normalizedCarPosition >= 0.999f) { lapCompletedFlag = true; // 后续处理逻辑... }
修改后的完整代码片段
while (true) { //........code........ // laptime float lapTimeInSeconds = static_cast<float>(graphic.iCurrentTime) / 1000.0f; printf("\rLAP: %.3f", lapTimeInSeconds); // save memcpy(&save_struct.lapTime_seconds, &lapTimeInSeconds, 4); memcpy(&save_struct.normalizedCarPosition, &graphic.normalizedCarPosition, 4); memcpy(&save_struct.gaz, &physics.gaz, 4); memcpy(&save_struct.brake, &physics.brake, 4); memcpy(&save_struct.speedKmh, &physics.speedKmh, 4); memcpy(&save_struct.steerAngle, &physics.steerAngle, 4); memcpy(&save_struct.gear, &physics.gear, 4); memcpy(&save_struct.carCoordiantes, &graphic.carCoordiantes, sizeof(save_struct.carCoordiantes)); // write bytes into the file fwrite(&save_struct, sizeof(SaveStruct), 1, saveFile); // 提前保存圈速快照 float finalLapTime = lapTimeInSeconds; // 用范围判断替代精确等于,避免错过时机 if (graphic.normalizedCarPosition >= 0.999f && graphic.normalizedCarPosition <= 1.001f) { fclose(saveFile); printf("\nFINAL LAP TIME: %.3f\n", finalLapTime); uint8_t seconds = static_cast<int>(finalLapTime) % 60; uint8_t minutes = static_cast<int>(finalLapTime) / 60; uint16_t millisecond = static_cast<uint16_t>((finalLapTime - (minutes * 60 + seconds)) * 1000); std::string final_file_name = "laps/lap-" + std::to_string(lapCount) + "-" + std::to_string(minutes) + "-" + std::to_string(seconds) + "-" + std::to_string(millisecond) + ".lap"; rename("laps/lap-not-completed.lap", final_file_name.c_str()); lapCount++; saveFile = fopen("laps/lap-not-completed.lap", "wb"); } }
额外优化建议
- 用
static_cast替代C风格强制转换,提升代码可读性和类型安全性。 - 确保共享内存的读取是线程安全的,如果游戏和你的程序是多线程,可能需要加锁保护共享内存的读取操作。
内容的提问来源于stack exchange,提问作者obeid salem
相关产品推荐
相关产品推荐

