Перейти к основному содержимому

Объекты и сцены

Всё в вашем проекте строится на двух идеях: вещи, состоящие из компонентов, и сцены, решающие, когда эти вещи появляются. Эта страница про то и другое.

«Объект» и «entity» — одно и то же

Редактор называет их объектами, потому что именно так они выглядят на экране. Движок и скриптовый API называют их entity. Разницы нет — на этой странице entity используется там, где важно отличие от компонентов, и объект во всех остальных местах.

Два отношения, и это не одно и то же

Почти всё непонимание этого движка идёт из путаницы двух вещей, которые обе выглядят как «внутри».

Entity СОСТОИТ ИЗ компонентов. Компоненты — не дети, а части, определяющие, чем entity является. Каждого вида — не больше одного.

Entity  "Лампа"
├── Meta имя, включена ли, видима ли
├── Transform где стоит, как повёрнута, какого размера
├── Model какую 3D-модель рисовать
└── Events на что реагирует

Entity может СОДЕРЖАТЬ другие entity. Это дети, и они сами по себе полноценные entity — у каждого свои компоненты.

Entity  "Лампа"
└── Entity "Лампочка" ← отдельная entity…
├── Transform ← …со своими компонентами
└── Light

Вместе настоящая сцена выглядит так — компоненты слева от каждой entity, дети с отступом под ней:

Entity  "Гостиная"    ◆ Anchor          ← вот это СЦЕНА: у неё есть якорь

├── Entity "Лампа" ◆ Transform ◆ Model ◆ Events
│ └── Entity "Лампочка" ◆ Transform ◆ Light

└── Entity "Стол" ◆ Transform ◆ Model ◆ RigidBody ◆ Collider

Всё на этой картинке — вещи одного вида: entity. Сценой, лампой или физическим телом их делает только набор компонентов.

Почему это важно на практике

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

Если вы ловите себя на вопросе «это должно быть компонентом или дочерним объектом?», ответ такой: компонентом — когда это свойство самой вещи, ребёнком — когда это отдельная вещь, которая должна двигаться вместе с ней.

Entity — это то, что говорят её компоненты

Никакого меню типов объектов нет. Вы собираете нужное из компонентов:

Дайте entity……и получите
геометрию + материалвидимую форму
ссылку на модельимпортированную 3D-модель
компонент светаисточник света
текстовый компонентнадпись
rigid body + коллайдерто, что может двигать физика
якорьсцену
скрипт или патчповедение

Скажем, нужен прыгающий мяч. Начните со сферы и материала — уже видно. Добавьте rigid body и коллайдер — он падает и отскакивает. Добавьте скрипт — он что-то делает при приземлении. Каждый компонент добавляет одну способность, а его удаление её забирает.

Три формы, которые вам встретятся

Одна и та же модель entity даёт три вещи, ощущающиеся по-разному, но устроенные одинаково:

Что этоЕстьНет
Сценаякорь и детиtransform
Обычный объектtransform плюс что нужноякорь
Поведение уровня spaceскрипт или патч и нет родителяtransform, якорь

У сцены нет transform, потому что ей негде быть: её положение задаёт то, к чему она привязана в реальном мире. У носителя уровня space его нет, потому что он вообще не в мире — это просто логика, которая продолжает работать.

По одному компоненту каждого типа на entity

Нужны три материала на одной модели? Используйте слоты внутри её единственного компонента материала. Нужны два чего-то другого? Используйте дочерние entity — лампа с двумя лампочками это entity лампы с двумя детьми.

У каждой entity также есть имя (по нему вы её находите) и родитель.

Включён и видим — разное

В инспекторе эти два похожи, а ведут себя совершенно по-разному.

Выключенный убирает entity из работающего проекта. Не рисуется, не нажимается, скрипты остановлены, события молчат. Как будто её нет.

Невидимый лишь перестаёт рисоваться и нажиматься. Она на месте: скрипты работают, физика сталкивается.

Итого: невидимая стена, которая всё же преграждает путь? Невидимая. Приз, который появится позже? Выключен, пока не понадобится.

Родители и дети

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

Entity без родителя сидит в корне своей сцены.

Удаление объекта удаляет всё, что внутри

Дети тоже, и их дети. Если что-то надо сохранить — сначала вытащите наружу.

Сделать entity ребёнком собственного потомка нельзя — редактор откажется, вместо того чтобы запутать дерево.

Сцены и якоря

Сцена — это entity с якорем, и якорь отвечает на один вопрос: когда этому появиться?

ЯкорьВаша сцена появляется, когда…
imageкамера узнаёт печатную картинку
qrотсканирован QR-код
geoпосетитель оказался в определённом месте
faceобнаружено лицо
surfaceпосетитель ставит её на пол, стену, потолок или стол
panoramaоткрывается панорамное окружение
3dсразу — обычная 3D-сцена, без всякого AR
VPS — не отдельный якорь

Позиционирование по отсканированной карте реального места — это опция якоря surface, а не отдельный тип. Настройте сцену surface, а потом включите VPS.

Несколько сцен, один маркер

Сцены с общим триггером (та же картинка, тот же QR-код, то же место) образуют группу, и одновременно показывается только одна сцена из группы.

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

Показ и скрытие при обнаружении — это просто пара событий, которые редактор заводит за вас (on-detect показывает, on-lost скрывает). Это обычные события, так что их можно менять — например, чтобы контент оставался на экране после ухода маркера из кадра, что посетители обычно предпочитают контенту, исчезающему от малейшего дрожания руки.

У сцен surface три отдельные настройки

Их часто путают, поэтому вот они рядом:

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

Поведение, которое переживает сцену

Дайте entity поведение и никакого родителя — и она перестанет принадлежать какой-то одной сцене: она принадлежит всему space. Она работает, пока сцены сменяются, и слышит каждое событие, где бы оно ни произошло.

Именно там место счётчику очков, глобальному контроллеру или «запомнить, что выбрал посетитель». Скрипт внутри сцены останавливается в тот же момент, что и она.

Как редактор подписывает объекты

Вы увидите подписи вроде model, primitive, text. Редактор определяет их по тому, что несёт объект, в таком порядке:

ссылка на splat               → splat
model + скиннинг → animated model
model → static model
video → video ← проверяется раньше геометрии
text → text
audio → audio
light → light
geometry → primitive
всё остальное → object

Это объясняет небольшой сюрприз: плоскость с видео подписана video, а не primitive. И это же объясняет, почему материал и геометрию можно править только у примитивов и статических моделей.


Дальше: Компоненты — чем на самом деле управляет каждый из них.