fix: 修复组件销毁时事件解绑和空引用问题并添加任务界面

- 在多个组件的onDestroy方法中添加节点有效性检查,防止无效节点上解绑事件
- 修复MissionComp中任务启动逻辑,改为通过UI打开方式触发MissionStart事件
- 添加新的任务界面(UIID.Mission)及相关配置
- 修复MissionCardComp中Map未初始化导致的空引用问题
- 优化按钮事件绑定和解绑逻辑,增加空值检查
This commit is contained in:
panw
2026-05-08 14:14:38 +08:00
parent c70e3bbb4d
commit 07aec09283
16 changed files with 19665 additions and 19580 deletions

View File

@@ -176,6 +176,11 @@ export class MissionCardComp extends CCComp {
/** 组件销毁时解绑所有事件并清理英雄信息面板 */
onDestroy() {
if (this.cards_chou && this.cards_chou.isValid) {
this.cards_chou.off(NodeEventType.TOUCH_START, this.onDrawTouchStart, this);
this.cards_chou.off(NodeEventType.TOUCH_END, this.onDrawTouchEnd, this);
this.cards_chou.off(NodeEventType.TOUCH_CANCEL, this.onDrawTouchCancel, this);
}
this.unbindEvents();
this.clearHeroInfoPanels();
}
@@ -205,6 +210,17 @@ export class MissionCardComp extends CCComp {
missionData.hero_max_num = FightSet.HERO_MAX_NUM;
missionData.hero_extend_max_num = FightSet.HERO_MAX_NUM + 1;
}
// 确保 Map 被正确初始化
if (!this.heroInfoItems) {
this.heroInfoItems = new Map();
}
// 确保卡牌组件列表已被正确缓存
if (!this.cardComps || this.cardComps.length === 0) {
this.cacheCardComps();
}
this.clearHeroInfoPanels();
this.layoutCardSlots();
this.clearAllCards();
@@ -362,9 +378,11 @@ export class MissionCardComp extends CCComp {
oops.message.off(GameEvent.UseHeroCard, this.onUseHeroCard, this);
oops.message.off(GameEvent.UseSpecialCard, this.onUseSpecialCard, this);
oops.message.off(GameEvent.CardPoolUpgrade, this.onCardPoolUpgrade, this);
this.cards_chou?.off(NodeEventType.TOUCH_START, this.onDrawTouchStart, this);
this.cards_chou?.off(NodeEventType.TOUCH_END, this.onDrawTouchEnd, this);
this.cards_chou?.off(NodeEventType.TOUCH_CANCEL, this.onDrawTouchCancel, this);
if (this.cards_chou && this.cards_chou.isValid) {
this.cards_chou.off(NodeEventType.TOUCH_START, this.onDrawTouchStart, this);
this.cards_chou.off(NodeEventType.TOUCH_END, this.onDrawTouchEnd, this);
this.cards_chou.off(NodeEventType.TOUCH_CANCEL, this.onDrawTouchCancel, this);
}
// this.cards_up?.off(NodeEventType.TOUCH_START, this.onUpgradeTouchStart, this);
// this.cards_up?.off(NodeEventType.TOUCH_END, this.onUpgradeTouchEnd, this);
// this.cards_up?.off(NodeEventType.TOUCH_CANCEL, this.onUpgradeTouchCancel, this);
@@ -700,26 +718,35 @@ export class MissionCardComp extends CCComp {
/** 全量分发给4槽每个槽位是否接收由 CardComp 自己判断(锁定可跳过) */
private dispatchCardsToSlots(cards: CardConfig[]) {
if (!this.cardComps) return;
for (let i = 0; i < this.cardComps.length; i++) {
const accepted = this.cardComps[i].applyDrawCard(cards[i] ?? null);
mLogger.log(this.debugMode, "MissionCardComp", "dispatch card", {
index: i,
card: cards[i]?.uuid ?? 0,
accepted
});
if (this.cardComps[i]) {
const accepted = this.cardComps[i].applyDrawCard(cards[i] ?? null);
mLogger.log(this.debugMode, "MissionCardComp", "dispatch card", {
index: i,
card: cards[i]?.uuid ?? 0,
accepted
});
}
}
}
/** 系统清空4槽用于任务切换 */
private clearAllCards() {
this.cardComps.forEach(comp => comp.clearBySystem());
if (!this.cardComps) return;
this.cardComps.forEach(comp => {
if (comp) comp.clearBySystem();
});
}
private layoutCardSlots() {
if (!this.cardComps) return;
const count = this.cardComps.length;
if (count === 0) return;
for (let i = 0; i < count; i++) {
this.cardComps[i].setSlotPosition(this.cardsPos[i]);
if (this.cardComps[i]) {
this.cardComps[i].setSlotPosition(this.cardsPos[i]);
}
}
mLogger.log(this.debugMode, "MissionCardComp", "layout card slots", {
count,
@@ -956,12 +983,14 @@ export class MissionCardComp extends CCComp {
}
private clearHeroInfoPanels() {
this.heroInfoItems.forEach(item => {
if (item.node && item.node.isValid) {
item.node.destroy();
}
});
this.heroInfoItems.clear();
if (this.heroInfoItems) {
this.heroInfoItems.forEach(item => {
if (item && item.node && item.node.isValid) {
item.node.destroy();
}
});
this.heroInfoItems.clear();
}
if (this.hero_info_node && this.hero_info_node.isValid) {
for (let i = this.hero_info_node.children.length - 1; i >= 0; i--) {
const child = this.hero_info_node.children[i];
@@ -1149,6 +1178,13 @@ export class MissionCardComp extends CCComp {
this.clearHeroInfoPanels();
this.resetButtonScale(this.cards_chou);
// this.resetButtonScale(this.cards_up);
this.node.destroy();
// 关键:在 reset/销毁 时将 Map 置空,彻底切断引用
this.heroInfoItems = null as any;
this.cardComps = [] as any;
if (this.node && this.node.isValid) {
this.node.destroy();
}
}
}