UGF学习6-导表

数据表

什么是数据表

excel->text->UGF

使用方法

基本流程

  1. 编写Excel数据表格
  2. 将Excel数据表格保存为UTF-8编码的txt文本文件
  3. 编写数据表的解析类,该类需要继承 DataRowBase 类
  4. 在UGF的预加载流程中读取数据表txt文本文件,完成框架的解析
  5. 在编程时通过行号取得数据表数据

常用方法

加载数据表

  1. 实例化数据表对象
    IDataTable<数据类> dataTable = GameEntry.DataTable.CreateDataTable<数据类>();
  2. 将自定义的数据表对象装箱为数据表基类 DataTableBase
    DataTableBase dataTableBase = dataTable as DataTableBase;
  3. 将数据加载如数据表
    dataTableBase.ReadData("数据表txt文件路径", this);

代码案例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using GameFramework.DataTable;
using GameFramework.Event;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

public class Demo5_ProcedureLaunch : ProcedureBase
{
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
// 订阅加载成功事件
GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
// 订阅加载失败事件
GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
// 加载配置表
IDataTable<DRScene> dataTable = GameEntry.DataTable.CreateDataTable<DRScene>();
DataTableBase dataTableBase = dataTable as DataTableBase;
dataTableBase.ReadData("Assets/GameMain/DataTables/Scene.txt", this);
}
// 加载失败响应函数
private void OnLoadDataTableFailure(object sender, GameEventArgs e)
{
Log.Debug("失败");
}
// 加载成功响应函数
private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
{
LoadDataTableSuccessEventArgs ne = e as LoadDataTableSuccessEventArgs;
if (ne.UserData != this)
return;
Log.Debug("加载成功! " + ne.DataTableAssetName);
}
}

获取数据

  • 获取数据表对象
    IDataTable<数据类> 数据表对象 = DataTable.GetDataTable<数据类>();

  • 获取所有数据行,返回数据行数组
    数据类[] 数据表对象.GetAllDataRows();

  • 获取指定数据行
    数据表对象.GetDataRow(行号);

    不存在此行时返回空

  • 获取所有满足条件的数据行
    数据表对象.GetDataRows((x) => { return x.Id > 0; });

  • 获取满足条件的第一个数据行
    数据表对象.GetDataRow((x) => { return x.AssetName == "Land"; });

案例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
{
// 获取数据表对象
IDataTable<DRScene> dataTable = GameEntry.DataTable.GetDataTable<DRScene>();
//使用方法1:获得所有的行,并转化为数组(不转换带表格开头带#的)
DRScene[] allData = dataTable.GetAllDataRows();
Log.Debug("allData行数 : " + allData.Length);

//使用方法2:获取的第x行的数据
DRScene first = dataTable.GetDataRow(1);
if (first != null)
{
// 此行存在,可以获取内容了
Log.Debug(first.Id + " " + first.AssetName + " " + first.AssetValue);
}

//使用方法3:获取所有满足条件的行
DRScene[] usefulRows = dataTable.GetDataRows((x) => { return x.Id > 0; });
foreach (var drScene in usefulRows)
{
Log.Debug("usefulRows :" + drScene);
}

//使用方法4:获得满足条件的第一行
DRScene usefulRow = dataTable.GetDataRow((x) => { return x.AssetName == "Land"; });
Log.Debug("usefulRow:" + usefulRow);
}

使用案例

以场景数据表为例:

  1. 编写Excel数据表格

  2. 将Excel数据表格保存为UTF-8编码的txt文本文件

  3. 编写数据表的解析类,该类需要继承 DataRowBase 类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    using UnityGameFramework.Runtime;

    public class SceneConfig : DataRowBase
    {
    // 数据表行号
    private int m_Id;
    public override int Id => m_Id;
    // 场景名称
    public string SceneName { get; private set; }
    // 场景路径
    public string ScenePath { get; private set; }
    // 场景描述
    public string SceneInfo { get; private set; }
    // 字符流逐行解析
    public override bool ParseDataRow(string dataRowString, object userData)
    {
    //输入的是每一行字符串,
    string[] columnStrings = dataRowString.Split('\t');
    int index = 1;
    m_Id = int.Parse(columnStrings[index++]);
    SceneName = columnStrings[index++];
    ScenePath = columnStrings[index++];
    SceneInfo = columnStrings[index++];
    return true;
    }
    }
  4. 在UGF的预加载流程中读取数据表txt文本文件,完成框架的解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    using GameFramework.DataTable;
    using GameFramework.Event;
    using GameFramework.Procedure;
    using UnityGameFramework.Runtime;
    using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

    public class LaunchProcedure : ProcedureBase
    {
    protected override void OnEnter(ProcedureOwner procedureOwner)
    {
    base.OnEnter(procedureOwner);
    GameEntry.InitBuiltinComponents();

    // 订阅加载成功事件
    GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
    // 订阅加载失败事件
    GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
    // 加载配置表
    IDataTable<SceneConfig> dataTable = GameEntry.DataTable.CreateDataTable<SceneConfig>();
    DataTableBase dataTableBase = dataTable as DataTableBase;
    dataTableBase.ReadData("Assets/GameMain/Configs/SceneConfigs.txt", this);

    ChangeState<MenuProcedure>(procedureOwner);
    }

    // 加载失败响应函数
    private void OnLoadDataTableFailure(object sender, GameEventArgs e)
    {
    Log.Debug("场景数据表加载失败!");
    }
    // 加载成功响应函数
    private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
    {
    LoadDataTableSuccessEventArgs ne = e as LoadDataTableSuccessEventArgs;
    if (ne.UserData != this)
    return;
    Log.Debug("场景数据表加载成功! " + ne.DataTableAssetName);
    }
    }
    1. 在编程时通过行号取得数据表数据

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class MainGameProcedure : ProcedureBase
      {
      protected override void OnEnter(ProcedureOwner procedureOwner)
      {
      base.OnEnter(procedureOwner);
      Log.Debug("进入游戏主流程");
      IDataTable<SceneConfig> dataTable = GameEntry.DataTable.GetDataTable<SceneConfig>();
      SceneConfig usefulRow = dataTable.GetDataRow((x) => { return x.SceneName == "MainScenes"; });
      GameEntry.Scene.LoadScene(usefulRow.ScenePath, this);
      }

      }

程序化生成

https://blog.csdn.net/qq_35179648/article/details/112300863

原理

DataRowBase接口

  • 行号
    int Id
    抽象属性,需要重写

    1
    2
    3
    // 数据表行号
    private int m_Id;
    public override int Id => m_Id;
  • 逐行解析

    • 字符流
      bool ParseDataRow(string dataRowString, object userData)
    • 字节流
      bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData)

实现案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 字符流逐行解析
public override bool ParseDataRow(string dataRowString, object userData)
{
//输入的是每一行字符串,
string[] columnStrings = dataRowString.Split('\t');

int index = 1;
m_Id = int.Parse(columnStrings[index++]);

SceneID = int.Parse(columnStrings[index++]);
SceneName = columnStrings[index++];
SceneInfo = columnStrings[index++];

return true;
}

全局配置表

全局配置表用于存储一些全局只读的游戏配置。

使用方法

全局配置表使用方法如下:

  1. 书写全局配置文档(方法同数据表)

  2. 预加载流程中读取配置文档
    string configAssetName = AssetUtility.GetConfigAsset(configName, false);

  3. 解析文档到框架
    编写解析脚本(方法同数据表)
    将解析脚本挂到Config对象上

    使用GameEntry.Config.ReadData(configAssetName, this);方法解析配置文档

  4. 通过全局配置组件使用配置表内容