Ответы пользователя по тегу Unity
  • Где учить c# с нуля для игр?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Попробуйте вот такую книгу:
    Изучаем C# через разработку игр на Unity. 5-е издание Ферроне Харрисон
    Учат с нуля, показывают нужные важные вещи, с попыткой учить через Юнити (хотя по мне, лучше учиться с консольными приложениями).

    Если хорошо поискать, можно найти вариант подешевле...
    Ответ написан
  • Unity 2d функция Collider 2D почему не работает?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    >У героя Body Type - Kinematic
    У героя Body Type должен быть Dynamic, иначе физика не заработает. Тип Kinematic - положение объектом полностью управляется скриптом, а не физикой. Значит, если вы хотите использовать физику, то используйте тип Dynamic.

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

    Для начала рекомендую серию из трёх статей (во второй см. комментарий для доработки старого кода в новых версиях юнити)
    Ответ написан
    3 комментария
  • Property и Fields?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Да, при создании автосвойства создаётся скрытая переменная - данные должны где-то храниться.

    Эта переменная создаётся с хитрым именем (с запрещёнными в c# символами в имени переменной). Можно увидеть это таким способом:
    class TestClass
    {
        private int _a;
        public int A
        {
            get { return _a; }
            set { _a = value; }
        }
    
        public int B { get; set; }
    }
    
    var testClass = typeof(TestClass);
    var fields = testClass.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (var fieldInfo in fields)
    {
        Console.WriteLine(fieldInfo.Name);
    }
    // результат:
    // _a
    // <B>k__BackingField
    Ответ написан
    4 комментария
  • Как избежать проблем с Execution Order?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Я в Awake использую инициализацию самого компонента, не используя связи с другими компонентами. А в Start все компоненты уже инициализированы, их можно использовать.

    Компонент A в Start получает ссылку на компонент B. Не факт, что B уже вызвал Start и не имеет нужные ссылки. Тут два варианта
    - B тоже должен иметь ссылку на A. Тогда A может передать себя в B (до вызова B.Start).
    - B должен иметь ссылку на компонент C. Тут могут быть проблемы.

    Чтобы такие связи были независимы от порядка, то каждый компонент в Awake должен поместить себя (зарегистрироваться) в какой-то контейнер, через который в Start в любом компоненте можно получить нужную ссылку.

    Контейнером может быть
    - статическое поле класса (если компонент планируется только один, то получается типа полу-синглтон - поле устанавливается в Awake, а потом используется отовсюду во время Start и после)
    - специальный список в родителе (если компонент не одиночка)
    - IoC-контейнер
    Ответ написан
    4 комментария
  • Как полностью очистить массив?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Возможно, лучше взять список List<int> вместо массива:
    public List<int> checkAddDel;
    
    checkAddDel = new List<int>(Word.Length); // предварительно указывать размер не обязательно, 
                                              // но если известно заранее, то лучше указать
    
    Console.WriteLine(checkAddDel.Count); // 0
    for (var i = 0; i < Word.Length; i++)
    {
        checkAddDel.Add((i + 1) * 10);
    }
    Console.WriteLine(checkAddDel.Count); // размер теперь стал равным Word.Length
    
    // используем список
    DoWork(checkAddDel);
    
    checkAddDel.Clear(); // теперь стал пустым
    Console.WriteLine(checkAddDel.Count); // 0
    Ответ написан
    Комментировать
  • Как создать систему заданий в игре?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Хороший ответ Yegor, добавлю ещё другую таблицу: условия появления заданий - какая задача появляется после какой. Туда же можно добавить другие условия: время, уровень, наличие предметов или наоборот отсутствие (исчез важный предмет - добавить необязательное задание для получения этого предмета заново).
    Ответ написан
    Комментировать
  • Как сделать так, чтобы каждый if выполнался одновременно?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Проверяйте не отдельные клавиши, а сочетания:
    var isLeftPressed = Input.GetButton("LeftArrow");
    var isUpPressed = Input.GetButton("UpArrow");
    var isRightPressed = Input.GetButton("RightArrow");
    var isDownPressed = Input.GetButton("DownArrow");
    if (isUpPressed && isDownPressed && Time.time > timeToFire)
    {
        timeToFire = Time.time + 1 / fireRate;
        Instantiate(fireSphere, firePoint.position, firePoint.rotation);
    }
    Ответ написан
    Комментировать
  • В чём ошибка внутри этого кода?

    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
    Программист, преподаватель
    так и не осознал, что хранится в БД, а что - в 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 комментарий
  • Какой уровень математики нужен в GameDev (Unity, UE4)?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Математика в gamedev нужна в любом случае. Даже если делается маленькая игрушка, то нужно хотя бы понимать, как работает пропорция...
    Но вот вопрос - какой уровень математики нужен в gamedev.
    TL;DR: очень желателен средний уровень (хотя бы уровень 11 класса).
    Долгое объяснение:
    1) Игру можно делать вообще без математики - движок берёт на себя сложную математику. Но чем больше игра, тем больше будет нужно понимание математики - математика может пригодиться при расчёте выстрелов, при расчёте "хитрого" поиска пути, обязательно пригодится в при разработке ИИ, и уж точно пригодится при расчёте баланса (но это работа гейм-дизайнера, а не программиста).
    2) Причём, нужно именно понимание - не столько умение решать типовые задачки, сколько способность анализировать формулы придумывать свои. Например, какую-то фишку можно сделать несколькими способами, и вероятнее всего, более производительным будет тот способ, который лучше использует математику. Помимо обычной математики, может пригодиться геометрия. И уж точно пригодится булева алгебра.
    3) Начиная с восьмого класса, в школе учат не только считать тривиальные задачки, но и развивают так называемое "математическое мышление". Особенно этому учат "задачки со звёздочкой" (более сложные, но необязательные, не знаю, во всех ли учебниках есть такие). Именно математическое мышление позволяет лучше продумывать алгоритмы. (N.B. рекомендую почитать Я.И.Перельмана с его "Занимательной математикой")
    4) ААА-игры делаются не одним-двумя программистами, при разработке ААА-игр программистов используются десятки (а всего разработчиков может быть сотни, от гейм-дизайнеров до композиторов). Все из них не обязательно должны знать математику хорошо. Но если не знать, то вероятность развиться "повыше" - то сложнее.
    5) При некоторых играх математика почти не нужна (при использовании приличного движка), а в некоторых играх математика точно нужна.
    6) Программирование - техническая наука. Да, "гуманитарии" тоже могут стать программистами, но им будет сложнее. Ещё Ломоносов сказал: "Математика ум в порядок приводит" - в нашем классе математики в школе была такая картинка на стене. И я как учитель могу подтвердить эту мысль.

    Итог.
    Можно ли сделать игру без математики? Можно.
    Математика поможет разработке игры? Почти наверняка.
    Хочется развиваться хотя бы до сениора? Учи математику.
    Ответ написан
    Комментировать
  • Как настроить переход одной анимации в другую unity?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Есть отличные три урока создания анимаций:
    Основы создания 2D персонажа в Unity 3D 4.3. Часть 1: заготовка персонажа и анимация покоя
    https://habrahabr.ru/post/211472/ Часть 1: заготовка персонажа и анимация покоя
    habrahabr.ru/post/211847 Часть 2: бегущий персонаж
    habrahabr.ru/post/212309 Часть 3: прыжки (и падения)

    Версия Юнити старая, и кое-что придётся изменить в код - в первую очередь добавить
    переменную-ссылку на ригидбоди и инициализировать в Start():
    private new Rigidbody2D rigidbody2D;
    void Start()
    {
        rigidbody2D = GetComponent<Rigidbody2D>();
    }
    Ответ написан
    1 комментарий
  • Какое разрешений экрана выбрать на Unity3d для Android игрушки?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Ответ написан
    Комментировать
  • Разработка игр с умом?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Рекомендую начать с чего-нибудь попроще, пусть даже клон. Сделайте клон какого-нибудь платформера или Galaxy (или что больше нравится). Это важно, потому что дальше будет слишком много времени будет уходить на сложные задачи по программированию, с которым у вас пока слабо. Когда вы сделаете вашу первую программу, дальше вам будет гораздо проще. Если вы будете хорошо развиваться, то можно попробовать сделать за 2-4 недели, и только потом идти к вашей игре, которую вы хотите делать. Получив какой-то опыт, вам будет легче понять хорошим советам по архитектуре игры.
    Лично у меня есть несколько человек, с которыми я общаюсь и помогаю с программированием. Напишите в скайп, можно начать общение.
    Ответ написан
    7 комментариев
  • Где ошибка в коде?

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

    [TelepatMode On]
    Думаю, код урока старый, а версия Юнити новая. В новой версии Юнити отсутствуют свойства transform, rigidbody2d и некоторые другие, их убрали для оптимизации. Создайте их сами и установите их, например, так:
    public class PlayerScript : MonoBehaviour
    {
        private Rigidbody2d _rigidbody2d;
    
        private void Start()
        {
            _rigidbody2d = GetComponent<Rigidbody2d>();
        }
    
        // остальной код
    }

    и дальше везде писать _rigidbody2d вместо rigidbody2d.
    Ответ написан
    Комментировать
  • Unity: NullReferenceException: Object reference not set to an instance of an object в чём ошибка?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Я думаю, проблема как раз в том, что у вас разные компоненты у разных объектов - у зомби пытаетесь получить доступ к объекту скрипта жизней, но этот скрипт у персонажа, а не у зомби, поэтому playerHealth = GetComponent(); даст null.

    Вы неправильно пытаетесь связываться с разными объектами. В одном объекте не нужно иметь ссылку на объект другого персонажа. А как же тогда уменьшить жизни? Через событие - у вас есть OnTriggerEnter2D - вот в нём есть ссылка на тот объект, с которым только что столкнулся, вот в нём и нужно выбивать жизни:
    void OnTriggerEnter2D(Collider2D col)
    {
        if (col.gameObject.name == "Character")
        {
            var pers = col.gameObject.GetComponent<HealthCharacter>();
            if (pers != null)
            {
                pers.TakeDamage(attackDamage);
            }
        }
    }

    И не надо проверять объект по его имени (я имею в виду код if (col.gameObject.name == "Character") ), в Юнити есть прекрасная штука - теги. Создайте тег Enemy и тег Hero (или как у вас там персонаж называется), и вот по ним проверяйте - с ним столкнулся, или нет.
    Ответ написан
  • Как правильно инициализировать данные в Unity C#?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Это как раз тот случай, когда ваш код нужно писать в Awake(), а не в Start(). Awake() запускается сразу после запуска игры (для каждого объекта), потом происходит первоначальная настройка всех объектов, и после этого запускается Start() (опять же - для каждого объекта). Юнити не указывает, в каком порядке будут инициализированы объекты сцены. Поэтому, в Awake() пишите код, связанный с этим самим объектом, а код, связанный с другими объектами, пишите в Start().
    Ответ написан
    3 комментария
  • Создание игры на IOS в unity3d без мака?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Unity Cloud Build поддерживает сборку для iOS. Но пока доступна для Pro-пользователей.
    https://unity3d.com/ru/unity/cloud-build
    Ответ написан
    Комментировать
  • Как рисовать простые векторные 2D фигуры в Unity3D для GUI?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Используйте NGUI.
    Версия 2 доступна бесплатно, работает хорошо. Скачать можно вот отсюда, в разделе Free Version.
    Или дождитесь выхода Unity4.6, там они делают свою новую систему GUI по типу NGUI. Думаю, за лето выпустят. А если всё-таки не успеют выпустить в версии 4.*, то в пятой точно должны выпустить.
    Ответ написан
  • Какими средствами в Unity3d 4.5 можно создать "землю"для 2d игры (вид сверху)?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Создайте спрайт и подложите его под ваши игровые объекты - для этого нужно увеличить координату z. Поставьте побольше, не ошибётесь (не 1-2, а смело ставьте сотню), чтобы потом можно было между объектами первого плана (z=0) и землёй можно было расположить ещё объекты.
    Но скорее всего, у вас будет не один спрайт для земли, а несколько.
    Лучше сделать в иерархии пустой объект, назвать его Ground и в него уже вкладывать объекты (спрайты) земли (их же будет несколько, очевидно). Это нужно для организации объектов на сцене, чтобы объекты разного назначения не путались друг с другом в общем списке. Тогда координату z нужно устанавливать у этого объекта Ground, а внутренние уже не важно, какой z имеют.
    Скорее всего, у вас будут отдельные спрайты для земли, не имеющие никакого взаимодействия с игровыми объектами (персонажем, врагами, бонусами, или что там у вас), и будут интерактивные объекты - мобы, здания, персонаж. Вот на последние и надо размещать ваши скрипты.
    Ответ написан