GameFramework框架知识

目录

工程资源

一、加载Excel配置表的txt文件(读写)

二、GameFramework之Procedure流程


工程资源

https://github.com/AMikeW/BStandShaderResources

*** 资源使用注意事项 ***

 

一个是场景,一个是Log日志类所需的脚本定义标记启动才能看到打印日志。当然你用UnityEngine.Debug是没有问题的。

一、加载Excel配置表的txt文件(读写)

直接另存为.txt文本文件,或者直接改后缀为.txt 转为文本文件

放置到Unity的目录下,不一定是要在Resources特殊目录,这里只是测试随便放的。

using GameFramework.DataTable;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityGameFramework.Runtime;

public class TestConfig : IDataRow
{
    public int Id { get; protected set; }
    public string Name { get; protected set; }
    public int Atk { get; protected set; }

    public bool ParseDataRow(string dataRowString, object userData)
    {
        try
        {
            string[] text = dataRowString.Split('\t');
            int index = 0;
            index++;
            Id = int.Parse(text[index++]);
            Name = text[index++];
            Atk = int.Parse(text[index++]);
        }
        catch (Exception e)
        {
            Log.Error("TestConfig ParseDataRow Error:" + e.ToString());
            return false;
        }
        return true;
    }

    public bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData)
    {
        throw new System.NotImplementedException();
    }

    public override string ToString()
    {
        return string.Format("Id:{0},Name:{1},Atk:{2}", Id, Name, Atk);
    }
}
   private void StartLoadConfig()
   {
        //监听加载配置表成功事件
        EventComponent Event = GameEntry.GetComponent<EventComponent>();
        Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnDataLoadedSuccess);
        // 获取框架数据表组件
        DataTableComponent dataTableComponent
            = UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
        IDataTable<TestConfig> dataTable = dataTableComponent.CreateDataTable<TestConfig>();
        DataTableBase dataTableBase = dataTable as DataTableBase;
        dataTableBase.ReadData("Assets/AssetBundles/Resources/Test.txt");
   }

   private void OnDataLoadedSuccess(object sender, GameEventArgs e)
    {
        Log.Error("加载成功:");
    DataTableComponent dataTableComponent = GameEntry.GetComponent<DataTableComponent>();
        IDataTable<TestConfig> dtScene = dataTableComponent.GetDataTable<TestConfig>();

        TestConfig[] allTestConfigs = dtScene.GetAllDataRows();// 所有的行获取为数组
        Log.Debug("allTestConfig : " + allTestConfigs.Length);

        TestConfig first = dtScene.GetDataRow(1); //获取的是ID为1的TestConfig
        if (first != null)
        {
            Log.Debug("first id = 1:" + first.ToString());
        }
        else
        {

        }
        //获取所有满足条件的行
        TestConfig[] testConfigsIdGreater0s = dtScene.GetDataRows((x) => { return x.Id > 0; });
        foreach (var v in testConfigsIdGreater0s)
        {
            Log.Debug("testConfigsIdGreater0 :" + v.ToString());
        }
        //获取第一次满足条件的行 返回它
        TestConfig testConfigsNameEqualCondition = dtScene.GetDataRow((x) => { return x.Name == "mutou"; });
        Log.Debug("testConfigsNameEqualCondition:" + testConfigsNameEqualCondition.ToString());
    }

坑点&提示: 

①、注意这里的加载路径必须是Assets开头的相对路径。

②、旧版本加载配置表方法是 DataTableComponent.LoadDataTable<T>(string)

二、GameFramework之Procedure流程

如上图所示,进入流程为ProcedureLaunch流程,它是一个继承于ProcedureBase的C#脚本 ,如下:

using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

public class ProcedureLaunch : ProcedureBase
{
    protected override void OnEnter(ProcedureOwner procedureOwner)
    {
        base.OnEnter(procedureOwner);
        Log.Debug("初始化!");

        SceneComponent scene = UnityGameFramework.Runtime.GameEntry.GetComponent<SceneComponent>();
        scene.LoadScene("Assets/Scenes/Menu.unity", this);

        ChangeState<ProcedureMenu>(procedureOwner);
    }
}

当游戏运行时,会进入初始流程的OnEnter方法,若需要转换到其他Procedure流程,则使用ProcedureBase类的方法ChangeState<T>(ProcedureOwner)进行转到下一个流程,不难发现它就是个状态机而已。有OnEnter自然有OnExit方法,还有其他方法请自行测试。上面方法,还使用到了SceneComponent类对象进行加载场景,它是同步追加加载,即现有场景不会销毁的,加载后如下图所示。SceneComponent类是GameFramework物体下的子物体Scene的脚本Scene(留坑①)。

进入Menu场景并切换到ProcedureMenu流程后(此时并不清楚具体是否加载完毕场景后才进入ProcedureMenu流程,留坑②),进入Menu流程后我打算加载一个面板,并在面板上设置一个按钮用于进入Game场景,并且切换到ProcedureGame流程。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework;
using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
using GameFramework.Fsm;
using GameFramework.UI;
using GameFramework.Event;

public class ProcedureMenu : ProcedureBase
{
    ProcedureOwner procedureOwner;
    protected override void OnEnter(ProcedureOwner procedureOwner)
    {
        base.OnEnter(procedureOwner);
        Log.Debug("菜单场景 加载UI");

        //GameFramework框架的事件系统
        EventComponent Event = GameEntry.GetComponent<EventComponent>();
        //EventName是一个枚举,它是用户自定义的枚举,代表事件ID(必须唯一)
        Event.Subscribe((int)EventName.GameStart, OnGameStart);

        //加载UI并显示UI
        UIComponent UI = GameEntry.GetComponent<UIComponent>();
        //(按顺序进行出现) 第三个参数优先级priority暂时未发现用途                
        int id = UI.OpenUIForm("Assets/AssetBundles/Prefab/UIMenu.prefab", "NormalGroup");
        this.procedureOwner = procedureOwner;
    }

    /// <summary>
    /// 触发EventName.GameStart事件时的回调方法
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnGameStart(object sender, GameEventArgs e)
    {
        ChangeState<ProcedureGame>(procedureOwner);
    }

}

UIMenu.prefab挂载一个继承于UIFormLogic的脚本,实现了它自带的一些生命周期方法如OnInit OnOpen等,在按钮按下时会销毁当前Menu场景,同步追加Game场景,并发送ProcedureMenu流程监听的事件类对象(其id为EventName.GameStart),并调用UIComponent的关闭UI方法,进行关闭当前UI。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;

public class UIMenu : UIFormLogic
{
    private Button button;
    private void Awake()
    {
    }
    protected override void OnInit(object userData)
    {
        base.OnInit(userData);
        button = transform.Find("EnterGameBtn").GetComponent<Button>();
    }

    protected override void OnOpen(object userData)
    {
        base.OnOpen(userData);
        button.onClick.AddListener(EnterGame);
    }

    protected override void OnClose(bool isShutdown, object userData)
    {
        base.OnClose(isShutdown, userData);
        button.onClick.RemoveAllListeners();
    }

    protected override void OnRecycle()
    {
        base.OnRecycle();
        button = null;
    }

    public void EnterGame()
    {
        SceneComponent scene = GameEntry.GetComponent<SceneComponent>();
         卸载所有场景
        //string[] loadedSceneAssetNames = scene.GetLoadedSceneAssetNames();
        //for (int i = 0; i < loadedSceneAssetNames.Length; i++)
        //{
        //    scene.UnloadScene(loadedSceneAssetNames[i]);
        //}       

        scene.UnloadScene("Assets/Scenes/Menu.unity", this);
        scene.LoadScene("Assets/Scenes/Game.unity", this);
        EventComponent Event = GameEntry.GetComponent<EventComponent>();
        Event.Fire(this, new CommonGameEventArgs((int)EventName.GameStart));
        UIComponent UI = GameEntry.GetComponent<UIComponent>();
        UI.CloseUIForm(UIForm);//关闭自身        
    }
}

其中CommonGameEventArgs是一个自定义的事件参数类,取名为公共游戏事件参数类,它允许传入事件ID动态设置自身ID,而不是固定ID,但这也带来了坏处,则是不能够写入太多非公共的方法处理数据等情况。(此例仅做参考,实战还是单独一个ID一个类比较好,模仿GameFramework内置的一些事件参数类即可)

using GameFramework.Event;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CommonGameEventArgs : GameEventArgs
{
    private int m_Id;
    public override int Id => m_Id;

    public CommonGameEventArgs(int id)
    {
        m_Id = id;
    }
    public override void Clear()
    {

    }
}

当点击进入游戏按钮,派发事件后会触发ProcedureMenu类的OnGameStart方法执行跳转到ProcedureGame流程。

ProcedureGame流程进行了加载配置表,并监听内置的加载配置成功事件LoadDataTableSuccessEventArgs.EventId。

using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
using GameFramework.Event;
using GameFramework.DataTable;

public class ProcedureGame : ProcedureBase
{
    protected override void OnEnter(ProcedureOwner procedureOwner)
    {
        base.OnEnter(procedureOwner);
        Log.Debug("ProcedureGame 状态进入!");

        EventComponent Event = GameEntry.GetComponent<EventComponent>();
        Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnDataLoadedSuccess);

        // 获取框架数据表组件
        DataTableComponent dataTableComponent
            = UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
        IDataTable<TestConfig> dataTable = dataTableComponent.CreateDataTable<TestConfig>();
        DataTableBase dataTableBase = dataTable as DataTableBase;
        dataTableBase.ReadData("Assets/AssetBundles/Resources/Test.txt");
    }

    private void OnDataLoadedSuccess(object sender, GameEventArgs e)
    {
        UIComponent UI = GameEntry.GetComponent<UIComponent>();
        int id = UI.OpenUIForm("Assets/AssetBundles/Prefab/UIGame.prefab", "NormalGroup", this);
    }
}

UIGame类是一个测试加载出的配置表内容的UI类,如下所示:

using GameFramework.DataTable;
using GameFramework.Event;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;

public class UIGame : UIFormLogic
{
    Button button;
    protected override void OnInit(object userData)
    {
        base.OnInit(userData);
        button = transform.Find("Button").GetComponent<Button>();
    }
    protected override void OnOpen(object userData)
    {
        base.OnOpen(userData);
        button.onClick.AddListener(OnClick);
    }
    protected override void OnClose(bool isShutdown, object userData)
    {
        base.OnClose(isShutdown, userData);
        button.onClick.RemoveAllListeners();
    }

    private void OnClick()
    {
        //获取配置表TestConfig表
        DataTableComponent dataTableComponent = GameEntry.GetComponent<DataTableComponent>();
        IDataTable<TestConfig> dtScene = dataTableComponent.GetDataTable<TestConfig>();

        TestConfig[] allTestConfigs = dtScene.GetAllDataRows();// 所有的行获取为数组        

        //注意:Config必须要有一个int名为id的字段
        TestConfig first = dtScene.GetDataRow(1); //获取的是ID为1的TestConfig
        if (first != null)
        {
            Log.Debug("first id = 1:" + first.ToString());
        }
        else
        {

        }
        //获取所有满足条件的行
        TestConfig[] testConfigsIdGreater0s = dtScene.GetDataRows((x) => { return x.Id > 0; });
        foreach (var v in testConfigsIdGreater0s)
        {
            Log.Debug("testConfigsIdGreater0 :" + v.ToString());
        }
        //获取第一次满足条件的行 返回它
        TestConfig testConfigsNameEqualCondition = dtScene.GetDataRow((x) => { return x.Name == "mutou"; });
        Log.Debug("testConfigsNameEqualCondition:" + testConfigsNameEqualCondition.ToString());
    }
}

相关信息截图,以供参考制作对应的prefab、excel等。(其实excel就是加载配置表那个表)

猜你喜欢

转载自blog.csdn.net/qq_39574690/article/details/108891470
今日推荐