TGViewer
Channel Public Channel
Unity: Всё, что вы не знали о разработке

Unity: Всё, что вы не знали о разработке

@unsafecsharp

Авторский канал о разработке в Unity от Alex Silaev (CTO в Zillion Whales). Mushroom Wars 2 моих рук дело.
Рассказываю об интересный кейсах, делюсь лайфхаками, решениями.
Subscribers
1.73K
Photos
40
Videos
0
Links
101

Showing posts older than #162 · Back to latest

Older Posts 20 shown
Post #161 1.58K
Хранение айдишников

Мы храним SystemInfo.deviceUniqueIdentifier, который вовсе не device id, а advertisement id, т.е. раньше он был айдишником девайса, но потом от их использования отказались в пользу различных авторизаций.
Но мы хотим, чтобы юзер мог играть без авторизации, т.е. юзер должен передать некую уникальную строку.

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

Раньше этот айдишник был вполне стабилен, т.к. являлся заводским уникальным айдишником. Сейчас нам дают рекламный айди, который может измениться в любой момент. Самый простой способ - сохранить его в PlayerPrefs, чтобы даже при его изменении со стороны ОС - ничего не менялось для игрока. Естественно, мы предупреждаем, что лучше бы подключить какую-нибудь сеть типа фейсбука, чтобы не потерять прогресс, но это как прочитать readme.

Но люди продолжали жаловаться, что аккаунты теряются, в основном на ios, т.к. именно там рекламные айдишники меняются и меняются часто. Т.е. люди просто удаляли игру и ставили ее заново, прогресс естественно терялся. Чтобы решить эту проблему, мы начали сохранять ключ в Keychain и проблема ушла.

#keychain #ios #deviceid
  • 👍 16
  • 🔥 5
  • 🤷‍♀ 2
  • 🥴 1
Post #160 1.44K
Для того, чтобы в инспекторе при отрисовке массива отображались нормальные названия элементов, а не Element 0, Element 1, Element N, можно использовать строку первым полем:

struct Item {
public string key;
...
}

Тогда введенные данные в этот ключ будут отображаться вместо стандартного Element X, что повысит читаемость и поиск, и вам не придется писать дополнительных редакторов для элементов.

#lifehack #arrays #inspector #editor
  • 🔥 19
  • 👍 7
  • 🤯 7
  • 🥱 2
Post #159 1.45K
Нормализация векторов

Это приведение к единичному размеру, при этом направление сохраняется. Обычно мы используем для этого v.normalized или v.Normalize(). Второй вариант будет немного быстрее первого, т.к. мы не создаем копию вектора, а изменяем существующий.

Но как оно работает внутри? Как нетрудно догадаться из определения нормализации, чтобы привести вектор к единичному - нам нужна его длина, а длина вектора - это корень по теореме Пифагора. Поэтому если вы по какой-то причине уже получили длину вектора, то просто поделите (ну поделите, ага https://t.me/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
Post #158 1.39K
Time.deltaTime vs Time.fixedDeltaTime

Я уже делал пост про FixedUpdate (https://t.me/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…
  • 🥱 9
  • 🔥 6
  • 👍 2
Post #157 1.47K
StaticBatchingUtility.Combine

Позволяет комбайнить меши, которые находятся на GameObject. Довольно удобно, чтобы не ползать по иерархии и не собирать их там.
Есть способ комбинировать меши и без этого:
mesh.CombineMeshes
Но придется передавать туда уже структуры, в которых описываются матрицы и мешки.
Мы такое часто использовали для 3D, когда мы создавали одну мешку и вместо 1к объектов получали всего один. Есстественно, нужно понимать, что батчить нужно по-материально, т.е. какой-то код с этой логикой нужно будет все же написать.

#batching #static #code #api
  • 🔥 13
  • ❤ 2
  • 👾 2
Post #156 1.59K
Texture2D.PackTextures

Мы часто используем этот метод для динамического создания атласа, когда, например, мы загружаем аватарки игроков, а какие они будут мы заранее не знаем. Или мы формируем атлас для боя, когда игроки могут выбрать какие-нибудь скины юнитов, а нам все еще нужен 1 draw call ;)

#atlas #runtime #code #api
  • 🔥 41
  • 👍 9
Post #155 1.54K
Lerp vs LerpUnclamped

Давайте сначала разберемся что такое Lerp. Это линейная функция, которая задается двумя точками B и C (см изображение), а третье значение t - это как значение между 0 и 1, где 0 - это B, а 1 - это C.
Таким образом получается, что перемещение по линии - это и есть lerp или интерполяция. А вот LerpUnclamped - это экстраполяция, т.е. когда мы не обрезаем значение t до 0..1.

b + (c - b) * clamp01(t);

Т.е. по сути мы сначала сдвигаем сетку координат в ноль (c - b), а потом умножаем получившийся вектор на t, а после сдвигаем получившийся вектор назад.
С Unclamped мы просто не делаем операцию clamp, тем самым можем позволить результату выходить за границы b-c.

#basics #lerp
  • 🔥 10
  • 👍 3
Post #154 1.39K
Вспомнил забавную технику, которую я использовал когда мы делали Mushroom Wars 2 еще для Steam (а это была наша первая таргет платформа, если что).
Так вот, мы изначально решили делать 2д игру, а не 3д, хотя и опыт позволял, да и можно было хайполи позволить для стима. Но мы решили, что не стоит недооценивать время и любое "красивое 3д" через несколько лет станет "всратым говном". Поэтому мы сделали ставку на 2д.

А теперь к делу. Мы рисовали домики и юнитов на карте в 2д и pixel perfect. Но мы хотели еще real-time тени туда впихнуть. И вот тогда придумали забавное решение: мы запилили low-poly мешки домов по краям с бОльшей геометрией, внутрь мешки вставили 2д спрайт, а саму мешку не рендерили, т.е. рендерили и блендили только тени на мешку и от мешки. В итоге получился pixel perfect рендер с realtime тенями.

Потом мы отказались от этой штуки в пользу спрайтов и render texture, т.к. нам нужно было на чайниках выходить, но история осталась 🙂

#rendering #shadows #story
  • 👍 13
  • 🔥 3
  • ❤ 1
  • 👾 1
Post #153 1.43K
Упоротая оптимизация.

История произошла совсем недавно: мне нужно было понять почему у нас крашился слабый девайс на загрузке одной конкретной игровой карты, при этом на других он вел себя хорошо. У меня сразу подозрение пало на память, т.к. поведение характерно именно для такого кейса. Проверил логи - действительно память закончилась.

А теперь самое инетерсное, начал разбираться и оказалось, что наш картоделатель посадил по 5к юнитов в домики "за картой", чтобы потом оттуда пускать их по триггеру. А рендер работает таким образом, что ему нужно знать верхнее ограничение по отрисовке количества юнитов. Для нормальной игры это вычислялось по формуле: "берем сумму всех юнитов во всех домиках на карте и умножаем на количество игроков (т.к. в теории каждый игрок может применить какой-нибудь скилл, который сдублирует юнитов, например)". Но если вдруг мы что-то не учли - мы просто не рисуем юнитов и все, что в принципе ок, т.к. когда у тебя 1к юнитов на экране - ты уже не понимаешь где кто, а когда 4к - так и подавно.

Так вот этому коду уже 7 лет и понятное дело, что его никто не трогал все это время, но когда в 2015 году мы писали этот код - юнити мало чего умела нормально рисовать в больших количествах, и мы оптимизировали и микрооптимизировали все что видели.
Так вот мы жили с такой игровой картой уже месяца 3 и только сейчас заметили проблему на девайсе с памятью, хотя у нас вместо того, чтобы рисовать и обрабатывать 4к юнитов максимум (+рендер на 20к), мы вдруг начали обрабатывать 220к и никто этого не заметил... И, наверное, если бы не этот девайс - так бы и пошли в релиз 🙂

А вы все "преждевременная оптимизация, преждевременная оптимизация..." 😂

#story #bug
  • 🥴 19
  • 🤣 11
  • 👍 4
  • 🔥 3
  • ❤ 1
Post #152 1.35K
Если вы не используете параметр out, по которому возвращается значение, то можете писать просто _:

Method(out int notUsed);
Method(out _);

#basics
  • 🔥 13
  • 👍 8
  • 🤡 8
  • 🥱 4
  • 🗿 2
  • 🤯 1
  • 💯 1
Post #151 1.37K
Unity: Всё, что вы не знали о разработке Умножение vs Деление Надеюсь, что вы все в курсе, что операция деления выполняется намного медленнее операции умножения. Если нет, то имейте ввиду. Я часто встречаю вот такой код: a += b / 2f; И мне все время хочется такой код написать так: a += b * 0.5f;…
Комменты
  • 😁 6
Post #150 1.43K
Умножение vs Деление

Надеюсь, что вы все в курсе, что операция деления выполняется намного медленнее операции умножения. Если нет, то имейте ввиду.

Я часто встречаю вот такой код:

a += b / 2f;

И мне все время хочется такой код написать так:

a += b * 0.5f;

Еще можно заменять по тому же принципу и любые другие константы. Но что делать, если у нас деление не на константу, а на x? Да все просто, делаем y = 1f / x и используем уже y.

#basics #performance #code
  • 🔥 26
  • 🥴 15
  • 👍 10
  • 🤔 7
  • 👌 7
  • ❤ 2
  • 💯 1
  • 😴 1
Post #149 1.58K
Запись с последней лекции про основы современной компьютерной графики:

https://youtu.be/EiucC4M0VuY

#record #event
  • 🔥 42
  • 👍 2
  • ❤ 1
Post #148 1.46K
Overdraw опаснее draw call.

Дело касается в основном мобилок, но вообще принцип тот же везде. Overdraw - это по сути метрика, с помощью которой можно понять сколько раз вы закрашиваете один и тот же пиксель. Во-первых, красить пиксель дважды - плохая примета. Во-вторых, видяхи на мобилах довольно слабые и каждый новый проход по одному месту может сильно просаживать производительность.

На практике легко получить такую проблему партикл системой с тысячами частиц. Может казаться, что производительность падает из-за количества частиц, но на самом деле проблема на 99% в overdraw. Кстати, для этого в настройках рендера партикл системы есть параметр, который ограничивает максимальный размер частицы относительно размера экрана, т.к. чем больше площадь - тем хуже. Поэтому 100 больших частиц у камеры хуже, чем 10к, но далеко.

#rendering #overdraw
  • 🔥 24
  • 👍 3
  • 🤨 2
Post #147 1.32K
Лекция закончилась :( Надеюсь, что было интересно))
По-традиции, запись будет позже.
Пишите свои комменты по этой лекции и по темам, которые вы бы хотели обсудить.

#event
  • 🔥 23
  • 😴 1
Post #146 1.36K
Напоминаю, что сегодня пройдет лекция про основы современной трехмерной графики:
https://t.me/unsafecsharp/141

Регайтесь :)

#event
  • 🔥 10
  • 👍 3
Post #145 1.39K
Мы часто используем для редактора поля вида

UnityEngine.Object dir;

для того, чтобы в инспекторе перетащить туда папку. Это очень удобно, чтобы не писать константы в коде.

#editor
  • 🔥 57
  • 🙉 3
Post #144 1.43K
В C++ нет дженериков.

Их нет, да, но как тогда работают дженерики, которые мы делаем в C#? Там то они есть;) а мы используем il2cpp почти всегда для продакшена. В итоге под каждый тип, который мы вызываем, будет создан метод. Это стоит учитывать, когда вы создаете дженерик метод и делаете миллион разных вариантов вызовов, то ожидайте код в размере миллиона копипастных методов;)

#cpp #generics #il2cpp
  • 🔥 16
  • 👍 2
  • ❤ 1
Post #143 1.64K
Вот такую задачку мы задаем на собесе, чтобы понять понимает ли человек основы и вообще работал ли он со структурами (или только с классами):

void Method(IInterface obj) {}

public struct S : IInterface {}
public struct A : IInterface {}

void Something() {
Method(new S());
Method(new A());
}

interface IInterface {…}

Но вопрос мы ставим так: «какие проблемы вы видите с этим кодом?». А дальше внимательно слушаем, если ответ типа «ну тут нужно все вообще переписать», то так и будет в вашем прод проекте, все перепишут, а в итоге результата будет ноль;)

#interview #code
  • 👍 16
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →