IgdrasilCore — Основной модуль движка
Обзор
IgdrasilCore — ядро движка Igdrasil. Содержит:
GameObject— базовый класс для всех игровых объектов.- IO — сериализация (бинарная, JSON, YAML, XML) и система управления ассетами через
AssetBundle. - Utils — криптография, хеширование, сжатие данных, CRC/Adler контрольные суммы, случайные числа.
- Editor — атрибуты для интеграции с редактором (инспектор, валидация).
GameObject
Базовый класс, от которого наследуются все игровые объекты.
Основные свойства
public class GameObject
{
public Guid GUID { get; set; } // Уникальный идентификатор
}
Использование
// Создать новый объект с автогенерируемым GUID
var obj = new GameObject();
// Или с заданным GUID
var obj2 = new GameObject(new Guid("..."));
// Сравнение по GUID
if (obj == obj2) { /* ... */ }
Особенности
- Сравнение (
==,!=,Equals) происходит поGUID, а не по ссылке. - Хеш-код основан на
GUID. ToString()возвращает тип и идентификатор:{TypeName 12345678-...}.
Сериализация и AssetBundle
AssetBundle
Контейнер для хранения сериализованных объектов с поддержкой типов, ссылок и иерархических структур.
var bundle = new AssetBundle();
// Сериализовать объект (используется GUID объекта)
var obj = new MyObject();
bundle.Serialize(obj);
// Или с явным GUID
bundle.Serialize(someGuid, obj);
// Получить объект по GUID
var retrieved = bundle[guid];
// Удалить
bundle.Remove(guid);
// Количество блоков
int count = bundle.Length;
Загрузка и сохранение
var bundle = new AssetBundle();
bundle.Serialize(player);
// Использовать сериализатор для преобразования
var serializer = new AssetBundleJsonSerializer(prettyPrint: true);
byte[] data = serializer.Serialize(bundle);
// Сохранить на диск
await File.WriteAllBytesAsync("bundle.json", data);
// Загрузить с диска
byte[] loaded = await File.ReadAllBytesAsync("bundle.json");
var deserializedBundle = serializer.Deserialize(loaded);
Интеграция с пользовательскими типами
public class MyObject : GameObject
{
[SerializableField]
public string Name { get; set; }
[SerializableField]
public int Health { get; set; }
}
// Автоматически регистрируется при сериализации
var bundle = new AssetBundle();
bundle.Serialize(myObject);
Утилиты
Random — Xoroshiro128+
Детерминированный генератор случайных чисел на основе Xoroshiro128+.
// Глобальный экземпляр
var rng = Random.Shared;
// Новый генератор с seed
var rng = new Random(42);
// Случайные числа
ulong ul = rng.NextULong(); // 0 .. ulong.MaxValue
long l = rng.NextLong(); // long.MinValue .. long.MaxValue
float f = rng.NextFloat(); // [0, 1)
int i = rng.NextInt(100); // [0, 100)
// В диапазоне
int range = rng.NextInt(10, 20); // [10, 20)
float fRange = rng.NextFloat(1.5f, 3.5f); // [1.5, 3.5)
// Вероятность
if (rng.NextBool(0.7f)) { /* 70% шанс */ }
// Выбрать случайный элемент
T item = rng.PickRandom(collection);
EncryptionHelper
Шифрование AES, RSA и создание ключей.
// Создать ключ из пароля
byte[] key = EncryptionHelper.AesCreateKey("mypassword");
byte[] iv = EncryptionHelper.AesCreateIV("mypassword");
// Сгенерировать случайный ключ
byte[] randomKey = EncryptionHelper.AesGenerateKey(32); // 32 байта = 256 бит
// Зашифровать и расшифровать
byte[] encrypted = EncryptionHelper.AesEncrypt(dataBytes, key, iv);
byte[] decrypted = EncryptionHelper.AesDecrypt(encrypted, key, iv);
// RSA (асимметричное шифрование)
(byte[] publicKey, byte[] privateKey) = EncryptionHelper.GenerateRsaKey();
byte[] encrypted = EncryptionHelper.RsaEncrypt(data, publicKey);
byte[] decrypted = EncryptionHelper.RsaDecrypt(encrypted, privateKey);
HashHelper
SHA-1/256/384/512 хеширование.
// От строки
string hash1 = HashHelper.GenerateSha1("hello");
string hash256 = HashHelper.GenerateSha256("world");
// От массива байт
byte[] data = Encoding.UTF8.GetBytes("data");
string hash = HashHelper.GenerateSha256(data);
// От потока (файл и т.д.)
using var file = File.OpenRead("largeFile.bin");
string fileHash = HashHelper.GenerateSha256(file);
// CRC и Adler
ushort crc16 = CRC16.Calculate(data);
uint crc32 = CRC32.Calculate(data);
ushort adler16 = Adler16.Calculate(data);
uint adler32 = Adler32.Calculate(data);
CompressionHelper
Сжатие Deflate, GZip, Brotli, LZMA.
byte[] data = Encoding.UTF8.GetBytes("Hello, World!");
// Deflate
byte[] compressed = CompressionHelper.DeflateCompress(data, CompressionLevel.Optimal);
byte[] decompressed = CompressionHelper.DeflateDecompress(compressed);
// GZip
byte[] gzipped = CompressionHelper.GZipCompress(data);
byte[] ungzipped = CompressionHelper.GZipDecompress(gzipped);
// LZMA
byte[] lzmaCompressed = CompressionHelper.LzmaCompress(data);
byte[] lzmaDecompressed = CompressionHelper.LzmaDecompress(lzmaCompressed);
// Асинхронно
byte[] compressedAsync = await CompressionHelper.DeflateCompressAsync(data, CompressionLevel.Optimal);
UID
Генерация уникальных идентификаторов.
// Новый UID
var uid = UID.New();
// Из существующего значения
var uid2 = new UID(12345);
// Конверсия
int value = uid.AsInt;
string str = uid.ToString();
StringUtils
Работа со строками.
// Проверки
bool isEmpty = StringUtils.IsEmpty(str);
bool isNullOrEmpty = StringUtils.IsNullOrEmpty(str);
bool isNumber = StringUtils.IsNumeric(str);
// Преобразования
string upper = StringUtils.ToUpperFirst(str);
string lower = StringUtils.ToLowerFirst(str);
ReflectionUtils
Работа с рефлексией.
// Получить все свойства с атрибутом
var props = ReflectionUtils.GetPropertiesWithAttribute<SerializableFieldAttribute>(obj.GetType());
// Проверить наличие атрибута
bool hasAttr = ReflectionUtils.HasAttribute<MyAttribute>(typeof(MyClass));
// Вызвать метод по имени
object result = ReflectionUtils.InvokeMethod(obj, "MethodName", params);
ComparisonUtils
Сравнение с допуском.
// Сравнить float с допуском
bool equals = ComparisonUtils.NearlyEqual(a, b, 0.0001f);
// Клип в диапазон
int clamped = ComparisonUtils.Clamp(value, min, max);
// Lerp
float interpolated = ComparisonUtils.Lerp(start, end, t);
IO — Форматы сериализации
JSON
var obj = new MyObject { Name = "Test", Health = 100 };
// Сериализовать в JSON
string json = JsonUtils.Serialize(obj);
// Десериализовать из JSON
MyObject loaded = JsonUtils.Deserialize<MyObject>(json);
XML
// Сериализовать в XML
string xml = XmlUtils.Serialize(obj);
// Десериализовать из XML
MyObject loaded = XmlUtils.Deserialize<MyObject>(xml);
YAML
// Сериализовать в YAML
string yaml = YamlUtils.Serialize(obj);
// Десериализовать из YAML
MyObject loaded = YamlUtils.Deserialize<MyObject>(yaml);
Бинарные потоки
Для эффективного сохранения и загрузки больших объёмов данных.
var reader = new BinaryReaderWithEndians(stream);
var writer = new BinaryWriterWithEndians(stream);
// Чтение/запись с контролем порядка байт
int value = reader.ReadInt32(Endianness.BigEndian);
writer.WriteInt32(value, Endianness.LittleEndian);
Editor — Атрибуты
SerializableField
Отмечает поле для сериализации.
public class MyObject : GameObject
{
[SerializableField]
public string Name { get; set; }
[SerializableField]
public int Value { get; set; }
}
ShowInInspector
Отображает поле в редакторском инспекторе.
public class MyObject : GameObject
{
[SerializableField, ShowInInspector]
public float Speed { get; set; }
}
Space / Header
Добавляет визуальные разделители в инспектор.
public class MyObject : GameObject
{
[Space(10)]
[Header("Physics")]
[SerializableField, ShowInInspector]
public float Mass { get; set; }
}
LimitCount
Ограничивает количество элементов в коллекции.
[SerializableField, LimitCount(5)]
public List<GameObject> Children { get; set; }
Иерархия данных — Tree
Древовидная структура для организации данных.
var root = new Tree<string>("root");
// Добавить узлы
root.AddChild("child1");
root.AddChild("child2");
// Получить детей
foreach (var child in root.Children)
{
Console.WriteLine(child.Value);
}
// Навигация
var parent = root.Parent;
var firstChild = root.Children.FirstOrDefault();
Практика и примеры
Полный пример: сохранение и загрузка игрового объекта
// 1. Определить класс объекта
public class Player : GameObject
{
[SerializableField, ShowInInspector]
public string Name { get; set; }
[SerializableField, ShowInInspector]
public int Level { get; set; }
[SerializableField]
public List<string> Inventory { get; set; } = new();
}
// 2. Создать и заполнить
var player = new Player { Name = "Hero", Level = 5 };
player.Inventory.AddRange(new[] { "Sword", "Shield", "Potion" });
// 3. Сохранить в AssetBundle
var bundle = new AssetBundle();
bundle.Serialize(player);
await bundle.SaveAsync("player.igb");
// 4. Загрузить
var loadedBundle = await AssetBundle.LoadAsync("player.igb");
var loadedPlayer = loadedBundle[player.GUID] as Player;
Console.WriteLine($"{loadedPlayer.Name} (Level {loadedPlayer.Level})");
Безопасное хранение с шифрованием
var bundle = new AssetBundle();
bundle.Serialize(sensitiveData);
// Сохранить с шифрованием
byte[] bundleBytes = await bundle.SaveBytesAsync();
byte[] key = EncryptionHelper.AesCreateKey("secretPassword");
byte[] iv = EncryptionHelper.AesCreateIV("secretPassword");
byte[] encrypted = EncryptionHelper.AesEncrypt(bundleBytes, key, iv);
await File.WriteAllBytesAsync("secure.igb", encrypted);
// Восстановить
byte[] encryptedData = await File.ReadAllBytesAsync("secure.igb");
byte[] decrypted = EncryptionHelper.AesDecrypt(encryptedData, key, iv);
var loadedBundle = await AssetBundle.LoadFromBytesAsync(decrypted);
Производительность и рекомендации
- Random.Shared используйте для глобального состояния; создавайте новые экземпляры для независимых потоков/сценариев.
- AssetBundle идеален для пакетной загрузки; для больших файлов используйте потоковое чтение.
- Сжатие: Deflate/GZip быстрее, LZMA/Brotli сжимают лучше — выбирайте по требованиям.
- Хеширование: SHA256 балансирует безопасность и скорость; SHA512 для критичных данных.
- Криптография: AES для симметричного, RSA для обмена ключами.
© 2026 Igdrasil Project. Все права защищены.