• Есть ли большой туториал для изучения С# desktop + DB?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Лучшей книгой для вас будет Эндрю Троелсен "Язык программирования C# 6.0 и платформа .NET 4.6".
    Прекрасная книга для профессионалов, рассказывает обо всём в языке и почти обо всех возможностях и использованиях. В первую очередь, предназначена для программистов, которые уже умеют программировать, но не знают язык C#. В ей всё структурировано на разделы, каждый из них можно читать независимо и использовать как справочник.
    У этой книги есть только один недостаток - написана для профессионалов, и автор пишет, как делать, но не пишет, почему так делать - вы и так уже это понимаете, иначе книга стала бы совсем уж гигантской.

    Рекомендую взять время и попробовать написать несколько консольных программ на c#, начиная с моего любимого решателя квадратных уравнений :) и работы со списками (простой телефонный справочник). И только после этого начинайте работать с WPF.

    А вот очень приличный учебник по wpf:
    https://professorweb.ru/my/WPF/base_WPF/level1/inf...
    Довольно суховато написано, но с неплохими примерами.

    И опять же, рекомендую не начинать делать вашу программу, а сделать с помощью WPF те же программы, которые написали с консолью. И освойтё MVVM.
    Ответ написан
    1 комментарий
  • Почему HttpClient.GetAsync некорректно использует ссылку с символом "#"?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    После символа # указывается локальный фрагмент (или якорь) страницы - элемент внутри страницы, который использует браузер для навигации по странице. Также используется для локальных (клиентских) настроек страницы.
    В вашем случае, после # указан тип сортировки p1_name_asc - сортировать таблицу по имени по увеличению. Например, чтобы сортировать по уменьшению, можно поставить тип p1_name_desc.
    Проблема в том, что сортировка происходит в браузере, а не на сервере (сервер вообще не увидит эту часть адреса).
    Если нужно получить список именно так, как указано в ссылке, то вы тоже должны сортировать результат после получения списка.
    Ответ написан
    Комментировать
  • Какой паттерн лучше использовать при необходимости реализации методов из разных классов?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Композиция, а не наследование.
    D реализует IM1 и IM2, но не наследуется от классов A, B, C.
    class D : IM1, IM2
    {
        B _b;
        C _c;
        public D(B b, C c)
        {
            _b = b;
            _c = c;
        }
    
        public void M1()
        {
            _b.M1();
        }
    
        public void M2()
        {
            _c.M2();
        }
    }
    Ответ написан
    Комментировать
  • Каким образом организовать поиск по сайту на Symfony?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    1) использовать один из движков поиска (sphinx, ElasticSearch). Есть готовые бандлы, помогающие использовать эти движки в symfony-проекте.
    2) либо сделать самому кучу поисков по нужным сущностям, можно сделать UNION запрос:
    SELECT id, title, 'article' as `type` FROM Article WHERE ...
    UNION SELECT id, title, 'news' as `type` FROM News WHERE ...
    UNION SELECT id, title, 'post' as `type` FROM Post WHERE ...

    да, второй способ без индексирования. Зато простой :), если поиск нужен "для галочки". Если нужен нормальный поиск с хорошей произодительностью, то используй первый способ.
    Ответ написан
    1 комментарий
  • Как решит ошибку при выводе любых данных через команду echo или print_r в контроллере?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Не используйте echo и print_r, используйте dump(). Результат будет не в html ответа, а в консоли отладчика (панельке внизу страницы).
    Если сильно нужно использовать именно echo, то можно использовать буферизацию вывода (скорее всего, можно просто поставить ob_start() перед выводом echo).
    Ответ написан
  • Как проще округлить три числа подряд, не используя итерацию, на C#?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Без цикла только так, как вы сказали (с вариантами в виде создания временных переменных с результатами). Иначе нужен цикл. Но цикл может быть внутри какой-нибудь функции, например, в string.Join. И то, всё равно придётся вручную поместить данные в массив.
    double a = 10.123, b = 20.234, c = 30.345;
    Console.WriteLine(Math.Round(a, 2) + " " + Math.Round(b, 2) + " " + Math.Round(c, 2));
    Console.WriteLine(string.Join(" ", new []{a, b, c}.Select(x => x.ToString("F2"))));


    Ещё можно попробовать изгальнуться - поместить данные в поля и получить список полей через рефлексию.
    Ответ написан
    2 комментария
  • Как использовать объект из другого метода в консольном приложении C#?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Обратиться к объекту можно обратиться только по ссылке на него. Если есть ссылка - можно использовать.
    Ссылка на объект port1 сохранена в локальной переменной метода Data. После окончания вызова этого метода, все локальные переменные исчезают. Чтобы обратиться на этот объект из другого метода, есть несколько способов:
    1) сохранить ссылку в поле класса, а не в локальную переменную. Доступ к полям есть во всех методах класса (кроме статических).
    2) если второй метод вызывается из первого, то во второй метод можно передать ссылку аргументом. У вас второй метод не вызывается из метода Data, в этом случае, так не получится использовать.
    3) сам объект может передать ссылку на себя другим объектам, тогда те смогут его использовать (это как раз у вас и происходит, как и сказал Петр)

    Обратите внимание, что если бы вы не сделали добавление обработчика события, то после завершения вызова метода Data, не оставалось бы ни одной ссылки на этот объект, и сборщик мусора (GarbageCollector, GC) отметил бы его мусором и удалил бы его (раньше или позже). А раз вы сделали обработчик события, то этот объект не является мусором (он используется другим объектом). Мусором он станет, когда вы удалите обработчик события.

    Каким способом передавать ссылку лучше всего? В зависимости от контекста (т.е. от способа использования этого объекта):
    1) если вы создали временный объект, который вы использовали и больше не нужен, то передавайте ссылку на него аргументами при вызове методов, его используемых. Когда объект больше не нужен, GC быстро и безболезненно удалит его.
    2) если вы создали постоянный объект, который должен работать какое-то время после окончания метода, в котором объект создан, то нужно положить ссылку на него в поле класса (или в список, или ещё куда-нибудь). Пока есть ссылка, остаётся объект. Когда он уже не нужен, то нужно удалить ссылку на него (присвоить в поле null или новую ссылку, удалить из списка и пр.). Не забывайте обнулять ссылки на не нужные объекты!
    3) Можно использовать косвенные ссылки (например, обработчики события), но это обычно неудобно - не ясно, когда исчезнут ссылки на объект, а в некоторых случаях, удалить обработчик уже не получится (опять же, это сложно сделать без ссылки). Подобные вещи - места для трудноуловимых багов. Поэтому, лучше использовать способы 1 или 2.
    Ответ написан
    Комментировать
  • Как заменить switch case паттерном стратегия?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Switch
    public enum DamageType { Melee, Range, Magic }
    public class Monster
    {
        public double Health { get; private set; }
        public double MeleeDamage { get; private set; }
        public double RangeDamage { get; private set; }
        public double MagicDamage { get; private set; }
        public DamageType FavoriteDamageType { get; private set; }
    
        public Monster(double health, double meleeDamage, double rangeDamage, double magicDamage, DamageType favoriteDamageType)
        {
            Health = health;
            MeleeDamage = meleeDamage;
            RangeDamage = rangeDamage;
            MagicDamage = magicDamage;
            FavoriteDamageType = favoriteDamageType;
        }
    
        public void AttackTo(Monster monster, DamageType damageType)
        {
            switch (damageType) // используется switch
            {
                case MonsterType.Melee: monster.Health -= MeleeDamage; break;
                case MonsterType.Range: monster.Health -= RangeDamage; break;
                case MonsterType.Magic: monster.Health -= MagicDamage; break;
            }
        }
    
        public void AttackTo(Monster monster)
        {
            AttackTo(monster, FavoriteDamageType);
        }
    }


    То же самое, но со стратегией
    public class Monster
    {
        public double Health { get; set; }
        public double MeleeDamage { get; private set; }
        public double RangeDamage { get; private set; }
        public double MagicDamage { get; private set; }
        public IDamageStrategy FavoriteDamageStrategy { get; private set; }
    
        public Monster(double health, double meleeDamage, double rangeDamage, double magicDamage, IDamageStrategy favoriteDamageStrategy)
        {
            Health = health;
            MeleeDamage = meleeDamage;
            RangeDamage = rangeDamage;
            MagicDamage = magicDamage;
            FavoriteDamageStrategy = favoriteDamageStrategy;
        }
    
        public void AttackTo(Monster monster, IDamageStrategy damageStrategy)
        {
            damageStrategy.Attack(this, monster); // не используется switch
        }
    
        public void AttackTo(Monster monster)
        {
            AttackTo(monster, FavoriteDamageStrategy);
        }
    }
    
    
    public interface IDamageStrategy
    {
        void Attack(Monster attacker, Monster defender);
    }
    public class MeleeDamageStrategy : IDamageStrategy 
    {
        public void Attack(Monster attacker, Monster defender)
        {
            defender.Health -= attacker.MeleeDamage;
        }
    }
    public class RangeDamageStrategy : IDamageStrategy 
    {
        public void Attack(Monster attacker, Monster defender)
        {
            defender.Health -= attacker.RangeDamage;
        }
    }
    public class MagicDamageStrategy : IDamageStrategy 
    {
        public void Attack(Monster attacker, Monster defender)
        {
            defender.Health -= attacker.MagicDamage;
        }
    }

    Отличие класса Monster только в коде первого метода AttackTo. Ну и свойства FavoriteDamageType или FavoriteDamageStrategy.

    Стратегия может быть полезна, если код атаки, в зависимости от типа, сильно отличается, используя внешние данные (не из класса монстра), например, день или ночь, ясно/дождь и пр. Использование стратегии переносит часть кода из класса монстра (и так сложного класса) в несколько простых классов.
    Ответ написан
    1 комментарий
  • Как сделать фильтрацию .where() в Immediate Window?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Сделайте метод, в котором фильтруйте циклом, а не Linq-запросом.
    Ответ написан
    Комментировать
  • Анимация кометы по орбите, как реализовать?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Посмотрите статью Павло Пономаренко Солнечная система на LibCanvas? в комментах есть версия на флэше, на Fabric.js, на canvas без библиотек (правильная ссылка), CSS-only и даже на Silverlight :)
    Ответ написан
    Комментировать
  • Wpf listview: как обновить только один элемент его?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    1) Список моделей хранить в ObservableCollection,
    2) В классе модели реализовать интерфейс INotifyPropertyChanged (можно сделать это в базовом классе)
    3) В свойствах модели в сеттере вбрасывать событие PropertyChanged с именем свойства:
    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name != value)
            {
                _name= value;
                RaisePropertyChanged(nameof(Name));
            }
        }
    }
    
    // можно сделать в базовом классе, в котором и реализовать интерфейс INotifyPropertyChanged
    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    Ответ написан
    Комментировать
  • Как правильно открыть окно в другом приложении?

    lexxpavlov
    @lexxpavlov Автор вопроса
    Программист, преподаватель
    В описании функции SetForegroundWindow написаны условия, когда эта функция работает. В некоторых случаях почему-то в другое окно не передаётся клавиатурный фокус. Точнее, второй процесс, который открывает окно, не имеет фокуса. Почему-то в некоторых случаях это не мешает ему открывать активное окно (видимо, одно из других условий срабатывает), но в некоторых - не может сделать окно активным.

    Решение - симулировать нажатие клавиши в процессе, который будет открывать окно:
    private const byte VK_LMENU = 0xA4;
    private const byte KEYEVENTF_EXTENDEDKEY = 0x01;
    private const byte KEYEVENTF_KEYUP = 0x02;
    private const byte KEYSCAN_LALT = 0xB8;
    
    [DllImport("user32.dll")]
    internal static extern bool SetForegroundWindow(IntPtr hwnd);
    [DllImport("user32.dll")]
    private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
    
    public static void BringWindowToFront(IntPtr hwnd)
    {
        // симуляция нажатия клавиши ALT https://stackoverflow.com/a/13881647/1343405
        keybd_event(VK_LMENU, KEYSCAN_LALT, 0, 0);
        keybd_event(VK_LMENU, KEYSCAN_LALT, KEYEVENTF_KEYUP, 0);
    
        SetForegroundWindow(hwnd);
    }


    Полезные ссылки: вопрос, статья.
    Ответ написан
    Комментировать
  • В чём ошибка внутри этого кода?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    У вас ошибки указаны в сообщениях в студии:

    1) Operator '<' cannot be applied to operand of type 'Vector2' and 'int'
    direction - это Vector2, его нельзя сравнивать с числом. Нужно сравнивать direction.x < 0 или direction.y < 0 (или и то, и другое вместе, как вам нужно).

    2) ; expected
    После if должна быть инструкция, закончившаяся ; (или в фигурных скобках). У вас этого нет.

    И прислушайтесь советов Denis Gaydak!
    Если ещё можно написать такой код, как вы сделали, (хотя вы и не сделали :) ), то изменять его уже не получится - дольше времени разбираться с ним, чем исправлять.
    Сделайте такие методы: ProcessTouch(Touch touch), MoveFigureBy(int value), RotateFigure(), FallFigure() и их вызывайте в CheckUserInput(). Обратите внимание, что я в старте поместил ссылку на GameScript в переменную GridObject. Это важно, потому что метод FindObjectOfType ресурсоёмкий, а у вас он вызывается несколько раз в каждом Update (то есть, десятки раз в секунду!).

    Я позволил себе предложить вот такой код (я только исправил две ошибки, о которых вы говорили, и сделал рефакторинг):
    GameScript GridObject;
    
    void Start()
    {
    	GridObject = FindObjectOfType<GameScript>();
    }
    
    void Update () 
    {
        CheckUserInput();
    }
    
    void CheckUserInput()
    {
        if (Input.touchCount > 0) ProcessTouch(Input.GetTouch(0));
        if (Input.GetKeyDown(KeyCode.RightArrow)) MoveFigureBy(1);
        if (Input.GetKeyDown(KeyCode.LeftArrow)) MoveFigureBy(-1);
        if (Input.GetKeyDown(KeyCode.UpArrow)) RotateFigure();
        if (Input.GetKeyDown(KeyCode.DownArrow) || Time.time - fall >= fallSpeed) FallFigure();
    }
    
    void ProcessTouch(Touch touch)
    {
        if (touch.phase == TouchPhase.Began)
        {
            previousUnitPosition = new Vector2 (touch.position.x, touch.position.y);
        } else if (touch.phase == TouchPhase.Moved)
        {
            Vector2 touchDeltaPosition = touch.deltaPosition;
            direction = touchDeltaPosition.normalized;
    
            if (Mathf.Abs(touch.position.x - previousUnitPosition.x) >= touchSensitivityHorizontal && direction.x < 0 &&toucht.deltaPosition.y > -10 && touch.deltaPosition.y < 10) // на этой строке ошибка direction < 0
            {
                // что делать???
            }      
        } else if (touch.phase == TouchPhase.Ended)
        {
    
        }
    }
    void MoveFigureBy(int value)
    {
        transform.position += new Vector3(value, 0, 0);
        if (CheckIsValidPosition()) 
        {
            GridObject.UpdateGrid(this);
        } else 
        {
            transform.position += new Vector3(-1 * value, 0, 0);
        }
    }
    void RotateFigure()
    {
    	if (allowRotation) 
        {
            if (limitRotation) 
            {
                if (transform.rotation.eulerAngles.z >= 90) {
                    transform.Rotate(0,0,-90);
                } else 
                {
                    transform.Rotate(0,0,90);
                }
            } else 
            {
                transform.Rotate (0,0,90);
            }
            if(CheckIsValidPosition()) 
            {
                GridObject.UpdateGrid(this);
            } else 
            {
                if (limitRotation) 
                {
                    if (transform.rotation.eulerAngles.z >= 90) 
                    {
                        transform.Rotate(0,0,-90);
                    } else 
                    {
                        transform.Rotate (0,0,90);
                    }
                } else 
                {
                  transform.Rotate (0,0,-90);
                }
            }
        }
    }
    void FallFigure()
    {
        transform.position += new Vector3(0, -1, 0);
            
        fall = Time.time;
    
        if (CheckIsValidPosition()) 
        {
            GridObject.UpdateGrid(this);
        } else 
        {
              transform.position += new Vector3(0, 1, 0);
              GridObject.DeleteRow();
              if (GridObject.CheckIsAboveGrid (this))
              {
                  GridObject.GameOver ();
              }
              enabled = false;
              GridObject.SpawnNextFigure();
        }
    }
    Ответ написан
    Комментировать
  • В чём можно делать конспекты?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Попробуйте MyTetra
    Также посмотрите интересную статью автора Самая нужная программа на свете на хабре.
    Ответ написан
    Комментировать
  • Почему Doctrine не записывает передаваемый ей параметр?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Уберите поле parentId, и всё заработает. Такое поле в БД сделает доктрина сама, при создании связи между таблицами. Можно оставить это поле в сущности, если так хочется, но устанавливать ассоциацию между записями всё равно нужно полем parent.

    Плюс, похоже, у вас ошибка в типе связи в полях parent и division. У вас тип связи OneToOne, то есть, у руководителя может быть только один сотрудник, и в подразделении может быть только один сотрудник. Поставьте тип связи ManyToOne (см. статью).
    Ответ написан
    Комментировать
  • Как правильно называть следующий синтаксис?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    SomeClass obj = new SomeClass();
    Нужно понимать, что происходит в этой строке. В этой строке происходит две вещи:
    1) создаётся экземпляр класса SomeClass и размещается в куче (специальном месте для хранения объектов). Сами экземпляры не имеют собственных имён, только адрес в куче.
    2) объявляется локальная переменная, и в эту переменную присваивается адрес вновь созданного объекта. Имя именно у переменной, а не у объекта!
    Теперь с объектом можно работать по ссылке, например, присваивать поля и свойства и вызывать методы. Может быть несколько разных ссылок на один объект, но одна ссылка не может быть на несколько объектов (в ссылочной переменной - просто конкретный адрес).

    Теперь разберёмся с терминами "экземпляр" и "объект". Экземпляр является объектом, но не все объекты являются экземплярами определённого класса (например, структуры - это объекты, но не экземпляры класса. Чтобы лучше понять это, нужно изучить различие переменных по ссылке и по значению). В языке C# практически всё является объектом (даже примитивные типы могут рассматриваться как объекты). В том числе, и экземпляры класса. Класс можно считать "шаблоном", который указывает правила создания объекта (количество и тип полей в объекте).

    Статические элементы класса не принадлежат ни одному объекту (экземпляру), можно сказать, эти элементы принадлежат самому классу. Поэтому, нельзя обратиться к статическому элементу через переменную экземпляра, но можно обратиться просто по имени элемента в коде метода. В том видеоуроке объяснено неверно.

    главный вопрос, как нужно комментировать эту строку: "my.age = 5"?

    Присвоить значение 5 полю age объекта на который ссылается переменная my (зачеркнутый текст обычно не говорится, но подразумевается). Вместо слова "объекта" можно сказать "экземпляра", это тоже верно (потому что экземпляр - это тоже объект).
    Ответ написан
    5 комментариев
  • Чем реально полезным можно заняться школьнику знающему программирование?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    >Хорошо знаю Си-Шарп и Юнити.
    Ну так в чём дело? Сделайте отличную игру (или не отличную, но свою). Все школьники (и не только школьники) мечтают об этом. Я не шучу, это может стать полезным, (частично) приятным и (есть шанс) прибыльным. А раз вы школьник, то у вас полно свободного времени (не нужно зарабатывать на хлеб).
    Но главное - решить дойти до конца, до релиза, до победы. Например, возьмите любую любимую игру (небольшую) и сделаете клон (возможно, доработать под себя).
    Либо найдите команду разработчиков, которые ищут программиста (вагон таких предложений). Но нужно выбрать хорошую команду (чтобы была похожа на серьёзную).

    Или другой вариант предложил Александр Тер - сделать что-нибудь полезное для общества. Как пример, был подобный случай несколько лет назад.
    Ответ написан
    1 комментарий
  • Как правильно настроить адаптивное изображение по psd макету?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Подобная проблема бывает в случае, когда в зависимости режима просмотра (ширины окна) меняется соотношение сторон - например, в широкоформатном режиме картинка в формате 2:1, а в портретном 1:1 или да же высота больше, чем ширина.
    Для показа такой адаптивной картинки, в идеале нужно подготовить несколько вариантов картинки, для различных режимов просмотра, и показывать нужную картинку в зависимости от media query в css.
    Ответ написан
    2 комментария
  • Как сформировать Excel на основании Json?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Проще всего массив нарядов преобразовать в csv. А потом из csv можно преобразовать в xls с помощью, например, библиотеки EPPlus (простой пример использования).

    Само преобразование лучше произвести в отдельном методе, а не в AjaxTest4(). Лучше даже в отдельном классе, имхо.
    Ответ написан
  • Какие архитектурные подходы выбрать для разработки клиент-серверной игры?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    так и не осознал, что хранится в БД, а что - в RAM ... автоматические системы кеширования/сброса в БД?

    В БД хранится вся информация мира, в текущий момент. Представьте, что сервер внезапно "умер", вся инфа в памяти исчезла, и теперь доступна только та инфа, которая сейчас в БД. Но получить инфу довольно долго, поэтому, используются кэши, иногда - многоуровневые. Если бы БД имела бесконечную скорость работы, то кэш был бы не нужен. Но, к сожалению, кэш необходим. В идеале, в кэше находится вся та же инфа, что и в БД. Но сложнейшая задача - инвалидация кэша (в БД инфа уже изменилась, а в кэше - нет, ещё хуже - в одном кэше тоже изменилась, а в другом - нет). Для того, чтобы потом не собирать баги лопатами, то придётся создавать автоматические системы кеширования/сброса.
    Почитайте статьи "Архитектура высоконагруженных приложений. Масштабирование распределенных систем" (части 1 2) от Badoo.

    Как, собственно, производить синхронизацию клиента и сервера?

    Весь мир только на сервере, у клиента нужны только доступные (видимые) игроку объекты, иначе игроки узнают "лишнюю" инфу (например, в World of Tanks есть способы узнать "невидимые" танки). Но, к сожалению, так обычно не получается. Клиенту приходится знать чуть о большем количестве объектов, для того, чтобы прогнозировать их поведение. Но в космических играх попытаться можно сделать видимость объектов. Вы сказали про сенсоры корабля, эта очень хорошая мысль - объект исчез из сенсора, то пусть клиент удаляет этот объект. Если в дальнейшем объект становится в сенсоре, то пусть об этом сервер сообщит клиенту (или не сообщит, например, корабль включил маскировку, тогда клиент вообще не знает, что "кто-то" есть). Это можно добавить в геймдизайн - если объект попадает в зону сенсора, то сенсор увидит не в тот же миг, а через некоторе время, в зависимости от харакетристик сенсора (но не меньше пинга, хе-хе).
    Почитайте серию статей "Сетевое программирование для разработчиков игр" (части 1 2 3), а также блог 0fps.net (на английском, нет нормального содержания, но есть сильные статьи). Ещё полезнейшая статья "Борьба с читерами в онлайн-играх: 22 «нужно» и «нельзя»".

    создавать на клиенте экземпляр той же симуляции мира, что и на сервере

    На клиенте создавать серверный мир не нужно, но и полностью отделяться тоже не стоит. Часть кода между сервером и клиентом будет общим. И чем больше, тем легче потом разрабатывать и клиент, и сервер. Помните про наследование с полиморфизмом, про общие проекты в решении.
    Сервер не должен ничего знать про Unity3d, да и клиент игровую логику должен делать без использования инструментов Unity (про это ещё говорит TheShock). Так будет гораздо проще в дальнейшем.

    может ли что-нибудь дать использование ASP.NET (возможно core) в качестве основы, или для таких целей его использование бессмысленно?

    ASP.NET не нужен, имхо, он мало пользы может дать игровому серверу. Я бы начал делать сервер на .NET Core (можно и .NET Framework, просто сложнее будет деплоить. Подумайте про Azure).

    Дмитрий Александров предложил про чанки. Мне кажется, что это хорошая мысль. Почитайте статью "Введение в октодеревья", возможно, это решит проблему с длинными расстояниями. Чанки будут нужны, потому что однажды один сервер не сможет "осилить" весь мир, придётся разделять его.
    Ответ написан
    1 комментарий