《火拼24》系列教程第二章内容来袭!在首章教程的基础上,本节将深度揭秘如何运用 UOS 的 Remote Config 服务,实现游戏关卡难度的动态调控——手把手教你通过远程配置灵活修改关卡参数,无需迭代新版本即可实时优化玩家体验,让游戏平衡性调整更高效、更智能!

教程视频

项目工程获取与学习指引

1. 初始项目工程下载

  • 仓库地址:

https://cnb.cool/unity/uos/Rush24Tutorial/-/tree/lesson2-start

  • 分支名称:lesson2-start 分支

  • 分支说明:请先下载 lesson2-start 分支的项目工程,该分支是本节学习的起点。

2.完整示例工程参考
  • 仓库地址:

https://cnb.cool/unity/uos/Rush24Tutorial/-/tree/lesson2-end

  • 分支名称:lesson2-end 分支

  • 分支说明:lesson2-end 分支包含本节所有功能的完整实现代码,建议在学习完成后参考或用于调试对照。

教程学习大纲

1. 使用 Remote Config 在服务端配置关卡数据

2. 封装获取远程配置数据的脚本工具类

3. 使用 Remote Config 的数据来动态调控游戏关卡难度

教程操作步骤

接下来我们要开始本节课的学习啦!

1. 使用 Remote Config 在服务端配置关卡数据

1.1 下载并打开项目工程

请先通过上面提供的 git 仓库链接,下载初始状态(lesson2-start 分支)的项目工程。

然后通过 Unity Hub,打开刚刚下载好的项目工程。在教程中,我们是使用Unity 2022.3.42 f1c1版本来打开项目工程的,该教程同样适用于团结引擎,请大家自行选择想要使用的版本来开始你的学习。

打开项目工程以后,首先确保你的项目已经绑定了第一章节教程中设置过的同一个UOS App,因为那个 UOS App 中已经开通过 Passport 服务了。

我们会在第一节教程的功能的基础上,继续来添加如何实现在服务端动态调整游戏关卡难度!

1.2什么是 Remote Config

Remote Config 是可以和任意 UOS 应用搭配使用的远程配置模块,支持开发者动态更改游戏配置,以减少不必要的打包发版次数。

一些使用Remote Config的例子如下:

  • A/B Testing 和新功能上线;

  • 可集成 CDN 进行灰度测试;

  • 提前设定好时间的节日推广/限时活动;

  • 白名单/黑名单,或根据玩家标签(Tag)提供差异化体验。

1.3 开通Remote Config 服务并安装 SDK

在 UOS Launcher 的下拉服务窗口列表中,找到Remote Config,点击Enable开启服务。

然后点击Install SDK,安装 Remote Config SDK。

1.4 配置关卡数据

1.4.1 配置(Config)的概念

配置(Config)是面向游戏开发者的概念,是传统的 Config 形式,以 key-value 的形式存储在云端,游戏开发者有权对 Config 进行管理,其中更改是实时生效的。

1.4.2 配置 Remote Config

在 UOS 网页端,进入Remote Config ->配置管理」页面,点击「配置(CONFIG)」下面的「立即创建」按钮:

在弹出窗口中,输入配置的key、类型和对应的值:

  • 名称:我们输入 AllStageLevels,表示该配置是游戏关卡的数据。对于同一 UOS App 来说,名称(key)是不能重复的。

  • 类型:字段类型有 int、float、long、bool、string、json 六个选项,在这里我们使用 string 类型。

  • 值:暂时输入 5,6,7,8 2,3,4,5。表示第一关的四张牌的数据是 5,6,7,8,第二关的四张牌的数据是 2,3,4,5。在这里输入关卡数据的格式是:两道题目之间用「空格」分隔,同一道题的四个数值之间用「英文逗号」分隔。

配置完数据之后,点击「添加」按钮,就可以看到配置好的数据了。

1.4.3 覆盖 ( Override)的概念

我们可以看到在「配置管理」页面,还有一个覆盖(Override)的配置,等后面用到 Override 时再详细讲解它的用法。

先来了解下覆盖(Override)的概念:

覆盖(Override)也是面向游戏开发者(Developer)的概念,为了在 Config 之上进行更加灵活的特异性配置,包括应用百分比、生效开始时间、过期时间等。只有游戏开发者可以对 Override 进行管理。

2. 封装获取远程配置数据的脚本工具类

配置好了数据以后,我们来看看代码中,具体的是如何实现加载 RemoteConfig 中的数据的!

2.1 创建脚本来存放配置的 key

在下图所示的路径下,创建一个新的脚本文件夹 RemoteConfig,并在该文件夹下创建一个新的脚本 RemoteConfigKeys.cs。

静态类RemoteConfigKeys,用于存放远程配置的键名常量。

  • 定义一个常量字符串 AllStageLevels,表示所有关卡的配置键名。

namespace TwentyFour.Scripts.Features.RemoteConfig
{
    // 定义一个静态类,用于存放远程配置的键名常量
    public static class RemoteConfigKeys
    {
        // 定义一个常量字符串,表示所有关卡的配置键名
        public const string AllStageLevels = "AllStageLevels";
    }
}

它的值要和刚才 RemoteConfig 网页段配置的 key 名称保持一致。

2.2 创建获取远程配置的辅助类

在 RemoteConfig 文件夹下,再创建一个新的脚本 RemoteConfigHelper.cs。

该脚本中的代码实现了一个远程配置辅助工具类,用于从远程服务器获取和管理游戏的配置数据,方便游戏根据远程参数灵活调整功能和表现。

2.2.1 初始化 Remote Config SDK

创建 Init 方法,作为整个远程配置功能的初始化入口。在方法内先调用 Initialize 来初始化 RemoteConfig SDK。在初始化过程中如果发生了错误,我们会通过 try...catch... 捕获异常,并打印记录的错误信息,便于代码调试。

using System;
using System.Threading.Tasks;
using Unity.UOS.Config;
using Logger = TwentyFour.Scripts.Utilities.Logger;

namespace TwentyFour.Scripts.Features.RemoteConfig
{
    // 定义远程配置辅助类
    public class RemoteConfigHelper
    {
        // 初始化远程配置的异步方法
        public static async Task Init()
        {
            try
            {
                // 初始化远程配置SDK
                RemoteConfigSDK.Initialize();
            }
            catch (Exception e)
            {
                // 捕获异常并记录错误日志
                Logger.LogError($"RemoteConfigHelper Init Error:{e}");
            }
        }
    }
 }
2.2.2 获取 Remote Config 配置过的数据

在初始化方法Init中,调用封装的GetDefaultRemoteConfig方法,来异步获取玩家的默认远程配置,以便游戏运行时动态调整行为。

  • 首先定义字典 _remoteConfigData ,用于本地存储远程配置数据,方便后续快速读取,无需每次都访问服务器;

  • 然后调用 SDK 提供的 GetPlayerSettingsAsync 函数,向服务器发起一个异步网络请求,以获取为当前玩家准备的配置。

网络请求完成后,如果成功了:

  • 通过 settings.data 从返回结果中获取响应数据,存在变量 response 中;

  • 然后将从服务器收到的配置列表(response.Settings)转换成一个字典,并将其赋值给刚才定义过的字典 _remoteConfigData;

  • 接下来为了调试和监控,遍历所有获取到的配置项(response.Settings),用 StringBuilder 高效地构建了一个完整的字符串,然后通过 Logger.Log(sb) 将所有配置项打印到日志中,方便开发者查看拉取到的数据是否正确。

网络请求完成后,如果失败了:

  • 如果网络请求或服务器处理失败,就在日志中记录一条错误信息,方便排查问题。

无论成功与否,最后都将获取到的玩家默认的配置结果(settings)返回。

using System;
using System.Threading.Tasks;
using Unity.UOS.Config;
using Logger = TwentyFour.Scripts.Utilities.Logger;
using Cloud;
using Unity.UOS.Config.Model;
using System.Linq;
using System.Text;

namespace TwentyFour.Scripts.Features.RemoteConfig
{
    // 定义远程配置辅助类
    public class RemoteConfigHelper
    {
        // 用于存储远程配置数据的静态字典,键为配置名,值为Setting对象
        private static Dictionary

 _remoteConfigData = new Dictionary

 ();         // 初始化远程配置的异步方法         public static async Task Init()         {             try             {                 // 初始化远程配置SDK                 RemoteConfigSDK.Initialize();                 await GetDefaultRemoteConfig(); // 获取默认远程配置             }             catch (Exception e)             {                 // 捕获异常并记录错误日志                 Logger.LogError($"RemoteConfigHelper Init Error:{e}");             }         }         // 异步获取默认远程配置的方法         public static async Task > GetDefaultRemoteConfig()         {             // 发送请求获取玩家默认设置             var settings = await RemoteConfigSDK.GetPlayerSettingsAsync(new GetPlayerSettingsRequest());             if (settings.IsSuccess())             {                 // 获取响应数据                 GetPlayerSettingsResponse response = settings.data;                 // 将设置转换为字典并保存                 _remoteConfigData = response.Settings.ToDictionary(x => x.Key, x => x.Value);                 var sb = new StringBuilder();                 // 遍历所有设置,拼接日志信息                 foreach (var entry in response.Settings)                 {                     sb.AppendLine($"Remote Config: {entry.Key} - {entry.Value} ,type: {entry.Value.Type}");                 }                 // 记录日志                 Logger.Log(sb);             }             else             {                 // 获取失败时记录错误日志                 Logger.LogError($"RemoteConfigHelper GetDefaultRemoteConfig Error");             }             // 返回结果             return settings;         }     }  } 

2.2.3 封装读取配置数据的接口

封装方法GetString(key),用于从远程配置缓存中获取字符串类型的配置值。后续如果配置了其它数据类型,用到的时候,会再详细讲解其它类型的数据如何读取。

  • 方法中传入你想要获取的配置项的名称(key);

  • 然后尝试从 _remoteConfigData 字典中查找是否存在指定 key 的配置项,如果找到了并且该配置项的类型是 string 类型,则返回配置项的值。如果找不到,则返回一个空字符串。

namespace TwentyFour.Scripts.Features.RemoteConfig
{
    // 定义远程配置辅助类
    public class RemoteConfigHelper
    {
        //......

        // 获取远程配置的字符串类型的数据的方法
        public static string GetString(string key)
        {
            // 尝试从字典中获取指定key的值,并判断类型是否为String
            if (_remoteConfigData.TryGetValue(key, out var value) && value.Type == ConfigType.String)
            {
                // 返回字符串值
                return value.Value;
            }
            // 未获取到则返回空字符串
            return string.Empty;
        }
    }
 }

3. 使用 Remote Config 的数据来动态调控游戏关卡难度

3.1 调用初始化远程配置的方法

在游戏启动时,我们将按顺序完成远程配置、关卡、存档的初始化,最后再进入主场景。

因此,先找到脚本 LoadGameData.cs,在协程方法 Init() 中,实现在成功创建角色之后,先调用初始化远程配置数据的方法 InitRemoteConfig。

  • 在 InitRemoteConfig 方法中,调用之前封装好的 RemoteConfigHelper.cs 脚本中的 Init 方法,实现远程配置的初始化;

  • 然后使用 WaitUntil 等待这个异步任务完成。

using TwentyFour.Scripts.Features.RemoteConfig;

namespace TwentyFour.Scripts.Gameplay.HomePage
{
    public class LoadGameData : MonoBehaviour
    {
        //......

        // Start is called before the first frame update
        IEnumerator Init()
        {
            yield return StartCoroutine(InitRemoteConfig());
            yield return StartCoroutine(InitStage());
            yield return StartCoroutine(InitSave());
            GameRouter.LoadHomeSceneFirst();
        }
        //......

        IEnumerator InitRemoteConfig()
        {
            var t = RemoteConfigHelper.Init();
            yield return new WaitUntil(()=>t.IsCompleted);
            yield return null;
        }
    }
}

接着运行游戏进行测试,可以看到 Console 控制台打印的日志信息。说明已经加载到了远程配置的关卡数据了,但是发现 Game 窗口中的关卡数据还没有发生变化。

原因是:在 StageManager.cs 脚本的 LoadAllStagesFromRemoteConfig 方法中,看到目前使用的还是本地的 Resources 文件夹下的 levels.txt 文件中的关卡数据。

    public static class StageManager
    {
        //......

        public static void LoadAllStagesFromRemoteConfig()
        {
            var file = Resources.Load ( "levels").text;
            HandleFileContent(file);
        }
    }

Resources 文件夹下的 levels.txt 文件中的关卡数据如下:

3.2 使用从 RemoteConfig 加载到的关卡数据

现在我们修改下代码,实现从远程配置(RemoteConfig )来加载所有关卡的数据。

打开StageManager.cs 脚本:

  • 在原来的方法 HandleFileContent 中,处理的是从 levels.txt 获取到的字符串,每一行的分隔符号是\n,现在的每一行题目的分隔符是「空格」,修改代码 fileString.Split('\n',' ') 中的分隔符号,这里可以使用可变参数类型,所以一次性可以传入多个字符分隔符;

  • 该方法的作用主要是:将一段特定格式的字符串,也就是刚才远程配置过的数据5,6,7,8 2,3,4,5,解析成关卡对象(Stage),并存储到 _allStages 列表中。

namespace TwentyFour.Scripts.Gameplay.GameMode.StageMode
{
    public static class StageManager
    {     
        //......
        private static void HandleFileContent(string text)
        {
            _allStages = new List ();
            string fileString = text.Replace("\r", ""); 
            string[] lines = fileString.Split('\n',' ');

            //......
        }
    }
}

然后在 LoadAllStagesFromRemoteConfig 方法中,调用 RemoteConfigHelper.cs 脚本中封装的 GetString 方法,实现从服务器的远程配置中获取配置好的字符串类型的关卡数据,存放到变量 file 中,然后判断以下两种情况:

  • 如果远程配置有数据(即字符串不为空),则使用远程配置的关卡数据;

  • 如果远程没有获取到数据(即字符串为空),则使用本地 Resources 文件夹中名为 levels.txt 的文本资源,作为关卡数据;

  • 两种情况下,最终都会调用 HandleFileContent 方法来对关卡数据的字符串进行解析的。

using TwentyFour.Scripts.Features.RemoteConfig;

namespace TwentyFour.Scripts.Gameplay.GameMode.StageMode
{
    public static class StageManager
    {     
        //......  
        public static void LoadAllStagesFromRemoteConfig()
        {
            //获取 RemoteConfig 中配置的关卡数据
            var file = RemoteConfigHelper.GetString(RemoteConfigKeys.AllStageLevels);
            if (string.IsNullOrEmpty(file))
            {
                //使用本地 Resources 文件夹中名为 levels.txt 的文本资源,作为关卡数据
                file = Resources.Load ( "levels").text;               
            }

            //解析存放关卡数据的字符串
            HandleFileContent(file);
        }
    }
}

再次运行测试,可以看到 Game 窗口中闯关界面关卡数只有两关了,说明数据已经从配置的 RemoteConfig 中获取到了。

接着,大家可以自行再次修改 UOS 网页端 RemoteConfig 中配置的关卡数据,然后登出账号后重新登录,就会自动加载新的关卡数据了。

下节教程预告

教程主题——《火拼24》系列教程三:游戏闯关进度的云端存档

《火拼24》下一篇教程,将揭秘基于 CRUD Save 打造的游戏闯关进度云端存档功能。它能实现当前登录用户闯关进度的云端保存,让用户退出游戏后再次进入仍可无缝衔接,精彩不容错过!

小贴士:为方便大家提前学习,教程三的分支代码已同步更新,可提前下载查阅或本地调试。

  • 教程三:初始项目工程(供学习参考)

https://cnb.cool/unity/uos/Rush24Tutorial/-/tree/lesson3-start

  • 教程三:完整示例工程参考(可直接运行)

https://cnb.cool/unity/uos/Rush24Tutorial/-/tree/lesson3-end

记得锁定更新,别错过每一步关键指南哦!

Unity Online Services (UOS) 是一个专为游戏开发者设计的一站式游戏云服务平台,提供覆盖游戏全生命周期的开发、运营和推广支持。

了解更多 UOS 相关信息:

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

技术交流 QQ 群:823878269

Unity 官方微信

第一时间了解Unity引擎动向,学习进阶开发技能

每一个“点赞”、“在看”,都是我们前进的动力