一个简单的游戏框架:配置表方案
代码:https://github.com/HushengStudent/myGameFramework
1、配置表格式
csv,逗号分隔,可以使用wps和Excel打开编辑,方便策划使用;
默认第一行为注释;
默认第二行为字段名+类型;二者以冒号隔开;
默认第一列为主键;
2、配置表导出方案
在编辑器下,读取配置表的内容,并把内容按规则转换成对应类型,然后把内容转换为对应的字节数组,写入到二进制文件,并生成对应的读表代码,在使用配置表的时候,根据生成的读表代码,自动加载对应的二进制文件,从而实现配置表解决方案;
(1)数据类型转换为byte[]
如:
#region int
private static int _intLength = 4;
public static int INT_LENGTH { get { return _intLength; } }
/// <summary>
/// 以字节数组的形式返回指定的32位有符号整数值;
/// </summary>
/// <param name="value">要转换的数字;</param>
/// <returns>长度为4的字节数组;</returns>
public static byte[] GetBytes(int value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 返回由字节数组中前四个字节转换来的32位有符号整数;
/// </summary>
/// <param name="value">字节数组;</param>
/// <returns>由四个字节构成的32位有符号整数;</returns>
public static int GetInt32(byte[] value)
{
return BitConverter.ToInt32(value, 0);
}
/// <summary>
/// 返回由字节数组中指定位置的四个字节转换来的32位有符号整数;
/// </summary>
/// <param name="value">字节数组;</param>
/// <param name="startIndex">value内的起始位置;</param>
/// <returns>由四个字节构成的32位有符号整数;</returns>
public static int GetInt32(byte[] value, int startIndex)
{
return BitConverter.ToInt32(value, startIndex);
}
这样就能完成类型转换;
字符串在使用的时候,约定第一位为字符串的长度:
#region string
/// <summary>
/// 以UTF-8字节数组的形式返回指定的字符串;
/// </summary>
/// <param name="value">要转换的字符串;</param>
/// <returns>UTF-8字节数组;</returns>
public static byte[] GetBytes(string value)
{
return Encoding.UTF8.GetBytes(value);
}
/// <summary>
/// 返回由UTF-8字节数组转换来的字符串;
/// </summary>
/// <param name="value">UTF-8字节数组;</param>
/// <returns>字符串;</returns>
public static string GetString(byte[] value)
{
if (value == null)
{
throw new Exception("Value is invalid.");
}
return Encoding.UTF8.GetString(value, 0, value.Length);
}
#endregion
protected static void ReadString(ref byte[] byteArr, ref int byteOffset, out string str)
{
int len;
//第一位为长度;
ReadInt32(ref byteArr, ref byteOffset, out len);
str = Encoding.UTF8.GetString(byteArr, byteOffset, len);
byteOffset += len;
}
每读一次,就计算对应位置偏移;
(2)二进制文件的读取与生成
#region Txt
/// <summary>
/// 保存Txt;
/// </summary>
/// <param name="path"></param>
/// <param name="contents"></param>
public static void Write2Txt(string path, string[] contents)
{
File.WriteAllLines(path, contents);
}
/// <summary>
/// 读取Txt;
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string[] ReadFromTxt(string path)
{
return File.ReadAllLines(path);
}
#endregion
#region Bytes
/// <summary>
/// 保存Bytes;
/// </summary>
/// <param name="path"></param>
/// <param name="bytes"></param>
public static void Write2Bytes(string path, byte[] bytes)
{
File.WriteAllBytes(path, bytes);
}
/// <summary>
/// 读取Bytes;
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static byte[] ReadFromBytes(string path)
{
return File.ReadAllBytes(path);
}
#endregion
主要使用以上方法读取txt,修改txt,将txt转换为byte[],将byte[]写入文件;
之前有写过用MemoryStream写入字节流,然后调用GetBuff()获得byte[]数组,但是出错了;
扫描二维码关注公众号,回复:
2188409 查看本文章
备注
请注意,在缓冲区中包含分配的字节数,这可能是未使用。 例如,如果"test"的字符串写入到 MemoryStream 对象,从返回的缓冲区的长度 GetBuffer 为 256,而非 4,与未使用为 252 字节。 若要获取缓冲区中的数据,请使用 ToArray 方法; 但是, ToArray 在内存中创建数据的副本。
也可以是缓冲区 null。
(3)示例
道具Id,道具名字,道具描述
ItemId:INT,ItemName:STRING,ItemDes:STRING
1,屠龙刀,屠龙宝刀,武林至尊
2,倚天剑,倚天不出,谁与争锋
3,打狗棒,丐帮帮主信物
生成读表代码:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using Framework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemTableDB : BaseTableDB<ItemTable>
{
public static readonly ItemTableDB instance=new ItemTableDB();
}
// Generated from: ItemTable.csv
public class ItemTable : TableData
{
public int ItemId;
public string ItemName;
public string ItemDes;
public override int Key
{
get
{
return ItemId;
}
}
public override void Decode(byte[] byteArr, ref int bytePos)
{
ReadInt32(ref byteArr,ref bytePos,out ItemId);
ReadString(ref byteArr,ref bytePos,out ItemName);
ReadString(ref byteArr,ref bytePos,out ItemDes);
}
}
BaseTable主要是读表代码,为了方便管理,提供Table基类,统一调用Load方法;
测试加载:
TableMgr.Instance.LoadTable("ItemTable",ItemTableDB.instance);
调用该方法,就会自动加载ItemTable,并读取对应的二进制文件,并且把文件数据加载到ItemTableDB.instance对象;