Unity как шифровать данные в json
Перейти к содержимому

Unity как шифровать данные в json

  • автор:

Защита контента

Пока есть возможность использовать шифрование во время передачи ваших ассетов, пока они не добрались до получателя, у вас всё ещё есть возможность вернуть свой контент обратно. Например, есть инструменты, позволяющие сохранять 3D данные на уровне драйверов, позволяя пользователям извлекать модели и текстуры во время их отправки на обработку вашей видеокартой. С этой целью мы и решили дать возможность вашим пользователям извлекать нужные им ассеты из вашей игры.

Однако, если хотите, вы можете использовать и свой собственный способ шифрования данных для AssetBundle файлов.

Одним из способов добиться этого, является использование TextAsset типа для хранения ваших данных в байтах. Можно зашифровать нужные вам файлы, сохранив их с расширением .bytes, которое Unity будет воспринимать как TextAsset тип. После импортирования в редактор, данные файлы будут включены в ваши AssetBundles как TextAssets и размещены на сервере. Затем на стороне клиента будет скачан нужный AssetBundle, из TextAsset типов файлов которого будут извлечены необходимые клиенту данные. При таком подходе будут шифроваться не сами AssetBundles, а лишь TextAsset файлы, находящиеся в них.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d"; IEnumerator Start () < while (!Caching.ready) yield return null; // Start a download of the encrypted assetbundle WWW www = new WWW.LoadFromCacheOrDownload (url, 1); // Wait for download to complete yield return www; // Load the TextAsset from the AssetBundle TextAsset textAsset = www.assetBundle.Load("EncryptedData", typeof(TextAsset)); // Get the byte data byte[] encryptedData = textAsset.bytes; // Decrypt the AssetBundle data byte[] decryptedData = YourDecryptionMethod(encryptedData); // Use your byte array. The AssetBundle will be cached >

В качестве альтернативы можно полностью зашифровать AssetBundles в хранилище и затем скачать его путём использования WWW класса. До тех пор, пока ваши файлы хранятся на сервере в качестве бинарных данных, они могут иметь любое расширение. Как только нужный AssetBundle будет скачан, вам нужно будет декодировать данные, используя свойство .bytes вашего WWW экземпляра, чтобы получить расшифрованные данные из AssetBundle и воссоздать из памяти AssetBundle, используя AssetBundle.CreateFromMemory.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d"; IEnumerator Start () < // Start a download of the encrypted assetbundle WWW www = new WWW (url); // Wait for download to complete yield return www; // Get the byte data byte[] encryptedData = www.bytes; // Decrypt the AssetBundle data byte[] decryptedData = YourDecryptionMethod(encryptedData); // Create an AssetBundle from the bytes array AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData); yield return acr; AssetBundle bundle = acr.assetBundle; // You can now use your AssetBundle. The AssetBundle is not cached. >

Преимущество второго подхода в сравнении с первым в том, что вы можете использоваться любой метод (кроме AssetBundles.LoadFromCacheOrDownload) для передачи своих байтов и данных в качестве закодированных — например сокеты в плагине. Минусом здесь будет то, что данные не будут кешироваться при использовании автоматического кеширования Unity. Можно добавить любые проигрыватели, кроме WebPlayer-а, который должен быть загружен вручную с вашего жёсткого диска с использованием AssetBundles.CreateFromFile

В качестве третьего способа будет неплохо взять лучшее из двух других, путём хранения самого AssetBundle в качестве TextAsset в других, нормальных AssetBundles. Не закодированный AssetBundle, содержащий в себе закодированный будет кешироваться. Оригинальный AssetBundle может быть затем загружен в память, декодирован и инстанциирован, используяAssetBundle.CreateFromMemory.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d"; IEnumerator Start () < while (!Caching.ready) yield return null; // Start a download of the encrypted assetbundle WWW www = new WWW.LoadFromCacheOrDownload (url, 1); // Wait for download to complete yield return www; // Load the TextAsset from the AssetBundle TextAsset textAsset = www.assetBundle.Load("EncryptedData", typeof(TextAsset)); // Get the byte data byte[] encryptedData = textAsset.bytes; // Decrypt the AssetBundle data byte[] decryptedData = YourDecryptionMethod(encryptedData); // Create an AssetBundle from the bytes array AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData); yield return acr; AssetBundle bundle = acr.assetBundle; // You can now use your AssetBundle. The wrapper AssetBundle is cached >

Проблема с Шифрованием JSON

Author24 — интернет-сервис помощи студентам

Есть две сцены (Меню и игра)
В меню есть скрипт, который сохраняет и загружает игру, обращаясь к скрипту сохранения/загрузки а уже этот обращаеться к скрипту, который это кодирует и декдирует.
Цепь такая: Главный скрипт -> Скрипт Save/Load -> Скрипт шифрования

Так вот всё работает прекрасно, НО на второй сцене (Игре), если вызвать функцию сохранения или загрузки — ничего не произойдёт и если перейти обратно из игры в меню (По UI кнопке), то мне напишет в консоль — «Key Not Exist»

Главный скрипт (Меню) (Так-же и в скрипте, который уже в ИГРЕ находится)

1 2 3
[SerializeField] private ALL_SaveAndLoadFromJSON SaveAndLoad; //Ссылка на скрипт Save/Load SaveAndLoad.Save(); //Сохранение SaveAndLoad.Load(); //Загрузка

Скрипт Save/Load

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
public class ALL_SaveAndLoadFromJSON : MonoBehaviour { [SerializeField] private ALL_AesCryptJSON_Logic aesEncrypt; //Шифрование public Saves saves; public class Saves { //Тут много переменных с данными для сохранения //Например public int Money; public int Score; public bool isMusic; public bool isSound; } //Сохранение в JSON public void Save() { string json = JsonUtility.ToJson(saves); byte[] encryptedBytes = this.aesEncrypt.Encrypt(json); EncryptedGameCoreStruct encryptedGameCore = new EncryptedGameCoreStruct() { data = encryptedBytes, }; string encryptedJson = JsonUtility.ToJson(encryptedGameCore); File.WriteAllText(Path.Combine(Application.persistentDataPath + "/Save.json"), encryptedJson); } //Выгрузка сохранений из JSON public void Load() { string encryptedJson = File.ReadAllText(Application.persistentDataPath + "/Save.json"); byte[] encryptedBytes = JsonUtility.FromJsonEncryptedGameCoreStruct>(encryptedJson).data; string json = aesEncrypt.Decrypt(encryptedBytes); saves = JsonUtility.FromJsonSaves>(json); } }

Скрипт Шифрования

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
public class ALL_AesCryptJSON_Logic : MonoBehaviour { public byte[] Encrypt(string str) { byte[] encryptedBytes; using (Aes aes = Aes.Create()) { aes.GenerateKey(); aes.GenerateIV(); ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { using (StreamWriter sm = new StreamWriter(cs)) { sm.Write(str); } } encryptedBytes = ms.ToArray(); } using (SHA256 sha = SHA256.Create()) { byte[] bytes = sha.ComputeHash(encryptedBytes); string hash = BitConverter.ToString(bytes).Replace(oldValue:"-", newValue:""); AesCryptoParametersStruct c = new AesCryptoParametersStruct { key = aes.Key, iv = aes.IV }; SaveEncryptParameters(c, hash); } } return encryptedBytes; } public string Decrypt(byte[] encryptedBytes) { AesCryptoParametersStruct c = LoadEncryptParameters(encryptedBytes); string decryptedString; using (Aes aes = Aes.Create()) { aes.Key = c.key; aes.IV = c.iv; ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (MemoryStream ms = new MemoryStream(encryptedBytes)) { using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) { using (StreamReader sr = new StreamReader(cs)) { decryptedString = sr.ReadToEnd(); } } } } return decryptedString; } public void SaveEncryptParameters(AesCryptoParametersStruct c, string key) { string json = JsonUtility.ToJson(c); PlayerPrefs.SetString(key, json); } public AesCryptoParametersStruct LoadEncryptParameters(byte[] encryptedBytes) { string key; using (SHA256 sha = SHA256.Create()) { byte[] hash = sha.ComputeHash(encryptedBytes); key = BitConverter.ToString(hash).Replace(oldValue:"-", newValue:""); } if (!PlayerPrefs.HasKey(key)) { throw new PlayerPrefsException(error: "Key Not Exist"); } string json = PlayerPrefs.GetString(key); PlayerPrefs.DeleteKey(key); return JsonUtility.FromJsonAesCryptoParametersStruct>(json); } }

Структура Шифрования

1 2 3 4 5 6 7 8 9 10 11 12 13 14
namespace Structs { [System.Serializable] public struct AesCryptoParametersStruct { public byte[] key; public byte[] iv; } [System.Serializable] public struct EncryptedGameCoreStruct { public byte[] data; } }

Руководство по сериализации и десериализации JSON в Unity с использованием C#

Руководство по сериализации и десериализации JSON в Unity с использованием C#

В современной разработке игр и приложений на Unity, работа с JSON стала обыденностью. JSON (JavaScript Object Notation) – это легковесный формат обмена данными, который легко читается как людьми, так и машинами. В Unity, для работы с JSON предусмотрены встроенные средства, позволяющие сериализовать и десериализовать данные с минимальными усилиями. В этой статье мы подробно разберем процесс сериализации и десериализации JSON и JSON-массивов, используя язык программирования C#.

Содержание показать

Основы JSON в Unity

Прежде чем глубоко погружаться в сериализацию и десериализацию, важно понять, что такое JSON и как он используется в Unity. JSON представляет собой формат, который использует удобочитаемые текстовые строки для представления структурированных данных. В Unity, вы можете представить любой объект как JSON строку и наоборот – преобразовать JSON строку в объект C#.

// Пример JSON строки string json = ""; 

Сериализация объектов в JSON

Сериализация – это процесс преобразования объекта в формат, который может быть сохранен или передан. В контексте JSON, это означает преобразование объектов C# в JSON строки. Unity предоставляет класс JsonUtility , который позволяет легко сериализовать объекты.

using UnityEngine; [System.Serializable] public class Player < public string name; public int level; public float health; >// Сериализация объекта Player в строку JSON Player player = new Player() < name = "Warrior", level = 35, health = 100.0f >; string playerJson = JsonUtility.ToJson(player); Debug.Log(playerJson); 

Десериализация JSON в объекты

Десериализация – это обратный процесс сериализации, когда JSON строка преобразуется обратно в объект C#. Это позволяет вам восстановить объекты из строк JSON, которые могли быть сохранены в файле или получены из веб-сервиса.

// Десериализация строки JSON обратно в объект Player Player deserializedPlayer = JsonUtility.FromJson(playerJson); Debug.Log(deserializedPlayer.name); 

Работа с JSON-массивами

Часто данные приходят в виде массивов JSON, и для работы с ними нужен немного другой подход, поскольку JsonUtility не поддерживает сериализацию и десериализацию массивов напрямую.

[System.Serializable] public class PlayerArray < public Player[] players; >// Десериализация JSON-массива string jsonArray = "<\"players\":[<\"name\":\"Warrior\",\"level\":35,\"health\":100.0>]>"; PlayerArray playerArray = JsonUtility.FromJson(jsonArray); 

Продвинутые техники сериализации

Иногда вам может понадобиться сериализовать более сложные объекты или объекты с приватными полями. В этом случае вы можете использовать библиотеки сторонних разработчиков, такие как Newtonsoft.Json (Json.NET), которые предлагают больше гибкости и функций.

using Newtonsoft.Json; // Сериализация с использованием Json.NET string advancedJson = JsonConvert.SerializeObject(player, Formatting.Indented); Debug.Log(advancedJson); 

Сохранение и загрузка JSON файлов

В Unity, вы можете легко сохранять JSON строки в файлы и загружать их обратно. Это полезно для сохранения состояния игры, настроек или других данных.

using System.IO; // Сохранение JSON в файл File.WriteAllText(Application.persistentDataPath + "/player.json", playerJson); // Загрузка JSON из файла string loadedJson = File.ReadAllText(Application.persistentDataPath + "/player.json"); Player loadedPlayer = JsonUtility.FromJson(loadedJson); 

Обработка ошибок при работе с JSON

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

try < Player errorPlayer = JsonUtility.FromJson(invalidJson); > catch (System.ArgumentException e)

Лучшие практики и советы

При работе с JSON, старайтесь следовать некоторым лучшим практикам:
– Всегда проверяйте ваши JSON строки на валидность перед их использованием.
– Используйте [System.Serializable] атрибут для классов, которые вы хотите сериализовать.
– При необходимости, используйте атрибуты [SerializeField] и [HideInInspector] для управления сериализацией отдельных полей.
– Для более сложной сериализации рассмотрите использование сторонних библиотек, таких как Json.NET.

Читайте так же Обновление интерфейса пользователя из фонового потока в C#

Сериализация и десериализация JSON в Unity – это мощные инструменты для работы с данными. Они позволяют легко сохранять состояние игры, настроек и обмениваться данными между различными системами. Следуя этому руководству и советам, вы сможете эффективно интегрировать JSON в свои проекты на Unity.

Как сделать грамотное сохранение

У меня в игре должно быть сохранение. Я знаю, что есть такая штука как playerprefs, но она позволяет хранить только переменные. У меня генерация деревьев и прочего через скрипт, и при каждом запуске сцены они разные. Неужели, мне нужно будет все объекты сохранять через массивы, чтобы записать положение всех объектов на сцене? Если есть какой нибудь другой путь для сохранения, скажите пожалуйста.

Отслеживать
задан 21 июн 2017 в 9:36
51 1 1 бронзовый знак

Знаю идея бредовая: создавать рядом с игрой фалы.txt записавать туда значения которые нужно сохранить, потом их шифровать и менять разрешенее на допусти файл.gg. Все это не сложно реализовать C# испольховав библиотеку System.IO; Подробнее про работу с файлами — goo.gl/AQAjVu . Вопрос хороший

– user240100
21 июн 2017 в 9:41

А как насчет стартовых значений для генераций ? Ну т.е. раз генерируются деревья, то сделайте стартовое значение известным. И именно его записывать в сэйв. Тогда после загрузки ваш алгоритм для известного стартового значения будет всегда рисовать одну и ту же сцену. Правда тут придется задействовать алгоритмы и математику для того, чтобы для конечного n всегда существовало только единичное значение y (х — стартовое число, y — результат генерации).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *