游戏开发指南:使用 UOS C# 云函数快速构建与部署服务端逻辑实战教学

news2024/11/26 18:25:20

零基础的服务端小白,现在也可以使用 Unity 结合 C# 来轻松搞定游戏服务端啦!

在本篇文章中,我们将以游戏中的“抽卡”功能为例,展示如何使用 Unity Online Services(UOS)提供的强大 C# 云函数服务,引导你在 Unity 开发环境中快速实现和部署联网游戏中的服务端逻辑。

不管你是萌新还是技术大佬,在这里你都将有所收获。

我们准备了一个抽卡模拟器作示例,供大家来体验 Func 功能的同时尽享抽卡的乐趣!大家可以进入下方的 UOS 官网链接,进行在线体验哦!

https://uos.unity.cn/product/func

本教程中涉及 UOS 服务包括:

  • 云函数服务 Func Stateless (C#):用于部署抽卡服务端逻辑代码

  • 云数据库服务 CRUD Storage:用于存储玩家信息、抽卡记录等数据

云函数服务 Func Stateless

在保障游戏或应用安全性的重要考量下,确保关键逻辑和数据的权威性处理仅在服务器端执行显得尤为重要。这是因为客户端的代码包体容易被破解或篡改,从而引发不公平竞争、数据泄露等安全问题。为此,采用云函数作为服务端逻辑的实现方式,相比传统服务器部署模式,不仅增强了安全性,还带来了显著的成本效益。

UOS Func Stateless (C#) 云函数服务,不仅继承了云函数的所有优势,如弹性扩展、按需付费等,还针对游戏开发者的需求进行了深度优化。

采用 UOS Func Stateless (C#) 云函数相较于传统逻辑服务器的主要优势:

1. 前后端同步开发:得益于云函数的灵活性和独立性,开发者可以并行进行前端 UI 与后端逻辑的开发,无需等待服务器端的完整部署,大大提升了开发效率。

2. 本地调试便捷:UOS Func Stateless 支持在本地开发环境中直接调试云函数,无需部署到云端即可验证逻辑的正确性,降低了调试难度,加快了开发迭代速度。

3. 自动化服务端逻辑抽取与部署:通过集成开发环境(IDE)或命令行工具,UOS Func Stateless 能够自动将服务端逻辑代码打包并部署到云端,简化了部署流程,减少了人为错误,让开发者更专注于业务逻辑的实现。

4. 与数据库服务深度集成:UOS Func Stateless (C#) 云函数与 CRUD Storage 数据库服务无缝对接,支持直接在函数内部进行数据库操作,如增删改查(CRUD),实现了数据逻辑与存储逻辑的高度集成,简化了数据处理的复杂度,提升了整体性能。

综上所述,UOS Func Stateless (C#) 云函数以其高效、灵活、安全且成本低的特点,为游戏开发者提供了一个理想的服务端逻辑解决方案,助力他们在快速迭代的市场环境中保持竞争优势。

云数据库服务 CRUD Storage

接着,我们再来看一下云数据库服务 CRUD Storage,都支持哪些数据库呢?

CRUD Storage 提供了完善的关系型数据库,文档型数据库,KV数据库等,以最简便易用的方式进行封装,可大幅减少您的运维工作量,更专注于业务开发。目前支持的数据库类型包含 MySQL,PostgreSQL,MongoDB,Redis。

教程视频

[UOS教程]-用C#云函数快速构建与部署服务端逻辑实战指南

https://www.bilibili.com/video/BV18E4m1Q7vb/?spm_id_from=333.788

教程学习大纲

  1. 在 UOS 官网下载示例项目工程

  2. 创建 UOS App 并启用 Func Stateless 服务

  3. 启用 CRUD Storage 数据库服务,并配置 Mongo 数据库

  4. 设置云函数的安装和配置目录,并安装第三方库

  5. 在本地模式下调试并运行项目

  6. 上传和部署云函数,切换到远程调用模式下测试云函数的调用

  7. 在 UOS 中连接并查看 CRUD Storage 数据库的存储信息

  8. 自定义创建一个新的云函数,并实现将数据存储在 CRUD Storage 数据库

教程案例工程源文件

教程内学习用到的项目工程文件可以通过以下两种方式进行下载:

代码仓库的地址:

https://unitychina.coding.net/public/uos/FuncStatelessCSharpDemo/git/files

UOS 官网示例教程中在线下载:

https://uos.unity.cn/doc/func/stateless/csharp-tutorial

教程操作步骤

接下来让我们来看看 Func Stateless 云函数结合 CRUD Storage 数据库在项目中的具体用法吧。

1. 在UOS官网下载示例项目工程

1.1 下载项目工程文件

可以选择上面提到的两种方式之一进行下载教程使用的项目工程。这里给大家演示下从 UOS 官网下载项目的过程。

首先前往上方提供的官网的教程链接地址,在「FUNC」的文档左侧页面选择「Stateless」下方的「示例教程(C#)」,在「准备工作」模块点击按钮「DEMO UNITY 工程」,就可以下载抽卡 Demo 的项目工程了。

1.2 解压缩项目工程文件

在下载完项目工程压缩包以后,请解压缩下图中的项目工程文件。

1.3 加载项目工程

然后打开 Unity Hub,选择电脑上已经安装过的 Unity 编辑器版本,来打开刚刚下载好的项目工程。

2. 创建 UOS App 并开启 Func Stateless 服务

温馨提示:当前项目中已安装好 UOS Launcher 和 Func Stateless SDK ,不需要再次安装了。如果是开发者自己新创建的项目工程,还没有安装过的话,可以通过下面的步骤进行安装。

2.1 安装 UOS Launcher

在 Unity Editor 菜单栏中打开「Window -> Package Manager」,点击左上角的「+」,选择「Add package from git URL」;

然后输入UOS Launcher 的 git 地址,点击「Add」等待安装完成;

https://e.coding.net/unitychina/uos/UOSLauncher.git

注意:该步骤要求当前环境已安装 git,且 UOS Launcher 兼容的最低 Unity 版为 2021.3(LTS)。

2.2 创建 UOS App ,并绑定创建的 Unity 项目工程

接着再次前往 UOS 官网 (https://uos.unity.cn),创建一个 UOS 应用。选择一个创建好的组织,输入项目的名字,点击「创建并启用」。

在设置页面找到 UOS App 的信息并复制,供后面使用。

然后回到 Unity 编辑器中,点击菜单栏「UOS -> Open Launcher」。在 UOS 面板中填写 AppID/AppSecret/AppServiceSecret,并点击「Link App」与 UOS APP 进行关联。

2.3 开启 Func - Stateless 服务,并安装 Func Stateless SDK

开启 Func - Stateless 服务

在编辑器内 Unity Online Services 窗口的下拉服务列表中,找到 Func - Stateless,点击 Enable 按钮来开启服务。如果想使用 JavaScript 进行云函数开发的话,也可以去网页端启用 JavaScript 版的云函数服务。

安装 Func Stateless SDK

在下方截图的位置,点击「Install SDK」的按钮 ,就可以将 Func - Stateless 服务 SDK 安装到当前项目中。

如果项目中已经安装过 Func-Stateless SDK 的话,是可以在 Package Manager 页面中看到的。

3. 启用 CRUD Storage 数据库服务,并配置 Mongo 数据库

开启 CRUD Storage 服务

在创建的应用的页面左侧再次找到「概览」页面,然后在服务列表中找到「CRUD Storage」 服务,点击「免费试用」的按钮。

创建 Mongo 数据库

在创建进入「CRUD Storage -> 数据库管理」页面,点击「创建数据库」。

在创建数据库的页面,填写实例名称(仅支持数字、字母和下划线的组合,不能为空),依次选择“所在地域”、“数据库类型”、“数据库实例”、“数据库版本”、输入或者拖动选择数据库磁盘大小、 按要求填写用户名和密码,并点击「创建」。

等待几十秒之后,就可以看到数据库分配成功并处于运行状态中了。

4. 配置项目工程

在项目的 Project 窗口中,找到「Assets/Scenes/Demo.unity」场景并打开。

点击 「Import TMP Essentials」按钮,导入 TextMeshPro 的字体资源。

5. 设置云函数的安装和配置目录,并安装第三方库

当前的示例项目使用了 UOS 专门为开发者准备的,方便联合使用 Func - Stateless 与 CRUD Storage 的库,目前可以通过以下方式引入到项目当中。

导入 NuGetForUnity 工具

在 Unity Editor 菜单栏中点击 「UOS -> Func Stateless -> Import NuGetForUnity」,来导入 UOS 版本的 NuGetForUnity 工具。

修改云函数的安装和配置目录

导入完成后,点击菜单栏中「NuGet -> Preferencs」打开配置界面。修改Packages Install Path 为云函数所在目录下的 Packages 目录;Packages Config Path 为云函数所在目录。

安装库 UOS.FuncStateless.MongoDB

修改完成配置后,点击「NuGet -> Manager NuGet Packges」打开界面。在输入框中输入需要安装的库的名称(例如,UOS.FuncStateless.MongoDB),点击「Search」搜索,然后点击 「Install」 下载安装所需要的库。

Install 安装完成之后,在 Installed 页面可以看到已安装好的库。

6. 在本地模式下调试并运行项目

接下来大家就直接在 Unity 编辑中点击运行项目吧!在本地调试模式下访问的是数据库的公网地址,并且当前工程项目在和 UOS App 进行绑定的时候,数据库的信息就已经自动关联上了。

运行后游戏的演示效果:

代码分析

接下来打开云函数所在的类的脚本,在 LoginService 脚本的构造函数的初始化中,可以获取到数据库连接的登录的相关信息。

[CloudService]
public class LoginService
{
    private readonly IMongoCollection<User> _collection;

    public LoginService()
    {
        Debug.Log("init login service");
        var conn = Task.Run(async () => await MongoConnectionManager.GetConnection()).Result;
        var database = conn.GetDatabase(MongoConfig.DBName);
        _collection = database.GetCollection<User>(MongoConfig.CollectionName);
    }
}

在 ActionService 脚本的构造函数的初始化中,可获取到数据库连接的抽卡的相关信息。

 [CloudService]
 public class ActionService
 {
     private readonly IMongoCollection<User> _collection;

     public ActionService()
     {
         Debug.Log("init action service");
         var conn = Task.Run(async () => await MongoConnectionManager.GetConnection()).Result;
         var database = conn.GetDatabase(MongoConfig.DBName);
         _collection = database.GetCollection<User>(MongoConfig.CollectionName);
     }
 }

 

在 MongoConfig 脚本中可看到配置的 Mongo 数据库的参数。

namespace CloudService
{
    public static class MongoConfig
    {
        public const string DBName = "stateless-demo";
        public const string CollectionName = "users";
    }
}

7. 上传项目工程中已经创建的云函数

当您验证完成您的代码逻辑或您需要打包的项目时,请先切换成远程模式,上传云函数后再进行验证远程调用。

7.1 上传云函数

通过点击菜单栏 「UOS -> Func Stateless -> Open Panel」按钮, 打开「Func Stateless Tool」窗口。

在打开的工具的窗口中,可以看到当前项目中的云函数。

下面我们来看看 ActionService.cs 脚本中的抽卡云函数(Draw)的代码吧,代码中实现了从卡池中抽取卡,并返回抽取的结果。

[CloudFunc]
public async Task<DrawResult> Draw(string id, int count)
{
    Debug.Log("call to draw");
    var filter = Builders<User>.Filter.Eq("_id", id);
    var user = await _collection.Find(filter).FirstOrDefaultAsync();
    if (user == null)
    {
        return new DrawResult
        {
            Ok = false,
            Message = "user not found"
        };
    }
    if (count > user.Diamonds)
    {
        return new DrawResult
        {
            Ok = false,
            Message = "钻石不够抽卡",
        };
    }
    // start to draw
    var res = new List<Item>(count);
    var pool = user.DrawPool;
    if (pool == null || pool.Count == 0)
    {
        pool = Helper.NewDrawPool();
    }
    if (pool.Count < count)
    {
        var n = pool.Count;
        var needN = count - n;
        res.AddRange(pool);
        pool = Helper.NewDrawPool();

        var lastN = pool.Skip(pool.Count - needN).Take(needN).ToList();
        pool.RemoveRange(pool.Count - needN, needN);
        res.AddRange(lastN);
    }
    else
    {
        var lastCount = pool.Skip(pool.Count - count).Take(count).ToList();
        pool.RemoveRange(pool.Count - count, count);
        res.AddRange(lastCount);
        if (res.Any(e => e.Type == 0))
        {
            pool = Helper.NewDrawPool();
        }
    }
    //此处省略抽卡的逻辑代码,计算好的抽卡结果保存在 DrawResult 类型的变量中
    return new DrawResult
    {
        Ok = true,
        Items = res
    };
}

找到场景中的抽卡的 Button 按钮,可以看到按钮响应的是 MainUIController 脚本中的 DrawCard 方法。

下面的示例代码给我们展示的是抽卡的方法(DrawCard)的客户端的逻辑代码。

public async void DrawCard(int count = 1)
{
    ShowLoading(true);
    try
    {
        await NetworkManager.DrawCard(count);
    }
    catch (Exception e)
    {
        Debug.Log(e.Message);
        ShowLoading(false);
        MessageUI.Show(e.Message);
    }
}

这里的 NetworkManager.DrawCard 的代码是等待服务器返回抽卡的结果。

public async Task DrawCard(int count)
{
    var drawResult = await _as.Draw(_accountId, count);
    if (!drawResult.Ok)
    {
        onError.Invoke(drawResult.Message, 3);
        return;
    }

    var listResult = new List<Item>(drawResult.Items.Count);
    listResult.AddRange(drawResult.Items.Select(it => new Item
    {
        Type = it.Type switch
        {
            0 => ItemType.Hero,
            1 => ItemType.Prop,
            _ => ItemType.Other
        },
        Name = it.Name,
        Count = it.Count,
        Level = it.Level
    }));

    onDrawCard.Invoke(listResult);
}

然后,我们就可以点击「上传云函数」的按钮,等待云函数的构建和部署。

根据控制台日志的输出信息,看到远程模式下代码缓存更新已完成。

可以通过点击工具中的时间戳,快速跳转到网页控制台查看云函数部署情况。

当云函数构建完成后,工具已经自动将您的云函数部署到 Func Stateless 了。

7.2 切换成远程调用模式

在工具中,将云函数的调用模式由「本地调用」切换到「远程调用」。防止客户端包体可能会被破解,所以权威性逻辑不能在客户端执行,而必须在服务端上执行。

切换到远程调用模式后,云函数代码发生了变化。打开脚本可以看到,云函数中的代码由原来的业务逻辑变成了远程调用的代码。如下图所示:

ActionService.cs脚本中的当前云函数:

[CloudService]
public class ActionService
{
     //此处省略其它代码......
    [CloudFunc]
    public async Task<GetItemsResult> GetHeroes(string id)
    {
        var json = "{" + $"\"id\":{JsonConvert.SerializeObject(id)}" + "}";
        var jsonResult = await HttpClient.Call($"https://{ActionServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/actionservice", "getheroes", json);
        return JsonConvert.DeserializeObject<GetItemsResult>(jsonResult);
    }

    [CloudFunc]
    public async Task<DrawResult> Draw(string id, int count)
    {
        var json = "{" + $"\"id\":{JsonConvert.SerializeObject(id)},\"count\":{JsonConvert.SerializeObject(count)}" + "}";
        var jsonResult = await HttpClient.Call($"https://{ActionServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/actionservice", "draw", json);
        return JsonConvert.DeserializeObject<DrawResult>(jsonResult);
    }
}

LoginService.cs脚本中的当前云函数:

[CloudService]
 public class LoginService
 {
     [CloudFunc]
     public async Task<LoginResult> Login(string username, string password)
     {
         var json = "{" + $"\"username\":{JsonConvert.SerializeObject(username)},\"password\":{JsonConvert.SerializeObject(password)}" + "}";
         var jsonResult = await HttpClient.Call($"https://{LoginServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/loginservice", "login", json);
         return JsonConvert.DeserializeObject<LoginResult>(jsonResult);
     }
 }

7.3 查看调用的日志信息

切换成远程调用模式后,再次运行游戏项目。可以在网页端的控制台上,查看云函数的调用日志,看到项目已经成功调用了上传的云函数。

7.4 查看数据库的存储信息

然后,可通过 CRUD Storage 的数据库管理页面连接到数据库。

在弹出的页面中,可看到存储的数据库中的 users 的账户登录和抽卡数据的信息。

8. 自行创建一个新的云函数,进行调用和测试

第一次打开工具后,需要点击 「+新建云函数」 来创建您的第一个云函数脚本类 NewService.cs,其中会包含示例代码,大家可以基于自己的业务需求在此代码基础上进行修改。

注意:SDK 会默认创建 Assets/Scripts/CloudService 目录作为云函数代码的目录。

打开 NewService.cs 脚本后,脚本中有详细的使用说明的介绍,脚本中默认已经创建好了两个云函数 Echo 和 GetUserInfo 了,代码如下所示:

using System.Threading.Tasks;
using Unity.UOS.Func.Stateless.Core.Attributes;
using UnityEngine;

namespace CloudService
{
    // 注意事项
    // 1. 云函数类所在脚本文件的名称必须与类名相同。
    // 2. 所有的类必须放置于命名空间内,且所用到的代码文件必须放到同一目录中。
    // 3. 使用 [CloudService] 标记有远程调用函数的类,使用 [CloudFunc] 标记需要远程调用的函数。
    // 4. 请在云函数类构造函数中初始化云函数,不要创建并调用其他带有参数的构造函数。
    // 5. 切换到远程模式后云函数类只会保留带有 [CloudFunc] 的方法,其他字段将会被隐藏。
    // 6. 使用 [CloudFunc] 标记的函数必须符合 public async Task<返回数据类型> 函数名称(输出参数) { 函数体 } 这样的格式。
    // 7. 编写代码中只能使用 UnityEngine 命名空间下的 Debug.Log,Debug.LogWarning,Debug.LogError 函数,不能使用其他函数。

    [CloudService]
    public class NewService
    {
        public NewService()
        {
            // 初始化
        }

        [CloudFunc]
        public async Task<string> Echo(string msg)
        {
            Debug.Log($"call echo with {msg}");
            return msg;
        }

        [CloudFunc]
        public async Task<UserInfo> GetUserInfo(string userId)
        {
            Debug.Log($"get information about user {userId}");
            return new UserInfo
            {
                Name = "Jack",
                Age = 18
            };
        }
    }

    public class UserInfo
    {
        public string Name;
        public int Age;
    }
}

然后我们需要创建一个调用云函数的 C# 脚本,当前脚本命名为 TestCall.cs,脚本代码如下所示:

using CloudService;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestCall : MonoBehaviour
{
    private async void Start()
    {
        var ns = new NewService();

        var echoResult = await ns.Echo("hello world");
        Debug.Log($"echoResult: {echoResult}");

        var userInfo = await ns.GetUserInfo("userId");
        Debug.Log($"userInfo: {userInfo.Name} - {userInfo.Age}");
    }
}

接着,我们在场景中创建一个空的游戏对象,可以先命名为 TestCall,将创建好的脚本 TestCall.cs 挂载到场景中刚才创建的空游戏对象上。

先在本地调试模式下运行,查看控制台的打印输出结果,看到云函数本地已经被调用了。

9. 自建云函数后,将数据存储在 CRUD Storage数据库

初步学习了云函数的用法后,接下来我们再次创建一个新的云函数脚本,来教大家实现将一个自定义的数据的信息,实现增删改查的操作,并保存在 CRUD Storage 数据库中。

参考 CRUD 连接指南的示例用法:

https://uos.unity.cn/doc/func/stateless/crud-connect#csharp#mongodb

9.1 创建云函数脚本

再次点击「+新建云函数」,来创建一个新的云函数类脚本,命名为 MongoService.cs。然后在 UOS 官网的「CRUD 连接指南」页面,复制 MongoDB 云函数示例代码,粘贴在脚本 MongoService.cs 中。

脚本中有四个云函数:

  • 云函数 CreateAsync—— 来实现向数据库中插入一条信息

  • 云函数 ReadAllAsync—— 来实现读取数据库的信息

  • 云函数 UpdateAsync—— 来实现更新数据库中的信息

  • 云函数 DeleteAsync—— 来实现从数据库中删除一条信息

[CloudFunc]//向数据库中插入一条信息
public async Task<bool> CreateAsync(Person p)
{
    var client = await MongoConnectionManager.GetConnection();
    var database = client.GetDatabase(DBName);
    var collection = database.GetCollection<Person>(CollectionName);
    await collection.InsertOneAsync(p);
    return true;
}

[CloudFunc]//读取数据库的信息
public async Task<List<Person>> ReadAllAsync()
{
    var client = await MongoConnectionManager.GetConnection();
    var database = client.GetDatabase(DBName);
    var collection = database.GetCollection<Person>(CollectionName);
    var options = new FindOptions<Person, Person>
    {
        Projection = Builders<Person>.Projection.Exclude("_id")
    };
    var people = await collection.FindAsync(new BsonDocument(), options);
    return await people.ToListAsync();
}

[CloudFunc]//更新数据库中的信息
public async Task<bool> UpdateAsync(string who, int newBalance)
{
    var client = await MongoConnectionManager.GetConnection();
    var database = client.GetDatabase(DBName);
    var collection = database.GetCollection<Person>(CollectionName);
    var filter = Builders<Person>.Filter.Eq("Name", who);
    var update = Builders<Person>.Update.Set("Balance", newBalance);
    var updateResult = await collection.UpdateOneAsync(filter, update);
    return updateResult.IsAcknowledged;
}

[CloudFunc]//从数据库中删除一条信息
public async Task<bool> DeleteAsync(string who)
{
    var client = await MongoConnectionManager.GetConnection();
    var database = client.GetDatabase(DBName);
    var collection = database.GetCollection<Person>(CollectionName);
    var deleteFilter = Builders<Person>.Filter.Eq("Name", who);
    var deleteResult = await collection.DeleteOneAsync(deleteFilter);
    return deleteResult.IsAcknowledged;
}

9.2 创建调用云函数的脚本

创建一个调用云函数的脚本,命名为 MongoManager.cs,可以在 UOS 官网的「CRUD 连接指南」页面,复制 MongoDB 的调用云函数的示例代码。

// MongoManager.cs
using System.Text;
using CloudServic页面,复制 MongoDB 的调用云函数的示例代码。// MongoManager.csespace ClientScript
{
    public class MongoManager : MonoBehaviour
    {
        private string RandomString(int length)//随机一个字符串,后面随机用户的名字的时候会调用
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            var sb = new StringBuilder();
            for (var i = 0; i < length; i++)
            {
                var idx = Random.Range(0, chars.Length);
                sb.Append(chars[idx]);
            }

            return sb.ToString();
        }

        // Start is called before the first frame update
        private async void Start()
        {
            var ms = new MongoService();

            // 插入
            var personName1 = RandomString(6);
            var personName2 = RandomString(6);
            await ms.CreateAsync(new Person() { Name = personName1, Balance = 9999 });
            await ms.CreateAsync(new Person() { Name = personName2, Balance = 999 });

            // 查询
            var allPerson = await ms.ReadAllAsync();
            Debug.Log($"found {allPerson.Count} person");
            foreach (var person in allPerson)
            {
                Debug.Log($"name: {person.Name}; balance: {person.Balance}");
            }

            // 修改
            var updateResult = await ms.UpdateAsync(personName1, 123);
            Debug.Log($"{personName1} modified result: {updateResult}");

            // 删除
            var deleteResult = await ms.DeleteAsync(personName2);
            Debug.Log($"{personName2} delete result: {deleteResult}");

            // 查询
            allPerson = await ms.ReadAllAsync();
            Debug.Log($"found {allPerson.Count} person");
            foreach (var person in allPerson)
            {
                Debug.Log($"name: {person.Name}; balance: {person.Balance}");
            }
        }
    }
}

MongoManager.cs 脚本还是挂载在之前创建好的游戏对象 TestCall 上。

9.3 本地调用测试 先在本地模式下进行调试吧,运行项目后,在控制台看到运行后打印输出的结果。

9.4 上传云函数

在 Func Stateless Tool 工具中,可看到刚才创建的4个云函数,点击「上传云函数」。

通过点击工具中的时间戳,跳转到网页控制台可以看到云函数已经成功部署到了 Func Stateless 上了。

9.5 远程模式下调用测试

将当前的云函数的调用模式,切换到「远程调用」模式。

此时再次查看脚本 MongoService.cs 中的云函数的代码:

[CloudService]
public class MongoService
{
    [CloudFunc]
    public async Task<bool> CreateAsync(Person p)
    {
        var json = "{" + $"\"p\":{JsonConvert.SerializeObject(p)}" + "}";
        var jsonResult = await HttpClient.Call($"https://{MongoServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/mongoservice", "createasync", json);
        return JsonConvert.DeserializeObject<bool>(jsonResult);
    }

    [CloudFunc]
    public async Task<List<Person>> ReadAllAsync()
    {
        var json = "{" + $"" + "}";
        var jsonResult = await HttpClient.Call($"https://{MongoServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/mongoservice", "readallasync", json);
        return JsonConvert.DeserializeObject<List<Person>>(jsonResult);
    }

    [CloudFunc]
    public async Task<bool> UpdateAsync(string who, int newBalance)
    {
        var json = "{" + $"\"who\":{JsonConvert.SerializeObject(who)},\"newBalance\":{JsonConvert.SerializeObject(newBalance)}" + "}";
        var jsonResult = await HttpClient.Call($"https://{MongoServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/mongoservice", "updateasync", json);
        return JsonConvert.DeserializeObject<bool>(jsonResult);
    }

    [CloudFunc]
    public async Task<bool> DeleteAsync(string who)
    {
        var json = "{" + $"\"who\":{JsonConvert.SerializeObject(who)}" + "}";
        var jsonResult = await HttpClient.Call($"https://{MongoServiceq3k9FwJi5A.Domain}/release/d040d269-5083-4c53-babe-c3670e8a29b9/mongoservice", "deleteasync", json);
        return JsonConvert.DeserializeObject<bool>(jsonResult);
    }
}
 

在编辑器中再次运行项目后,通过查看 UOS 网页端云函数的调用日志信息,也可以看出自定义的云函数被成功调用了。

最后在 CRUD Storage 页面再次查看数据库的存储信息,可以看到用户自定义的数据库 testdb 中存储的 people 集合的信息了。

学习途径

UOS 配套的相关学习教程视频也已同步上传至 Unity 中文课堂和 B 站,搜索 “用C#云函数快速构建与部署服务端逻辑实战指南” 即可找到,欢迎大家前往学习,UOS 更多学习教程持续更新中,敬请期待。

了解更多 UOS 相关信息:

官网:https://uos.unity.cn

技术交流 QQ 群:823878269

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2207234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch(二)集成Spring Boot 基本的API操作

目录 一、集成Spring Boot 1、创建项目 2、pom文件 查看springboot集成的依赖 3、增加es的config类 二、索引相关API 1、创建索引 2、获取索引&#xff0c;判断其是否存在 3、删除索引 三、文档相关API 1、添加文档 2、获取文档&#xff0c;判断是否存在 3、获取文档…

Java后端面试----某团一面

美团一面 1.介绍一下你的第一个项目 这个就不多说了&#xff0c;主要是根据自己的简历上面的项目进行一个简短的概括使用的技术栈和什么背景解决了什么问题等等。 2.线程安全的类有哪些&#xff0c;平时有使用过哪些&#xff0c;主要解决什么问题 在Java中线程安全的类比如…

对后端返回的日期属性进行格式化(扩展 Spring MVC 的消息转换器)

格式化之前 格式化之后&#xff1a; 解决方式 方式一 在属性中加上注解&#xff0c;对日期进行格式化 JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//JsonFormat(pattern &quo…

echarts按需引入解决项目大小问题

背景&#xff1a; 按需加载缩减项目大小&#xff0c;提升项目性能和可用性 实现&#xff1a; 创建echarts.js main.js进行配置 页面中引用 效果 全量导入 按需加载&#xff1a;

Chrome清除nslookup解析记录 - 强制http访问 - 如何禁止chrome 强制跳转https

步骤&#xff1a; 地址栏输入 chrome://net-internals/#hsts在Delete domain 栏的输入框中输入要http访问的域名&#xff0c;然后点击“delete”按钮最后在Query domain 栏中搜索刚才输入的域名&#xff0c;点击“query”按钮后如果提示“Not found”即可&#xff01; 办法来自…

Linux系统:apt upgrade与apt update 命令的作用

一.sudo apt update命令 sudo apt update命令的主要作用是更新本地软件包列表。‌ 它不会下载或安装新的软件包&#xff0c;而是更新本地系统中软件包的列表&#xff0c;以反映远程存储库中的最新可用软件包信息。这确保了软件包管理器&#xff08;APT&#xff09;具有最新的软…

第十六周周报:单发的目标检测系列

目录 摘要 Abstract 一、SSD 1.1 模型结构 1.2 代码 二、YOLO 三、Termius 总结 摘要 本周主要学习单阶段的目标检测算法&#xff0c;如SSD、YOLO模型。详细学习了每个模型的原理&#xff0c;以及SSD和YOLO模型之间的异同。在本篇博客中将展示SSD的PyTorch实现代码&am…

Django使用uwsgi和nginx进行手动部署

在Django项目中使用uWSGI和Nginx进行部署是一种常见的生产环境配置。以下是一个详细的步骤指南&#xff0c;帮助你完成这个过程。 前提条件 有一个已经开发好的Django项目。服务器已安装Python、pip、Nginx和uWSGI。有一个有效的域名(可选&#xff0c;但推荐)。 步骤一&#xf…

CPU指令融合技术概述

什么是指令融合&#xff1f; 某些指令&#xff0c;例如add $3,$2,0, 只会使用rd/rs两个字段&#xff0c;但是这条指令却占用了全部32个bit, 这样会使得代码密度不高&#xff0c;指令域的有效利用率不高&#xff1b;这样&#xff0c;在实现某些功能的情况下&#xff0c;会使得CP…

Java创建线程池和线程池的七个核心参数

线程池的工作流程是&#xff1a;当一个任务被提交到线程池时&#xff0c;线程池会根据当前的线程数量和工作队列的状态来决定如何处理这个任务。如果当前运行的线程数量小于corePoolSize&#xff0c;则创建新线程执行任务&#xff1b;如果大于等于corePoolSize&#xff0c;则将…

毕设开源 大数据电影数据分析与可视化系统(源码+论文)

文章目录 0 前言1 项目运行效果2 设计概要3 最后 0 前言 &#x1f525;这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师…

完全免费安卓远程安卓方案:FRP+ADB甲壳虫方案,远程手机不是问题。

引言 在当今这个数字化时代&#xff0c;无论是在个人项目还是商业应用中&#xff0c;能够从公网访问到内网设备的能力变得越来越重要&#xff0c;尤其是安卓终端设备&#xff0c;在必要的情况下&#xff0c;从安卓远程到安卓进行紧急指导救援是未来一种重要的趋势. 通过合理的…

Java - WebSocket

一、WebSocket 1.1、WebSocket概念 WebSocket是一种协议&#xff0c;用于在Web应用程序和服务器之间建立实时、双向的通信连接。它通过一个单一的TCP连接提供了持久化连接&#xff0c;这使得Web应用程序可以更加实时地传递数据。WebSocket协议最初由W3C开发&#xff0c;并于2…

3种常用的缓存读写策略详解

在详解3种常用的缓存读写之前&#xff0c;我们先要了解什么事缓存读写。 缓存读写是指在使用缓存技术时&#xff0c;对数据进行读取和更新的操作过程。缓存是一种用于提高系统性能和可扩展性的技术&#xff0c;通过减少对慢速存储&#xff08;如数据库&#xff09;的访问次数&…

CAN总线仲裁机制

文章目录 1、什么是CAN总线仲裁&#xff1f;2、仲裁机制3、仲裁过程 1、什么是CAN总线仲裁&#xff1f; CAN总线上的每个节点都能监测到总线上发送的数据&#xff0c;当总线空闲时每个节点都能够进行报文发送&#xff0c;多个节点同时发送报文时&#xff0c;最终由哪个节点来进…

中间件有哪些分类?

中间件的分类 中间件是位于操作系统和应用程序之间的软件&#xff0c;它提供了一系列服务来简化分布式系统中的应用程序开发和集成。中间件可以根据其功能和用途被分为不同的类别。以下是中间件的一些主要分类&#xff1a; 1. 通信处理&#xff08;消息&#xff09;中间件&am…

Sentinel 1.80(CVE-2021-44139)

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性 Report a Sentinel Security Vulnerability …

华为eNSP实验:以太网交换---MAC地址漂移防止与检测

一&#xff1a;MAC地址漂移 MAC地址漂移是一种网络攻击技术&#xff0c;它利用了网络设备&#xff08;如交换机&#xff09;的动态学习特性来改变网络流量的路径。这种攻击可能导致数据包被错误地转发到未经授权的设备上&#xff0c;从而造成信息泄露或拒绝服务攻击。为了防止…

ViirtualBox+Vagrant快速创建虚拟机,固定IP地址

ViirtualBoxVagrant配置虚拟机共分三步 1.ViirtualBox的安装 2.Vagrant的安装 3.VirtualBoxVagrant配置虚拟机 1.安装virtual Box 2.进入官网 下载 https://www.virtualbox.org/wiki/Downloads 下载对应版本 https://www.virtualbox.org/wiki/Download_Old_Builds_6_1 使用…

物联网中的远距离通信LoRa无线技术

LoRa&#xff08;Long Range Radio&#xff09;远距离无线传输技术是基于扩频调制技术的低功耗、远距离无线通信技术&#xff0c;采用扩频调制&#xff0c;通过将原始信号与一个伪随机序列进行编码&#xff0c;使得信号的带宽显著增加&#xff0c;从而在更宽的频谱上传输。这种…