fix(map, mission): 修复槽位布局与重置位置异常问题
1. 为英雄组件clearBySystem增加位置重置判断,避免未初始化时将槽位重置到原点 2. 重构任务面板槽位布局逻辑,统一使用三等分水平布局 3. 新增布局辅助方法,处理预制体Widget组件冲突问题 4. 禁用多个冗余的任务预制体节点,清理无效引用
This commit is contained in:
@@ -6029,7 +6029,7 @@
|
|||||||
"node": {
|
"node": {
|
||||||
"__id__": 348
|
"__id__": 348
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": false,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 354
|
"__id__": 354
|
||||||
},
|
},
|
||||||
@@ -7599,7 +7599,7 @@
|
|||||||
"node": {
|
"node": {
|
||||||
"__id__": 456
|
"__id__": 456
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": false,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 462
|
"__id__": 462
|
||||||
},
|
},
|
||||||
@@ -8571,7 +8571,7 @@
|
|||||||
"node": {
|
"node": {
|
||||||
"__id__": 522
|
"__id__": 522
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": false,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 528
|
"__id__": 528
|
||||||
},
|
},
|
||||||
@@ -9562,7 +9562,7 @@
|
|||||||
"node": {
|
"node": {
|
||||||
"__id__": 590
|
"__id__": 590
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": false,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 596
|
"__id__": 596
|
||||||
},
|
},
|
||||||
@@ -14349,7 +14349,7 @@
|
|||||||
"__id__": 530
|
"__id__": 530
|
||||||
},
|
},
|
||||||
"equip_refresh": {
|
"equip_refresh": {
|
||||||
"__id__": 530
|
"__id__": 464
|
||||||
},
|
},
|
||||||
"shop_refresh": {
|
"shop_refresh": {
|
||||||
"__id__": 598
|
"__id__": 598
|
||||||
|
|||||||
@@ -578,11 +578,16 @@ export class CHeroComp extends CCComp {
|
|||||||
/**
|
/**
|
||||||
* 系统清槽:任务开始/结束时强制重置。
|
* 系统清槽:任务开始/结束时强制重置。
|
||||||
* 清空数据与 UI 并隐藏节点。
|
* 清空数据与 UI 并隐藏节点。
|
||||||
|
*
|
||||||
|
* 仅在 setSlotPosition 初始化过静止位置后才恢复位置,
|
||||||
|
* 否则 restPosition 为默认 (0,0,0),会把所有槽位重置到中心。
|
||||||
*/
|
*/
|
||||||
clearBySystem() {
|
clearBySystem() {
|
||||||
this.cardData = null;
|
this.cardData = null;
|
||||||
this.isPurchased = false;
|
this.isPurchased = false;
|
||||||
this.node.setPosition(this.restPosition);
|
if (this.hasFixedBasePosition) {
|
||||||
|
this.node.setPosition(this.restPosition);
|
||||||
|
}
|
||||||
this.applyEmptyUI();
|
this.applyEmptyUI();
|
||||||
this.node.active = false;
|
this.node.active = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
* - smc.vmdata.mission_data —— 局内数据(coin / hero_num / hero_max_num)
|
* - smc.vmdata.mission_data —— 局内数据(coin / hero_num / hero_max_num)
|
||||||
*/
|
*/
|
||||||
import { mLogger } from "../common/Logger";
|
import { mLogger } from "../common/Logger";
|
||||||
import { _decorator, instantiate, Label, Node, NodeEventType, Prefab, Tween, tween, Vec3, UITransform } from "cc";
|
import { _decorator, instantiate, Label, Node, NodeEventType, Prefab, Tween, tween, Vec3, UITransform, Widget } from "cc";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
import { GameEvent } from "../common/config/GameEvent";
|
import { GameEvent } from "../common/config/GameEvent";
|
||||||
@@ -155,10 +155,13 @@ export class MissionCardComp extends CCComp {
|
|||||||
/** 英雄数量显示节点(含 icon + num 子节点) */
|
/** 英雄数量显示节点(含 icon + num 子节点) */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
hero_num_node: Node = null!
|
hero_num_node: Node = null!
|
||||||
/**技能刷新按钮节点 */
|
/** 技能刷新按钮节点 */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
skill_refresh: Node = null!
|
skill_refresh: Node = null!
|
||||||
|
|
||||||
|
/** 槽位水平坐标(屏幕 720 三等分,卡片 230,列宽 240) */
|
||||||
|
private readonly slotPosX: number[] = [-240, 0, 240];
|
||||||
|
|
||||||
/** 装备刷新按钮节点 */
|
/** 装备刷新按钮节点 */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
equip_refresh: Node = null!;
|
equip_refresh: Node = null!;
|
||||||
@@ -221,7 +224,6 @@ export class MissionCardComp extends CCComp {
|
|||||||
onLoad() {
|
onLoad() {
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
this.cacheCardComps();
|
this.cacheCardComps();
|
||||||
this.layoutCardSlots();
|
|
||||||
this.initCardsPanelPos();
|
this.initCardsPanelPos();
|
||||||
this.initPanelLayout();
|
this.initPanelLayout();
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "onLoad init", {
|
mLogger.log(this.debugMode, "MissionCardComp", "onLoad init", {
|
||||||
@@ -542,6 +544,9 @@ export class MissionCardComp extends CCComp {
|
|||||||
// 根据物品数量设置列表面板高度
|
// 根据物品数量设置列表面板高度
|
||||||
this.resizeListBox(this.shopBoxNode, targetCount);
|
this.resizeListBox(this.shopBoxNode, targetCount);
|
||||||
|
|
||||||
|
// 三等分水平布局
|
||||||
|
this.layoutSlotsHorizontal(this.itemCardComps);
|
||||||
|
|
||||||
// 默认显示商店面板
|
// 默认显示商店面板
|
||||||
if (this.shopPanNode) {
|
if (this.shopPanNode) {
|
||||||
this.shopPanNode.active = true;
|
this.shopPanNode.active = true;
|
||||||
@@ -556,6 +561,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
/**
|
/**
|
||||||
* 确保药品槽位数量足够。
|
* 确保药品槽位数量足够。
|
||||||
* 优先复用现有槽位,不足时从 itemPrefab 实例化补充。
|
* 优先复用现有槽位,不足时从 itemPrefab 实例化补充。
|
||||||
|
* 实例化后立即按 slotPosX 定位,避免堆叠在 (0,0)。
|
||||||
*/
|
*/
|
||||||
private ensureItemSlots(targetCount: number) {
|
private ensureItemSlots(targetCount: number) {
|
||||||
if (!this.shopBoxNode || !this.itemPrefab) return;
|
if (!this.shopBoxNode || !this.itemPrefab) return;
|
||||||
@@ -570,6 +576,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
const comp = node.getComponent(ItemListComp) || node.addComponent(ItemListComp);
|
const comp = node.getComponent(ItemListComp) || node.addComponent(ItemListComp);
|
||||||
this.itemCardComps.push(comp);
|
this.itemCardComps.push(comp);
|
||||||
}
|
}
|
||||||
|
this.layoutSlotsHorizontal(this.itemCardComps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 清空商品列表(复用槽位,仅清空数据) */
|
/** 清空商品列表(复用槽位,仅清空数据) */
|
||||||
@@ -1015,6 +1022,9 @@ export class MissionCardComp extends CCComp {
|
|||||||
// 根据物品数量设置列表面板高度
|
// 根据物品数量设置列表面板高度
|
||||||
this.resizeListBox(this.equipsBoxNode, targetCount);
|
this.resizeListBox(this.equipsBoxNode, targetCount);
|
||||||
|
|
||||||
|
// 三等分水平布局
|
||||||
|
this.layoutSlotsHorizontal(this.equipCardComps);
|
||||||
|
|
||||||
// 默认显示装备面板
|
// 默认显示装备面板
|
||||||
if (this.equipsPanNode) {
|
if (this.equipsPanNode) {
|
||||||
this.equipsPanNode.active = true;
|
this.equipsPanNode.active = true;
|
||||||
@@ -1029,6 +1039,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
/**
|
/**
|
||||||
* 确保装备槽位数量足够。
|
* 确保装备槽位数量足够。
|
||||||
* 优先复用现有槽位,不足时从 equipPrefab 实例化补充。
|
* 优先复用现有槽位,不足时从 equipPrefab 实例化补充。
|
||||||
|
* 实例化后立即按 slotPosX 定位,避免堆叠在 (0,0)。
|
||||||
*/
|
*/
|
||||||
private ensureEquipSlots(targetCount: number) {
|
private ensureEquipSlots(targetCount: number) {
|
||||||
if (!this.equipsBoxNode || !this.equipPrefab) return;
|
if (!this.equipsBoxNode || !this.equipPrefab) return;
|
||||||
@@ -1043,6 +1054,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
const comp = node.getComponent(EquipListComp) || node.addComponent(EquipListComp);
|
const comp = node.getComponent(EquipListComp) || node.addComponent(EquipListComp);
|
||||||
this.equipCardComps.push(comp);
|
this.equipCardComps.push(comp);
|
||||||
}
|
}
|
||||||
|
this.layoutSlotsHorizontal(this.equipCardComps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 清空装备列表(复用槽位,仅清空数据) */
|
/** 清空装备列表(复用槽位,仅清空数据) */
|
||||||
@@ -1088,6 +1100,9 @@ export class MissionCardComp extends CCComp {
|
|||||||
// 根据技能数量设置列表面板高度
|
// 根据技能数量设置列表面板高度
|
||||||
this.resizeListBox(this.skillBoxNode, targetCount);
|
this.resizeListBox(this.skillBoxNode, targetCount);
|
||||||
|
|
||||||
|
// 三等分水平布局
|
||||||
|
this.layoutSlotsHorizontal(this.skillCardComps);
|
||||||
|
|
||||||
// 默认显示技能面板
|
// 默认显示技能面板
|
||||||
if (this.skillPanNode) {
|
if (this.skillPanNode) {
|
||||||
this.skillPanNode.active = true;
|
this.skillPanNode.active = true;
|
||||||
@@ -1102,6 +1117,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
/**
|
/**
|
||||||
* 确保技能槽位数量足够。
|
* 确保技能槽位数量足够。
|
||||||
* 优先复用现有槽位,不足时从 sCardPrefab 实例化补充。
|
* 优先复用现有槽位,不足时从 sCardPrefab 实例化补充。
|
||||||
|
* 实例化后立即按 slotPosX 定位,避免堆叠在 (0,0)。
|
||||||
*/
|
*/
|
||||||
private ensureSkillSlots(targetCount: number) {
|
private ensureSkillSlots(targetCount: number) {
|
||||||
if (!this.skillBoxNode || !this.sCardPrefab) return;
|
if (!this.skillBoxNode || !this.sCardPrefab) return;
|
||||||
@@ -1112,10 +1128,15 @@ export class MissionCardComp extends CCComp {
|
|||||||
// 补充实例化不足的槽位
|
// 补充实例化不足的槽位
|
||||||
while (this.skillCardComps.length < targetCount) {
|
while (this.skillCardComps.length < targetCount) {
|
||||||
const node = instantiate(this.sCardPrefab);
|
const node = instantiate(this.sCardPrefab);
|
||||||
|
// 先禁用根节点 Widget 再挂到父节点:
|
||||||
|
// 否则 addChild 激活当帧 lateUpdate 时 Widget 会对齐覆盖 position
|
||||||
|
const widget = node.getComponent(Widget);
|
||||||
|
if (widget) widget.enabled = false;
|
||||||
this.skillBoxNode.addChild(node);
|
this.skillBoxNode.addChild(node);
|
||||||
const comp = node.getComponent(SCardComp) || node.addComponent(SCardComp);
|
const comp = node.getComponent(SCardComp) || node.addComponent(SCardComp);
|
||||||
this.skillCardComps.push(comp);
|
this.skillCardComps.push(comp);
|
||||||
}
|
}
|
||||||
|
this.layoutSlotsHorizontal(this.skillCardComps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 清空技能卡槽(复用槽位,仅清空数据) */
|
/** 清空技能卡槽(复用槽位,仅清空数据) */
|
||||||
@@ -1232,6 +1253,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
if (this.cardPrefab && this.cards_node && this.cards_node.isValid) {
|
if (this.cardPrefab && this.cards_node && this.cards_node.isValid) {
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
const node = instantiate(this.cardPrefab);
|
const node = instantiate(this.cardPrefab);
|
||||||
|
// 先禁用根节点 Widget 再挂到父节点:
|
||||||
|
// 否则 addChild 激活当帧 lateUpdate 时 Widget 会对齐覆盖 position
|
||||||
|
const widget = node.getComponent(Widget);
|
||||||
|
if (widget) widget.enabled = false;
|
||||||
this.cards_node.addChild(node);
|
this.cards_node.addChild(node);
|
||||||
const comp = node.getComponent(CHeroComp) || node.addComponent(CHeroComp);
|
const comp = node.getComponent(CHeroComp) || node.addComponent(CHeroComp);
|
||||||
this.cardComps.push(comp);
|
this.cardComps.push(comp);
|
||||||
@@ -1246,6 +1271,8 @@ export class MissionCardComp extends CCComp {
|
|||||||
cardPrefabValid: this.cardPrefab.isValid
|
cardPrefabValid: this.cardPrefab.isValid
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 实例化后立即按 slotPosX 定位,避免堆叠在 (0,0)
|
||||||
|
this.layoutCardSlots();
|
||||||
} else {
|
} else {
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "cacheCardComps failed", {
|
mLogger.log(this.debugMode, "MissionCardComp", "cacheCardComps failed", {
|
||||||
cardPrefabValid: this.cardPrefab?.isValid,
|
cardPrefabValid: this.cardPrefab?.isValid,
|
||||||
@@ -1503,7 +1530,49 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private layoutCardSlots() {
|
private layoutCardSlots() {
|
||||||
// 布局由 cHero.prefab 根节点 Widget 约束控制,代码不再覆盖位置
|
// 走 CHeroComp.setSlotPosition,同步更新其 restPosition,
|
||||||
|
// 避免 clearBySystem 恢复位置时与布局结果不一致
|
||||||
|
for (let i = 0; i < this.cardComps.length && i < this.slotPosX.length; i++) {
|
||||||
|
const comp = this.cardComps[i];
|
||||||
|
if (comp && comp.node && comp.node.isValid) {
|
||||||
|
const widget = comp.node.getComponent(Widget);
|
||||||
|
if (widget) widget.enabled = false;
|
||||||
|
comp.setSlotPosition(this.slotPosX[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三等分水平布局:
|
||||||
|
* 按固定坐标数组 slotPosX 排列槽位,超出数量的槽位不处理。
|
||||||
|
*
|
||||||
|
* Why: 各卡池根节点的 Layout 组件已移除,槽位水平位置改由代码统一控制。
|
||||||
|
* 部分预制体根节点残留 Widget 组件(对齐父节点中心),
|
||||||
|
* 启用时会在 lateUpdate 覆盖代码设置的 position,需先禁用。
|
||||||
|
*
|
||||||
|
* @param comps 槽位组件数组(CHeroComp / EquipListComp / SCardComp / ItemListComp)
|
||||||
|
*/
|
||||||
|
private layoutSlotsHorizontal(comps: Array<CHeroComp | EquipListComp | SCardComp | ItemListComp>) {
|
||||||
|
for (let i = 0; i < comps.length && i < this.slotPosX.length; i++) {
|
||||||
|
const node = comps[i]?.node;
|
||||||
|
if (!node || !node.isValid) continue;
|
||||||
|
// 禁用根节点 Widget,防止其在对齐刷新时覆盖 position
|
||||||
|
const widget = node.getComponent(Widget);
|
||||||
|
if (widget) widget.enabled = false;
|
||||||
|
const pos = node.getPosition();
|
||||||
|
node.setPosition(this.slotPosX[i], pos.y, pos.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟一帧执行布局:
|
||||||
|
* 首次实例化的嵌套预制体在首帧会先恢复到原始位置,
|
||||||
|
* 等下一帧预制体初始化完成后再定位,避免首帧堆叠在 (0,0)。
|
||||||
|
*/
|
||||||
|
private layoutSlotsHorizontalDeferred(comps: Array<CHeroComp | EquipListComp | SCardComp | ItemListComp>) {
|
||||||
|
this.scheduleOnce(() => {
|
||||||
|
this.layoutSlotsHorizontal(comps);
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private playButtonPressAnim(node: Node | null) {
|
private playButtonPressAnim(node: Node | null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user