Skip to main content

SDK Remote Config для Unreal Engine (версия 7.0.0)

SDK Remote Config – это облачный сервис, который позволяет изменять поведение и внешний вид вашего приложения, не требуя от пользователей загрузки обновления приложения. Плагин инкапсулирует в себе запрос конфигурации с сервера, кэширование, фоновое обновление. Имеет удобный интерфейс API для получения данных.

Пример реализации

Ознакомьтесь с приложением-примером, чтобы узнать, как правильно интегрировать SDK Remote Config.

Ключевые особенности

  • Выбор наиболее удобного механизма обновления конфигурации.
  • Возможность указывать процент распространения конфигурации на аудиторию.
  • Возможность передавать дополнительную информацию для построения воронки конкретной конфигурации. Формировать конфигурацию можно даже для конкретных пользователей.
  • Набор callback, который можно использовать для аналитики.
  • Минимальное количество внешних зависимостей.

Подключение в проект

  1. Скопируйте проекты плагина из официального репозитория RuStore на GitFlic.

  2. Скопируйте содержимое папки unreal_example/Plugins в папку Plugins внутри своего проекта. Перезапустите Unreal Engine.

  3. В списке плагинов (Edit > Plugins > Project > Mobile) отметьте плагины RuStoreRemoteConfig и RuStoreCore.

  4. В файле YourProject.Build.cs в списке PublicDependencyModuleNames подключите модули модули RuStoreCore и RuStoreRemoteConfig.

  5. В настройках проекта (Edit > Project Settings > Android) установите параметры:

    • Minimum SDK Version — не ниже 24;
    • Target SDK Version — не ниже 31.

Инициализация

Создание RemoteConfigClient

Инициализация RemoteConfigClient должна происходить в момент Application.onCreate(), так как при запуске фоновой синхронизации SDK должна быть проинициализирована.

Для инициализации RemoteConfigClient выполните расширение класса GameApplication и добавьте в метод onCreate следующий код.

Инициализация в Application
package com.example.RuStoreRemoteConfigApp;

import android.content.Context;
import com.epicgames.ue4.GameApplication;
import ru.rustore.unitysdk.remoteconfigclient.model.UnityUpdateBehaviour;
import ru.rustore.unitysdk.remoteconfigclient.RuStoreUnityRemoteConfigClient;

public class RuStoreRemoteConfigApplication extends GameApplication {

public final String APP_ID = "a83c91d3-21b4-4891-841e-0ed0fc39a562";
public final int UPDATE_TIME = 15;
public final String UPDATE_BEHAVIOUR = "Actual";

@Override
public void onCreate() {
super.onCreate();

RuStoreUnityRemoteConfigClient.INSTANCE.init(APP_ID, UPDATE_TIME, UPDATE_BEHAVIOUR, null, null, getApplicationContext());
}
}

Для замены класса GameApplication на RuStoreRemoteConfigApplication в файле манифеста вашего проекта, воспользуйтесь функционалом Unreal Plugin Language.

Пример UPL.xml
<prebuildCopies>
<copyDir src="$S(PluginDir)/Java" dst="$S(BuildDir)/src/com/example/RuStoreRemoteConfigApp" />
</prebuildCopies>

<androidManifestUpdates>
<addAttribute tag="application" name="android:name" value="com.example.RuStoreRemoteConfigApp.RuStoreRemoteConfigApplication" />
</androidManifestUpdates>

UpdateBehaviour

UpdateBehaviour — это параметр, определяющий поведение SDK. При создании экземпляра RemoteConfigClientBuilder, по умолчанию используется значение UpdateBehaviour.Default с интервалом синхронизации 15 минут.

Различия в значениях UpdateBehaviour

UpdateBehaviourОписание

Actual

При инициализации каждый запрос конфигурации выполняется через запрос к серверу.

Значение Actual гарантирует получение самой актуальной конфигурации, но скорость выполнения запроса зависит от скорости сети.

Этот тип инициализации отменяет процесс фонового обновления.

Default

При инициализации запрос конфигурации выполняется из локального постоянного хранилища, которое обновляется в указанный интервал.

Если инициализация выполняется первый раз и локальное постоянное хранилище пустое, запрос отправляется на сервер. Скорость выполнения запроса зависит от объема данных и скорости сети. Доступ к конфигурации будет ожидать завершения инициализации.

Значение Default не гарантирует, что в рамках жизни процесса запрос конфигурации будет отдавать одинаковый результат, так как синхронизация данных может выполниться в фоне.

Этот тип инициализации запускает процесс фонового обновления.

Snapshot

При инициализации запрос конфигурации выполняется из локального inMemory-хранилища. inMemory-хранилище заполняется результатом первого запроса из постоянного хранилища и сохраняется в таком виде до конца жизни процесса.

Если инициализация выполняется первый раз и локальное постоянное хранилище пустое, запрос отправляется на сервер. Скорость выполнения запроса зависит от объема данных и скорости сети. Доступ к конфигурации будет ожидать завершения инициализации.

Значение Snapshot гарантирует, что в рамках жизни процесса запросы конфигурации будут отдавать одинаковый результат.

Этот тип инициализации запускает процесс фонового обновления.

Инициализация в C++ и Blueprint

Для доступа к методам SDK из C++ и Blueprint выполните инициализацию плагина, используя метод Init.

Вызов метода Init
URuStoreRemoteConfigClient::Instance()->Init();

Все операции с объектом URuStorePushClient также доступны из Blueprints. Ниже преставлен пример инициализации.

img

Деинициализация

Вызов метода Init для URuStoreRemoteConfigClient привязывает объект к корню сцены. Если дальнейшая работа с объектом больше не планируется, для освобождения памяти необходимо выполнить метод Dispose. Вызов Dispose отвяжет объект от корня и безопасно завершит все отправленные запросы.

Вызов метода Dispose
URuStoreRemoteConfigClient::Instance()->Dispose();
img

Опциональные параметры инициализации

Установить опциональные параметры инициализации можно через интерфейс RemoteConfigClientParameters.

Интерфейс RemoteConfigClientParameters
public interface RemoteConfigClientParameters {
String getAppBuild();
String getAppVersion();
String getDeviceId();
String getDeviceModel();
String getEnvironment();
String getOsVersion();
}

Через методы setAccount и setLanguage можно установить дополнительные параметры, которые могут быть использованы для получения конкретной конфигурации.

Методы setAccount и setLanguage могут быть вызваны в любое время.

Инициализация с опциональными параметрами
public final String APP_ID = "a83c91d3-21b4-4891-841e-0ed0fc39a562";
public final int UPDATE_TIME = 15;
public final String UPDATE_BEHAVIOUR = "Actual";
public final String ACCOUNT = "MyAccount";
public final String LANGUAGE = "ru";

RemoteConfigClientParametersImpl parameters;

/* Ваша инициализация parameters */

RuStoreUnityRemoteConfigClient.INSTANCE.setAccount(ACCOUNT);
RuStoreUnityRemoteConfigClient.INSTANCE.setLanguage(LANGUAGE);
RuStoreUnityRemoteConfigClient.INSTANCE.init(APP_ID, UPDATE_TIME, UPDATE_BEHAVIOUR, parameters, null, getApplicationContext());
ПараметрОписание
OsVersionУсловие в конфигураторе: Os Version
Позволят сравнивать OsVersion со значением, установленным в интерфейсе. По умолчанию OsVersion не передается, в этом случае возвращается конфиг по умолчанию.
DeviceModelУсловие в конфигураторе: Device Model
Позволят сравнивать DeviceModel со значением, установленным в интерфейсе. По умолчанию DeviceModel не передается, у этом случае возвращается конфиг по умолчанию.
LanguageУсловие в конфигураторе: Language
Позволят сравнивать Language со значением, установленным в интерфейсе. По умолчанию Language не передается, у этом случае возвращается конфиг по умолчанию.
Для передачи Language необходимо реализовать ConfigRequestParameterProvider.
AccountУсловие в конфигураторе: Account
Позволят сравнивать account со значением, установленным в интерфейсе.
Условие в конфигураторе: Account Percentile
Позволят раздавать конфиг по значению account на определенный процент.
Условие в конфигураторе: Interval Account Percentile
Позволят раздавать конфиг по значению account на определенный процент и в определенный день.
Для передачи Account необходимо реализовать ConfigRequestParameterProvider.
DeviceIdУсловие в конфигураторе: DeviceID
Позволят сравнивать DeviceId со значением, установленным в интерфейсе.
Условие в конфигураторе: DeviceID Percentile
Позволят раздавать конфиг по значению DeviceId на определенный процент.
Условие в конфигураторе: Interval DeviceID Percentile
Позволят раздавать конфиг по значению DeviceId на определенный процент и в определенный день.
AppVersionУсловие в конфигураторе: App Version
Позволят сравнивать AppVersion со значением, установленным в интерфейсе.
EnvironmentУсловие в конфигураторе: App Environment
Позволят сравнивать Environment со значением, установленным в интерфейсе
Environment может принимать значения: Alpha, Beta, Release.
Этот параметр удобно использовать для тестирования конфигурации на различных сборках приложения.
AppBuildУсловие в конфигураторе: App Build
Позволят сравнивать AppBuild со значением, установленным в интерфейсе.

ConfigRequestParameterProvider

Реализация ConfigRequestParameterProvider дает возможность динамически передавать параметры на сервер для синхронизации конфигурации.

Поддерживаемый список параметров: Language и Account.

Инициализация

Для доступа к методам ConfigRequestParameterProvider из C++ и Blueprint выполните инициализацию URuStoreConfigRequestParameterProvider, используя метод Init.

URuStoreConfigRequestParameterProvider::Instance()->Init();
img

Деинициализация

Вызов метода Init для URuStoreConfigRequestParameterProvider привязывает объект к корню сцены. Если дальнейшая работа с объектом больше не планируется, для освобождения памяти необходимо выполнить метод Dispose. Вызов Dispose отвяжет объект от корня и безопасно завершит все отправленные запросы.

URuStoreConfigRequestParameterProvider::Instance()->Dispose();
img

Передаваемые параметры

Динамически установить параметры ConfigRequestParameterProvider можно, используя методы SetAccount и SetLanguage.

Вызов методов SetAccount и SetLanguage
URuStoreConfigRequestParameterProvider::Instance()->SetAccount("MyAccount");
URuStoreConfigRequestParameterProvider::Instance()->SetLanguage("ru");
img img

Получить текущие параметры ConfigRequestParameterProvider можно, используя методы GetAccount и GetLanguage.

FString account = URuStoreConfigRequestParameterProvider::Instance()->GetAccount();
FString language = URuStoreConfigRequestParameterProvider::Instance()->GetLanguage();
img img

RemoteConfigClientEventListener

Реализация RemoteConfigClientEventListener дает возможность получать обратные вызовы (callback) о работе SDK, такие как завершение инициализации и обновление постоянного хранилища.

Инициализация

Для доступа к методам RemoteConfigClientEventListener из C++ и Blueprint выполните инициализацию URuStoreConfigRequestParameterProvider, используя метод Init.

URuStoreRemoteConfigClientEventListener::Instance()->Init();

Все операции с объектом URuStoreRemoteConfigClientEventListener также доступны из Blueprints. Ниже преставлен пример инициализации.

img

Деинициализация

Вызов метода Init для URuStoreRemoteConfigClientEventListener привязывает объект к корню сцены. Если дальнейшая работа с объектом больше не планируется, выполните метод Dispose для освобождения памяти. Вызов Dispose отвяжет объект от корня и безопасно завершит все отправленные запросы.

URuStoreRemoteConfigClientEventListener::Instance()->Dispose();
img

Обратные вызовы

Список обратных вызовов (сallbacks).

Подписка на следующие события URuStoreRemoteConfigClientEventListener дает возможность получать обратные вызовы о работе SDK, такие как завершение инициализации и обновление постоянного хранилища и т.п.

  • OnBackgroundJobErrors — возвращает ошибку фоновой работы.
  • OnFirstLoadComplete — вызывается при окончании первой загрузки.
  • OnInitComplete — вызывается при окончании инициализации.
  • OnMemoryCacheUpdated — вызывается при изменении кэша в памяти.
  • OnPersistentStorageUpdated — вызывается при изменении постоянного хранилища.
  • OnRemoteConfigNetworkRequestFailure — вызывается при ошибке сетевого запроса Remote Config.
События URuStoreRemoteConfigClientEventListener
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRemoteConfigClientEventBackgroundJobErrorsDelegate, int64, requestId, FString, exception);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventFirstLoadCompleteDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventInitCompleteDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventMemoryCacheUpdatedDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventPersistentStorageUpdatedDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRemoteConfigClientEventRemoteConfigNetworkRequestFailureDelegate, int64, requestId, FString, throwable);

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventBackgroundJobErrorsDelegate OnBackgroundJobErrors;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventFirstLoadCompleteDelegate OnFirstLoadComplete;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventInitCompleteDelegate OnInitComplete;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventMemoryCacheUpdatedDelegate OnMemoryCacheUpdated;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventPersistentStorageUpdatedDelegate OnPersistentStorageUpdated;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventRemoteConfigNetworkRequestFailureDelegate OnRemoteConfigNetworkRequestFailure;
Подписка на событие слушателя
FScriptDelegate OnBackgroundJobErrorsDelegate;
FScriptDelegate OnFirstLoadCompleteDelegate;
FScriptDelegate OnInitCompleteDelegate;
FScriptDelegate OnMemoryCacheUpdatedDelegate;
FScriptDelegate OnPersistentStorageUpdatedDelegate;
FScriptDelegate OnRemoteConfigNetworkRequestFailureDelegate;

Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnBackgroundJobErrorsCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnFirstLoadCompleteCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnInitCompleteCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnMemoryCacheUpdatedCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnPersistentStorageUpdatedCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnRemoteConfigNetworkRequestFailureCallback"));

URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnBackgroundJobErrorsCallbackDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnFirstLoadCompleteDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnInitCompleteDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnMemoryCacheUpdatedDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnPersistentStorageUpdatedDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnRemoteConfigNetworkRequestFailureDelegate);
Методы обработчика обратных вызовов
UFUNCTION()
void OnBackgroundJobErrorsCallback(int64 requestId, FString exception) {
// Process callback
}

UFUNCTION()
void OnFirstLoadCompleteCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnInitCompleteCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnMemoryCacheUpdatedCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnPersistentStorageUpdatedCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnRemoteConfigNetworkRequestFailureCallback(int64 requestId, FString throwable) {
// Process callback
}
img

Получение конфигурации

Получение конфигурации происходит через вызов метода GetRemoteConfig.


Каждый запрос GetRemoteConfig возвращает requestId, который уникален в рамках одного запуска приложения. Каждое событие возвращает requestId того запроса, который запустил это событие.

Вызов метода GetRemoteConfig
long requestId = URuStoreRemoteConfigClient::Instance()->GetRemoteConfig(
[](long requestId, TSharedPtr<FURuStoreRemoteConfig, ESPMode::ThreadSafe> response)
// Process success
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • Обратный вызов (callback) Success возвращает структуру FURuStoreRemoteConfig с информацией от текущем наборе данных в параметре Response.

  • Обратный вызов (callback) Failure возвращает структуру FURuStoreError с информацией об ошибке в параметре Error. Все ошибки описаны в разделе Возможные ошибки.

Структура FURuStoreRemoteConfig

Экземпляр FURuStoreRemoteConfig – это текущий набор всех данных, полученных в зависимости от выбранной политики обновления при инициализации. Экземпляр имеет весь набор ключей, которые были переданы с сервера, в зависимости от параметров, указанных при инициализации.

Структура FURuStoreRemoteConfig
USTRUCT(BlueprintType)
struct RUSTOREREMOTECONFIG_API FURuStoreRemoteConfig
{
GENERATED_USTRUCT_BODY()

public:
UPROPERTY(BlueprintReadOnly)
TMap<FString, FString> data;
};

Возможные ошибки

Если вы получили в ответ Failure, не рекомендуется отображать ошибку пользователю. Отображение ошибки может негативно повлиять на пользовательский опыт.

Структура FURuStoreError
USTRUCT(BlueprintType)
struct RUSTORECORE_API FURuStoreError
{
GENERATED_USTRUCT_BODY()

FURuStoreError()
{
name = "";
description = "";
}

UPROPERTY(BlueprintReadOnly)
FString name;

UPROPERTY(BlueprintReadOnly)
FString description;
};
  • name — название ошибки. Содержит имя simpleName класса ошибки.
  • description — сообщение ошибки.
ОшибкаОписание
BackgroundConfigUpdateErrorПоявляется при ошибке в работе фоновой синхронизации.
FailedToReceiveRemoteConfigПоявляется в случае ошибки при вызове метода получения конфигурации.
RemoteConfigCastExceptionПоявляется в случае некорректного получения данных по ключу из класса RemoteConfig. Ошибка может быть связана с невозможностью приведения к типу, либо значение по передаваемому ключу отсутствует.
RemoteConfigClientAlreadyExistПоявляется в случае повторного создания RemoteConfigClient в рамках жизни процесса.
RemoteConfigClientNotCreatedПоявляется в случае доступа к RemoteConfigClient через статическое поле instance до создания RemoteConfigClient.
RemoteConfigCommonExceptionОбщая непредвиденная ошибка.
RemoteConfigNetworkExceptionПоявляется при сетевой ошибке.