Skip to content

UI and Interaction Architecture Findings

Date: 2026-05-13

This note captures C++ architecture findings from the pre-refactor review. It is intentionally scoped to ownership, coupling, and Unreal C++ best-practice concerns.

Status: historical. Several recommendations have since been implemented, including moving prompt ownership to AAndromedaHUD, replacing concrete character handoff with carry-provider interfaces, removing the old processing result UI, removing the reusable interactable component pattern, and reorganizing source folders by ownership boundary. Current rules live in Ownership Boundaries, Gameplay Scaffold, and Unreal Project Structure.

Review Scope

  • Reviewed all 35 C++ files under Source/Andromeda.
  • Covered character, player controller, game mode/module setup, interaction interfaces/components, carry behavior, salvage item/data types, workstation actors, spawn point, and UI widgets.
  • No code changes were made as part of the review.

Findings At Time Of Review

  • AAndromedaCharacter owns too much UI presentation. It creates and updates the interaction prompt widget, tracks prompt suppression, and pushes focus changes directly into UI.
  • UI creation and input mode ownership are split across gameplay classes. Scanner and warehouse actors create viewport widgets and set mouse/input mode, while the widgets close themselves and cast back to the character.
  • Workstation interaction now depends on inherited physical screen components plus placement validation volumes. ScreenComponent forwards workstation operation intent and can host workstation widgets; placement volumes validate freeform-placed items without owning interaction behavior. Missing visual widget setup should not block scanner gameplay.
  • The previous reusable interactable component pattern has been removed. capability implementers now own their own capability state and return explicit event sources.
  • Workstation, carry, and salvage item ownership is circular. Carry clears workstation state when picking up an item; workstations pull carry state directly from AAndromedaCharacter; salvage items track both HeldBy and CurrentStation.

Things That Are Already Reasonable

  • Components generally use TObjectPtr and UPROPERTY where Unreal lifetime tracking matters.
  • Most gameplay actors/components disable ticking when they do not need it. The character tick is currently justified by interaction focus tracing, though that may move into an interaction component later.
  • UAndromedaCarryComponent is a good direction for separating carry mechanics from the character, even though its station cleanup responsibility should be revisited.
  • UAndromedaSalvageItemData as a UPrimaryDataAsset is an appropriate place for authorable salvage definitions and package requirements.
  • AAndromedaSalvageSpawnPoint, AAndromedaGameMode, the module files, and the passive widget data-refresh code did not show major ownership problems.

Detailed Ownership Notes

  • The interaction prompt should move out of AAndromedaCharacter, but the character can remain the source of focus information until a dedicated interaction component exists.
  • Input mode and cursor state should be centralized in AAndromedaPlayerController, not controlled by workstation actors or individual widgets.
  • Result widgets should not cast to AAndromedaCharacter to unsuppress prompts. Closing UI should notify a controller/UI owner, which then restores the appropriate interaction mode.
  • Scanner, packager, and warehouse screens should not be treated as suit HUD panels by default. They are workstation-owned world screens with their own UX.
  • The suit HUD can still receive station data after interaction, such as scan history or a compact "scan received" notification.
  • AAndromedaWorkstation::PlaceItemFromCharacter ties stations specifically to AAndromedaCharacter. A later refactor should prefer an interface/component-oriented handoff so stations depend on carry capability, not a concrete character class.
  • UAndromedaCarryComponent::TryPickUpTarget is now the authoritative pickup execution point. Future work should watch whether character focus/input routing grows large enough to justify a dedicated interaction router component.
  • AAndromedaSalvageItem owns both domain state and pickup debug presentation. Domain state belongs there for now; user-facing presentation should move out.

Desired UI Model

There are two separate UI categories:

  • Suit HUD: player-owned helmet UI. This should handle persistent player-facing information such as the interaction prompt, carried item state, player/suit state, compact scanned-item recall, alerts, and notifications.
  • World screens: workstation-owned physical screens. Scanner and packager workstation screens should belong to their world actors and present workstation-specific state.

The scanner flow should eventually look like this:

Player interacts with scanner
-> scanner processes item
-> scanner updates its own world-space screen
-> scanner records scan data in the station databank
-> suit HUD may show a compact alert or allow recall later
  • Character or interaction component: movement, camera, carrying, interaction trace/focus, activating interactables.
  • Player controller: input mode, cursor state, interaction mode, routing between player, suit HUD, and focused workstation screens.
  • HUD or player-owned UI component: interaction prompt, persistent suit HUD widgets, player/suit state presentation, scan recall, notifications.
  • Workstation actors: workstation gameplay, workstation state, and workstation-attached world-space screen data.
  • Widgets: passive presentation and button events only. They should avoid owning global input mode or casting to the character for gameplay/UI state changes.

Likely Refactor Direction

  1. Introduce a suit HUD owner, likely AAndromedaHUD or a controller-owned UAndromedaSuitHudComponent.
  2. Move the interaction prompt out of AAndromedaCharacter into the suit HUD.
  3. Have the character or a future UAndromedaInteractionComponent broadcast focused interactable changes instead of directly updating widgets.
  4. Move modal input mode/cursor handling into AAndromedaPlayerController.
  5. Continue converting remaining temporary workstation result UI into workstation-owned screen state where the interaction design calls for it.
  6. Untangle station/carry/salvage ownership by making one layer responsible for each state transition.