babalae/better-genshin-impact · critical · Exception
灰度分层地图 {LayerId} 读取失败
Error message
灰度分层地图 {LayerId} 读取失败 What it means
Companion to error 406, thrown when reading the gray map image for a template-match layer. Same caveat: Bv.ImRead is non-nullable, so the '?? throw' is unreachable; the actual failure for a missing <LayerId>_gray.webp (or .png when IsOverSize) is a FileNotFoundException from File.OpenRead inside ImRead, not this custom exception.
Source
Thrown at BetterGenshinImpact/GameTask/Common/Map/Maps/Base/BaseMapLayerByTemplateMatch.cs:42
public float Top { get; set; } = 0;
public float Left { get; set; } = 0;
public bool IsOverSize { get; set; } = false;
[JsonIgnore]
public required FastSqDiffMatcher CoarseColorMatcher; // 小尺寸彩图
[JsonIgnore]
public Mat FineGrayMap = new Mat(); // 大尺寸灰度图
public void LoadLayer(string layerDir)
{
SpeedTimer speedTimer = new($"加载 {LayerId} 地图图片");
var colorMapFileName = LayerId + "_color" + ".webp";
var colorMapPath = Path.Combine(layerDir, colorMapFileName);
var coarseColorMap = Bv.ImRead(colorMapPath)?? throw new Exception($"彩色分层地图 {LayerId} 读取失败");
speedTimer.Record("精确匹配用彩图");
CoarseColorMatcher = new FastSqDiffMatcher(coarseColorMap, new Size(52, 52));
var grayMapFileName = LayerId + "_gray" + (IsOverSize ? ".png" : ".webp");
var grayMapPath = Path.Combine(layerDir, grayMapFileName);
FineGrayMap = Bv.ImRead(grayMapPath, ImreadModes.Grayscale)?? throw new Exception($"灰度分层地图 {LayerId} 读取失败");
speedTimer.Record("粗匹配用灰度图");
speedTimer.DebugPrint();
}
public static List<BaseMapLayerByTemplateMatch> LoadLayers(SceneBaseMapByTemplateMatch sceneBaseMap)
{
var layers = new List<BaseMapLayerByTemplateMatch>();
var layerDir = Path.Combine(Global.Absolute(@"Assets\Map\"), sceneBaseMap.Type.ToString());
if (!Directory.Exists(layerDir))
{
return layers;
}
var jsonFiles = Directory.GetFiles(layerDir, "*.json", SearchOption.AllDirectories);
foreach (var jsonFile in jsonFiles)
{
var json = File.ReadAllText(jsonFile);
var tempLayers = JsonSerializer.Deserialize<List<BaseMapLayerByTemplateMatch>>(json) ?? throw new Exception("Failed to deserialize JSON.");
layers.AddRange(tempLayers);View on GitHub (pinned to a7cb36712d)
Solutions
- Confirm <LayerId>_gray.webp (or <LayerId>_gray.png when IsOverSize=true) exists for each layer.
- Ensure the IsOverSize flag in the JSON matches which gray-image extension is shipped.
- Guard with File.Exists(grayMapPath) before ImRead so the intended error message is actually produced.
Example fix
// before
FineGrayMap = Bv.ImRead(grayMapPath, ImreadModes.Grayscale)?? throw new Exception($"灰度分层地图 {LayerId} 读取失败");
// after
if (!File.Exists(grayMapPath)) throw new Exception($"灰度分层地图 {LayerId} 读取失败: 缺少 {grayMapPath}");
FineGrayMap = Bv.ImRead(grayMapPath, ImreadModes.Grayscale); Defensive patterns
Strategy: validation
Validate before calling
var grayMapPath = Path.Combine(layerDir, LayerId + "_gray" + (IsOverSize ? ".png" : ".webp"));
if (!File.Exists(grayMapPath)) throw new FileNotFoundException($"缺少灰度地图: {grayMapPath}", grayMapPath); Prevention
- Ensure IsOverSize in JSON matches the shipped gray-image extension.
- Validate all referenced image paths exist at startup.
When it happens
Trigger: LoadLayer computes grayMapPath = Path.Combine(layerDir, LayerId + "_gray" + (IsOverSize ? ".png" : ".webp")) and calls Bv.ImRead(grayMapPath, ImreadModes.Grayscale). Missing file → File.OpenRead throws before this message could ever be reached.
Common situations: IsOverSize flag in the JSON is true but only a .webp (not .png) gray map exists, or vice versa; LayerId mismatch; partial asset deployment.
Related errors
- 彩色分层地图 {LayerId} 读取失败
- 地图数据加载失败,文件: {kpFilePath}
- 地图数据加载失败,文件: {matFilePath}
- 地图数据加载失败,文件: {kpFilePath}
- 分层地图数据文件夹中中存在无法解析的文件名: {fileName}
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/bcd627559f4382c0.
Report an issue: GitHub.