Unity

Unity #

Подключение #

Скачайте актуальный .unitypackage cо страницы релизов на github.com и импортируйте в проект. Для корректной работы необходимо импортироавать все файлы, кроме папки Examples. Ее можно импортировать по желанию. В ней есть сцена с примерами использования.

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

Когда игра загружена — плагин уже проинициализирован. Ничего дополнительно делать не нужно.

Сборка #

Для корректной работы плагина необходимо выбрать соответствующий WebGL Template.

Здесь есть ряд настроек внешнего вида:
Overlay Background Color — цвет фона.
Progress Bar Background Color — цвет фона загрузочной полосы.
Progress Bar Fill Color — цвет самой полосы.
Game Distribution Game ID — ID игры, если публикуете на GameDistribution.
VK Play Game ID — ID игры, если публикуете на VK Play.
Adsgram Block ID — ID рекламного блока, если публикуете в Telegram и используете adsgram.ai.

Цвет задаётся в формате HEX. Например, чёрный — #000000. Для значения по умолчанию нужно поставить знак -.

Чтобы заменить иконку — просто замените файл WebGLTemplates/Bridge/icon.png.

⚠️ Предупреждение
При загрузке файлов на Crazy Games в пункте Game Type нужно выбрать HTML5.

Информация о платформе #

ID платформы #

Bridge.platform.id
Возвращает ID платформы, на которой запущена игра в данный момент. Возможные значения: playgama, crazy_games, game_distribution, yandex, wortal, playdeck, telegram, vk, ok, vk_play, absolute_games, mock.

Язык #

Bridge.platform.language

Если платформа предоставляет данные об языке пользователя — то это будет язык, который установлен у пользователя на платформе. Если не предоставляет — это будет язык браузера пользователя.

Формат: ISO 639-1. Пример: ru, en.

Параметр из адресной строки #

Bridge.platform.payload

С помощью данного параметра можно в ссылку на игру встраивать какую-либо вспомогательную информацию.

Платформа Формат ссылки
Playgama
Crazy Games crazygames.com/game/example?payload=your-info
Game Distribution
Yandex yandex.com/games/play/183100?payload=your-info
Wortal
PlayDeck
Telegram
VK Play
VK vk.com/app8056947#your-info
OK
Absolute Games
Mock site.com/game?payload=your-info

Информация о домене #

Bridge.platform.tld
Если данных нет – null. Если данные есть – com, ru, etc.

Отправка сообщения платформе #

Bridge.platform.SendMessage(PlatformMessage.GameReady);
Сообщение Описание
GameReady Игра загрузилась, все загрузочные экраны прошли, игрок может взаимодействовать с игрой.
InGameLoadingStarted Началась какая-либо загрузка внутри игры. Например, когда идёт загрузка уровня.
InGameLoadingStopped Загрузка внутри игры окончена.
GameplayStarted Начался геймплей. Например, игрок зашёл в уровень с главного меню.
GameplayStopped Геймплей закончился/приостановился. Например, при выходе с уровня в главное меню, открытии меню паузы и т.д.
PlayerGotAchievement Игрок достиг особенного момента. Например, победил босса, установил рекорд и т.д.

Серверное время #

private void Start()
{
    Bridge.platform.GetServerTime(OnGetServerTimeCompleted);
}

private void OnGetServerTimeCompleted(DateTime? result)
{
    if (result.HasValue)
    {
        Debug.Log(result.Value);
    }
}

Информация о девайсе #

Тип девайса #

Bridge.device.type
Возвращает тип девайса, с которого пользователь запустил игру. Возможные значения: mobile, tablet, desktop, tv.

Информация об игроке #

Поддержка авторизации #

Bridge.player.isAuthorizationSupported
Возможные значения: true, false.

Авторизован ли игрок в данный момент #

Bridge.player.isAuthorized
Возможные значения: true, false.

ID игрока #

Bridge.player.id
Если данных нет – null. Если данные есть – данные в формате string.

Имя игрока #

Bridge.player.name
Если данных нет – null. Если данные есть – данные в формате string.

Аватар игрока #

Bridge.player.photos
Возможные значения: пустой массив, массив с ссылками на изображения.

Авторизация игрока #

private void Start() 
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            options.Add("scopes", true);
            break;
    }
    
    Bridge.player.Authorize(options, OnAuthorizePlayerCompleted);
}

private void OnAuthorizePlayerCompleted(bool success) 
{
    if (success) 
    {
        // Игрок успешно авторизован
    }
    else
    {
        // Ошибка, что-то пошло не так
    }
}

Информация об игре #

Текущее состояние видимости #

Bridge.game.visibilityState

Возвращает текущее состояние видимости игры (вкладки с игрой). Возможные значения: visible, hidden.

📝 Примечание
Нужно реагировать на изменение состояния видимости. Например, выключать звук в игре при hidden и включать при visible.
// Изменение состояния видимости можно отслеживать, подписавшись на событие
private void Start()
{
    Bridge.game.visibilityStateChanged += OnGameVisibilityStateChanged;
}

private void OnGameVisibilityStateChanged(VisibilityState state)
{
    switch (state) 
    {
        case VisibilityState.Visible:
            // Вкладка с игрой видима
            break;
        case VisibilityState.Hidden:
            // Вкладка с игрой скрыта
            break;
    }
}

Пользовательские данные #

Есть два типа хранилища: локальное local_storage и внутреннее platform_internal. При записи в локальное — данные сохраняются у игрока на конкретном девайсе, при записи во внутреннее — данные сохраняются на серверах платформы.

Тип хранилища по умолчанию #

Bridge.storage.defaultType
Тип хранилища, который используется по-умолчанию в конкретный момент на конкретной платформе. Возможные значения: local_storage, platform_internal.

Проверка на поддержку #

Bridge.storage.IsSupported(StorageType.LocalStorage)
Bridge.storage.IsSupported(StorageType.PlatformInternal)
Возможные значения: true, false.

Проверка на доступность #

Bridge.storage.IsAvailable(StorageType.LocalStorage)
Bridge.storage.IsAvailable(StorageType.PlatformInternal)
Возможные значения: true, false.

Загрузка данных #

// Получить данные по ключу
private void Start()
{
    Bridge.storage.Get("level", OnStorageGetCompleted);
}

private void OnStorageGetCompleted(bool success, string data)
{
    // Загрузка произошла успешно
    if (success)
    {
        if (data != null) 
        {
            Debug.Log(data);
        }
        else
        {
            // Данных по ключу level нет
        }
    }
    else
    {
        // Ошибка, что-то пошло не так
    }
}

// Получить данные по нескольким ключам
private void Start()
{
    Bridge.storage.Get(new List<string>() { "level", "coins" }, OnStorageGetCompleted);
}

private void OnStorageGetCompleted(bool success, List<string> data)
{
    // Загрузка произошла успешно
    if (success)
    {
        if (data[0] != null)
        {
            Debug.Log($"Level: {data[0]}");
        }
        else
        {
            // Данных по ключу level нет
        }
        
        if (data[1] != null)
        {
            Debug.Log($"Coins: {data[1]}");
        }
        else
        {
            // Данных по ключу coins нет
        }
    }
    else
    {
        // Ошибка, что-то пошло не так
    }
}

// Получить данные из конкретного хранилища
private void Start()
{
    Bridge.storage.Get("level", OnStorageGetCompleted, StorageType.LocalStorage);
}

private void OnStorageGetCompleted(bool success, string data)
{
    // Загрузка произошла успешно
    if (success)
    {
        if (data != null) 
        {
            Debug.Log(data);
        }
        else
        {
            // Данных по ключу level нет
        }
    }
    else
    {
        // Ошибка, что-то пошло не так
    }
}

Сохранение данных #

// Сохранить данные по ключу
private void Start()
{
    Bridge.storage.Set("level", "dungeon_123", OnStorageSetCompleted);
}

private void OnStorageSetCompleted(bool success)
{
    Debug.Log($"OnStorageSetCompleted, success: {success}");
}

// Сохранить данные по нескольким ключам
private void Start()
{
    var keys = new List<string>() { "level", "is_tutorial_completed", "coins" };
    var data = new List<object>() { "dungeon_123", true, 12 };
    Bridge.storage.Set(keys, data, OnStorageSetCompleted);
}

// Сохранить данные в конкретное хранилище
private void Start()
{
    Bridge.storage.Set("level", "dungeon_123", OnStorageSetCompleted, StorageType.LocalStorage);
}

Удаление данных #

// Удалить данные по ключу
private void Start()
{
    Bridge.storage.Delete("level", OnStorageDeleteCompleted);
}

private void OnStorageDeleteCompleted(bool success)
{
    Debug.Log($"OnStorageDeleteCompleted, success: {success}");
}

// Удалить данные по нескольким ключам
private void Start()
{
    var keys = new List<string>() { "level", "is_tutorial_completed", "coins" };
    Bridge.storage.Delete(keys, OnStorageDeleteCompleted);
}

// Удалить данные из конкретного хранилища
private void Start()
{
    Bridge.storage.Delete("level", OnStorageDeleteCompleted, StorageType.LocalStorage);
}

Если при работе с данными не передавать конкретный тип хранилища, то используется тип хранилища по умолчанию Bridge.storage.defaultType.

Bridge.advertisement.isBannerSupported
Возможные значения: true, false.
private void Start()
{
    var options = new Dictionary<string, object>();

    switch (Bridge.platform.id)
    {
        case "vk":
            options.Add("position", "bottom");
            options.Add("layoutType", "resize");
            options.Add("canClose", false);
            break;
    }
    
    Bridge.advertisement.ShowBanner(options);
}
Bridge.advertisement.HideBanner()
Bridge.advertisement.bannerState
Текущее состояние баннера. Возможные значения: loading, shown, hidden, failed.
// Отслеживать изменение состояния можно подписавшись на событие
private void Start()
{
    Bridge.advertisement.bannerStateChanged += OnBannerStateChanged;
}

private void OnBannerStateChanged(BannerState state)
{
    Debug.Log(state);
}
Межстраничная реклама. Обычно показывается в момент загрузки уровня/поражения и т.д.
// Значение по умолчанию = 60 секунд
Bridge.advertisement.minimumDelayBetweenInterstitial
Между показами Interstitial-рекламы нужно соблюдать временные интервалы. Например, Yandex просто не покажет рекламу если вызывать слишком часто, а VK будет показывать так часто, как вызывается метод. Для удобства, в данном SDK есть встроенный механизм таймера между показами. Вам нужно лишь указать нужный интервал и можно дёргать метод показа рекламы сколько угодно.
private void Start() 
{
    // Установить минимальный интервал
    Bridge.advertisement.SetMinimumDelayBetweenInterstitial(30);
}
Bridge.advertisement.interstitialState

Текущее состояние рекламы. Возможные значения: loading, opened, closed, failed.

📝 Примечание
Нужно реагировать на изменение состояния рекламы. Например, выключать звук в игре при opened и включать при closed и failed.
// Отслеживать изменение состояния можно подписавшись на событие
private void Start()
{
    Bridge.advertisement.interstitialStateChanged += OnInterstitialStateChanged;
}

private void OnInterstitialStateChanged(InterstitialState state)
{
    Debug.Log(state);
}
private void Start() 
{
    Bridge.advertisement.ShowInterstitial();
}
Реклама за вознаграждение.
Bridge.advertisement.rewardedState

Текущее состояние рекламы. Возможные значения: loading, opened, closed, rewarded, failed.

📝 Примечание
Нужно реагировать на изменение состояния рекламы. Например, выключать звук в игре при opened и включать при closed и failed.
⚠️ Предупреждение
Награду игроку нужно выдавать только при наступлении состояния rewarded.
// Отслеживать изменение состояния можно подписавшись на событие
private void Start()
{
    Bridge.advertisement.rewardedStateChanged += OnRewardedStateChanged;
}

private void OnRewardedStateChanged(RewardedState state)
{
    Debug.Log(state);
}
Bridge.advertisement.ShowRewarded()
Проверить включен ли блокировщик рекламы.
private void Start()
{
    Bridge.advertisement.CheckAdBlock(OnCheckAdBlockCompleted);
}

private void OnCheckAdBlockCompleted(bool result)
{
    Debug.Log(result); // true or false
}

Социальные взаимодействия #

Поделиться #

Bridge.social.isShareSupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "vk":
            options.Add("link", "https://vk.com/mewton.games");
            break;
    }

    Bridge.social.Share(options, OnShareCompleted);
}

private void OnShareCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Вступить в сообщество #

Bridge.social.isJoinCommunitySupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
            
    switch (Bridge.platform.id)
    {
        case "vk":
            options.Add("groupId", 199747461);
            break;
        case "ok":
            options.Add("groupId", 62984239710374);
            break;
    }
    
    Bridge.social.JoinCommunity(options, OnJoinCommunityCompleted);
}

private void OnJoinCommunityCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Пригласить друзей #

Bridge.social.isInviteFriendsSupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "ok":
            options.Add("text", "Hello World!");
            break;
    }

    Bridge.social.InviteFriends(options, OnInviteFriendsCompleted);
}

private void OnInviteFriendsCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Опубликовать пост #

Bridge.social.isCreatePostSupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "vk":
            options.Add("message", "Hello World!");
            options.Add("attachments", "photo-199747461_457239629");
            break;
        
        case "ok":
            var media = new object[]
            {
                new Dictionary<string, object>
                {
                    { "type", "text" },
                    { "text", "Hello World!" },
                },
                new Dictionary<string, object>
                {
                    { "type", "link" },
                    { "url", "https://apiok.ru" },
                },
                new Dictionary<string, object>
                {
                    { "type", "poll" },
                    { "question", "Do you like our API?" },
                    { 
                        "answers", 
                        new object[]
                        {
                            new Dictionary<string, object>
                            {
                                { "text", "Yes" },
                            },
                            new Dictionary<string, object>
                            {
                                { "text", "No" },
                            }
                        }
                    },
                    { "options", "SingleChoice,AnonymousVoting" },
                },
            };
            
            options.Add("media", media);
            break;
    }

    Bridge.social.CreatePost(options, OnCreatePostCompleted);
}

private void OnCreatePostCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Добавить в избранное #

Bridge.social.isAddToFavoritesSupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    Bridge.social.AddToFavorites(OnAddToFavoritesCompleted);
}

private void OnAddToFavoritesCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Добавить на рабочий стол #

Bridge.social.isAddToHomeScreenSupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    Bridge.social.AddToHomeScreen(OnAddToFavoritesCompleted);
}

private void OnAddToHomeScreenCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Оценить игру #

Bridge.social.isRateSupported

Поддерживается ли функционал на платформе. Возможные значения: true, false.

private void Start()
{
    Bridge.social.Rate(OnRateCompleted);
}

private void OnRateCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}
Bridge.social.isExternalLinksAllowed

Разрешены ли внешние ссылки на платформе. Возможные значения: true, false.

Лидерборды #

Поддержка #

Bridge.leaderboard.isSupported
Возможные значения: true, false.

Нативный popup #

Bridge.leaderboard.isNativePopupSupported

Поддерживается ли нативный popup. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "vk":
            options.Add("userResult", 42);
            options.Add("global", true);
            break;
    }

    Bridge.leaderboard.ShowNativePopup(options, OnShowNativePopupCompleted);
}

private void OnShowNativePopupCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Очки игрока #

Запись #

Bridge.leaderboard.isSetScoreSupported

Поддерживается ли запись очков игрока с клиента. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            options.Add("score", 42);
            options.Add("leaderboardName", "YOUR_LEADERBOARD_NAME");
            break;
    }

    Bridge.leaderboard.SetScore(options, OnSetScoreCompleted);
}

private void OnSetScoreCompleted(bool success)
{
    if (success)
    {
        // Операция прошла успешно
    }
    else
    {
        // Произошла ошибка
    }
}

Чтение #

Bridge.leaderboard.isGetScoreSupported

Поддерживается ли чтение очков игрока. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            options.Add("leaderboardName", "YOUR_LEADERBOARD_NAME");
            break;
    }

    Bridge.leaderboard.GetScore(options, OnGetScoreCompleted);
}

private void OnGetScoreCompleted(bool success, int score)
{
    if (success)
    {
        // Данные успешно получены
        Debug.Log(score);
    }
    else
    {
        // Что-то пошло не так
    }
}

Записи таблицы #

Bridge.leaderboard.isGetEntriesSupported

Поддерживается ли чтение полной таблицы. Возможные значения: true, false.

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            options.Add("leaderboardName", "YOUR_LEADERBOARD_NAME");
            options.Add("includeUser", true);
            options.Add("quantityAround", 10);
            options.Add("quantityTop", 10);
            break;
    }

    Bridge.leaderboard.GetEntries(options, OnGetEntriesCompleted);
}

private void OnGetEntriesCompleted(bool success, List<Dictionary<string, string>> entries)
{
    Debug.Log($"OnGetEntriesCompleted, success: {success}, entries:");
    
    if (success)
    {
        switch (Bridge.platform.id)
        {
            case "yandex":
                foreach (var entry in entries)
                {
                    Debug.Log("ID: " + entry["id"]);
                    Debug.Log("Score: " + entry["score"]);
                    Debug.Log("Rank: " + entry["rank"]);
                    Debug.Log("Name: " + entry["name"]);
                    Debug.Log("Photo: " + entry["photo"]);
                }
                break;
        }
    }
}

Внутриигровые покупки #

Существуют два типа покупок — постоянные (например, отключение рекламы) и расходуемые (например, внутриигровые монеты).

Поддержка #

Bridge.payments.isSupported
Возможные значения: true, false.

Покупка #

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            options.Add("id", "PURCHASE_ID");
            break;
    }
    
    Bridge.payments.Purchase(options, OnPurchaseCompleted);
}

private void OnPurchaseCompleted(bool success)
{
    Debug.Log(success);
}

Расходование #

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            options.Add("purchaseToken", "PURCHASE_TOKEN");
            break;
    }
    
    Bridge.payments.ConsumePurchase(options, OnConsumePurchaseCompleted);
}

private void OnConsumePurchaseCompleted(bool success)
{
    Debug.Log(success);
}

Каталог всех товаров #

private void Start()
{
    Bridge.payments.GetCatalog(OnGetCatalogCompleted);
}

private void OnGetCatalogCompleted(bool success, List<Dictionary<string, string>> catalog)
{
    Debug.Log($"OnGetCatalogCompleted, success: {success}, items:");
                
    if (success)
    {
        switch (Bridge.platform.id)
        {
            case "yandex":
                foreach (var item in catalog)
                {
                    Debug.Log("ID: " + item["id"]);
                    Debug.Log("Title: " + item["title"]);
                    Debug.Log("Description: " + item["description"]);
                    Debug.Log("Image URI: " + item["imageURI"]);
                    Debug.Log("Price: " + item["price"]);
                    Debug.Log("Price Currency Code: " + item["priceCurrencyCode"]);
                    Debug.Log("Price Currency Image: " + item["priceCurrencyImage"]);
                    Debug.Log("Price Value: " + item["priceValue"]);
                }
                break;
        }
    }
}

Список купленных товаров #

private void Start()
{
    Bridge.payments.GetPurchases(OnGetPurchasesCompleted);
}

private void OnGetPurchasesCompleted(bool success, List<Dictionary<string, string>> purchases)
{
    Debug.Log($"OnGetPurchasesCompleted, success: {success}, items:");
    
    if (success)
    {
        switch (Bridge.platform.id)
        {
            case "yandex":
                foreach (var purchase in purchases)
                {
                    Debug.Log("Product ID: " + purchase["productID"]);
                    Debug.Log("Purchase Token: " + purchase["purchaseToken"]);
                }
                break;
        }
    }
}

Удаленная конфигурация #

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

Поддержка #

Bridge.remoteConfig.isSupported
Возможные значения: true, false.

Загрузка значений #

private void Start()
{
    var options = new Dictionary<string, object>();
    
    switch (Bridge.platform.id)
    {
        case "yandex":
            var clientFeatures = new object[]
            {
                new Dictionary<string, object>
                {
                    { "name", "levels" },
                    { "value", "5" },
                }
            };
            
            options.Add("clientFeatures", clientFeatures);
            break;
    }
    
    Bridge.remoteConfig.Get(options, OnRemoteConfigGetCompleted);
}

private void OnRemoteConfigGetCompleted(bool success, List<Dictionary<string, string>> data)
{
    if (success)
    {
        foreach (var keyValuePair in data)
        {
            Debug.Log($"key: { keyValuePair.Key }, value: { keyValuePair.Value }");
        }
    }
}
← Godot Defold →