同步主站 Cocos 当前工程:关卡资源、运行脚本与打包工具。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -34,7 +34,7 @@ import { VisualAssets } from './visual/VisualAssets';
|
||||
import { resolveThemeId } from './theme/ThemeDatabase';
|
||||
import { LevelDisplay } from './level/LevelDisplay';
|
||||
import { mergeLevelConfigWithMapData } from './level/LevelConfigMerge';
|
||||
import { ensureEntityUILayer, findLevelChildByName, forEachLevelEntityNode, sortIsoTiles } from './level/TileLayout';
|
||||
import { ensureEntityUILayer, findLevelChildByName, forEachLevelEntityNode, primeIsoDrawOrder, sortIsoTiles } from './level/TileLayout';
|
||||
import { Movement } from './gameplay/Movement';
|
||||
import { tryLinkPlayerVehicle, tryLinkVehicleRider } from './controller/RideLink';
|
||||
import { GridSnapHelper } from './level/GridSnapHelper';
|
||||
@@ -73,6 +73,8 @@ export class GameController extends Component {
|
||||
|
||||
@property({ group: { name: '关卡切换', id: '1' }, type: CCInteger, displayName: '当前关卡', readonly: true })
|
||||
curLevelID = 1;
|
||||
/** 编辑器最近一次要求加载的关;过期回传不再通知,避免慢关握手错切 */
|
||||
private requestedLevelID = 0;
|
||||
|
||||
@property({ group: { name: '关卡切换', id: '1' }, displayName: '关卡范围', readonly: true })
|
||||
levelRangeHint = '1–80';
|
||||
@@ -105,8 +107,22 @@ export class GameController extends Component {
|
||||
private levelLoadSeq: Promise<void> = Promise.resolve();
|
||||
/** 倍速 1/2/4,作用于移动与角色动画 */
|
||||
gameSpeed = 1;
|
||||
|
||||
//终于完成了********PlayerLTH17/2026/9/12
|
||||
private creating = false;
|
||||
/** SwitchLevel 排队未完成:拦截并暂存 Player/Vehicle 指令,避免执行按钮 200ms 抢跑 */
|
||||
private levelBusy = false;
|
||||
private pendingLevelOps = 0;
|
||||
private pendingActorMsgs: Array<{ objectName: string; methodName: string; param?: string | number }> = [];
|
||||
/** 进关完成后的干净场景树,同关 SwitchLevel 按 Unity:销毁当前实例再 instantiate 这份缓存 */
|
||||
private levelSnapshot: Node | null = null;
|
||||
private levelSnapshotId = 0;
|
||||
/** 加载中只保留最后一次 SwitchLevel,避免连点排队重建 */
|
||||
private queuedLevelId: number | null = null;
|
||||
private instantResetGuard = false;
|
||||
private lastInstantResetAt = 0;
|
||||
private lastInstantResetId = 0;
|
||||
/** 已显示在场上、可以同关原地重置的关卡 ID(adopt 之后才写入) */
|
||||
private playableLevelId = 0;
|
||||
private curConfig: LevelConfig | null = null;
|
||||
private gridTypes = new Map<string, GridEntry>();
|
||||
private gridTypesForProps = new Map<string, GridEntry>();
|
||||
@@ -137,6 +153,7 @@ export class GameController extends Component {
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.disposeLevelSnapshot();
|
||||
if (GameController.instance === this) GameController.instance = null;
|
||||
}
|
||||
|
||||
@@ -284,6 +301,7 @@ export class GameController extends Component {
|
||||
if (typeof window !== 'undefined') {
|
||||
(window as unknown as { cocosIns?: typeof api }).cocosIns = api;
|
||||
(window as unknown as { unityInstance?: typeof api }).unityInstance = api;
|
||||
this.publishLevelReady(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,9 +320,19 @@ export class GameController extends Component {
|
||||
if (c) this.invoke(c, methodName, param);
|
||||
return;
|
||||
}
|
||||
if (this.shouldDeferActorMessage(objectName)) {
|
||||
if (methodName === 'CallMove' || methodName === 'callMove') {
|
||||
console.warn('[tfrh-reset] CallMove 被关卡重置拦住,稍后发出', { creating: this.creating, levelBusy: this.levelBusy });
|
||||
}
|
||||
this.pendingActorMsgs.push({ objectName, methodName, param });
|
||||
return;
|
||||
}
|
||||
if (methodName === 'CallMove' || methodName === 'callMove') {
|
||||
console.warn('[tfrh-reset] CallMove 立刻执行', { param, playableLevelId: this.playableLevelId, busy: this.levelBusy });
|
||||
}
|
||||
const node = this.findNodeByName(objectName);
|
||||
if (!node) {
|
||||
if (objectName === 'Player' && this.creating) return;
|
||||
if (objectName === 'Player' && (this.creating || this.levelBusy)) return;
|
||||
console.warn(`SendMessage: 未找到 ${objectName}`);
|
||||
return;
|
||||
}
|
||||
@@ -577,17 +605,37 @@ export class GameController extends Component {
|
||||
}
|
||||
for (const ch of [...this.mainLevelEntrance.children]) {
|
||||
if (!ch || ch.name === 'LineGrid') continue;
|
||||
if (ch.isValid) ch.destroy();
|
||||
if (!ch.isValid) continue;
|
||||
ch.active = false;
|
||||
ch.removeFromParent();
|
||||
ch.destroy();
|
||||
}
|
||||
} else if (this.curLevel?.isValid) {
|
||||
this.curLevel.active = false;
|
||||
this.curLevel.removeFromParent();
|
||||
this.curLevel.destroy();
|
||||
}
|
||||
this.curLevel = null;
|
||||
this.playableLevelId = 0;
|
||||
this.syncCurLevelRef();
|
||||
this.gridTypes.clear();
|
||||
this.gridTypesForProps.clear();
|
||||
this.groundCells.clear();
|
||||
this.borderCells.clear();
|
||||
this.disposeLevelSnapshot();
|
||||
}
|
||||
|
||||
/** 新关就绪后再卸旧关,避免执行/取消时闪出另一张地图 */
|
||||
private adoptLevelRoot(levelRoot: Node) {
|
||||
this.curLevel = levelRoot;
|
||||
this.playableLevelId = Number(this.curLevelID);
|
||||
if (!this.mainLevelEntrance?.isValid) return;
|
||||
for (const ch of [...this.mainLevelEntrance.children]) {
|
||||
if (!ch?.isValid || ch === levelRoot || ch.name === 'LineGrid') continue;
|
||||
ch.active = false;
|
||||
ch.removeFromParent();
|
||||
ch.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
confirmSwitchLevel(levelID?: number) {
|
||||
@@ -610,34 +658,110 @@ export class GameController extends Component {
|
||||
);
|
||||
}
|
||||
this.inputLevel = String(id);
|
||||
this.requestedLevelID = id;
|
||||
this.pendingActorMsgs = [];
|
||||
this.setLevelBusy(true);
|
||||
const inPlace = this.tryResetCurrentLevelInPlace(id);
|
||||
console.warn('[tfrh-reset] SwitchLevel', {
|
||||
id,
|
||||
playableLevelId: this.playableLevelId,
|
||||
curLevelID: this.curLevelID,
|
||||
inPlace,
|
||||
creating: this.creating,
|
||||
pendingLevelOps: this.pendingLevelOps,
|
||||
hasLevel: !!this.curLevel?.isValid,
|
||||
});
|
||||
if (inPlace) {
|
||||
this.setLevelBusy(false);
|
||||
return;
|
||||
}
|
||||
void this.loadLevel(id);
|
||||
}
|
||||
|
||||
loadLevel(levelID: number) {
|
||||
if (!this.ready && !this.mainLevelEntrance) {
|
||||
console.warn('[GameController] 尚未初始化');
|
||||
if (this.pendingLevelOps <= 0) this.setLevelBusy(false);
|
||||
return;
|
||||
}
|
||||
if (!this.mainLevelEntrance) {
|
||||
console.error('[GameController] mainLevelEntrance 未绑定');
|
||||
if (this.pendingLevelOps <= 0) this.setLevelBusy(false);
|
||||
return;
|
||||
}
|
||||
void this.enqueueLoadLevel(levelID, false);
|
||||
}
|
||||
|
||||
private enqueueLoadLevel(levelID: number, forceRestart: boolean) {
|
||||
this.queuedLevelId = levelID;
|
||||
if (this.tryResetCurrentLevelInPlace(levelID) && this.pendingLevelOps <= 0 && !this.creating) {
|
||||
this.queuedLevelId = null;
|
||||
this.setLevelBusy(false);
|
||||
return this.levelLoadSeq;
|
||||
}
|
||||
this.setLevelBusy(true);
|
||||
if (this.pendingLevelOps > 0) return this.levelLoadSeq;
|
||||
this.pendingLevelOps++;
|
||||
this.levelLoadSeq = this.levelLoadSeq
|
||||
.then(() => this.loadLevelNow(levelID, forceRestart))
|
||||
.catch((e) => console.error('[GameController] 关卡加载失败', e));
|
||||
.then(async () => {
|
||||
while (this.queuedLevelId != null) {
|
||||
const id = this.queuedLevelId;
|
||||
this.queuedLevelId = null;
|
||||
await this.loadLevelNow(id, forceRestart);
|
||||
}
|
||||
})
|
||||
.catch((e) => console.error('[GameController] 关卡加载失败', e))
|
||||
.finally(() => {
|
||||
this.pendingLevelOps = Math.max(0, this.pendingLevelOps - 1);
|
||||
if (this.queuedLevelId != null && this.pendingLevelOps <= 0) {
|
||||
void this.enqueueLoadLevel(this.queuedLevelId, forceRestart);
|
||||
return;
|
||||
}
|
||||
if (this.pendingLevelOps <= 0) this.setLevelBusy(false);
|
||||
});
|
||||
return this.levelLoadSeq;
|
||||
}
|
||||
|
||||
private async loadLevelNow(levelID: number, forceRestart: boolean) {
|
||||
if (levelID === this.curLevelID && this.curLevel?.isValid && this.curConfig) {
|
||||
await this.restartCurrentLevel();
|
||||
return;
|
||||
private shouldDeferActorMessage(objectName: string) {
|
||||
if (!this.levelBusy && !this.creating) return false;
|
||||
return objectName === 'Player' || objectName === 'Vehicle'
|
||||
|| /^Player[AB]\d$/.test(objectName) || /^Vehicle[AB]\d$/.test(objectName);
|
||||
}
|
||||
|
||||
private setLevelBusy(busy: boolean) {
|
||||
this.levelBusy = busy;
|
||||
this.publishLevelReady(!busy);
|
||||
if (!busy) this.flushPendingActorMsgs();
|
||||
}
|
||||
|
||||
private publishLevelReady(ready: boolean) {
|
||||
const apply = (target: { __tfrhLevelReady?: boolean; __tfrhLevelBusy?: boolean } | null) => {
|
||||
if (!target) return;
|
||||
target.__tfrhLevelBusy = !ready;
|
||||
target.__tfrhLevelReady = ready;
|
||||
};
|
||||
if (typeof window === 'undefined') return;
|
||||
apply(window as unknown as { __tfrhLevelReady?: boolean; __tfrhLevelBusy?: boolean });
|
||||
try {
|
||||
if (window.parent && window.parent !== window) {
|
||||
apply(window.parent as unknown as { __tfrhLevelReady?: boolean; __tfrhLevelBusy?: boolean });
|
||||
}
|
||||
} catch {
|
||||
/* 跨域 iframe 无法写父页,编辑器仍靠游戏内排队挡住抢跑 */
|
||||
}
|
||||
this.destroyCurLevel();
|
||||
}
|
||||
|
||||
private flushPendingActorMsgs() {
|
||||
if (!this.pendingActorMsgs.length) return;
|
||||
const queued = this.pendingActorMsgs;
|
||||
this.pendingActorMsgs = [];
|
||||
for (const msg of queued) {
|
||||
this.sendMessage(msg.objectName, msg.methodName, msg.param);
|
||||
}
|
||||
}
|
||||
|
||||
private async loadLevelNow(levelID: number, _forceRestart: boolean) {
|
||||
if (this.tryResetCurrentLevelInPlace(levelID)) return;
|
||||
await this.createNewLevel(levelID);
|
||||
}
|
||||
|
||||
@@ -657,26 +781,139 @@ export class GameController extends Component {
|
||||
console.log(`[GameController] 已刷新关卡 ${this.curLevelID} 贴图`);
|
||||
}
|
||||
|
||||
/** 重置玩家/道具,保留关卡砖块与背景,避免闪屏 */
|
||||
private async restartCurrentLevel() {
|
||||
if (!this.curLevel?.isValid || !this.curConfig || !this.mainLevelEntrance) {
|
||||
await this.createNewLevel(this.curLevelID);
|
||||
/**
|
||||
* 同关执行:只当场拉回出生点,不拆地图。不同 ID 就是不同地图,绝不以偏移折成同一关。
|
||||
*/
|
||||
private tryResetCurrentLevelInPlace(levelID: number): boolean {
|
||||
if (this.creating) return false;
|
||||
if (Number(levelID) !== Number(this.playableLevelId)) return false;
|
||||
if (!this.curLevel?.isValid || !this.curConfig) return false;
|
||||
this.queuedLevelId = null;
|
||||
this.resetCurrentLevelInPlace();
|
||||
return true;
|
||||
}
|
||||
|
||||
private resetCurrentLevelInPlace() {
|
||||
if (this.instantResetGuard) return;
|
||||
const id = Number(this.playableLevelId);
|
||||
const now = Date.now();
|
||||
if (id === this.lastInstantResetId && now - this.lastInstantResetAt < 50) {
|
||||
this.pendingActorMsgs = [];
|
||||
this.initData();
|
||||
return;
|
||||
}
|
||||
const config = this.curConfig;
|
||||
const levelRoot = this.curLevel;
|
||||
const tileNames = LevelDisplay.collectTileNames(config);
|
||||
await VisualAssets.ensureLevelAssetsReady(config, tileNames);
|
||||
await this.purgeDynamicEntities(levelRoot);
|
||||
const spawned = await this.spawnAllEntities(levelRoot, config);
|
||||
await this.finalizeEntityPresentation(levelRoot, config);
|
||||
this.instantResetGuard = true;
|
||||
try {
|
||||
this.restartCurrentLevelSync();
|
||||
this.lastInstantResetAt = Date.now();
|
||||
this.lastInstantResetId = id;
|
||||
} finally {
|
||||
this.instantResetGuard = false;
|
||||
}
|
||||
}
|
||||
|
||||
private captureLevelSnapshot(levelRoot: Node) {
|
||||
this.disposeLevelSnapshot();
|
||||
if (!levelRoot?.isValid) return;
|
||||
const snap = instantiate(levelRoot);
|
||||
snap.active = false;
|
||||
snap.removeFromParent();
|
||||
this.levelSnapshot = snap;
|
||||
this.levelSnapshotId = Number(this.curLevelID);
|
||||
}
|
||||
|
||||
private disposeLevelSnapshot() {
|
||||
if (this.levelSnapshot?.isValid) this.levelSnapshot.destroy();
|
||||
this.levelSnapshot = null;
|
||||
this.levelSnapshotId = 0;
|
||||
}
|
||||
|
||||
/** 对齐 Unity Addressables 二次 Instantiate:旧关卸掉,缓存树当场克隆出来。 */
|
||||
private replayFromSnapshot(): boolean {
|
||||
const snap = this.levelSnapshot;
|
||||
if (!snap?.isValid || this.levelSnapshotId !== Number(this.curLevelID) || !this.mainLevelEntrance) {
|
||||
return false;
|
||||
}
|
||||
const fresh = instantiate(snap);
|
||||
if (!fresh?.isValid) return false;
|
||||
fresh.active = false;
|
||||
GridSnapHelper.purgeRuntimeGrids(fresh);
|
||||
fresh.parent = this.mainLevelEntrance;
|
||||
fresh.setPosition(0, 0, 0);
|
||||
this.adoptLevelRoot(fresh);
|
||||
if (this.curConfig) this.applyMapDataFromConfig(this.curConfig);
|
||||
this.initGridTypes();
|
||||
this.initData();
|
||||
EventManager.dispatch(EventType.LevelInit);
|
||||
this.refreshAllVehicleIcons(fresh);
|
||||
this.finishLevelDrawOrder(fresh);
|
||||
this.revealLevelEntities(fresh);
|
||||
fresh.active = true;
|
||||
void GameAudio.playBackground(fresh);
|
||||
GridSnapHelper.purgeRuntimeGrids(fresh);
|
||||
console.log(`[GameController] 已按快照重建关卡 ${this.curLevelID}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
private restartCurrentLevelSync() {
|
||||
const config = this.curConfig;
|
||||
const levelRoot = this.curLevel;
|
||||
if (!config || !levelRoot?.isValid) return;
|
||||
this.resetExistingMoversToSpawn(levelRoot, config);
|
||||
this.restoreCollectedProps(levelRoot);
|
||||
this.initData();
|
||||
EventManager.dispatch(EventType.LevelInit);
|
||||
this.applyMapDataFromConfig(config);
|
||||
this.initGridTypes();
|
||||
this.refreshAllVehicleIcons(levelRoot);
|
||||
this.externalCallLevelInfo(spawned);
|
||||
this.syncPlayerAppearanceToLevel(config);
|
||||
console.log(`[GameController] 已重置关卡 ${this.curLevelID}(无重载)`);
|
||||
this.finishLevelDrawOrder(levelRoot);
|
||||
this.revealLevelEntities(levelRoot);
|
||||
console.log(`[GameController] 已重置关卡 ${this.curLevelID}`);
|
||||
}
|
||||
|
||||
private restoreCollectedProps(levelRoot: Node) {
|
||||
const walk = (node: Node) => {
|
||||
if (!node?.isValid) return;
|
||||
node.getComponent(PropController)?.restoreForRestart();
|
||||
for (const ch of node.children) walk(ch);
|
||||
};
|
||||
walk(levelRoot);
|
||||
}
|
||||
|
||||
private resetExistingMoversToSpawn(levelRoot: Node, config: LevelConfig) {
|
||||
for (const s of config.spawns ?? []) {
|
||||
if (s.kind === 'player') {
|
||||
const pc = findLevelChildByName(levelRoot, 'Player')?.getComponent(PlayerController);
|
||||
if (!pc) continue;
|
||||
pc.direction = this.resolveDirection(s.playerDirection) ?? Direction.South;
|
||||
pc.setSpawnCell(new Vec3(s.x, s.y, 0));
|
||||
pc.resetToSpawn();
|
||||
continue;
|
||||
}
|
||||
if (s.kind === 'vehicle') {
|
||||
const vc = findLevelChildByName(levelRoot, 'Vehicle')?.getComponent(VehicleController);
|
||||
if (!vc) continue;
|
||||
vc.direction = this.resolveDirection(s.vehicleDirection) ?? Direction.North;
|
||||
vc.setSpawnCell(new Vec3(s.x, s.y, 0));
|
||||
vc.resetToSpawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private purgePropEntities(levelRoot: Node): Promise<void> {
|
||||
const toRemove = this.collectDynamicEntities(levelRoot).filter((n) => {
|
||||
const name = n.name;
|
||||
return name === 'Prop' || name.startsWith('Prop_')
|
||||
|| name === 'PropDecor' || name.startsWith('PropDecor_')
|
||||
|| !!n.getComponent(PropController);
|
||||
});
|
||||
for (const ch of toRemove) {
|
||||
ch.removeFromParent();
|
||||
ch.destroy();
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
this.scheduleOnce(() => resolve(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
/** 主题 entityDisplay 中 Y 偏移/站立补偿变更后,重算实体世界坐标(缩放只改贴图尺寸) */
|
||||
@@ -796,15 +1033,33 @@ export class GameController extends Component {
|
||||
const vc = ch.getComponent(VehicleController);
|
||||
if (vc) tryLinkVehicleRider(vc);
|
||||
});
|
||||
// 先排图层再显示,避免载具带着错误 sibling 露出来
|
||||
sortIsoTiles(levelRoot, true);
|
||||
// 延迟一帧再强制全量:等 LevelDisplay.scheduleOnce 对齐完砖,开局金币/遮挡一次算准
|
||||
this.scheduleOnce(() => {
|
||||
if (levelRoot?.isValid) sortIsoTiles(levelRoot, true);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private revealLevelEntities(levelRoot: Node) {
|
||||
forEachLevelEntityNode(levelRoot, (node) => {
|
||||
if (node?.isValid && !node.active) node.active = true;
|
||||
});
|
||||
}
|
||||
|
||||
private finishLevelDrawOrder(levelRoot: Node | null) {
|
||||
if (!levelRoot?.isValid) return;
|
||||
sortIsoTiles(levelRoot, true);
|
||||
primeIsoDrawOrder(levelRoot, 2);
|
||||
}
|
||||
|
||||
async createNewLevel(levelID: number) {
|
||||
if (this.creating) return;
|
||||
console.warn('[tfrh-reset] createNewLevel 开始(整关重建)', {
|
||||
levelID,
|
||||
playableLevelId: this.playableLevelId,
|
||||
curLevelID: this.curLevelID,
|
||||
creating: this.creating,
|
||||
});
|
||||
if (this.creating) {
|
||||
console.warn('[tfrh-reset] createNewLevel 被 creating 挡住,同关执行会走异步队列');
|
||||
return;
|
||||
}
|
||||
this.creating = true;
|
||||
try {
|
||||
await ensureRuntimeAssetsForLevel(levelID);
|
||||
@@ -834,20 +1089,15 @@ export class GameController extends Component {
|
||||
// 在 instantiate 前无法拦截;先禁用 prefab 内 GridSnapHelper 的 showGrid
|
||||
GridSnapHelper.stripBeforePlayFromPrefab(prefab);
|
||||
const levelRoot = instantiate(prefab);
|
||||
levelRoot.active = false;
|
||||
GridSnapHelper.purgeRuntimeGrids(levelRoot);
|
||||
levelRoot.parent = this.mainLevelEntrance;
|
||||
levelRoot.setPosition(0, 0, 0);
|
||||
this.curLevel = levelRoot;
|
||||
// 预制体 onEnable 可能已画格,挂载后再清一次
|
||||
GridSnapHelper.purgeRuntimeGrids(this.mainLevelEntrance!);
|
||||
|
||||
const runtimeConfig = mergeLevelConfigWithMapData(config, levelRoot);
|
||||
this.curConfig = runtimeConfig;
|
||||
this.applyMapDataFromConfig(runtimeConfig);
|
||||
await LevelDisplay.prepare(levelRoot, runtimeConfig);
|
||||
|
||||
const mapTheme = runtimeConfig.theme || 'silu';
|
||||
await ThemeBackground.apply(this.mainLevelEntrance, mapTheme);
|
||||
await VisualAssets.ensureLevelAssetsReady(
|
||||
runtimeConfig,
|
||||
LevelDisplay.collectTileNames(runtimeConfig),
|
||||
@@ -855,6 +1105,14 @@ export class GameController extends Component {
|
||||
|
||||
const spawned = await this.spawnAllEntities(levelRoot, runtimeConfig);
|
||||
await this.finalizeEntityPresentation(levelRoot, runtimeConfig);
|
||||
|
||||
this.adoptLevelRoot(levelRoot);
|
||||
this.curConfig = runtimeConfig;
|
||||
this.applyMapDataFromConfig(runtimeConfig);
|
||||
levelRoot.active = true;
|
||||
|
||||
const mapTheme = runtimeConfig.theme || 'silu';
|
||||
await ThemeBackground.apply(this.mainLevelEntrance, mapTheme);
|
||||
this.syncPlayerAppearanceToLevel(runtimeConfig);
|
||||
|
||||
await GameAudio.playBackground(levelRoot);
|
||||
@@ -863,6 +1121,8 @@ export class GameController extends Component {
|
||||
this.initData();
|
||||
EventManager.dispatch(EventType.LevelInit);
|
||||
this.refreshAllVehicleIcons(levelRoot);
|
||||
this.finishLevelDrawOrder(levelRoot);
|
||||
this.revealLevelEntities(levelRoot);
|
||||
if (this.mainLevelEntrance?.isValid) {
|
||||
LineGridRenderer.ensure(this.mainLevelEntrance);
|
||||
}
|
||||
@@ -991,6 +1251,7 @@ export class GameController extends Component {
|
||||
const { node, pos, visual } = built;
|
||||
ensureEntityUILayer(node);
|
||||
node.setPosition(pos);
|
||||
node.active = false;
|
||||
node.parent = parent;
|
||||
await VisualAssets.setupEntityVisualAsync(
|
||||
node,
|
||||
@@ -1093,6 +1354,12 @@ export class GameController extends Component {
|
||||
* { LevelID, PlayerName, VehicleName }
|
||||
*/
|
||||
externalCallLevelInfo(objects: Node[]) {
|
||||
if (this.requestedLevelID > 0 && Number(this.curLevelID) !== Number(this.requestedLevelID)) {
|
||||
console.warn(
|
||||
`[GameController] 跳过过期 externalLevelInfo cur=${this.curLevelID} want=${this.requestedLevelID}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
const info: ExternalLevelInfo = {
|
||||
LevelID: this.curLevelID,
|
||||
PlayerName: '',
|
||||
|
||||
Reference in New Issue
Block a user