Files
aibis-dream/Assets/Scripts/MiniGame/Gear/GearSystem.cs
T
2025-08-19 20:45:12 +08:00

403 lines
12 KiB
C#

using System;
using System.Collections;
using System.Linq;
using AibisDream.FixSystem;
using AibisDream.Framework;
using AibisDream.Kit;
using Cinemachine;
using DG.Tweening;
using UnityEditor;
using UnityEngine;
namespace AibisDream
{
public class GearSystem : SystemHasData
{
#region 索引
public GameObject gearPrefab;
public GameObject shaftPrefab;
[Header("组件索引")]
[SerializeField] private Transform panel;
[SerializeField] private SpriteRenderer cover;
[SerializeField] private Transform coverStick;
[SerializeField] private Transform needle;
[SerializeField] private Transform shaftRoot;
private ShaftGraph _shaftGraph;
#endregion
[Header("位置参数")]
public Vector3 coverUpPos;
public Vector3 coverDownPos;
public Vector3 panelOpenPos;
public Vector3 panelClosePos;
public Vector3 needleEmptyPos;
public Vector3[] needlePosArr;
public float needleDuration;
public float initSpeed = 1;
private bool _isTargetReached;
private bool _isDiscReady;
[HideInInspector] public bool isAvailable;
private bool _isInteractive;
public bool IsGearActive => isAvailable && _isInteractive;
private IUnRegister[] _evtUnRegisters;
private void Awake()
{
Init();
}
#region 生命周期管理
private void Init()
{
FixSystemCenter.SystemDic.Register(this);
// 注册相机
var virtualCam = transform.Find("Gear Camera").GetComponent<ICinemachineCamera>();
CameraKit.Instance.RegisterCamera(CameraEnum.Gear, virtualCam);
}
private void OnEnable()
{
var unRegister1 = EnumEventSystem.Global.Register(InteractionEventEnum.Start, () => _isInteractive = true);
var unRegister2 = EnumEventSystem.Global.Register(InteractionEventEnum.End, () => _isInteractive = false);
_evtUnRegisters = new[] { unRegister1, unRegister2 };
}
private void OnDisable()
{
foreach (var evtUnRegister in _evtUnRegisters)
{
evtUnRegister.UnRegister();
}
}
private void Start()
{
InitShaftGraph();
LinkEngineSpeed();
}
private void InitShaftGraph()
{
var shafts = shaftRoot.GetComponentsInChildren<Shaft>();
var panelShafts = panel.GetComponentsInChildren<Shaft>();
_shaftGraph = new ShaftGraph(shafts, panelShafts);
}
private void LinkEngineSpeed()
{
var engine = FixSystemCenter.SystemDic.Get<EngineSystem>();
_shaftGraph.StartRotate(initSpeed);
engine.updateSpeedEvent.AddListener(_shaftGraph.Accelerate);
}
private void UnlinkEngineSpeed()
{
var engine = FixSystemCenter.SystemDic.Get<EngineSystem>();
_shaftGraph.StartRotate(initSpeed);
engine.updateSpeedEvent.RemoveListener(_shaftGraph.Accelerate);
}
private void OnDestroy()
{
CameraKit.Instance.UnRegisterCamera(CameraEnum.Gear);
}
#endregion
/// <summary>
/// 判断吸附位置
/// </summary>
/// <param name="pos">齿轮当前位置</param>
/// <param name="gearRadius">齿轮半径</param>
/// <returns>能够被吸附的轴</returns>
public Shaft CheckClosestShaft(Vector3 pos, float gearRadius)
{
return _shaftGraph.QuerySnapShaft(pos, gearRadius);
}
/// <summary>
/// 判断齿轮能不能放进轴内
/// </summary>
/// <param name="sourceShaft">当前轴</param>
/// <param name="gearRadius">齿轮半径</param>
/// <returns>是否可用</returns>
public bool CheckGearSuitable(Shaft sourceShaft, float gearRadius)
{
return _shaftGraph.CheckGearSuitable(sourceShaft, gearRadius);
}
/// <summary>
/// 某个轴上齿轮发生变化时更新临接关系
/// </summary>
/// <param name="shaftId">轴ID</param>
public void ChangeGraphVertex(int shaftId)
{
_shaftGraph?.ChangeVertex(shaftId);
}
/// <summary>
/// 按轴名称弹出齿轮
/// </summary>
/// <param name="shaftName">轴名称</param>
/// <returns></returns>
public void PopupGearByShaftName(string shaftName)
{
var shafts = shaftRoot.GetComponentsInChildren<Shaft>();
var target = Array.Find(shafts, shaft => shaft.gameObject.name == shaftName);
target.PopupGear();
}
#region 胜利状况判断
public bool IsShaftInBox(Transform shaft)
{
return shaftRoot == shaft.parent;
}
public void CheckGearSystemState()
{
Debug.Log("Check Gear");
if (_shaftGraph.AllRunning())
{
if (_shaftGraph.AllNewGear())
{
StorageSystem.Instance?.SetValue("$allNewGear", true);
}
DialogController.Instance?.StartDialogNode("AllGearsRunning");
}
}
public void ReachTargetSpeed()
{
if (!_isTargetReached)
{
StorageSystem.Instance?.SetValue("$speedReached", true);
_isTargetReached = true;
}
}
public void ResetTargetState()
{
if (_isTargetReached)
{
StorageSystem.Instance?.SetValue("$speedReached", false);
_isTargetReached = false;
}
}
#endregion
public IEnumerator OpenCover()
{
// 旋转拉杆
yield return coverStick.DORotate(new Vector3(0, 0, -90), 1.5f).WaitForCompletion();
// 开盖
var sq = DOTween.Sequence();
sq.Join(cover.transform.DOLocalMove(coverUpPos, 1.5f));
sq.Join(cover.DOFade(0, 1.5f));
yield return sq.WaitForCompletion();
isAvailable = true;
}
public IEnumerator CloseCover()
{
isAvailable = false;
// 关盖
var sq = DOTween.Sequence();
sq.Join(cover.transform.DOLocalMove(coverDownPos, 1.5f));
sq.Join(cover.DOFade(1, 1.5f));
yield return sq.WaitForCompletion();
// 旋转拉杆
yield return coverStick.DORotate(new Vector3(0, 0, 0), 1.5f).WaitForCompletion();
}
public IEnumerator OpenGearPanel()
{
panel.gameObject.SetActive(true);
yield return panel.DOLocalMove(panelOpenPos, 1f).WaitForCompletion();
}
public IEnumerator CloseGearPanel()
{
yield return panel.DOLocalMove(panelClosePos, 1f).WaitForCompletion();
panel.gameObject.SetActive(false);
}
public IEnumerator MoveNeedle(int discIdx)
{
Vector3 target;
if (discIdx > needlePosArr.Length || discIdx <= 0)
{
target = needleEmptyPos;
}
else
{
target = needlePosArr[discIdx - 1];
}
yield return needle.DORotate(target, needleDuration).WaitForCompletion();
}
#region 数据保存与加载
private static readonly string DataPath = Application.streamingAssetsPath + "/LevelData/GearSystem/";
private string[] _keyOptions;
public override string CurDataKey { get; set; }
public override string GetConfigPath()
{
return DataPath;
}
public override void LoadLevel()
{
if (string.IsNullOrEmpty(CurDataKey))
{
Debug.Log("配置项名称为空");
return;
}
if (!ConfigUtil.Instance.TryLoadConfig<GearSystemData>(DataPath + CurDataKey, out var data))
{
Debug.Log("没有找到配置项");
return;
}
#if UNITY_EDITOR
// 现将当前配置保存为temp避免丢失
if (CurDataKey != "temp.json")
{
SaveByKey("temp.json");
}
#endif
LoadByData(data);
}
private void LoadByData(GearSystemData gearSystemData)
{
// 先清除
var shaftsObj = GetComponentsInChildren<Shaft>(true);
foreach (var oldShaft in shaftsObj)
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
DestroyImmediate(oldShaft.gameObject);
}
else
{
Destroy(oldShaft.gameObject);
}
#else
Destroy(oldShaft.gameObject);
#endif
}
// 再添加
var shafts = new Shaft[gearSystemData.shaftLevelDataArray.Length];
for (int i = 0; i < gearSystemData.shaftLevelDataArray.Length; i++)
{
var newShaft = Instantiate(shaftPrefab, shaftRoot).GetComponent<Shaft>();
newShaft.Load(gearSystemData.shaftLevelDataArray[i]);
shafts[i] = newShaft;
}
var panelShafts = new Shaft[gearSystemData.panelShaftArray.Length];
for (int i = 0; i < gearSystemData.panelShaftArray.Length; i++)
{
var newShaft = Instantiate(shaftPrefab, panel, true).GetComponent<Shaft>();
newShaft.Load(gearSystemData.panelShaftArray[i]);
panelShafts[i] = newShaft;
}
#if UNITY_EDITOR
if (!EditorApplication.isPlaying) return;
#endif
UnlinkEngineSpeed();
_shaftGraph = new ShaftGraph(shafts, panelShafts);
LinkEngineSpeed();
}
public override void SaveLevel()
{
if (string.IsNullOrEmpty(CurDataKey)) return;
SaveByKey(CurDataKey);
}
private void SaveByKey(string key)
{
var shaftDataArray = shaftRoot
.GetComponentsInChildren<Shaft>()
.Select(shaft => shaft.Save())
.ToArray();
var panelShaftArray = panel
.GetComponentsInChildren<Shaft>()
.Select(shaft => shaft.Save())
.ToArray();
var data = new GearSystemData
{
shaftLevelDataArray = shaftDataArray,
panelShaftArray = panelShaftArray
};
ConfigUtil.Instance.SaveConfig(data, DataPath + key);
}
public void AddShaft()
{
Instantiate(shaftPrefab, shaftRoot);
}
public void LoadPanelShaft(string dataKey)
{
// 查询
if (!ConfigUtil.Instance.TryLoadConfig<GearSystemData>(DataPath + dataKey, out var data))
{
Debug.Log("没有找到配置项");
return;
}
// 删除面板上的齿轮
var panelShafts = panel.GetComponentsInChildren<Shaft>();
foreach (var shaftItem in panelShafts)
{
Destroy(shaftItem);
}
// 读取数据
var newPanelShafts = new Shaft[data.panelShaftArray.Length];
for (int i = 0; i < data.panelShaftArray.Length; i++)
{
var newShaft = Instantiate(shaftPrefab, panel, true).GetComponent<Shaft>();
newShaft.Load(data.panelShaftArray[i]);
newPanelShafts[i] = newShaft;
}
_shaftGraph.UpdatePanel(newPanelShafts);
}
#endregion
}
[Serializable]
public struct GearSystemData
{
public ShaftLevelData[] shaftLevelDataArray;
public ShaftLevelData[] panelShaftArray;
}
}