一.MySql

1.启动mysql

fef10df3c28c4fd8b5935996fb976b34.png

2.登陆自己的mysql

bcb10876795042daadc01f426e062a8a.png3.创建表

5ccb34bfd13c4c7aabf3d49cc215876c.png

二.Node.js

 1.打开node.js

cc7e4322e9d441dbbaa9ecebc713cf81.png

2.在命令行(终端)执行以下步骤:

d3267dcf2b054435b950461de5046e0c.png

 安装依赖包

运行以下命令来安装后端所需的依赖包:

npm install express body-parser mysql2 bcrypt jsonwebtoken cors

  • express:一个轻量级的 Web 框架,用于创建 API。
  • body-parser:解析请求体数据。
  • mysql2:用于连接和操作 MySQL 数据库。
  • bcrypt:用于加密和验证用户密码。
  • jsonwebtoken:用于生成和验证用户身份的 JWT。
  • cors:解决跨域问题(Unity 客户端需要用到)。

由于 bcrypt 编译需要较多环境配置,可以使用更轻量化的模块,如 bcryptjs,它是纯 JavaScript 实现,不需要编译。

edae21b8c9094767a28c5d897875c35f.png

3.编写index.js

我这里用的是vscode

db4e164b6319416d81f908421d663aef.png

下面是index.js的代码,需要替换

// 引入 Express 框架,用于创建和管理 Web 服务器
const express = require("express");

// 引入 body-parser 中间件,用于解析请求体数据
const bodyParser = require("body-parser");

// 引入 mysql2/promise 模块,用于连接和操作 MySQL 数据库,支持 Promise
const mysql = require("mysql2/promise"); 

// 引入 bcryptjs 模块,用于对密码进行加密和校验
const bcrypt = require("bcryptjs");

// 引入 cors 模块,用于处理跨域请求
const cors = require("cors");

// 创建 Express 应用实例
const app = express();

// 定义服务器监听的端口号
const port = 3000;


// 使用中间件
app.use(cors());

app.use(bodyParser.json());

// 数据库连接配置
const dbConfig = {
    host: "localhost",
    user: "自己的用户名",
    password: "自己的密码",
    database: "自己创建的数据库的名",
};

let db;

// 初始化数据库连接
async function initializeDbConnection() {
    try {
        db = await mysql.createConnection(dbConfig);
        console.log("已成功连接到数据库");
    } catch (err) {
        console.error("数据库连接失败:", err);
        process.exit(1); // 如果连接失败,退出程序
    }
}

// 注册接口
app.post("/register", async (req, res) => {
    const { username, password } = req.body;

    // 验证用户名和密码是否为空
    if (!username || !password) {
        return res.status(400).json({ error: "用户名和密码不能为空" });
    }

    try {
        // 检查用户名是否已存在
        const [rows] = await db.query("SELECT * FROM users WHERE username = ?", [username]);
        if (rows.length > 0) {
            return res.status(400).json({ error: "用户名已被注册" });
        }

        // 加密密码
        const hashedPassword = await bcrypt.hash(password, 10);

        // 插入用户数据
        await db.query("INSERT INTO users (username, password_hash) VALUES (?, ?)", [username, hashedPassword]);

        res.status(201).json({ message: "注册成功" });
    } catch (error) {
        console.error("注册错误:", error);
        res.status(500).json({ error: "服务器内部错误" });
    }
});

// 登录接口
app.post("/login", async (req, res) => {
    const { username, password } = req.body;

    // 验证用户名和密码是否为空
    if (!username || !password) {
        return res.status(400).json({ error: "用户名和密码不能为空" });
    }

    try {
        // 检查用户名是否存在
        const [rows] = await db.query("SELECT * FROM users WHERE username = ?", [username]);
        if (rows.length === 0) {
            return res.status(400).json({ error: "用户名或密码错误" });
        }

        const user = rows[0];

        // 比较密码
        const isMatch = await bcrypt.compare(password, user.password_hash);
        if (!isMatch) {
            return res.status(400).json({ error: "用户名或密码错误" });
        }

        res.status(200).json({ message: "登录成功" });
    } catch (error) {
        console.error("登录错误:", error);
        res.status(500).json({ error: "服务器内部错误" });
    }
});

// 启动服务器
(async () => {
    await initializeDbConnection(); // 初始化数据库连接
    app.listen(port, () => {
        console.log(`服务器正在运行,地址:http://localhost:${port}`);
    });
})();

然后在根目录的终端输入node index.js

就会看到成功连接

9829a376981146ec93dadad8b1d0404a.png

三.Postman

f26b037832364871869fefa44cc300ed.png

5aa29c6fe3c94feb914b510a53cc5e42.png

7887184a8f3f484ebdc451f58267bd84.png(昨天还有成功显示。。。)

四.Unity

8194a2fc619b49a7b41630c95897a17c.png

写loginManager的脚本(在文章最后)

7f076fa027c94fc690f6d6f7bb637f4e.png

输入后成功显示注册成功,然后跳转场景

然后我们在数据库查询一下,果然保留了记录,还有创建时间

af24f940bd374636b9cdf418160e21b1.png

然后因为我昨天注册就是这个名字,所以可以看到控制台显示我今天注册失败,说明昨天保留到数据库了

590b8b0d38a74d6cb6338fcea8b113c1.png

然后今天换了一个用户名

d320746db624431ebba1d8079b810b00.png

可以看到console面板显示注册成功

注册成功后点登陆就能看到下一关场景了

952673f437e244659ef72d40bb4bc16c.png

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class LoginManager : MonoBehaviour
{
    public InputField nameInput; // 用户名输入框
    public InputField passwordInput; // 密码输入框
    public GameObject registerSuccessMessage; // 注册成功提示
    public GameObject loginErrorMessage; // 登录失败提示

    private string registerUrl = "http://localhost:3000/register"; // 注册 API 地址
    private string loginUrl = "http://localhost:3000/login"; // 登录 API 地址

    // 注册功能
    public void Register()
    {
        string username = nameInput.text.Trim(); // 去除多余空格
        string password = passwordInput.text.Trim();

        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
        {
            Debug.LogError("用户名或密码不能为空!");
            StartCoroutine(ShowMessage(loginErrorMessage)); // 显示错误提示
            return;
        }

        // 调用协程进行注册
        StartCoroutine(RegisterUser(username, password));
    }

    private IEnumerator RegisterUser(string username, string password)
    {
        // 创建 JSON 数据
        string jsonData = $"{{\"username\":\"{username}\",\"password\":\"{password}\"}}";

        // 创建请求
        UnityWebRequest request = new UnityWebRequest(registerUrl, "POST");
        byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonData);
        request.uploadHandler = new UploadHandlerRaw(bodyRaw);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        Debug.Log($"发送注册请求到: {registerUrl}");
        yield return request.SendWebRequest();

        if (request.result == UnityWebRequest.Result.Success)
        {
            Debug.Log($"注册成功: {request.downloadHandler.text}");
            StartCoroutine(ShowMessage(registerSuccessMessage)); // 显示注册成功提示
        }
        else
        {
            Debug.LogError($"注册失败: {request.error}\n响应: {request.downloadHandler.text}");
            StartCoroutine(ShowMessage(loginErrorMessage)); // 显示错误提示
        }
    }

    // 登录功能
    public void Login()
    {
        string username = nameInput.text.Trim(); // 去除多余空格
        string password = passwordInput.text.Trim();

        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
        {
            Debug.LogError("用户名或密码不能为空!");
            StartCoroutine(ShowMessage(loginErrorMessage)); // 显示错误提示
            return;
        }

        // 调用协程进行登录
        StartCoroutine(LoginUser(username, password));
    }

    private IEnumerator LoginUser(string username, string password)
    {
        // 创建 JSON 数据
        string jsonData = $"{{\"username\":\"{username}\",\"password\":\"{password}\"}}";

        // 创建请求
        UnityWebRequest request = new UnityWebRequest(loginUrl, "POST");
        byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonData);
        request.uploadHandler = new UploadHandlerRaw(bodyRaw);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        Debug.Log($"发送登录请求到: {loginUrl}");
        yield return request.SendWebRequest();

        if (request.result == UnityWebRequest.Result.Success)
        {
            Debug.Log($"登录成功: {request.downloadHandler.text}");
            SceneManager.LoadScene("GameScene1"); // 跳转到下一个场景
        }
        else
        {
            Debug.LogError($"登录失败: {request.error}\n响应: {request.downloadHandler.text}");
            StartCoroutine(ShowMessage(loginErrorMessage)); // 显示登录失败提示
        }
    }

    // 显示提示信息
    private IEnumerator ShowMessage(GameObject messageObject)
    {
        messageObject.SetActive(true);
        yield return new WaitForSeconds(2f);
        messageObject.SetActive(false);
    }
}

 

 

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐