1
This commit is contained in:
@@ -16084,6 +16084,22 @@ PrefabInstance:
|
|||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: PW_Plane_1
|
value: PW_Plane_1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1305285418536295, guid: f4f7967ac88aaaf4f975719c27df12aa, type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1333113903768364, guid: f4f7967ac88aaaf4f975719c27df12aa, type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1364716670320141, guid: f4f7967ac88aaaf4f975719c27df12aa, type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1372994856248276, guid: f4f7967ac88aaaf4f975719c27df12aa, type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4313960313673800, guid: f4f7967ac88aaaf4f975719c27df12aa, type: 3}
|
- target: {fileID: 4313960313673800, guid: f4f7967ac88aaaf4f975719c27df12aa, type: 3}
|
||||||
propertyPath: m_LocalScale.x
|
propertyPath: m_LocalScale.x
|
||||||
value: 4.4716
|
value: 4.4716
|
||||||
|
|||||||
@@ -17289,6 +17289,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1084716326253117915, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1139735090001087078, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
- target: {fileID: 1139735090001087078, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -17354,6 +17359,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3686788617825013159, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3706220059061985850, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
- target: {fileID: 3706220059061985850, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -17469,11 +17479,21 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8456440153089082935, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 8553831016633651482, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
- target: {fileID: 8553831016633651482, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8990963234669806065, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 9011820818510108152, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
- target: {fileID: 9011820818510108152, guid: 29589d6bc93a47e499105e964f1f5c6b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
|
|||||||
@@ -28841,6 +28841,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1092006923787695085, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1898051008385034303, guid: 9672abcceca61c846b14184d9bba766f,
|
- target: {fileID: 1898051008385034303, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -28856,6 +28861,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2372885871247165783, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 2414516914643537171, guid: 9672abcceca61c846b14184d9bba766f,
|
- target: {fileID: 2414516914643537171, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -28876,6 +28886,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3336049404196487681, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3424540851437192074, guid: 9672abcceca61c846b14184d9bba766f,
|
- target: {fileID: 3424540851437192074, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -28886,6 +28901,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3684409744614040008, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4178955796969763688, guid: 9672abcceca61c846b14184d9bba766f,
|
- target: {fileID: 4178955796969763688, guid: 9672abcceca61c846b14184d9bba766f,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
|
|||||||
@@ -28297,6 +28297,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 2736570820237217112, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 2854444671909311366, guid: 6bca3101cb2436147ba613930ade7bc6,
|
- target: {fileID: 2854444671909311366, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -28307,6 +28312,16 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3471896425151648088, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3596577447608897696, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4277595997587927750, guid: 6bca3101cb2436147ba613930ade7bc6,
|
- target: {fileID: 4277595997587927750, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
@@ -28397,6 +28412,11 @@ PrefabInstance:
|
|||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7242293744027100629, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IsActive
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 7257220591867521751, guid: 6bca3101cb2436147ba613930ade7bc6,
|
- target: {fileID: 7257220591867521751, guid: 6bca3101cb2436147ba613930ade7bc6,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SortingLayer
|
propertyPath: m_SortingLayer
|
||||||
|
|||||||
@@ -708,8 +708,17 @@ public class UIManager : MonoSingleton<UIManager>
|
|||||||
yield return handle;
|
yield return handle;
|
||||||
if (handle.Status == AsyncOperationStatus.Succeeded)
|
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
prefabCache[type] = handle.Result;
|
// ⭐ 竞态守卫:预载期间 ShowAsync 已自行加载并缓存了同一面板(玩家点得快时发生),
|
||||||
handleCache[type] = handle;
|
// 这里若再覆盖缓存,预载拿到的句柄会丢失、引用计数 +1 泄漏 → 释放本句柄即可
|
||||||
|
if (prefabCache.ContainsKey(type))
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prefabCache[type] = handle.Result;
|
||||||
|
handleCache[type] = handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3855,6 +3855,7 @@ GameObject:
|
|||||||
- component: {fileID: 2075409202}
|
- component: {fileID: 2075409202}
|
||||||
- component: {fileID: 2075409203}
|
- component: {fileID: 2075409203}
|
||||||
- component: {fileID: 2075409204}
|
- component: {fileID: 2075409204}
|
||||||
|
- component: {fileID: 2075409205}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Manager
|
m_Name: Manager
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -4345,6 +4346,18 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
audioMixer: {fileID: 24100000, guid: ca43f9a7549657a49a2978e97c7a621a, type: 2}
|
audioMixer: {fileID: 24100000, guid: ca43f9a7549657a49a2978e97c7a621a, type: 2}
|
||||||
|
--- !u!114 &2075409205
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2075409194}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: bd70cad3c45605a4f824c9eaf1eb081d, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
--- !u!1001 &3569938244496052059
|
--- !u!1001 &3569938244496052059
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -824,7 +824,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private IEnumerator SpawnFishBatchedCoroutine(List<OnFishSpawnFishItem> queue, bool isSync)
|
private IEnumerator SpawnFishBatchedCoroutine(List<OnFishSpawnFishItem> queue, bool isSync)
|
||||||
{
|
{
|
||||||
const int batchSize = 5; // 每帧生成5条
|
// ⭐ 加载期(进度条还在走、面板未加载完成)每帧只出 2 条:单帧 5 条 Spine 鱼
|
||||||
|
// (首次创建含骨架/贴图初始化)会卡住进度条和界面动画(玩家反馈"90% 卡"的一部分);
|
||||||
|
// 加载完成进房后恢复每帧 5 条(正常出鱼间隔大,不挤)
|
||||||
|
int batchSize = (currGameType != null && !currGameType.IsGameLoadCompleted) ? 2 : 5;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (index < queue.Count)
|
while (index < queue.Count)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,6 +170,16 @@ namespace Assets.MyGame.Scripts.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static IEnumerator LoadSceneThenResources(UIBase panel, string sceneName)
|
private static IEnumerator LoadSceneThenResources(UIBase panel, string sceneName)
|
||||||
{
|
{
|
||||||
|
// ⭐ 第一步只加载 UI:面板刚实例化显示,先让 2 帧把 UI(含进度条)完整渲染出来,
|
||||||
|
// 再从"里面有进度条的画面"开始加载非 UI 资源(场景/鱼/音频)——
|
||||||
|
// 避免面板第一帧和场景加载启动挤在同一帧,UI 出现那下发卡
|
||||||
|
yield return null;
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
// ⭐ 场景加载阶段进度条从 0 缓慢爬升(此阶段只加载了 UI 面板):条不会静止像卡死
|
||||||
|
if (panel is GameMainPanel_FishBase barPanel)
|
||||||
|
barPanel.BeginSceneLoadingProgress();
|
||||||
|
|
||||||
// ③ 目标场景仅加载一次:标记已加载后不再重复 LoadSceneAsync(防止人机通知触发重复加载)
|
// ③ 目标场景仅加载一次:标记已加载后不再重复 LoadSceneAsync(防止人机通知触发重复加载)
|
||||||
if (!string.IsNullOrEmpty(sceneName) && !_loadedGameScenes.Contains(sceneName))
|
if (!string.IsNullOrEmpty(sceneName) && !_loadedGameScenes.Contains(sceneName))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Spine.Unity;
|
using Spine.Unity;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -591,9 +592,11 @@ public class FlyTurretData : TurretData
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 入场飞机预热(进房加载收尾时由面板调用,卡顿被进度条遮住) ====================
|
// ==================== 入场飞机预热(进房加载收尾时由面板调用,卡顿被进度条遮住) ====================
|
||||||
// XJMH 进入房间时"命中"的那架完整飞机(骨架 + 尾迹/护盾十多个粒子系统 + 贴图首次上传)首帧初始化很重;
|
// XJMH 进入房间时"命中"的那架完整飞机 PW_Plane(骨架 + 41 个粒子系统、2.2MB 预制体、52 个节点):
|
||||||
// 全部堆在"加载到100%、进度条已隐藏"那一帧做,玩家会看到明显卡顿(其他玩法没有这套 XJMH 独有资产)。
|
// 整根激活会让 41 套粒子在同一帧全部首初始化(分配缓冲/上传网格贴图)——单帧几百 ms 主线程尖峰。
|
||||||
// 预热 = 在进度条还在走时把飞机临时挂到激活的父节点下、缩到 0 隐藏,激活一两帧完成初始化,再原样还原。
|
// 这就是"只有星际迷航进房卡、其它玩法不卡"的原因(其他玩法没有这套 XJMH 独有资产)。
|
||||||
|
// 预热 = 进度条还在走时把飞机临时挂到激活父节点下、缩到 0 隐藏;骨架 1 帧 + 粒子按每帧 8ms 预算
|
||||||
|
// 逐帧点亮完成初始化,再原样还原(玩家全程不可见)。
|
||||||
|
|
||||||
private Coroutine _prewarmRoutine;
|
private Coroutine _prewarmRoutine;
|
||||||
private Transform _prewarmPlane; // 预热中的飞机(被打断时还原用)
|
private Transform _prewarmPlane; // 预热中的飞机(被打断时还原用)
|
||||||
@@ -603,6 +606,8 @@ public class FlyTurretData : TurretData
|
|||||||
private Quaternion _prewarmOrigRot;
|
private Quaternion _prewarmOrigRot;
|
||||||
private Vector3 _prewarmOrigScale;
|
private Vector3 _prewarmOrigScale;
|
||||||
private bool _prewarmOrigActive;
|
private bool _prewarmOrigActive;
|
||||||
|
/// <summary>粒子分帧点亮的帧内计时(Stopwatch 不受 Time.realtimeSinceStartup 帧内不刷新影响)</summary>
|
||||||
|
private static readonly System.Diagnostics.Stopwatch _prewarmFrameSw = new System.Diagnostics.Stopwatch();
|
||||||
|
|
||||||
/// <summary>入场飞机预热(面板在加载收尾阶段调用;座位/炮台需已激活)。幂等:重复调用只跑一次。</summary>
|
/// <summary>入场飞机预热(面板在加载收尾阶段调用;座位/炮台需已激活)。幂等:重复调用只跑一次。</summary>
|
||||||
public void PrewarmEnterPlane()
|
public void PrewarmEnterPlane()
|
||||||
@@ -625,27 +630,67 @@ public class FlyTurretData : TurretData
|
|||||||
_prewarmOrigScale = plane.localScale;
|
_prewarmOrigScale = plane.localScale;
|
||||||
_prewarmOrigActive = plane.gameObject.activeSelf;
|
_prewarmOrigActive = plane.gameObject.activeSelf;
|
||||||
|
|
||||||
// 只开入场要用的 Body、关掉免费三类——避免把五十来个粒子系统全部初始化(反而更重);
|
// 容器显隐(与入场动画 EnterActionRoutine 一致):开 Body/护盾、关免费三类
|
||||||
// ⭐ 护盾粒子拆到下一帧再开:和 Body 骨架/粒子挤同一帧 = 单帧尖峰(90% 收尾窗口卡顿的来源之一)
|
|
||||||
SetPlaneChildActive(plane, "Body", true);
|
SetPlaneChildActive(plane, "Body", true);
|
||||||
|
SetPlaneChildActive(plane, "PW_Effect_Defend", true);
|
||||||
SetPlaneChildActive(plane, "FreeEffect", false);
|
SetPlaneChildActive(plane, "FreeEffect", false);
|
||||||
SetPlaneChildActive(plane, "FreeEffect_Crit", false);
|
SetPlaneChildActive(plane, "FreeEffect_Crit", false);
|
||||||
SetPlaneChildActive(plane, "FreeEffect_Speedup", false);
|
SetPlaneChildActive(plane, "FreeEffect_Speedup", false);
|
||||||
|
|
||||||
|
// ⭐ 关键修复("只有 XJMH 进房卡主线程"的根因):
|
||||||
|
// 整根 SetActive(true) 会让 41 个粒子系统在同一帧全部首初始化(单帧几百 ms)。
|
||||||
|
// 先把"会被激活的"粒子节点逐个关掉(飞机根此刻未激活,只是置标志、不做初始化),
|
||||||
|
// 等飞机激活(这一帧只初始化骨架等非粒子部分)后,按"每帧约 8ms 预算"逐帧点亮——
|
||||||
|
// 设备快一帧多开几个、设备慢一帧只开一个,单帧尖峰摊平到十几帧,不再顶住主线程。
|
||||||
|
// ⚠️ 只动"容器开着"的粒子(Body/护盾);免费三类容器已关、默认关着的粒子都不动,保持原状。
|
||||||
|
var psNodes = new List<GameObject>(64);
|
||||||
|
foreach (var ps in plane.GetComponentsInChildren<ParticleSystem>(true))
|
||||||
|
{
|
||||||
|
if (ps == null || ps.gameObject == plane.gameObject) continue;
|
||||||
|
if (!IsActiveUnder(ps.transform, plane)) continue; // 容器关着的(免费三类等)不预热
|
||||||
|
ps.gameObject.SetActive(false);
|
||||||
|
psNodes.Add(ps.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
// 临时挂到根节点(激活中)并缩到 0:既能触发初始化,又完全不可见
|
// 临时挂到根节点(激活中)并缩到 0:既能触发初始化,又完全不可见
|
||||||
Transform holder = transform.root;
|
Transform holder = transform.root;
|
||||||
if (holder != null && holder != _prewarmOrigParent)
|
if (holder != null && holder != _prewarmOrigParent)
|
||||||
plane.SetParent(holder, true);
|
plane.SetParent(holder, true);
|
||||||
plane.localScale = Vector3.zero;
|
plane.localScale = Vector3.zero;
|
||||||
plane.gameObject.SetActive(true);
|
LoadingStallWatchdog.Phase = "预热·飞机骨架激活帧";
|
||||||
yield return null; // Body 骨架首帧网格
|
plane.gameObject.SetActive(true); // 这一帧只初始化骨架等非粒子部分
|
||||||
SetPlaneChildActive(plane, "PW_Effect_Defend", true); // 护盾粒子单独一帧开
|
yield return null; // 骨架首帧网格
|
||||||
yield return null; // 护盾首帧模拟
|
|
||||||
yield return null; // 再等一帧让首帧网格上传铺开
|
// ⭐ 逐帧分批点亮粒子(帧内时间预算自适应:快机多开、慢机少开)
|
||||||
|
LoadingStallWatchdog.Phase = "预热·飞机粒子分帧";
|
||||||
|
const double frameBudgetMs = 8.0;
|
||||||
|
_prewarmFrameSw.Restart();
|
||||||
|
for (int i = 0; i < psNodes.Count; i++)
|
||||||
|
{
|
||||||
|
if (psNodes[i] == null) continue;
|
||||||
|
psNodes[i].SetActive(true);
|
||||||
|
if (_prewarmFrameSw.Elapsed.TotalMilliseconds >= frameBudgetMs)
|
||||||
|
{
|
||||||
|
_prewarmFrameSw.Restart();
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield return null; // 最后一批首帧模拟
|
||||||
|
yield return null; // 首帧网格上传铺开
|
||||||
|
|
||||||
FinishPrewarmRestore();
|
FinishPrewarmRestore();
|
||||||
Debug.Log($"[XJMH入场] 飞机预热完成({plane.name})");
|
Debug.Log($"[XJMH入场] 飞机预热完成({plane.name},粒子分帧点亮 {psNodes.Count} 个)");
|
||||||
_prewarmRoutine = null;
|
_prewarmRoutine = null;
|
||||||
|
// 诊断:预热结束,把卡顿监测阶段还给加载段(后续卡顿归因不错位到预热)
|
||||||
|
LoadingStallWatchdog.Phase = "60~78 音频加载";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>节点在"飞机根若激活"的前提下是否会被激活(检查自身到飞机根之间每级的 activeSelf)</summary>
|
||||||
|
private static bool IsActiveUnder(Transform node, Transform stopRoot)
|
||||||
|
{
|
||||||
|
for (var t = node; t != null && t != stopRoot; t = t.parent)
|
||||||
|
if (!t.gameObject.activeSelf) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>预热还原:飞机隐藏并恢复到预热前的挂载/变换/激活状态(协程正常收尾或中途被打断都用它)</summary>
|
/// <summary>预热还原:飞机隐藏并恢复到预热前的挂载/变换/激活状态(协程正常收尾或中途被打断都用它)</summary>
|
||||||
|
|||||||
@@ -346,6 +346,14 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
|||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⭐ 预热用:本次座位首次激活时先"只整理炮台列表、不点亮默认炮台"——
|
||||||
|
/// 把炮台 Spine 骨架的首初始化(几十~上百 ms)拆到下一帧单独做,避免座位激活那一帧
|
||||||
|
/// 同时扛"座位整层 OnEnable + 炮台骨架首建"两个大活。由 GameMainPanel_FishBase 预热流程设置;
|
||||||
|
/// 任何入座/兜底路径(ShowPlayer)都会强制复位并保证炮台被点亮,不会留空座位。
|
||||||
|
/// </summary>
|
||||||
|
[System.NonSerialized] public bool deferDefaultTurretLightUp;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// XJMH 模式:炮台是座位自带子对象,预制体里已摆好,不需要 LoadTurret 加载。
|
/// XJMH 模式:炮台是座位自带子对象,预制体里已摆好,不需要 LoadTurret 加载。
|
||||||
/// ⭐ 默认炮台 = 排序后索引 0 的那把(对应座位 GetChild(0) 的绿炮台)。
|
/// ⭐ 默认炮台 = 排序后索引 0 的那把(对应座位 GetChild(0) 的绿炮台)。
|
||||||
@@ -359,9 +367,33 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
NormalizeXJMHTurretList();
|
NormalizeXJMHTurretList();
|
||||||
|
// ⭐ 预热路径:只整理列表,点亮留给预热协程下一帧调 ActivateDefaultXJMHTurretForPrewarm
|
||||||
|
if (deferDefaultTurretLightUp) return;
|
||||||
ApplyXJMHTurret(0);
|
ApplyXJMHTurret(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 预热续帧:点亮默认炮台(配合 deferDefaultTurretLightUp,把炮台骨架首初始化拆到单独一帧)。
|
||||||
|
/// ⚠️ "是否已点亮"必须看列表里有没有"激活状态"的炮台——currentTurret 是可序列化字段,
|
||||||
|
/// 预制体里预置了引用,不代表炮台已激活(用它当判据会出现"炮台永远不点亮"的 bug)。
|
||||||
|
/// </summary>
|
||||||
|
public void ActivateDefaultXJMHTurretForPrewarm()
|
||||||
|
{
|
||||||
|
if (turretControlMode != TurretControlMode.XJMH) return;
|
||||||
|
if (HasActiveXJMHTurret()) return; // 已点亮(正常入座路径已做过)
|
||||||
|
deferDefaultTurretLightUp = false;
|
||||||
|
InitXJMHTurret();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>列表里当前是否有"激活状态"的炮台("默认炮台是否已点亮"的正确判据)</summary>
|
||||||
|
public bool HasActiveXJMHTurret()
|
||||||
|
{
|
||||||
|
if (xjmhTurretList == null) return false;
|
||||||
|
for (int i = 0; i < xjmhTurretList.Count; i++)
|
||||||
|
if (xjmhTurretList[i] != null && xjmhTurretList[i].gameObject.activeSelf) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 整理 XJMH 炮台列表:剔除空引用,并按座位下的兄弟顺序排序。
|
/// 整理 XJMH 炮台列表:剔除空引用,并按座位下的兄弟顺序排序。
|
||||||
/// ⭐ 排序原因:切换面板的 4 个按钮固定是 绿/蓝/金/VIP(索引 0~3),
|
/// ⭐ 排序原因:切换面板的 4 个按钮固定是 绿/蓝/金/VIP(索引 0~3),
|
||||||
@@ -1137,6 +1169,11 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// ⭐ 兜底:预热被中断(激活了座位但还没轮到点亮炮台就退出/销毁)时,入座这里补点亮,
|
||||||
|
// 保证任何时候都不会出现"座位亮着但炮台是空的"(判据:列表里有没有激活的炮台)
|
||||||
|
if (!HasActiveXJMHTurret())
|
||||||
|
ActivateDefaultXJMHTurretForPrewarm();
|
||||||
|
|
||||||
// ⭐ XJMH 进入房间入场动画(原版 Battery:EnterAction):仅本地座位播
|
// ⭐ XJMH 进入房间入场动画(原版 Battery:EnterAction):仅本地座位播
|
||||||
// (Enter 音效 + 飞机从下方升起变回炮台 + PlaneBack 音效);
|
// (Enter 音效 + 飞机从下方升起变回炮台 + PlaneBack 音效);
|
||||||
// 本次激活周期只播一次(OnDisable 复位,重进房重新播),切炮台不受影响
|
// 本次激活周期只播一次(OnDisable 复位,重进房重新播),切炮台不受影响
|
||||||
|
|||||||
@@ -0,0 +1,615 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"yzNumber": 70001,
|
||||||
|
"lineList": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70002,
|
||||||
|
"lineList": [
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70003,
|
||||||
|
"lineList": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70004,
|
||||||
|
"lineList": [
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70101,
|
||||||
|
"lineList": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70102,
|
||||||
|
"lineList": [
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70103,
|
||||||
|
"lineList": [
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70104,
|
||||||
|
"lineList": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70201,
|
||||||
|
"lineList": [
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70202,
|
||||||
|
"lineList": [
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70203,
|
||||||
|
"lineList": [
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70204,
|
||||||
|
"lineList": [
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70205,
|
||||||
|
"lineList": [
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70206,
|
||||||
|
"lineList": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70207,
|
||||||
|
"lineList": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"count": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70208,
|
||||||
|
"lineList": [
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"count": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70209,
|
||||||
|
"lineList": [
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70210,
|
||||||
|
"lineList": [
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70211,
|
||||||
|
"lineList": [
|
||||||
|
16
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70212,
|
||||||
|
"lineList": [
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70213,
|
||||||
|
"lineList": [
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70214,
|
||||||
|
"lineList": [
|
||||||
|
19
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70215,
|
||||||
|
"lineList": [
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70216,
|
||||||
|
"lineList": [
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70217,
|
||||||
|
"lineList": [
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70218,
|
||||||
|
"lineList": [
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"count": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70219,
|
||||||
|
"lineList": [
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70220,
|
||||||
|
"lineList": [
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"count": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70221,
|
||||||
|
"lineList": [
|
||||||
|
26
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70222,
|
||||||
|
"lineList": [
|
||||||
|
27
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70223,
|
||||||
|
"lineList": [
|
||||||
|
6,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"count": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70224,
|
||||||
|
"lineList": [
|
||||||
|
10,
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70225,
|
||||||
|
"lineList": [
|
||||||
|
21,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71001,
|
||||||
|
"lineList": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71002,
|
||||||
|
"lineList": [
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71003,
|
||||||
|
"lineList": [
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71004,
|
||||||
|
"lineList": [
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71005,
|
||||||
|
"lineList": [
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71006,
|
||||||
|
"lineList": [
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71007,
|
||||||
|
"lineList": [
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71008,
|
||||||
|
"lineList": [
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"count": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71009,
|
||||||
|
"lineList": [
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71010,
|
||||||
|
"lineList": [
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30
|
||||||
|
],
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71011,
|
||||||
|
"lineList": [
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
33
|
||||||
|
],
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71012,
|
||||||
|
"lineList": [
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71013,
|
||||||
|
"lineList": [
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"count": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70401,
|
||||||
|
"lineList": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70402,
|
||||||
|
"lineList": [
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70403,
|
||||||
|
"lineList": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70404,
|
||||||
|
"lineList": [
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70405,
|
||||||
|
"lineList": [
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70406,
|
||||||
|
"lineList": [
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70407,
|
||||||
|
"lineList": [
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70408,
|
||||||
|
"lineList": [
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70409,
|
||||||
|
"lineList": [
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70410,
|
||||||
|
"lineList": [
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70411,
|
||||||
|
"lineList": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70412,
|
||||||
|
"lineList": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70413,
|
||||||
|
"lineList": [
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70414,
|
||||||
|
"lineList": [
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70415,
|
||||||
|
"lineList": [
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"count": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70416,
|
||||||
|
"lineList": [
|
||||||
|
16
|
||||||
|
],
|
||||||
|
"count": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70417,
|
||||||
|
"lineList": [
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70418,
|
||||||
|
"lineList": [
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70419,
|
||||||
|
"lineList": [
|
||||||
|
19
|
||||||
|
],
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70420,
|
||||||
|
"lineList": [
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70421,
|
||||||
|
"lineList": [
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70422,
|
||||||
|
"lineList": [
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70423,
|
||||||
|
"lineList": [
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70424,
|
||||||
|
"lineList": [
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70425,
|
||||||
|
"lineList": [
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70426,
|
||||||
|
"lineList": [
|
||||||
|
26
|
||||||
|
],
|
||||||
|
"count": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70427,
|
||||||
|
"lineList": [
|
||||||
|
27
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70428,
|
||||||
|
"lineList": [
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"count": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70429,
|
||||||
|
"lineList": [
|
||||||
|
29
|
||||||
|
],
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70430,
|
||||||
|
"lineList": [
|
||||||
|
30
|
||||||
|
],
|
||||||
|
"count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70431,
|
||||||
|
"lineList": [
|
||||||
|
31
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70432,
|
||||||
|
"lineList": [
|
||||||
|
32
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70433,
|
||||||
|
"lineList": [
|
||||||
|
33
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70434,
|
||||||
|
"lineList": [
|
||||||
|
34
|
||||||
|
],
|
||||||
|
"count": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70435,
|
||||||
|
"lineList": [
|
||||||
|
35
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 70436,
|
||||||
|
"lineList": [
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"count": 20
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 37136faa1f387f2498c01033bc961bbc
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -246,119 +246,254 @@
|
|||||||
{
|
{
|
||||||
"yzNumber": 71001,
|
"yzNumber": 71001,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
1,
|
1
|
||||||
2,
|
|
||||||
3
|
|
||||||
],
|
],
|
||||||
"count": 3
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71002,
|
"yzNumber": 71002,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
4,
|
2
|
||||||
5,
|
|
||||||
6
|
|
||||||
],
|
],
|
||||||
"count": 5
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71003,
|
"yzNumber": 71003,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
7,
|
3
|
||||||
8,
|
|
||||||
9
|
|
||||||
],
|
],
|
||||||
"count": 4
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71004,
|
"yzNumber": 71004,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
10,
|
4
|
||||||
11,
|
|
||||||
12
|
|
||||||
],
|
],
|
||||||
"count": 6
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71005,
|
"yzNumber": 71005,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
13,
|
5
|
||||||
14,
|
|
||||||
15
|
|
||||||
],
|
],
|
||||||
"count": 3
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71006,
|
"yzNumber": 71006,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
16,
|
6
|
||||||
17,
|
|
||||||
18
|
|
||||||
],
|
],
|
||||||
"count": 6
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71007,
|
"yzNumber": 71007,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
19,
|
7
|
||||||
20,
|
|
||||||
21
|
|
||||||
],
|
],
|
||||||
"count": 4
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71008,
|
"yzNumber": 71008,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
22,
|
8
|
||||||
23,
|
|
||||||
24
|
|
||||||
],
|
],
|
||||||
"count": 2
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71009,
|
"yzNumber": 71009,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
25,
|
9
|
||||||
26,
|
|
||||||
27
|
|
||||||
],
|
],
|
||||||
"count": 8
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71010,
|
"yzNumber": 71010,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
28,
|
10
|
||||||
29,
|
|
||||||
30
|
|
||||||
],
|
],
|
||||||
"count": 3
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71011,
|
"yzNumber": 71011,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
31,
|
11
|
||||||
32,
|
|
||||||
33
|
|
||||||
],
|
],
|
||||||
"count": 3
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71012,
|
"yzNumber": 71012,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
34,
|
12
|
||||||
35,
|
|
||||||
36
|
|
||||||
],
|
],
|
||||||
"count": 3
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 71013,
|
"yzNumber": 71013,
|
||||||
"lineList": [
|
"lineList": [
|
||||||
1,
|
13
|
||||||
3,
|
|
||||||
5
|
|
||||||
],
|
],
|
||||||
"count": 2
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71014,
|
||||||
|
"lineList": [
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71015,
|
||||||
|
"lineList": [
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71016,
|
||||||
|
"lineList": [
|
||||||
|
16
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71017,
|
||||||
|
"lineList": [
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71018,
|
||||||
|
"lineList": [
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71019,
|
||||||
|
"lineList": [
|
||||||
|
19
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71020,
|
||||||
|
"lineList": [
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71021,
|
||||||
|
"lineList": [
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71022,
|
||||||
|
"lineList": [
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71023,
|
||||||
|
"lineList": [
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71024,
|
||||||
|
"lineList": [
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71025,
|
||||||
|
"lineList": [
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71026,
|
||||||
|
"lineList": [
|
||||||
|
26
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71027,
|
||||||
|
"lineList": [
|
||||||
|
27
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71028,
|
||||||
|
"lineList": [
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71029,
|
||||||
|
"lineList": [
|
||||||
|
29
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71030,
|
||||||
|
"lineList": [
|
||||||
|
30
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71031,
|
||||||
|
"lineList": [
|
||||||
|
31
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71032,
|
||||||
|
"lineList": [
|
||||||
|
32
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71033,
|
||||||
|
"lineList": [
|
||||||
|
33
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71034,
|
||||||
|
"lineList": [
|
||||||
|
34
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71035,
|
||||||
|
"lineList": [
|
||||||
|
35
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"yzNumber": 71036,
|
||||||
|
"lineList": [
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"yzNumber": 70401,
|
"yzNumber": 70401,
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// XJMH 进房首帧预热(加载 90%→100% 收尾窗口调用,进度条还显示着玩家看不到):
|
/// XJMH 进房预热(60% 音频段起点调用,进度条还显示着玩家看不到):
|
||||||
/// 把本地座位(座位自带炮台随 Awake 一起初始化)与"入场要用的那架完整飞机"提前点亮——
|
/// 把本地座位(座位自带炮台随 Awake 一起初始化)与"入场要用的那架完整飞机"提前点亮——
|
||||||
/// 这些 XJMH 独有资产首次初始化(骨架/粒子/贴图首上传)很重,全堆在 100% 那一帧玩家会看到明显卡顿。
|
/// 这些 XJMH 独有资产首次初始化(骨架/粒子/贴图首上传)很重,全堆在 100% 那一帧玩家会看到明显卡顿。
|
||||||
/// ⭐ 按帧拆散(避免"90% 卡死"):先让一帧(进度条先刷新)→ 只留默认炮台、关掉其余 3 把 →
|
/// ⭐ 按帧拆散(避免"90% 卡死"):先让一帧(进度条先刷新)→ 只留默认炮台、关掉其余 3 把 →
|
||||||
@@ -497,39 +497,169 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
|
|
||||||
private IEnumerator PrewarmXJMHCoroutine(SitPosData sit)
|
private IEnumerator PrewarmXJMHCoroutine(SitPosData sit)
|
||||||
{
|
{
|
||||||
// ⭐ 先等一帧:StartCoroutine 会同步执行到第一个 yield —— 原先座位激活的重活
|
// ⭐ 先等一帧:StartCoroutine 会同步执行到第一个 yield —— 座位激活的重活不能和进度条
|
||||||
// 和"90%"写入进度条是同一帧(数字还没刷新、主线程就被占住,看起来"90 卡死")。
|
// 写数字挤在同一帧(玩家看到"卡在 60/61")。先让一帧,进度条先刷新
|
||||||
// 先让一帧,进度条和收尾循环跑起来再干重活
|
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
bool willActivate = sit != null && !sit.gameObject.activeSelf;
|
bool willActivate = sit != null && !sit.gameObject.activeSelf;
|
||||||
|
|
||||||
// ⭐ 只有"座位从未激活、这次预热才激活"时才预关炮台:
|
// ⭐ 分帧方案(XJMH 进房不卡主线程的关键)—— 把所有"可以错开的初始化"从同一帧剥出去:
|
||||||
// 预制体里 4 把 XJMH 炮台(SkeletonGraphic)默认激活,座位 SetActive 时 4 套骨架/材质/贴图
|
// ① 座位外壳(1 帧,只扛座位整层 OnEnable)
|
||||||
// 挤在同一帧全部首初始化(单帧尖峰巨大);先关掉后,这一帧只初始化 Awake 点亮的默认那把。
|
// ② 默认炮台 Spine 骨架首初始化(单独 1 帧,见 SitPosData.deferDefaultTurretLightUp)
|
||||||
// ⚠️ 座位已在激活状态时不能动(Awake 不会再跑,关掉就回不来)
|
// ③ 座位外壳粒子 + 默认炮台粒子(本方法先关掉,之后逐帧点亮)
|
||||||
if (willActivate && sit.xjmhTurretList != null)
|
// ④ 入场飞机(FlyTurretData.PrewarmPlaneRoutine:骨架 1 帧 + 41 个粒子逐帧点亮)
|
||||||
|
List<GameObject> lazyPsNodes = null;
|
||||||
|
if (willActivate)
|
||||||
{
|
{
|
||||||
|
// 预关全部 4 把炮台(Spine 骨架默认全开,不关的话激活帧一次初始化 4 套)
|
||||||
|
// ⚠️ 座位已在激活状态时不能动(Awake 不会再跑,关掉就回不来)
|
||||||
|
if (sit.xjmhTurretList != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sit.xjmhTurretList.Count; i++)
|
||||||
|
{
|
||||||
|
var t = sit.xjmhTurretList[i];
|
||||||
|
if (t != null && t.gameObject.activeSelf) t.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集"激活后会被点亮"的粒子并先关掉(此刻根未激活,只是置标志、无初始化):
|
||||||
|
// 座位外壳层(炮台/飞机子树此刻未激活,自动被排除)+ 默认炮台子树(兄弟顺序最靠前=绿色那把)
|
||||||
|
lazyPsNodes = CollectActiveParticlesUnder(sit.transform);
|
||||||
|
var defaultTurret = GetDefaultXJMHTurret(sit);
|
||||||
|
if (defaultTurret != null)
|
||||||
|
{
|
||||||
|
var turretPsNodes = CollectActiveParticlesUnder(defaultTurret.transform);
|
||||||
|
if (turretPsNodes != null)
|
||||||
|
{
|
||||||
|
if (lazyPsNodes == null) lazyPsNodes = turretPsNodes;
|
||||||
|
else lazyPsNodes.AddRange(turretPsNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ① 激活座位【外壳】:设 defer 标记 → Awake 只整理炮台列表、不点亮炮台
|
||||||
|
// (这一帧只扛"座位整层 OnEnable",把炮台骨架首建推到下一帧)
|
||||||
|
sit.deferDefaultTurretLightUp = true;
|
||||||
|
LoadingStallWatchdog.Phase = "预热·座位外壳激活帧";
|
||||||
|
sit.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null; // 座位外壳首帧
|
||||||
|
|
||||||
|
// ② 单独一帧点亮默认炮台:Spine 骨架首初始化(材质/网格/贴图上传)只花在这一帧
|
||||||
|
// ⚠️ 判据用"列表里有没有激活的炮台",不能用 currentTurret(可序列化字段,预制体里预置了引用)
|
||||||
|
if (willActivate && !sit.HasActiveXJMHTurret())
|
||||||
|
{
|
||||||
|
LoadingStallWatchdog.Phase = "预热·炮台骨架激活帧";
|
||||||
|
sit.ActivateDefaultXJMHTurretForPrewarm();
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null; // 炮台骨架首帧网格
|
||||||
|
|
||||||
|
// ③ 逐帧点亮座位/炮台粒子(每帧约 8ms 预算)
|
||||||
|
if (lazyPsNodes != null && lazyPsNodes.Count > 0)
|
||||||
|
{
|
||||||
|
LoadingStallWatchdog.Phase = "预热·座位/炮台粒子分帧";
|
||||||
|
yield return ChunkEnableParticles(lazyPsNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
// ④ 飞机隐藏预热(座位激活后 currentTurret 已就绪 = 入场会用的那把;内部对 41 个粒子分帧)
|
||||||
|
var turret = sit != null ? sit.currentTurret as FlyTurretData : null;
|
||||||
|
if (turret != null)
|
||||||
|
{
|
||||||
|
LoadingStallWatchdog.Phase = "预热·飞机(骨架+粒子分帧)";
|
||||||
|
turret.PrewarmEnterPlane();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>XJMH 默认炮台 = 兄弟顺序最靠前的那把(与 SitPosData.NormalizeXJMHTurretList 的排序一致)</summary>
|
||||||
|
private static TurretData GetDefaultXJMHTurret(SitPosData sit)
|
||||||
|
{
|
||||||
|
if (sit == null || sit.xjmhTurretList == null) return null;
|
||||||
|
TurretData best = null;
|
||||||
|
int bestIdx = int.MaxValue;
|
||||||
|
for (int i = 0; i < sit.xjmhTurretList.Count; i++)
|
||||||
|
{
|
||||||
|
var t = sit.xjmhTurretList[i];
|
||||||
|
if (t == null) continue;
|
||||||
|
int idx = t.transform.GetSiblingIndex();
|
||||||
|
if (idx < bestIdx) { bestIdx = idx; best = t; }
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 收集"根若激活就会被激活"的粒子节点并先把它们关掉(此刻根未激活,SetActive(false) 只置标志、
|
||||||
|
/// 不触发任何初始化)——配合 ChunkEnableParticles 把这些粒子系统的首初始化逐帧分摊。
|
||||||
|
/// 容器(父级)关着的不收集;自身默认关闭的粒子也不动。
|
||||||
|
/// </summary>
|
||||||
|
private static List<GameObject> CollectActiveParticlesUnder(Transform root)
|
||||||
|
{
|
||||||
|
if (root == null) return null;
|
||||||
|
List<GameObject> list = null;
|
||||||
|
var systems = root.GetComponentsInChildren<ParticleSystem>(true);
|
||||||
|
for (int i = 0; i < systems.Length; i++)
|
||||||
|
{
|
||||||
|
var ps = systems[i];
|
||||||
|
if (ps == null || ps.gameObject == root.gameObject) continue;
|
||||||
|
if (!IsActiveUnderRoot(ps.transform, root)) continue;
|
||||||
|
ps.gameObject.SetActive(false);
|
||||||
|
if (list == null) list = new List<GameObject>(16);
|
||||||
|
list.Add(ps.gameObject);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>节点在"根若激活"的前提下是否会被激活(检查自身到根之间每级的 activeSelf)</summary>
|
||||||
|
private static bool IsActiveUnderRoot(Transform node, Transform root)
|
||||||
|
{
|
||||||
|
for (var t = node; t != null && t != root; t = t.parent)
|
||||||
|
if (!t.gameObject.activeSelf) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>逐帧分批点亮粒子节点(每帧约 8ms 预算:快机一帧多开、慢机一帧一个)</summary>
|
||||||
|
private static IEnumerator ChunkEnableParticles(List<GameObject> nodes)
|
||||||
|
{
|
||||||
|
const double budgetMs = 8.0;
|
||||||
|
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
for (int i = 0; i < nodes.Count; i++)
|
||||||
|
{
|
||||||
|
if (nodes[i] != null) nodes[i].SetActive(true);
|
||||||
|
if (sw.Elapsed.TotalMilliseconds >= budgetMs)
|
||||||
|
{
|
||||||
|
sw.Restart();
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⭐ 进房早期(0~2%)预关闭"未激活座位"的多余 XJMH 炮台。
|
||||||
|
/// 原因:XJMH 座位预制体里 4 把炮台(SkeletonGraphic)默认激活,而座位首次 SetActive 时
|
||||||
|
/// 4 套骨架/材质/贴图会挤在同一帧全部首初始化(单帧尖峰);预关后 Awake 的 InitXJMHTurret
|
||||||
|
/// 只点亮默认那把 → 激活帧只初始化 1 套。其它玩家/bot 的座位在 100% 入座时才激活,
|
||||||
|
/// 同样受益(否则每个座位入座都要初始化 4 套)。
|
||||||
|
/// ⚠️ 只处理"尚未激活"的座位:已激活的座位 Awake 已跑过,会被 Admin 逻辑重新点亮,
|
||||||
|
/// 动它反而可能把炮台关掉回不来。
|
||||||
|
/// </summary>
|
||||||
|
private void PreCloseInactiveSitExtraTurrets()
|
||||||
|
{
|
||||||
|
if (list_Sits == null) return;
|
||||||
|
foreach (var sit in list_Sits)
|
||||||
|
{
|
||||||
|
if (sit == null || sit.turretControlMode != TurretControlMode.XJMH) continue;
|
||||||
|
if (sit.gameObject.activeSelf) continue; // 已激活座位不动
|
||||||
|
// 列表为空时 Awake 不会补开炮台 → 全关会留空座位,跳过
|
||||||
|
if (sit.xjmhTurretList == null || sit.xjmhTurretList.Count == 0) continue;
|
||||||
for (int i = 0; i < sit.xjmhTurretList.Count; i++)
|
for (int i = 0; i < sit.xjmhTurretList.Count; i++)
|
||||||
{
|
{
|
||||||
var t = sit.xjmhTurretList[i];
|
var t = sit.xjmhTurretList[i];
|
||||||
if (t != null && t.gameObject.activeSelf) t.gameObject.SetActive(false);
|
if (t != null && t.gameObject.activeSelf) t.gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ① 提前激活本地座位:Awake → InitXJMHTurret → 激活默认炮台(首初始化在这里完成,
|
|
||||||
// 被加载界面遮住)。100% 时 JoinGame 再 SetActive(true) 是幂等的,不影响正常入座流程
|
|
||||||
if (willActivate)
|
|
||||||
sit.gameObject.SetActive(true);
|
|
||||||
|
|
||||||
// 座位/炮台初始化(骨架首帧网格上传、材质铺开)多留两帧,再点飞机
|
|
||||||
yield return null;
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
// ② 飞机隐藏预热(座位激活后 currentTurret 已就绪 = 入场会用的那把)
|
|
||||||
var turret = sit != null ? sit.currentTurret as FlyTurretData : null;
|
|
||||||
if (turret != null)
|
|
||||||
turret.PrewarmEnterPlane();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshGGKCount()
|
private void RefreshGGKCount()
|
||||||
@@ -1379,6 +1509,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
// 90 ⭐确认点:走到这里时所有资源 await 都已完成
|
// 90 ⭐确认点:走到这里时所有资源 await 都已完成
|
||||||
// 90~100 平滑推进收尾(替代原来的 2 秒死等,条一直在动)
|
// 90~100 平滑推进收尾(替代原来的 2 秒死等,条一直在动)
|
||||||
SetLoadProgress(0.01f);
|
SetLoadProgress(0.01f);
|
||||||
|
LoadingStallWatchdog.Phase = "0~2 卸载大厅UI";
|
||||||
|
|
||||||
// ⭐ 卸载大厅 UI 资源(进游戏释放 HomeUIRes 内存,回大厅时由离房流程重新预载):
|
// ⭐ 卸载大厅 UI 资源(进游戏释放 HomeUIRes 内存,回大厅时由离房流程重新预载):
|
||||||
// 大厅主面板此时已被关闭(实例销毁时 SubUIManager.ReleaseAll 已释放子面板句柄),
|
// 大厅主面板此时已被关闭(实例销毁时 SubUIManager.ReleaseAll 已释放子面板句柄),
|
||||||
@@ -1391,7 +1522,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
// 不再把"打开小包 + 标签求交集"的耗时压在 78% 那一帧(进度条卡死点)
|
// 不再把"打开小包 + 标签求交集"的耗时压在 78% 那一帧(进度条卡死点)
|
||||||
_ = LoadBulletClip();
|
_ = LoadBulletClip();
|
||||||
|
|
||||||
|
// ⭐ 预关"未激活座位"的多余 XJMH 炮台(4 把 SkeletonGraphic 默认全开):
|
||||||
|
// 座位首次 SetActive 才做骨架/材质首初始化——预关后激活那一刻只初始化默认那把(1 套);
|
||||||
|
// 其它玩家/bot 的座位在 100% 入座时才激活,4 套→1 套,大幅削掉入座瞬间的卡顿
|
||||||
|
PreCloseInactiveSitExtraTurrets();
|
||||||
|
|
||||||
// 路线:2~30(大包同步解压期间回调不刷新 → 预估进度保证条持续推进)
|
// 路线:2~30(大包同步解压期间回调不刷新 → 预估进度保证条持续推进)
|
||||||
|
LoadingStallWatchdog.Phase = "2~30 路线";
|
||||||
StartCreepProgress(0.02f, 0.30f);
|
StartCreepProgress(0.02f, 0.30f);
|
||||||
await MonsterMoveLine.LoadBezier(p =>
|
await MonsterMoveLine.LoadBezier(p =>
|
||||||
{
|
{
|
||||||
@@ -1400,6 +1537,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
if (flow != _resourceFlowToken) return; // ⭐ 期间已退出/切换,本轮作废
|
if (flow != _resourceFlowToken) return; // ⭐ 期间已退出/切换,本轮作废
|
||||||
|
|
||||||
// 鱼包:30~60,内部子进度实时上报(预估进度兜底 LZMA 解压阻塞段,不再卡在 30)
|
// 鱼包:30~60,内部子进度实时上报(预估进度兜底 LZMA 解压阻塞段,不再卡在 30)
|
||||||
|
LoadingStallWatchdog.Phase = "30~60 鱼包";
|
||||||
StartCreepProgress(0.30f, 0.60f);
|
StartCreepProgress(0.30f, 0.60f);
|
||||||
await FishResourcesData.LoadFishAssetsData(p =>
|
await FishResourcesData.LoadFishAssetsData(p =>
|
||||||
{
|
{
|
||||||
@@ -1408,7 +1546,16 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
if (flow != _resourceFlowToken) return;
|
if (flow != _resourceFlowToken) return;
|
||||||
|
|
||||||
// 玩法音频:60~78
|
// 玩法音频:60~78
|
||||||
|
LoadingStallWatchdog.Phase = "60~78 音频";
|
||||||
StartCreepProgress(0.60f, 0.78f);
|
StartCreepProgress(0.60f, 0.78f);
|
||||||
|
|
||||||
|
// ⭐ XJMH 座位/飞机预热:把"首次实例化"的活提前到加载期做(这些活反正躲不掉,不做就会
|
||||||
|
// 堆到 100% 入座/入场动画那一帧卡——已确认注释掉它 100% 会卡一下)。
|
||||||
|
// 放在音频段起点:本段是真实加载耗时段(大量小包 IO,本来就有加载卡顿),混在里面的小帧不显眼。
|
||||||
|
// 重活已全部按帧拆开:座位外壳 1 帧 / 炮台骨架 1 帧 / 座位·炮台·飞机粒子逐帧点亮(每帧 8ms 预算)。
|
||||||
|
// 如果你更愿意"加载顺滑、接受 100% 卡一下",把下面这行注释回去即可。
|
||||||
|
PrewarmXJMHForLocalSeat();
|
||||||
|
|
||||||
await AudioResourcesData.LoadAudioGame(p =>
|
await AudioResourcesData.LoadAudioGame(p =>
|
||||||
{
|
{
|
||||||
if (flow == _resourceFlowToken) SetLoadProgress(Mathf.Max(_loadProgress, Mathf.Lerp(0.60f, 0.78f, p)));
|
if (flow == _resourceFlowToken) SetLoadProgress(Mathf.Max(_loadProgress, Mathf.Lerp(0.60f, 0.78f, p)));
|
||||||
@@ -1418,6 +1565,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
// ⭐ 开火音效 PW_Shoot 在 Default Local Group(Audio+PTCBZS 双标签交集检索):
|
// ⭐ 开火音效 PW_Shoot 在 Default Local Group(Audio+PTCBZS 双标签交集检索):
|
||||||
// 只命中 Default 小包,不把其它玩法的巨型音频包拉进内存;
|
// 只命中 Default 小包,不把其它玩法的巨型音频包拉进内存;
|
||||||
// 资源在 0~2% 已后台 kick-off 且全局常驻,这里 await 基本瞬时通过(不再把打开包的耗时压在 78% 主线程上)
|
// 资源在 0~2% 已后台 kick-off 且全局常驻,这里 await 基本瞬时通过(不再把打开包的耗时压在 78% 主线程上)
|
||||||
|
LoadingStallWatchdog.Phase = "78~84 开火音效";
|
||||||
StartCreepProgress(0.78f, 0.84f);
|
StartCreepProgress(0.78f, 0.84f);
|
||||||
await LoadBulletClip();
|
await LoadBulletClip();
|
||||||
StopCreepProgress();
|
StopCreepProgress();
|
||||||
@@ -1436,6 +1584,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadingStallWatchdog.Phase = "84~90 EnterRoom/初始鱼";
|
||||||
CreateFishManager.Instance.EnterRoom(gameType);
|
CreateFishManager.Instance.EnterRoom(gameType);
|
||||||
CreateFishManager.Instance.isResources = true;
|
CreateFishManager.Instance.isResources = true;
|
||||||
SetLoadProgress(0.87f);
|
SetLoadProgress(0.87f);
|
||||||
@@ -1468,12 +1617,10 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
AudioManager.Instance.ChangeBG(GameBgmAudioId);
|
AudioManager.Instance.ChangeBG(GameBgmAudioId);
|
||||||
|
|
||||||
// ⭐ 90% 确认点:走到这里所有资源加载都已完成(上面全是 await 顺序执行)
|
// ⭐ 90% 确认点:走到这里所有资源加载都已完成(上面全是 await 顺序执行)
|
||||||
|
// (XJMH 座位/飞机预热已挪到 60% 音频段起点——这里是纯净的平滑收尾,不再有重活)
|
||||||
|
LoadingStallWatchdog.Phase = "90~100 收尾";
|
||||||
SetLoadProgress(0.9f);
|
SetLoadProgress(0.9f);
|
||||||
|
|
||||||
// ⭐ XJMH 预热:借 90→100 的收尾窗口(进度条还在走)提前把本地座位/炮台 + 入场飞机点亮。
|
|
||||||
// 这些 XJMH 独有资产首次初始化(骨架/粒子/贴图)很重,堆到 100% 那帧玩家会看到卡一下
|
|
||||||
PrewarmXJMHForLocalSeat();
|
|
||||||
|
|
||||||
// ⭐ 90→100 平滑收尾:约 1 秒走完,进度条持续在动(替代原 2 秒死等;
|
// ⭐ 90→100 平滑收尾:约 1 秒走完,进度条持续在动(替代原 2 秒死等;
|
||||||
// 保留这段缓冲是等出鱼首帧/场景渲染稳定,比原来快 1 秒+)
|
// 保留这段缓冲是等出鱼首帧/场景渲染稳定,比原来快 1 秒+)
|
||||||
for (int i = 1; i <= 20; i++)
|
for (int i = 1; i <= 20; i++)
|
||||||
@@ -1491,6 +1638,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
|
|
||||||
// ⭐ 加载到 100%(进度条已隐藏):标记完成 + 执行挂起的进房初始化(座位/房间信息)。
|
// ⭐ 加载到 100%(进度条已隐藏):标记完成 + 执行挂起的进房初始化(座位/房间信息)。
|
||||||
// 入场动画等表现由初始化链路在此之后触发——玩家可见、位置已就绪
|
// 入场动画等表现由初始化链路在此之后触发——玩家可见、位置已就绪
|
||||||
|
LoadingStallWatchdog.Phase = "100 首屏初始化";
|
||||||
IsGameLoadCompleted = true;
|
IsGameLoadCompleted = true;
|
||||||
if (_pendingFirstShowInit)
|
if (_pendingFirstShowInit)
|
||||||
{
|
{
|
||||||
@@ -1498,6 +1646,9 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
ApplyFirstShowInit();
|
ApplyFirstShowInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载与首屏初始化完成 → 关闭监测(阶段置空,不再打日志)
|
||||||
|
LoadingStallWatchdog.Phase = "";
|
||||||
|
|
||||||
// ⭐ 无操作自动退出:加载完成,从现在开始计无操作时间
|
// ⭐ 无操作自动退出:加载完成,从现在开始计无操作时间
|
||||||
ArmIdleAutoExit();
|
ArmIdleAutoExit();
|
||||||
}
|
}
|
||||||
@@ -1868,6 +2019,9 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
private void SetLoadProgress(float p)
|
private void SetLoadProgress(float p)
|
||||||
{
|
{
|
||||||
p = Mathf.Clamp01(p);
|
p = Mathf.Clamp01(p);
|
||||||
|
// ⭐ 不回退:场景加载阶段的爬升/预估进度可能已把条推到前面,
|
||||||
|
// 后续固定值(0.01/0.02 等)不能把它拉回去(带上限取大值)
|
||||||
|
if (p < _loadProgress) p = _loadProgress;
|
||||||
_loadProgress = p;
|
_loadProgress = p;
|
||||||
if (_changeRoomBar != null)
|
if (_changeRoomBar != null)
|
||||||
_changeRoomBar.SetProgress(0.55f + p * 0.45f);
|
_changeRoomBar.SetProgress(0.55f + p * 0.45f);
|
||||||
@@ -1875,6 +2029,22 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
JinDuTiao.SetProgress(p);
|
JinDuTiao.SetProgress(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⭐ 第一步(只加载了 UI 面板、游戏场景还在加载中):进度条从 0 缓慢爬升到约 3%。
|
||||||
|
/// 由 WebSocketReponseList 在"面板显示后、场景加载前"调用;真实资源加载开始时由
|
||||||
|
/// LoadResources 接管(SetLoadProgress 不回退,固定起点值不会把条拉回去)。
|
||||||
|
/// </summary>
|
||||||
|
public void BeginSceneLoadingProgress()
|
||||||
|
{
|
||||||
|
SetLoadProgress(0.005f);
|
||||||
|
// creep 段末 = 0.05(内部上限 = 段末-2% ≈ 3%,给 LoadResources 的接管留空间)
|
||||||
|
StartCreepProgress(0.005f, 0.05f);
|
||||||
|
|
||||||
|
// ⭐ 挂"加载卡顿监测"(诊断):单帧 ≥120ms 打日志+阶段名,直接定位卡主线程的环节
|
||||||
|
LoadingStallWatchdog.Attach(this);
|
||||||
|
LoadingStallWatchdog.Phase = "场景加载(0~3%)";
|
||||||
|
}
|
||||||
|
|
||||||
// ---- 预估进度(大包 LZMA 同步解压期间主线程阻塞、回调不刷新 → 条卡死像没响应)----
|
// ---- 预估进度(大包 LZMA 同步解压期间主线程阻塞、回调不刷新 → 条卡死像没响应)----
|
||||||
/// <summary>加载进度当前值(真实或预估),预估推进时判断不回退</summary>
|
/// <summary>加载进度当前值(真实或预估),预估推进时判断不回退</summary>
|
||||||
private float _loadProgress = 0f;
|
private float _loadProgress = 0f;
|
||||||
@@ -6767,3 +6937,37 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⭐ 加载期卡顿监测(诊断用,挂面板对象、随面板销毁):
|
||||||
|
/// 加载全程 Update 检查单帧耗时,凡单帧 ≥120ms 就打一条日志并带"当前阶段"——
|
||||||
|
/// 用于精确定位是哪个环节顶住了主线程(进度条/界面动画卡顿的根因)。
|
||||||
|
/// 阶段名由 GameMainPanel_FishBase / FlyTurretData 在流程中随时更新;加载完成后置空即静默。
|
||||||
|
/// 排查完成后可整体删除本类及各 Phase 赋值。
|
||||||
|
/// </summary>
|
||||||
|
public class LoadingStallWatchdog : MonoBehaviour
|
||||||
|
{
|
||||||
|
/// <summary>当前阶段(由加载流程更新;为空=不监测)</summary>
|
||||||
|
public static string Phase = "";
|
||||||
|
private static int _logged;
|
||||||
|
|
||||||
|
/// <summary>在面板下挂一个监测器(存在则不重复创建)</summary>
|
||||||
|
public static void Attach(MonoBehaviour host)
|
||||||
|
{
|
||||||
|
if (host == null || host.GetComponentInChildren<LoadingStallWatchdog>(true) != null) return;
|
||||||
|
var go = new GameObject("LoadingStallWatchdog");
|
||||||
|
go.transform.SetParent(host.transform, false);
|
||||||
|
go.AddComponent<LoadingStallWatchdog>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Phase)) return;
|
||||||
|
float dt = Time.unscaledDeltaTime;
|
||||||
|
if (dt >= 0.12f && _logged < 80)
|
||||||
|
{
|
||||||
|
_logged++;
|
||||||
|
Debug.Log($"[加载卡顿] 「{Phase}」单帧 {dt * 1000f:F0}ms(第 {_logged} 条)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4308,6 +4308,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 6dec7b077ca94844c8c1360f71e7aa58, type: 3}
|
m_Script: {fileID: 11500000, guid: 6dec7b077ca94844c8c1360f71e7aa58, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
|
buttonClickAudioID: 60009
|
||||||
panelAddressConfig: {fileID: 11400000, guid: 21aa1c64fb06c5d4c9769a8650a3dbc1, type: 2}
|
panelAddressConfig: {fileID: 11400000, guid: 21aa1c64fb06c5d4c9769a8650a3dbc1, type: 2}
|
||||||
subPanelParent: {fileID: 1078076760308578925}
|
subPanelParent: {fileID: 1078076760308578925}
|
||||||
textMeshProUGUI_RoomID: {fileID: 222610915537559086}
|
textMeshProUGUI_RoomID: {fileID: 222610915537559086}
|
||||||
|
|||||||
@@ -222,6 +222,17 @@ public class UIHome_BY_SelectRoomLevelPanel : SubUIBase
|
|||||||
}
|
}
|
||||||
if (currGameType!= GameType.JQQD)
|
if (currGameType!= GameType.JQQD)
|
||||||
{
|
{
|
||||||
|
// ⭐ 预载该玩法的主游戏面板(纯 UI 资源、异步后台加载):选场页停留的几秒足够加载完,
|
||||||
|
// 点场次进房时 ShowAsync 命中缓存直接秒开——"第一步只加载 UI,先把 UI 展示出来,
|
||||||
|
// 显得加载快",其它资源(场景/鱼/音频)等 UI 出来后再加载
|
||||||
|
switch (currGameType)
|
||||||
|
{
|
||||||
|
case GameType.FLZY: UIManager.Instance.PreloadPanel(UIPanel.MainGamePanelFLZY); break;
|
||||||
|
case GameType.YYSC: UIManager.Instance.PreloadPanel(UIPanel.MainGamePanelYYSC); break;
|
||||||
|
case GameType.XJMH: UIManager.Instance.PreloadPanel(UIPanel.MainGamePanelXJMH); break;
|
||||||
|
case GameType.HHWK: UIManager.Instance.PreloadPanel(UIPanel.MainGamePanelHHWK); break;
|
||||||
|
}
|
||||||
|
|
||||||
GameObject LV1 = SelectRoom1.transform.GetChild(((int)currGameType)).gameObject;
|
GameObject LV1 = SelectRoom1.transform.GetChild(((int)currGameType)).gameObject;
|
||||||
LV1.SetActive(true);
|
LV1.SetActive(true);
|
||||||
var Lv1Item = LV1.GetComponent<SeccionItem>();
|
var Lv1Item = LV1.GetComponent<SeccionItem>();
|
||||||
|
|||||||
Reference in New Issue
Block a user