{"record":{"id":"155b3324f29c0097","repo":"babalae/better-genshin-impact","slug":"3","errorCode":null,"errorMessage":"切换角色：连续 3 次未检测到合法角色卡片","messagePattern":"切换角色：连续 3 次未检测到合法角色卡片","errorType":"exception","errorClass":"PartySetupFailedException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/GameTask/Common/Job/SwitchCharacterStateMachineTask.cs","lineNumber":1402,"sourceCode":"            for (var attempt = 1; attempt <= EmptyCardDetectionRetryCount; attempt++)\n            {\n                using var capture = CaptureToRectArea(true);\n                using var gridRegion = capture.DeriveCrop(gridRoi);\n                var cards = DetectCharacterCards(\n                    gridRegion.SrcMat, out var rejectedCount, out var connectedComponentCount);\n                lastDetectedCardCount = cards.Count;\n                LogCardDetection(cards, rejectedCount, connectedComponentCount, attempt);\n                if (cards.Count < expectedTeamCount)\n                {\n                    if (attempt < EmptyCardDetectionRetryCount)\n                    {\n                        await Delay(200, ct);\n                        continue;\n                    }\n\n                    if (cards.Count == 0)\n                    {\n                        throw new PartySetupFailedException(\"切换角色：连续 3 次未检测到合法角色卡片\");\n                    }\n                }\n\n                foreach (var card in cards\n                             .OrderBy(card => card.CardRect.Y)\n                             .ThenBy(card => card.CardRect.X)\n                             .Take(expectedTeamCount))\n                {\n                    using var avatar = gridRegion.SrcMat.SubMat(card.AvatarRect);\n                    var candidate = recognizer.Recognize(avatar);\n                    _logger.LogDebug(\n                        \"切换角色：RECT({X},{Y},{Width},{Height})，角色={CharacterName}，score={Score:0.000}\",\n                        card.CardRect.X,\n                        card.CardRect.Y,\n                        card.CardRect.Width,\n                        card.CardRect.Height,\n                        candidate.CharacterName,\n                        candidate.Score);","sourceCodeStart":1384,"sourceCodeEnd":1420,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/GameTask/Common/Job/SwitchCharacterStateMachineTask.cs#L1384-L1420","documentation":"Inside the card-detection retry loop of RecognizeTeamSlotsFromCharacterList, DetectCharacterCards returned zero accepted cards for all EmptyCardDetectionRetryCount (3) attempts on the final pass. With no cards the avatar set is empty, so recognition is aborted.","triggerScenarios":"On attempt == EmptyCardDetectionRetryCount, cards.Count < expectedTeamCount and cards.Count == 0 — every card candidate was rejected by DetectCharacterCards (rejectedCount/connectedComponentCount logged via LogCardDetection) across all 3 passes.","commonSituations":"The character grid ROI CharacterGridRoi1080(24,86,766,743) is wrong for the current layout so the crop is blank; DetectCharacterCards' connected-component/threshold heuristics reject everything under different lighting or UI theming; the list is filtered to a state with no visible cards; capture scale mismatch.","solutions":["Inspect the LogCardDetection output (rejectedCount, connectedComponentCount) to see if candidates exist but are rejected — tune DetectCharacterCards thresholds.","Confirm CharacterGridRoi1080 still bounds the grid in the current game version.","Verify capture resolution/assetScale so the grid crop is sized as expected.","If the grid legitimately has fewer than expected cards, reconcile expectedTeamCount rather than requiring 3."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await switchTask.Start(...); }\ncatch (PartySetupFailedException ex) when (ex.Message.Contains(\"未检测到合法角色卡片\"))\n{ _logger.LogError(ex, \"角色卡片检测失败：检查网格 ROI 与 DetectCharacterCards 阈值\"); }","preventionTips":["Keep CharacterGridRoi1080 aligned with the current grid bounds.","Tune DetectCharacterCards thresholds against current lighting/theming.","Ensure capture scale produces correctly sized grid crops."],"tags":["party-setup","opencv","card-detection","computer-vision","switch-character"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}