Hello. This course starts by slowing the refactor down: before moving code, we need a reliable picture of what the code currently does and which kind of responsibility each part represents.
Your prototype already has enough moving parts for boundaries to blur naturally: a playable character, collision and movement, rendering, a character camera alongside an editor camera, ImGui tooling, Photon multiplayer work, and packaging. The goal of this lesson is not to judge that structure or redesign it yet. It is to produce an inventory that makes the mixed responsibilities visible, especially inside classes such as Scene.
By the end, you will have a practical document that labels each meaningful responsibility as platform, engine runtime, editor, or game-specific. That document will become the evidence base for the dependency map in the next lesson.
Four homes for engine responsibilities
A useful first distinction is between where code happens to live today and where its responsibility belongs. A Scene.cpp file may currently contain input handling, collision updates, rendering, editor camera controls, and actor storage. That does not make all of those “Scene responsibilities.” It means Scene is currently a host for several concerns that need to be named separately.
Use these four categories for the inventory.
| Category | Core purpose | Typical examples in your engine |
|---|---|---|
| Platform | Encapsulates concrete operating-system, windowing, graphics-API, device, or third-party boundaries. | GLFW window and event polling, OpenGL context setup, raw keyboard/mouse events, filesystem and time access. |
| Engine runtime | Reusable capabilities needed to load and run an interactive world. It should not contain the rules of one particular game. | Main loop, actor/component framework, transform propagation, render orchestration, collision queries, resource loading. |
| Editor | Developer-facing authoring, inspection, and debugging facilities. A player should not need these to play the packaged game. | ImGui inspector panels, hierarchy/selection state, gizmos, editor camera, play/stop controls. |
| Game-specific | The rules, content, configuration, and player-facing behavior of the game you are building. | Character movement rules, jump and sprint tuning, level content, player-camera feel, multiplayer replication rules. |
Two cautions prevent this from becoming a simplistic labeling exercise:
- A third-party library is not a category. GLFW and OpenGL are platform-facing because they expose external facilities. Photon may support a reusable runtime networking service, while the decision to replicate a player transform, join a particular room, or interpret network messages is game-specific.
- A component is not automatically runtime code. A
TransformComponentis plausibly a reusable runtime component. APlayerControllerComponentthat interprets jump input and applies sprint speed is game-specific. An editor-only selection component belongs to the editor.
The basic question is: If I began a different game tomorrow, would this behavior still make sense unchanged? If yes, it is a candidate for the runtime or platform layer. If it exists only so developers can make, inspect, or debug content, it is editor code. If it defines what this game does, it is game code.
A reference model, not a template
The Godot Engine architectural diagram separates a low-level Core and Drivers layer from scene-facing types and higher-level services. Do not copy its names or class hierarchy; the useful idea is simply that a “scene” layer is not expected to absorb all platform, rendering, audio, physics, and tool responsibilities.

In your project, a Scene may remain an important runtime object. It might be the container for actors and components in a loaded world. But an inventory asks a more precise question: does a particular Scene method manage world membership, execute game rules, issue OpenGL calls, maintain editor selection, or create a GLFW window? Those are distinct responsibilities even if one class currently performs all of them.
A mature engine does not need to begin with dozens of libraries or separate executables. The key is conceptual separation first. You can keep the current build structure while identifying code that will eventually need clearer boundaries.
Game Engine Architecture 101 // Code Review
Watch “Game Engine Architecture 101 // Code Review” by The Cherno for a concise argument that game code, a reusable runtime, and developer tools serve different audiences. Treat its discussion as a boundary model, not as a requirement to immediately split your project into multiple binaries.
Watch the boundary problem, focusing on why putting one game and its engine into an undifferentiated unit makes future reuse difficult. Then watch the two audiences, noting the distinction between player-facing runtime behavior and editor-only project-selection or authoring UI.
The most relevant point for your current engine is the editor camera. Its existence is not a problem. It becomes a structural problem only when it is treated as the same thing as the player’s runtime camera, or when a packaged player build must carry editor-specific controls and panels merely because the two were never distinguished.
Open 3D Engine expresses a similar separation with standard, editor, and system components. Its exact framework is not the point here, but its vocabulary is useful: some behavior operates on entities at runtime, some exists only while authoring content, and some is engine-wide rather than belonging to an individual entity.
Overview of Open 3D Engine Entities and Components - Open 3D Engine
Read the “Types of components” portion of Open 3D Engine’s overview. It gives a concrete industry example of separating entity behavior from editor-only behavior and engine-wide services.
Under “Types of components,” read the full “Standard components,” “Editor components,” and “System components” subsections. Start with the editor and system distinction. Focus on the purpose and lifetime context of each category, rather than adopting O3DE’s event bus or singleton patterns for your engine.
“System component” in this source means engine-wide behavior, not “make everything globally accessible.” Whether a service should be global, owned by an application object, or passed through an interface is an ownership and access question for a later module. For now, record the responsibility without prematurely choosing its implementation.
Classify behavior, not just classes
When you open your codebase, avoid making one row per folder and calling the job complete. A folder can be named Engine while containing a player controller, and a class named Scene can contain editor and platform code. Instead, make a row for each meaningful behavioral unit.
For example, these are different rows:
- “Poll native window events.”
- “Translate raw keyboard state into a jump request.”
- “Integrate a character’s velocity.”
- “Draw the selected actor’s bounding box.”
- “Submit mesh and material data for rendering.”
- “Store the actors currently loaded in a world.”
Each row should use a verb phrase. That forces clarity: “Input” is vague; “poll raw input devices” is not.
The boundary cases in your prototype are especially instructive:
| Current area | Likely split of responsibilities |
|---|---|
| GLFW and OpenGL setup | Creating a native window, owning an OpenGL context, polling OS events, and swapping buffers are platform responsibilities. A renderer that turns scene-visible objects into draw submissions is runtime. |
| Input | Reading raw key and mouse state is platform-facing. A reusable input abstraction can be runtime. Mapping a key to “jump,” “sprint,” or a particular player action is game-specific policy. |
| Actor-component model | Generic actor IDs, component registration, and transform relationships are runtime infrastructure. A particular combination of components that defines your cube character is game-specific content. |
| Movement and jumping | Generic math, gravity integration, or a collision query may be runtime. Movement direction conventions, sprint multiplier, jump impulse, and the conditions under which your character may jump are game rules. |
| Collision | Collider representation and overlap or sweep queries are runtime capabilities. Deciding that a player is grounded, takes damage, slides, or is allowed to jump after a collision is game behavior. |
| Camera | Projection, view-matrix construction, and a runtime CameraComponent are reusable runtime facilities. A third-person rig’s offsets and follow behavior may be game-specific. The editor camera, editor navigation controls, and viewport focus rules are editor-only. |
| Meshes and materials | Runtime resource objects and render submission are runtime. OpenGL resource creation is platform/backend work. The mesh and material choices for your ground and cube character are game content. |
| ImGui | ImGui itself is only a UI library. Hierarchy panels, component inspectors, selection, and editor camera controls are editor responsibilities. A debug overlay available in a development build may be runtime tooling, but it should be labeled separately from player-facing UI. |
| Photon multiplayer | A narrow connection or transport adapter can be a reusable runtime service. Room policy, spawn rules, which actor fields replicate, and how received state affects the player are game-specific. |
| Export and packaging | The executable and runtime assets are the product. Export configuration, packaging commands, and developer-facing build tooling are editor/tooling responsibilities rather than part of live gameplay. |
These are provisional classifications, not claims about what your existing code already does well. If your MovementComponent currently calls OpenGL, reads GLFW keys, performs collision, and decides jumping, give it several inventory rows and mark it mixed. The inventory should reveal that fact rather than hiding it behind one category.
Open 3D Engine’s high-level overview is also useful here because it distinguishes core facilities, authoring tools, asset processing, and a shippable runtime. That wider view helps prevent treating “the engine” as only the code that runs in the game loop.
Key Concepts: How Open 3D Engine Works - Open 3D Engine
Read the opening overview from Open 3D Engine. Use it to compare your four inventory categories with a real engine’s core modules, authoring tools, asset pipeline, and shipping process.
At the start of the page, before “Overview of the O3DE SDK,” read the opening overview. Notice that core modules, authoring tools, asset processing, and packaging have different users and execution contexts. You do not need to reproduce this scale; you are identifying the same distinctions in a much smaller engine.
Build the first inventory
Create one markdown file, spreadsheet, or note named something like docs/architecture/current-responsibility-inventory.md. Do not move files, rename classes, introduce interfaces, or change ownership while doing this. The document is a snapshot of reality, not a refactor proposal.
1. List the code that participates in a build or tool session
Spend about five minutes making a raw list. Start with your own source files and major third-party integration points, not every getter or utility function. Include:
- the application entry point and main loop;
Scene, actor, and component classes;- transforms, movement, collision, mesh/material, camera, and spring arm code;
- renderer and OpenGL wrapper code;
- GLFW, window, input, filesystem, and timing integration;
- ImGui setup and every visible editor panel or editor-only control;
- editor and character camera switching;
- Photon connection, callbacks, synchronization, and session setup;
- asset loading and package/export scripts or configuration.
If a source file serves several purposes, do not try to force the entire file into a single label. Break it into its significant methods or regions.
2. Write a responsibility statement for each item
Use the narrowest statement that is still useful. Compare these two entries:
| Too broad | Better inventory entries |
|---|---|
Scene manages the game. | Stores loaded actors; creates or removes actors; dispatches per-frame updates; updates transform hierarchy; submits meshes for rendering; contains editor-camera switching. |
Input handles controls. | Polls native keyboard/mouse state; exposes device state; maps input to player movement; maps input to editor navigation. |
Camera controls the view. | Computes a view matrix; follows the player; handles editor fly-camera input; chooses the active runtime camera. |
The better statements may later end up in different classes. That is fine. You are not deciding the final class design today.
3. Apply four classification tests
For each responsibility, assign a primary home. Add a short “why” note when it is not obvious.
| Test | If the answer is yes | Likely classification |
|---|---|---|
| Would the packaged game need this even if no developer tools existed? | It belongs somewhere in the shipped product. | Runtime or game-specific |
| Does this exist to create, inspect, select, configure, or debug content? | Its primary user is the developer. | Editor |
| Does it translate between your code and GLFW, OpenGL, the OS, device APIs, or another external SDK? | It sits at an external boundary. | Platform, or a runtime integration adapter |
| Could another game reuse this behavior with no knowledge of your cube character, movement rules, or level? | It offers a general capability. | Runtime |
| Does it express your current game’s rules, tuning, content, or network meaning? | It defines the particular game. | Game-specific |
A responsibility can touch several categories, but it should receive one primary classification. If you cannot choose, use Mixed — split candidate and state exactly what is mixed. For instance:
Scene::Updatecurrently polls GLFW keys, updates actors, runs collision, changes the editor camera, and renders meshes.
Classification: Mixed — platform input, runtime world update, editor controls, and runtime rendering coordination are combined.
That sentence is a strong outcome, not a failure. It gives the eventual refactor a concrete target without prescribing the refactor yet.
4. Start with this inventory template
Copy and adapt this table. The entries below are hypotheses based on the systems you described; replace them with the exact names and behavior you find in your code.
| Code area or method | Responsibility in one verb phrase | Primary home | Status or evidence |
|---|---|---|---|
| Application entry point | Start the selected application mode and enter the main loop | Runtime | Inspect what it initializes and whether it opens editor UI unconditionally |
| GLFW wrapper | Create the window, own the graphics context, and poll native events | Platform | Confirm where GLFW calls occur |
| OpenGL rendering backend | Allocate GPU objects and issue OpenGL draw commands | Platform | Confirm whether rendering policy is mixed in |
| Renderer | Convert visible world data into render submissions | Runtime | Split from direct OpenGL backend calls if currently combined |
Scene actor registry | Store actors belonging to a loaded world | Runtime | Confirm whether it also owns editor state |
Scene update dispatcher | Coordinate generic world update phases | Runtime | Mark mixed if it contains player rules or ImGui controls |
| Transform component/system | Store and propagate position, rotation, and scale | Runtime | Verify whether transform update is independent of rendering |
| Player movement logic | Apply movement direction, sprint, and jump rules | Game-specific | Record actual tunable values and input assumptions |
| Collision system | Provide collision shapes, detection, and queries | Runtime | Keep player reactions in separate game rows |
| Character camera rig | Follow the playable character with game-specific offsets | Game-specific | Separate generic camera math from rig policy |
| Editor camera | Navigate the authoring viewport | Editor | Include mode switching and editor input mappings |
| ImGui hierarchy and inspector | Display and edit scene data for developers | Editor | Record selection and inspector state separately if useful |
| Photon adapter | Connect to Photon and move generic network data | Runtime | Record the SDK boundary and callbacks |
| Multiplayer game rules | Define rooms, player spawn, replication fields, and message meaning | Game-specific | Include every place network events mutate gameplay state |
| Export configuration | Produce a distributable build and required assets | Editor/tooling | Record what differs between editor and packaged builds |
5. Add an “uncertain or mixed” section
Finish the document with a short list titled Questions revealed by the inventory. Keep these as observations, not solutions. Examples:
- “The active camera is selected by code that also renders ImGui controls.”
- “The player controller obtains raw GLFW state directly.”
- “Photon callbacks modify
Sceneactor storage without a clear gameplay boundary.” - “Mesh loading is mixed with the choice of the ground mesh used by this particular level.”
- “The packaged build may initialize editor-only camera or panel state.”
This list is the bridge to later lessons. Do not resolve it by adding a singleton, an event bus, or more Scene methods. At this stage, accuracy is more valuable than elegance.
A practical definition of “done”
This first inventory is complete when:
- every major system involved in launching, editing, playing, networking, or packaging is listed;
- every entry has a verb-based responsibility statement;
- every entry has one primary classification or an explicit
Mixed — split candidatelabel; - character camera and editor camera behavior are recorded separately;
- raw platform input is separated on paper from game input meaning;
- Photon transport concerns are separated on paper from multiplayer game rules;
Scenehas been decomposed into the responsibilities it currently hosts, without changing its code.
Aim for roughly 15–20 minutes on the initial pass after the resource study. It is normal to leave a few rows uncertain. The point is to replace the feeling that “everything is connected” with a small set of specific, inspectable facts.
Key takeaways
A useful engine inventory does not catalog classes; it catalogs responsibilities. Platform code faces external APIs and the operating environment. Runtime code supplies reusable execution capabilities. Editor code serves authors and should not be required for player gameplay. Game-specific code defines the actual rules, content, tuning, and network meaning of your project.
Your Scene is allowed to be central without being responsible for everything. For this lesson, record the separate jobs it currently performs and mark mixed areas honestly. Preserve the prototype exactly as it works today.
Next, you will turn this responsibility inventory into a dependency map: which systems call, store, or create which others.
Can't find a good explanation? Sign up and we'll make it for you
Sign up