文档

支持

Remote Config

Remote Config

代码集成

Implement Remote Config in your game code using the RemoteConfig API.
阅读时间6 分钟最后更新于 1 个月前

RemoteConfig
API 包含在
Unity.Services
命名空间中,您必须将其加入您的游戏脚本中。有关其类和方法的更多信息,请参阅 Remote Config 脚本 APIRemote Config Runtime 脚本 API 文档。

实现自定义属性

要为游戏覆盖条件提供自定义属性,请在游戏脚本中实现以下
struct
变量:
  • 如果您的应用程序使用自己的跟踪方法,则通过
    SetCustomUserID
    方法使用
    Delivery
    结构来提供自定义玩家 ID 属性。如果没有开发者定义的属性,Remote Config 将自动生成 ID。
  • 使用
    userAttributes
    结构来提供自定义用户类别属性。
  • 使用
    appAttributes
    结构来提供自定义应用类别属性。
  • 使用
    filterAttributes
    结构来提供自定义过滤器类别属性,以减少有效负载。
注意:自定义属性完全是可选的。您可以在没有这些结构的情况下实现 Unity Remote Config,并针对游戏覆盖条件使用预定义的 Unity 属性。有关属性类别的更多信息,请参阅关于条件的文档。 首先,为实现自定义属性和阻止函数的脚本创建框架:
using UnityEngine;using Unity.Services.RemoteConfig;using Unity.Services.Authentication;using Unity.Services.Core;using System.Threading.Tasks;public class RemoteConfigExample : MonoBehaviour { public struct userAttributes { // Optionally declare variables for any custom user attributes: public bool expansionFlag; } public struct appAttributes { // Optionally declare variables for any custom app attributes: public int level; public int score; public string appVersion; } public struct filterAttributes { // Optionally declare variables for attributes to filter on any of following parameters: public string[] key; public string[] type; public string[] schemaId; } // Optionally declare a unique assignmentId if you need it for tracking: public string assignmentId; // Declare any Settings variables you’ll want to configure remotely: public int enemyVolume; public float enemyHealth; public float enemyDamage; // The Remote Config package depends on Unity's authentication and core services. // These dependencies require a small amount of user code for proper configuration. async Task InitializeRemoteConfigAsync() { // initialize handlers for unity game services await UnityServices.InitializeAsync(); // options can be passed in the initializer, e.g if you want to set AnalyticsUserId or an EnvironmentName use the lines from below: // var options = new InitializationOptions() // .SetEnvironmentName("testing") // .SetAnalyticsUserId("test-user-id-12345"); // await UnityServices.InitializeAsync(options); // remote config requires authentication for managing environment information if (!AuthenticationService.Instance.IsSignedIn) { await AuthenticationService.Instance.SignInAnonymouslyAsync(); } } async Task Awake () { // In this example, you will fetch configuration settings on Awake. } // Create a function to set your variables to their keyed values: void ApplyRemoteConfig (ConfigResponse configResponse) { // You will implement this in the final step. }}

在运行时获取并应用设置

接下来,实现您的 Remote Config 支持函数并在运行时调用这些函数,以便从服务检索键值对,然后将它们映射到相应的变量。 Remote Config 服务返回
RemoteConfigService.Instance
对象,用于在运行时获取并应用您的配置设置。在此示例中,您将使用它来从远程服务获取键值对,并在检索时调用您的
ApplyRemoteConfig
函数。
ApplyRemoteConfig
接收一个
ConfigResponse
结构,该结构表示对获取请求的响应,并使用
RemoteConfigService.Instance.appConfig
方法来应用设置。
// Retrieve and apply the current key-value pairs from the service on Awake:async Task Awake () { // initialize Unity's authentication and core services, however check for internet connection // in order to fail gracefully without throwing exception if connection does not exist if (Utilities.CheckForInternetConnection()) { await InitializeRemoteConfigAsync(); } // Add a listener to apply settings when successfully retrieved: RemoteConfigService.Instance.FetchCompleted += ApplyRemoteConfig; // you can set the user’s unique ID: // RemoteConfigService.Instance.SetCustomUserID("some-user-id"); // you can set the environment ID: // RemoteConfigService.Instance.SetEnvironmentID("an-env-id"); // Fetch configuration settings from the remote service, they must be called with the attributes structs (empty or with custom attributes) to initiate the WebRequest. await RemoteConfigService.Instance.FetchConfigsAsync(new userAttributes(), new appAttributes()); // Example on how to fetch configuration settings using filter attributes: // var fAttributes = new filterAttributes(); // fAttributes.key = new string[] { "sword","cannon" }; // RemoteConfigService.Instance.FetchConfigs(new userAttributes(), new appAttributes(), fAttributes); // Example on how to fetch configuration settings if you have dedicated configType: // var configType = "specialConfigType"; // Fetch configs of that configType // RemoteConfigService.Instance.FetchConfigs(configType, new userAttributes(), new appAttributes()); // Configuration can be fetched with both configType and fAttributes passed // RemoteConfigService.Instance.FetchConfigs(configType, new userAttributes(), new appAttributes(), fAttributes); // All examples from above will also work asynchronously, returning Task<RuntimeConfig> // await RemoteConfigService.Instance.FetchConfigsAsync(new userAttributes(), new appAttributes()); // await RemoteConfigService.Instance.FetchConfigsAsync(new userAttributes(), new appAttributes(), fAttributes); // await RemoteConfigService.Instance.FetchConfigsAsync(configType, new userAttributes(), new appAttributes()); // await RemoteConfigService.Instance.FetchConfigsAsync(configType, new userAttributes(), new appAttributes(), fAttributes);}void ApplyRemoteConfig (ConfigResponse configResponse) { // Conditionally update settings, depending on the response's origin: switch (configResponse.requestOrigin) { case ConfigOrigin.Default: Debug.Log ("No settings loaded this session and no local cache file exists; using default values."); break; case ConfigOrigin.Cached: Debug.Log ("No settings loaded this session; using cached values from a previous session."); break; case ConfigOrigin.Remote: Debug.Log ("New settings loaded this session; update values accordingly."); break; } enemyVolume = RemoteConfigService.Instance.appConfig.GetInt("enemyVolume"); enemyHealth = RemoteConfigService.Instance.appConfig.GetInt("enemyHealth"); enemyDamage = RemoteConfigService.Instance.appConfig.GetFloat("enemyDamage"); assignmentId = RemoteConfigService.Instance.appConfig.assignmentId; // These calls could also be used with the 2nd optional arg to provide a default value, e.g: // enemyVolume = RemoteConfigService.Instance.appConfig.GetInt("enemyVolume", 100);}

访问具有特定配置类型的配置

相应配置类型的所有设置都将正确地储存在缓存中。您可以通过传递配置类型来访问这些设置,例如:
RemoteConfigService.Instance.GetConfig("settings");RemoteConfigService.Instance.GetConfig("specialConfigType");

元数据参数

收到每个请求时,我们都会在后端创建一个分配事件。 在对请求的响应中,与
configs
代码块一起返回一个
metadata
代码块,其中包括以下参数:
MetaDataBlock
  • 每个分配事件都会创建
    assignmentId
    ,它用于跟踪事件和最终的用户细分
  • environmentId
    表示发生分配的环境
  • configAssignmentHash
    在分配时创建,表示该特定分配的唯一签名
configAssignmentHash
可以通过
appConfig
进行访问:
RemoteConfigService.Instance.appConfig.configAssignmentHash
在确定要使用的
configAssignmentHash
后,可以通过使用
SetConfigAssignmentHash()
方法来在有效负载中将其传递到后端:
RemoteConfigService.Instance.SetConfigAssignmentHash("4d1064c5198a26f073fe8301da3fc5ead35d20d1");
如果将
configAssignmentHash
传递到后端,后端将返回该特定
configAssignmentHash
创建时存在的配置。
configAssignmentHash
生命周期的 TTL 为 56 小时。经过该时间后,可以再次请求
configAssignmentHash
,而 TTL 将再次重置为 56 小时。

其他注意事项

利用 JSON 类型的 Settings 来覆盖对象

假设我们的代码中具有如下
CubeInfo
类:
[System.Serializable]public class CubeInfo{ public float rotateX = 10f; public float rotateY = 10f; public float rotateZ = 10f; public float rotSpeed = 1.0f; public Color color = Color.white;}
JSON 编辑器模式窗口支持以下类型的 JSON 转换:
  • 文本资源
  • 脚本化对象
  • 附加到游戏对象的自定义脚本
如果要使用文本资源,我们可以设置在结构上与
CubeInfo
类匹配的 Settings:
CubeJsonTextAsset
对于脚本化对象,单击选择框旁边的右上方圆点。选择一个脚本化对象后,该对象会自动转换为 json:
CubeJsonSO
如果从场景中选择游戏对象,则将显示一个额外的下拉选单,其中包括附加到该游戏对象的所有 Monobehavior 自定义脚本。您选择的对象会转换为 JSON:
CubeJsonCustomScript
要在运行时将这些设置应用到 CubeInfo 对象,请使用 JsonUtility 类来完成该操作:
case ConfigOrigin.Remote:var jsonCubeString = RemoteConfigService.Instance.appConfig.GetJson("jsonCubeString");JsonUtility.FromJsonOverwrite(jsonCubeString, CubeInfo);

安全

Unity 用来下载 Remote Config 数据的 Web 服务是只读的,但并不安全。这意味着第三方或许能够查看您的 Remote Config 数据。请勿将敏感或机密信息存储在您的配置设置中。同样,最终用户也可以读取和修改保存的设置文件(尽管在下次会话启动时,Remote Config 会在有可用的互联网连接时覆盖任何修改)。

平台支持

当前版本的 Remote Config Runtime 经过测试可以在以下平台上成功运行: 桌面:
  • Windows (PC)
  • Mac
  • Linux 平台
移动:
  • iOS
  • Android
有关 Remote Config 的控制台支持的信息,请联系我们的支持团队