簡體   English   中英

如何從Unity連接到數據庫

[英]How to connect to database from Unity

我正在嘗試通過 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 中,使用WWWUnityWebRequest類與該腳本通信,然后,您將能夠從 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協議。

另一種方法是在命令提示符中創建您自己的專用服務器來進行通信並將其連接到統一到 Handel 多人游戲和 SQL 通信。 通過這種方式,您可以堅持使用一種語言創建所有內容。 但是一個非常陡峭的學習曲線。

Unity 是游戲引擎。

所以答案就是這樣。

但是,有些域需要直接連接數據庫。

您不應該直接在游戲域中訪問數據庫。

無論如何,問題是由非英文計算機名稱引起的。

我在之前的項目中遇到了以下錯誤。

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)

將計算機名稱更改為 ENGLISH 后,它可以工作。

我不知道進展如何但它有效。

Mono 的 System.Data.dll 在 PC 中有一些問題具有非英文計算機名稱。

所以,至少是 Unity 項目。

您應該告訴您的客戶不要將他們的計算機名稱設置為非英語。

我不知道單聲道的人是否知道這些問題。

---------- 2018版以后就可以了 ----------

Api 兼容級別 > .Net 4.x

您可以在非英文計算機名稱機器上連接數據庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM