using cfg.GuideCfg; using System; using System.Linq; using Cysharp.Threading.Tasks; using Gameplay.Level; using UnityEngine.UI; using UnityEngine; using Framework; using cfg.LevelCfg; namespace Gameplay.Guide { /// /// 引导状态 /// public enum E_GuideState { /// /// 等待引导 /// Idle, /// /// 引导中 /// Guiding, /// /// 引导完成 /// Complete, } /// /// 引导步骤基类 /// public abstract class GuideStepBase { /// /// 引导完成类型 /// private readonly GuideCompleteBase completeBase; /// /// 引导配置 /// public DataGuideCfg Cfg { get; private set; } /// /// 引导状态 /// public E_GuideState GuideState { get; private set; } /// /// 是否引导中 /// public bool IsGuiding { get { return E_GuideState.Guiding == GuideState; } } public GuideStepBase(DataGuideCfg cfg) { Cfg = cfg; GuideState = E_GuideState.Idle; completeBase = Cfg.GuideCompleteType switch { E_GuideCompleteType.PlayVideoOver => new PlayVideoComplete(Cfg, Complete), E_GuideCompleteType.OpenUI => new OpenUIComplete(Cfg, Complete), E_GuideCompleteType.CloseUI => new CloseUIComplete(Cfg, Complete), E_GuideCompleteType.OpenUIAndAnim => new OpenUIAndAnimComplete(Cfg, Complete), E_GuideCompleteType.CloseUIAndAnim => new CloseUIAndAnimComplete(Cfg, Complete), E_GuideCompleteType.EnterFightLevelComplete => new EnterFightLevelComplete(Cfg, Complete), E_GuideCompleteType.EnterStorylineLevelComplete => new EnterStorylineLevelComplete(Cfg, Complete), E_GuideCompleteType.EmbattleComplete => new LevelEmbattleComplete(Cfg, Complete), E_GuideCompleteType.EmbattleVehicleComplete => new LevelEmbattleComplete(Cfg, Complete), E_GuideCompleteType.FightBegin => new FightBeginComplete(Cfg, Complete), E_GuideCompleteType.FightMoveBeginComplete => new FightBeginMoveComplete(Cfg, Complete), E_GuideCompleteType.FightMoveComplete => new FightMoveComplete(Cfg, Complete), E_GuideCompleteType.FightAttackComplete => new FightAttackComplete(Cfg, Complete), E_GuideCompleteType.PreparaUseSkillComplete => new FightPreparaUseSkillComplete(Cfg, Complete), E_GuideCompleteType.PreparaUsePlayerSkillComplete => new FightPreparaUsePlayerSkillComplete(Cfg, Complete), E_GuideCompleteType.FightUseSkillComplete => new FightUseSkillComplete(Cfg, Complete), E_GuideCompleteType.FightUsePlayerSkillComplete => new FightUsePlayerSkillComplete(Cfg, Complete), E_GuideCompleteType.LevelComplete => new LevelComplete(Cfg, Complete), E_GuideCompleteType.ClickGuideButton => new ClickGuideButtonComplete(Cfg, Complete), E_GuideCompleteType.ClickFloorComplete => new ClickGuideFloorComplete(Cfg, Complete), E_GuideCompleteType.FightStartButtonShowComplete => new WaitFightStartButtonShowComplete(Cfg, Complete), E_GuideCompleteType.WaitPreparatShowComplete => new WaitPreparatShowComplete(Cfg, Complete), E_GuideCompleteType.WaitEnemyRetreat => new WaitEnemyRetreatComplete(Cfg, Complete), E_GuideCompleteType.WaitChangeName => new WaitChangeNameComplete(Cfg, Complete), E_GuideCompleteType.WaitEditTeamComplete => new WaitEditTeamComplete(Cfg, Complete), E_GuideCompleteType.AnyClickComplete => new AnyClickComplete(Cfg, Complete), E_GuideCompleteType.SaveTeamComplete => new SaveTeamComplete(Cfg, Complete), E_GuideCompleteType.JoinVehicle => new JoinVehicle(Cfg, Complete), E_GuideCompleteType.WaitLoadingComplete => new WaitLoadingComplete(Cfg, Complete), E_GuideCompleteType.ClearTeamComplete => new ClearTeamComplete(Cfg, Complete), E_GuideCompleteType.SelectTeamComplete => new SelectTeamComplete(Cfg, Complete), E_GuideCompleteType.SkillCDComplete => new SkillCDComplete(Cfg, Complete), E_GuideCompleteType.WaitComplete => new WaitComplete(Cfg, Complete), _ => throw new Exception($"未处理类型:{Cfg.GuideCompleteType}"), }; } /// /// 开始引导 /// public async void StartGuide() { GuideState = E_GuideState.Guiding; DebugUtil.Log($"开始id为{Cfg.Id}的引导,延迟{Cfg.StepStartDelay}秒开始"); // #00FA9A绿色 await DoBeforeGuide(); await UniTask.Delay((int)(Cfg.StepStartDelay * 1000f)); // 延迟时间开始 DoRealBeforeGuide(); DebugUtil.Log($"实际执行id为{Cfg.Id}的引导"); // #00FA9A绿色 DoGuide(); CommonUtils.GuideStepBiEvent(Cfg.Id, 0); // BI打点 } /// /// 跳过当前步骤 /// public void SkipStep() { } /// /// 完成引导 /// protected void Complete() { if (!IsGuiding) return; DebugUtil.Log($"完成id为{Cfg.Id}的引导"); // #00FA9A绿色 GuideState = E_GuideState.Complete; DoBeforeComplete(); RecoverState(); GuideManager.Instance.CompleteStep(this); CommonUtils.GuideStepBiEvent(Cfg.Id, 1); // BI打点 CommonUtils.GuideStepBiEvent(Cfg.Id.ToString()); } /// /// 结束引导 /// public void EndGuide() { if (!IsGuiding) return; completeBase.RemoveListener(); RecoverState(); GuideState = E_GuideState.Idle; } /// /// 引导开始之前 /// protected virtual async UniTask DoBeforeGuide() { InputManager.Instance.IsEnable = false; await UI_GuideController.Open(); completeBase.AddListener(); } /// /// 引导实际开始之前 /// protected virtual void DoRealBeforeGuide() { InputManager.Instance.IsEnable = true; } /// /// 引导 /// protected virtual void DoGuide() { SetGuideState(); } /// /// 引导完成之前 /// protected virtual void DoBeforeComplete() { completeBase.RemoveListener(); UIManager.Instance.CloseWindow(UINameConst.UI_Guide); } /// /// 设置引导状态 /// protected abstract void SetGuideState(); /// /// 还原状态 /// protected abstract void RecoverState(); } #region 引导点击 /// /// 点击按钮 /// internal sealed class ClickButtonStep : GuideStepBase { /// /// UI名 /// private readonly string uiName; /// /// 按钮路径 /// private readonly string buttonPath; public ClickButtonStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length <= 1) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.UI名,2.按钮路径"); uiName = Cfg.GuideTypeParams[0]; buttonPath = Cfg.GuideTypeParams[1]; } protected override async void DoGuide() { try { base.DoGuide(); await UI_GuideController.Open(UI_GuideController.E_GuideArrowType.Button, uiName, buttonPath, Cfg); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); GuideManager.Instance.SkipAllGuide(); } } protected override void SetGuideState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel) LevelManager.Instance.CurrentLevel.SetPause(true); } protected override void RecoverState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel) LevelManager.Instance.CurrentLevel.SetPause(false); } } /// /// 滑动按钮 /// internal sealed class SliderButtonStep : GuideStepBase { /// /// UI名 /// private readonly string uiName; /// /// 按钮路径 /// private readonly string buttonPath; /// /// 地板索引 /// private readonly int floorIndex; public SliderButtonStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length <= 1) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.UI名,2.按钮路径,3(可选).地板索引"); uiName = Cfg.GuideTypeParams[0]; buttonPath = Cfg.GuideTypeParams[1]; if (Cfg.GuideTypeParams.Length > 2) { if (int.TryParse(Cfg.GuideTypeParams[2], out int index)) floorIndex = index; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第3个参数类型错误:应该为int类型"); } } protected override async void DoGuide() { try { base.DoGuide(); await UI_GuideController.Open(UI_GuideController.E_GuideArrowType.SliderButton, uiName, buttonPath, Cfg, floorIndex); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel) LevelManager.Instance.CurrentLevel.SetPause(true); } protected override void RecoverState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel) LevelManager.Instance.CurrentLevel.SetPause(false); } } /// /// 点击地板 /// internal sealed class ClickFloorStep : GuideStepBase { /// /// 底板索引 /// private readonly int floorIndex; public ClickFloorStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length <= 0) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.地板索引"); if (int.TryParse(Cfg.GuideTypeParams[0], out int index)) floorIndex = index; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第1个参数类型错误:应该为int类型"); } protected override async void DoGuide() { try { base.DoGuide(); await UI_GuideController.Open(floorIndex, Cfg); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel && LevelManager.Instance.CurrentLevel.isInBattle) { LevelManager.Instance.CurrentLevel.SetPause(true); } UIRoot.Instance.IsEnableGraphicRaycasterByGuide(false); GuideManager.Instance.IsControlFloor = true; GuideManager.Instance.FloorIndex = floorIndex; } protected override void RecoverState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel && LevelManager.Instance.CurrentLevel.isInBattle) { if (GuideManager.Instance.IsUseSkillSuccess) LevelManager.Instance.CurrentLevel.SetPause(false); } UIRoot.Instance.IsEnableGraphicRaycasterByGuide(true); GuideManager.Instance.IsControlFloor = false; GuideManager.Instance.FloorIndex = -1; } } /// /// 指向UI说明 /// internal sealed class NoteStep : GuideStepBase { /// /// UI名 /// private readonly string uiName; /// /// 按钮路径 /// private readonly string buttonPath; public NoteStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length > 1) { uiName = cfg.GuideTypeParams[0]; buttonPath = cfg.GuideTypeParams[1]; } } protected override async void DoGuide() { try { base.DoGuide(); await UI_GuideController.Open(UI_GuideController.E_GuideArrowType.UI, uiName, buttonPath, Cfg); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel && LevelManager.Instance.CurrentLevel.isInBattle) LevelManager.Instance.CurrentLevel.SetPause(true); } protected override void RecoverState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel && LevelManager.Instance.CurrentLevel.isInBattle) LevelManager.Instance.CurrentLevel.SetPause(false); } } /// /// 滑动按钮上阵 /// internal sealed class SliderButtonBattleStep : GuideStepBase { /// /// UI名 /// private readonly string uiName; /// /// 按钮路径 /// private readonly string buttonPath; /// /// 地板索引 /// private readonly int floorIndex; public SliderButtonBattleStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length <= 1) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.UI名,2.按钮路径,3(可选).地板索引"); uiName = Cfg.GuideTypeParams[0]; buttonPath = Cfg.GuideTypeParams[1]; if (Cfg.GuideTypeParams.Length > 2) { if (int.TryParse(Cfg.GuideTypeParams[2], out int index)) floorIndex = index; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第3个参数类型错误:应该为int类型"); } } protected override async void DoGuide() { try { base.DoGuide(); await UI_GuideController.Open(UI_GuideController.E_GuideArrowType.SliderButton, uiName, buttonPath, Cfg, floorIndex); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel) LevelManager.Instance.CurrentLevel.SetPause(true); GuideManager.Instance.IsControlFloor = true; GuideManager.Instance.FloorIndex = floorIndex; EventManager.Instance.Register(EventManager.EventName.Guide_CancelModeFight, OnCancelFightModel); } protected override void RecoverState() { EventManager.Instance.Unregister(EventManager.EventName.Guide_CancelModeFight, OnCancelFightModel); if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel) LevelManager.Instance.CurrentLevel.SetPause(false); GuideManager.Instance.IsControlFloor = false; GuideManager.Instance.FloorIndex = -1; } private async void OnCancelFightModel() { await UniTask.Delay(300); await UI_GuideController.Open(UI_GuideController.E_GuideArrowType.SliderButton, uiName, buttonPath, Cfg, floorIndex); } } #endregion /// /// 播放视频 /// internal sealed class PlayVideoStep : GuideStepBase { /// /// 视频路径 /// private readonly string videoPath; public PlayVideoStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length <= 0) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.视频路径"); videoPath = Cfg.GuideTypeParams[0]; } protected override async void DoGuide() { try { base.DoGuide(); UIManager.Instance.CloseWindow(UINameConst.UI_Guide); GuideManager.Instance.IsPlayPVVideo = true; await UI_PVAnimaPlayController.Open(videoPath); Complete(); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { } protected override void RecoverState() { } } /// /// 显示引导提示 /// internal sealed class ShowGuideTipStep : GuideStepBase { /// /// 引导提示配置id /// private readonly int guideTipCfgId; public ShowGuideTipStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length <= 0) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.引导Tip的Id"); if (int.TryParse(Cfg.GuideTypeParams[0], out int id)) guideTipCfgId = id; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第1个参数类型错误:应该为int类型"); } protected override async void DoGuide() { try { base.DoGuide(); await UI_GuideTipController.Open(guideTipCfgId); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel && LevelManager.Instance.CurrentLevel.isInBattle) LevelManager.Instance.CurrentLevel.SetPause(true); } protected override void RecoverState() { if (LevelManager.Instance.IsInLevel && null != LevelManager.Instance.CurrentLevel && LevelManager.Instance.CurrentLevel.isInBattle) LevelManager.Instance.CurrentLevel.SetPause(false); } } #region 进入流程 /// /// 切换主场景状态 /// internal sealed class EnterMainStateStep : GuideStepBase { public EnterMainStateStep(DataGuideCfg cfg) : base(cfg) { } protected override void DoGuide() { try { base.DoGuide(); GameStateManager.Instance.ChangeState(new GameStateMainScene()); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { } protected override void RecoverState() { } } /// /// 进入关卡 /// internal sealed class EnterLevelStep : GuideStepBase { /// /// 关卡id /// private readonly int levelId; /// /// 进入故事关卡后是否立即播放 /// private readonly bool isPlay; public EnterLevelStep(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length < 1) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.关卡id"); if (int.TryParse(Cfg.GuideTypeParams[0], out int id)) levelId = id; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第1个参数类型错误:应该为int类型"); if (Cfg.GuideTypeParams.Length > 1) { if (bool.TryParse(Cfg.GuideTypeParams[1], out bool isPlay)) this.isPlay = isPlay; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第2个参数类型错误:应该为bool类型"); } else isPlay = true; } protected override void DoGuide() { try { base.DoGuide(); LevelManager.Instance.TryEnterLevel(levelId, null, null, isPlay); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); GuideManager.Instance.ShowSkipAllGuide(); } } protected override void SetGuideState() { } protected override void RecoverState() { } } /// /// 进入编队 /// internal sealed class EnterEnterEditTeam : GuideStepBase { /// /// 关卡id /// private readonly int levelId; public EnterEnterEditTeam(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length < 1) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.关卡id"); if (int.TryParse(Cfg.GuideTypeParams[0], out int id)) levelId = id; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第1个参数类型错误:应该为int类型"); } protected override void DoGuide() { try { base.DoGuide(); GameStateManager.Instance.ChangeState(new GameStateMainScene(false, async () => { await JumpToManager.JumpFuncAsync(cfg.JumpFuncType.TeamSelect, levelId); })); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { } protected override void RecoverState() { } } /// /// 进入队伍信息 /// internal sealed class EnterEnterTeamInfo : GuideStepBase { /// /// 关卡id /// private readonly int levelId; public EnterEnterTeamInfo(DataGuideCfg cfg) : base(cfg) { if (Cfg.GuideTypeParams.Length < 1) throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},参数数量错误:1.关卡id"); if (int.TryParse(Cfg.GuideTypeParams[0], out int id)) levelId = id; else throw new Exception($"引导id:{Cfg.Id}, 引导类型:{Cfg.GuideStepType},第1个参数类型错误:应该为int类型"); } protected override void DoGuide() { try { base.DoGuide(); GameStateManager.Instance.ChangeState(new GameStateMainScene(false, async () => { await JumpToManager.JumpFuncAsync(cfg.JumpFuncType.TeamInfoByGuide, levelId); })); } catch (Exception e) { DebugUtil.LogError($"引导id:{Cfg.Id},执行错误,异常信息:{e}"); } } protected override void SetGuideState() { } protected override void RecoverState() { } } #endregion /// /// 关卡上阵 /// internal sealed class LevelEmbattleStep : GuideStepBase { public LevelEmbattleStep(DataGuideCfg cfg) : base(cfg) { } protected override async UniTask DoBeforeGuide() { await base.DoBeforeGuide(); UIWindow uiWindow = UIManager.Instance.GetOpenedWindowByPath(UINameConst.UI_StartBtn_CMSBtn); if (null == uiWindow) return; Transform ts = uiWindow.gameObject.transform.Find("UIStartBtn/Image_UI_Start_BG/Button_StartBtn"); if (null == ts) return; Button btn = ts.GetComponent