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

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

@unsafecsharp

Авторский канал о разработке в Unity от Alex Silaev (CTO в Zillion Whales). Mushroom Wars 2 моих рук дело.
Рассказываю об интересный кейсах, делюсь лайфхаками, решениями.
Subscribers
1.74K
Photos
40
Videos
0
Links
101
Recent Posts 20 shown
Post #283 2.32K
Век живи - век учись

Я вот только сегодня узнал, что оказывается можно писать не только так:


var str = $"{value}";


А еще и вот так:


var str = $$"""{{value}}""";


Или вот так:


var str = $$$"""{{{value}}}""";


Или проще говоря, от количества $ символов зависит количество скобочек. В целом довольно удобно иногда может быть.
Я вот обнаружил это только сейчас, т.к. мне всегда хватало и одного $.

#csharp #strings
  • 😐 33
  • 🔥 17
  • 🤔 13
  • 🤣 9
  • 🤡 3
  • ❤ 2
  • 👍 2
  • 🥰 1
  • 🤨 1
  • 🤗 1
Post #282 2.88K
Overlay

У юнити, начиная с 2022.2, появилась возможность рисовать свои окна в SceneView, при этом не прибегая к костылям вида "подпишусь на колбэк GUI, потом нарисую хрен пойми где хрен пойми как".

UnityEditor.Overlays.Overlay - позволяет это сделать очень просто и легко.


[Overlay(typeof(SceneView), "YourUniqueId", "Caption", defaultDisplay = true)]
public class YourOverlay : Overlay {
public override VisualElement CreatePanelContent() {
return new Label("Test");
}
}


В целом довольно удобно, когда нужны какие-то настройки объектов на сцене, раньше приходилось руками рисовать, а сейчас удобная тулза.

#unity #editor #sceneview
  • 🔥 59
  • 👍 9
Post #281 3.16K
Удобное API

Вы наверняка сталкивались с такой проблемой:

void Method<T>(System.Action<T> callback) {...}

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

Method<MyObj>(static (obj) => {
// И вот тут нам явно не хватает данных при static
});

Отсюда 2 выхода: либо мы используем аллокации при замыкании, либо реализуем некий второй параметр, в который мы сможем положить любые данные:


void Method<T1, T2>(T1 t1, System.Action<T1, T2> callback) {...}


С точки зрения метода будем считать, что T1 - это замыкание, которое мы передаем в метод:


Method<int, MyObj>(123, static (closure, obj) => { ... });


Вроде уже неплохо, но что если у нас вместо простого int будет что-то сложнее, например, кортеж ValueTuple:


Method<ValueTuple<int, int>, MyObj>((123, 234), static (closure, obj) => { ... });


Выходит уже неприятно, а если представить, что это мы захотим передать несколько параметров разных своих типов, то будет прям совсем нечитаемо.

И тут тоже есть элегантное решение:


struct ClosureAPI<TClosure> {
public TClosure data;
public MyContainer container;
public Method<T>(System.Action<T, TClosure> callback) {
this.container.Method(this.data, callback);
}
}

ClosureAPI<TClosure> Closure<TClosure>(TClosure data) {
return new ClosureAPI<TClosure>() {
data = data,
container = this,
};
}

void Method<T1, T2>(T1 t1, System.Action<T1, T2> callback) {...}


Таким образом снаружи это будет выглядеть как:

container.Closure((123, 234)).Method<MyObj>(static (data, obj) => { ... });


Вот таким образом мы избавляемся от необходимости указывать дженерик тип, который используем.

Естественно, если вы передаете все инстансы в метод, то вам не нужно указывать типы, но если (как в примере выше) у вас тип передаете только как дженерик, то такой подход избавит от необходимости указывать дженерик замыкания.

#zeroalloc #architecture #code
  • 🔥 24
  • 🤔 9
  • ❤ 6
  • 👍 2
Post #280 2.79K
Простые лайфхаки

Часто встречаю в разных проектах подобные конструкции (на самом деле обычно они страшнее, но я убрал все лишнее):

var result = false;
if (Method1() == true) result = true;
if (Method2() == true) result = true;
if (Method3() == true) result = true;
...
return result;


На самом деле этот код можно записать проще:

var result = false;
result |= Method1();
result |= Method2();
result |= Method3();
...
return result;


Аналогично можно делать и обратную историю:

var result = true;
result &= ...


В целом подобных штук можно найти немало, которые сэкономят время и приведут код с красивому и читаемому виду.

#lifehack #basics #code
  • 🔥 37
  • 👍 8
  • 🤡 7
  • ❤ 6
  • 😐 6
Post #279 3.04K
Довольно интересная задачка попалась на собеседовании в гугле:
Есть матрица (массив массивов) вида
[
[1, 0, 0, 0, 0, 1],
[0, 1, 0, 1, 1, 1],
[0, 0, 1, 0, 1, 0],
[1, 0, 0, 0, 1, 0],
[1, 0, 1, 1, 0, 0],
[1, 0, 0, 0, 0, 1]
]


Нужно реализовать метод, который найдет все острова. Островом считаются 1, которые не примыкают к границам. Диагонали не считаются за соединения.
То есть на выходе должна быть матрица такого вида:
[
[0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]
]


Как вы бы решали такую задачу?
Доп вопросы:
- Возможно ли решить задачу без аллоцирования памяти? (Стэк константного размера не считается)
- Какая минимально возможная сложность по времени (О-нотация)?

#interview #task #algorithms
  • 🔥 11
  • 👍 6
  • 😨 4
Post #278 3.7K
Unity.Profiling.IgnoredByDeepProfilerAttribute

Аттрибут, который спасет вам время, если у вас много кода, который вы точно не хотели бы видеть в профайлере.

#attributes #profiling #unity
  • 🔥 57
  • 👍 10
Post #277 4.91K
Рукожопы (других слов нет) выпустили апдейт юнити, в котором отломали uitk в инспекторе.
Так что ждем хотфикс, а пока (если у вас вдруг ломается инспектор) можно отключить uitk и использовать imgui:
Project Settings -> Editor -> use IMGUI

#editor #unity
  • 😁 51
  • 👍 9
Post #275 5.09K
Всем привет ;)

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

Но я хотел бы предложить свои услуги в качестве консультаций в частном порядке, то есть мы разберем вашу проблему и найдем оптимальное для нее решение. Готов помочь с любыми проблемами на ваших текущих проектах или просто подтянуть знания по какой-то теме.
Оплата по договоренности.

https://boosty.to/chromealex

Пишите в личку: @chromealex
  • 🔥 78
  • 👍 24
  • 🤡 5
  • 👏 4
Post #274 3.43K
NoAlias

Этот аттрибут используется для Burst и позволяет экономить на инструкциях.
Например:


int Method(ref int a, ref int b) {
b = 13;
a = 42;
return b;
}


В данном случае Burst не знает, пересекаются ли данные a и b (хранятся ли в памяти в одном месте или нет).
То есть тут будет 3 инструкции mov, 2 для установки значения, а третья - для чтения этого значения. Если же добавить аттрибут NoAlias, возврат данных будет без дополнительной загрузки:


int Method([NoAlias] ref int a, ref int b) {
b = 13;
a = 42;
return b;
}


Аттрибут можно использовать для NativeArray (контейнеров), которые не пересекаются, и в качестве возврата из методов [return: NoAlias]. При этом это имеет смысл, если метод не заинлайнен, т.к. при инлайне аттрибут не будет иметь смысла.

#noalias #burst #code
  • 🔥 20
  • ❤ 2
Post #273 2.33K
ResourcesAPI

В юнити 6.2 появилась классная штука, которая позволяет переопределить дефолтные методы загрузки ресурсов. И это круто, если подобным образом они будут развиваться и дальше, то когда-нибудь можно будет переписать весь движок 🙂

https://docs.unity3d.com/6000.2/Documentation/ScriptReference/ResourcesAPI.html

#unity #api #resources
  • 🔥 27
  • 🤡 3
  • 👍 2
  • 😁 1
Post #272 2.36K
Unity.Mathematics

На самом деле многие не поняли зачем им использовать Unity.Mathematics, если у них есть Vector2/Vector3 и Mathf, например.
Давайте разберем самый простой пример:

var a = 10;
var b = 20;
var c = 30;
var result = a * b + c; // Считаем результат


У Unity.Mathematics есть math.mad, который внутри делает тоже самое:

void mad(int a, int b, int c) => a * b + c;


И самая большая ошибка считать, что никакой разницы в коде не будет. А работает это так: при компиляции кода, вызов math.mad мапится напрямую на simd-инструкцию, то есть код превращается из 2х инструкций в одну.
Пример с math.mad - это лишь пример того, где вы можете сэкономить, в целом есть всякие select еще, которые тоже все избегают использовать.

#unity #simd #math
  • 🔥 48
  • 😁 2
  • ❤ 1
Post #271 2.62K
Player Loop

Вместо MonoBehaviour на сцене можно использовать инжект в текущий луп. Для этого нужно понимать в какой именно мы хотим добавить вызов своего метода. Всего есть 8 групп:

TimeUpdate = 0
Initialization = 1
EarlyUpdate = 2
FixedUpdate = 3
PreUpdate = 4
Update = 5
PreLateUpdate = 6
PostLateUpdate = 7


Использовать проще всего с инжектом при инициализации, но в принципе можно вызывать этот код когда угодно, как и удалять свою систему из обработки:


[RuntimeInitializeOnLoadMethod]
static void Inject() {
var loop = PlayerLoop.GetCurrentPlayerLoop();
var sys = new PlayerLoopSystem {
type = typeof(YourClassName),
updateDelegate = () => Debug.Log("Custom Update")
};
var index = 4; // PreUpdate (см список выше)
loop.subSystemList[index].subSystemList = loop.subSystemList[index].subSystemList.Append(sys).ToArray();
PlayerLoop.SetPlayerLoop(loop);
}


#unity #playerloop
  • 🔥 51
  • 👍 2
Post #270 2.1K
CallerFilePathAttribute

Этот аттрибут позволяет получить путь к файлу, из которого происходит вызов метода:


void Sample([CallerFilePath] string file = null) {
UnityEngine.Debug.Log(file);
}


Еще обратите внимание, что есть CallerMemberName (из какого метода вызов) и CallerLineNumber (на какой строке).

#debug #csharp #code
  • 🔥 34
  • ❤ 5
  • 👍 3
  • 👀 1
Post #269 2.92K
https://youtu.be/GUVi04UCKsQ

Поговорили про AI, какие основные алгоритмы используют для этого, что из себя представляют, где что использовать

#streams #ai
YouTube unsafecsharp: [AI] FSM, BT, Utility AI, GOAP, Influence Maps, Steering Behaviour, Voronoi Diagram Рассмотрим основные алгоритмы: [AI] FSM, BT, Utility AI, GOAP, Influence Maps, Steering Behvaiour, Voronoi Diagram Больше на канале https://t.me/unsafecsharp
  • 🔥 39
  • 🤩 2
Post #268 3.45K
https://youtu.be/TilgB9G1G3g

Когда-то давно я показывал видео про наброски rts, в этом видео рассматривается основная механика построения деревьев и поиск данных в них. На ее основе можно строить физику, коллизии, RVO, поиск целей и множество других интересных вещей.

#becs #trees
  • 👍 14
  • 🔥 8
  • ❤ 5
  • 🥰 1
Post #267 3.9K
https://docs.google.com/presentation/d/1LlxyWOz88aXjAQVVJdN3Fss08E8Rnu8k/edit?usp=drivesdk&ouid=113802151767136274653&rtpof=true&sd=true

Делюсь с вами моей презой для одного из закрытых ивентов. Тут собрана база, но вполне возможно, что в вашей компании/команде вы отходите от нее, чтобы делать мир лучше :)

#events #presentation #allocations
Google Docs Презентация Allocs.pptx И что с ними делать © Copyright PresentationGO.com – The free PowerPoint and Google Slides template library 1 Аллокации
  • 🔥 43
  • 👍 12
  • 🥰 4
  • ❤ 2
  • 😁 1
  • 😨 1
Post #266 3.31K
Marshal.OffsetOf

С помощью этого метода я в BECS нахожу где фактически находится поле в структуре, в которое я хотел бы записать данные.
Я это использую в кодогене, когда я точно знаю название поля и хочу вписать туда данные, но использовать рефлексию для этого нет никакого желания.

Работает примерно так:

var offset = Marshal.OffsetOf(type, field.Name);
codeGenOutput.Add($"var addr = (byte*)_addressOf(ref obj) + {offset};");
codeGenOutput.Add($"*(({objType}*)addr) = new SomeStruct(...);");


В итоге получается, что мы просто записываем данные в структуру obj без рефлексии и нам не важно приватное там поле или публичное.

#unsafe #fieldoffset #marshal
  • 🔥 31
  • 🤔 6
  • 👍 4
  • ❤ 2
Post #264 3.29K
https://github.com/chromealex/ME.Monitor/tree/main

Написал тут тулзу для мониторинга за серваками.
Умеет ping, tcp, rest, выводит графики, рисует маршруты. Предназначена для сборки в качестве standalone/adroid/ios билдов. Строит наглядно визуализацию расположения серверов и маршруты к ним. Для примера есть Config.json с рандомными сервисами, которые можно легко заменить на свои.

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

Предложения принимаются :)

#unity #tools #monitoring
  • 🔥 23
  • 👍 11
  • 🥰 4
  • 😁 3
Older posts →

About this channel

How can I read @unsafecsharp without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Unity: Всё, что вы не знали о разработке: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Unity: Всё, что вы не знали о разработке have?
Unity: Всё, что вы не знали о разработке (@unsafecsharp) has 1.74K subscribers on Telegram, refreshed roughly every 30 minutes.
Does Unity: Всё, что вы не знали о разработке know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
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 →