Feature Flags in Vessel
- Rickperros

- Jan 16
- 4 min read
Feature flags are a standard practice for a lot of game developments, especially in the mobile industry, but for some reason there are still a lot of studios and indie developers that are not using them. Today I want to explain what this strategy is, why it is useful, and how we are using it in Vessel.
What are feature flags?
Essentially it is a software development strategy that aims to modify the features of a program without rewriting and recompiling it. Usually they are represented by a boolean flag, if you are a non technical person a boolean is any variable that can have two states: true, and false. So the idea behind this strategy is pretty simple: gate execution flows using a flag, if the flag is true then the feature is enabled, otherwise it is ignored.
But why are those useful?
There are a lot of advantages for not rewriting your software each time you need to modify its behaviour. For me the main ones are:
Faster response if there is a localized issue. In asynchronous teams like ours, this is vital to ensure the wheel is always spinning. To illustrate this imagine that a team member is working on the lighting of the level, they just need to have the character moving around to test their changes. Let’s imagine that the minimap feature is crashing due to unknown reasons and the coder that is responsible to fix it will be offline for the next few days. Being able to disable the minimap allows our artist to work instead of waiting until the coder is back. Another common example is deploying the game with a broken character, or feature. Instead of blocking your players until you have a fix you can disable the broken feature in a matter of seconds.
A/B testing. Feature flags aren’t only for disabling features. They can provide different alternatives to test which version works better.
Finally, and very similar to the prior one, build configuration. People usually think about feature versions in a matter of “which version works best” but another interesting point of view is “which version of the feature does the player prefer”. The first one is interesting for A/B testing and for product vision, the second one is really interesting from an accessibility point of view. For example, with this strategy you can provide the player with the option of disabling quick time events, or enabling or disabling the map, etc. In essence you allow an experience customization.
How are we implementing them?
For Vessel team there are two main needs that we need to fulfill with our feature flags:
They must be globally accessible.
They must be configurable from outside the game and editor flow.
In order to achieve that we used the built systems in Unreal. All our feature flags are created in a dedicated game instance subsystem which makes them automatically globally available since it is a class (a piece of code for any non-technical reader) that can be accessed from everywhere. Those are also declared as config variables, this is a mark that allows setting the values from an external text file. This is useful for critical failures where the build or the editor can’t be opened and makes it easier for non-technical people to use them.
Then all those config flags have a twin that is transient (this means that we don’t store its values between executions). Internally, we use this transient value but this duplicity allows us to modify single executions without losing the configuration values.
At this point the feature flag is ready to use. Then in each feature entry point we just check the flag status by retrieving the game instance subsystem and calling a getter. In this particular case we believe it is better to use getters instead of the raw value because it allows us to build a hierarchy of feature flags. Let’s see some example:
We have a feature flag called EnableMeleeCombat and we have a feature called EnableLightCombo. Even if the light combo feature is enabled we want to consider it disabled if melee combat is not enabled.
Using dedicated methods instead of retrieving raw values allows us to build this modularity without adding complexity on the rest of the code.
Finally to use them easily from development builds an editor we extended the cheat class with a couple of methods. The first one just switches the value in the transient var which is useful for in-run tests. The second one changes the flag config value making it permanent.
Final thoughts
For now we are just using the most simple form of feature flags which are booleans, but those can take many forms, enums, ints, anything, even gameplay tags. For us they are really important since they empower us to use defensive programming but I will save that for another post! Do you like more technical posts? Let me know in the comments! Subscribe and don’t miss anything from the Vessel team!





Masterclass de control de danys
Good approach, wish I used it in other projects jajaja