Unity5权威讲解第十四章第十节内容 【在Unity中连接数据库】

论坛 期权论坛 脚本     
匿名技术用户   2021-1-2 05:09   247   0

14.10 在Unity中连接数据库

应用程序收发数据通常有很多中方法,但其中最快、最常用的方法是连接数据库。虽然此处使用了“直接连接”这个说法,但实际上需要ODBC(Open Database connectivity,开放数据库互联)或者JDBC等中间件才能连接数据库。

如前所述,在Unity中也可以通过ODBC连接数据库,但实际开发中会根据平台不同而有所区别。如图14-116所示,也可通过Web服务器的服务器脚本(Server Side Script)连接到数据库并收发数据。各位熟知的PHP、ASP、JSP等都是服务器端脚本,实际开发中可用JSON、XML、CSV等格式收发数据。

14.10.1 JSON

JSON(JavaScript Object Notation)是收发数据的一种格式,主要用于轻量级数据。其结构虽然借鉴了Java的语法,但它独立于计算机编程语言或平台。另外,大部分服务器端脚本都支持解析或构建JSON格式的消息体。

JSON支持的数据类型有整数、字符串、布尔型、数组等。

下列示例就是保存游戏玩家信息的JSON消息体。

JSON格式消息以大括号({})表示开始和结束,然后在大括号内写入要识别的键名和键值。

其中的键值可根据JSON支持的数据类型决定。

JSON中,数组的开始和结束均有中括号([])表示。上述示例中,“拥有技能”键保存的键值为数组,包含"掩蔽","透明模式","穿甲弹"这3个字符串类型的值。

JSON支持嵌套子JSON结构体。

{

"姓名":"狙击手",

"性别":"男",

"职业":"狙击手",

"能力值":{

"等级":37,

"生命力":480,

"活力":270,

"法力":1200

},

"拥有技能":["掩蔽","透明模式","穿甲弹"],

"分数":2750000,

}

提示:关于JSON的详细内容请参考下列网址http://www.json.org/json-zh.html

14.10.2 SimpleJSON

如果想在Unity中使用JSON,需要可以分拆和构建JSON消息的JSON解析器。Unity中可以使用的JSON解析器有SimpleJSON、LitJSON、JSONObject、JsonFX等,本书使用的是SimpleJSON解析器。

SimpleJSON的使用方法较为简单,不需要复杂的C#高级语法。可在下列网站下载SimpleJOSN。

http://wiki.unity3d.com/index.php/SimpleJSON

下载的SimpleJSON.zip文件包括JSON Test文件夹、plugins文件、SimpleJSON.unitypackkage文件夹,只需plugins文件夹中的SimpleJSON.cs文件导入项目视图的Plugins文件夹即可。

制作新的场景并简单测试JSON。先将本节开头的JOSN示例重命名为user_info.json并保存,放入项目视图的Resources文件夹。

{

"姓名":"狙击手",

"性别":"男",

"职业":"狙击手",

"能力值":

{

"等级":37

,"生命力":480

,"活力":270

,"法力":1200

},

"拥有技能":["掩蔽","透明模式","穿甲弹"],

"分数":2750000,

}

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using SimpleJSON;

public class LoadUserInfo : MonoBehaviour

{

public TextAsset jsonData = null;

public string strJsonData = null;

// Use this for initialization

void Start()

{

//加载Resources文件夹中的JSON文件

jsonData = Resources.Load<TextAsset>("user_info");

//将Json文件转化为字符串类型的文件

strJsonData = jsonData.text;

// Debug.Log(strJsonData);

//解析JSON文件

var N = JSON.Parse(strJsonData);

//获取key为姓名的键值

string user_name = N["姓名"].ToString();

//从能力值中获取key为等级的键值

int level = N["能力值"]["等级"].AsInt;

Debug.Log(user_name);

Debug.Log(level.ToString());

for (int i = 0; i < N["拥有技能"].Count; i++)

{

Debug.Log(N["拥有技能"][i].ToString());

}

}

将脚本添加到场景后执行,控制台视图中会出现如图14-118所示的日志信息。

14-118 解析JSON文件的结果

14.10.3 将分数信息保存到数据库

本节将之前坦克爆炸时的累积的分数保存到数据库,然后将其封装为JSON格式的文件并显示到画面。为了便于测试数据保存的内容,各位可以使用我的服务器以使用MySQL数据库。我为每个测试数据库都分配了一个序列号,这样可以避免各自的数据相互干扰。复制并打开下列网址,输入简单的信息再点击“生成账号”按钮,就会得到一个序列号。请复制此序列号。

http://www.unity3d.com/Tankwar/UserRegister.html

14-119 为了使用我的MySQL数据库而分配序列号

注意

考虑到运营服务器的成本,我会定期初始化保存的数据,所以此数据库只用于学习。另外,如果数据保存及查询时产生过多的流量,则测试账号的页面会暂时终止。

如脚本14-45所示编写脚本,将其命名为DataMgr,用于数据库中保存和查询数据。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class DataMgr : MonoBehaviour

{

public static DataMgr instance = null;

//为了使用MySQL数据库而分配的序列号

private const string seqNo = "3201411232";

//保存分数的PHP地址

private string urlSave = "http://www.Unity3dStudy.com/Tankwar/save_score.php";

void Awkae()

{

instance = this;

}

public IEnumerator SaveScore(string user_name, int killCount)

{

WWWForm form = new WWWForm();

//设置要传递的参数

form.AddField("user_name", user_name);

form.AddField("kill_count", killCount);

form.AddField("seq_no", seqNo);

//调用URL

var www = new WWW(urlSave, form);

//等待完成

yield return www;

if (string.IsNullOrEmpty(www.error))

{

Debug.Log(www.text);

}

else

{

Debug.Log("Error" + www.error);

}

}

}

使用seqNo变量保存从图14-119额页面中获取的序列号,避免与其他读者的数据弄混。

//为了使用MySQL数据库而分配的序列号

private const string seqNo = "3201411232";

使用save_score.php将分数保存到数据库,php页面的源码如脚本14-46所示

<?php

//连接数据库

$connect = mysql_connect("localhost","用户名","密码");

//查看是否连接成功

if($connect==0)

{

?>SORRY SOCRE SERVER CONNECTION ERROR<?

}else

{

}

//设置要使用的数据库

mysql_select_db("数据库名称",$connect);

//以POST方式传递的参数保存到变量

$user_name = $_POST["user_name"];

$kill_count = $_POST["kill_count"];

$seq_no = $_POST["seq_no"];

//生成SQL查询语句

$sql = "INSERT INTO tb_score(user_name,kill_count,seq_no)";

$sql.="\n values("'.$user_name.'",".$kill_count.",".$seq_no.")";

$sql.="\n ON DUPLICATE KEY UPDATE kill_count = kill_count +1";

//执行SQL查询语句

$result = mysql_query($sql,$connect);

//返回查询语句的执行结果

if($result)

{

echo("YOUR SCORE SAVED.");

}else

{

echo("eroor");

}

//断开与数据库的连接

mysql_close($connect);

?>

DataMgr脚本制作完成后,将其添加到场景中的GameManager游戏对象。

如脚本14-47所示,将DataMgr脚本中定义的“向数据库保存数据”的函数添加到TankDamage脚本的IncKillCount函数。

void InKillCount()

{

++killCount;

if (texttKillCount != null)

texttKillCount.text = killCount.ToString();

Debug.Log(killCount);

if(DataMgr.instance!=null)

StartCoroutine(DataMgr.instance.SaveScore(gameObject.name, 1));

}

// Update is called once per frame

void Update () {

if (Input.GetKeyDown(KeyCode.I))

InKillCount();

}

重新构建2个游戏可执行文件并运行,在不同游戏窗口中互相攻击,可以在控制台视图中看到诸如YOUR SCORE SAVED.的日志和执行的SQL查询语句,说明数据已经正常保存到数据库(此处使用键盘的I键为分数增加的模拟操作)。

14.10.4 从数据库获取排名信息

下面从数据获取保存的排名信息。从数据中查询数据,构建为JSON格式的消息并返回,然后在Unity中解析JSON消息以获取数据。我制作的PHP脚本源码如脚14-48所示。

<?php

//连接数据库

$connect = mysql_connect("localhost","用户名","密码");

//查看是否连接成功

if($connect==0)

{

?>SORRY SOCRE SERVER CONNECTION ERROR<?

}else

{

}

//设置要使用的数据库

mysql_select_db("数据库名称",$connect);

//以POST方式传递的参数保存到变量

$seq_no = $_POST["seq_no"];

//生成SQL查询语句

$sql = "SELECT ";

$sql.="\n @rownum:=@rownum+1 as ranking";

$sql.="\n ,A.user_name as user_name";

$sql.="\n ,A.kill_count as kill_count";

$sql.="\n FROM tb_score as A, (SELECT @rownum := 0) R ";

$sql.="\n where A.seq_no ='".$seq_no."'";

$sql.="\n ODDER BY kill_count DESC";

//执行SQL查询语句

$result = mysql_query($sql,$connect);

//保存JSON的数组

$rows = array();

$return = array();

//从开始到最终记录始终输出查询结果值

while($row = mysql_fetch_arrya($result))

{

$rows["ranking"] = $row["ranking"];//获取排名

$rows["user_name"] = $row["user_name"];//获取用户名

$rows["kill_count"] = $row["kill_count"];//获取分数

//向数组添加记录值以生成JSON数据

array_push($return ,$rows);

}

header("Content-type:application/json");

//生成JSON文件

echo json_encode($return);

//断开与数据库的连接

mysql_close($connect);

?>

向DataMgr脚本添加入脚本14-49所示代码,解析JSON格式的消息并获取、显示排名信息数据。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using SimpleJSON;

public class DataMgr : MonoBehaviour

{

public static DataMgr instance = null;

//为了使用MySQL数据库而分配的序列号

private const string seqNo = "3201411232";

//保存分数的PHP地址

private string urlSave = "http://www.Unity3dStudy.com/Tankwar/save_score.php";

//可以获取排名信息的PHP地址

private string urlScoreList = "http://www.Unity3dStudy.com/Tankwar/get_score_list.php";

void Awake()

{

instance = this;

}

public IEnumerator SaveScore(string user_name, int killCount)

{

WWWForm form = new WWWForm();

//设置要传递的参数

form.AddField("user_name", user_name);

form.AddField("kill_count", killCount);

form.AddField("seq_no", seqNo);

//调用URL

var www = new WWW(urlSave, form);

//等待完成

yield return www;

if (string.IsNullOrEmpty(www.error))

{

Debug.Log(www.text);

}

else

{

Debug.Log("Error" + www.error);

}

StartCoroutine(this.GetScoreList());

}

public IEnumerator GetScoreList()

{

WWWForm form = new WWWForm();

//设置要传递的参数

form.AddField("seq_no", seqNo);

//调用URL

var www = new WWW(urlScoreList, form);

//等待完成

yield return www;

if (string.IsNullOrEmpty(www.error))

{

Debug.Log(www.text);

//调用显示分数的函数

DispScoreList(www.text);

}

else

{

Debug.Log("Error" + www.error);

}

}

//解析JSON文件并显示分数的函数

void DispScoreList(string strJsonData)

{

//解析JSON文件

var N = JSON.Parse(strJsonData);

//根据JSON对象数组大小循环

for (int i = 0; i < N.Count; i++)

{

int ranking = N[i]["ranking"].AsInt;

string userName = N[i]["user_name"].ToString();

int killCount = N[i]["kill_count"].AsInt;

//将结果值显示到控制台视图

Debug.Log(ranking.ToString() + userName + killCount.ToString());

}

}

}

本示例中,排名信息以JSON格式传递,脚本需要使用SimpleJSON,所以在DataMgr脚本的开始部分添加了using SimpleJSON以声明相应的命名空间。

将分数保存到数据库后,脚本访问了get_score_list.php以获取排名信息。Get_score_list.php中生成的JSON格式的消息如下所示。

[

{"ranking":"1","user_name":"Zack","kill_count":"17"},

{"ranking":"2","user_name":"Penzer",kill_count":"9"}

]

运行游戏,操作坦克互相攻击,可在控制台视图中看到从数据库获取的结果值,如图所示。

本博文参考:Unity5权威讲解,【韩】李在贤 著 孔雪玲 译,ISBN 978-7-115-43636-8

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP