Skip to content

t1k:unity:tof:feature-entry

FieldValue
Moduletof
Version2.2.2
Efforthigh
Tools

Keywords: btn_, controller, entry-point, feature-button, feature-entry, FeatureEntryConfig, FeatureEntryDefaultConfig, FeatureEntryLocationConfig, orchestration, scriptable-object, spine-skin, ViewId

/t1k:unity:tof:feature-entry

Core implementation of entry core feature for Unity games.

A TheOneFeature module that is DI-registered (builder.RegisterRaceEvent()) is fully functional in code but invisible to the player until it is also added to the FeatureEntry configs. These two ScriptableObjects drive which features appear at which UI anchors.

AssetRole
Assets/Resources/GameConfigs/FeatureEntryDefaultConfig.assetPer-feature defaults — icon, label key, default visibility, badge rules
Assets/Resources/GameConfigs/FeatureEntryLocationConfig.assetPer-location placement — which features appear at which anchor, in what order

Both are loaded via Resources.Load by the FeatureEntry framework at startup. Editing them is a YAML .asset change — read unity-text-config Tier 2 rules first; prefer the Inspector when possible.

Integration Workflow (Adding a New Feature)

Section titled “Integration Workflow (Adding a New Feature)”
  1. DI register the feature + its XxxFeatureEntry/XxxFeatureEntryView first (see t1k-unity-tof-registration).
  2. FeatureEntryDefaultConfig<DefaultRemoteConfig>k__BackingField is an escaped JSON string keyed by the FeatureEntry class name (NOT a short id). Append a key for your entry:
    "XxxFeatureEntry": { "$type": "XxxCondition", "Level": 0, "AlwaysShow": false, "SkinType": "skeleton", "Skin": "btn_xxx_skin" }
    • key = the XxxFeatureEntry class name; $type = its IFeatureCondition impl (e.g. ExpeditionCondition).
    • Skin = the Addressables address of the Spine SkeletonDataAsset (see button reference); SkinType: "skeleton".
  3. Build the button prefab + skin — create btn_<feature>.prefab (variant of btn_feature), wire its featureId/label/view component, register its Addressable at address = the entry’s ViewId, and create/point its Spine skin. Full procedure: references/add-feature-entry-button.md.
  4. FeatureEntryLocationConfig — append entries that map the feature into the locations where it should appear (HomeScreen header, WinPopup grid, ShopHeader, etc.). Order matters — it controls visual order at that anchor.
  5. Verify — see Verification section below.

Common location keys present in FeatureEntryLocationConfig:

  • HomeScreen — main menu entries
  • WinPopup / LosePopup — end-of-level entries
  • ShopHeader — top strip of the shop
  • LoadingScreen — loading screen badges

A feature can appear at multiple locations by adding multiple rows in the Location config.

  • Play the scene that hosts the anchor. The new entry button should appear with the correct icon + label.
  • Missing icon → check the IconAddress resolves via IAssetsManager.LoadAsync<Sprite>().
  • Missing label → check the localization key exists in the active locale’s string table.
  • Missing button → entry exists in Default but not in Location config, or DefaultEnabled = false.
  • FeatureId must match the string the feature’s own DI registration uses to identify itself. Mismatch = button shows but click goes nowhere.
  • Order is significant in Location config — appending vs inserting changes the on-screen layout.
  • Both configs live under Resources/ — they bypass Addressables on purpose. Do not move them or Resources.Load will return null at runtime.
  • Inspector edits are safer than YAML edits because Unity rewrites fileID/guid references for sprite + ScriptableObject fields. Hand-editing those references is the #1 cause of missing icons after a “simple” edit.
  • Features without an entry config row are not invisible — they are inactive. The FeatureEntry framework only ticks features that exist in FeatureEntryDefaultConfig. So forgetting this step also breaks badge updates, blueprint refresh hooks, and event subscriptions wired through the entry framework.
  • ViewId IS the Addressables address of the button prefab. The framework loads btn_<feature> by that address; forgetting to register the prefab in the Addressables group (UIs.asset for the home/shop strip) means the entry silently has no view. See references/add-feature-entry-button.md.
  • Config key + condition $type are CLASS names, not slugs — the JSON is keyed by XxxFeatureEntry and $type is the XxxCondition class. (The older “FeatureId/IconAddress/LabelLocalizationKey/DefaultEnabled” field description was inaccurate — the real schema is the Skin/$type JSON shown in step 2.)
  • Cloning a sibling button keeps its view component — you must swap the root MonoBehaviour’s m_Script guid to your XxxFeatureEntryView, or BaseFeatureEntry.SetView’s (T) cast gets the wrong type. Full prefab + Spine-skin clone procedure: references/add-feature-entry-button.md.
  • Sub-agents don’t get Unity MCP tools forwarded — a spawned agent can write asset files + metas correctly but cannot refresh_unity/read_console. Run the import/verify from the main session or have the user focus the Editor to auto-refresh.
  • Creating a variant prefab is NOT possible via MCP — use a temp Editor MenuItem script. manage_prefabs.create_from_gameobject only makes standalone prefabs (and errors with unlink_if_instance:false); execute_code’s CodeDom backend fails on Windows ("filename or extension is too long" from mono.exe) and Roslyn isn’t installed. The reliable path is a temporary [MenuItem] script calling PrefabUtility.SaveAsPrefabAsset(instance, path) on a prefab instance (produces a true Variant), driven by execute_menu_item, then deleted. Full pattern: references/add-feature-entry-button.md § “Authoring a variant from a base prefab”.
  • Use “Auto Generate Children” to wire a view’s serialized fields. Assets/UITemplate/Tools/SerializeFieldCreator/ ships a CONTEXT/MonoBehaviour/Auto Generate Children tool that creates + assigns a child per empty [SerializeField] object reference. It’s a context menu (needs a MenuCommand, can’t be run via execute_menu_item) and must run inside an open Prefab Stage — drive it by reflection from a temp script. It fails on abstract TMP_Text-typed fields ("can't add … abstract") — those children are created unassigned; finish them by adding a concrete TextMeshProUGUI and assigning. Full procedure + cleanup steps: references/add-feature-entry-button.md § “Auto-generate + wire the view’s serialized children”.

interface

  • IFeatureCondition (IFeatureCondition.cs)
  • IFeatureConditionHandler (IFeatureCondition.Handler.cs)
  • IFeatureCurrencyTracking (IFeatureCurrencyTracking.cs)
  • IFeatureEntry (IFeatureEntry.cs)
  • IFeatureEntryService (IFeatureEntryService.cs)
  • IFeatureEntryView (IFeatureEntry.View.cs)
  • IFeatureInitializeHandler (IFeatureInitializeHandler.cs)
  • IFeatureInitializeService (IFeatureInitializeService.cs)
  • IFeatureLocation (FeatureEntryLocationConfig.cs)

class

  • BaseFeatureCondition (IFeatureCondition.cs)
  • BaseFeatureConditionHandler (IFeatureCondition.Handler.cs)
  • FeatureConditionDropdownAttribute (FeatureConditionDropdownAttribute.cs)
  • FeatureConditionOptionAttributeDrawer (FeatureConditionOptionAttributeDrawer.cs)
  • FeatureDropdownAttribute (FeatureDropdownAttribute.cs)
  • FeatureEntryAsyncExtensions (FeatureEntryAsyncExtensions.cs)
  • FeatureEntryConfig (FeatureEntryConfig.cs)
  • FeatureEntryConfigConvert (FeatureEntryConfig.Convert.cs)
  • FeatureEntryConfigToolModule (FeatureEntryConfigToolModule.cs)
  • FeatureEntryDataController (FeatureEntryDataController.cs)
  • FeatureEntryDefaultConfig (FeatureEntryDefaultConfig.cs)
  • FeatureEntryFTUECondition (FeatureEntryFTUECondition.cs)
  • FeatureEntryLocationConfig (FeatureEntryLocationConfig.cs)
  • FeatureEntryLocationConfigToolModule (FeatureEntryLocationConfigToolModule.cs)
  • FeatureEntryPresenterExtensions (IFeatureEntry.cs)
  • FeatureEntryService (FeatureEntryService.cs)
  • FeatureEntryUnlockModel (FeatureEntryUnlockService.cs)
  • FeatureEntryUnlockService (FeatureEntryUnlockService.cs)
  • FeatureEntryValidator (FeatureEntryValidator.cs)
  • FeatureEntryVContainer (FeatureEntryVContainer.cs)
  • FeatureInitializeService (FeatureInitializeService.cs)
  • FeatureLocation (FeatureEntryLocationConfig.cs)
  • FeatureManagerVContainer (FeatureManagerVContainer.cs)
  • FeatureOptionAttributeDrawer (FeatureOptionAttributeDrawer.cs)
  • TypeDropdownAttribute (TypeDropdownAttribute.cs)
  • TypeDropdownAttributeDrawer (TypeDropdownAttributeDrawer.cs)

None detected.

  • FeatureEntryDefaultConfig
  • FeatureEntryLocationConfig
  • FeatureLocation
  1. Reference package TheOneFeature in your project.
  2. Register the Feature Entry services via VContainer (see Architecture).
  3. Configure any ScriptableObjects listed in Config section.
  4. Subscribe to signals listed in Signals / Events to react to state changes.

Detected public types (35):

interface

  • IFeatureCondition (IFeatureCondition.cs)
  • IFeatureConditionHandler (IFeatureCondition.Handler.cs)
  • IFeatureCurrencyTracking (IFeatureCurrencyTracking.cs)
  • IFeatureEntry (IFeatureEntry.cs)
  • IFeatureEntryService (IFeatureEntryService.cs)
  • IFeatureEntryView (IFeatureEntry.View.cs)
  • IFeatureInitializeHandler (IFeatureInitializeHandler.cs)
  • IFeatureInitializeService (IFeatureInitializeService.cs)
  • IFeatureLocation (FeatureEntryLocationConfig.cs)

class

  • BaseFeatureCondition (IFeatureCondition.cs)
  • BaseFeatureConditionHandler (IFeatureCondition.Handler.cs)
  • FeatureConditionDropdownAttribute (FeatureConditionDropdownAttribute.cs)
  • FeatureConditionOptionAttributeDrawer (FeatureConditionOptionAttributeDrawer.cs)
  • FeatureDropdownAttribute (FeatureDropdownAttribute.cs)
  • FeatureEntryAsyncExtensions (FeatureEntryAsyncExtensions.cs)
  • FeatureEntryConfig (FeatureEntryConfig.cs)
  • FeatureEntryConfigConvert (FeatureEntryConfig.Convert.cs)
  • FeatureEntryConfigToolModule (FeatureEntryConfigToolModule.cs)
  • FeatureEntryDataController (FeatureEntryDataController.cs)
  • FeatureEntryDefaultConfig (FeatureEntryDefaultConfig.cs)
  • FeatureEntryFTUECondition (FeatureEntryFTUECondition.cs)
  • FeatureEntryLocationConfig (FeatureEntryLocationConfig.cs)
  • FeatureEntryLocationConfigToolModule (FeatureEntryLocationConfigToolModule.cs)
  • FeatureEntryPresenterExtensions (IFeatureEntry.cs)
  • FeatureEntryService (FeatureEntryService.cs)
  • FeatureEntryUnlockModel (FeatureEntryUnlockService.cs)
  • FeatureEntryUnlockService (FeatureEntryUnlockService.cs)
  • FeatureEntryValidator (FeatureEntryValidator.cs)
  • FeatureEntryVContainer (FeatureEntryVContainer.cs)
  • FeatureInitializeService (FeatureInitializeService.cs)
  • FeatureLocation (FeatureEntryLocationConfig.cs)
  • FeatureManagerVContainer (FeatureManagerVContainer.cs)
  • FeatureOptionAttributeDrawer (FeatureOptionAttributeDrawer.cs)
  • TypeDropdownAttribute (TypeDropdownAttribute.cs)
  • TypeDropdownAttributeDrawer (TypeDropdownAttributeDrawer.cs)

Detected DI registrations:

  • FeatureConditionDropdownAttribute
  • FeatureDropdownAttribute
  • FeatureEntryDataController
  • FeatureEntryService
  • FeatureEntryUnlockService
  • FeatureInitializeService

Run with FEATURE_MATRIX/DEPENDENCY_GRAPH integration to fill.

  • Source: UnityTheOneFeatureProject/Packages/TheOneFeature/Core/Features/FeatureEntry/
  • Doc: UnityTheOneFeatureProject/Packages/TheOneFeature/Core/Features/FeatureEntry/Core/README.md
  • Doc: UnityTheOneFeatureProject/Packages/TheOneFeature/Core/Features/FeatureEntry/Core/CHANGELOG.md
  • Doc: UnityTheOneFeatureProject/Packages/TheOneFeature/Core/Features/FeatureEntry/Default/CHANGELOG.md
  • Namespace: TheOne.Features.FeatureEntry.Core.Editor, TheOne.Features.FeatureEntry.Core, TheOne.Features.FeatureEntry.Core.DI, TheOne.Features.FeatureEntry.Core.Entry, TheOneFeature.Core.Features.FeatureEntry.Scripts.FTUE, TheOne.Features.FeatureEntry.Core.LocalData, TheOne.Features.FeatureEntry.Core.Models.Conditions, TheOne.Features.FeatureEntry.Core.Models, TheOne.Features.FeatureEntry.Default.DI, TheOne.Features.FeatureEntry.Default