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(); CameraKit.Instance.RegisterCamera(CameraEnum.Gear, virtualCam); } private void OnEnable() { var unRegister1 = EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, () => _isInteractive = true); var unRegister2 = EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, () => _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(); var panelShafts = panel.GetComponentsInChildren(); _shaftGraph = new ShaftGraph(shafts, panelShafts); } private void LinkEngineSpeed() { var engine = FixSystemCenter.SystemDic.Get(); _shaftGraph.StartRotate(initSpeed); engine.updateSpeedEvent.AddListener(_shaftGraph.Accelerate); } private void UnlinkEngineSpeed() { var engine = FixSystemCenter.SystemDic.Get(); _shaftGraph.StartRotate(initSpeed); engine.updateSpeedEvent.RemoveListener(_shaftGraph.Accelerate); } private void OnDestroy() { CameraKit.Instance.UnRegisterCamera(CameraEnum.Gear); } #endregion /// /// 判断吸附位置 /// /// 齿轮当前位置 /// 齿轮半径 /// 能够被吸附的轴 public Shaft CheckClosestShaft(Vector3 pos, float gearRadius) { return _shaftGraph.QuerySnapShaft(pos, gearRadius); } /// /// 判断齿轮能不能放进轴内 /// /// 当前轴 /// 齿轮半径 /// 是否可用 public bool CheckGearSuitable(Shaft sourceShaft, float gearRadius) { return _shaftGraph.CheckGearSuitable(sourceShaft, gearRadius); } /// /// 某个轴上齿轮发生变化时更新临接关系 /// /// 轴ID public void ChangeGraphVertex(int shaftId) { _shaftGraph?.ChangeVertex(shaftId); } /// /// 按轴名称弹出齿轮 /// /// 轴名称 /// public void PopupGearByShaftName(string shaftName) { var shafts = shaftRoot.GetComponentsInChildren(); 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(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(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(); 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(); 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() .Select(shaft => shaft.Save()) .ToArray(); var panelShaftArray = panel .GetComponentsInChildren() .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(DataPath + dataKey, out var data)) { Debug.Log("没有找到配置项"); return; } // 删除面板上的齿轮 var panelShafts = panel.GetComponentsInChildren(); 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(); newShaft.Load(data.panelShaftArray[i]); newPanelShafts[i] = newShaft; } _shaftGraph.UpdatePanel(newPanelShafts); } #endregion } [Serializable] public struct GearSystemData { public ShaftLevelData[] shaftLevelDataArray; public ShaftLevelData[] panelShaftArray; } }