Как сделать скрипт на c

Добавил пользователь Евгений Кузнецов
Обновлено: 10.09.2024

Знай, что я не смогу дать тебе все навыки владения языком. Но не беспокойся, для этого существует множество различных туториалов, книг, видео-лекций. Но как и в случае с иностранными языками, чтобы понять язык программирования, необходимо использовать его на практике. Поэтому мы будем писать с тобой скрипты для GTA 5.

Какие ты захочешь. Только не читерские. Я, конечно, могу взломать любую защиту, но этому учить тебя не буду, хорошо? Мы с тобой займемся скриптами для одиночной игры. Ты познакомишься с внутренним функционалом GTA 5, который довольно обширен. Он настолько огромен, что ещё не был до конца изучен, представляешь?

Но не бойся. Всё, что нужно для создания полноценного мода, уже давно известно. С этим не возникнет никаких проблем.

Прежде, чем приступить, тебе нужен софт. Скачай и установи Visual Studio . Именно в этом редакторе мы создадим с тобой первый скрипт.

Перед тобой открылась рабочая область и начальные строчки кода. Но к этому мы вернемся позже. В правой колонке найди "Обозреватель решений". Там будет отображаться созданный тобою проект. Найти там пункт "Ссылки", нажми на него правой кнопкой мыши - "Добавить ссылку". Нажми кнопку обзор и добавь файл ScriptHookVDotNet2.dll. Он должен быть установлен у тебя в игре, если ты всё же решил заниматься скриптингом

Так же к проекту необходимо подключить стандартную библиотеку Windows - System.Windows.Forms

Теперь необходимо добавить пространство имен в начало скрипта:

using GTA;using GTA.Native;using GTA.Math;using System;using System.Collections.Generic;using System.Drawing;using System.Reflection;using System.Windows.Forms;

В наш уже готовый код допишем настройки, чтобы наш класс унаследовал GTA.Script:

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

Как видишь, редактор подчеркивает эти строчки красным, якобы там ошибка. Ошибка в том, что мы только что объявили события, но не вписали их в код. Давай это исправим:

Ошибка исправлена. Теперь этот код можно запустить в игре. Но ничего не произойдет, потому что он пустой. Давай добавим что-нибудь. Например. Дадим игроку 5 звезд розыска при нажатии определенной клавиши. Что для этого нужно? Нам необходимо перехватить нажатие клавиши! Для этого мы и добавили событие KeyDown: оно срабатывает при каждом нажатии клавиш на клавиатуре, а класс KeyEventArgs содержит все данные о нажатой клавише. С помощью оператора IF мы можем узнать, нажата ли нужная нам клавиша, и если да, то мы выдадим игроку звезды розыска.

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

Наш скрипт готов. Найди в верхнем меню пункт "Сборка" - "Собрать решение".

Если всё прошло успешно, в окне ты найдешь путь к своему dll файлу. Если в процессе сборки вылезли ошибки, скидывай скриншот в комментарии, я попытаюсь тебе помочь.

Скрипт необходимо положить в папку Scripts, которая находится в корневой папке GTA 5. Если её нет, то просто создай и положи туда свой скрипт.

Давай зайдем в игру, и убедимся, что наш скрипт работает. Звезды розыска выдаются на английскую клавишу H, ты же можешь выбрать любую другую на своё усмотрение.

Данный мануал не написан мною. Я являюсь лишь его переводчиком, но также мною в данный мануал было включено кое-что из своих знаний, дабы весь туториал получился более развёрнутым и давал хорошие знания по UnityScript. Здесь собраны переведённые мною статью в официальногоScriptingReference, а также с unifycommunity. Все они объединены в один мануал, состоящий из трёх глав, где первые две главы это перевод статей с unifycommunity, а третья (И самая большая глава) содержит пока что незаконченный, но уже готовый более чем наполовину официальныйScriptingReference.

Я думаю, что данный мануал будет полезен многим новичкам на Unity, да и ветеранам будет, что прочитать, чтобы освежить память.

UnityScript представляет собой специальную версию популярного в среде Web-программирования языка JavaScript. Эта глава представляет широкий обзор языка. В последующих главах мы будем подробнее вдаваться в технику программирования на нём.

Приступая к работе

Для того чтобы назначить наш скрипт какому-либо объекту в сцене, для начала следует его создать. Итак, давайте создадим самый простой объект, на который и назначим наш скрипт. Для этого в верхнем меню Unity, необходимо выбрать пункт “GameObject –> CreateEmpty”. После этого в окне “Hierarchy” вы можете наблюдать только что созданный нами пустой объект с именем “GameObject”. Ну что же, теперь дело за малым, осталось назначить наш скрипт на этот объект, для этого просто перетащите созданный нами скрипт на данный объект.

Все назначенные вами на объект скрипты, вы всегда можете увидеть в окне “Inspector”, после того как выберете его в окне “Hierarchy”. В этом же окне вы можете изменить и значения переменных ваших скриптов.

Ну что же, после того как скрипт назначен на объект, мы можем протестировать его. Для этого просто нажмите кнопку “Play”. И в нижнем углу, в окне консоли вы сможете наблюдать появившуюся надпись “Hello, World”.

Весь код JavaScript, который написан или будет написан вами для ваших проектов. Как правило, хранится в текстовом файле с расширением .js, как и в нашем примере “helloworld.js”. Также, стоить отметить то, что после того как вы написали сценарий во встроенном редакторе Unity и сохранили его, движок автоматически компилирует его и проверяет на наличие ошибок. Это помогает вам предотвратить ошибки в игре в ходе её тестирования. И если ваш скрипт имеет ошибку, то Unity автоматически оповестит вас об этом в консоли.

Теперь мы можем приступить к изучению такой темы как “Типы”. UnityScript имеет различные ссылки и типы значений использующиеся для написания ваших скриптов. Значения и ссылки отличаются тем, как данные связаны с переменной. Для типов значений, только одна переменная связана с данными, а что же касается ссылочных типов, то они могут иметь множество переменных связанных между собой данными.

Две переменные ссылочного типа могут указывать на один и тот же экземпляр класса самостоятельно.

После того как вы запустите игры, вы увидите что назначение на intValueanotherValue копирует данные, в то время как назначение на classVaranotherValue копирует указывает две переменные с теми же данными.

Предопределённые типы

UnityScript имеет следующие стандартные типы:

Дополнительные встроенные типы перечислены в справочнике ScriptingReference.

Стандартные типы могут быть преобразованы. Явные преобразования поддерживаются для ссылочных типов, но не для предопределённых типов значений. Будьте осторожны при преобразовании между предопределёнными типами, которые имеют различные минимальные и максимальные диапазоны. Например:

В UnityScript есть два типа массивов – встроенные массивы и массивы класса. Массивы позволяют хранить несколько объектов в одной переменной. Вот пример того что можно сделать с массивом класса:

Встроенные массивы очень быстры и эффективны, но они не могут быть изменены. Также их можно отредактировать в окне “Inspector”. Вот простой пример того как можно использовать встроенные массивы:

Также, встроенные массивы полезны при критичной производительности кода.

Обычные массивы JavaScript могут быть изменены, отсортированы, а также могут проводить другие операции из массива класса. Также JavaScript массивы не отображаются в инспекторе.

Сценарий, написанный вами внутри одного или же нескольких файлов, как правило, имеет хотя бы одно определение классов, имеющих то же имя что и сам файл. Например, скрипт MyJavaScript.jsбудет содержать определение MyJavaScript класса. Обычно Unity автоматически создаёт класс с правильным именем, и всё что находится внутри этого файла будет членом этого класса.

Ключевые слова

Ключевое слово является идентификатором, как последовательность символов которая зарезервирована.

Ключевые слова Unity Script:

Литерал – запись в исходном коде, представляющая собой фиксированное значение.

Есть два булевых(boolean) значения: правда(true) и ложь(false).

Тип boolean является логическим.

Целые литералы используются для значений целого типа, таких как int, uint, long и ulong.

Десятичные литералы используются для десятичных цифр, где количество знаков после запятой одно из следующих:

1 2 3 4 5 6 7 8 9

Шестнадцатеричные целые литералы

Шестнадцатеричные целые литералы состоят из шестнадцатеричных цифр, где шестнадцатеричные цифры одно из следующих:

1 2 3 4 5 6 7 8 9 ABCDEFABCDEF

Реальные литералы используются для написания значений с плавающей точкой. Реальные литералы можно записать в виде:

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

Строчные литералы составляют из нуля или больших символов, заключённых в двойные кавычки.

Строка имеет тип String.

Ключевое слово null делает литерал нулевого типа.

Операторы и знаки пунктуации

Знаки пунктуации включают в себя: <> [] () . , : ;

Операторы включают в себя: + – * / % & | ^ ! = ? ++ && || > == = = => Create -> C Sharp/Boo Script menu, the created template will already contain the necessary definition.

2.Использованиефункций Awake или Start дляинициализации.

Различие между Awake и Start заключается в том, что Awake вызывается, когда загружается сцена, а Start iвызывается непосредственно перед первым вызовом Update или FixedUpdate . Все функции Awake вызываются перед любым вызовом функции Start .

3. Имя класса должно соответствовать имени файла.

5. Не используйте пространства имен.

На данный момент Unity не поддерживает размещение Ваших скриптов в пространствах имен. Это требование будет отменено в будущих версиях.

6. Только публичные поля сериализуются и показываются в инспекторе.

Приватные и защищенные поля показываются только в Debug Mode. Свойства не сериализуются и не показываются в инспекторе.

7. Избегайте использования конструкторов или инициализации переменных.

Никогда не используйте конструкторов или инициализации переменных в скриптах производных от MonoBehaviour. Вместо этого используйте функции Awake или Start для этих целей. Юнити автоматически вызывает конструктор, даже в режиме редактора. Это обычно происходит непосредственно после компиляции скрипта для установки всех переменных в значение по умолчанию. Мало того, что это может привести к вызову конструктора непредвиденное число раз, но он также может быть вызван и для префабов или неактивных игровых объектов.

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

Используйте конструктор только если вы наследуетесь от ScriptableObject.

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

Так что если Вы хотите реализовать шаблон singleton НЕ используйте конструктор. Используйте вместо него Awake. На самом деле нет причин иметь хоть какой-то код в конструкторе класса унаследованного от MonoBehaviour.

Это приводит к чрезвычайно быстрому выполнению скриптов – приблизительно в 20 раз быстрее чем традиционный javascript и на 50% медленнее чем нативный C++ код. Unity нужно некоторое время для компиляции всех Ваших скриптов когда Вы сохраняете их. Вы можете видеть что Unity еще компилирует их по маленькому вращающемуся прогрессбару в нижнем правом углу главного окна Unity.

Компиляция скриптов происходит в 4 шага:

1. Все скрипты в “Standard Assets”, “Pro Standard Assets” или “Plugins” компилируются первыми.

Скрипты в этих папках не могут напрямую обращаться к скриптам вне этих папок.

Невозможно обращаться к классам или их переменным напрямую, однако возможна коммуникация с ними с использованием GameObject.SendMessage.

2. Всескриптыв “Standard Assets/Editor”, “Pro Standard Assets/Editor” или “Plugins/Editor”компилируютсядалее.

Если Вы хотите использовать пространство имен UnityEditor тогда поместите Ваши скрипты в эти папки. Например для добавления меню или создания пользовательского мастера Вам нужно поместить Ваши скрипты в эти папки.

Эти скрипты могут иметь прямой доступ к скриптам из предыдущей группы.

3. Все другие скрипты вне “Editor” компилируются далее.

Все скрипты не в папках выше или не в папке “Editor” компилируются далее.

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

4. Все скрипты в папке “Editor” компилируются последними.

Если Вы хотите использовать пространство имен UnityEditor тогда поместите Ваши скрипты в эту папку. Например для добавления меню или создания пользовательского мастера Вам нужно поместить Ваши скрипты в эту папку.

Эти скрипты имеют доступ ко всем скриптам из всех предыдущих групп.

Добавочно любой скрипт в папке, называемой WebPlayerTemplates не компилируется восе.

Условная компиляция Conditional compilation against the Unity version.

Этот код может быть использован для учета особенностей доступных только в указанной версии Unity. Заметим, что эти определния присутствуют только начиная с версии 2.6. Будущие версии также будут предоставлять соответствующие определения для идентификации версии в Ваших скриптах.

Совместимость Unity и Mono

Некоторые функции в этом мануале (например, различные функции GetComponent) перечислены с вариантом, который имеет букву T или имя типа в угловых скобках после имени функции:

Такие функции известны как “generic” функции. Значимым для скриптинга является что вы получите указанный тип параметра и/или возвращаемого значения когда вы вызываете эти функции. В JavaScript это может быть использовано, чтобы обойти ограничения динамической типизации:

Любая функция, которая имеет generic вариант указанный в мануале позволяет использовать этот специальный синтаксис вызова.

Any questions left? Ask me!

About the author Pavel Nakonechnyy

Business Analyst & Journalist. I'm being read by future CEOs and unicorn startups founders. Follow me on Twitter, Discord, and Telegram.


Эксперт в медицинских тренажерах VR на Unity, физических симуляциях и сетевых играх.

Что такое Unity

Unity — это и среда разработки, и игровой движок, с помощью которого создаются проекты для разных платформ: ПК, мобильных устройств, игровых консолей и интернет-платформ, — поэтому он называется кроссплатформенным. В Unity есть инструменты для создания объектов, их перемещения, работы с графикой, текстурами и звуком, поэтому сделать полноценную игру с его помощью можно даже в одиночку.

Наглядный пример игры, созданной на Unity, которая поддерживает разные устройства, — Genshin Impact, успешный мультиплатформенный проект китайской студии miHoYo Limited. Более популярной стала ее мобильная версия, но пользователи могут войти в аккаунт, например, с компьютера и продолжить играть с того же момента, на котором остановились в мобильной версии. Кроме Genshin Impact, на Unity созданы такие известные проекты, как Hearthstone, Outlast, Cuphead, Pokemon GO и многие другие.

В игровой индустрии существуют десятки разных движков. Одни разработаны под конкретную игру, на других можно делать игры конкретного жанра (шутеры от первого лица, платформеры, гонки), а есть универсальные, вроде Unity, которые открывают разработчикам больше возможностей. Уникальность Unity заключается в сочетании нескольких факторов. Кроме того, что этот движок позволяет создавать проекты под разные устройства и не ограничивает разработчика конкретным жанром, он:

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

Посмотрите также: Как установить Unity

Как создать простую игру

При создании собственного проекта важно помнить, что разработка кода — это примерно 20% игры; гораздо большее значение в ней имеют другие аспекты:

Разработчик игр на Unity

Перед созданием игры важно продумать все эти моменты и представить общую картину, а также найти референсы, на которые можно ориентироваться, продумать опорные точки сюжета и механики. Для создания игры именно на Unity также пригодится понимание некоторых базовых терминов, с которыми постоянно придется сталкиваться в процессе разработки:

Русского языка в настройках нет, так что придется совершенствовать технический английский. Всего Unity занимает 11,3 Гб,поэтому перед установкой лучше проверить свободное место на диске и почистить его при необходимости.

Следующий шаг — создание Unity ID. Можно регистрироваться с помощью почты или использовать предложенные аккаунты, например Google, Facebook или Apple. Важно поставить первые две галочки: согласие с условиями использования Unity и признание политики конфиденциальности. Третья галочка — это согласие на маркетинговые рассылки, ее ставить не обязательно.

После регистрации Unity предложит создать тестовый проект Microgame. На выбор предлагается пять шаблонов:

  • LEGO Microgame;
  • шутер от первого лица;
  • картинг;
  • платформер;
  • пустой 3D-шаблон.

Можно выбрать любой из них и посмотреть, как работает создание игры в конкретном жанре. Обучающий материал пошагово демонстрирует назначение различных окон в интерфейсе и принцип работы с элементами игры: как заставить двигаться персонажей, поменять текстуру объекта или его форму. В обучении окно Scene, в котором происходит вся работа с элементами, уже заполнено различными объектами, но при создании проекта с нуля оно будет пустым.

Создание проекта

После обучения можно перейти к созданию своей первой игры на Unity с помощью кнопки NEW в меню проектов.

Новому проекту присваивается имя, выбираются место хранения на диске и темплейт — то есть шаблон для разработки, внешний вид и функционал которого зависит от количества измерений в игре. Проще начинать с 2D-проектов, так как для этого формата создано больше готовых ассетов. Конечно, можно сразу начать делать 3D-игры, но в этом случае многие элементы и анимации придется самостоятельно создавать с нуля или выделять бюджет на то, чтобы делегировать эту часть работы другим специалистам.

Настройка интерфейса

В стандартном интерфейсе проекта шесть элементов рабочей области:

  1. Верхняя панель инструментов— в ней находятся стандартные вкладки File, Edit, Help, как во многих других интерфейсах, а также вкладки Assets, GameObject, Components и Window.
  2. Scene — окно сцены, в котором выстраивается игровое пространство (элементы игрового мира, текстуры, фигурки персонажей и прочее).
  3. Games — это окно игры, в котором можно посмотреть глазами пользователя, как будут двигаться элементы и работать игровые механики.
  4. Hierarchy — окно иерархии, в нем перечислен список всех элементов (GameObject), которые помещены в окно Scene.
  5. Project — это система папок, в которых хранятся ассеты по категориям (текстуры, шрифты, звуки и т.д.).
  6. Inspector — окно для изменения элементов игры, их размера, цвета, положения в пространстве и других характеристик.


Добавление объекта

Объекты на экран Scene можно добавить из Asset Store. Для этого на панели инструментов нужно кликнуть на вкладку Window –> General –> Asset Store.

В строке поиска можно по названиям найти нужные компоненты, например, сет Free Platform Game Assets.

Как и другие ассеты, он загружается с помощью кнопки Import.

Перед загрузкой появится список всех компонентов, которые содержит этот пакет; некоторые из них можно исключить. Если в списке есть персонажи, текстуры или другие элементы, которые вам не нужны, можно просто снять галочки, и пакет загрузится без них.

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

Шаг 2. Перенести в область Scene

Работа со скриптами

За поведение игровых объектов отвечают присоединенные к ним компоненты (Components). Базовый компонент любого объекта — Transform, он отвечает за положение элемента в окне Scene, возможность поворачивать и масштабировать его. К базовому компоненту можно добавить, например, Renderer, который меняет цвет, или RigidBody, который отвечает за массу и физику объекта. Но кроме базовых компонентов, объектам можно задавать особые условия, и для этого как раз используются скрипты.

Базовые элементы скриптов — это:

  • using — элемент в коде, который подключает библиотеки;
  • public class — в этой строке обычно прописан класс MonoBehaviour, он содержит набор функций, необходимых для работы скрипта;
  • void — те самые функции, с их помощью прописываются действия, происходящие в игре.

Рассмотрим, например, функцию start. Любое действие в ней произойдет только один раз, когда запустится игра. Пропишем здесь print (“Hi”).

И можно заметить, что в консоли это слово выводится один раз.

Функция update — повторяющаяся, ее можно использовать, например, для передвижения объекта. Для этого в скрипте задается переменная int i = 0, она выводится на экран с помощью функции print (i) и увеличивается на одну единицу за каждый шаг с помощью i++.

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

Настройка триггеров

Для понимания сути триггеров важно усвоить, что такое коллайдер (Collider). Это компонент, который присваивается объекту в пространстве игры, задает форму и делает его твердым, недоступным для прохождения сквозь него. Например, если мы разместим монетку в 2D-пространстве и захотим сделать так, чтобы она упала на платформу, то без использования компонента Collider ничего не получится — монетка пролетит сквозь платформу.

Поэтому обоим объектам необходимо присвоить компонент Box Collider 2D — это тонкая зеленая линия, которая обводит элементы по контуру, и за счет этой рамки они становятся твердыми, то есть один не может пройти сквозь другой.

Так объекты обязательно соприкоснутся и монета встанет на платформу.

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

Чтобы создать триггер, нужно накинуть тот же самый компонент коллайдера, но поставить галочку Is Trigger.

Триггеры распознают три варианта взаимодействия области на карте и объекта:

  • OnTriggerEnter — объект зашел в зону;
  • OnTriggerStay — объект находится в зоне;
  • OnTriggerExit — объект покинул зону.

Что дальше?

Разработчик игр на Unity

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

В данной рубрике будут простые и короткие примеры как сделать ваш код более красивым и читаемым.

Оператор ?? Называется оператором null-объединения, он возвращает левое значение, если оно не равно null, в противном случае возвращает правое.

Object x = null ;
Object y = x ?? 100;

В конечно результате y будет равен 100, так как x равен null.

Иногда мы обращаемся к объекту, а он может быть равен null, тогда надо перестраховаться и сделать проверку на null, которая будет выглядеть вот так:

if(_player.Gun != null)
_player.Gun.SomeMethod() ;

Но можно сделать данное выражение более красивым и приятным для чтения:
_player?.Gun.SomeMethod();

Александр Касаткин


Александр Касаткин

Егор Полянский


Егор Полянский

Liskov Substitution Principle

На самом деле, один из тех принципов, после прочтения формулировки которого, мой мозг слегка взрывался и просился закрыть эту вкладку в браузере. Приведу несколько формулировок, одна с википедии, другая с сайта metanit:
Показать полностью.

Когда я читал это в первый раз, то мне показалось, что меня изнасиловали.
А теперь я попытаюсь дать вам определение этого принципа простыми словами и привести пример, который останется в вашей голове на всю оставшуюся жизнь.

Итак, принцип подстановки Барбары Лисков. Он же Liskov Substitution Principle. Он же LSP. Простыми словами принцип звучит так:

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

Т.е. Если у вас есть класс Enemy и она весит на объекте в игре, все работает и все прекрасно, потом вы решили создать класс Zombie, который наследуется от Enemy, и у вас должна быть возможность заменить класс Enemy на объекте на Zombie и ваша игра должна продолжить функционирование.

Драма в 3-х актах:
Акт 1.

Приходя утром на работу вы открываете свой трекер задач и видите следующее: нужно реализовать игровую бомбу. Вы садитесь кодить, сама задача показалась вам очень простой и буквально за пару часов вы справились. Делов-то добавить красивые эффект, таймер, красивый эффект и нанесение урона.

Акт 2. Первые проблемы.

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

Акт 3. Решение проблемы.

Вы понимаете, что все ваши враги, это дочерние классы Enemy, в котором есть метод GetExplosionDamage(). Хммм, думаете вы, а что если просто сделать его виртуальным и в дочерних классах просто дописывать то, что надо. Таким образом вы сможете написать один раз нанесение бомбой урона через метод GetExplosionDamage(), а уже если надо, то в дочерних классах дописать получение 0 урона или наоборот двойной порции. Вот оно, решение найдено, теперь все работает отлично и гибко!

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

Всем спасибо за внимание.

Александр Касаткин


Александр Касаткин

Саня Гончаров

SOLID. Часть 2.
Open/Closed Principle
Принцип закрытости/открытости:
Объекты и сущности должны быть открыты для расширения, но закрыты для модификации.

Показать полностью.
А теперь капнем глубже и простыми словами. Примером будет выступать ситуация, в которой побывает почти каждый программист в геймдеве. Надо разработать логику атаки персонажа. Далеко ходить не будем, возьмем того же робота из прошлого примера. Вы наливаете себе чашечку кофе, уже представляете в голове, как у вас будет отдельный класс под атаку робота, ведь вы уже знакомы с принципом единственной ответственности, и начинаете творить. Спустя некоторое время, вы откидываетесь на спинку стула и смотрите на свое творение. Оно почти прекрасно, думаете вы, перетаскиваете вашу карточку в трекере заданий в done, и в отличном расположении духа отправляетесь домой. Но, спустя некоторое время, вы видите у себя в задачах, что робот теперь может не только пулями стрелять, но и огнеметом обзавелся. Так, думаете вы, надо подредактировать код, докинуть в него конструкцию switch или воспользоваться старым добрым if. Спустя несколько часов работы, все готово, робот теперь может и огоньком врага подогреть и пулями отпугнуть. Но еще через недельку, вам приходит задача, что он теперь может и лазером жахнуть, ладно, думаете вы, от еще одного if никто не умрет. Еще неделя, еще один тип атаки, еще if… Спустя несколько месяцев скрипт вашей атаки уже по размерам может посоревноваться с войной и миром. Такс, думаете вы, где-то я явно оплошал.

А вот как было бы правильно. Прочитав эту статью, вы набрались знаний и сели заново проектировать атаку робота. Так, думаете вы, логика атаки явно будет изменяться, так что надо предусмотреть ее модификацию, но сделать так, чтобы основной класс обработки атаки не раздувался. Поэтому вы прописываете базовую логику атаки, а-ля просто ее запуск по нажатию на клавишу. Но сам запуск логики мы будем производить через интерфейс, т.е. само нанесение урона, спавна каких-то эффектов и еще особенности, которые будут присущи какому-нибудь типу атаки, будут уже в классе, которые реализует интерфейс IAttackType. В этому интерфейсе будет всего одна функция Attack(). А классы LazerAttack, BulletAttack и т.д. будут реализовывать логику атаки. Таким образом у вас будет класс PlayerAttack, а в нем будет переменная типа IAttackType, которая будет в себе содержать ссылку, на нужный нам класс, который реализует интерфейс IAttackType. Таким образом, когда вас попросят реализовать еще какой-нибудь вид атаки, то вы просто создадите класс, который реализует интерфейс IAttackType и все. А когда вашего PlayerAttack не изменится. А подмену ссылки в зависимости от выбранного вам типа атаки, можете сделать в классе AttackTypeSelect. Теперь вы можете создать новые типы атак не модифицирую PlayerAttack и соблюдая принцип открытости/закрытости.

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

Все спасибо за внимание!

Саня Гончаров

Вадим Сабастьян

Саня Гончаров

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

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

SOLID — принципы объекто-ориентированногопрограммирования.

SOLID это аббре­ви­а­тура пяти основ­ных прин­ци­пов про­ек­ти­ро­ва­ния в объ­ектно-ори­ен­ти­ро­ван­ном про­грам­ми­ро­ва­нии — Single responsibility, Open-closed, Liskov substitution, Interface segregation и Dependency inversion (прин­ципы един­ствен­ной ответ­ствен­но­сти, откры­то­сти / закры­то­сти, под­ста­новки Бар­бары Лис­ков, раз­де­ле­ния интер­фейса и инвер­сии зависимостей)

Аббре­ви­а­тура SOLID была пред­ло­жена Робер­том Мар­ти­ном, авто­ром несколь­ких книг, широко извест­ных в сооб­ще­стве разработчиков. Эти прин­ципы поз­во­ляют стро­ить на базе ООП мас­шта­би­ру­е­мые и сопро­вож­да­е­мые про­грамм­ные про­дукты с понят­ной биз­нес-логи­кой.

Single responsibility (прин­цип един­ствен­ной ответ­ствен­но­сти)
Open-closed (прин­цип откры­то­сти / закры­то­сти)
Liskov substitution (прин­цип под­ста­новки Бар­бары Лис­ков)
Interface segregation (прин­цип раз­де­ле­ния интер­фейса)
Dependency inversion (прин­цип инвер­сии зави­си­мо­стей)

Single responsibility principle
Итак, начнем с одного из самых простых принципов, коим является принцип единственной ответственности. Он гласит, что у вашего класса должна быть только одна причина для изменения. А под обязанностью здесь понимается набор функций, которые выполняют единую задачу. Суть этого принципа заключается в том, что класс должен выполнять одну единственную задачу. Но, думаю, тут лучше всего перейти сразу к примеру, так будет понятнее. Полагаю, что подавляющее большинство читающих именно создатели игр, поэтому и пример будет основан на моменте из разработки игры.

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

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

Но давайте вернемся назад во времени и вы подойдет к этой задаче с умом. Поймете, что каждому действию можно написать свой класс, ходить он будет в MoveLauncher, стрелять в AttackLauncher, и т.д., и у вас получится много маленьких и аккуратных классов, и потом, когда вы захотите что-то убрать или добавить, вам придется убрать один тип лаунчера и вставить другой. Система будет минималистична и понятна. Он стал словно модульным и каждый модуль отвечает за свою функцию(обязанность). Так что вы можете легко убрать какой-то и вставить новый. Мне сразу в голову приходит один телефон, который когда-то активно рекламировали.

И пускай ваш код, будет таким же, как и это телефон!

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

Всем спасибо за прочтение!

Когда я общался с другими разработчиками, меня часто интересовал вопрос: какие вопросы вы задаете на собеседованиях на middle, junior или senior unity3d разработчик? И почти каждый раз упоминались принципы программирования, так что я решил посвятить небольшую статью именно им. Также они в целом будут полезны для того, чтобы сформировать правильный подход к написанию кода.
Показать полностью. Сейчас есть программисты, у которых 2-3 года опыта работы, но они не знают простых правил написания хорошего и качественного кода, это будет скорее вводная часть, потому что самый сок - это SOLID принципы, но их мы оставим для второй части.

В про­ек­ти­ро­ва­нии сле­до­ва­ние прин­ципу KISS выра­жа­ется в том, что:

Сле­до­ва­ние прин­ципу DRY при­во­дит к модуль­ной архи­тек­туре при­ло­же­ния и к чёт­кому раз­де­ле­нию ответ­ствен­но­сти за биз­нес-логику между про­грамм­ными клас­са­ми. А это — залог сопро­вож­да­е­мой архи­тек­ту­ры. Хотя чаще не DRY при­во­дит к модуль­но­сти, а уже модуль­но­сть, в свою оче­редь, обес­пе­чи­вает прин­ци­пи­аль­ную воз­мож­ность соблю­де­ния этого прин­ципа в боль­ших про­ек­тах.

Принципы программирования SOLID.
SOLID - это принципы проектирования, которые позволяют нам справляться с большинством проблем проектирования программного обеспечения. Роберт К. Мартин составил эти принципы в 1990-х годах. ОНи предоставляют нам способы перехода от тесно связанного кода и небольшой инкапсуляции к желаемым результатам слабо связанных и инкапсулированных элементов. SOLID является аббревиатурой от следующего.
S: Принцип единой ответственности (SRP)
O: Принцип открытости и закрытости (OSP)
L: Принцип замещения Лисков (LSP)
I: Принцип разделения интерфейса (ISP)
D: Принцип инверсирования зависимостей (DIP)

Читайте также: