using System; using System.Collections; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using DG.Tweening; //引导功能包含 // 1.功能开启 // 2.引导NPC对话 // 3.点击引导 public class NewBieWin : UIBase { [SerializeField] NewBieMask m_NewBieMask; //遮罩,可镂空 //新功能开放 [SerializeField] Transform m_NewFunction; [SerializeField] Transform m_ContainerFunctionBg; [SerializeField] Text m_FunctionName; [SerializeField] Image m_FuncIcon; //功能图片飞入对应位置 [SerializeField] UIEffectPlayer unlockEffect; //飞到对应功能后爆开特效 [SerializeField] UIEffectPlayer funcEffect; //功能解锁特效 //引导npc对话 [SerializeField] Transform m_GuideTalkRect; [SerializeField] UIEffectPlayer m_newBieGuideNPC; [SerializeField] Button m_ClickTalk; [SerializeField] RichText m_TalkText; //点击引导 [SerializeField] Transform m_NewBieGuide; [SerializeField] Transform m_ContainerDialogue; [SerializeField] RichText m_Dialogue; [SerializeField] RectTransform m_DialogueBG; [SerializeField] Image m_ArrowUP; [SerializeField] Image m_ArrowDown; [SerializeField] Image m_ArrowLeft; [SerializeField] Image m_ArrowRight; [SerializeField] UIEffectPlayer m_ClickEffect; [SerializeField] ClickScreenOtherSpace m_ClickScreenOtherSpace; Transform m_ClickTarget; GuideConfig config; NewBieGuideScriptableObject stepConfig; //引导步骤 float lastShowTime; #region Built-in protected override void InitComponent() { m_ClickTalk.AddListener(() => { ReportStepOver(); }); } protected override void OnPreOpen() { m_ClickTarget = null; tryGuideCount = 0; //关闭其他可能在主界面显示的窗口等 // UIManager.Instance.CloseWindow(); NewBieCenter.Instance.guideStepChangeEvent += OnStepChange; // Display(); } protected override void OnPreClose() { //关闭时隐藏,避免下次打开会有残留闪烁问题;因为打开时延后处理 m_NewFunction.SetActive(false); m_NewBieGuide.SetActive(false); m_GuideTalkRect.SetActive(false); m_ContainerDialogue.SetActive(false); m_NewBieMask.SetActive(false); NewBieCenter.Instance.currentGuide = 0; } protected override void OnClose() { NewBieCenter.Instance.guideStepChangeEvent -= OnStepChange; if (NewBieCenter.Instance.currentGuide != 0) { NewBieCenter.Instance.FinishCurrentGuideWithoutCloseWin(); } m_ClickTarget = null; stepConfig = null; } protected override void NextFrameAfterOpen() { Display(); } #endregion void Display() { config = GuideConfig.Get(NewBieCenter.Instance.currentGuide); if (config == null) { CloseWindow(); return; } var step = NewBieCenter.Instance.guideStep; stepConfig = ScriptableObjectLoader.LoadSoNewBieGuideStep(step); if (stepConfig == null) { CloseWindow(); return; } if (stepConfig.guideType == GuideType.Function) { UIManager.Instance.CloseWindow(); } Debug.Log($"引导ID:{NewBieCenter.Instance.currentGuide} 引导步骤:{step}"); lastShowTime = Time.time; //避免弹装备界面和引导冲突 if (config.WinName != "EquipExchangeWin" && UIManager.Instance.IsOpened()) { UIManager.Instance.CloseWindow(); } //引导的是战斗 解除暂停 if (stepConfig.UIElementPath.Contains("HomeBtn") && UIManager.Instance.IsOpened()) { NewBieCenter.Instance.ResumeGame(); } try { m_ClickTarget = FindTransform(stepConfig.UIElementPath); if (m_ClickTarget != null) { m_lastTargetPosition = m_ClickTarget.position; tryGuideCount = 0; } else { if (tryGuideCount > 3) { #if UNITY_EDITOR if (!string.IsNullOrEmpty(stepConfig.UIElementPath)) Debug.LogError($"引导步骤{step}找不到目标{stepConfig.UIElementPath}, 若不需要请删除路径"); #endif ReportStepOver(); tryGuideCount = 0; return; } DelayDisplay().Forget(); return; } } catch (Exception ex) { Debug.LogError(ex); NewBieCenter.Instance.FinishNewBieGuide(NewBieCenter.Instance.currentGuide); } var type = stepConfig.guideType; if (type == GuideType.NewBie && stepConfig.clickCompleteNoMask) { m_NewBieMask.SetActive(false); } else { m_NewBieMask.SetActive(true); m_NewBieMask.Display(step, m_ClickTarget); } if (type == GuideType.Function) { m_NewFunction.SetActive(true); m_NewBieGuide.SetActive(false); m_GuideTalkRect.SetActive(false); funcEffect.PlayByArrIndex(0); DisplayFunctionUnLock(config.Condition); } else if (type == GuideType.NpcTalk) { m_NewFunction.SetActive(false); m_NewBieGuide.SetActive(false); m_GuideTalkRect.SetActive(true); DisplayNPCTalk(); } else { m_NewFunction.SetActive(false); m_NewBieGuide.SetActive(true); m_GuideTalkRect.SetActive(false); DisplayGuide(); } } int tryGuideCount = 0; //界面加载慢还未显示的情况 多检测两次 如果还找不到则警告提示 async UniTask DelayDisplay() { await UniTask.Delay((tryGuideCount + 1) * 100); tryGuideCount++; Display(); } private void DisplayFunctionUnLock(int _functionId) { var config = FuncOpenLVConfig.Get(_functionId); m_FunctionName.text = config.Name; m_FuncIcon.SetSprite(config.Icon); m_FuncIcon.SetNativeSize(); m_ContainerFunctionBg.SetActive(true); m_FunctionName.SetActive(true); m_FuncIcon.SetActive(true); m_FuncIcon.transform.localPosition = Vector3.zero; unlockEffect.Stop(); Co_FunctionUnLockDelay().Forget(); } void DisplayNPCTalk() { if (stepConfig.effect == 0) { m_newBieGuideNPC.SetActive(false); } else { m_newBieGuideNPC.SetActive(true); m_newBieGuideNPC.effectId = stepConfig.effect; m_newBieGuideNPC.PlayByArrIndex(stepConfig.usherAction); m_newBieGuideNPC.transform.localPosition = stepConfig.usherPosition; m_newBieGuideNPC.transform.localScale = new Vector3(stepConfig.usherOrientation == NewBieGuideScriptableObject.UsherOrientation.Normal ? 1 : -1, 1, 1); } m_TalkText.text = stepConfig.GetTipContent(); } private void DisplayGuide() { Co_DisplayGuide(); } //完成当前引导步骤 private void ReportStepOver() { m_ClickTarget = null; NewBieCenter.Instance.ReportGuideStepComplete(NewBieCenter.Instance.guideStep); } private void OnStepChange() { Display(); } async UniTask Co_FunctionUnLockDelay() { await UniTask.Delay(1300); m_ContainerFunctionBg.SetActive(false); m_FunctionName.SetActive(false); unlockEffect.transform.position = m_ClickTarget.position; m_FuncIcon.transform.DOMove(m_ClickTarget.position, 0.5f).SetEase(Ease.OutQuad).OnComplete(() => { m_FuncIcon.SetActive(false); unlockEffect.onComplete = ReportStepOver; unlockEffect.Play(); }); } void Co_DisplayGuide() { if (stepConfig.HasTipContent()) { m_ContainerDialogue.SetActive(true); m_Dialogue.text = stepConfig.GetTipContent(); //强制刷新一次 contentSizeFitter 的计算 LayoutRebuilder.ForceRebuildLayoutImmediate(m_DialogueBG); m_ArrowUP.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Top); m_ArrowDown.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Bottom); m_ArrowLeft.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Left); m_ArrowRight.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Right); m_ContainerDialogue.transform.position = m_ClickTarget.position; m_ContainerDialogue.transform.localPosition = m_ContainerDialogue.transform.localPosition + (Vector3)stepConfig.tipPosition; } else { m_ContainerDialogue.SetActive(false); } m_ClickEffect.effectId = stepConfig.effect; //如果需要点击特效也增加偏移量 m_ClickEffect.SetActive(false); DelayShowClickEffect().Forget(); if (stepConfig.clickCompleteNoMask) { m_ClickScreenOtherSpace.enabled = true; m_ClickScreenOtherSpace.AddListener(() => { ReportStepOver(); }); } else { m_ClickScreenOtherSpace.enabled = false; m_ClickScreenOtherSpace.RemoveAllListeners(); } } async UniTask DelayShowClickEffect() { await UniTask.Delay(stepConfig.delayTime); m_ClickEffect.SetActive(true); m_ClickEffect.Play(); m_ClickEffect.transform.position = m_ClickTarget.position; m_ClickEffect.transform.localPosition = m_ClickEffect.transform.localPosition + (Vector3)stepConfig.usherPosition; } void LateUpdate() { if (Input.GetMouseButtonUp(0)) { if (stepConfig == null) { return; } if (stepConfig.clickCompleteNoMask) { return; } if (stepConfig.clickAnyWhereComplete || m_NewBieMask.mask.IsInCirleArea(Input.mousePosition, CameraManager.uiCamera)) { if (stepConfig.delayTime > 0 && (Time.time - lastShowTime)*1000 < stepConfig.delayTime) { return; } if (m_ClickTarget == null) { Debug.LogError("引导 m_ClickTarget == null; step = " + NewBieCenter.Instance.guideStep); ReportStepOver(); return; } var btn = m_ClickTarget.GetComponent