只有你足够强,别人才会和你讲道理。
文章: 280
浏览: 3,005,055
  • 博主:笨木头
  • 关注:Unity、Net Core、Blazor
  • 邮箱:musicvs@163.com
笨木头  2018-03-15 17:10     Unity3D,Game Framework     阅读(19386)     评论(21)
转载请注明,原文地址: http://www.benmutou.com/archives/2579
文章来源:笨木头与游戏开发
本文 Game Framework 版本:3.1.1

本文 Unity3D 版本:2017.3

更多GF教程和实例:https://github.com/mutouzdl/gameframework_demo.git

 
转载请注明,原文地址:http://www.benmutou.com/archives/2579 文章来源:笨木头与游戏开发
 

加载配置文件也算是这个框架的基础,很多事情都依赖于配置文件(比如加载实体也是先读取配置文件,然后再创建对象的),本Demo将和大家一起了解GameFramework是如何加载配置文件的。

关于加载配置文件,官网也是有文档的,大家可以选择看文档:http://gameframework.cn/archives/category/module/buildin/datatable

本文只做简单的补充说明,和要注意的地方。

1.配置文件格式

官方默认的配置文件格式是"制表符分隔"文本,即用tab作为分隔符的文件。

比如我们新建一个Hero.txt配置文件,如下格式(使用Excel编辑):



带有#号的行为注释行,不带#号的为正式数据。

2.导出配置文件

在框架中是不能直接加载Excel配置文件的,需要保存为制表符分隔的文本文件,使用Excel自带的另存为功能即可:

3.关于文件格式的坑

官方的文档特意说明了,导出的文本文件编码必须是ANSI,为此我遇到了一点问题——文件总是无法加载出来,内容一直是空的。

我以为是我的文件格式有问题,所以折腾了很久(这也是为什么这篇Demo隔了这么久才发布)。

原因是我的文件里带有中文,官方明确指出,除了注释行,其他地方不要出现中文。

然而,我只是注释行里出现了中文,依然无法加载。

最终,我把Hero.txt文件再另存为UTF-8格式,问题就解决了,大家也多留意一下。

4.与配置文件对应的类

因为文件需要加载到内存,当然需要对象来存储,我们首先要建一个和文件字段一一对应的类。

新建一个脚本,命名我DRHero.cs,内容如下:
using System.Collections;
using System.Collections.Generic;
using GameFramework.DataTable;
using UnityEngine;
public class DRHero : IDataRow
{
    public int Id { get; protected set; }
    public string Name { get; private set; }
    public int Atk { get; private set; }
    public void ParseDataRow(string dataRowText)
    {
        string[] text = dataRowText.Split('\t');
        int index = 0;
        index++; // 跳过#注释列
        Id = int.Parse(text[index++]);
        Name = text[index++];
        Atk = int.Parse(text[index++]);
    }
}
我们的Hero.txt文件里包含了Id、Name、Atk三个字段内容,所以DRHero类里也有对应的字段。

并且DRHero需要继承IDataRow,最重要的是ParseDataRow函数,这是解析配置文件的关键地方。

当框架读取配置文件时,会把文件的每一行内容作为参数调用ParseDataRow函数,这个函数负责解析字段内容。

由于Hero.txt是使用tab分隔的,所以直接把一行的内容按照tab拆分,然后一个个读取即可(注意,第1列是#号注释列,需要跳过)。

5.加载配置文件

新建一个Demo5场景,并且新建一个Demo5_ProcedureLaunch.cs脚本,作为初始流程。

我们在初始流程的OnEnter函数里加载配置文件:
protected override void OnEnter(ProcedureOwner procedureOwner)
    {
        base.OnEnter(procedureOwner);
        // 获取框架事件组件
        EventComponent Event
            = UnityGameFramework.Runtime.GameEntry.GetComponent<EventComponent>();
        // 获取框架数据表组件
        DataTableComponent DataTable
            = UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
        // 订阅加载成功事件
        Event.Subscribe(UnityGameFramework.Runtime.LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
        // 加载配置表
        DataTable.LoadDataTable<DRHero>("Hero", "Assets/Demo5/Hero.txt");
    }

 

由于GameFramework加载资源都是异步的,所以我们需要通过订阅LoadDataTableSuccessEvent事件来监听文件的加载。

加载配置文件需要用到框架的DataTableComponent组件的LoadDataTable函数。

函数需要指定配置表对应的类类型(这里是DRHero),第一参数是数据表名称,暂时没发有什么作用,第二个参数是配置文件的路径。

6.读取加载完成的文件数据

刚刚只是加载了配置文件,我们需要在很多地方用到文件的内容,所以接下里就要读取配置文件的内容。

之前已经订阅了配置表加载成功的事件,所以我们在这个事件里加载文件内容试试(实际上我们可以在其他地方加载,配置文件已经在内存里了,可以随时加载)
private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
    {
        // 获取框架数据表组件
        DataTableComponent DataTable
            = UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
        // 获得数据表
        IDataTable<DRHero> dtScene = DataTable.GetDataTable<DRHero>();
        
        // 获得所有行
        DRHero[] drHeros = dtScene.GetAllDataRows();
        Log.Debug("drHeros:" + drHeros.Length);
        // 根据行号获得某一行
        DRHero drScene = dtScene.GetDataRow(1); // 或直接使用 dtScene[1]
        if (drScene != null)
        {
            // 此行存在,可以获取内容了
            string name = drScene.Name;
            int atk = drScene.Atk;
    Log.Debug("name:" + name + ", atk:" + atk);
        }
        else
        {
            // 此行不存在
        }
        // 获得满足条件的所有行
        DRHero[] drScenesWithCondition = dtScene.GetAllDataRows(x => x.Id > 0);
        
        // 获得满足条件的第一行
        DRHero drSceneWithCondition = dtScene.GetDataRow(x => x.Name == "mutou");
    
    }
加载配置表内容还是需要用到DataTableComponent组件,通过组件的GetDataTable函数即可获取配置表内容,获得IDataTable<DRHero>集合对象。

通过调用集合的GetAllDataRows可以获取配置表所有行的数据,通过GetDataRow可以获取某一个的数据。

并且,GetAllDataRows和GetDataRow支持传入查询表达式进行条件筛选,如果大家有用过LINQ的话,就知道这是有多方便的事情了。

7.唠叨一下

其实加载配置文件的核心步骤只有4个:

a.创建配置文件

b.创建文件类

c.加载配置文件到内存

d.在需要的地方读取配置文件内容

明白了这四个步骤,就没问题了。

 

OK,更多的内容大家还是参考官方文档吧,我在这里仅作补充说明。

21 条评论
  • 一学就废 2022-08-25 16:08:11

    DRHero.cs类为
    public bool ParseDataRow(string dataRowString, object userData)
    {
    string[] text = dataRowString.Split('\t');

    int index = 0;
    index++; // 跳过#注释列

    Id = int.Parse(text[index++]);
    Name = text[index++];
    Atk = int.Parse(text[index++]);

    return true;
    }

    Demo5_ProcedureLaunch.cs类中的
    DataTable.LoadDataTable("Hero", "Assets/Demo5/Hero.txt");更换为
    DataTableBase dataTableBase = DataTable.CreateDataTable(Type.GetType("DRHero"));
    dataTableBase.ReadData("Assets/GameMain/DataTables/Hero.txt");
    // 获得满足条件的所有行DRHero[] drScenesWithCondition = dtScene.GetAllDataRows(x => x.Id > 0);更换为
    DRHero[] drScenesWithCondition = dtScene.GetDataRows(x => x.Id > 0);
    24回复
    • 大宝 2023-07-25 16:46:35

      using System;
      1回复
  • 于铁锌 2022-03-10 15:38:04

    Load data table failure, asset name 'Assets/UserYu/Demo5/Hero.txt', error message 'GameFramework.GameFrameworkException: Data asset '# 配置文件测试
    # int string int
    # ID 名称 攻击
    1 hema 1
    2 motou 999
    3 tom 8
    ' is 'NotExist'.

    0回复
  • Claux 2021-12-03 21:58:56

    //新版本加载配置表的方式。摘自StarForce
    DataTableComponent DataTable = GameEntry.GetComponent();
    //创建并加载配置表
    DataTableBase dataTableBase = DataTable.CreateDataTable(Type.GetType("DRHero"));
    dataTableBase.ReadData("Assets/GameMain/DataTables/Hero.txt");
    4回复
  • 方向 2021-04-09 15:22:50

    希望能更新一下加载配置文件
    0回复
  • 小学生 2020-08-19 16:34:10

    希望更新一篇新的加载的表格数据教程,大佬 新的框架已经不适用了
    0回复
  • 上上下下左右左右BABA 2019-07-03 17:40:59

    木头大佬,我使用新版本加载配置文件果不其然出现问题。想了一下午找不到解决方案,可否说一下新版本怎么加载配置文件呢?
    0回复
    • 博主 笨木头 2019-07-03 17:50:45

      新版本ParseDataRow函数改成这样了:
      public override bool ParseDataRow(GameFrameworkSegment dataRowSegment) {}

      然后分割字段变成这样:
      string[] text = dataRowSegment.Source.Substring(dataRowSegment.Offset, dataRowSegment.Length).Split(ColumnSplit, StringSplitOptions.None);

      这个详细的可以参考一下官方最新的飞机Demo(。_。)
      0回复
      • dd 2019-10-09 17:32:33

        官方最新的demo飞机在哪里下载呀
        0回复
        • 博主 笨木头 2019-10-10 07:24:47

          这里:https://github.com/EllanJiang/StarForce
          我也有写过关于飞机Demo的小教程:http://www.benmutou.com/archives/2473
          0回复
  • kuxuee 2019-06-03 17:27:21

    不支持中文有点不科学,比如配置文件 角色有名字,武器有名字,这可咋整
    0回复
    • 博主 笨木头 2019-06-04 07:42:02

      支持中文的,用UTF-8就好,我的游戏一直在用,都有中文内容。原文可能误导大家了
      0回复
  • 静享生活 2019-04-29 13:52:00

    startForce那个demo中有直接根据配置文件生成对应文件类的工具类”DataTableGeneratorMenu“,我觉得配置文件多的话可以参考一下用。
    0回复
  • fa 2019-02-25 14:54:25

    [与配置文件对应的类]的时候继承的IDataRow报错:“DRHero”不实现接口成员“IDataRow.ParseDataRow(GameFrameworkSegment)” [Assembly-CSharp]
    '“DRHero”不实现接口成员“IDataRow.ParseDataRow(GameFrameworkSegment)” [Assembly-CSharp]
    '“DRHero”不实现接口成员“IDataRow.ParseDataRow(GameFrameworkSegment)” [Assembly-CSharp]
    0回复
    • 博主 笨木头 2019-02-25 17:49:45

      确实,新版本已经改了函数结构了...本文不适应新版本...
      0回复
    • sky 2019-05-20 16:06:30

      新版本继承这个DataRowBase,参数改成GameFrameworkSegment dataRowSegment,感觉越改越麻烦了呢。
      0回复
  • 阿里晕呕爱思 2018-06-20 21:33:13

    Load data table failure, asset name 'Assets/Example/Demo5/Hero.txt', error message 'GameFramework.GameFrameworkException: Can not parse data table 'DRHero' at ' 1 libai 999' with exception 'System.FormatException: Input string was not in the correct format
    按照您的教程,我把表的数据全部换成英文了,还是读不出来
    0回复
    • 博主 笨木头 2018-06-21 07:34:14

      这个报错信息,可能是你读字段的顺序错了,也可能是你的文件格式有点问题,建议调试一下。
      0回复
      • 阿里晕呕爱思 2018-06-22 15:05:26

        找到原因了哈哈哈哈,谢谢
        0回复
发表评论
粤ICP备16043700号

本博客基于 BlazorAnt Design Blazor 开发