Feature flags, features registry, and app arguments. Use when gating features behind remote flags (FeatureFlagsConfiguration), feature gating, conditional features, runtime configuration, command-line flags, launch arguments, registering features in FeaturesRegistry, checking or adding app arguments (AppArgs), or implementing feature providers.
Scanned 5/27/2026
Install via CLI
openskills install decentraland/unity-explorer---
name: feature-flags-and-configuration
description: "Feature flags, features registry, and app arguments. Use when gating features behind remote flags (FeatureFlagsConfiguration), feature gating, conditional features, runtime configuration, command-line flags, launch arguments, registering features in FeaturesRegistry, checking or adding app arguments (AppArgs), or implementing feature providers."
user-invocable: false
---
# Feature Flags & Configuration
## Sources
- `docs/feature-flags.md` — Runtime feature flag system
- `docs/features-registry.md` — Centralized feature state management
- `docs/app-arguments.md` — Command-line flags and arguments
---
## When to Use Each Mechanism
| Need | Mechanism |
|------|-----------|
| Simple remote flag | `FeatureFlagsConfiguration.IsEnabled()` |
| Flag + app args combined | `FeaturesRegistry` |
| Runtime-dependent check | `IFeatureProvider` + `FeaturesRegistry` |
| Launch-time configuration only | `AppArgs.HasFlag()` / `TryGetValue()` |
---
## Feature Flags (Remote)
### Fetching
`IFeatureFlagsProvider.GetAsync()` calls the remote endpoint with:
- User address
- Debug flag
- Referer header
Default endpoint: `https://feature-flags.decentraland.org/explorer.json`
### Naming Convention
- **Server side:** `explorer-alfa-your-feature`
- **Codebase:** `alfa-your-feature` (prefix `explorer-` is stripped automatically)
### Checking Feature Flags
```csharp
// Simple check
bool enabled = featureFlagsCache.Configuration.IsEnabled("alfa-your-feature");
// Check with variant
bool enabled = featureFlagsCache.Configuration.IsEnabled("alfa-your-feature", "my-variant");
// Static shorthand (common pattern)
bool enabled = FeatureFlagsConfiguration.Instance.IsEnabled(FeatureFlagsStrings.CUSTOM_MAP_PINS_ICONS);
```
### Code Example — Feature Flag Gating
From `MapPinLoaderSystem.cs`:
```csharp
public partial class MapPinLoaderSystem : BaseUnityLoopSystem, IFinalizeWorldSystem
{
private readonly bool useCustomMapPinIcons;
public MapPinLoaderSystem(World world, /* ... */) : base(world)
{
// Cache flag value in constructor — Why: flag checks happen every frame in Update;
// re-fetching from config every frame is wasteful
useCustomMapPinIcons = FeatureFlagsConfiguration.Instance.IsEnabled(
FeatureFlagsStrings.CUSTOM_MAP_PINS_ICONS);
}
protected override void Update(float t)
{
LoadMapPinQuery(World);
UpdateMapPinQuery(World);
HandleComponentRemovalQuery(World);
HandleEntityDestructionQuery(World);
// Conditionally run texture loading
if (useCustomMapPinIcons)
ResolveTexturePromiseQuery(World);
}
}
```
### Variants
Feature flags can carry payload data in three formats:
```csharp
// String payload
if (config.TryGetTextPayload("alfa-feature", "variantId", out string? text))
UseText(text);
// CSV payload (returns rows × columns)
if (config.TryGetCsvPayload("alfa-feature", "variantId", out List<List<string>>? csv))
UseValues(csv);
// JSON payload (deserializes to DTO type)
if (config.TryGetJsonPayload<MyConfigDto>("alfa-feature", "variantId", out MyConfigDto? dto))
UseConfig(dto);
```
### Configuration Options
```csharp
var options = new FeatureFlagOptions
{
UserId = userAddress,
URL = flagsEndpoint,
AppName = "explorer",
Hostname = hostname
};
```
Overridable via app arguments:
- `--feature-flags-url` — Custom endpoint URL
- `--feature-flags-hostname` — Custom hostname
## Features Registry (Local)
`FeaturesRegistry` is a singleton that consolidates feature enable/disable logic from multiple sources: feature flags, app arguments, editor mode, and runtime conditions.
**Why FeaturesRegistry exists alongside FeatureFlagsConfiguration:** `FeatureFlagsConfiguration` only handles remote flags. `FeaturesRegistry` consolidates all sources (remote flags, app args, editor mode, runtime checks) into a single query point, so systems don't need to check multiple sources.
### Declaring Features
```csharp
// Each feature gets a FeatureId (numbered enum)
public enum FeatureId
{
YOUR_FEATURE = 42,
}
```
### Registering Feature States
```csharp
// In SetFeatureStates (bulk registration)
public void SetFeatureStates(FeatureFlagsCache cache, AppArgs args)
{
SetFeatureState(FeatureId.YOUR_FEATURE,
cache.Configuration.IsEnabled("alfa-your-feature") || args.HasFlag("--enable-feature"));
}
// Or individually
FeaturesRegistry.Instance.SetFeatureState(FeatureId.YOUR_FEATURE, true);
```
### Checking Features
```csharp
bool enabled = FeaturesRegistry.Instance.IsEnabled(FeatureId.YOUR_FEATURE);
```
### Feature Providers
For runtime-dependent features (e.g., user-specific checks):
```csharp
public class MyFeatureProvider : IFeatureProvider
{
public FeatureId FeatureId => FeatureId.MY_FEATURE;
public async UniTask<bool> IsFeatureEnabledAsync(CancellationToken ct)
{
// Runtime check (e.g., server call)
return await CheckIfEnabledAsync(ct);
}
}
// Register
FeaturesRegistry.Instance.RegisterFeatureProvider(new MyFeatureProvider());
```
Feature providers should cache values and reset on condition change.
## App Arguments
Command-line flags that configure application behavior. Work via command line or deep links.
### Usage
```
# Command line
--flag-name value
# Deep link
decentraland://?flag-name=value
```
### Key Flags by Category
| Category | Flag | Purpose |
|----------|------|---------|
| General | `--debug` | Enable debug mode |
| General | `--hub` | Hub mode |
| Environment | `--realm` | Target realm |
| Environment | `--local-scene` | Local scene development |
| Environment | `--position` | Starting position |
| Auth | `--skip-auth-screen` | Skip authentication |
| Performance | `--disable-disk-cache` | Disable disk cache |
| Performance | `--simulateMemory` | Simulate memory pressure |
| Development | `--use-log-matrix` | Custom log matrix JSON file |
| Development | `--launch-cdp-monitor-on-start` | Launch CDP monitor |
| Feature Flags | `--feature-flags-url` | Custom FF endpoint |
| Feature Flags | `--feature-flags-hostname` | Custom FF hostname |
| Display | `--windowed-mode` | Force windowed mode |
### Accessing in Code
```csharp
// Check flag presence
if (appArgs.HasFlag(AppArgsFlags.DEBUG))
EnableDebugMode();
// Get flag value
if (appArgs.TryGetValue(AppArgsFlags.REALM, out var realm))
UseRealm(realm);
```
No comments yet. Be the first to comment!