скрипт не прикрепляется к объекту в unity

Можно ли в Unity использовать скрипт, который не прикреплен к объекту на сцене?

Здравствуйте.
Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона.
Благодарю

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

seaman
Извините, я не понял. Вы предложили два метода?
Я так понимаю что если статический класс, то все поля тоже статик должны быть.
А можно без статического класса это сделать?

Dexter384
>А можно без статического класса это сделать?

Femidko
> ScriptableObject
>
> http://docs.unity3d.com/ScriptReference/ScriptableObject.html
Лайк!

поздний апдейт: внезапно нашел нужный кусок доков. тупой вопрос снимается

А в Unity разве нет объекта класса User? В движке ShiVa он есть, один экземпляр создается автоматически и живет во время всей работы приложения, он не привязан к сцене, но на него тоже вешаются скрипты.

Virtex
> А в Unity разве нет объекта класса User?
Нет.

FireFenix
Воспользовался вашей реализацией. Но возник вопрос. Почему если оставить класс наследуемым от MonoBehaviour
то A._Instance = new A(); всегда остается равным нулю?

Dexter384
> Воспользовался вашей реализацией. Но возник вопрос. Почему если оставить класс наследуемым от MonoBehaviour то A._Instance = new A(); всегда остается равным нулю?
Потому, что классы Unity не должны создаваться через констурктор, а должны через AddComponent или сниматься через GetComponent после инстанса префаба

FireFenix
> Singleton
Благодарю. А можете подсказать как сделать синглтон, который наследуется от MonoBehaviour?

Источник

Unity3d. Уроки от Unity 3D Student (B04-B08)

Предыдущие уроки вы можете найти в соответствующем топике.

Теперь в каждом посте в скобках (в конце) будут указываться номера уроков. Буква в начале номера обозначает раздел (B-Beginner, I — Intermediate).

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

Базовый Урок 04 — Уничтожение объектов

В уроке рассказывается как удалять объекты со сцены, использую команду Destroy (уничтожить).

Создайте пустую сцену и добавьте в нее сферу (GameObject->Create Other->Sphere) и куб (GameObject->Create Other->Cube). Куб назовем “Box”. Расположите объекты как показано на рисунке ниже.
скрипт не прикрепляется к объекту в unity. 602c7453af013d9a7c89af9980c71bb7. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-602c7453af013d9a7c89af9980c71bb7. картинка скрипт не прикрепляется к объекту в unity. картинка 602c7453af013d9a7c89af9980c71bb7. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Добавьте C#-Скрипт (Project View->Create->C# Script) и назовите его Destroyer. Как уже говорилось, при создании C#-скрипта Unity создает некий каркас, состоящий из подключенных библиотек и основного класса (используемого скриптом) с методами Start() и Update(). В Базовом Уроке 02 (основы ввода) использовался метод Update(), который вызывается каждый кадр. В данном случае мы воспользуемся методом Start(), который выполняется сразу после загрузки сцены. Добавим в тело метода Start() функцию Destroy() и передадим в нее gameObject, указав таким образом, что скрипт должен уничтожить объект, компонентом которого он является:

Добавим скрипт к сфере. Сделать это можно несколькими путями. Перетащив скрипт из Project View на сферу в Scene View.
скрипт не прикрепляется к объекту в unity. 211fb84cd94a7d1a3c1eda4e5cb08b04. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-211fb84cd94a7d1a3c1eda4e5cb08b04. картинка скрипт не прикрепляется к объекту в unity. картинка 211fb84cd94a7d1a3c1eda4e5cb08b04. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Или на имя объекта в Hierarchy.
скрипт не прикрепляется к объекту в unity. 36829431b600476969497bef38ddfadc. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-36829431b600476969497bef38ddfadc. картинка скрипт не прикрепляется к объекту в unity. картинка 36829431b600476969497bef38ddfadc. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Так же можно выбрать сферу и добавить скрипт через меню компонентов (Component->Scripts->Destroyer) или просто перетащив скрипт в Inspector View выбранного объекта.
скрипт не прикрепляется к объекту в unity. 45d1277d36cf8b93a312cce116807b48. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-45d1277d36cf8b93a312cce116807b48. картинка скрипт не прикрепляется к объекту в unity. картинка 45d1277d36cf8b93a312cce116807b48. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Снова выберите сферу и убедитесь, что среди компонентов присутствует ваш скрипт.
скрипт не прикрепляется к объекту в unity. b0403. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0403. картинка скрипт не прикрепляется к объекту в unity. картинка b0403. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Нажмите на Play и вы увидите, что сразу после загрузки сцены сфера исчезает.
скрипт не прикрепляется к объекту в unity. b0404. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0404. картинка скрипт не прикрепляется к объекту в unity. картинка b0404. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Давайте теперь попробуем уничтожить другой объект. Для этого нам понадобится статический метод Find класса GameObject. Заменим код в методе Start() следующим:

Примечание от автора перевода: Обратите внимание, что во втором случае мы передаем значение, вызывая статическую функцию, поэтому пишем имя класса (GameObject — с большой буквы), в то время как в первом мы передаем объект этого класса (gameObject — с маленькой буквы). В противном случае компилятор выдаст ошибку:

error CS0176: Static member `UnityEngine.GameObject.Find(string)’ cannot be accessed with an instance reference, qualify it with a type name instead

что переводится как:
“статический член UnityEngine.GameObject.Find(string) не может быть доступен по ссылки экземпляра (класса), вместо этого определите (вызовите) его с именем типа.”

Сохраним изменения в коде скрипта. Скрипт не требуется убирать со сферы и добавлять к нашему кубу, т.к. назависимо от того, к какому объекту он теперь прикреплен, скрипт будет искать любой объект (на сцене) с именем Box. Нажмем Play и увидим как теперь сфера остается в сцене, а куб пропадает.
скрипт не прикрепляется к объекту в unity. b0405. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0405. картинка скрипт не прикрепляется к объекту в unity. картинка b0405. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Что делать, если нам требуется уничтожить объект не сразу, а спустя какое-то время? Это можно сделать передав значение во 2ой параметр функции Destroy:

Нажмите Play и убедитесь, что куб изчезает через 3и секунды после того, как сцена целиком загрузится.

Дополнительные материалы:

Базовый Урок 05 — Реализация создание объектов

В уроке рассказывается как создавать объекты в сцене в реальном времени (runtime), используя префабы и команду Instantiate (инстанциирование)

Если вы хотите добавлять объекты на сцену, когда сцена уже загружена, то вам требуется использовать скрипты, а точнее команду Instantiate().

Загрузите сцену из Базового урока 03 (Префабы) или создайте такую же новую. В нашей сцене присутствует префаб BouncyBox.
скрипт не прикрепляется к объекту в unity. a9c20463392be04283ed51279a6ff151. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-a9c20463392be04283ed51279a6ff151. картинка скрипт не прикрепляется к объекту в unity. картинка a9c20463392be04283ed51279a6ff151. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Нажмите Play и убедитесь, что куб по-прежнему падает и отталкивается от поверхностей.
Теперь удалите со сцены экземпляр BouncyBox.
скрипт не прикрепляется к объекту в unity. b5b083bee9d81941b87ae0365a998697. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b5b083bee9d81941b87ae0365a998697. картинка скрипт не прикрепляется к объекту в unity. картинка b5b083bee9d81941b87ae0365a998697. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

После этого добавьте пустой объект (напоминаю, GameObject->Create Empty или Ctrl + Shift + N в Windows, Cmd + Shift + N в MacOS). Расположите его примерно в том месте, где раньше был экземпляр BouncyBox.
скрипт не прикрепляется к объекту в unity. e43972c0f39feb3c235d00f722fdf28d. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-e43972c0f39feb3c235d00f722fdf28d. картинка скрипт не прикрепляется к объекту в unity. картинка e43972c0f39feb3c235d00f722fdf28d. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Создадим C#-Скрипт и назовем его Creater. Начнем редактирование скрипта. Заведем открытую (public) переменную типа GameObject и назовем ее thePrefab. Модификатор public требуется указывать, если, например, вы хотите передавать значение переменной через Inspector View. После чего в теле функции Start() создадим еще один GameObject (с именем instance) и проинициализируем его значением с помощью статической функции Instantiate().

Рассмотрим метод Instantiate() подробнее.

Метод клонирует объект original с заданными вектором положения (position) и кватернионом поворота (rotation).
Тип Vector3 является обычным 3х компонентым вектором (аналогично вектору из R 3 ).
Тип Quaternion — кватернион, задающий поворот объекта.

Добавьте скрипт к пустому объекту (c именем GameObject).Напоминаю, поскольку thePrefab объявлен с модификатором public, вы можете задавать его начальное значение прямо в Inspector View (у соответствующего компонента, то есть в нашем случае это Creator у GameObject’а). Перетащите наш префаб в место указания значения (или выберете его из списка, кликнув на кружок справа).
скрипт не прикрепляется к объекту в unity. 5871c6be3bf62675e92f57fd8f92d3a3. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-5871c6be3bf62675e92f57fd8f92d3a3. картинка скрипт не прикрепляется к объекту в unity. картинка 5871c6be3bf62675e92f57fd8f92d3a3. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Нажмем Play и увидим, что на сцене появился наш прыгающий кубик.
скрипт не прикрепляется к объекту в unity. b0504. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0504. картинка скрипт не прикрепляется к объекту в unity. картинка b0504. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Но наш кубик прыгает просто вверх и вниз, потому что не имеет начального угла поворота. Выберите GameObject и поверните его под небольшим углом.

Теперь, нажав Play, вы увидите, что кубик падает и отталкивается под различными углами.
скрипт не прикрепляется к объекту в unity. e8527b147def4aec38429464f65ed7bc. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-e8527b147def4aec38429464f65ed7bc. картинка скрипт не прикрепляется к объекту в unity. картинка e8527b147def4aec38429464f65ed7bc. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Дополнительные материалы:

Базовый Урок 06 — Простой таймер

В данном уроке рассказывается как в Unit при помощи скриптов
создавать простой таймер, используя Time.deltaTime и переменную типа float.

Воспользуемся сценой из предыдущего урока (с пустым игровым объектом,
генерирующим экземпляры префаба, т.е. BouncyBox).
скрипт не прикрепляется к объекту в unity. a8f2f897ce9a8b26dfa0a36a26dd949e. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-a8f2f897ce9a8b26dfa0a36a26dd949e. картинка скрипт не прикрепляется к объекту в unity. картинка a8f2f897ce9a8b26dfa0a36a26dd949e. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Создадим С#-скрипт и назовем его Timer. Добавим переменную myTimer, и напишем следующий код.

Сохраняем скрипт и переключаемся назад в Unity. Добавим скрипт к объекту GameObject.
скрипт не прикрепляется к объекту в unity. b0601. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0601. картинка скрипт не прикрепляется к объекту в unity. картинка b0601. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Напомню, т.к. myTimer объявлена открытой (public), то в Inspector View вы можете менять ее начальное значение.

Жмем Play. Как только значение myTimer упадет до нуля, в статус баре вы увидите строку GAME OVER. Значение переменной myTimer будет продолжать опускаться (это можно увидеть в Inspector View).
скрипт не прикрепляется к объекту в unity. b0602. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0602. картинка скрипт не прикрепляется к объекту в unity. картинка b0602. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Для того, чтобы переменная myTimer не опускалась ниже нуля, добавим еще одно ветвление в функцию Update(), в итоге мы получаем следующий код:

Нажмем Play и проследим за поведением переменной myTimer. Когда ее значение будет достаточно близким к нулю, то оно перестанет изменяться.
скрипт не прикрепляется к объекту в unity. b0603. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0603. картинка скрипт не прикрепляется к объекту в unity. картинка b0603. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Дополнительные материалы:

Базовый Урок 07 — Основы движения

В уроке рассказывается, как двигать объекты c помощью функции transform.Translate.

Создадим сцену с кубом, камерой и источником света.
скрипт не прикрепляется к объекту в unity. b0700. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0700. картинка скрипт не прикрепляется к объекту в unity. картинка b0700. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Создадим новый C#-скрипт и назовем его Move.
Поскольку движение должно быть непрерывно во времени, то основной код будет располагаться в методе Update(). Вызовем функцию Translate, объекта transform и передадим ей в качестве параметра Vector3(0, 0, 1). Получим следующий код:

Разберемся подробнее в коде. Тут transform — это объект класса Transform, привязанный к нашему объекту. Метод Translate() двигает объект вдоль вектора на расстояние равное его длине (параллельный перенос).

Сохраним наш скрипт и добавим его к нашему кубу. Нажмите Play и увидите как куб стремительно улетает вдоль оси Oz.

скрипт не прикрепляется к объекту в unity. b0701. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0701. картинка скрипт не прикрепляется к объекту в unity. картинка b0701. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Давайте уменьшим скорость движения, например, умножив наш вектор на Time.deltaTime, то есть:

Нажмите Play и убедитесь, что куб начинает двигаться заметно медленнее.

Можно сделать наш скрипт более удобным в использовании, если скорость задать не фиксированным вектором, а через переменную. Заведем public переменную типа float и назовем ее speed. С помощью этой переменной можно будет задавать начальную скорость через Inspector View (по умолчанию она будет равна 5.0f):

Сохраним скрипт и убедимся, что в Inspector View у компонента Move появилась переменная Speed.
скрипт не прикрепляется к объекту в unity. b0702. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0702. картинка скрипт не прикрепляется к объекту в unity. картинка b0702. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Посмотрите, как будет меняться скорость движения нашего объекта в соответствии с заданным начальным значением этой переменной. Например, при Speed = 3 скорость объекта не очень быстрая, но и не медленная.

Примечение: Для выражения Vector3(0.0f, 0.0f, 1.0f) существует короткая (но видимо чуть более медленная, если не прав, прошу поправить) запись Vector3.forward.

Кусок кода из обертки:

Дополнительные материалы:

Базовый Урок 08 — Основы движения с помощью силы.

В уроке рассказывается как c помощью приложения силы двигать физическое тело (Rigidbody).

Если у вас на сцене есть объект с компонентом Rigidbody, то нужно задавать ему движение с помощью приложения силы (передав таким образом все расчеты движения физическому движку игры). В противном случае вы можете начать конфликтовать с физикой объекта. Мы по-прежнему используем сцену из Базового урока 03.

скрипт не прикрепляется к объекту в unity. b0800. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0800. картинка скрипт не прикрепляется к объекту в unity. картинка b0800. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Создадим C#-скрипт и назовем его Force. В методе Start() вызовем метод AddForce() компонента rigidbody (cвязанного с нашим объектом) и передадим ему вектор приложенной силы Vector3(0.0f, 0.0f, power). В классе заведем переменную типа float с именем power и значением, по умолчанию равным 500.0f:

Сохраним скрипт и добавим его к нашему объекту (или префабу). Теперь, если нажать Play, вы увидите как куб падает не вниз а под углом, из-за воздействия силы приложенной вдоль оси Oz.
скрипт не прикрепляется к объекту в unity. b0801. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-b0801. картинка скрипт не прикрепляется к объекту в unity. картинка b0801. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Источник

Методы организации взаимодействия между скриптами в Unity3D

Вступление

Подход 1. Назначение через редактор Unity3D

Пусть у нас в проекте есть два скрипта. Первый скрип отвечает за начисление очков в игре, а второй за пользовательский интерфейс, который, отображает количество набранных очков на экране игры.
Назовем оба скрипта менеджерами: ScoresManager и HUDManager.
Каким же образом менеджеру, отвечающему за меню экрана можно получить текущее количество очков от менеджера, отвечающего за начисление очков?
Предполагается, что в иерархии объектов(Hierarchy) сцены существуют два объекта, на один из которых назначен скрипт ScoresManager, а на другой скрипт HUDManager.
Один из подходов, содержит следующий принцип:
В скрипте UIManager определяем переменную типа ScoresManager:

Но переменную ScoresManager необходимо еще инициализировать экземпляром класса. Для этого выберем в иерархии объектов объект, на который назначен скрипт HUDManager и в настройках объекта увидим переменную ScoresManager со значением None.

скрипт не прикрепляется к объекту в unity. 900ef2696d5182d43a87f20483dfe6c1. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-900ef2696d5182d43a87f20483dfe6c1. картинка скрипт не прикрепляется к объекту в unity. картинка 900ef2696d5182d43a87f20483dfe6c1. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Далее, из окна иерархии перетаскиваем объект, содержащий скрипт ScoresManager в область, где написано None и назначаем его объявленной переменной:

скрипт не прикрепляется к объекту в unity. 6dc5a7da31258029d78f692b51778e73. скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-6dc5a7da31258029d78f692b51778e73. картинка скрипт не прикрепляется к объекту в unity. картинка 6dc5a7da31258029d78f692b51778e73. Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

После чего, у нас появляется возможность из кода HUDManager обращаться к скрипту ScoresManager, таким образом:

Все просто, но игра, не ограничивается одними набранными очками, HUD может отображать текущие жизни игрока, меню доступных действия игрока, информацию о уровне и многое другое. Игра может насчитывать в себе десятки и сотни различных скриптов, которым нужно получать информацию друг от друга.
Чтобы получить в одном скрипте данные из другого скрипта нам каждый раз придется описывать переменную в одном скрипте и назначать (перетаскивать вручную) ее с помощью редактора, что само по себе нудная работа, которую легко можно забыть сделать и потом долго искать какая из переменных не инициализирована.
Если мы захотим что-то отрефакторить, переименовать скрипт, то все старые инициализации в иерархии объектов, связанные с переименованным скриптом, сбросятся и придется их назначать снова.
В то же время, такой механизм не работает для префабов (prefab) — динамического создания объектов из шаблона. Если какому-либо префабу нужно обращаться к менеджеру, расположенному в иерархии объектов, то вы не сможете назначить самому префабу элемент из иерархии, а придется сначала создать объект из префаба и после этого программно присвоить экземпляр менеджера переменной только что созданного объекта. Не нужная работа, не нужный код, дополнительная связанность.
Следующий подход решает все эти проблемы.

Подход 2. «Синглтоны»

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

Примеры

Как правило, в единственном экземпляре существуют скрипты, отвечающие за общую логику пользовательского интерфейса, за проигрывание музыки, за отслеживание условий завершения уровня, за управление системой заданий, за отображение спецэффектов и так далее.
В то же время, скрипты игровых объектов существуют в большом количестве экземпляров: каждая птичка из «Angry Birds» управляется экземпляром скрипта птички со своим уникальным состоянием; для любого юнита в стратегии создается экземпляр скрипта юнита, содержащий его текущее количество жизней, позицию на поле и личную цель; поведение пяти разных иконок обеспечивается различными экземплярами одних и тех же скриптов, отвечающих за это поведение.
В примере из предыдущего шага скрипты HUDManager и ScoresManager всегда существуют в единственном экземпляре. Для их взаимодействия друг с другом применим паттерн «синглтон» (Singleton, он же одиночка).
В классе ScoresManager опишем статическое свойство типа ScoresManager, в котором будет храниться единственный экземпляр менеджера очков:

Осталось инициализировать свойство Instance экземпляром класса, который создает среда Unity3D. Так как ScoresManager наследник MonoBehaviour, то он участвует в жизненном цикле всех активных скриптов в сцене и во время инициализации скрипта у него вызывается метод Awake. В этот метод мы и поместить код инициализации свойства Instance:

После чего, использовать ScoresManager из других скриптов можно следующим образом:

Теперь нет необходимости в HUDManager описывать поле типа ScoresManager и назначать его в редакторе Unity3D, любой «скрипт-менеджер» может предоставлять доступ к себе через статическое свойство Instance, которое будет инициализировать в функции Awake.

Плюсы

— нет необходимости описывать поле скрипта и назначать его через редактор Unity3D.
— можно смело рефакторить код, если что и отвалится, то компилятор даст знать.
— к другим «скриптам-менеджерам» теперь можно обращаться из префабов, через свойство Instance.

Минусы

— подход обеспечивает доступ только к «скриптам-менеджерам», существующим в единственном экземпляре.
— сильная связанность.
На последнем «минусе» остановимся подробнее.
Пусть мы разрабатываем игру, в которой есть персонажи (unit) и эти персонажи могут погибать (die).
Где-то находится участок кода, который проверяет не погиб ли наш персонаж:

Получается, что персонаж после совей смерти должен разослать всем компонентам, которые в ней заинтересованы этот печальный факт, он должен знать о существовании этих компонентов и должен знать, что они им интересуются. Не слишком ли много знаний, для маленького юнита?
Так как игра, по логике, очень связанная структура, то и события происходящие в других компонентах интересуют третьи, юнит тут ничем не особенный.
Примеры таких событий (далеко не все):
— Условие прохождение уровня зависит от количества набранных очков, набрали 1000 очков – прошли уровень (LevelConditionManager связан с ScoresManager).
— Когда набираем 500 очков, достигаем важную стадию прохождения уровня, нужно проиграть веселую мелодию и визуальный эффект (ScoresManager связан с EffectsManager и SoundsManager).
— Когда персонаж восстанавливает здоровье, нужно проиграть эффект лечения над картинкой персонажа в панели персонажа (UnitsPanel связан с EffectsManager).
— и так далее.
В результате таких связей мы приходим к картине похожей на следующую, где все про всех все знают:

скрипт не прикрепляется к объекту в unity. . скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-. картинка скрипт не прикрепляется к объекту в unity. картинка . Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

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

Подход 3. Мировой эфир (Event Aggregator)

Введем специальный компонент «EventAggregator», основная функция которого хранить список событий, происходящих в игре.
Событие в игре — это функционал, предоставляющий любому другому компоненту возможность как подписаться на себя, так и опубликовать факт совершения этого события. Реализация функционала события может быть любой на вкус разработчика, можно использовать стандартные решения языка или написать свою реализацию.
Пример простой реализации события из прошлого примера (о смерти юнита):

Добавляем это событие в «EventAggregator»:

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

А любой компонент, которому интересно это событие, может отреагировать на него следующим образом (на примере менеджера отвечающего за количество набранных очков):

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

скрипт не прикрепляется к объекту в unity. . скрипт не прикрепляется к объекту в unity фото. скрипт не прикрепляется к объекту в unity-. картинка скрипт не прикрепляется к объекту в unity. картинка . Здравствуйте. Можно ли в Юнити использовать скрипт, который не прикреплен к объекту на сцене? Например для реализации синглтона. Благодарю

Замечание

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

Плюсы

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

Минусы

— нужно постоянно описывать новые события и добавлять их в мир.
— нарушение функциональной атомарности.

Последний минус рассмотрим более детально

Представим, что у нас есть объект «ObjectA», в котором вызывается метод «MethodA». Метод «MethodA», состоит из трех шагов и вызывает внутри себя три других метода, которые выполняют эти шаги последовательно («MethodA1», «MethodA2» и «MethodA3»). Во втором методе «MethodA2» происходит публикация какого-то события. И тут происходит следующее: все кто подписан на это событие начнут его обрабатывать, выполняя какую-то свою логику. В этой логике тоже может произойти публикация других событий, обработка которых также может привести к публикации новых событий и так далее. Дерево публикаций и реакции в отдельных случаях может очень сильно разрастись. Такие длинные цепочки крайне тяжело отлаживать.
Но самая страшная проблема, которая тут может произойти, это когда одна из веток цепочки приводит обратно в «ObjectA» и начинает обрабатывать событие путем вызова какого-то другого метода «MethodB». Получается, что метод «MethodA» у нас еще не выполнил все шаги, так как был прерван на втором шаге, и содержит сейчас в себе не валидное состояние (в шаге 1 и 2 мы изменили состояние объекта, но последнее изменение из шага 3 еще не сделали) и при этом начинается выполняться «MethodB» в этом же объекте, имея это не валидное состояние. Такие ситуации порождают ошибки, очень сложно отлавливаются, приводят к тому, что надо контролировать порядок вызова методов и публикации событий, когда по логике этого делать нет необходимости и вводят дополнительную сложность, которую хотелось бы избежать.

Решение

Решить описанную проблему не сложно, достаточно добавить функционал отложенной реакции на событие. В качестве простой реализации такого функционала мы можем завести хранилище, в которое будем складывать произошедшие события. Когда событие произошло, мы не выполняем его немедленно, а просто сохраняем где-то у себя. И в момент наступления очереди выполнения функционала какой-то компоненты в игре (в методе Update, например) мы проверяем на наличие произошедших событий и выполняем обработку, если есть такие события.
Таким образом, при выполнении метода «MethodA» не происходит его прерывание, а опубликованное событие все заинтересованные записывают себе в специальное хранилище. И только после того как к заинтересованным подписчикам дойдет очередь, они достанут из хранилища событие и обработают его. В этот момент весь «MethodA» будет завершен и «ObjectA» будет иметь валидное состояние.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *