using Object = UnityEngine.Object; using System.Collections.Generic; using Cysharp.Threading.Tasks; using Framework.Constants; using Gameplay.Manager; using UnityEngine; using System.Linq; using PhxhSDK; using System; namespace Gameplay.Level { public class PlankManager : Singlenton, IInitable, IUpdatable { private Dictionary _planks; public Dictionary Planks => _planks; private Dictionary> _plankHingeJoints; private GameObject _plankRoot; private LevelData _planksLevelData; private static readonly string HoleOfPlankPath = string.Format(Framework.Constants.Constants.ItemPrefabPath, "HoleOfPlank"); public async UniTask PreLoadLevelItem() { try { var plankIndex = LevelUtils.SortPlankLayer(_planksLevelData.HolesOfPlanksIndex); var sortLayer = LevelConstants.SortLayer; for (var i = 0; i < _planksLevelData.planksType.Count; i++) { var index = plankIndex[i]; var plankName = LevelUtils.GetPlankName(_planksLevelData.planksType[index], _planksLevelData.squareType[index]); var plankPath = string.Format(Framework.Constants.Constants.PlankPrefabPath, plankName); var myPlank = await AssetManager.Instance.LoadAssetAsync(plankPath); var pos = LevelUtils.GetPlankPositionInfo(KongManager.Instance.HoleDic, _planksLevelData.HolesOfPlanksIndex[index], _planksLevelData.planksType[index], _planksLevelData.squareType[index]); var tPlank = new Plank { Obj = Object.Instantiate(myPlank, pos, myPlank.transform.rotation) }; tPlank.Obj.name += i; tPlank.Obj.GetComponent().sortingOrder = sortLayer++; tPlank.Init(); InitHingJoint(tPlank); if (_planks.Keys.Contains(tPlank.Obj.name)) { DebugUtil.LogError("SamePlank:{0}", tPlank.Obj.name); } else { _planks.Add(tPlank.Obj.name, tPlank); } var holeOfPlankSortLayer = sortLayer++; for (var j = 0; j < _planksLevelData.HolesOfPlanksIndex[index].Count; j++) { var myHoleOfPlank = await AssetManager.Instance.LoadAssetAsync(HoleOfPlankPath); var holeOfPlankIndex = _planksLevelData.HolesOfPlanksIndex[index][j]; if (KongManager.Instance.HoleDic.TryGetValue($"Kong{holeOfPlankIndex}", out var hole)) { var holeOfPlank = Object.Instantiate(myHoleOfPlank, hole.Obj.transform.position, myHoleOfPlank.transform.rotation); holeOfPlank.transform.SetParent(tPlank.Obj.transform); holeOfPlank.name += j; holeOfPlank.gameObject.GetComponent().sortingOrder = holeOfPlankSortLayer; tPlank.HolesOfPlank.Add(holeOfPlank.name, holeOfPlank); } } tPlank.Obj.transform.SetParent(_plankRoot.transform); } } catch (Exception e) { DebugUtil.LogError("PlankMgr PreLoadLevelItem Error: {0}", e); } } public void Init() { _plankRoot = GameObject.Find("PlankRoot"); _planks = new Dictionary(); _plankHingeJoints = new Dictionary>(); _planksLevelData = LevelManager.Instance.CurrentLevel.LevelData; } private void InitHingJoint(Plank plank) { foreach (var hole in plank.CurAffectedHoles.Values) { if (hole.LevelThumbtack != null) { AddHingJoint2D(plank, hole.LevelThumbtack); } } } public Plank GetPlank(string plankName) { if (_planks.TryGetValue(plankName, out var plank)) { return plank; } return null; } public void RemovePlank(string plankName) { _planks.Remove(plankName); } public void ResumeDetection() { foreach (var plank in _planks.Values) { plank.StopDetect = false; } } /// /// 得到Hole所影响的所有木板 /// public List FindAffectedPlanks(Kong kong, bool isNeedRecord = false) { List planks = new List(); foreach (var plank in _planks.Values) { plank.StopDetect = isNeedRecord; if (plank.Obj.activeSelf && plank.CurAffectedHoles.Values.Contains(kong)) { planks.Add(plank); } } return planks; } /// /// 是否有不完全相交于洞口 (部分遮挡) /// public bool HasPlanksOverlapHole(Kong kong) { var result = false; var planks = FindAffectedPlanks(kong); foreach (var plank in planks) { if (plank.Obj.activeSelf && !LevelUtils.IsCanAddThumbtack(plank, kong)) { result = true; } } return result; } public void ReplaceAnchor(Plank plank, Thumbtack thumbtack) { try { if (plank == null || plank.Obj == null || thumbtack == null || thumbtack.Obj == null) { Debug.LogWarning("PlankManager.ReplaceAnchor: Plank or Thumbtack Obj is null!"); return; } var anchor = plank.Obj.transform.InverseTransformPoint(thumbtack.Obj.transform.position); var hingeJoint2Ds = plank.Obj.GetComponents(); foreach (var hingeJoint2D in hingeJoint2Ds) { if (hingeJoint2D.connectedBody.Equals(thumbtack.Obj.GetComponent())) { hingeJoint2D.anchor = new Vector2(anchor.x, anchor.y); } } } catch (Exception e) { DebugUtil.LogError("PlankManager.ReplaceAnchor Fail. Plank: {0}, Thumbtack: {1}, Error: {2}", plank?.Obj.name, thumbtack?.Obj.name, e); } } public void AddHingJoint2D(Plank plank, Thumbtack thumbtack) { try { if (plank == null || plank.Obj == null || thumbtack == null || thumbtack.Obj == null) { Debug.LogWarning("PlankManager.AddHingJoint: Plank or Thumbtack Obj is null!"); return; } HingeJoint2D hingeJoint2D = plank.Obj.AddComponent(); var thumbtackRig = thumbtack.Obj.GetComponent(); hingeJoint2D.connectedBody = thumbtackRig; var anchor = plank.Obj.transform.InverseTransformPoint(thumbtack.Obj.transform.position); hingeJoint2D.anchor = new Vector2(anchor.x, anchor.y); //DebugUtil.Log("{0}木板添加:{1}上的HJ2D", plank.Obj.name, thumbtack.Obj.name); if (!_plankHingeJoints.TryGetValue(plank, out var hjList)) { hjList = new Dictionary(); hjList.Add(thumbtackRig, hingeJoint2D); _plankHingeJoints.Add(plank, hjList); } else { _plankHingeJoints[plank].Add(thumbtackRig, hingeJoint2D); } } catch (Exception e) { DebugUtil.LogError("PlankManager.AddHingJoint Fail. Plank: {0}, Thumbtack: {1}, Error: {2}", plank?.Obj.name, thumbtack?.Obj.name, e); } } public void RemoveHingJoint2D(Plank plank, Thumbtack thumbtack) { try { if (plank == null || plank.Obj == null || thumbtack == null || thumbtack.Obj == null) { Debug.LogWarning("PlankManager.RemoveHingJoint: Plank or Thumbtack Obj is null!"); return; } if (!_plankHingeJoints.TryGetValue(plank, out var hjDic)) return; var thumbtackRig = thumbtack.Obj.GetComponent(); if (hjDic.TryGetValue(thumbtackRig, out var hj2D)) { LevelManager.Instance.CurUndoState.RemoveH2DjPlanks.Add(plank); DebugUtil.Log("{0}木板移除:{1}上的HJ2D", plank.Obj.name, thumbtack.Obj.name); Object.DestroyImmediate(hj2D); hjDic.Remove(thumbtackRig); if (hjDic.Count <= 0) { plank.Obj.GetComponent().AddForce(Vector2.right * LevelConstants.AddForce); } } } catch (Exception e) { DebugUtil.LogError("PlankManager.RemoveHingJoint Fail. Plank: {0}, Thumbtack: {1}, Error: {2}", plank?.Obj.name, thumbtack?.Obj.name, e); } } public void RemoveAllHingJoint2D(Plank plank) { if (!_plankHingeJoints.TryGetValue(plank, out var hjDic)) { DebugUtil.LogError("Error to get hjDic from _plankHingeJoints! Error plank: [ {0} ]", plank.Obj.name); } else { for (var i = 0; i < hjDic.Count; i++) { DebugUtil.LogWarning("销毁:{0}", hjDic.ElementAt(i).Value.connectedBody.name); Object.DestroyImmediate(hjDic.ElementAt(i).Value); } hjDic.Clear(); } } public void Release() { if (_planks == null) return; foreach (var plank in _planks) { if (plank.Value.Obj) Object.DestroyImmediate(plank.Value.Obj); } _plankHingeJoints.Clear(); _planks.Clear(); } public void Update(float deltaTime) { if (_planks == null) return; foreach (var plank in _planks.Values) { plank.Update(deltaTime); } } } }