GameFramework新手引导设计

新手引导设计

需求分析

引导开启条件;引导进入下一步条件(可混合:人工手动调用代码,高亮处点击,自定义事件,点击任意处);引导开始时调用自定义函数;引导结束时调用自定义函数;引导的界面;引导界面遮罩透明度;引导界面中高亮显示的对象名字列表;提示文本(上,中,下 三个位置选择)

引导开启条件

模块可配置引导开启条件:监听UI界面弹出、监听自定义事件、手动开启

引导进入下一步条件

模块可配置进入下一步的条件,可多种条件:高亮出点击、自定义事件、点击任意处、人工手动调用NextGuide 代码;

引导开始时调用自定义函数

满足需要再引导开始时需要执行的特殊需求

引导结束时调用自定义函数

满足需要再引导结束时需要执行的特殊需求

引导的界面

默认是带有引导形象和文字框的GuideForm,也可以引导用户自定义的UI界面

引导界面遮罩透明度

覆盖在GuideForm或者自定义的UI界面之上的Guide3DMaskForm,只有一层可挖空的黑色遮罩和一个透明按钮,可配置其透明度。

引导界面中高亮显示的对象名字列表

可配置对象名称,用 ,逗号隔开,用于自动高亮。

提示文本

可配置文本及文本位置

技术分析

有限状态机

提供创建、使用和销毁有限状态机的功能,一些适用于有限状态机机制的游戏逻辑;

引导类型

  • 纯文字引导
  • UI高亮引导
  • 自定义位置高亮引导(用户配置Guide3DMaskForm高亮位置,圆圈大小)

状态机设计

IGuideManager

新手引导管理 接口:获取当前引导、获取引导、是否存在引导、开始引导、初始化引导

GuideManager

新手引导管理

GuideBase

新手引导状态机基类,提供接口:OnInit、OnEnter、OnUpdate、OnLevel、OnDestory;

提供方法:关闭新手引导 Dispose、下一步引导Next、指向引导NextTo、新手引导开始点Start、检查是否满足启动新手引导的条件CanStartGuide、该引导开始时调用的函数、该引导结束时调用的函数

DialogGuide

纯文本对话引导,打开GuideForm

FormHighLightingGuide

UI高亮引导,在自定义的UI上高亮某一个UI元素

CustomGuide

自定义位置高亮引导(用户配置Guide3DMaskForm高亮位置,圆圈大小)

自定义状态机

为满足特殊情况,需要可自定义引导。

代码设计

GameBase.cs

using GameFramework.Fsm;
using GuideOwner = GameFramework.Fsm.IFsm<AppLogic.Guide.IGuideManager>;

namespace AppLogic.Guide
{
    public abstract class GuideBase : FsmState<IGuideManager>
    {
        /// <summary>
        /// 状态初始化时调用。
        /// </summary>
        /// <param name="guideOwner">流程持有者。</param>
        protected override void OnInit(GuideOwner guideOwner)
        {
            base.OnInit(guideOwner);
        }

        /// <summary>
        /// 进入状态时调用。
        /// </summary>
        /// <param name="guideOwner">流程持有者。</param>
        protected override void OnEnter(GuideOwner guideOwner)
        {
            base.OnEnter(guideOwner);
        }

        /// <summary>
        /// 状态轮询时调用。
        /// </summary>
        /// <param name="guideOwner">流程持有者。</param>
        /// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
        /// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
        protected override void OnUpdate(GuideOwner guideOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(guideOwner, elapseSeconds, realElapseSeconds);
        }

        /// <summary>
        /// 离开状态时调用。
        /// </summary>
        /// <param name="guideOwner">流程持有者。</param>
        /// <param name="isShutdown">是否是关闭状态机时触发。</param>
        protected override void OnLeave(GuideOwner guideOwner, bool isShutdown)
        {
            base.OnLeave(guideOwner, isShutdown);
        }

        /// <summary>
        /// 状态销毁时调用。
        /// </summary>
        /// <param name="guideOwner">流程持有者。</param>
        protected override void OnDestroy(GuideOwner guideOwner)
        {
            base.OnDestroy(guideOwner);
        }

        public virtual void Next(GuideNextType guideNextType)
        {
            
        }

        public virtual bool ClickWhateverToNext()
        {
            return true;
        }

        public virtual bool ClickHighlightObjectToNext()
        {
            return true;
        }
    }
}

GuideComponent.cd

using System;
using AppLogic.Guide;
using GameFramework;
using GameFramework.Fsm;
using UnityGameFramework.Runtime;

namespace AppLogic.Guide
{
    public class GuideComponent : GameFrameworkComponent
    {
        private IGuideManager m_GuideManager = null;

        private IFsmManager m_IFsmManager = null;

        public bool Flag;
        protected override void Awake()
        {
            base.Awake();
            m_IFsmManager = GameFrameworkEntry.GetModule<IFsmManager>();
            if (m_IFsmManager == null)
            {
                Log.Fatal("Procedure manager is invalid.");
                return;
            }
        }

        private void Start()
        {
            Flag = false;
            m_GuideManager = new GuideManager();
            //GuideBase[] procedures = new GuideBase[3];
            m_GuideManager.Initialize(m_IFsmManager,new DialogGuide(),new FormHighLightingGuide(),new CustomGuide(),new NoneGuide(),new PlantGuide(),new PlantChanChu());
        }

        private void OnDestroy()
        {
            m_GuideManager.Shutdown();
        }

        public bool HasGuide<T>() where T : GuideBase
        {
            return m_GuideManager.HasGuide<T>();
        }

        public bool HasGuide(Type guideBase)
        {
            return m_GuideManager.HasGuide(guideBase);
        }

        public void StartGuide(int guideType)
        {
            switch (guideType)
            {
                case 1:m_GuideManager.StartGuide<DialogGuide>();
                    break;
                case 2:m_GuideManager.StartGuide<FormHighLightingGuide>();
                    break;
                case 3:m_GuideManager.StartGuide<CustomGuide>();
                    break;
                case 4:m_GuideManager.StartGuide<PlantGuide>(); 
                    break;
                case 5: m_GuideManager.StartGuide<PlantChanChu>();
                    break;
            }
        }
        
        public void StartGuide<T>() where T : GuideBase
        {
            m_GuideManager.StartGuide<T>();
        }
        
        public void StartGuide(Type guideBase)
        {
            m_GuideManager.StartGuide(guideBase);
        }

        public GuideBase GetGuide<T>() where T : GuideBase
        {
            return m_GuideManager.GetGuide<T>();
        }
        
        public GuideBase GetGuide(Type guideBase)
        {
            return m_GuideManager.GetGuide(guideBase);
        }

        public void Next(GuideNextType guideNextType=GuideNextType.Custom)
        {
            m_GuideManager.CurrentGuide.Next(guideNextType);
        }

        public bool IsInGuide()
        {
            if (m_GuideManager.CurrentGuide == null)
            {
                return false;
            }
            if (m_GuideManager.CurrentGuide is NoneGuide)
            {
                return false;
            }

            return true;
        }
        public void CloseGuide()
        {
            m_IFsmManager.DestroyFsm<IFsmManager>();
        }
        /// <summary>
        /// 点击任意位置去下一步
        /// </summary>
        /// <returns></returns>
        public bool ClickWhateverToNext()
        {
            return m_GuideManager.CurrentGuide.ClickWhateverToNext();
        }
        /// <summary>
        /// 是否接收点击高亮去下一步引导 默认true
        /// </summary>
        /// <returns></returns>
        public bool ClickHighlightObjectToNext()
        {
            return m_GuideManager.CurrentGuide.ClickHighlightObjectToNext();
        }

        public int GetGuidId()
        {
            return GameEntry.DataNode.GetData<VarInt32>(Constant.DataNode.GuideId);
        }
    }
}

IGuideManager.cs

using System;
using GameFramework.Fsm;

namespace AppLogic.Guide
{
    public interface IGuideManager
    {
        /// <summary>
        /// 获取当前引导。
        /// </summary>
        GuideBase CurrentGuide
        {
            get;
        }
        
        /// <summary>
        /// 获取当前引导持续时间。
        /// </summary>
        float CurrentGuideTime
        {
            get;
        }

        void Shutdown();
        /// <summary>
        /// 初始化引导管理器。
        /// </summary>
        /// <param name="fsmManager">有限状态机管理器。</param>
        /// <param name="guide">引导管理器包含的引导。</param>
        void Initialize(IFsmManager fsmManager, params GuideBase[] guide);

        /// <summary>
        /// 开始引导。
        /// </summary>
        /// <typeparam name="T">要开始的引导类型。</typeparam>
        void StartGuide<T>() where T : GuideBase;

        /// <summary>
        /// 开始引导。
        /// </summary>
        /// <param name="GuideType">要开始的引导类型。</param>
        void StartGuide(Type GuideType);

        /// <summary>
        /// 是否存在引导。
        /// </summary>
        /// <typeparam name="T">要检查的引导类型。</typeparam>
        /// <returns>是否存在引导。</returns>
        bool HasGuide<T>() where T : GuideBase;

        /// <summary>
        /// 是否存在引导。
        /// </summary>
        /// <param name="GuideType">要检查的引导类型。</param>
        /// <returns>是否存在引导。</returns>
        bool HasGuide(Type GuideType);

        /// <summary>
        /// 获取引导。
        /// </summary>
        /// <typeparam name="T">要获取的引导类型。</typeparam>
        /// <returns>要获取的引导。</returns>
        GuideBase GetGuide<T>() where T : GuideBase;

        /// <summary>
        /// 获取引导。
        /// </summary>
        /// <param name="GuideType">要获取的引导类型。</param>
        /// <returns>要获取的引导。</returns>
        GuideBase GetGuide(Type GuideType);
    }
}

GuideManager.cs

using GameFramework;
using GameFramework.Fsm;
using System;
namespace AppLogic.Guide
{
    public class GuideManager : IGuideManager
    {
        private IFsmManager m_FsmManager;
        private IFsm<IGuideManager> m_GuideFsm = null;
        /// <summary>
        /// 初始化引导管理器的新实例。
        /// </summary>
        public GuideManager()
        {
            m_FsmManager = null;
            m_GuideFsm = null;
        }
        public GuideBase CurrentGuide
        {
            get
            {
                if (m_GuideFsm == null)
                {
                    throw new GameFrameworkException("You must initialize gudie first.");
                }

                return (GuideBase)m_GuideFsm.CurrentState;
            }
        }

        public float CurrentGuideTime { get; }

        /// <summary>
        /// 关闭并清理引导管理器。
        /// </summary>
        public void Shutdown()
        {
            if (m_FsmManager != null)
            {
                if (m_GuideFsm != null)
                {
                    m_FsmManager.DestroyFsm(m_GuideFsm);
                    m_GuideFsm = null;
                }

                m_FsmManager = null;
            }
        }

        /// <summary>
        /// 初始化引导管理器。
        /// </summary>
        /// <param name="fsmManager">有限状态机管理器。</param>
        /// <param name="guides">流程管理器包含的流程。</param>
        public void Initialize(IFsmManager fsmManager, params GuideBase[] guides)
        {
            if (fsmManager == null)
            {
                throw new GameFrameworkException("FSM manager is invalid.");
            }

            m_FsmManager = fsmManager;
            m_GuideFsm = m_FsmManager.CreateFsm(this, guides);
        }
        /// <summary>
        /// 开始引导
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <exception cref="GameFrameworkException"></exception>
        public void StartGuide<T>() where T : GuideBase
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }
            m_GuideFsm.Start<T>();
        }
        /// <summary>
        /// 开始引导流程
        /// </summary>
        /// <param name="GuideType"></param>
        /// <exception cref="GameFrameworkException"></exception>
        public void StartGuide(Type GuideType)
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }
            m_GuideFsm.Start(GuideType);
        }
        /// <summary>
        /// 开始引导流程
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="GameFrameworkException"></exception>
        public bool HasGuide<T>() where T : GuideBase
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }

            return m_GuideFsm.HasState<T>();
        }
        /// <summary>
        /// 是否存在引导
        /// </summary>
        /// <param name="GuideType"></param>
        /// <returns></returns>
        /// <exception cref="GameFrameworkException"></exception>
        public bool HasGuide(Type GuideType)
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }

            return m_GuideFsm.HasState(GuideType);
        }
        /// <summary>
        /// 获取引导
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="GameFrameworkException"></exception>
        public GuideBase GetGuide<T>() where T : GuideBase
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }
            return m_GuideFsm.GetState<T>();
        }

        /// <summary>
        /// 获取引导
        /// </summary>
        /// <param name="GuideType"></param>
        /// <returns></returns>
        /// <exception cref="GameFrameworkException"></exception>
        public GuideBase GetGuide(Type GuideType)
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }
            return (GuideBase)m_GuideFsm.GetState(GuideType);
        }

        /// <summary>
        /// 开始引导。
        /// </summary>
        /// <typeparam name="T">要开始的流程类型。</typeparam>
        public void StartProcedure<T>() where T : GuideBase
        {
            if (m_GuideFsm == null)
            {
                throw new GameFrameworkException("You must initialize procedure first.");
            }

            m_GuideFsm.Start<T>();
        }
    }
}

GuideType.cs

namespace AppLogic
{
    public enum GuideNextType
    {
        GuideFormClick,
        Guide3DFormClick,
        Custom
    }
}
posted @ 2022-11-10 22:43  an逞祥  阅读(479)  评论(0)    收藏  举报