using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using DG.Tweening; using UnityEngine.Rendering.Universal; using UnityEngine.UI; using UnityEngine.EventSystems; public class TreeControl : MonoSingleton { [Header("面板UI")] public GameObject CanvasUI; private CanvasGroup canvasGroup; private Sequence showSequence; // 缓存的打开动画序列 private Sequence hideSequence; // 缓存的关闭动画序列 [Header("树节点头部")] public TechItem HeadItem; [Header("解锁亮光强度")] public float MaxLightNum; [Header("解锁线宽度")] public float MaxLineWidth; [Header("未解锁亮光强度")] public float MinLightNum; [Header("未解锁线宽度")] public float MinLineWidth; [Header("点击所需时间")] public float NeedTimes; private Transform NodePa; private Dictionary BlindItem; private Dictionary BlindObj; public Dictionary TechItems; private Action FollowLineStyle; private Action MainStyle; private float currenttimes; [HideInInspector] public GameObject currentobj; private TechItem currentItem; private Dictionary NodeEvent; public Material LockLinematerial;//亮线 public Material UnLockLineMaterial;//暗线 public GameObject lineObj; public List NoTechInfo; public bool DebugRemainUnLock = false; public Image TimeImage;//时间冷却图像 public override void Awake() { base.Awake(); canvasGroup = CanvasUI.transform.GetComponent(); CanvasUI.SetActive(false); // 创建动画序列 CreateSequences(); NodePa = transform.Find("节点组"); BlindItem = new Dictionary(); BlindObj = new Dictionary(); TechItems = new Dictionary(); Instance.UINameOpen(false); } private void Start() { InfoBlind(HeadItem); CreatTree(HeadItem); } private void Update() { FollowLineStyle?.Invoke(); MainStyle?.Invoke(); // Vector3 pos = Camera.main.WorldToViewportPoint (CanvasUI.transform.position); // pos.x = Mathf.Clamp01(pos.x); // pos.y = Mathf.Clamp01(pos.y); // CanvasUI.transform.position = Camera.main.ViewportToWorldPoint(pos); } #region 初始化 private void InfoBlind(TechItem techItem) { if(!DebugRemainUnLock)techItem.LockOver = false; Debug.LogWarning("====" + techItem.itemName); Transform trans = NodePa.Find(techItem.itemName); Debug.LogWarning("---" + trans.name); if (!BlindItem.ContainsKey(trans)) { TechItems[techItem.itemName]= techItem; Debug.Log(techItem.itemName + " keji add " + trans.name); BlindItem.Add(trans, techItem); BlindObj.Add(techItem, trans); foreach (var item in techItem.children) { InfoBlind(item); } trans.Find("科技名UI/名字").GetComponent().text = techItem.itemName; } } public void CreatTree(TechItem techItem, HashSet names = null) { if (names == null) { names = new HashSet(); } if (!names.Contains(techItem.itemName)) { names.Add(techItem.itemName); BlindLineConnect(techItem); foreach (var item in techItem.children) { CreatTree(item, names); } } } private void LightNode(TechItem techItem) { Transform SelfTrans = BlindObj[techItem]; Light2D light = SelfTrans.GetComponent(); LightOpenALL(light); } private void NoLightNode(TechItem techItem) { Transform trans = BlindObj[techItem]; Light2D light = trans.GetComponent(); LightClose(light); } /// /// 已解锁亮光 /// private void LightOpenALL(Light2D light) { Debug.Log("已经解锁亮光"); light.intensity = MaxLightNum; } /// /// 未解锁-小亮 /// /// private void LightClose(Light2D light) { light.intensity = MinLightNum; } /// /// 绑定线 /// private void BlindLineConnect(TechItem techItem) { Transform SelfTrans = BlindObj[techItem]; // 遍历所有父节点 if (techItem.parent != null && techItem.parent.Count > 0) { // 遍历所有父节点 for (int i = 0; i < techItem.parent.Count; i++) { TechItem parent = techItem.parent[i]; if (BlindObj.TryGetValue(parent, out Transform SelfTransPa)) { // 创建一个空的子物体用于存放 LineRenderer GameObject lineRendererObject = Instantiate(lineObj, SelfTransPa); lineRendererObject.name = SelfTrans.name; lineRendererObject.transform.localPosition = Vector3.zero; // 确保位置保持一致 // 为这个新创建的子物体添加 LineRenderer LineRenderer newLineRenderer = lineRendererObject.GetComponent(); // 为该父节点的连接线添加 LineFollow 逻辑 FollowLineStyle += () => LineFollow(SelfTrans, newLineRenderer); LineBuild(newLineRenderer, techItem.LockOver); if (techItem.MainTech && BlindItem[SelfTransPa].MainTech)//两个都是主干 { lineRendererObject.SetActive(true); } } } } else { if (techItem == HeadItem) // 处理头节点的情况 { Transform SelfTransPa = SelfTrans.parent; LineRenderer newLineRenderer = SelfTransPa.GetComponent(); LineBuild(newLineRenderer, techItem.LockOver); FollowLineStyle += () => LineFollow(SelfTrans, newLineRenderer); } } if (techItem.LockOver) // 已解锁直接点亮 { GetLightAnimation(techItem); } else { NoLightNode(techItem); } if (techItem.MainTech || techItem.LockOver) { SelfTrans.gameObject.SetActive(true); } else { SelfTrans.gameObject.SetActive(false); } } private void LineBuild(LineRenderer lineRenderer, bool islock) { if (islock) { lineRenderer.startWidth = MaxLineWidth; lineRenderer.endWidth = MaxLineWidth; lineRenderer.material = LockLinematerial; } else { lineRenderer.startWidth = MinLineWidth; lineRenderer.endWidth = MinLineWidth; lineRenderer.material = UnLockLineMaterial; } } private void LineFollow(Transform target, LineRenderer line) { Vector3 pos = line.transform.InverseTransformPoint(target.position); line.SetPosition(1, pos); } #endregion #region 判断能否点亮 public void BtnDowm() // 鼠标点到了 { string str = ""; if (currentobj != null) { TechItem techItem = BlindItem[currentobj.transform]; if (!techItem.LockOver) // 自身未解锁 { if (GodComeTIemsEnough(techItem, ref str)) { if (techItem.ResourceEnough()) // 资源足够 { if (techItem == HeadItem) // 如果是头节点 { currenttimes = 0; MainStyle = KeepTime; currentobj.GetComponent().enabled = true; Debug.Log("点亮"); } else { if (AreAllParentsUnlocked(techItem)) // 检查所有父节点是否已解锁 { currenttimes = 0; MainStyle = KeepTime; currentobj.GetComponent().enabled = true; Debug.Log("点亮"); } else str = "相邻节点未解锁完"; } CanvasUI.transform.Find("内容").GetComponent().color = Color.yellow; } else CanvasUI.transform.Find("内容").GetComponent().color = Color.red; } } } ChangeCanvasContect(str); } /// /// 检查所有父节点是否都已解锁 /// private bool AreAllParentsUnlocked(TechItem techItem) { if (techItem.parent == null || techItem.parent.Count == 0) return true; // 如果没有父节点,返回 true foreach (var parent in techItem.parent) { if (!parent.LockOver) // 只要有一个父节点未解锁,就返回 false { return false; } } return true; // 如果所有父节点都已解锁,返回 true } private bool GodComeTIemsEnough(TechItem techItem, ref string str) { List gods = YiShiUI.Instance.godComingTimes; for (int i = 0; i < gods.Count; i++) { if (gods[i].godType == techItem.GodTimes.godType) { if (gods[i].Count >= techItem.GodTimes.Count) { return true; } else { str = "降神次数不足!" + gods[i].GetGodName() + ":(" + gods[i].Count + "/" + techItem.GodTimes.Count + ")"; return false; } } } return false; } public void BtnUp()//鼠标释放或者点亮了 { TimeImage.fillAmount = 0; MainStyle = null; if (currentobj != null && currentobj.TryGetComponent(out DoweenAnimator doween)) { doween.enabled = false; } currentobj = null; } public void KeepTime()//计时 { currenttimes += Time.deltaTime; TimeImage.transform.position = currentobj.transform.position; TimeImage.fillAmount = currenttimes / NeedTimes; if (currenttimes >= NeedTimes) { PlayEvent(BlindItem[currentobj.transform].itemName); GetLightAnimation(BlindItem[currentobj.transform]); CutReource(); BtnUp(); } } private void GetLightAnimation(TechItem techItem)//点亮效果 { if (techItem == HeadItem) { if (transform.Find("节点组").TryGetComponent(out LineRenderer line)) { LineBuild(line, true); } } else { foreach (TechItem item in techItem.parent) { Transform pa = BlindObj[item]; Transform child = pa.Find(techItem.itemName); child.gameObject.SetActive(true); if (child.TryGetComponent(out LineRenderer lineone)) { LineBuild(lineone, true); } } } Transform currentobj = BlindObj[techItem]; if (currentobj.TryGetComponent(out Light2D light2D)) { LightOpenALL(light2D); } CanvasUI.transform.Find("内容").GetComponent().text = ""; Refreshtech(currentobj.transform); } private void CutReource() //消耗资源 { BlindItem[currentobj.transform].LockTech(); } #endregion #region CanvasUI动画 /// /// 创建动画序列,用于打开和关闭 UI /// private void CreateSequences() { // 打开动画序列 showSequence = DOTween.Sequence() .AppendCallback(() => CanvasUI.SetActive(true)) .Append(canvasGroup.DOFade(1, 0.1f)) .OnComplete(() => { canvasGroup.interactable = true; canvasGroup.blocksRaycasts = true; }) .Pause() // 暂停动画 .SetAutoKill(false); // 防止动画自动销毁 // 关闭动画序列 hideSequence = DOTween.Sequence() .Append(canvasGroup.DOFade(0, 0.1f)) .OnComplete(() => { canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; CanvasUI.SetActive(false); }) .Pause() // 暂停动画 .SetAutoKill(false); // 防止动画自动销毁 } public void ChangeUIcontect(Transform trans) //ui内容改变 { currentItem = BlindItem[trans]; } public void ChangeCanvasContect(string str) { TechItem techItem = currentItem; CanvasUI.transform.Find("名字").GetComponent().text = techItem.itemName; CanvasUI.transform.Find("描述").GetComponent().text = techItem.Describe; CanvasUI.transform.Find("功能").GetComponent().text = techItem.FunDescription; string contectstr = ""; if (str != "") contectstr = "[" + str + "]" + "\n"; ; for (int i = 0; i < techItem.needReources.Count; i++) { string kindname = techItem.needReources[i].kind.ToString(); string countstr = techItem.needReources[i].Count.ToString(); contectstr += countstr ; } if (!techItem.LockOver) { CanvasUI.transform.Find("内容").GetComponent().text = contectstr; CanvasUI.transform.Find("ICON").gameObject.SetActive(true); } else { CanvasUI.transform.Find("内容").GetComponent().text = ""; CanvasUI.transform.Find("ICON").gameObject.SetActive(false); } } /// /// 打开 UI /// public void ActiveUITrue(Vector3 pos) { CanvasUI.transform.position = new Vector3(pos.x, pos.y, CanvasUI.transform.position.z); CanvasUI.SetActive(true); canvasGroup.alpha = 0; // 如果关闭动画正在播放,停止它 if (hideSequence.IsActive() && hideSequence.IsPlaying()) { hideSequence.Restart(); hideSequence.Pause(); } // 播放打开动画 showSequence.Restart(); UINameOpen(false); } /// /// 关闭 UI /// public void ActiveUIFalse() { // 如果打开动画正在播放,停止它 if (showSequence.IsActive() && showSequence.IsPlaying()) { showSequence.Restart(); showSequence.Pause(); } // 播放关闭动画 hideSequence.Restart(); UINameOpen(true); } public void UINameOpen(bool open) { foreach (Transform child in transform.Find("节点组")) { child.Find("科技名UI").gameObject.SetActive(open); } } #endregion #region 节点解锁事件 public void AddEvent(string EventName, Action action) { if (NodeEvent == null) { NodeEvent = new Dictionary(); } if (NodeEvent.TryGetValue(EventName, out Action events)) { events += action; NodeEvent[EventName] = events; } else { NodeEvent.Add(EventName, action); } } public string[] GetDescription(string techName) { TechItem item = TechItems[techName]; return new[] { item.Describe, item.FunDescription }; } private void PlayEvent(string EventName) { if (NodeEvent.TryGetValue(EventName, out Action action)) { Debug.LogWarning("触发"); action?.Invoke(); } else { Debug.LogError("不存在该事件名"); } } #endregion public void Refreshtech(Transform trans) //子节点是否能打开 { foreach (Transform child in trans) { if (child.name != "科技名UI") { child.gameObject.SetActive(true); Debug.LogWarning(child.name); transform.Find("节点组/" + child.name).gameObject.SetActive(true); } } } public UI_InformationPanel.BTInfo GetTechInfo(string name) { Debug.Log("Kejishu "+name); if (TechItems.ContainsKey(name)) { TechItem ti= TechItems[name]; return new UI_InformationPanel.BTInfo(ti.itemName, ti.FunDescription, ti.Describe); } else { foreach (UI_InformationPanel.BTInfo bti in NoTechInfo) { if (bti.BITName == name) return bti; } return null; } } }