From d72e16115055bde02ce286dd78330bac1b9a47b6 Mon Sep 17 00:00:00 2001 From: panw Date: Wed, 13 May 2026 17:27:22 +0800 Subject: [PATCH] =?UTF-8?q?refactor(map):=20=E4=BC=98=E5=8C=96=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=8D=A1=E7=89=87=E8=8B=B1=E9=9B=84=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 重构注释排版,统一说明战场节点对应规则 2. 调整英雄位置更新流程:先清理失效单位,再批量处理位置变更,最后统一刷新信息 3. 修复多英雄同帧位置变动可能导致的数据覆盖问题 --- assets/script/game/map/MissionCardComp.ts | 80 +++++++++++++---------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/assets/script/game/map/MissionCardComp.ts b/assets/script/game/map/MissionCardComp.ts index 78dc79b9..409cf3a8 100644 --- a/assets/script/game/map/MissionCardComp.ts +++ b/assets/script/game/map/MissionCardComp.ts @@ -903,21 +903,14 @@ export class MissionCardComp extends CCComp { // MoveComp.ts 里的 assignment: // lanePriority = [1, 0, 2]; // slotIndex 0->中路(1), 1->上路(0), 2->下路(2) - // laneIdx = lanePriority[slotIndex % 3]; - // col = Math.floor(slotIndex / 3); - // model.lane = laneIdx; - // model.lane_index = col; + // laneIdx = lanePriority[slotIndex % 3]; // priority: 1(中), 0(上), 2(下) + // model.lane = laneIdx; // - // 节点顺序预期: - // node_index=1 对应 1排上路 (lane=0, lane_index=0) - // node_index=2 对应 1排中路 (lane=1, lane_index=0) - // node_index=3 对应 1排下路 (lane=2, lane_index=0) - // node_index=4 对应 2排上路 (lane=0, lane_index=1) - // node_index=5 对应 2排中路 (lane=1, lane_index=1) - // node_index=6 对应 2排下路 (lane=2, lane_index=1) - // 因为 1排中路 在视觉上是最前面的,实际按路排(上/中/下): - const laneOrder = model.lane === 0 ? 0 : (model.lane === 1 ? 1 : 2); - const expectedNodeIndex = model.lane_index * 3 + laneOrder + 1; + // 所以当: + // model.lane = 0 (上路), model.lane_index = 0 -> 对应 node_index = 1 + // model.lane = 1 (中路), model.lane_index = 0 -> 对应 node_index = 2 + // model.lane = 2 (下路), model.lane_index = 0 -> 对应 node_index = 3 + const expectedNodeIndex = model.lane_index * 3 + model.lane + 1; mLogger.log(this.debugMode, "MissionCardComp", `ensureHeroInfoPanel calculation: lane=${model.lane}, lane_index=${model.lane_index} -> expectedNodeIndex=${expectedNodeIndex}`); @@ -955,6 +948,8 @@ export class MissionCardComp extends CCComp { private refreshHeroInfoPanels() { const removeKeys: number[] = []; + + // 1. 先将已死亡的英雄移除,释放占用的节点 this.heroInfoItems.forEach((item, eid) => { if (!item.node || !item.node.isValid) { removeKeys.push(eid); @@ -965,32 +960,45 @@ export class MissionCardComp extends CCComp { removeKeys.push(eid); return; } - - // 检查英雄是否改变了位置 (lane 或 lane_index 发生了变化) - const laneOrder = item.model.lane === 0 ? 0 : (item.model.lane === 1 ? 1 : 2); - const expectedNodeIndex = item.model.lane_index * 3 + laneOrder + 1; - - if (item.comp.node_index !== expectedNodeIndex) { - // 如果位置变了,需要转移到新的节点上 - const newComp = this.cachedHInfoComps.get(expectedNodeIndex); - if (newComp) { - // 隐藏旧节点 - item.node.active = false; - - // 转移到新节点 - item.comp = newComp; - item.node = newComp.node; - item.node.active = true; - item.comp.bindData(eid, item.model); - item.comp.setBattlePhase(this.isBattlePhase); - } - } - - this.updateHeroInfoPanel(item); }); for (let i = 0; i < removeKeys.length; i++) { this.heroInfoItems.delete(removeKeys[i]); } + + // 2. 然后再处理所有存活英雄的位置转移和信息刷新 + // 如果有多个英雄在同一帧发生位置变动,可能会出现目标节点暂时被其他还没更新的英雄占用的情况, + // 为了防止数据互相覆盖,我们先将需要转移的英雄收集起来。 + const needTransfer: Array<{eid: number, expectedNodeIndex: number}> = []; + + this.heroInfoItems.forEach((item, eid) => { + const expectedNodeIndex = item.model.lane_index * 3 + item.model.lane + 1; + if (item.comp.node_index !== expectedNodeIndex) { + needTransfer.push({eid, expectedNodeIndex}); + } else { + this.updateHeroInfoPanel(item); + } + }); + + // 执行位置转移 + for (const transfer of needTransfer) { + const item = this.heroInfoItems.get(transfer.eid); + if (!item) continue; + + const newComp = this.cachedHInfoComps.get(transfer.expectedNodeIndex); + if (newComp) { + // 隐藏旧节点 + item.node.active = false; + // 转移到新节点 + item.comp = newComp; + item.node = newComp.node; + item.node.active = true; + item.comp.bindData(transfer.eid, item.model); + item.comp.setBattlePhase(this.isBattlePhase); + + this.updateHeroInfoPanel(item); + } + } + this.updateHeroNumUI(false, false); }