forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Общие вопросы (http://forum.boolean.name/forumdisplay.php?f=166)
-   -   Проблемы разработки от EvilOkta (http://forum.boolean.name/showthread.php?t=17911)

Randomize 03.11.2019 18:41

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от EvilOkta (Сообщение 316766)
Когда кол-во классов становится большим становится сложно в голове удерживать какие методы они реализуют, интерфейсы наследуют и какими свойствами обладают.

Мне кажется, что тут скорее проблема проектирования и никакие документации не помогут. Стоит посмотреть на SOLID,
как на некий набор общепринятых практик по написанию легко поддерживаемого кода.
Естественно всё и сразу не надо пытаться исполнять, начать можно с "SRP",
а "DI" оставить до лучших времён, когда он действительно тебе будет нужен.

pax 05.11.2019 08:04

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от EvilOkta (Сообщение 316781)
Спасибо ) энтерпрайз дорого (я ж не зарабатываю программированием), идея с partial интересная. Параллельно в Excel заношу публичные методы классов и их сигнатуры, на всякий случай.

Есть полезное окно, в котором всю структуру проекта можно посмотреть. Называется Обозреватель объектов (Вид => Обозреватель объектов). Там все можно подсмотреть. А если есть XML комментарии, то и их можно посмотреть в удобном формате.

Цитата:

Сообщение от Антихрист (Сообщение 316782)
Конкретно к этому примеру - выглядит не очень. В первую очередь за счет цикла с сравнением строк внутри гетера. Добавь одну переменную и закэшируй туда индекс.
PHP код:

protected static readonly string[] Monthes =
        {
            
"января""февраля""марта""апреля""мая""июня""июля""августа""сентября""октября""ноября",
            
"декабря"
        
};

        protected 
byte monthIndex;
        protected 
string monthName;

        protected 
byte MonthIndex
        
{
            
get => monthIndex;
            
set
            
{
                if (
value <= || value 12) return;
                
monthIndex = (byte) (value 1);
                
monthName Monthes[monthIndex];
            }
        }

        protected 
string MonthName => monthName


Вообще хранить название месяца в отдельной переменной не надо. Зачем память тратить. Используй свойство, если есть индекс.
PHP код:

protected string MonthName => Mounthes[monthIndex]; 

или
PHP код:

protected byte monthIndex = -1;
protected 
string MonthName => monthIndex == -null Mounthes[monthIndex]; 


Антихрист 05.11.2019 23:23

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от pax (Сообщение 316786)
Есть полезное окно, в котором всю структуру проекта можно посмотреть. Называется Обозреватель объектов (Вид => Обозреватель объектов). Там все можно подсмотреть. А если есть XML комментарии, то и их можно посмотреть в удобном формате.



Вообще хранить название месяца в отдельной переменной не надо. Зачем память тратить. Используй свойство, если есть индекс.
PHP код:

protected string MonthName => Mounthes[monthIndex]; 


Согласен, если monthIndex не может быть изменен в другом месте выйдя за рамки массива.
Цитата:

PHP код:

protected byte monthIndex = -1;
protected 
string MonthName => monthIndex == -null Mounthes[monthIndex]; 


Вроде С# не позволит впихнуть в byte отрицательное значение.
Как вариант
PHP код:

protected bytemonthIndex null


pax 07.11.2019 20:52

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от Антихрист (Сообщение 316787)
Вроде С# не позволит впихнуть в byte отрицательное значение.
Как вариант
PHP код:

protected bytemonthIndex null


Да, писал прям сюда, поэтому ошибся. Можно sbyte в данном случае использовать.

EvilOkta 07.11.2019 21:48

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от Антихрист (Сообщение 316787)
Согласен, если monthIndex не может быть изменен в другом месте выйдя за рамки массива.

Хорошая идея! Можно сделать, это действительно лучше

Цитата:

Сообщение от pax (Сообщение 316786)
Есть полезное окно, в котором всю структуру проекта можно посмотреть. Называется Обозреватель объектов (Вид => Обозреватель объектов). Там все можно подсмотреть. А если есть XML комментарии, то и их можно посмотреть в удобном формате.

Вот! Как раз таки подобное я искал, спасибо!

Цитата:

Сообщение от Randomize (Сообщение 316783)
Мне кажется, что тут скорее проблема проектирования и никакие документации не помогут. Стоит посмотреть на SOLID,
как на некий набор общепринятых практик по написанию легко поддерживаемого кода.
Естественно всё и сразу не надо пытаться исполнять, начать можно с "SRP",
а "DI" оставить до лучших времён, когда он действительно тебе будет нужен.

SOLID только начал разбираться, но мне уже не понравилось "Каждый класс должен иметь одну и только одну причину для изменений" - у меня в голове это выглядит как огромная куча классов, каждый из который использует единственный публичный метод, который делает что-то. Я больше привык когда класс описывает поведение в заданных рамках, чтобы не нарушать принципа бритвы Оккама.

Чтобы не заниматься ответом на цитаты, вопрос для понимания - в каком формате лучше использовать и хранить БД в Unity?
Или вообще без разницы?
upd конкретизирую вопрос - для проекта нужно подкачивать массивы информации в текстовом виде, в чем их лучше хранить и динамически при необходимости загружать - csv, txt, xml, xls и т.п.?

EvilOkta 31.10.2020 14:45

Ответ: Проблемы разработки от EvilOkta
 
И снова здравствуйте! Понимаю, что людей тут мало осталось, но вдруг кто поможет:
Код:

  private void ResetBoolState(params bool[] ResetState)
    {
        foreach (bool rs in ResetState)
        {
            rs = false;
        }
    }

Такая конструкция не работает, так как IEnumerable не может изменять элемент коллекции. Есть ли варианты чтобы смог?
Задача - передать несколько bool параметров в метод и сбросить их состояния.

Andvrok 31.10.2020 15:06

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от EvilOkta (Сообщение 317853)
И снова здравствуйте! Понимаю, что людей тут мало осталось, но вдруг кто поможет:
Код:

  private void ResetBoolState(params bool[] ResetState)
    {
        foreach (bool rs in ResetState)
        {
            rs = false;
        }
    }

Такая конструкция не работает, так как IEnumerable не может изменять элемент коллекции. Есть ли варианты чтобы смог?
Задача - передать несколько bool параметров в метод и сбросить их состояния.

Никак, чтобы поменять значение примитивного типа вроде bool тебе надо его с ref передавать. А ref не стыкуется с params.

Randomize 31.10.2020 17:45

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от EvilOkta (Сообщение 317853)
Задача - передать несколько bool параметров в метод и сбросить их состояния.

Можно собрать все булы в 1 большой инт.
Примеры тут: https://alemil.com/bitmask

EvilOkta 31.10.2020 17:58

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от Randomize (Сообщение 317855)
Можно собрать все булы в 1 большой инт.
Примеры тут: https://alemil.com/bitmask

Хорошая идея! Возьму на заметку. Я, правда, уже решил задачу, но более топорным способом. Енумы соответствуют названиям булевых переменных в аниматоре
PHP код:

foreach (AnimatorControllerParameter parameter in NPCAnimator.parameters)
        {
            
NPCAnimator.SetBool(parameter.namefalse);
        }
        
NPCAnimator.SetBool(Enum.GetName(typeof(enState), (int)CurrentAnimationState), true); 


EvilOkta 14.11.2020 23:21

Ответ: Проблемы разработки от EvilOkta
 
Созрел новый вопрос.
Есть лист объектов, который заполняется при старте игры.
PHP код:

public static List<GameObjectWorkPoints = new List<GameObject>(); 

На каждом объекте в сцене висит скрипт TableIsBusy с одним и тем же методом IAmBusy()
Есть событие на которое нужно подписать все эти методы с каждого объекта.
Делегат и событие создано, но никак не могу понять как получить имя метода с объекта в листе, для подписки. Копаю в эту сторону, но дает ошибку - явно не так.
PHP код:

foreach (GameObject WorkPlace in GameLogicInit.WorkPoints)
        {
            
PlaceIsBusy += WorkPlace.GetComponent<TableIsBusy>().GetComponent("IAmBusyNow");
        } 

Как все таки правильно такие штуки делать? Интересует, потому что такие списки могут быть сформированы в рантайме и тогда необходимо получать список методов объектов в листе на ходу.

Andvrok 15.11.2020 01:06

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от EvilOkta (Сообщение 317893)
Созрел новый вопрос.
Есть лист объектов, который заполняется при старте игры.
PHP код:

public static List<GameObjectWorkPoints = new List<GameObject>(); 

На каждом объекте в сцене висит скрипт TableIsBusy с одним и тем же методом IAmBusy()
Есть событие на которое нужно подписать все эти методы с каждого объекта.
Делегат и событие создано, но никак не могу понять как получить имя метода с объекта в листе, для подписки. Копаю в эту сторону, но дает ошибку - явно не так.
PHP код:

foreach (GameObject WorkPlace in GameLogicInit.WorkPoints)
        {
            
PlaceIsBusy += WorkPlace.GetComponent<TableIsBusy>().GetComponent("IAmBusyNow");
        } 

Как все таки правильно такие штуки делать? Интересует, потому что такие списки могут быть сформированы в рантайме и тогда необходимо получать список методов объектов в листе на ходу.

Нет юнити под рукой, чтобы проверить, но чисто на сишарпе должно сработать что-то вроде:

PHP код:

PlaceIsBusy += WorkPlace.GetComponent<TableIsBusy>().IAmBusy

В подписку ты должен сам метод передать, а не вызов метода, соответственно без скобок ().
Ну и IAmBusy это же метод, а не тип, как ты его через GetComponent получать собрался?
И конечно же сигнатура метода IAmBusy должна подходить под делегат в твоём событии, но это, я думаю, ты и так понимаешь.

EvilOkta 15.11.2020 02:09

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от Andvrok (Сообщение 317894)
Нет юнити под рукой, чтобы проверить, но чисто на сишарпе должно сработать что-то вроде:

PHP код:

PlaceIsBusy += WorkPlace.GetComponent<TableIsBusy>().IAmBusy

В подписку ты должен сам метод передать, а не вызов метода, соответственно без скобок ().
Ну и IAmBusy это же метод, а не тип, как ты его через GetComponent получать собрался?
И конечно же сигнатура метода IAmBusy должна подходить под делегат в твоём событии, но это, я думаю, ты и так понимаешь.

Да, так заработало, спасибо! Сначала тупанул потому что вызываемый метод был private и соответственно был невидим для эвента.
По поводу EventSystem еще не разбирался что это за зверь такой, надо почитать. Пока тренируюсь на создании делегатов и эвентов, раньше и это было сложно - сейчас проще. Ну и как я понимаю эвенты и подписки создают слабую связность, что тоже хочется закрепить практикой )

Andvrok 15.11.2020 02:31

Ответ: Проблемы разработки от EvilOkta
 
Цитата:

Сообщение от EvilOkta (Сообщение 317896)
Да, так заработало, спасибо! Сначала тупанул потому что вызываемый метод был private и соответственно был невидим для эвента.
По поводу EventSystem еще не разбирался что это за зверь такой, надо почитать. Пока тренируюсь на создании делегатов и эвентов, раньше и это было сложно - сейчас проще. Ну и как я понимаю эвенты и подписки создают слабую связность, что тоже хочется закрепить практикой )

Покури на досуге https://habr.com/ru/post/527418/, может пару идей подкинет. Делегаты и события способ-то рабочий, но слишком «голый» и отчаянно требует сахара для удобств.

EvilOkta 15.11.2020 15:23

Ответ: Проблемы разработки от EvilOkta
 
Кстати по поводу событий и прочего. Я знаю, что плохая практика в Update постоянно проверять кучу состояний для управления объектом, но возник следующий вопрос. Попробую объяснить.
Допустим есть NPC, у него есть методы, отвечающие за различные "действия" - идти, сесть, стоять и т.п. Все эти методы выведены под общую сигнатуру, для того чтобы ими можно было бы управлять через события и т.п.
Но в чем подвох. Например метод "идти" получает точку назначения и включает NavAgent типа так:
PHP код:

NPCPathFinder.SetDestination(Target.transform.position); 

NPC начинает идти к цели - все отлично, но метод Walk по факту исполнен включением SetDestination, хотя NPC продолжает идти (я так и не разобрался, получается НавАгент работает асинхронно?). Допустим следующий метод после достижения цели должен быть "Стоять", и если формировать список методов для исполнения на основе делегата или списка методов, они сработают последовательно, т.е. установка цели -> метод Walk исполнен -> метод "стоять" (хотя NPC не дошел до цели). Это естественно неправильно.
Какие есть способы управления такими последовательностями?
У меня пока в голове только идея сделать какой-то промежуточный менеджер, который в апдейте каждую итерацию (что уже заставляет задуматься) проверяет достиг ли активный метод цели и если да, то активировать следующий в цепочке метод. Это нормальная практика, или костыли?
Надеюсь правильно объяснил задачу.

pax 16.11.2020 19:53

Ответ: Проблемы разработки от EvilOkta
 
Тебе нужно копать в сторону State Machine (машина состояний). В Unity есть встроенная в Animator'е. Её иногда можно приспособить для логики. Вот пример:


Можешь найти готовую машину состояний, на ассет сторе много разного. Поищи например так: https://assetstore.unity.com/?q=Beha...rees&orderBy=1


Часовой пояс GMT +4, время: 08:00.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot