StaticBatchingUtility.Combine
Позволяет комбайнить меши, которые находятся на GameObject. Довольно удобно, чтобы не ползать по иерархии и не собирать их там.
Есть способ комбинировать меши и без этого:
mesh.CombineMeshes
Но придется передавать туда уже структуры, в которых описываются матрицы и мешки.
Мы такое часто использовали для 3D, когда мы создавали одну мешку и вместо 1к объектов получали всего один. Есстественно, нужно понимать, что батчить нужно по-материально, т.е. какой-то код с этой логикой нужно будет все же написать.
#batching #static #code #api
🔥13❤2👾2
Time.deltaTime vs Time.fixedDeltaTime
Я уже делал пост про FixedUpdate (https://www.tgoop.com/unsafecsharp/103), но не писал про разницу между fixedDeltaTime и deltaTime.
В методе
А вот в
#unityloop #deltatime
Я уже делал пост про FixedUpdate (https://www.tgoop.com/unsafecsharp/103), но не писал про разницу между fixedDeltaTime и deltaTime.
В методе
Update
deltaTime будет равен времени, которое прошло с прошлого кадра, при этом fixedDeltaTime будет равен фиксированной величине.А вот в
FixedUpdate
fixedDeltaTime останется, а вот deltaTime будет равен fixedDeltaTime. Другими словами, можно использовать deltaTime внутри FixedUpdate
.#unityloop #deltatime
Telegram
Unity: Всё, что вы не знали о разработке
Как работает FixedUpdate.
Unity предоставляет нам 3 варианта update: Update, LateUpdate и FixedUpdate.
Update - этот метод вызывается настолько часто, насколько это возможно, проще говоря while (true) { Update(); }. Если включен vsync или установлен target…
Unity предоставляет нам 3 варианта update: Update, LateUpdate и FixedUpdate.
Update - этот метод вызывается настолько часто, насколько это возможно, проще говоря while (true) { Update(); }. Если включен vsync или установлен target…
🥱9🔥6👍2
Нормализация векторов
Это приведение к единичному размеру, при этом направление сохраняется. Обычно мы используем для этого
Но как оно работает внутри? Как нетрудно догадаться из определения нормализации, чтобы привести вектор к единичному - нам нужна его длина, а длина вектора - это корень по теореме Пифагора. Поэтому если вы по какой-то причине уже получили длину вектора, то просто поделите (ну поделите, ага https://www.tgoop.com/unsafecsharp/150):
И получите нормализованный вектор.
А то я часто встречаю примерно такой код в хот частях:
Хотя на деле проще было бы просто получить длину один раз и использовать ее дважды (ну или сделать свой метод для этого).
#vector #normalize #performance
Это приведение к единичному размеру, при этом направление сохраняется. Обычно мы используем для этого
v.normalized
или v.Normalize()
. Второй вариант будет немного быстрее первого, т.к. мы не создаем копию вектора, а изменяем существующий.Но как оно работает внутри? Как нетрудно догадаться из определения нормализации, чтобы привести вектор к единичному - нам нужна его длина, а длина вектора - это корень по теореме Пифагора. Поэтому если вы по какой-то причине уже получили длину вектора, то просто поделите (ну поделите, ага https://www.tgoop.com/unsafecsharp/150):
var inv_length = 1f / length;
v.x *= inv_length;
v.y *= inv_length;
И получите нормализованный вектор.
А то я часто встречаю примерно такой код в хот частях:
var length = v.magnitude;
var n = v.normalized;
Хотя на деле проще было бы просто получить длину один раз и использовать ее дважды (ну или сделать свой метод для этого).
#vector #normalize #performance
👍15🔥7🤔3
Для того, чтобы в инспекторе при отрисовке массива отображались нормальные названия элементов, а не Element 0, Element 1, Element N, можно использовать строку первым полем:
Тогда введенные данные в этот ключ будут отображаться вместо стандартного Element X, что повысит читаемость и поиск, и вам не придется писать дополнительных редакторов для элементов.
#lifehack #arrays #inspector #editor
struct Item {
public string key;
...
}
Тогда введенные данные в этот ключ будут отображаться вместо стандартного Element X, что повысит читаемость и поиск, и вам не придется писать дополнительных редакторов для элементов.
#lifehack #arrays #inspector #editor
🔥19👍7🤯7🥱2
Хранение айдишников
Мы храним SystemInfo.deviceUniqueIdentifier, который вовсе не device id, а advertisement id, т.е. раньше он был айдишником девайса, но потом от их использования отказались в пользу различных авторизаций.
Но мы хотим, чтобы юзер мог играть без авторизации, т.е. юзер должен передать некую уникальную строку.
Когда я разбирал исходники ios, я находил там несколько вариантов этой строки, там был и айди девайса, и мак адрес и всякие другие попытки получить уникальный айди (всего было штук 5, если мне не изменяет память).
Раньше этот айдишник был вполне стабилен, т.к. являлся заводским уникальным айдишником. Сейчас нам дают рекламный айди, который может измениться в любой момент. Самый простой способ - сохранить его в PlayerPrefs, чтобы даже при его изменении со стороны ОС - ничего не менялось для игрока. Естественно, мы предупреждаем, что лучше бы подключить какую-нибудь сеть типа фейсбука, чтобы не потерять прогресс, но это как прочитать readme.
Но люди продолжали жаловаться, что аккаунты теряются, в основном на ios, т.к. именно там рекламные айдишники меняются и меняются часто. Т.е. люди просто удаляли игру и ставили ее заново, прогресс естественно терялся. Чтобы решить эту проблему, мы начали сохранять ключ в Keychain и проблема ушла.
#keychain #ios #deviceid
Мы храним SystemInfo.deviceUniqueIdentifier, который вовсе не device id, а advertisement id, т.е. раньше он был айдишником девайса, но потом от их использования отказались в пользу различных авторизаций.
Но мы хотим, чтобы юзер мог играть без авторизации, т.е. юзер должен передать некую уникальную строку.
Когда я разбирал исходники ios, я находил там несколько вариантов этой строки, там был и айди девайса, и мак адрес и всякие другие попытки получить уникальный айди (всего было штук 5, если мне не изменяет память).
Раньше этот айдишник был вполне стабилен, т.к. являлся заводским уникальным айдишником. Сейчас нам дают рекламный айди, который может измениться в любой момент. Самый простой способ - сохранить его в PlayerPrefs, чтобы даже при его изменении со стороны ОС - ничего не менялось для игрока. Естественно, мы предупреждаем, что лучше бы подключить какую-нибудь сеть типа фейсбука, чтобы не потерять прогресс, но это как прочитать readme.
Но люди продолжали жаловаться, что аккаунты теряются, в основном на ios, т.к. именно там рекламные айдишники меняются и меняются часто. Т.е. люди просто удаляли игру и ставили ее заново, прогресс естественно терялся. Чтобы решить эту проблему, мы начали сохранять ключ в Keychain и проблема ушла.
#keychain #ios #deviceid
👍16🔥5🤷♀2🥴1
Лайвхак при работе с террейном
Когда-то давно мы делали 3D игру (да, такое тоже было, сейчас от нее остались старые исходники и пара видосов на ютубе).
Тогда в ходу были всякие тулзы вроде T4M. Но все подобные штуки работают по принципу раскраски или смешивания. Т.е. есть 4 канала маски, а есть 4 текстуры, там где красный - там тайлится первая текстура, где зеленый - вторая и т.д.
Но существует проблема тайлинга текстур, т.е. когда мы можем отдалить камеру таким образом, чтобы тайлинг стал заметен. Так вот чтобы этот эффект был менее заметен, мы не тайлили первую текстуру в террейне, т.е. она была растянута на всю площадь и обычно это была текстура "миникарты". Таким образом мы получали раскрашенный террейн по всей площади текстурой плохого качества.
После этого мы брали уже другие текстуры и тайлили их поверх той самой текстуры плохого качества, но с прозрачностью процентов 20-40. Таким образом тайлинг был практически незаметен, т.е. каждый тайл блендился со своим практически уникальным кусочком миникарты.
Сегодня используются различные техники при работе с поверхностями начиная от моей любимой «забьем болт» и заканчивая извращениями с шейдерами и дистанцией, но мне все еще нравится способ использовать текстуру плохого качества ;)
#tiling #terrain #lifehack
Когда-то давно мы делали 3D игру (да, такое тоже было, сейчас от нее остались старые исходники и пара видосов на ютубе).
Тогда в ходу были всякие тулзы вроде T4M. Но все подобные штуки работают по принципу раскраски или смешивания. Т.е. есть 4 канала маски, а есть 4 текстуры, там где красный - там тайлится первая текстура, где зеленый - вторая и т.д.
Но существует проблема тайлинга текстур, т.е. когда мы можем отдалить камеру таким образом, чтобы тайлинг стал заметен. Так вот чтобы этот эффект был менее заметен, мы не тайлили первую текстуру в террейне, т.е. она была растянута на всю площадь и обычно это была текстура "миникарты". Таким образом мы получали раскрашенный террейн по всей площади текстурой плохого качества.
После этого мы брали уже другие текстуры и тайлили их поверх той самой текстуры плохого качества, но с прозрачностью процентов 20-40. Таким образом тайлинг был практически незаметен, т.е. каждый тайл блендился со своим практически уникальным кусочком миникарты.
Сегодня используются различные техники при работе с поверхностями начиная от моей любимой «забьем болт» и заканчивая извращениями с шейдерами и дистанцией, но мне все еще нравится способ использовать текстуру плохого качества ;)
#tiling #terrain #lifehack
🔥18👍6
CullingGroup API
В юнити есть замечательная штука, которой мало кто пользуется. На самом деле дает возможность считать отсечение примитивами. На практике я такое часто использую для того, чтобы знать какие объекты нужно просчитывать, а какие - нет. Наверное, это апи можно считать уже устаревшим, т.к. приходят всякие brg, которые умеют в culling, плюс это апи не умеет в burst. Но на самом деле я все равно его использую, т.к. даже на уровне представления оно дает заметный прирост, если самому отключать аниматоры/рендеры и прочие штуки.
https://docs.unity3d.com/Manual/CullingGroupAPI.html
#culling #code #api
👍19🔥10🌭1👻1
Про производительность
Мы знаем, что производительность - это метрика, которую можно оценить по fps или frames per second, т.е. сколько раз мы можем за секунду выполнить всю логику в кадре и отрисовать все, что мы посчитали.
Логика - это все то, что мы пишем в наших методах Update, которые являются частью основного цикла кадра и это обрабатывается на cpu, а вот рендер - это то, что обрабатывает видяха.
В целом эти два процесса никак не связаны, то есть в какой-то момент времени cpu посчитал что-то и готов передать на gpu некие данные, которые будут обрабатываться уже там и как результат - будет картинка. Существуют еще compute shaders, которые по сути используют проц на видяхе, чтобы посчитать результат.
И вот тут нам нужно синхронизировать данные. То есть при использовании синхронизации нам нужно задать фиксированное количество времени, которое мы готовы потратить на кадр, например, 30 кадров в секунду или 33мс на кадр. И при синхронизации существует время ожидания, когда cpu ждет gpu или наоборот. В профайлере такие ожидания обозначаются как WaitForPresentOnGfxThread. А вот WaitForTargetFps - это время, которое нужно, чтобы поддержать заданный frame rate.
#sync #gpu #cpu
Мы знаем, что производительность - это метрика, которую можно оценить по fps или frames per second, т.е. сколько раз мы можем за секунду выполнить всю логику в кадре и отрисовать все, что мы посчитали.
Логика - это все то, что мы пишем в наших методах Update, которые являются частью основного цикла кадра и это обрабатывается на cpu, а вот рендер - это то, что обрабатывает видяха.
В целом эти два процесса никак не связаны, то есть в какой-то момент времени cpu посчитал что-то и готов передать на gpu некие данные, которые будут обрабатываться уже там и как результат - будет картинка. Существуют еще compute shaders, которые по сути используют проц на видяхе, чтобы посчитать результат.
И вот тут нам нужно синхронизировать данные. То есть при использовании синхронизации нам нужно задать фиксированное количество времени, которое мы готовы потратить на кадр, например, 30 кадров в секунду или 33мс на кадр. И при синхронизации существует время ожидания, когда cpu ждет gpu или наоборот. В профайлере такие ожидания обозначаются как WaitForPresentOnGfxThread. А вот WaitForTargetFps - это время, которое нужно, чтобы поддержать заданный frame rate.
#sync #gpu #cpu
👍22🔥6🥱3👾2
TypeCache API
Как-то не особо заметно прошло появление этого класса в юнити, но появился он аж в 2019.2.
Это такая удобная штука, которая позволяет получать уже нужные типы без необходимости искать их во всех ассембли.
https://docs.unity3d.com/ScriptReference/TypeCache.html
#editor #cache #types
🔥17👍5👾1
На какую тему хотели бы следующую лекцию?
Anonymous Poll
13%
ME.BECS
15%
ME.ECS
60%
Основы по шейдерам
12%
Ничего не хочу, ничего от жизни мне не надо… (с)
😁7🔥3🕊2
😁8🤣2
this или не this - вот в чем вопрос.
Немного о себе 🙂
Я начал программировать лет в 10, а зарабатывать на этом в 14. С тех пор прошло уже больше 20 лет, мне будет уже 36 (ох, какой же я старый стал).
Начинал я с pascal в школе, там были ассемблерные вставки и я познакомился с man. Потом перешел на visual basic, на котором делал всякие интересные штуки, познакомился с winapi. С приятелем в школе нашли dark basic и стали на нем писать какую-то фигню, но дело быстро свернулось, в основном из-за непонимания происходящего и что такое update loop, в visual basic такого не было 🙂
Потом в универе занимался плюсами, года 4 на них потратил.
В последние годы универа увлекся php, настолько, что в итоге первая фултайм работа была связана именно с этим. Помимо php ессно я занимался разными бд, full-text-search движками и прочими штуками, т.к. без этого стека выжить было нереально.
Потом решил, что бэк - это уже не так интересно, в софт идти совсем не хотелось, а игры я тогда вообще не понимал как делаются (хотя под directx еще на vb писал какие-то штуки), поэтому пошел в понятную область - в js. Пытался рендер делать на js, но с приходом первого html5 - перестал пытаться.
И вот тут, как не сложно догадаться, я все же решился пойти в игры. Не буду описывать подробности этого непростого периода, но в итоге я нашел Unity (хотя даже тогда выбор был из нескольких движков, в том числе и UE). В Unity меня привлекли мобилки (хотя что я тогда о них знал, недавно только вышел iphone 3G) и самое главное - js. Да, я быстро понял, что это никакой не js, а скорее нечто среднее между js и action script, но Unity уже была скачана, первый видос на ютубе посмотрен, где человек упроно называл сцену "скин" (как сейчас помню), так что куда деваться - надо писать свою ММОРПГ (шучу, терпеть их не могу, если честно). Конечно же я начал делать свою RTS 🙂
Ну так вот. К чему я это все. Я писал this, пишу this и буду писать this.
#story #life #this
Немного о себе 🙂
Я начал программировать лет в 10, а зарабатывать на этом в 14. С тех пор прошло уже больше 20 лет, мне будет уже 36 (ох, какой же я старый стал).
Начинал я с pascal в школе, там были ассемблерные вставки и я познакомился с man. Потом перешел на visual basic, на котором делал всякие интересные штуки, познакомился с winapi. С приятелем в школе нашли dark basic и стали на нем писать какую-то фигню, но дело быстро свернулось, в основном из-за непонимания происходящего и что такое update loop, в visual basic такого не было 🙂
Потом в универе занимался плюсами, года 4 на них потратил.
В последние годы универа увлекся php, настолько, что в итоге первая фултайм работа была связана именно с этим. Помимо php ессно я занимался разными бд, full-text-search движками и прочими штуками, т.к. без этого стека выжить было нереально.
Потом решил, что бэк - это уже не так интересно, в софт идти совсем не хотелось, а игры я тогда вообще не понимал как делаются (хотя под directx еще на vb писал какие-то штуки), поэтому пошел в понятную область - в js. Пытался рендер делать на js, но с приходом первого html5 - перестал пытаться.
И вот тут, как не сложно догадаться, я все же решился пойти в игры. Не буду описывать подробности этого непростого периода, но в итоге я нашел Unity (хотя даже тогда выбор был из нескольких движков, в том числе и UE). В Unity меня привлекли мобилки (хотя что я тогда о них знал, недавно только вышел iphone 3G) и самое главное - js. Да, я быстро понял, что это никакой не js, а скорее нечто среднее между js и action script, но Unity уже была скачана, первый видос на ютубе посмотрен, где человек упроно называл сцену "скин" (как сейчас помню), так что куда деваться - надо писать свою ММОРПГ (шучу, терпеть их не могу, если честно). Конечно же я начал делать свою RTS 🙂
Ну так вот. К чему я это все. Я писал this, пишу this и буду писать this.
#story #life #this
🔥36👍9🌚5👏3❤🔥2👨💻2👎1🥰1
Триангулятор
Нам часто нужно из точек сделать меш, чтобы потом отрисовать его.
Для этой цели нужно использовать алгоритм триангуляции (например, вот этот ). Вообще реализаций полно, так что не думаю что с этим будут проблемы.
Суть сводится к тому, чтобы на выходе получить треугольники (как следует из названия) из точек. А для создания мешки нам нужны вертексы (те самые точки) и индексы (как именно эти точки образуют треугольники).
#triangulator #math #mesh
Нам часто нужно из точек сделать меш, чтобы потом отрисовать его.
Для этой цели нужно использовать алгоритм триангуляции (например, вот этот ). Вообще реализаций полно, так что не думаю что с этим будут проблемы.
Суть сводится к тому, чтобы на выходе получить треугольники (как следует из названия) из точек. А для создания мешки нам нужны вертексы (те самые точки) и индексы (как именно эти точки образуют треугольники).
#triangulator #math #mesh
👍6🔥2👌2🥱2
Texture2D.GenerateAtlas
Я уже писал про PackTextures, но эта штука ломается, если невозможно запаковать текстуры, т.к. их размер превышает максимальный размер атласа. Для этого можно использовать GenerateAtlas, т.к. этот метод ничего не делает с текстурами, а только работает с ректами и возвращает true, если все объекты поместятся в атлас. То есть можно сначала вызвать его, а потом использовать PackTextures, либо запаковать самостоятельно, используя SetPixels.#api #code #unity
🔥15👍3
Instantiate<T>()
Я часто встречаю в коде вот такой вариант:
var instance = Instantiate(prefabGo);
instance.GetComponent<MyComponent>();
Дело в том, что можно использовать такой вариант:
var instance = Instantiate(prefabMyComponent);
Который сразу вернет нам ссылку на инстанс нашего объекта.
#lifehack #basics #instantiate #code
🥱67👍18🔥6🥴5🌚1💯1
Год назад мы решили записать нашу главную тему игры в виде простого клипа:
https://www.youtube.com/watch?v=RtR4E0z5Sys
При этом музыканты - это все люди из нашей компании.
А вы делали что-нибудь подобное в своих студиях или проектах?
Делитесь ссылками в комментах!
#clip #video #soundtrack #mushroomwars2
https://www.youtube.com/watch?v=RtR4E0z5Sys
При этом музыканты - это все люди из нашей компании.
А вы делали что-нибудь подобное в своих студиях или проектах?
Делитесь ссылками в комментах!
#clip #video #soundtrack #mushroomwars2
YouTube
Main Theme - Rock Edition by the Devs Band | Mushroom Wars 2
Watch music clip of the main theme of Mushroom Wars 2 recorded by the developers rock band and real Rudo himself!
Discord https://discord.gg/mw
Facebook https://www.facebook.com/MushroomWarsUniverse/
Community tournaments: https://battlefy.com/mushroom-wars…
Discord https://discord.gg/mw
Facebook https://www.facebook.com/MushroomWarsUniverse/
Community tournaments: https://battlefy.com/mushroom-wars…
🔥27❤2🥰1
Для каких платформ вы делаете проект?
Anonymous Poll
41%
PC/Steam
54%
iOS
77%
Android
5%
Switch
6%
PS
6%
XBOX
16%
Другие
👍4🥰2🤨2🍓2
Может показаться, что я забыл (или забил) делать посты для канала, но на самом деле - нет, у нас просто релиз в этом месяце, а вы знаете как это запарно, ведь нужно успеть сделать 90% проекта за последние 2 недели.
На самом деле выходит очень даже неплохо и я обязательно поделюсь результатом, когда проект выйдет в релиз (будет софт).
#release #newproject #news
На самом деле выходит очень даже неплохо и я обязательно поделюсь результатом, когда проект выйдет в релиз (будет софт).
#release #newproject #news
👍51🔥10🫡5❤2👾2
Texture2DArray
Недавно столкнулся с проблемой, что у нас в проекте перестали влезать все юниты в один атлас, а нам прям надо, чтобы все юниты рисовались в один проход. Тут я вспомнил, что была такая древняя штука как Texture2DArray. Принцип простой: по сути у вас вместо 2д текстуры, она становится 3д, в шейдере нужны минимальные изменения для поддержки этого.
На практике же всплыло 2 проблемы:
1. Слои должны быть одного размера, т.е. нельзя сделать один слой 2к, а другой - 1к;
2. Эта штука не работает на андроиде.
Если первую проблему решить довольно просто, переписав пакер, то вот со второй проблемой никакого решения собственно и нет.
Пришлось уходить от массивов в сторону кучи сэмплеров, благо нам нужно по требованиям рисовать не так много атласов.
#shaders #texture2darray #android
Недавно столкнулся с проблемой, что у нас в проекте перестали влезать все юниты в один атлас, а нам прям надо, чтобы все юниты рисовались в один проход. Тут я вспомнил, что была такая древняя штука как Texture2DArray. Принцип простой: по сути у вас вместо 2д текстуры, она становится 3д, в шейдере нужны минимальные изменения для поддержки этого.
На практике же всплыло 2 проблемы:
1. Слои должны быть одного размера, т.е. нельзя сделать один слой 2к, а другой - 1к;
2. Эта штука не работает на андроиде.
Если первую проблему решить довольно просто, переписав пакер, то вот со второй проблемой никакого решения собственно и нет.
Пришлось уходить от массивов в сторону кучи сэмплеров, благо нам нужно по требованиям рисовать не так много атласов.
#shaders #texture2darray #android
🔥8👍5🤯2
Есть такой мемчик, где люди делятся на 2 типа и вот это все. Ну там где у человека выключено отображение ворнингов и там где включено.
Я отношусь к тем, у кого они включены и вообще не люблю когда в логах мусор.
Так вот, в шарпе есть такая штука:
Она позволяет включать и выключать либо все ворнинги, либо конкретные, если указано какие конкретно нужно отключить.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#pragma-warning
Вообще я предпочитаю исправлять предупреждения, а не использовать эти директивы, но тем не менее иногда без этого никуда.
Поддерживайте ваш код в чистоте и без лишних логов и предупреждений.
#logs #pragma #warnings
Я отношусь к тем, у кого они включены и вообще не люблю когда в логах мусор.
Так вот, в шарпе есть такая штука:
#pragma warning disable
#pragma warning restore
Она позволяет включать и выключать либо все ворнинги, либо конкретные, если указано какие конкретно нужно отключить.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#pragma-warning
Вообще я предпочитаю исправлять предупреждения, а не использовать эти директивы, но тем не менее иногда без этого никуда.
Поддерживайте ваш код в чистоте и без лишних логов и предупреждений.
#logs #pragma #warnings
Docs
Preprocessor directives - C# reference
Learn the different C# preprocessor directives that control conditional compilation, warnings, nullable analysis, and more
🔥15👍11😐3🤡1