飞机场存档

This commit is contained in:
2026-07-28 18:29:49 +08:00
parent ddd9c6fd00
commit 2afafb8aa6
18 changed files with 1515 additions and 114 deletions
+248 -14
View File
@@ -5,6 +5,15 @@ using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>炮台控制模式</summary>
public enum TurretControlMode
{
/// <summary>普通模式:动态克隆炮台,显示金币+钻石,按钮打开面板切换</summary>
Normal = 0,
/// <summary>星际迷航模式:座位子对象激活/停用,只显示金币,长按炮台弹出扇形切换</summary>
XJMH = 1
}
public class SitPosData : MonoBehaviour
{
/// <summary>本地玩家的座位引用(由游戏面板初始化时设置)</summary>
@@ -41,6 +50,10 @@ public class SitPosData : MonoBehaviour
[Tooltip("炮台实例化的父节点")]
public Transform turretParent;
[Header("炮台控制模式")]
[Tooltip("Normal=普通模式(动态克隆炮台,显示金币+钻石,按钮切换); XJMH=星际迷航模式(座位子对象激活/停用,只显示金币,长按扇形切换)")]
public TurretControlMode turretControlMode = TurretControlMode.Normal;
[Tooltip("炮台锚点位置(相对 turretParent)")]
public Vector2 turretAnchoredPos = Vector2.zero;
@@ -50,6 +63,14 @@ public class SitPosData : MonoBehaviour
/// <summary>当前运行中的炮台实例</summary>
public TurretData currentTurret;
// -------------------------
// XJMH 炮台列表(星际迷航专用)
// -------------------------
[Header("XJMH 炮台列表")]
[Tooltip("XJMH 模式专用:在 Inspector 中拖入座位下的所有炮台子对象(带 TurretData 组件)。" +
"数量不多,建议按炮台编号升序排列,便于扇形切换按索引选择。")]
public List<TurretData> xjmhTurretList = new List<TurretData>();
// 状态机入口(GameMainPanel 调用)
public Action<TurretState> OnStateChange;
@@ -90,8 +111,63 @@ public class SitPosData : MonoBehaviour
private void Awake()
{
btn_TurretAdd.onClick.AddListener(() => ChangeTurretAddConsumeNum());
btn_TurretMinus.onClick.AddListener(() => ChangeTurretMinusConsumeNum());
if (btn_TurretAdd != null)
btn_TurretAdd.onClick.AddListener(() => ChangeTurretAddConsumeNum());
if (btn_TurretMinus != null)
btn_TurretMinus.onClick.AddListener(() => ChangeTurretMinusConsumeNum());
// XJMH 模式:隐藏钻石显示(只显示金币)
if (turretControlMode == TurretControlMode.XJMH && tMP_DiamondNum != null)
tMP_DiamondNum.gameObject.SetActive(false);
// XJMH 模式:炮台是座位自带子对象,预制体里已摆好,不需要加载。
// 这里只做引用初始化,不做激活/停用。
if (turretControlMode == TurretControlMode.XJMH)
InitXJMHTurret();
}
/// <summary>
/// XJMH 模式:炮台是座位自带子对象,预制体里已摆好激活状态,不需要 LoadTurret 加载。
/// 此方法只做引用初始化:从 <see cref="xjmhTurretList"/> 取第一个激活的炮台赋给 currentTurret,
/// 并绑定旋转节点、状态机入口、世界坐标缓存。不做任何激活/停用操作。
/// </summary>
private void InitXJMHTurret()
{
if (xjmhTurretList == null || xjmhTurretList.Count == 0)
{
Debug.LogWarning($"[SitPosData] XJMH 炮台列表未配置,座位 {posID} 无炮台可用");
return;
}
// 优先取列表中第一个激活的炮台;若全部未激活,取 list[0]
TurretData found = null;
foreach (var td in xjmhTurretList)
{
if (td == null) continue;
if (td.gameObject.activeSelf)
{
found = td;
break;
}
}
if (found == null)
{
found = xjmhTurretList[0];
found.gameObject.SetActive(true);
}
currentTurret = found;
currentTurretNumber = found.turretNumber;
Transform parent = turretParent != null ? turretParent : transform;
tra_CurrTurret = currentTurret.transform.parent != parent
? currentTurret.transform.parent
: currentTurret.transform;
OnStateChange = currentTurret.ChangeState;
UpdateTurretWorldPos();
Debug.Log($"[SitPosData] XJMH 炮台引用已初始化: #{currentTurretNumber}");
}
private void OnEnable()
@@ -127,13 +203,17 @@ public class SitPosData : MonoBehaviour
{
localPlayerSit = this;
var cannonUsing = GameManager.Instance.user.cannonUsing;
if (cannonUsing != null && int.TryParse(cannonUsing.number, out int num))
LoadTurret(num);
// XJMH 模式:炮台是座位自带子对象,Awake 已初始化引用,不需要加载
if (turretControlMode != TurretControlMode.XJMH)
{
var cannonUsing = GameManager.Instance.user.cannonUsing;
if (cannonUsing != null && int.TryParse(cannonUsing.number, out int num))
LoadTurret(num);
var wingUsing = GameManager.Instance.user.wingUsing;
if (wingUsing != null && int.TryParse(wingUsing.number, out int wingNum))
LoadWing(wingNum);
var wingUsing = GameManager.Instance.user.wingUsing;
if (wingUsing != null && int.TryParse(wingUsing.number, out int wingNum))
LoadWing(wingNum);
}
}
// 非人机玩家加入时,自动分配为首个房主
@@ -177,13 +257,28 @@ public class SitPosData : MonoBehaviour
}
}
// ==================== 炮台加载(动态克隆) ====================
// ==================== 炮台加载 ====================
/// <summary>
/// 根据炮台编号,从 Addressables 加载预制体并克隆到 turretParent。
/// 位置/旋转/缩放保持预制体原始值,不动。
/// 根据炮台编号加载炮台。
/// Normal 模式:从 Addressables 加载预制体并克隆到 turretParent。
/// XJMH 模式:炮台是座位子对象,激活对应编号子对象、停用其他。
/// </summary>
public void LoadTurret(int turretNumber)
{
if (turretControlMode == TurretControlMode.XJMH)
{
SwitchTurretChild(turretNumber);
return;
}
LoadTurretNormal(turretNumber);
}
/// <summary>
/// 普通模式:从 Addressables 加载预制体并克隆到 turretParent。
/// 位置/旋转/缩放保持预制体原始值,不动。
/// </summary>
private void LoadTurretNormal(int turretNumber)
{
// ⭐ 换炮台时只清活跃子弹(清屏),保留池缓存(同 prefab 能复用)
// 用 ClearActive 而非 ClearAll:ClearAll 会清池导致永远不复用
@@ -225,17 +320,153 @@ public class SitPosData : MonoBehaviour
currentTurret.turretNumber = turretNumber;
// 缓存旋转节点
//tra_CurrTurret = currentTurret.transform.GetChild(0);
tra_CurrTurret = currentTurret.transform.parent;
// 绑定状态机入口
OnStateChange = currentTurret.ChangeState;
// ⭐ 缓存炮台在世界坐标(Z=0平面)的位置,bot AI/锁定检测距离时用
// 和子弹起点(GetBulletStartWorldPos)用相同的 UI→世界 转换方式
UpdateTurretWorldPos();
Debug.Log($"[SitPosData] 炮台已加载: #{turretNumber}");
Debug.Log($"[SitPosData] 炮台已加载(Normal): #{turretNumber}");
}
/// <summary>
/// XJMH 模式:炮台都是座位的子对象,激活对应编号的炮台、停用其他。
/// 不需要 Instantiate/Destroy,只做激活/停用,无需额外处理。
/// 优先从 <see cref="xjmhTurretList"/> 查找,列表为空时回退遍历子对象。
/// </summary>
private void SwitchTurretChild(int turretNumber)
{
BulletPool.Instance.ClearActive();
// 炮台挂载根:turretParent 优先,否则用座位自身
Transform parent = turretParent != null ? turretParent : transform;
// 优先用 Inspector 配置的炮台列表
TurretData found = null;
if (xjmhTurretList != null && xjmhTurretList.Count > 0)
{
foreach (var td in xjmhTurretList)
{
if (td == null) continue;
bool active = td.turretNumber == turretNumber;
td.gameObject.SetActive(active);
if (active) found = td;
}
}
else
{
// 回退:列表未配置时遍历子对象
for (int i = 0; i < parent.childCount; i++)
{
var child = parent.GetChild(i);
var td = child.GetComponent<TurretData>();
if (td == null) continue;
if (td.turretNumber == turretNumber)
{
child.gameObject.SetActive(true);
found = td;
}
else
{
child.gameObject.SetActive(false);
}
}
}
if (found == null)
{
Debug.LogWarning($"[SitPosData] XJMH 子对象中未找到炮台 #{turretNumber}");
return;
}
currentTurretNumber = turretNumber;
currentTurret = found;
// 炮台若挂在中间旋转容器下,用容器作为旋转节点;否则用炮台自身
tra_CurrTurret = currentTurret.transform.parent != parent
? currentTurret.transform.parent
: currentTurret.transform;
OnStateChange = currentTurret.ChangeState;
UpdateTurretWorldPos();
Debug.Log($"[SitPosData] 炮台已切换(XJMH): #{turretNumber}");
}
/// <summary>
/// XJMH 模式:按列表索引直接切换炮台。
/// 用于扇形切换 UI 中按位置选择炮台,避免再做编号匹配。
/// </summary>
/// <param name="index">xjmhTurretList 中的索引</param>
/// <returns>切换成功返回 true;索引越界或列表为空返回 false</returns>
public bool SwitchTurretByIndex(int index)
{
if (turretControlMode != TurretControlMode.XJMH) return false;
if (xjmhTurretList == null || index < 0 || index >= xjmhTurretList.Count) return false;
var td = xjmhTurretList[index];
if (td == null) return false;
// 命中当前炮台则无需切换
if (td.turretNumber == currentTurretNumber) return true;
SwitchTurretChild(td.turretNumber);
return true;
}
/// <summary>
/// XJMH 模式:根据当前炮台在 xjmhTurretList 中的索引返回下一个炮台编号。
/// 用于"切换到下一把"的快捷操作。循环切换,列表为空返回 -1。
/// </summary>
public int GetNextTurretNumber()
{
if (turretControlMode != TurretControlMode.XJMH) return -1;
if (xjmhTurretList == null || xjmhTurretList.Count == 0) return -1;
int currIdx = xjmhTurretList.FindIndex(td => td != null && td.turretNumber == currentTurretNumber);
if (currIdx < 0) return xjmhTurretList[0].turretNumber;
int nextIdx = (currIdx + 1) % xjmhTurretList.Count;
return xjmhTurretList[nextIdx].turretNumber;
}
/// <summary>
/// 获取当前可用的炮台编号列表。
/// Normal 模式:从资源表按类型查询。
/// XJMH 模式:优先从 <see cref="xjmhTurretList"/> 读取,列表为空时回退扫描座位子对象。
/// </summary>
public List<int> GetAvailableTurretNumbers()
{
var result = new List<int>();
if (turretControlMode == TurretControlMode.XJMH)
{
// 优先用配置的炮台列表
if (xjmhTurretList != null && xjmhTurretList.Count > 0)
{
foreach (var td in xjmhTurretList)
if (td != null) result.Add(td.turretNumber);
}
else
{
// 回退:扫描座位子对象
Transform parent = turretParent != null ? turretParent : transform;
for (int i = 0; i < parent.childCount; i++)
{
var td = parent.GetChild(i).GetComponent<TurretData>();
if (td != null)
result.Add(td.turretNumber);
}
}
}
else
{
var list = TurretResourcesData.GetTurretDataByType(1);
if (list != null)
result = list.ConvertAll(d => d.turretNumber);
}
return result;
}
/// <summary>
@@ -286,6 +517,9 @@ public class SitPosData : MonoBehaviour
/// </summary>
public void LoadWing(int turretNumber)
{
// XJMH 模式没有翅膀概念,直接跳过
if (turretControlMode == TurretControlMode.XJMH) return;
// 先清理已有翅膀(保留预设的 Camera,它是用来渲染翅膀到 RawImage 的)
for (int i = wingParent.childCount - 1; i >= 0; i--)
{