【GameFramework框架内置模块】3、数据表(Data Table)

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

【GameFramework框架】系列教程目录:
https://blog.csdn.net/q764424567/article/details/135831551

二、正文

2-1、简介

DataTable数据表是一个表的数据集合,可以理解为DataRow的字典集合比如Dictionary<int,T> m_DataRow

DataTable数据表是数据集合的访问查询类,主要操作有数据的增删改查方法(虽然框架提供了删除的接口,但是一般是不需要进行修改或者删除的,读取就好了)。

框架推荐我们使用DataTable数据表来设置初始数据,比如玩家初始生命值、初始蓝量、初始防御力等,下面就来看一下如何使用吧。

2-2、使用说明

2-2-1、准备数据表及生成实体类

以StarForce项目为例,数据表存放在这个位置:
在这里插入图片描述
每一个数据表都对应一个C#,这个C#对应表里面的字段,这样才能使用里面的信息,比如Music数据表
在这里插入图片描述
对应的C#类在这个目录下:
在这里插入图片描述
DRMusic.cs

//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
// 此文件由工具自动生成,请勿直接修改。
// 生成时间:2021-06-16 21:54:35.591
//------------------------------------------------------------using GameFramework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityGameFramework.Runtime;namespace StarForce
{/// <summary>/// 音乐配置表。/// </summary>public class DRMusic : DataRowBase{private int m_Id = 0;/// <summary>/// 获取音乐编号。/// </summary>public override int Id{get{return m_Id;}}/// <summary>/// 获取资源名称。/// </summary>public string AssetName{get;private set;}public override bool ParseDataRow(string dataRowString, object userData){string[] columnStrings = dataRowString.Split(DataTableExtension.DataSplitSeparators);for (int i = 0; i < columnStrings.Length; i++){columnStrings[i] = columnStrings[i].Trim(DataTableExtension.DataTrimSeparators);}int index = 0;index++;m_Id = int.Parse(columnStrings[index++]);index++;AssetName = columnStrings[index++];GeneratePropertyArray();return true;}public override bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData){using (MemoryStream memoryStream = new MemoryStream(dataRowBytes, startIndex, length, false)){using (BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8)){m_Id = binaryReader.Read7BitEncodedInt32();AssetName = binaryReader.ReadString();}}GeneratePropertyArray();return true;}private void GeneratePropertyArray(){}}
}

大家注意,这个配置表的实体类DRXXX类是工具生成的,不需要手动修改的,如果需要重新生成,可以点击菜单的Star Force→ Generator DataTables
在这里插入图片描述
DataTable数据表读取数据是分成一行一行的,每一行就是一个DataRow,在代码中对应的其实就是一个数据对象,index++是指同一行数据列数增加,一一对应了数据类型。

OK,数据表准备好之后,我们就在框架中加载配置。

2-2-2、ProcedurePreloa预加载

新建脚本,命名为Test04.cs,编辑代码:

using StarForce;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using UnityEngine;
using UnityGameFramework.Runtime;public class Test04 : MonoBehaviour
{DataTableComponent DataTable;string[] DataTableNames;void Start(){DataTable = UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();DataTableNames = new string[2] { "Scene", "Music" };// 预加载 data tables数据表foreach (string dataTableName in DataTableNames){LoadDataTable(dataTableName);}}/// <summary>/// 加载表数据/// </summary>/// <param name="dataTableName"></param>private void LoadDataTable(string dataTableName){string dataTableAssetName = AssetUtility.GetDataTableAsset(dataTableName, false);// 表名、表名资源路径、用户自定义数据DataTable.LoadDataTable(dataTableName, dataTableAssetName, this);}private void Update(){if (Input.GetKeyDown(KeyCode.W)){QueryData();}}/// <summary>/// 查询表数据/// </summary>private void QueryData(){//获取指定表数据列表var drScene = DataTable.GetDataTable<DRScene>();//根据行号查找数据DRScene scene1 = drScene.GetDataRow(1);Debug.Log("获取第一行数据的ID值:"+scene1.Id);//根据指定条件,比如按id查找,按名字查找DRScene scene2 = drScene.GetDataRow(x => x.Id == 1);DRScene scene3 = drScene.GetDataRow(x => x.AssetName == "Menu");Debug.Log("获取id等于1的场景名:"+scene2.AssetName);Debug.Log("获取场景名等于Menu的id值:" + scene3.Id);//根据条件查找多条数据DRScene[] scene4 = drScene.GetDataRows(x => x.Id > 0);for (int i = 0; i < scene4.Length; i++){Debug.Log("获取id大于0的背景音乐编号:" + scene4[i].BackgroundMusicId);}}
}

运行结果:
在这里插入图片描述

对应的Scene.txt数据表:
在这里插入图片描述
PS:这里补充说明一下,加载表数据用了StarForce项目的拓展函数,方便加载,所以需要引用StarForce命名空间,推荐大家下载StarForce项目来学习这个框架。

2-3、实现及代码分析

接下来,就分析一下这个数据表DataTable是如何加载及代码分析。

首先,用流程图说明一下:

Created with Raphaël 2.3.0 开始 创建数据节点表 编写数据表对应的cs文件 加载数据表 使用数据表

(1)第一步,创建数据节点表

数据表需要严格按照它这个格式来,行是字段,列是每条数据:
在这里插入图片描述
这样看,不太清晰,我们用Excel看一下:
在这里插入图片描述
说到这,有一点想要说明一下,因为这些数据表一般是策划来修改,然后导入到我们项目中的。

而策划一般使用Excel表,而程序需要csv、xml、Json、txt格式,所以就需要一个Excel导出这个文件的工具,这个工具我们后续也会进行拓展开发,框架没有带这些,但是框架提供了接口,也是很方便的。

(2)第二步,编写数据表对应的CS文件
这个是工具自动生成的,点击菜单的Star Force→Generate DataTables,来看一下代码如何实现的:
在这里插入图片描述
DataTableGenerator.cs脚本,获取到表里面的行的数据保存到字符序列中,然后保存到文件中:
在这里插入图片描述

(3)第三步,加载数据表

加载数据表,就是用的StarForce项目的拓展函数:

//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------using GameFramework.DataTable;
using System;
using UnityEngine;
using UnityGameFramework.Runtime;namespace StarForce
{public static class DataTableExtension{private const string DataRowClassPrefixName = "StarForce.DR";internal static readonly char[] DataSplitSeparators = new char[] { '\t' };internal static readonly char[] DataTrimSeparators = new char[] { '\"' };public static void LoadDataTable(this DataTableComponent dataTableComponent, string dataTableName, string dataTableAssetName, object userData){if (string.IsNullOrEmpty(dataTableName)){Log.Warning("Data table name is invalid.");return;}string[] splitedNames = dataTableName.Split('_');if (splitedNames.Length > 2){Log.Warning("Data table name is invalid.");return;}string dataRowClassName = DataRowClassPrefixName + splitedNames[0];Type dataRowType = Type.GetType(dataRowClassName);if (dataRowType == null){Log.Warning("Can not get data row type with class name '{0}'.", dataRowClassName);return;}string name = splitedNames.Length > 1 ? splitedNames[1] : null;DataTableBase dataTable = dataTableComponent.CreateDataTable(dataRowType, name);dataTable.ReadData(dataTableAssetName, Constant.AssetPriority.DataTableAsset, userData);}public static Color32 ParseColor32(string value){string[] splitedValue = value.Split(',');return new Color32(byte.Parse(splitedValue[0]), byte.Parse(splitedValue[1]), byte.Parse(splitedValue[2]), byte.Parse(splitedValue[3]));}public static Color ParseColor(string value){string[] splitedValue = value.Split(',');return new Color(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3]));}public static Quaternion ParseQuaternion(string value){string[] splitedValue = value.Split(',');return new Quaternion(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3]));}public static Rect ParseRect(string value){string[] splitedValue = value.Split(',');return new Rect(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3]));}public static Vector2 ParseVector2(string value){string[] splitedValue = value.Split(',');return new Vector2(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]));}public static Vector3 ParseVector3(string value){string[] splitedValue = value.Split(',');return new Vector3(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]));}public static Vector4 ParseVector4(string value){string[] splitedValue = value.Split(',');return new Vector4(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3]));}}
}

StarForce的拓展类DataTableExtension中定义LoadDataTable(ddataTableName,dataTableAssetName,this)函数通过名字获取资源路径并执行ReadData()函数。

通过DataProvie<DataTableBase>读取并解析数据:

namespace GameFramework.DataTable
{private readonly DataProvider<DataTableBase> m_DataProvider;public DataTableBase(string name){//dataProvider的初始化m_DataProvider = new DataProvider<DataTableBase>(this);}/// 数据表基类。public abstract class DataTableBase : IDataProvider<DataTableBase>{public void ReadData(string dataTableAssetName, int priority, object userData){m_DataProvider.ReadData(dataTableAssetName, priority, userData);}}    
}

通过m_ResourceManager来加载数据,然后通过m_DataProviderHelper加载数据:

/// 配置表属于AssetOnFileSystem,调用ResourceManager资源管理器,执行读取数据。
public void ReadData(string dataAssetName, int priority, object userData)
{HasAssetResult result = m_ResourceManager.HasAsset(dataAssetName);switch (result){case HasAssetResult.AssetOnFileSystem:m_ResourceManager.LoadAsset(dataAssetName, priority, m_LoadAssetCallbacks, userData);break;default:throw new GameFrameworkException(Utility.Text.Format("Data asset '{0}' is '{1}'.", dataAssetName, result.ToString()));}
}///加载成功的回调,使用数据辅助器进行读取并解析数据
private void LoadAssetSuccessCallback(string dataAssetName, object dataAsset, float duration, object userData)
{if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, dataAsset, userData)){throw GameFrameworkException}
}

(4)第四步,使用数据表
使用数据辅助类来读取数据,读取出来txt/bytes流,最后通过数据辅助类来解析数据:

public class DefaultDataTableHelper : DataTableHelperBase
{/// 读取数据表。public override bool ReadData(DataTableBase dataTable, string dataTableAssetName, object dataTableAsset, object userData){TextAsset dataTableTextAsset = dataTableAsset as TextAsset;if (dataTableTextAsset != null){return dataTable.ParseData(dataTableTextAsset.text, userData);}return false;}/// 解析数据表。public override bool ParseData(DataTableBase dataTable, string dataTableString, object userData){int position = 0;string dataRowString = null;while ((dataRowString = dataTableString.ReadLine(ref position)) != null){if (dataRowString[0] == '#') continue;dataTable.AddDataRow(dataRowString, userData)}return true;}
}

每个DR类都有ParseDataRow()函数来解析自己的数据格式,读取完毕,得到一个数据实体对象,保存在数据集合中。

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/702668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zemax人眼模型

人眼模型可以从下面这张图来提取 按照前后顺序&#xff0c;简化模型中跟成像直接相关的就是&#xff1a; 角膜、前方&#xff08;液状体&#xff09;、瞳孔、晶状体、玻璃体、视网膜 一般情况下我们认为瞳孔可以作为光阑 入瞳4mm视场&#xff08;近轴像高&#xff09;5波长0…

【Java程序设计】【C00290】基于Springboot的网上书城管理系统(有论文)

基于Springboot的网上书城管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的网上书城管理系统 本系统分为系统功能模块、管理员功能模块以及用户功能模块。 系统功能模块&#xff1a;在系统首页可以查看首…

Vue.js+SpringBoot开发生活废品回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 资源类型&资源品类模块3.3 回收机构模块3.4 资源求购/出售/交易单模块3.5 客服咨询模块 四、免责说明 一、摘要 1.1 项目介绍 生活废品回收系统是可持续发展的解决方案&#xff0c;旨在鼓…

网络编程中的read、write函数的三种返回值处理及readn和writen函数

read函数返回值为0&#xff0c;表示对端关闭。 write函数返回值为0&#xff0c;表示什么东西都没写。 比如&#xff1a;总共想读4096个字节&#xff0c;每次只发1500个字节&#xff0c;就需要读多次。 readn函数读一行&#xff0c;读到\n

java实战:Redis实现查找附近的人

本文将介绍如何使用Redis实现查找附近的人的功能。我们将探讨如何使用Redis的地理空间&#xff08;Geospatial&#xff09;索引功能&#xff0c;并展示一个简单的Java代码示例&#xff0c;该示例使用Jedis库和Redis的GEOADD命令来添加位置信息&#xff0c;以及使用GEORADIUS命令…

【Flutter/Android】运行到安卓手机上一直卡在 Running Gradle task ‘assembleDebug‘... 的终极解决办法

方法步骤简要 查看你的Flutter项目需要什么版本的 Gradle 插件&#xff1a; 下载这个插件&#xff1a; 方法一&#xff1a;浏览器输入&#xff1a;https://services.gradle.org/distributions/gradle-7.6.3-all.zip 方法二&#xff1a;去Gradle官网找对应的版本&#xff1a;h…

Unity(第六部)向量的理解和算法

标量:只有大小的量。185 888 999 &#xff08;类似坐标&#xff09; 向量:既有大小&#xff0c;也有方向。&#xff08;类似以个体为主体的方向&#xff0c;前方一百米&#xff09; 向量的模:向量的大小。&#xff08;类似以个体为主体的方向&#xff0c;前方一百米、只取一百米…

洛谷P1135题解

题目背景 感谢 yummy 提供的一些数据。 题目描述 呵呵&#xff0c;有一天我做了一个梦&#xff0c;梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯&#xff0c;而且第 i 层楼&#xff08;1≤i≤N&#xff09;上有一个数字 K[i]​&#xff08;0≤K[i]​≤N&#xff09;…

最新红盟云卡个人自动发卡开源系统源码优化版

红盟云卡系统是云商学院旗下的一款基于 PHPMySQL 开发的虚拟商品在线售卖平台。它是一款漂亮且功能丰富的发卡网站&#xff0c;可以与社区进行对接。该系统完全开源且无任何加密&#xff0c;可商业使用&#xff0c;并支持个人免签多个接口。 下载地址&#xff1a;优化版.zip

【JavaEE Spring 项目】在线 OJ 系统

在线OJ系统 1. 需求2. 最终页面展示3. 需求分析4. 创建 Spring 项目5. 前后端交互接口约定6. 后端功能实现6.1 编译运行模块6.1.1 进程和线程的相关知识6.1.2 Java 中的多进程编程6.1.3 进程间通信 -- 文件6.1.4 Java中的 IO 知识6.1.5 封装创建进程执行命令工具类6.1.6 实现编…

项目:shell实现多级菜单脚本编写

目录 1. 提示 2. 演示效果 2.1. 一级菜单 2.2. 二级菜单 2.3. 执行操作 3. 参考代码 1. 提示 本脚本主要实现多级菜单效果&#xff0c;并没有安装LAMP、LNMP环境&#xff0c;如果要用在实际生成环境中部署LNMP、LAMP环境&#xff0c;只需要简单修改一下就可以了。 2. 演…

C#高级--设计模式(七个原则)

一、单一职责原则 原理&#xff1a; 单一职责原则即&#xff1a;对于一个类而言&#xff0c;应该仅有一个引起他变化的原因。换言之&#xff0c;一个类只负责一个功能领域中的相应职责。 单一职责原则是实现高内聚、低耦合的指导方针&#xff0c;它是最简单但又最难运用的原则…

keepalived+HAProxy+MySQL双主实验

keepalivedHAProxyMySQL双主实验 环境准备 node1(HAProxy1):192.168.184.10 node2(HAProxy2):192.168.184.20 node3(MySQL1):192.168.184.30 node4(MySQL2):192.168.184.40 虚拟IP vip&#xff1a;192.168.184.100MySQL部署 在node3执行以下脚本&#xff1a; #!/bin/bash sy…

具身智能(Embodied AI)的概念、核心要素、难点及突破性进展

在ChatGPT之后&#xff0c;具身智能&#xff08;Embodied AI&#xff09;这个大模型概念火了&#xff0c;那什么是具身智能呢&#xff1f; 什么是具身智能&#xff1f; 具身智能作为人工智能发展的一个重要分支&#xff0c;正在迅速崭露头角&#xff0c;成为科技界和大众关注…

c++ http操作接口

很简单的使用libcurl来操作http与服务器来通讯&#xff0c;包含http与https&#xff0c;对外只开放 #include "request.h" #include "response.h" #include "url.h" 三个头文件&#xff0c;简单易用&#xff0c;使用的实例如下&#xff1a; vo…

【Linux】部署单机项目(自动化启动)

目录 一.jdk安装 二.tomcat安装 三.MySQL安装 四.部署项目 一.jdk安装 1.上传jdk安装包 jdk-8u151-linux-x64.tar.gz 进入opt目录&#xff0c;将安装包拖进去 2.解压安装包 防止后面单个系列解压操作&#xff0c;我这边就直接将所有的要用的全部给解压&#xff0c;如下图注…

【数据集】世界水评估方案指标:灌溉面积/灌溉用水等

世界水评估方案指标 概述(Overview)数据下载(Data Download)案例1:F. Irrigated lands案例2:G. Irrigated water use参考World Water Development Report II-Indicators for World Water Assessment Programme 概述(Overview) 在关于全球环境变化和可持续发展的辩论…

(详细使用指南)Linux下交叉编译带ffmpeg的opencv并移植到RK3588等ARM端

一 问题背景 瑞芯微RK3588等嵌入式板作为边缘端设备为算法模型的部署提供了便利&#xff0c;目前很多分类或好检测模型针对边缘端做了优化或量化&#xff0c;使得在边缘端也能达到实时稳定的识别和检测效果。 但嵌入式设备普遍的flash emmc不大&#xff0c;一般在32G左…

Jitsi Meet 大型视频会议调优方案

jitsi meet 大型视频会议调优方案 在举办一些大型会议的时候,比如100个人会议,为了节约宽带和节省资源,我们并不会选择传输全部的音视频资源。 举个例子,比如100个人线下会议,如果大家都说话的情况下,大家要么听不清,要么听得是声音最大的那几个人。 视频会议也可以借…

Linux开发:pam5 Ubuntu22.04中编译linux-pam

Ubuntu22.04中使用的是linux-pam GitHub - linux-pam/linux-pam: Linux PAM (Pluggable Authentication Modules for Linux) project linux-pam不仅包含了源代码还有相关的文档以及例子&#xff0c;是学习pam的一个很好的参考。 编译linux-pam的方法&#xff1a; 1.下载源代码…