目录
前言:
一、Entity配置表
1、创建数据表
2、创建数据表行类
二、Character配置表
1、创建数据表
2、写数据表行类
三、加载数据表
四、扩展一下Entity模块
五、应用Character数据表的位置信息
六、测试
总结:
前言:
上一篇中我们已经成功在场景中加载出了玩家实体,并且能够控制玩家移动。但是上次是直接调用实体模块加载出实体,在游戏体量大了之后,代码中到处充斥着这种加载方式的代码就会带来诸多问题,比如需要改变实体的资源路径名的话,就得找到各处的相关代码进行修改,这将大大提高维护和修改复杂度。所以我们需要引入数据表这样一个伟大的东西,来对游戏主体和实体资源之间进行进一步的解耦。
这一次我们将借用数据表,先配置实体数据表的信息,然后读取数据表的配置信息加载出实体。
一、Entity配置表
1、创建数据表
首先在excel里面这么打:
(#开头的是注释。要真正搞懂数据表怎么写与其看各种教程比较推荐啃源码,看看源码是怎么处理读取的数据表的字符串的,这样自己可以不用总是按照StarForce的格式写,也可以自定义自己的数据表格式,自定义解析数据表的方式等。)
接着导出为txt文件Entity,放到数据表文件夹下面:
2、创建数据表行类
数据表行类的作用就是用来解析数据表的每一行的,看看StarForce的就知道怎么写了:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using UnityGameFramework.Runtime;
namespace ShadowU
{
public class DREntity : DataRowBase
{
private int m_Id;
public override int Id
{
get { return m_Id; }
}
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);
Log.Debug(columnStrings[i]);
Log.Debug(columnStrings[i].Length);
}
int index = 0;
index++;
m_Id = int.Parse(columnStrings[index++]);
AssetName = columnStrings[index++];
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();
}
}
return true;
}
}
}
二、Character配置表
这个表用来配置和角色相关的信息,暂时就配置一个角色的初始位置.(以后多关卡可以扩展)
1、创建数据表
2、写数据表行类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using UnityGameFramework.Runtime;
namespace ShadowU
{
public class DRCharacter : DataRowBase
{
private int m_Id;
public override int Id
{
get { return m_Id; }
}
public Vector3 SpawnPosition
{
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);
Log.Debug(columnStrings[i]);
Log.Debug(columnStrings[i].Length);
}
int index = 0;
index++;
m_Id = int.Parse(columnStrings[index++]);
index++;
string[] rowSpawnPosition = columnStrings[index++].Split('|');
SpawnPosition = new Vector3(int.Parse(rowSpawnPosition[0]),int.Parse(rowSpawnPosition[1]), int.Parse(rowSpawnPosition[2]));
return true;
}
//还有个解析二进制数据的没必要写因为我不是二进制数据存储的
}
}
三、加载数据表
数据表都搞好了,下面就是加载数据表以备试用。
在ProcedureLaunch流程里面加载数据表的逻辑里面加载我们新增的两个表:
就这么简单。
四、扩展一下Entity模块
咱把”加载主角实体“这个操作整合到一个函数ShowPlayer()里面,并且作为Entity模块的一个扩展方法:
五、应用Character数据表的位置信息
数据表里的这个SpawnPosition位置信息,是要写到玩家实体对应的PlayerData类的实例数据里的Position属性里去的,最终Entity模块会根据实体数据里的Position属性确定生成实体的位置。
所以我们在PlayerData的构造方法里面查询数据表,填上玩家出生的位置信息:
六、测试
现在我们整个读取数据表加载实体的流程基本上搞定了。
我们已经创建了数据表信息,数据表行类,并且在游戏初始化的时候加载数据表。
我们利用Character数据表里的出生位置信息赋予玩家实体初始位置。
我们利用用Entity数据表里的资源名称信息加载玩家实体资源。
下面我们在主流程中调用我们写的扩展方法ShowPlayer()看看效果:
但是报错了:
找了半天错误我真的没话讲。。。
原因是数据表最后有两行空行。。。。删掉就好了。
然后在解决这个bug的时候我还发现自己代码的一些错误,DRCharacter里解析坐标时候的Int.Parse()要改成float.Parse():
然后重新运行:
点击开始
哦看来是没问题了,就是初始坐标设置的有问题(红色报错是个人问题不用管)
数据表改个坐标:
再次运行:
成功!
总结:
养成实体从数据表配置中加载的好习惯。