如何从Unity连接到数据库
本文关键字:数据库 连接 Unity | 更新日期: 2023-09-27 18:03:50
我试图通过Unity连接到MS SQL数据库。然而,当我尝试打开连接时,我得到一个IOException: connection lost.
我已经从Unity'Editor'Data'Mono'lib' Mono' 2.0中导入了System.Data.dll。我使用以下代码: using UnityEngine;
using System.Collections;
using System.Data.Sql;
using System.Data.SqlClient;
public class SQL_Controller : MonoBehaviour {
string conString = "Server=myaddress.com,port;" +
"Database=databasename;" +
"User ID=username;" +
"Password=password;";
public string GetStringFromSQL()
{
LoadConfig();
string result = "";
SqlConnection connection = new SqlConnection(conString);
connection.Open();
Debug.Log(connection.State);
SqlCommand Command = connection.CreateCommand();
Command.CommandText = "select * from Artykuly2";
SqlDataReader ThisReader = Command.ExecuteReader();
while (ThisReader.Read())
{
result = ThisReader.GetString(0);
}
ThisReader.Close();
connection.Close();
return result;
}
}
这是我得到的错误:
IOException: Connection lost
Mono.Data.Tds.Protocol.TdsComm.GetPhysicalPacketHeader ()
Mono.Data.Tds.Protocol.TdsComm.GetPhysicalPacket ()
Mono.Data.Tds.Protocol.TdsComm.GetByte ()
Mono.Data.Tds.Protocol.Tds.ProcessSubPacket ()
Mono.Data.Tds.Protocol.Tds.NextResult ()
Mono.Data.Tds.Protocol.Tds.SkipToEnd ()
Rethrow as TdsInternalException: Server closed the connection.
Mono.Data.Tds.Protocol.Tds.SkipToEnd ()
Mono.Data.Tds.Protocol.Tds70.Connect (Mono.Data.Tds.Protocol.TdsConnectionParameters connectionParameters)
Mono.Data.Tds.Protocol.Tds80.Connect (Mono.Data.Tds.Protocol.TdsConnectionParameters connectionParameters)
请忽略这种方法的任何安全风险,我需要这样做进行测试,安全稍后会到来。感谢您的宝贵时间。
请忽略此方法的任何安全风险
不要这样做。安全在此之前或之后到来并不重要。因为密码在应用程序中是硬编码的,可以很容易地反编译和检索,所以您将不必重写整个代码。现在以正确的方式进行连接,这样您就不必重写整个应用程序了。
在你的服务器上运行你的数据库命令,使用php, perl或任何你熟悉的语言,但这应该在服务器上完成。
从Unity中,使用WWW
或UnityWebRequest
类与该脚本进行通信,然后,您将能够从Unity发送和接收信息到服务器。这样的例子有很多。即使这样,您仍然需要实现自己的安全性,但这比您现在拥有的要好得多。
你也可以用json接收多个数据。
下面是来自Unity wiki的完整示例。它展示了如何在Unity中使用php在服务器端和Unity + c#在客户端与数据库进行交互。
服务器端:
添加PDO分数:
<?php
// Configuration
$hostname = 'localhot';
$username = 'yourusername';
$password = 'yourpassword';
$database = 'yourdatabase';
$secretKey = "mySecretKey"; // Change this value to match the value stored in the client javascript below
try {
$dbh = new PDO('mysql:host='. $hostname .';dbname='. $database, $username, $password);
} catch(PDOException $e) {
echo '<h1>An error has ocurred.</h1><pre>', $e->getMessage() ,'</pre>';
}
$realHash = md5($_GET['name'] . $_GET['score'] . $secretKey);
if($realHash == $hash) {
$sth = $dbh->prepare('INSERT INTO scores VALUES (null, :name, :score)');
try {
$sth->execute($_GET);
} catch(Exception $e) {
echo '<h1>An error has ocurred.</h1><pre>', $e->getMessage() ,'</pre>';
}
}
?>
使用PDO检索分数:
<?php
// Configuration
$hostname = 'localhost';
$username = 'yourusername';
$password = 'yourpassword';
$database = 'yourdatabase';
try {
$dbh = new PDO('mysql:host='. $hostname .';dbname='. $database, $username, $password);
} catch(PDOException $e) {
echo '<h1>An error has occurred.</h1><pre>', $e->getMessage() ,'</pre>';
}
$sth = $dbh->query('SELECT * FROM scores ORDER BY score DESC LIMIT 5');
$sth->setFetchMode(PDO::FETCH_ASSOC);
$result = $sth->fetchAll();
if(count($result) > 0) {
foreach($result as $r) {
echo $r['name'], "'t", $r['score'], "'n";
}
}
?>
在服务器上启用跨域策略:
这个文件应该命名为"crossdomain.xml",并放在你的web服务器的根目录下。Unity要求你想通过WWW请求访问的网站有一个跨域策略。
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
客户端/统一侧:
来自Unity的客户端代码连接到服务器,与PDO交互,并根据调用哪个函数添加或检索分数。这个客户端代码稍微修改了一下,以便与最新的Unity版本编译。
private string secretKey = "mySecretKey"; // Edit this value and make sure it's the same as the one stored on the server
public string addScoreURL = "http://localhost/unity_test/addscore.php?"; //be sure to add a ? to your url
public string highscoreURL = "http://localhost/unity_test/display.php";
//Text to display the result on
public Text statusText;
void Start()
{
StartCoroutine(GetScores());
}
// remember to use StartCoroutine when calling this function!
IEnumerator PostScores(string name, int score)
{
//This connects to a server side php script that will add the name and score to a MySQL DB.
// Supply it with a string representing the players name and the players score.
string hash = Md5Sum(name + score + secretKey);
string post_url = addScoreURL + "name=" + WWW.EscapeURL(name) + "&score=" + score + "&hash=" + hash;
// Post the URL to the site and create a download object to get the result.
WWW hs_post = new WWW(post_url);
yield return hs_post; // Wait until the download is done
if (hs_post.error != null)
{
print("There was an error posting the high score: " + hs_post.error);
}
}
// Get the scores from the MySQL DB to display in a GUIText.
// remember to use StartCoroutine when calling this function!
IEnumerator GetScores()
{
statusText.text = "Loading Scores";
WWW hs_get = new WWW(highscoreURL);
yield return hs_get;
if (hs_get.error != null)
{
print("There was an error getting the high score: " + hs_get.error);
}
else
{
statusText.text = hs_get.text; // this is a GUIText that will display the scores in game.
}
}
public string Md5Sum(string strToEncrypt)
{
System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
byte[] bytes = ue.GetBytes(strToEncrypt);
// encrypt bytes
System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);
// Convert the encrypted bytes back to a string (base 16)
string hashString = "";
for (int i = 0; i < hashBytes.Length; i++)
{
hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
}
return hashString.PadLeft(32, '0');
}
这只是一个如何正确地做到这一点的例子。如果您需要实现会话功能并关心安全性,请查看OAuth 2.0协议。应该有一些现有的库可以帮助您开始使用OAuth协议。
另一种选择是在命令提示符中创建自己的专用服务器来进行通信,并将其连接到unity到Handel多人模式和SQL通信。通过这种方式,您可以坚持使用一种语言创建所有内容。但是学习曲线非常陡峭
Unity是游戏引擎
所以答案是正确的。
但是,有些域需要直接连接数据库。
你不应该在game域中直接访问数据库
无论如何,问题是由非英文计算机名引起的。
我在之前的项目中遇到了以下错误。
IOException: Connection lost
Mono.Data.Tds.Protocol.TdsComm.GetPhysicalPacketHeader ()
Mono.Data.Tds.Protocol.TdsComm.GetPhysicalPacket ()
Mono.Data.Tds.Protocol.TdsComm.GetByte ()
Mono.Data.Tds.Protocol.Tds.ProcessSubPacket ()
Mono.Data.Tds.Protocol.Tds.NextResult ()
Mono.Data.Tds.Protocol.Tds.SkipToEnd ()
Rethrow as TdsInternalException: Server closed the connection.
Mono.Data.Tds.Protocol.Tds.SkipToEnd ()
Mono.Data.Tds.Protocol.Tds70.Connect (Mono.Data.Tds.Protocol.TdsConnectionParameters connectionParameters)
Mono.Data.Tds.Protocol.Tds80.Connect (Mono.Data.Tds.Protocol.TdsConnectionParameters connectionParameters)
将计算机名称改为英文后,它可以工作。
我不知道是怎么回事。Mono的System.Data.dll在pc有非英语计算机名时有一些问题。
所以,至少Unity项目。
你应该告诉你的客户不要将他们的计算机名称设置为非英语。
我不知道mono的人是否知道这些问题。
---------- 在以后的2018年版本,没关系 ----------
Api兼容性级别> .Net 4.x
可以在非英文计算机名机中连接数据库