Войти
Инди-ЮнитиФорум

Мастер класс по хорошему коду в юнити (26 стр)

Страницы: 123 24 25 26 27 28 Следующая »
#375
23:56, 31 янв. 2021
Уже ночь, а я все обновляю страницу... А посты все появляются.
Продолжайте!

#376
0:08, 1 фев. 2021

Alprog
> Замерь сам, если хочешь.
что не хочется показывать плохие для тебя цифры :)

#377
(Правка: 1:44) 0:49, 1 фев. 2021

УРОК для тех кто не умеет обобщать (таких как Allprog) (подсчитай теперь пользу от своей говно сериализации с 3373 строк кода)

пользуйтесь простыми решениями, а не говно либами :) а уровень обобщения выбирайте под свои задачи вот мой вам главный совет

может еще показать, как обобщить эту одну функцию и на LoadBin+LoadText+SaveBin+SaveText+BinToText+TextToBin ?

Это уже за деньги :)

    public void ToBin()
    {
        // может кому то на любителя, но такое представление много лучше использование аттрибутов,
        // его можно выдернуть куда угодно и поставить под условия, чего нельзя сделать с аттрибутами
        Bin bin = new Bin("test.bin");
        bin.Add<string>(Tag);
        bin.Add<Vector3>(MainPosition);
        bin.AddListValue<Angle, Vector3>(Angles);
        bin.AddDicList<string, int>(History);
    }

public class Bin
{
    BinaryWriter bw;
    public Bin(string argFileName)
    {
        bw = new BinaryWriter(File.Open(argFileName, FileMode.Create));
    }

    public void Add<T>(T argValue)
    {
        bw.Write<T>(argValue); bw.Write("\n");
    }
    public void AddListValue<T, K>(List<T> argValue)
        where T : IValue<K>
    {
        List<T> locList = argValue as List<T>;
        for (int i = 0; i < locList.Count; i++)
        {
            bw.Write<K>(locList[i].Value);
        }
        bw.Write("\n");
    }
    public void AddDicList<T, K>(Dictionary<T, List<K>> argValue)
    {
        Dictionary<T, List<K>> locDic = argValue as Dictionary<T, List<K>>;
        foreach (KeyValuePair<T, List<K>> item in locDic)
        {
            bw.Write<T>(item.Key);
            for (int i = 0; i < item.Value.Count; i++)
            {
                bw.Write<K>(item.Value[i]);
            }
            bw.Write("\n");
        }
        bw.Write("\n");
    }
}

public interface IValue<T>
{
    public T Value { get; set; }
}


[System.Serializable]
public class Angle : IValue<Vector3>
{
    private Vector3 value_;
    public Vector3 Value { get { return value_; } set { value_ = value; } }

    public Angle(Vector3 argAngle)
    {
        Value = argAngle;
    }
}

вот так для обобщения удобнее

    public void ToBin()
    {
        Bin bin = new Bin("test.bin");
        bin.Add(Tag);
        bin.Add(MainPosition);
        bin.AddListValue(Angles, new Angle(Vector3.zero), Vector3.zero);
        bin.AddDicList(History, 1);
    }

проверим всех, это вам дом. задание, кто переделает класс class Bin, чтобы C# допустил синтаксис выше - тот получит звание как минимум мидла :)

#378
(Правка: 2:16) 2:05, 1 фев. 2021

tac
Какой прогресс.

Начал с баз данных:

чего только люди не по навыдумывают, лишь бы не учить базы данных
попробуй напиши зачем тебе сериализация, и почему ты не используешь базы данных, тогда и увидем кто дурачок?
хрень собачья .. учите ну например sqlite на клиенте и не занимайтесь хренью

Спустя 3 года и 25 страниц объяснений, что базы данных не годятся на реальных проектах по целому ряду причин, согласился, что в ряде случаев они не подходят, и начал обсуждать сериализацию.

Сначала, конечно, родил полный гавнокод с конкатенацией через "+" и назвал это оптимальным и быстрым решением.
Со второй попытки исправил "+" на StringBuilder.

На третью попытку ушло несколько страниц. Архитектор с 20+ годами опыта отказывался верить, что текстовая сериализация в разы медленее бинарной, потому что:

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

Когда начали писать тест, всё-таки дошло, что что-то не то, спохватился, и написал бинарную версию. Уже третья попытка только сериализации, даже если забыть прелюдию с базой данных.

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

Заметил, что ты уже 4 раза полностью переписал код, каждый раз усложняя его, но до сих пор даже не приблизился по функциональности к моему примеру? В моём примере обеспечивается и бинарная и текстовая сериализация, а у тебя только бинарная. А это неудобно во время разработки, что мы вроде как, уже с тобой закрепили за предыдущие 20 страниц. Поэтому задание на 5 версию твоего примера: как сделать так, чтобы можно было писать и ToBin() и ToText(), но при этом так, чтобы тебе не пришлось дублировать форматтер для каждого типа. Осилишь? Или будешь дублировать?

Когда справишься, далее пойдут вопросы посложнее. Что, например, случится, если скормить граф с циклическими ссылками в функцию ToBin? Очевидно, он войдёт в бесконечный цикл. Как этого избежать? Писать для каждого места, где есть циклические ссылки, свой ручной код обхода графа и конвертирование в массив? А если таких мест десятки? А если хочется иметь возможность сохранить всю сцену со всеми объектами в любой момент и вообще не думать о том, кто на кого ссылается? Существует ли способ написать это универсально? Generic'ами тут не обойдёшься. Ссылаться может любое поле.

Размышления над всеми этими вопросами рано или поздно заставят тебя ещё раз переписать свой пример. Это будет уже 6-ой раз. Ты сделаешь ещё один шаг на пути от неуча к нормальному программисту.

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

Так или иначе, думаю если с тобой заниматься в этой теме ежедневно, заставляя дорабатывать свой пример, чтобы он удовлетворял требованиям большого проекта, и там при этом не приходилось ради элементарных задач писать сотни строк однотипного кода, то дней через 30 такой практики, ты родишь нам плохонький, неоптимальный по размеру файла, без поддержки распределённых сохранений, но всё-таки сериалайзер, который умеет хотя бы то, что умеет Unity-сериализация. И тогда ты оглянешься на свой велосипед и всё поймёшь.

Ну или ничего этого не будет, а ты просто придумаешь очередную отмазку, почему это всё не нужно.

#379
(Правка: 2:22) 2:16, 1 фев. 2021

p.s. На самом деле никто с тобой заниматься не будет, разумеется. Твои бесконечные переобувания исчерпали мой лимит терпения. Больше я объяснять ничего не буду. Дальше будут только санкции применяться.

#380
(Правка: 2:36) 2:24, 1 фев. 2021

Что силенок мало закрывать тему (второй раз)? Давай бань уже, чтобы видели как ты обсираешься

элементарным обобщением, закрыл весь твой рефлекшен, что бессишся, когда не по твойму? Это от отсутствия своих мозгов, и желания использовать говно лабы ... поколение говнокодеров

Alprog
> Твои бесконечные переобувания
тебе дураку безмозглому показываю, куда должна была идти твоя мысль, если хотел сделать нормальную сериализацию ... оно не мне надо, вспомни :)

отличий не заметил, ну это опять же от отсутствия ... а они существенные, у тебя аттрибуты засрали все ...

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

#381
7:13, 1 фев. 2021

Alprog
> У меня есть быстрая функция сохранения и загрузки сейвов, которая занимает,
> условно 30 мс. Она прекрасно работает. Но ты просишь искусственно ещё добавить
> дорогую операцию перевода в текст, который занимает, условно, 500 мс, и которая
> не используется для сейвов никогда в моём проекте. И вот что мы измеряем в
> итоге? Мою сериализацию сейвов или тот факт, что переводить в текст и обратно -
> это дорого?

а вот тут, действительно, оказывается разница где-то в 10 раз между сохранением текста и бинарным представлением. Это я действительно, не дооценивал. Проверил на своих же примерах.

От разговора с тобой, хоть шерсти клок :)

#382
(Правка: 19:31) 19:17, 1 фев. 2021

Итак, наш нервный друг немного подуспокоился, поэтому подведем итоги.

Был бы приличный человек, давно бы пришли к взаимопониманию, а так сами видите, что происходит когда люди не уважают своих оппонентов.

1. Естественно, важной частью всех игр является умение сохранять состояние ряда объектов.
1.1. Это может применяться в различных подзадачах - как то просто сохранение игры для игрока, различные подсохранения состояний игровых объектов (как то был пример у меня с неким манипулятором, у которого игрок может задать разные программы, и в течении игры их надо запоминать и менять), для диалогов и много где. Основной признак этого - сохранение ряда свойств разных объектов объязательно с выгрузкой на постоянный носитель - в файл или БД (причем БД, тоже может быть файловая). И не будем это путать с клонированием (!).
1.2. Сохранять можно в разных форматах, два из которых наиболее важны - текстовый (как наиболее репрезентативный для разработчика), и бинарный (о котором стоит позаботится, если хочется больше скорости). И иметь возможность их преобразовывать один в другой.
1.3. В случае баз данных в виде хранилища, тут ничего принципиально не меняется - это просто другой физический носитель, и в нем можно так же хранить в разных форматах, только добавляется еще вариант с реляционным форматом. Главное правильно использовать когда это нужно. Когда нужен одновременный доступ к разным объектам - совершенно не правильно использовать файл, т.к. там доступ последовательный, и чтобы добраться к записи состояния манипулятора №2, нужно прочитывать состояние №1 - это не правильно. Вначале можно держать в разных файлах, или в свойствах префабов, часто этого хватает, но лучше внешние данные организовывать в БД, особенно если у вас в игре есть сеть.
2. При том, что задача описанная в п.1., естественно полезная и нужная, очень вредно делать это через т.н. сериализацию, и не будем путать её с записью данных в поток (текстовый или бинарный). Основным признаком современной сериализации, является то, что движки заставляют расставлять атрибуты в классах исходного кода, что совершенно не приемлемо.
2.1. Чисто стилистически атрибуты "заполняют" и смешиваются к кодом, и в этом случае доводится до абсурда использование атрибутов, в то время как атрибуты, в этом случае используются не по назначению с точки зрения ООП (но многих это почему то мало волнует, к сожалению)
2.2. Но главная беда, что такой сериализацией не возможно управлять, она становится статической на все время - все или ничего и только один раз. Можно, это пытаться как то выходить из положения, но как правило это адский трешак. В то время как рано или поздно появляется управляющая логика, которая управляет сохранением состояния объектов. И дело далеко не только в версиях сериализации, а она зависит от бизнес-логики самой игры.

Вывод очевиден, задача хорошая, но делать её надо по другому ... и сей разговор навел меня на мысль, что и в моем проекте не помешал бы нормальный инструмент для этого ...

#383
(Правка: 19:56) 19:55, 1 фев. 2021

А всем все-равно, что у архитектора с 20+ стажем флоаты сериализуются в строку без явного указания CultureInfo? Просто это первое, на чем обычно падает код сериализации / десериализации, запускаемый на разных системных локалях. Этому косяку учатся джуны на своем опыте на первой же неделе-месяце.

#384
(Правка: 20:31) 20:16, 1 фев. 2021

Leopotam
а где ты это увидел? "обычно" CultureInfo устанавливается на старте проекта ... мелко, товарищ

как я понимаю, тут много людей, которые понимаю только резко ... так вот ... я вам идею показываю, а не жопу подтираю (С)
#385
(Правка: 20:33) 20:31, 1 фев. 2021
а где ты это увидел?

В смысле где? Где ты собирал поля через ";", просто вызывая float.ToString("F4") - на разных системных локалях разделители разные, где-то точка, где-то запятая. При переносе сериализованных данных по сети, либо просто при смене локали в локальном профиле пользователя ты уже не сможешь десериализовать данные как было задумано. Про установку культуры - ты делаешь это для каждого треда руками?

Когда мне надоел текст, protobuf нещадно гадил аллокациями из-за иммутабельных классов, а flatbuffers требовал тонны бойлерплейта - пришлось изобрести кастомный сериализатор с поддержкой схем на подобие protobuf: https://github.com/Leopotam/simplebinary
Основное отличие от протобуфа и msgpack-а - простой бинарный формат без излишеств с переносом между платформами, кодоген не руками, на структах с пулингом. Т.е если не строки, то вполне вероятны нулевые аллокации после насыщения пулов.

#386
(Правка: 20:37) 20:34, 1 фев. 2021

Leopotam
> пришлось изобрести кастомный сериализатор с поддержкой схем на подобие
> protobuf: https://github.com/Leopotam/simplebinary
ух, ты ... популярное оказывается велосипедичество :) ну что я буду всех комментировать что-ли? напишу свой, тогда поговорим ...

Дай угадаю, снова сериализаия через аттрибуты?

#387
20:38, 1 фев. 2021
Дай угадаю, снова сериализаия через аттрибуты?

А можно все буквы подряд прочитать - я написал как оно сделано. Если не понятно, то в "README" по ссылке есть подробности с реализациями на разных языках.
#388
(Правка: 20:40) 20:40, 1 фев. 2021

Leopotam
> Про установку культуры - ты делаешь это для каждого
у меня есть т.н. SaveManager - культура устанавливается в его конструкторе? Еще вопросы? Или мне надо это каждому возомнившему себя сеньером, показывать?

#389
(Правка: 20:43) 20:40, 1 фев. 2021

Leopotam
> А можно все буквы подряд прочитать
а можно прямо ответить?

+ по ссылке, я не вижу исходников проекта

Страницы: 123 24 25 26 27 28 Следующая »
Инди-ЮнитиФорум

Тема закрыта.