t1k:unity:tof:feature-entry
| Field | Value |
|---|---|
| Module | tof |
| Version | 2.2.2 |
| Effort | high |
| Tools | — |
Keywords: btn_, controller, entry-point, feature-button, feature-entry, FeatureEntryConfig, FeatureEntryDefaultConfig, FeatureEntryLocationConfig, orchestration, scriptable-object, spine-skin, ViewId
How to invoke
Section titled “How to invoke”/t1k:unity:tof:feature-entryFeature Entry
Section titled “Feature Entry”Purpose
Section titled “Purpose”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.
The Two Configs
Section titled “The Two Configs”| Asset | Role |
|---|---|
Assets/Resources/GameConfigs/FeatureEntryDefaultConfig.asset | Per-feature defaults — icon, label key, default visibility, badge rules |
Assets/Resources/GameConfigs/FeatureEntryLocationConfig.asset | Per-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)”- DI register the feature + its
XxxFeatureEntry/XxxFeatureEntryViewfirst (seet1k-unity-tof-registration). - FeatureEntryDefaultConfig —
<DefaultRemoteConfig>k__BackingFieldis 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
XxxFeatureEntryclass name;$type= itsIFeatureConditionimpl (e.g.ExpeditionCondition). Skin= the Addressables address of the SpineSkeletonDataAsset(see button reference);SkinType: "skeleton".
- key = the
- Build the button prefab + skin — create
btn_<feature>.prefab(variant ofbtn_feature), wire itsfeatureId/label/view component, register its Addressable at address = the entry’sViewId, and create/point its Spine skin. Full procedure:references/add-feature-entry-button.md. - 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.
- Verify — see Verification section below.
Locations (Commonly Observed)
Section titled “Locations (Commonly Observed)”Common location keys present in FeatureEntryLocationConfig:
HomeScreen— main menu entriesWinPopup/LosePopup— end-of-level entriesShopHeader— top strip of the shopLoadingScreen— loading screen badges
A feature can appear at multiple locations by adding multiple rows in the Location config.
Verification
Section titled “Verification”- Play the scene that hosts the anchor. The new entry button should appear with the correct icon + label.
- Missing icon → check the
IconAddressresolves viaIAssetsManager.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.
Gotchas
Section titled “Gotchas”- 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 orResources.Loadwill return null at runtime. - Inspector edits are safer than YAML edits because Unity rewrites
fileID/guidreferences 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. ViewIdIS the Addressables address of the button prefab. The framework loadsbtn_<feature>by that address; forgetting to register the prefab in the Addressables group (UIs.assetfor the home/shop strip) means the entry silently has no view. Seereferences/add-feature-entry-button.md.- Config key + condition
$typeare CLASS names, not slugs — the JSON is keyed byXxxFeatureEntryand$typeis theXxxConditionclass. (The older “FeatureId/IconAddress/LabelLocalizationKey/DefaultEnabled” field description was inaccurate — the real schema is theSkin/$typeJSON shown in step 2.) - Cloning a sibling button keeps its view component — you must swap the root MonoBehaviour’s
m_Scriptguid to yourXxxFeatureEntryView, orBaseFeatureEntry.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
MenuItemscript.manage_prefabs.create_from_gameobjectonly makes standalone prefabs (and errors withunlink_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 callingPrefabUtility.SaveAsPrefabAsset(instance, path)on a prefab instance (produces a true Variant), driven byexecute_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 aCONTEXT/MonoBehaviour/Auto Generate Childrentool that creates + assigns a child per empty[SerializeField]object reference. It’s a context menu (needs aMenuCommand, can’t be run viaexecute_menu_item) and must run inside an open Prefab Stage — drive it by reflection from a temp script. It fails on abstractTMP_Text-typed fields ("can't add … abstract") — those children are created unassigned; finish them by adding a concreteTextMeshProUGUIand assigning. Full procedure + cleanup steps:references/add-feature-entry-button.md§ “Auto-generate + wire the view’s serialized children”.
Public API
Section titled “Public API”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)
Signals / Events
Section titled “Signals / Events”None detected.
Config / ScriptableObjects
Section titled “Config / ScriptableObjects”FeatureEntryDefaultConfigFeatureEntryLocationConfigFeatureLocation
Integration Steps
Section titled “Integration Steps”- Reference package
TheOneFeaturein your project. - Register the Feature Entry services via VContainer (see Architecture).
- Configure any ScriptableObjects listed in Config section.
- Subscribe to signals listed in Signals / Events to react to state changes.
Architecture
Section titled “Architecture”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:
FeatureConditionDropdownAttributeFeatureDropdownAttributeFeatureEntryDataControllerFeatureEntryServiceFeatureEntryUnlockServiceFeatureInitializeService
Dependencies
Section titled “Dependencies”Run with FEATURE_MATRIX/DEPENDENCY_GRAPH integration to fill.
References
Section titled “References”- 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