TyapLyapDev - Разработка игр | Движуха Сакутина
Photo
Уже сутки дерусь с пользовательским редактором юнити, чтобы сделать эту систему ещё удобнее, настраиваемой в специальном окне. Думаю, это станет полноценной утилитой, чтобы легко настраивать и не лезть в код. Сначала меня пугала работа в редакторе. Сейчас тоже пугает, но меньше, т.к. я начал раскидывать логику по ответственностям и дебажить, расширять, модифицировать становится проще.
Такой вот совет: если перед вами страшный код, раскидайте его по скриптам и работайте с кусочками.
Такой вот совет: если перед вами страшный код, раскидайте его по скриптам и работайте с кусочками.
🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Показыватель иконок в иерархии сцены 2.0! Теперь достаточно открыть окно, добавить элемент в список и выбрать там иконку и компонент, который висит на объектах для отрисовки. Чем это удобно? Ну, вы можете подсветить в иерархии сцены все объекты, на которые вашим коллегам по разработке надо обратить особое внимание. Я выделял объекты с дорожными модельками для человека, который собирал уровень. Оказалось очень даже удобно. Не тестил на разных версиях юньки, поэтому пишите, если найдёте баги 🙂
🔥4
TyapLyapDev - Разработка игр | Движуха Сакутина
Video
Какое было решение для снижения нагрузки: каждый кубик - объект, который внутри себя содержит триггер-коллайдер в виде сферы, чисто для плавности и саму модельку куба, которая выключена. Позиция триггера никогда не меняется, а вот позиция модельки при деактивации (и на старте) присваивает случайное сферическое отклонение и случайную дистанцию. При активации моделька получает ссылку на цель (игрока) появляется по направлению от цели на эту самую рандомную дистанцию, плюс рандомное отклонение и вращение. Чем меньше дистанция до цели, тем ближе моделька к нулевым координатам позиции и вращению.
Теперь игрок. У него есть детектор в виде сферы, который активирует кубы при входе в триггер и деактивирует при выходе. Физика настроена так, что детектор видит только кубы, а кубы детектор. Все остальные слои игнорируются.
Чтобы ручками не составлять лабиринты из кубиков, я сделал их генерацию с заполнением по всему объёму коллайдеров стен. Компонент принимает размер кубов для каждой стены, зазор между кубами и цветовую схему. После заполнения кубами у стены удаляется рендерер, отрисовывается гизмос в сцене и остаётся только коллайдер, по которому двигается коллайдер игрока.
В целом я постарался в оптимизацию, поэтому всё работает без лагов, сколько бы кубов на сцене не находилось.
Теперь игрок. У него есть детектор в виде сферы, который активирует кубы при входе в триггер и деактивирует при выходе. Физика настроена так, что детектор видит только кубы, а кубы детектор. Все остальные слои игнорируются.
Чтобы ручками не составлять лабиринты из кубиков, я сделал их генерацию с заполнением по всему объёму коллайдеров стен. Компонент принимает размер кубов для каждой стены, зазор между кубами и цветовую схему. После заполнения кубами у стены удаляется рендерер, отрисовывается гизмос в сцене и остаётся только коллайдер, по которому двигается коллайдер игрока.
В целом я постарался в оптимизацию, поэтому всё работает без лагов, сколько бы кубов на сцене не находилось.
🔥4❤1
Сделай первую игру с нуля и получи грант на 1 000 000 рублей
Привет! Я веду этот канал как участник творческой мастерской Романа Сакутина. Наша цель создавать творческие игры и радовать игроков.
Становись разработчиком игр вместе со мной здесь - https://ijunior.ru/workshop-gamedev?utm_source=telegram_workshops&utm_medium=pinned_post&utm_campaign=tyaplyapdev
Привет! Я веду этот канал как участник творческой мастерской Романа Сакутина. Наша цель создавать творческие игры и радовать игроков.
Становись разработчиком игр вместе со мной здесь - https://ijunior.ru/workshop-gamedev?utm_source=telegram_workshops&utm_medium=pinned_post&utm_campaign=tyaplyapdev
ijunior.ru
Сделай первую игру с нуля и получи грант на 1 000 000 рублей
Бесплатная творческая мастерская от Романа Сакутина. Тебя ждут лекции и клуб творцов
😁4
TyapLyapDev - Разработка игр | Движуха Сакутина pinned «Сделай первую игру с нуля и получи грант на 1 000 000 рублей Привет! Я веду этот канал как участник творческой мастерской Романа Сакутина. Наша цель создавать творческие игры и радовать игроков. Становись разработчиком игр вместе со мной здесь - https:/…»
TyapLyapDev - Разработка игр | Движуха Сакутина
Как по мне, офигенно получается. Тема - "Шутер". Доп тема - "Гравитационные аномалии". На видео результат 4 недель кодинга 😎 Спасибо 3-дшнику @TrutnevI за подготовленный ассет пистолета-обливалки 🔫
SoakPC.zip
50.1 MB
Я по ходу билд не скидывал этого проекта. Можете игрануть, это на ПК
🔥1
Media is too big
VIEW IN TELEGRAM
Языковая локализация игры.
Вам уже доводилось переводить игры на другие языки? Я уже с этим несколько раз сталкивалася, поэтому просто сделал для себя заготовку.
Самый простой, понятный и эффективный способ - накидывать на объекты с текстовыми компонентами кастомный скрипт, в котором есть несколько полей для записи. Вся логика уложилась в 3 скрипта, в которых суммарно 132 строчки кода - это уже с удобным переключением.
Ассет с демосценой прикреплю в комментариях (при импорте так же подтяните TMP). Ещё я в комменты запульну сообщения с кодом чтобы вы могли посмотреть, а кто-то возможно найдёт косяки.
Пишите замечания, задавайте вопросы, с радостью пообщаюсь 🙂
Вам уже доводилось переводить игры на другие языки? Я уже с этим несколько раз сталкивалася, поэтому просто сделал для себя заготовку.
Самый простой, понятный и эффективный способ - накидывать на объекты с текстовыми компонентами кастомный скрипт, в котором есть несколько полей для записи. Вся логика уложилась в 3 скрипта, в которых суммарно 132 строчки кода - это уже с удобным переключением.
Ассет с демосценой прикреплю в комментариях (при импорте так же подтяните TMP). Ещё я в комменты запульну сообщения с кодом чтобы вы могли посмотреть, а кто-то возможно найдёт косяки.
Пишите замечания, задавайте вопросы, с радостью пообщаюсь 🙂
🔥4👍2
Зачем кешировать transform?
Кеширование трансформа в Unity (например, _transform = transform) делают для повышения производительности. Вот основные причины:
1. Избежание повторных вызовов геттера
Свойство transform в Unity не просто возвращает поле - оно вызывает внутренний метод GetComponent<Transform>(), который ищет компонент в GameObject. Это требует вычислительных затрат.
Кеширование сохраняет ссылку на трансформ один раз (например, в Awake()), избегая повторного поиска.
2. Сокращение накладных расходов
В циклах (например, Update()) частые обращения к transform без кеширования могут снижать FPS, особенно на мобильных устройствах или при большом количестве объектов.
Пример без кеширования:
Пример с кешированием:
Важно!
Современные версии Unity (особенно с 2018+) оптимизировали геттер transform, и разница в производительности стала менее заметной. Однако для критичных к производительности проектов кеширование всё ещё рекомендуется.
Всегда кешируйте компоненты в Awake() или Start(), а не в Update(), чтобы избежать лишних операций.
Что ещё кешируют?
Другие компоненты: Rigidbody, Renderer, Canvas и т.д.
Ссылки на игровые объекты, если они используются часто.
Таким образом, кеширование — это простая и эффективная практика для оптимизации кода в Unity.
Кеширование трансформа в Unity (например, _transform = transform) делают для повышения производительности. Вот основные причины:
1. Избежание повторных вызовов геттера
Свойство transform в Unity не просто возвращает поле - оно вызывает внутренний метод GetComponent<Transform>(), который ищет компонент в GameObject. Это требует вычислительных затрат.
Кеширование сохраняет ссылку на трансформ один раз (например, в Awake()), избегая повторного поиска.
2. Сокращение накладных расходов
В циклах (например, Update()) частые обращения к transform без кеширования могут снижать FPS, особенно на мобильных устройствах или при большом количестве объектов.
Пример без кеширования:
void Update()
{
// Каждый раз вызывается геттер transform
transform.Translate(1, 0, 0);
transform.Rotate(0, 1, 0);
}
Пример с кешированием:
private Transform _transform;
void Awake()
{
_transform = transform; // Сохраняем ссылку один раз
}
void Update()
{
_transform.Translate(1, 0, 0); // Работаем с кешированной ссылкой
_transform.Rotate(0, 1, 0);
}
Важно!
Современные версии Unity (особенно с 2018+) оптимизировали геттер transform, и разница в производительности стала менее заметной. Однако для критичных к производительности проектов кеширование всё ещё рекомендуется.
Всегда кешируйте компоненты в Awake() или Start(), а не в Update(), чтобы избежать лишних операций.
Что ещё кешируют?
Другие компоненты: Rigidbody, Renderer, Canvas и т.д.
Ссылки на игровые объекты, если они используются часто.
Таким образом, кеширование — это простая и эффективная практика для оптимизации кода в Unity.
👍4❤2🔥2
Хочу поделиться с вами своими соображениями по поводу комментариев в коде. Мне кажется это плохой практикой и вот почему:
1. Код желательно писать так, чтобы он сам говорил за себя. Для этого достаточно придумывать понятные названия для классов, полей и методов, а так же раскидывать логику по ответственностям.
2. Если в коде и комментариях одно и то же, то какой смысл в этих комментариях?!
3. Если вы изменили логику в коде, но не поправили пояснения в комментариях, то это скорее запутает, чем поможет.
Таким образом комментирование - скорее бесполезная штука и двойная работа.
Но не будем голословными. Для примера я качнул из ассет стора Starter Assets - ThirdPersonController .
Давайте посмотрим кусочки:
Вообще в этом классе 392 строки и он занимается сразу всем. Если раскидать по скриптам, то внезапно окажется, что поля с комментарием // cinemachine попадут в один класс, // player в другой класс и т.д. Это означает, что сама архитектура снимет с вас необходимость группировать поля таким способом. Но допустим, это прототип и не страшно, что здесь всего напихано. Смотрим ещё раз:
В самом названии полей написано _cinemachine , так же и в остальных. Здесь можно поудалять комментарии, оставить лишь разделение групп пустыми строками и читаемость нисколько не пострадает, а даже улучшится.
Смотрим дальше:
В комментарии говорится "// получите ссылку на нашу основную камеру". А в коде что? А вот: если ссылка на Камеру равна null , получить ссылку по тегу "MainCamera" и присоить её _mainCamera
Пока закроем глаза на использование тегов, но чем сам код здесь объясняет хуже комментария?
Дальше:
// reset our timeouts on start - // сбросьте наши тайм-ауты при запуске. А что мешает сделать метод:
Во-первых не придётся писать, что сбрасываем при старте - логично же, что раз метод вызывается в старте, то там идёт сброс таймаутов. Во-вторых, можно переиспользовать этот метод в других частях кода.
Дальше просто поскидываю такие кусочки кода. Посмотрите, как это комично выглядит:
1. Код желательно писать так, чтобы он сам говорил за себя. Для этого достаточно придумывать понятные названия для классов, полей и методов, а так же раскидывать логику по ответственностям.
2. Если в коде и комментариях одно и то же, то какой смысл в этих комментариях?!
3. Если вы изменили логику в коде, но не поправили пояснения в комментариях, то это скорее запутает, чем поможет.
Таким образом комментирование - скорее бесполезная штука и двойная работа.
Но не будем голословными. Для примера я качнул из ассет стора Starter Assets - ThirdPersonController .
Давайте посмотрим кусочки:
// cinemachine
private float _cinemachineTargetYaw;
private float _cinemachineTargetPitch;
// player
private float _speed;
private float _animationBlend;
private float _targetRotation = 0.0f;
private float _rotationVelocity;
private float _verticalVelocity;
private float _terminalVelocity = 53.0f;
// timeout deltatime
private float _jumpTimeoutDelta;
private float _fallTimeoutDelta;
// animation IDs
private int _animIDSpeed;
private int _animIDGrounded;
private int _animIDJump;
private int _animIDFreeFall;
private int _animIDMotionSpeed;
Вообще в этом классе 392 строки и он занимается сразу всем. Если раскидать по скриптам, то внезапно окажется, что поля с комментарием // cinemachine попадут в один класс, // player в другой класс и т.д. Это означает, что сама архитектура снимет с вас необходимость группировать поля таким способом. Но допустим, это прототип и не страшно, что здесь всего напихано. Смотрим ещё раз:
// cinemachine
private float _cinemachineTargetYaw;
private float _cinemachineTargetPitch;
В самом названии полей написано _cinemachine , так же и в остальных. Здесь можно поудалять комментарии, оставить лишь разделение групп пустыми строками и читаемость нисколько не пострадает, а даже улучшится.
Смотрим дальше:
private void Awake()
{
// get a reference to our main camera
if (_mainCamera == null)
{
_mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
}
}
В комментарии говорится "// получите ссылку на нашу основную камеру". А в коде что? А вот: если ссылка на Камеру равна null , получить ссылку по тегу "MainCamera" и присоить её _mainCamera
Пока закроем глаза на использование тегов, но чем сам код здесь объясняет хуже комментария?
Дальше:
private void Start()
{
...
// reset our timeouts on start
_jumpTimeoutDelta = JumpTimeout;
_fallTimeoutDelta = FallTimeout;
}
// reset our timeouts on start - // сбросьте наши тайм-ауты при запуске. А что мешает сделать метод:
private void ResetTimeouts()
{
_jumpTimeoutDelta = JumpTimeout;
_fallTimeoutDelta = FallTimeout;
}
Во-первых не придётся писать, что сбрасываем при старте - логично же, что раз метод вызывается в старте, то там идёт сброс таймаутов. Во-вторых, можно переиспользовать этот метод в других частях кода.
Дальше просто поскидываю такие кусочки кода. Посмотрите, как это комично выглядит:
// set sphere position, with offset
Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset,
transform.position.z);
// clamp our rotations so our values are limited 360 degrees
_cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);
// Cinemachine will follow this target
CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride, _cinemachineTargetYaw, 0.0f);
// set target speed based on move speed, sprint speed and if sprint is pressed
float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;
// reset the fall timeout timer
_fallTimeoutDelta = FallTimeout;
❤3👍1🔥1
Forwarded from Soulshift | ALPHA
🔥 Привет, герои Emberfall!
Рады сообщить, что регистрация и авторизация в игре работают на 100%! Теперь вы можете:
- Создать аккаунт: нажмите SIGN UP, придумайте уникальный Nickname и пароль
- Войти в игру: нажмите LOGIN или отметьте «Remember me» для быстрого доступа
- Восстановить доступ: нажмите Forgot Password? и получите ссылку для сброса пароля
Готовьтесь к новому приключению: собирайте отряды героев, прокачивайте умения и побеждайте в эпических сражениях!
Подписывайтесь на канал, чтобы первыми узнать дату закрытого бета-тестирования и получить эксклюзивные бонусы.
Вперед, навстречу легендам Emberfall! ⚔️✨
Рады сообщить, что регистрация и авторизация в игре работают на 100%! Теперь вы можете:
- Создать аккаунт: нажмите SIGN UP, придумайте уникальный Nickname и пароль
- Войти в игру: нажмите LOGIN или отметьте «Remember me» для быстрого доступа
- Восстановить доступ: нажмите Forgot Password? и получите ссылку для сброса пароля
Готовьтесь к новому приключению: собирайте отряды героев, прокачивайте умения и побеждайте в эпических сражениях!
Подписывайтесь на канал, чтобы первыми узнать дату закрытого бета-тестирования и получить эксклюзивные бонусы.
Вперед, навстречу легендам Emberfall! ⚔️✨
🔥2❤1👍1
Предположим мы меняем позицию и вращение объекта, например:
IDE -шка выдаст вот такое сообщение: "Assigning position and rotation sequentially could be optimized." ("Можно оптимизировать последовательное назначение положения и поворота").
Послушаемся и применим рекомендации, получится следующее:
Такое объединение оправданно, т.к. SetPositionAndRotation() обновляет позицию и вращение за один вызов. Движок вычисляет мировые преобразования только один раз. А вот раздельные присваивания (position и rotation) приводят к двум отдельным операциям, каждая из которых вызывает пересчёт матриц преобразования, коллизий и других зависимых компонентов.
В этом случае без предъяв. Но когда вы пишите собственные методы, избегайте "и" в их названии. Если в голову приходит назвать через "And", то скорее всего это 2 разных метода и логику надо на них разделить. Например, CalculateAndShoot() - тут одна часть вообще математическая, которую иногда даже нет необходимости хранить конкретно в этом классе, а вторая отвечает за стрельбу. Или, например, PlaySoundAndAnimate() - сомнительное название. А скорее всего они вообще окажутся в разных классах и встретятся лишь в каком-нибудь методе типа OnPressJump(), который подписан на событие _input.JumpPressed += OnPressJump.
Такая вот инфа.
Интересно ли вам углубиться в код-стайл?
🔥 - да
💩 - нет
private void Update()
{
_transform.position = _position;
_transform.rotation = _quaternion;
}
IDE -шка выдаст вот такое сообщение: "Assigning position and rotation sequentially could be optimized." ("Можно оптимизировать последовательное назначение положения и поворота").
Послушаемся и применим рекомендации, получится следующее:
private void Update()
{
_transform.SetPositionAndRotation(_position, _quaternion);
}
Такое объединение оправданно, т.к. SetPositionAndRotation() обновляет позицию и вращение за один вызов. Движок вычисляет мировые преобразования только один раз. А вот раздельные присваивания (position и rotation) приводят к двум отдельным операциям, каждая из которых вызывает пересчёт матриц преобразования, коллизий и других зависимых компонентов.
В этом случае без предъяв. Но когда вы пишите собственные методы, избегайте "и" в их названии. Если в голову приходит назвать через "And", то скорее всего это 2 разных метода и логику надо на них разделить. Например, CalculateAndShoot() - тут одна часть вообще математическая, которую иногда даже нет необходимости хранить конкретно в этом классе, а вторая отвечает за стрельбу. Или, например, PlaySoundAndAnimate() - сомнительное название. А скорее всего они вообще окажутся в разных классах и встретятся лишь в каком-нибудь методе типа OnPressJump(), который подписан на событие _input.JumpPressed += OnPressJump.
Такая вот инфа.
Интересно ли вам углубиться в код-стайл?
🔥 - да
💩 - нет
🔥10
🚀 Не просто кодстайл, а философия читаемого кода в Unity
Привет, коллеги! 👋 Сегодня хочу показать вам не просто список правил, а целостный подход к написанию кода на C# в Unity, который делает его предсказуемым, читаемым и быстрым. Тут не всё, смотрите прикреплённый в комментариях файл (вообще я его составлял для того, чтобы закидывать первым же сообщением в нейросеть и на дальнейшие вопросы получать ответы уже в понятной для меня стилистике).
Вот несколько ключевых принципов, которые я использую:
1. 🤫 Инкапсуляция
Почему так? Это защита от хаоса: Никто извне не сможет изменить скорость как захочет.
Явность намерений: Поле публично только для инспектора, а не для других скриптов.
Контроль: Вся логика изменения значения находится в одном месте.
Если надо будет получить значение, то будем передавать через свойство, а изменять через метод с валидацией, например:
2. 📖 Код как техническая документация
Я избавляюсь от комментариев-костылей. Для этого вместо, например, void Proc() пишу полностью void ProcessPlayerInput().
Не "dir", а "direction", не "rb", а "rigidbody" и т.д. Вообще не стоит стремиться сокращать, буквы в коде абсолютно бесплатные )
Имя метода должно однозначно говорить о его цели, а код говорить сам за себя.
Но если ваш класс называется Health, то не надо называть поле _healthValue. Нет необходимости повторять имя класса в полях и методах. Это избыточно. Например, я обращаюсь к классу извне и получаю значение: "float переменная = _health.HealthValue;" - хуже, чем "float переменная = _health.Value;"
3. ⚡️Микро-оптимизации на уровне привычки
Обратите внимание на порядок операций:
Современное железо разницы особо не почувствует, но Visual Studio скорее всего предложит вам поменять операнды местами. Поэтому я включаю это правило в запрос нейронкам.
4. 🧠 Психология именования
Методы — это глаголы: CalculatePath(), TryGetComponent(), ShowInfo().
bool-переменные — это вопрос: isGrounded, canAttack, hasTarget.
Коллекции — во множественном числе: List<Enemy> _enemies.
А ещё следует избегать неоднозначных названий, типа Check - т.к. неясно - возвращает этот метод значение или просто проверяет внутри себя и сохраняет значение в поле. Методы, возвращающие булево значение, можно называть так же с Is, Can, Has. Возвращающие методы с Get только предоставляют инфу, а с Give – отдают данные из метода, с удалением этих данных в классе.
5. 🧼 Чистый и безопасный C#
Явная типизация: List<Vector3> points вместо var points. Читаемость важнее, чем удобство записи. Я хочу видеть тип значения, понимать, с чем работаю без дополнительных манипуляций со всплывающими подсказками.
Главный принцип: Код должен читаться как интересная техническая книга, а не как древние руны, которые нужно расшифровывать.
А что вы думаете? Какое ваше самое главное правило в кодстайле, без которого вы не можете работать? Я вообще предлагаю прям поболтать на эту тему, т.к. она куда обширнее, чем можно было бы рассказать одной публикацией. Буду ждать вас в комментариях! 👇
Привет, коллеги! 👋 Сегодня хочу показать вам не просто список правил, а целостный подход к написанию кода на C# в Unity, который делает его предсказуемым, читаемым и быстрым. Тут не всё, смотрите прикреплённый в комментариях файл (вообще я его составлял для того, чтобы закидывать первым же сообщением в нейросеть и на дальнейшие вопросы получать ответы уже в понятной для меня стилистике).
Вот несколько ключевых принципов, которые я использую:
1. 🤫 Инкапсуляция
// Вместо:
public float Speed
// Пишем:
[SerializeField] private float _speed;
Почему так? Это защита от хаоса: Никто извне не сможет изменить скорость как захочет.
Явность намерений: Поле публично только для инспектора, а не для других скриптов.
Контроль: Вся логика изменения значения находится в одном месте.
Если надо будет получить значение, то будем передавать через свойство, а изменять через метод с валидацией, например:
public float Speed => _speed;
public void SetSpeed(float value)
{
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value), "Скорость не может быть отрицательной");
_speed = value;
}
2. 📖 Код как техническая документация
Я избавляюсь от комментариев-костылей. Для этого вместо, например, void Proc() пишу полностью void ProcessPlayerInput().
Не "dir", а "direction", не "rb", а "rigidbody" и т.д. Вообще не стоит стремиться сокращать, буквы в коде абсолютно бесплатные )
Имя метода должно однозначно говорить о его цели, а код говорить сам за себя.
Но если ваш класс называется Health, то не надо называть поле _healthValue. Нет необходимости повторять имя класса в полях и методах. Это избыточно. Например, я обращаюсь к классу извне и получаю значение: "float переменная = _health.HealthValue;" - хуже, чем "float переменная = _health.Value;"
3. ⚡️Микро-оптимизации на уровне привычки
Обратите внимание на порядок операций:
// Медленнее (умножение вектора на скаляр)
transform.position += transform.forward * _speed * Time.deltaTime;
// Быстрее (умножение скаляров между собой)
transform.position += _speed * Time.deltaTime * transform.forward;
Современное железо разницы особо не почувствует, но Visual Studio скорее всего предложит вам поменять операнды местами. Поэтому я включаю это правило в запрос нейронкам.
4. 🧠 Психология именования
Методы — это глаголы: CalculatePath(), TryGetComponent(), ShowInfo().
bool-переменные — это вопрос: isGrounded, canAttack, hasTarget.
Коллекции — во множественном числе: List<Enemy> _enemies.
А ещё следует избегать неоднозначных названий, типа Check - т.к. неясно - возвращает этот метод значение или просто проверяет внутри себя и сохраняет значение в поле. Методы, возвращающие булево значение, можно называть так же с Is, Can, Has. Возвращающие методы с Get только предоставляют инфу, а с Give – отдают данные из метода, с удалением этих данных в классе.
5. 🧼 Чистый и безопасный C#
Явная типизация: List<Vector3> points вместо var points. Читаемость важнее, чем удобство записи. Я хочу видеть тип значения, понимать, с чем работаю без дополнительных манипуляций со всплывающими подсказками.
Главный принцип: Код должен читаться как интересная техническая книга, а не как древние руны, которые нужно расшифровывать.
А что вы думаете? Какое ваше самое главное правило в кодстайле, без которого вы не можете работать? Я вообще предлагаю прям поболтать на эту тему, т.к. она куда обширнее, чем можно было бы рассказать одной публикацией. Буду ждать вас в комментариях! 👇
👍6❤2🔥1
В беседе одного из чатов подняли вопрос, а насколько это тяжёлая операция - создание объекта и какое преимущество у пула.
Вот, я написал скриптик, чтобы проверить на практике.
В первом случае инстантировал и дестроил 5000 объектов. Во втором инстантировал внутри пула при необходимости и возвращал в пул.
В случае с пулом получилось почти в 6 раз эффективнее. Создавал примитив - куб.
Но я думаю, что пулы - оптимизация. Пока проект небольшой и если нет фризов, то оптимизировать нет необходимости. Может игра вообще получится неиграбельной и проект отправится на свалку, тогда зачем заранее париться за оптимизацию.
Вот, я написал скриптик, чтобы проверить на практике.
В первом случае инстантировал и дестроил 5000 объектов. Во втором инстантировал внутри пула при необходимости и возвращал в пул.
В случае с пулом получилось почти в 6 раз эффективнее. Создавал примитив - куб.
Но я думаю, что пулы - оптимизация. Пока проект небольшой и если нет фризов, то оптимизировать нет необходимости. Может игра вообще получится неиграбельной и проект отправится на свалку, тогда зачем заранее париться за оптимизацию.
👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Кто играл в MiSide, наверно заметил, что там кнопка выхода слегка убегает от курсора.
Мне было интересно реализовать что-то подобное. Здесь две кнопки: одна храбрая - тянется к курсору, а вторая трусливая - пытается отталкиваться.
Я скину пакет в комментариях к этой записи, но учитывайте 3 момента:
1. Я позволил себе наговнокодить, т.к. знал, что менторам на проверку скидывать не придётся.
2. Это выдернуто прям из проекта и поэтому добавил заглушки, где раньше была связь с другими классами
3. TextMeshPro - эта штука в консоль выбрасывает ошибки. Их можно проигнорить, запустить демо-сцену и в PlayMode всё начнёт работать, но в идеале удалить объекты с компонентами TextMeshPro в сцене и создать заново.
Мне было интересно реализовать что-то подобное. Здесь две кнопки: одна храбрая - тянется к курсору, а вторая трусливая - пытается отталкиваться.
Я скину пакет в комментариях к этой записи, но учитывайте 3 момента:
1. Я позволил себе наговнокодить, т.к. знал, что менторам на проверку скидывать не придётся.
2. Это выдернуто прям из проекта и поэтому добавил заглушки, где раньше была связь с другими классами
3. TextMeshPro - эта штука в консоль выбрасывает ошибки. Их можно проигнорить, запустить демо-сцену и в PlayMode всё начнёт работать, но в идеале удалить объекты с компонентами TextMeshPro в сцене и создать заново.
👍3🔥3