import { _decorator, Component, Node, director, resources, instantiate, Prefab, js } from 'cc'; const { ccclass, property } = _decorator; @ccclass('PanelBase') export class PanelBase extends Component { protected isOpen: boolean = false; public async open(): Promise { if (this.isOpen) return; this.node.active = true this.isOpen = true; this.onOpen(); } static async LoadPanel(prefabPath: string, parentNode: Node) { let panelNode: Node = null resources.load(prefabPath, Prefab, (err, prefabAsset) => { if (prefabAsset) { const node = instantiate(prefabAsset); node.parent = parentNode; node.getComponent(PanelBase).open() panelNode = node } else { console.error(`Failed to load UI prefab: ${prefabPath}`); } }); await this.waitUntil(() => panelNode != null); return panelNode } static waitUntil(condition: () => boolean): Promise { return new Promise((resolve) => { const checkCondition = () => { if (condition()) { resolve(); // 条件成立,结束等待 } else { // 条件不成立,继续轮询 requestAnimationFrame(checkCondition); } }; checkCondition(); // 开始检查条件 }); } public close(): void { console.log("close panel", this.node.name) if (!this.isOpen) return; if (!this.isValid) return; if (this.node && this.node.parent) { this.node.removeFromParent(); this.node.destroy(); this.isOpen = false; this.onClose(); } } protected getPrefabPath(): string { let panelName = js.getClassName(this) return `ui/${panelName}`; // 生成预制件路径 } protected onOpen(): void { // 子类可以重写此方法以执行打开后的操作 } protected onClose(): void { // 子类可以重写此方法以执行关闭后的操作 } }