通用简单vs服务器

首先打开VS创建新项目

搜索ASP.NET Core Web API

自定义名称

默认 加取消两个勾选

安装数据库插件NuGet

右键项目名称 选择 管理NuGet程序包

点击浏览

搜索Microsoft.EntityFrameworkCore.Sqlite 选择安装

如果出现报错

说明不兼容更换8开头的版本

此时就看见已经再下载了

此时已经安装好了

接下来找到Program.cs脚本

双击点开

复制替换以下代码:

cs 复制代码
using Microsoft.EntityFrameworkCore;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
// 使用 SQLite 数据库,文件名为 game.db
builder.Services.AddDbContext<GameDb>(opt => opt.UseSqlite("Data Source=game.db"));
var app = builder.Build();

// 初始化:如果数据库文件不存在,自动创建
using (var scope = app.Services.CreateScope()) {
    scope.ServiceProvider.GetRequiredService<GameDb>().Database.EnsureCreated();
}

// --- 接口 1: 登录/注册 ---
app.MapPost("/auth", async (User user, GameDb db) => {
    var dbUser = await db.Users.FindAsync(user.Username);
    if (dbUser == null) {
        db.Users.Add(user); // 自动注册新账号
        await db.SaveChangesAsync();
        return Results.Ok(new { message = "Registered", score = 0 });
    }
    if (dbUser.Password == user.Password)
        return Results.Ok(new { message = "Logged in", score = dbUser.LastScore });
    return Results.Problem("Wrong password", statusCode: 401);
});

// --- 接口 2: 更新分数 ---
app.MapPost("/score", async (User data, GameDb db) => {
    var dbUser = await db.Users.FindAsync(data.Username);
    if (dbUser != null) {
        dbUser.LastScore = data.LastScore;
        await db.SaveChangesAsync();
        return Results.Ok();
    }
    return Results.NotFound();
});

// --- 接口 3: HTML 后台 ---
app.MapGet("/admin", async (GameDb db) => {
    var users = await db.Users.ToListAsync();
    var sb = new StringBuilder("<html><head><meta charset='utf-8'></head><body>");
    sb.Append("<h1>玩家积分后台</h1><table border='1'><tr><th>用户名</th><th>最后积分</th></tr>");
    foreach (var u in users) sb.Append($"<tr><td>{u.Username}</td><td>{u.LastScore}</td></tr>");
    sb.Append("</table></body></html>");
    return Results.Content(sb.ToString(), "text/html", Encoding.UTF8);
});

// 监听 6000 端口
app.Run("http://0.0.0.0:6000");

// --- 数据结构 ---
public class User {
    [System.ComponentModel.DataAnnotations.Key]
    public string Username { get; set; } = "";
    public string Password { get; set; } = "";
    public int LastScore { get; set; }
}
class GameDb : DbContext {
    public GameDb(DbContextOptions<GameDb> options) : base(options) { }
    public DbSet<User> Users => Set<User>();
}

点击运行就会弹出服务器运行界面

服务器搭建完成

接下来再Unity客户端中接入脚本

创建脚本NetworkManager.cs

cs 复制代码
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI; // 必须引用 UI 命名空间
using System.Collections;

public class NetworkManager : MonoBehaviour
{
    private string serverUrl = "http://localhost:6000";
    
    [Header("UI 引用")]
    public InputField usernameInput; // 拖入你的用户名输入框
    public InputField passwordInput; // 拖入你的密码输入框
    
    public string currentUsername;

    [System.Serializable]
    public class UserData { 
        public string Username; 
        public string Password; 
        public int LastScore; 
    }

    // --- 修改后的登录函数 (0个参数,现在能在列表里找到了) ---
    public void OnLoginButtonClick() {
        string user = usernameInput.text;
        string pass = passwordInput.text;
        currentUsername = user;
        StartCoroutine(Post("/auth", new UserData { Username = user, Password = pass }));
    }

    // 游戏结束时调用
    public void SaveScore(int score) {
        StartCoroutine(Post("/score", new UserData { Username = currentUsername, LastScore = score }));
    }

    IEnumerator Post(string path, UserData data) {
        string json = JsonUtility.ToJson(data);
        using (UnityWebRequest www = new UnityWebRequest(serverUrl + path, "POST")) {
            byte[] body = System.Text.Encoding.UTF8.GetBytes(json);
            www.uploadHandler = new UploadHandlerRaw(body);
            www.downloadHandler = new DownloadHandlerBuffer();
            www.SetRequestHeader("Content-Type", "application/json");
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success)
                Debug.Log("服务器返回: " + www.downloadHandler.text);
            else
                Debug.LogError("请求失败: " + www.error);
        }
    }
}

在场景中创建一个空物体命名为NetworkManager

挂载脚本

更新脚本NetworkManager.cs

cs 复制代码
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections;

public class NetworkManager : MonoBehaviour
{
    [Header("服务器配置")]
    public string serverUrl = "http://localhost:6000";
    public string gameSceneName = "GameScene"; // 登录成功后要跳转的场景名

    [Header("UI 组件引用")]
    public InputField usernameInput;
    public InputField passwordInput;

    [Header("当前玩家数据 (只读)")]
    public string currentUsername;
    public int lastBestScore;

    // 数据模型:发送给服务器
    [System.Serializable]
    public class UserData { 
        public string Username; 
        public string Password; 
        public int LastScore; 
    }

    // 数据模型:接收服务器返回
    [System.Serializable]
    public class AuthResponse {
        public string message;
        public int score;
    }

    private void Awake() {
        // 保证切换场景时,这个网络管理器不会被销毁
        DontDestroyOnLoad(gameObject);
    }

    // --- 给登录按钮点击使用的函数 ---
    public void OnLoginButtonClick() {
        if (usernameInput == null || passwordInput == null) {
            Debug.LogError("错误:请先在 Inspector 面板中拖入 InputField 物体!");
            return;
        }

        string user = usernameInput.text;
        string pass = passwordInput.text;

        if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(pass)) {
            Debug.LogWarning("用户名或密码不能为空");
            return;
        }

        currentUsername = user;
        StartCoroutine(PostRequest("/auth", new UserData { Username = user, Password = pass }));
    }

    // --- 给游戏逻辑调用的保存分数函数 ---
    public void SaveScore(int score) {
        if (string.IsNullOrEmpty(currentUsername)) {
            Debug.LogError("未登录,无法保存分数");
            return;
        }
        StartCoroutine(PostRequest("/score", new UserData { Username = currentUsername, LastScore = score }));
    }

    // --- 通用的 HTTP POST 协程 ---
    IEnumerator PostRequest(string path, UserData data) {
        string json = JsonUtility.ToJson(data);
        using (UnityWebRequest www = new UnityWebRequest(serverUrl + path, "POST")) {
            byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
            www.uploadHandler = new UploadHandlerRaw(bodyRaw);
            www.downloadHandler = new DownloadHandlerBuffer();
            www.SetRequestHeader("Content-Type", "application/json");

            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success) {
                string responseText = www.downloadHandler.text;
                Debug.Log("<color=green>服务器响应: </color>" + responseText);

                // 如果是登录请求,处理返回的数据并跳转
                if (path == "/auth") {
                    AuthResponse res = JsonUtility.FromJson<AuthResponse>(responseText);
                    lastBestScore = res.score;
                    Debug.Log($"登录/注册成功!玩家:{currentUsername},历史最高分:{lastBestScore}");
                    
                    // 跳转场景
                    SceneManager.LoadScene(gameSceneName);
                }
            } else {
                Debug.LogError("<color=red>网络请求失败: </color>" + www.error);
            }
        }
    }
}

拖拽用户名输入以及密码输入

修改服务器和客户端的端口为6001

因为通常6000有安全性问题会被拦截

再看一眼客户端开放的配置端口

现在进行测试

浏览器网址是:

先运行vs服务器

然后登录客户端 登录 如果是新入户登录即注册

注册成功进入游戏界面

打开后台网页

http://localhost:6001/admin

End.

相关推荐
m0_702036531 小时前
如何在MongoDB中实现按时间跨度的分片路由_时间序列范围分片与冷热节点架构.txt
jvm·数据库·python
2401_884454151 小时前
golang如何使用Fiber高性能框架_golang Fiber框架入门教程
jvm·数据库·python
ㄟ留恋さ寂寞1 小时前
Golang怎么读取和修改图片EXIF信息_Golang如何用goexif提取照片的拍摄时间和GPS位置【方法】
jvm·数据库·python
zhoutongsheng1 小时前
如何在 SvelteKit 中为动态加载的图片正确实现悬停显示覆盖层
jvm·数据库·python
IMPYLH1 小时前
Linux 的 truncate 命令
linux·运维·服务器·前端·bash
a7963lin1 小时前
Go语言怎么做分布式缓存_Go语言分布式缓存教程【经典】
jvm·数据库·python
zh1570231 小时前
golang如何生成和验证JWT Token_golang JWT Token生成验证步骤
jvm·数据库·python
_376271531 小时前
如何利用Bootstrap的Flex工具类快速排版
jvm·数据库·python
m0_740653221 小时前
Go 中通过指针实现变量名的“传入”与原地修改
jvm·数据库·python