Menu
Lumberyard
Developer Guide (Version 1.11)

System Components

A traditional game engine contains many singleton classes, each in charge of a major system. In Lumberyard, these singletons are built using the same component entity system that powers gameplay entities. When an application is starting up, a system entity is created. Any components placed on this entity are known as system components. The system entity always has the ID AZ::SystemEntityId (0).

When you build singletons as Lumberyard system components, you are using a powerful suite of complementary technologies that facilitate problem resolution through established patterns. This topic describes system components in detail.

Smart Initialization Order

As a game engine grows in size, it tends to develop many singleton classes. A singleton class often requires communication with other singletons to function. This means that the order in which singletons are initialized is very important. Lumberyard solves this by building singletons as components.

A component can declare which services it provides, and it can declare which other services it depends on. When components are activated, they are sorted according to these declared dependencies, ensuring proper initialization order.

The following example shows two components that Lumberyard has ordered for initialization.

Copy
class AssetDatabaseComponent : public Component { ... static void GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC("AssetDatabaseService")); } ... }; class AssetCatalogComponent : public AZ::Component { ... static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { required.push_back(AZ_CRC("AssetDatabaseService")); } ... };

The example shows how AssetDatabaseComponent is activated before AssetCatalogComponent. In the AssetDatabaseComponent class, the GetProvidedServices function reveals that the class provides a service called AssetDatabaseService. In the AssetCatalogComponent class, the GetRequiredServices function reveals that AssetCatalogComponent depends on AssetDatabaseService. Lumberyard understands this dependency and orders the initialization order accordingly.

For more information about the initialization order of components, see The AZ Bootstrapping Process.

Easily Configurable Components

Often, a singleton has settings that are configurable for each game. It can be difficult for a low-level singleton to access configuration data because the system used to process this data hasn't yet started. Therefore, low-level singletons often rely on simple data sources such as command line parsers or .ini files.

A system component can expose its configuration through AZ reflection. The Advanced Settings dialog box in the Project Configurator uses this feature to enable you to configure system components on a per-game basis. The Project Configurator saves an application descriptor file that contains the settings for each system component, and this file is used to bootstrap the application and configure each component before it is activated. This is the same technology that the Entity Inspector uses to configure gameplay entities in the Lumberyard Editor. For more information, see Configuring System Entities.

Writing System Components

To designate a component as a system component, rather than a gameplay component, you must set the AppearsInAddComponentMenu field to System when you reflect to the EditContext.

The following example code designates the MemoryComponent as a system component.

Copy
void MemoryComponent::Reflect(ReflectContext* context) { if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context)) { ... if (EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class<MemoryComponent>("Memory System", "Manages memory allocators") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System")) ... } } }

Required System Components

Often, a module requires the existence of a system component. This requirement can be established through the module's GetRequiredSystemComponents() function. Any component type declared here is guaranteed to exist when the application starts.

In the following example, the OculusDevice component is required by the Oculus Gem.

Copy
AZ::ComponentTypeList OculusGem::GetRequiredSystemComponents() const override { return AZ::ComponentTypeList{ azrtti_typeid<OculusDevice>(), }; }

If a system component is optional, you can add it from Advanced Settings in the Project Configurator.