Потихоньку завершаю работу с низкоуровневым рендером и пора подумать о организации сцены. Первоначально я горел идеей компонентной системы, но поработав в юнити в ней разочаровался. Идея компонентной системы в том что любой объект может состоять из разного числа компонентов. Но тут возникает первая проблема - идентификация этих компонент. Как узнать что вот этот компонент - колайдер, а вон тот - рендер меш? Вообще в идеальном вакууме, я думаю, компонентная система и не подразумевала что кто-то будет пытаться опознавать компоненты. Но в реальности это выглядит как-то так (С#)
Collider col = gameObject.GetComponent<Collider>();
или так
Collider col = gameObject.GetComponent("Collider");
Второй вариант ближе к C++... Но искать по имени (да даже если по хешу)... А если одинаковых компонентов несколько? Вообщем это не то что хорошо для реалтайма.
После этого я заметил еще одно свойство с которым столкнулся в юнити. Хоть по идее можно на объект вешать несколько компонентов, но есть уникальные, которые могут быть только в единственном числе:
Transform - этот компонент вообще должен быть у всех объектов (тут кстати уже обсуждали ранее эту проблему)
Collider - в юнити невозможно добавить два колайдера (попытка через редактор удалит старый, попытка через код приведет к error)
MeshRender - их вроде как можно несколько, но реально ли это вам нужно? Так что тоже всегда по одному на объект
Остальные компоненты - в юнити есть много компонент которые существуют в единственном числе.
А чего же тогда много? Скриптовых компонент - их может быть куча на каждом объекте.
И тут я подхожу к финальной мысли - к той системе, которую я хочу получить.
Есть GameObject, и у него есть свойства
class GameObject { Transform Collider* MeshRender* list<Script*> };
У каждого GO есть свойство Transform которое определяет его расположение в мире
Еще у них есть несколько указателей на свойства (Collider, MeshRender). они могут быть нулевыми - а значит у данного объекта их нет, то есть не все GO нуждаются в колайдере, и даже есть возможность создать GO которые не будут рисоваться на экран. Свойств этих будет много. Но любой GO не обязан содержать их все. Сейчас вы спросите - а как же возможность добавлять новые свойства? А вот приведите мне такие свойства которые пользователь захочет добавить к ГО, а то у меня идей нет:)
И в конце есть список скриптов (возможно так будут сделаны и еще несколько вещей, например материалы). То есть их может быть много, и именно ими пользователь будет задавать остальные нужные ему свойства.
Таким образом я решу проблему поиска компонентов. Если мне надо будет колайдер, то я напишу так:
Collider *col = gameObject->GetCollider(); if ( col) { }
Кстати, в юнити это тоже есть - у GO есть несколько сохраненных компонент которые можно использовать примерно также:
animation The Animation attached to this GameObject (Read Only). (null if there is none attached).
audio The AudioSource attached to this GameObject (Read Only). (null if there is none attached).
camera The Camera attached to this GameObject (Read Only). (null if there is none attached).
collider The Collider attached to this GameObject (Read Only). (null if there is none attached).
constantForce The ConstantForce attached to this GameObject (Read Only). (null if there is none attached).
guiText The GUIText attached to this GameObject (Read Only). (null if there is none attached).
guiTexture The GUITexture attached to this GameObject (Read Only). (null if there is none attached).
hingeJoint The HingeJoint attached to this GameObject (Read Only). (null if there is none attached).
light The Light attached to this GameObject (Read Only). (null if there is none attached).
networkView The NetworkView attached to this GameObject (Read Only). (null if there is none attached).
particleEmitter The ParticleEmitter attached to this GameObject (Read Only). (null if there is none attached).
particleSystem The ParticleSystem attached to this GameObject (Read Only). (null if there is none attached).
renderer The Renderer attached to this GameObject (Read Only). (null if there is none attached).
rigidbody The Rigidbody attached to this GameObject (Read Only). (null if there is none attached).
transform The Transform attached to this GameObject. (null if there is none attached).
Как видите, они тоже могут быть нулевыми как у меня:) Но у меня это будет более явно
Вообщем я просто взял лучшее (на мой взгляд) из компонентной системы и классической системы энтити и смешал
Это по GameObject.
Теперь про сцену
У меня будет World, это класс полностью хранящий все происходящее. Он будет содержать сцены (Scene). Каждая сцена равна сцене из юнити. В любой момент времени может быть только одна сцена... Но их можно смешивать (то есть из двух сцен создать одну, вообщем тоже идея из юнити). На сцене может быть любое число ГО. Также на сцене есть одна камера, потому что я не понимаю этой фичи в юнити с возможностью создать сцену без камеры (и получить черный экран) или создать несколько го с камерами. так что у меня основная камера будет всегда.
Го могут строится иерархию по принципу родитель - ребенок как в юнити, потому что это мне тоже понравилось. Корневого Го не будет. Каждый Го является корнем, и может содержать детей, но может и не содержать.
Ссылка | Комментарии [60]