Any sort of single-player game (or simulation) usually requires a set of goals to guide the player throughout the experience. Even if the game is open-ended, an infinite runner, or otherwise doesn’t have a definite conclusion, having an objective system is a great way of showing the user the controls or taking them through a tutorial.
I designed a modular objective system using C# as a building block for any sort of game mechanic during my time at Logica Iluminada. It consisted of a single manager that kept track of the current objective, displayed the objective system’s UI, and handled stuff like the 3-dimensional waypoint markers. The system was modular using the singleton design pattern for the main manager, while also maintaining a reference to all the objectives in the given scene/level.
Additional functionality, such as dialogues being triggered, was done via a separate delegate entity that handled coroutines for syncing audio, the subtitle UI, and events that triggered specific dialogue sequences. Other functionality (depending on the nature), was specifically added via an inheritance hierarchy to the base objective class. One way I expanded the flexibility of this system was via an objective that held an array of multiple “sub” objectives, thus creating a tree hierarchy so that multiple goals could be grouped without necessarily changing the objective itself.
Each base objective saved a position (the waypoint marker position), the title, the description (for the UI), whether the objective can be failed (for game over sequences), whether it is in progress (if it’s the current objective being played), and related delegate events that would be executed on start, on complete, and on fail (for customization).