游戏里的数据json存入数据库json文件还是用playerpref 好

4433人阅读
IOS开发(23)
cocos2d-x(4)
游戏客户端里一般无法读取策划写的excel配置表,需要先转成可以用的格式,例如json,xml格式。
我用到的工具是python脚本,python脚本的强大就在这不提啦,各种牛X的成熟库。。。
执行脚本如下:&import os
import sys
import codecs
import json
from xlrd import open_workbook
# &&type 'unicode'&&
# &&type 'float'&&
def my_text_(text):
&&&Return the translated text from json text.&&&
v = (&&type '&, &'&&)
if text[:len(v[0])] != v[0]: return text
if text[-len(v[1]):] != v[1]: return text
return text[len(v[0]) : -len(v[1])]
def sheet2json(sheet, jsonfile):
attribute_row = []
for col in range(sheet.ncols):
attribute_row.append(sheet.cell(row, col).value)
attribute = {}
for col in range(sheet.ncols):
attribute[attribute_row[col]] = my_text_(repr(type(sheet.cell_value(row, col))))
entities = []
for row in range(2, sheet.nrows):
entity = {}
for col in range(sheet.ncols):
entity[attribute_row[col]] = sheet.cell(row, col).value
row_dict = {}
row_dict[&entity&] = entity
entities.append(row_dict)
sheet_dict = {}
sheet_dict[&entities&] = entities
filed = codecs.open(&../../jsonsFromExcel/&+jsonfile, &w&, &utf-8&) #输出目录
filed.write(&%s& % json.dumps(sheet_dict, ensure_ascii=False, indent=4))
#print json.dumps(sheet_dict, ensure_ascii=False, indent=4)
filed.close()
if len(sys.argv) != 2 :
print &usage: %s [input xls file]& % sys.argv[0]
print &e.g. : %s myinput.xls& % sys.argv[0]
print &Note : the input file should be MS excel doc.\n&
sys.exit()
xls_file = sys.argv[1]
workbook = open_workbook(xls_file)
for sheet in workbook.sheets():
jsonfile = sheet.name + &.json&
#print &Converting %s's %s from EXCEL's sheet to JSON as %s& % (xls_file, sheet.name, jsonfile)
sheet2json(sheet, jsonfile)
用这个命令前需要先在系统里安装xlrd库,一个解析excel文件的第三方库
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:117633次
积分:1482
积分:1482
排名:千里之外
原创:32篇
转载:14篇
评论:15条
(2)(1)(1)(1)(5)(2)(2)(2)(3)(2)(2)(2)(1)(2)(3)(1)(3)(2)(1)(3)(4)(1)(1)手机游戏里面的.json格式的文件打开是乱码怎么办?_百度知道游戏用到的配置用text保存json格式,这样好还是直接用mysql数据库建表保存配置好.例如技能配置.副本配置等_百度知道114网址导航游戏开发设计模式(12)
unity3d(138)
命令模式:
对象池模式:
实现原型模式
原型模式带来的好处就是,想要构建生成任意独特对象的生成类,只需要一个生成类和一个原型即可。
当我们有一个抽象的敌人Monster类就有很多继承它的各种各样的敌人,人类、动物、龙等等,如果我们想为每个敌人做一个生成器父类Spawner,也会有与monster对应数量的子类,也许就会这样:
这样就会产生类的数量变多,而且这些类的功能是重复的。
开始的spawner类可能是这样的:
using UnityE
using System.C
public class Spawner : MonoBehaviour {
public GameObject createPerson(GameObject Person)
return Instantiate(Person);
public GameObject createAnimal(GameObject Animal)
return Instantiate(Animal);
public GameObject createDragon(GameObject Dragon)
return Instantiate(Dragon);
上面的代码可见我们有重复的方法,而且随着敌人子类增多这种重复代码会越来越多。
我们可以视所有怪兽为一个原型,让Spawner类只生成这个原型,通过改变这个原型来生产不同的怪兽。
再进一步,我们可以让这个原型有一个生成自己的方法,就不需要在Spawner类中new了只需要在Spawner类调用原型的方法就可以,我们做一个monster生成(克隆)自己的方法clone()。
using UnityE
using System.C
public class Monster : MonoBehaviour {
public string MonsterN
// Use this for initialization
virtual public Monster clone()
GameObject clone()
return Instantiate(this.gameObject) as GameO
这里存在一个深复制和浅复制的问题,C#数据类型大体分为值类型(valuetype)与引用类型(referencetype)。对于值类型数据,复制的时候直接将数据复制给另外的变量, 而对于引用型变量而言,复制时,其实只是复制了其引用。复制引用的方式叫浅复制,而逐一复制被复制对象的数据成员的方式称为深复制。
unity的Instantiate就是深复制GameObject
如果你想浅复制clone函数为:
virtual public Monster clone()
浅复制返回它本身的引用,如果你想深复制,就Instantiate一个新的:
GameObject clone()
return Instantiate(this.gameObject) as GameO
再看看子类
using UnityE
using System.C
public class AnimalMonster : Monster
public AnimalMonster()
MonsterName = &Animal&;
attack = 8;
defense = 15;
weapon = &tooth&;
这样每个敌人子类都有一个clone方法,就不需要每个都配一个Spawner类了,一个Spawner就可以。
using UnityE
using System.C
public class Spawner : MonoBehaviour {
// Use this for initialization
public void setPrototype(Monster _prototype)
this.prototype = _
GameObject createMonster()
return prototype.clone();
创建他们的方法也很简单,设置原型,create。
spawner.setPrototype(People);
spawner.createMonster();
spawner.setPrototype(Animal);
spawner.createMonster();
克隆出的属性值都和原型相同,如果当前怪兽处在某种状态,比如,中毒、虚弱、灼烧,也可以被复制下来。
再进一步,我们可以通过构造函数实例化不同的spawner对象来代替不同的spawner子类,使spawner实体专一化的生成某种怪兽
using UnityE
using System.C
public class Spawner : MonoBehaviour {
// Use this for initialization
public Prototype(Monster _prototype)
this.prototype = _
GameObject createMonster()
return prototype.clone();
Spawner PersonSpawner = new Spawner(People);
Spawner AnimalSpawner = new Spawner(Animal);
PersonSpawner.createMonster();
AnimalSpawner.createMonster();
利用泛型类实现原型模式
再进一步,我们可以建立一个SpawnerFor泛型类来更加专一的生成某种怪兽,SpawnerFor泛型类继承自Spawner类
using UnityE
using System.C
public class SpawnerFor&T& : Spawner
where T : Monster
Spawner s1;
Spawner s2;
void Start()
s1 = new SpawnerFor&PersonMonster&();
s2 = new SpawnerFor&AnimalMonster&();
s1.setPrototype(People);
s2.setPrototype(Animal);
s1.createMonster();
s2.createMonster();
如果不是返回gameobject,就要写一个这样的方法:
public GameObject createMonster()
return new T();
关于First Class type
最好的办法是把类型当做参数付给了生成类,这种类型叫做First Class类型,这样把要生成的怪兽的类型作为参数付给Spawner,Spawner就知道原型是要生成这种类型的参数了。
我们把类型分为三类:
First Class。该类型可以作为函数的参数和返回值,也可以赋给变量。
Second Class。该类型可以作为函数的参数,但不能从函数返回,也不能赋给变量。
Third Class。该类型作为函数参数也不行
也就是说First Class type可以把类型看作是对象来赋值、返回值等等。
但是在C++和C#中类的类型都不是First Class type,所以需要进行一些操作,像上面的方法那样。
对原型进行数据建模
我们通过数据建模data modeling把代码变成实在的数据。
通过这种方法我们不需要Monster的子类了,因为Monster里的属性都是相同的,我们只需要一个Monster类和一个存了各种敌人的数据的文件即可。这种方式的好处在数据量大的游戏中尤为明显,省去大量代码。我们首先需要把每个怪兽的属性都储存起来,然后能提供给Spawner读取,这就是序列化与反序列化。
也通过序列化和反序列化对原型进行数据建模。使用JSON,XML等等都可以,此处博主用JSON实现
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。易于人阅读和编写,同时也易于机器解析和生成(网络传输速率)。
JSON有简易的语法,XML有范的标签形式,JSON和XML有一个很大的区别在于有效数据率。JSON作为数据包格式传输的时候具有更高的效率,这是因为JSON不像XML那样需要有严格的闭合标签,这就让有效数据量与总数据包比大大提升,从而减少同等数据流量的情况下,网络的传输压力
具体写得很全很详细
我们可以在代码中生成JSON,也可以自己在txt中编写,大概的格式是这样的
&MonsterName&: &Person&,
&attack&: 10,
&defense&: 10,
&weapon&: &Sword&
上面是本文的例子,但是如果敌人类是这样的:
&MonsterName&: &dwarf saber&,
&characteristic&: &DEF up&,
&weapon&: &sword&,
&attacks&: [&hack&,&chop&]
&MonsterName&: &dwarf archer&,
&characteristic&: &DEF up&,
&weapon&: &bow&,
&attacks&: [&shoot&,&sight&]
&MonsterName&: &dwarf caster&,
&characteristic&: &DEF up&,
&weapon&: &wand&,
&magic&: [&fire ball&,&ice storm&]
好吧,虽然在矮人中caster这个职阶并不常见(武器想写破尽万法之符来着,但是fate里没有矮人英雄啊。。矮人还是多出现在欧洲风游戏里= =;)
可以明显发现里面的HP,characteristic属性是一样的,因为都是矮人,矮人本身的特性都是一样的,这里我们就出现了重复,解决方法就是使用享元模式,把相同的单拿出来,或者放在最普通的“原怪兽”或者是一个比较简单的怪兽里,再在其他怪兽中加一个这个原模型方便取值,这里博主把它放在矮人平民中。享元模式可以节省大量空间和读取时间:
&MonsterName&: &dwarf civilian&,
&characteristic&: &DEF up&,
&MonsterName&: &dwarf saber&,
&prototype&: &dwarf civilian&,
&weapon&: &sword&,
&attacks&: [&hack&,&chop&]
&MonsterName&: &dwarf archer&,
&prototype&: &dwarf civilian&,
&weapon&: &bow&,
&attacks&: [&shoot&,&sight&]
&MonsterName&: &dwarf caster&,
&prototype&: &dwarf civilian&,
&weapon&: &wand&,
&magic&: [&fire ball&,&ice storm&]
也可以实现道具和武器的多元化,比如一把“火焰剑”就可以视为一把长剑,和附加伤害,还有一个好听的名字:
&Name&: &FireBlaze&,
&prototype&: &long sword&,
& additionalDamage &: 10
长剑中就包含了剑类所有的基本属性,比如基础伤害,武器相克效果,等等等。。这就是细微的改变带来丰富的变化!
接下来要说JSON在unity中的代码实现,
分为在txt中写入数据叫做序列化,和读取数据叫做反序列化,
首先我们需要LitJson.dll(文章最后github链接中含有本文测试所有游戏代码和LitJson.dll)
在类前面需要:
using UnityE
using System.C
using System.Collections.G
using LitJ
using System.IO;
#if UNITY_EDITOR
using UnityE
在.net中的解析方式,在unity中用最后一种
先看写入文件方法:
void WriteJsonToFile(string path, string fileName)
System.Text.StringBuilder strB = new System.Text.StringBuilder();
JsonWriter jsWrite = new JsonWriter(strB);
jsWrite.WriteObjectStart();
jsWrite.WritePropertyName(&Monster&);//Monster为对象数组名
jsWrite.WriteArrayStart();//对象数组
jsWrite.WriteObjectStart();
jsWrite.WritePropertyName(&MonsterName&);
jsWrite.Write(&Person&);
jsWrite.WritePropertyName(&attack&);
jsWrite.Write(10);
jsWrite.WritePropertyName(&defense&);
jsWrite.Write(10);
jsWrite.WritePropertyName(&weapon&);
jsWrite.Write(&Sword&);
jsWrite.WriteObjectEnd();
jsWrite.WriteObjectStart();
jsWrite.WritePropertyName(&MonsterName&);
jsWrite.Write(&Animal&);
jsWrite.WritePropertyName(&attack&);
jsWrite.Write(8);
jsWrite.WritePropertyName(&defense&);
jsWrite.Write(15);
jsWrite.WritePropertyName(&weapon&);
jsWrite.Write(&tooth&);
jsWrite.WriteObjectEnd();
jsWrite.WriteObjectStart();
jsWrite.WritePropertyName(&MonsterName&);
jsWrite.Write(&Dragon&);
jsWrite.WritePropertyName(&attack&);
jsWrite.Write(100);
jsWrite.WritePropertyName(&defense&);
jsWrite.Write(200);
jsWrite.WritePropertyName(&weapon&);
jsWrite.Write(&fire breath&);
jsWrite.WriteObjectEnd();
jsWrite.WriteArrayEnd();
jsWrite.WriteObjectEnd();
Debug.Log(strB);
//创建文件目录
DirectoryInfo dir = new DirectoryInfo(path);
if (dir.Exists)
Debug.Log(&This file is already exists&);
Directory.CreateDirectory(path);
Debug.Log(&CreateFile&);
#if UNITY_EDITOR
AssetDatabase.Refresh();
//把json数据写到txt里
if (File.Exists(fileName))
//如果文件存在,那么就向文件继续附加(为了下次写内容不会覆盖上次的内容)
sw = File.AppendText(fileName);
Debug.Log(&appendText&);
//如果文件不存在则创建文件
sw = File.CreateText(fileName);
Debug.Log(&createText&);
sw.WriteLine(strB);
sw.Close();
#if UNITY_EDITOR
AssetDatabase.Refresh();
然后是读出,读出方法我们放在Spawner类里
Monster ReadJsonFromTXT(string name)
//解析json
Monster monster = new Monster();
JsonData jd = JsonMapper.ToObject(txt.text);
print(jd.IsArray);
JsonData monsterData = jd[&Monster&];
print(monsterData.IsArray);
//打印一下数组
for (int i = 0; i & monsterData.C i++)
if (name == monsterData[i][&MonsterName&].ToString())
monster.MonsterName = monsterData[i][&MonsterName&].ToString();
monster.attack = int.Parse(monsterData[i][&attack&].ToString());
monster.defense = int.Parse(monsterData[i][&defense&].ToString());
monster.weapon = monsterData[i][&weapon&].ToString();
写好的JSON可以在这个网站中测试/,这是博主生成的JSON
JSON测试结果,成功生成Monster
基本的好处就是对象可以深复制自己,可以很方便有无差错的生成实体,并且把本来大量的类和与之对应的生成类(而且还会随着扩充增加!),缩小成一个原型类,一个生成类,一个数据文件,减少了大量重复的,甚至不重复的代码量!数据文件可以根据实际情况选择xml或者是JSON或者是别的。
进一步考虑,玩家们都喜欢丰富的游戏,像这样可以对数据进行微小的改动就会产生很多变化,代码量花费很少,还能产生丰富的游戏世界,何乐而不为?
测试用全部代码及dll文件已共享至
命令模式:
对象池模式:
博主近期渲染:
& & & & & & & & & & & & & & & ---- by wolf96 &
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:284216次
积分:5296
积分:5296
排名:第3577名
原创:176篇
转载:139篇
评论:151条
阅读:2044
阅读:5466
阅读:8548
文章:64篇
阅读:116657
(1)(1)(1)(4)(8)(5)(56)(18)(8)(13)(17)(26)(15)(7)(4)(11)(8)(17)(12)(6)(11)(14)(13)(19)(20)(9)}

我要回帖

更多关于 json格式存入数据库 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信