This commit is contained in:
2026-10-09 22:06:36 +08:00
parent 3a985587bf
commit 1f4c19904f
25 changed files with 715 additions and 371 deletions
+91 -13
View File
@@ -1429,12 +1429,33 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
currentTurretNumber = turretNumber;
// 从 TurretResourcesData 拿预制体
// ⭐ 散包按需加载:缓存没有时异步取(PT{编号} 标签),完成后实例化
StartCoroutine(LoadTurretRoutine(turretNumber, ++_turretLoadSeq));
}
/// <summary>炮台加载序号(防加载期间再次切换的竞态)</summary>
private int _turretLoadSeq = 0;
/// <summary>炮台异步按需加载协程:AcquireTurretPrefabAsync 完成后实例化(原同步逻辑后半段)</summary>
private IEnumerator LoadTurretRoutine(int turretNumber, int seq)
{
GameObject prefab = TurretResourcesData.GetTurretPrefab(turretNumber);
if (prefab == null)
{
Debug.LogWarning($"[SitPosData] 炮台预制体未加载: #{turretNumber}");
return;
var task = TurretResourcesData.AcquireTurretPrefabAsync(turretNumber);
while (!task.IsCompleted) yield return null;
if (seq != _turretLoadSeq) // 期间又切换了炮台 → 丢弃并归还引用
{
TurretResourcesData.ReleaseTurretPrefab(turretNumber);
yield break;
}
prefab = task.Result;
}
if (prefab == null)
{
TurretResourcesData.ReleaseTurretPrefab(turretNumber);
Debug.LogWarning($"[SitPosData] 炮台预制体未加载: #{turretNumber}(检查 PT{turretNumber} 标签配置)");
yield break;
}
// 克隆到父节点
@@ -1451,11 +1472,14 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
Debug.LogError($"[SitPosData] 预制体上未找到 TurretData 组件: #{turretNumber}");
Destroy(instance);
return;
yield break;
}
currentTurret.turretNumber = turretNumber;
// ⭐ 战神装备中判断:异步加载完成后实时读(原方法开头局部变量 zhanShenActive 不能跨协程)
bool zhanShenActive = currentZhanShenData != null;
// 缓存旋转节点:优先用 TurretData.tra_RotationPivot,否则回退父节点
tra_CurrTurret = GetTurretRotationPivot(currentTurret);
@@ -1591,12 +1615,30 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
// 先清理已有翅膀
ClearWing();
// 从 TurretResourcesData 拿预制体
// ⭐ 散包按需加载(异步):缓存没有时按 PT{编号} 标签取,完成后实例化
StartCoroutine(LoadWingRoutine(turretNumber, ++_turretLoadSeq));
}
/// <summary>翅膀异步按需加载协程(模式同炮台:seq 防竞态)</summary>
private IEnumerator LoadWingRoutine(int turretNumber, int seq)
{
GameObject prefab = TurretResourcesData.GetTurretPrefab(turretNumber);
if (prefab == null)
{
Debug.LogWarning($"[SitPosData] 翅膀预制体未加载: #{turretNumber}");
return;
var task = TurretResourcesData.AcquireTurretPrefabAsync(turretNumber);
while (!task.IsCompleted) yield return null;
if (seq != _turretLoadSeq)
{
TurretResourcesData.ReleaseTurretPrefab(turretNumber);
yield break;
}
prefab = task.Result;
}
if (prefab == null)
{
TurretResourcesData.ReleaseTurretPrefab(turretNumber);
Debug.LogWarning($"[SitPosData] 翅膀预制体未加载: #{turretNumber}(检查 PT{turretNumber} 标签配置)");
yield break;
}
// 克隆到 wingParent,保持预制体原始位置/旋转/缩放
@@ -1637,20 +1679,52 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
/// (渲染由座位预设的 Camera + RawImage 完成,显示节点挂在 turretRotate 下会跟随瞄准旋转)。
/// ⭐ 炮台/战神显示二选一:加载战神后隐藏 turretParent(仅游戏内,切换面板 UI 不受影响)。
/// </summary>
/// <summary>战神加载序号(防加载期间再次切换的竞态:旧协程完成后丢弃结果)</summary>
private int _zsLoadSeq = 0;
public void LoadZhanShen(int zhanShenNumber)
{
// XJMH 模式没有战神概念,直接跳过(和翅膀一致)
if (turretControlMode == TurretControlMode.XJMH) return;
// 先清理已有战神(保留预设的 Camera,它是用来渲染战神到 RawImage 的)
ClearZhanShenInstance();
// ⭐ 切换战神:释放上一个的按需资源引用(别的座位还在用同一个战神则只减计数不卸载)
int prevNumber = currentZhanShenNumber;
ClearZhanShenInstance(); // 先清理已有战神实例(保留预设的 Camera)
if (prevNumber > 0 && prevNumber != zhanShenNumber)
TurretResourcesData.ReleaseZhanShen(prevNumber, ZhanShenUsage.GamePlay);
// 从 TurretResourcesData 拿游戏内使用的战神预制体
GameObject prefab = TurretResourcesData.GetZhanShenPrefab(zhanShenNumber, ZhanShenUsage.GamePlay);
// ⭐ 异步按需加载(不再阻塞主线程):散包模式下战神不预载,这里现取
StartCoroutine(LoadZhanShenRoutine(zhanShenNumber, ++_zsLoadSeq));
}
/// <summary>
/// 战神异步加载协程:等 AcquireZhanShenAsync 完成后实例化。
/// 加载期间座位被销毁 / 又切换了别的战神 → 丢弃本次结果并归还引用。
/// </summary>
private IEnumerator LoadZhanShenRoutine(int zhanShenNumber, int seq)
{
var task = TurretResourcesData.AcquireZhanShenAsync(zhanShenNumber, ZhanShenUsage.GamePlay);
while (!task.IsCompleted)
yield return null;
// 竞态丢弃:期间又切换了战神(seq 变了)→ 归还本次引用
if (seq != _zsLoadSeq)
{
TurretResourcesData.ReleaseZhanShen(zhanShenNumber, ZhanShenUsage.GamePlay);
yield break;
}
GameObject prefab = task.Result;
if (prefab == null)
{
Debug.LogWarning($"[SitPosData] 战神使用预制体未加载: #{zhanShenNumber}(检查 ZSYX 标签配置)");
return;
// 标签未配置(散包未拆):回退全量字典(启动 PT+ZSYX 加载的)
prefab = TurretResourcesData.GetZhanShenPrefab(zhanShenNumber, ZhanShenUsage.GamePlay);
}
if (prefab == null)
{
TurretResourcesData.ReleaseZhanShen(zhanShenNumber, ZhanShenUsage.GamePlay);
Debug.LogWarning($"[SitPosData] 战神使用预制体未加载: #{zhanShenNumber}(检查 ZS{zhanShenNumber}+ZSYX 标签配置)");
yield break;
}
// 克隆到 zhanShenParent,保持预制体原始位置/旋转/缩放
@@ -1702,7 +1776,11 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
/// <summary>清除战神并恢复普通炮台显示(炮台/战神显示二选一的另一半)</summary>
public void ClearZhanShen()
{
// ⭐ 卸下战神:释放按需资源引用(归零才真正卸包)
int prevNumber = currentZhanShenNumber;
ClearZhanShenInstance();
if (prevNumber > 0)
TurretResourcesData.ReleaseZhanShen(prevNumber, ZhanShenUsage.GamePlay);
currentZhanShenNumber = 0;
// 恢复普通炮台显示(特殊鱼炮台使用中不显示:等 RestoreTurretVisual 统一恢复)