Roblox vs UEFN tools - a gamejam study

So I spent the last 2 days to develop a game with tools I dont know both in Roblox Studio and in UEFN (using verse and SG).

I noticed a few things while doing both, and I can tell the weakness of each editor now with more clear eyes. Note that I didnt go in too deep for each, for the sake of time, I spent one day on each tool with the goal to build something at the end.

Roblox day 1: Built a trading card shop simulator, all basic mechanics needed to run the basic game loop, but minimal art.

UEFN day 1: Built some verse texts and got stuck in UMG having to add 262 Verse fields to build an inventory system. I didn’t have a prototype at the end, just some verse scripts.

Roblox strengths: Ease of access to logic, Lua is easy to understand, organized explorer (think outliner) that shows exactly where scripts go in server vs client, and where the persistant storage and player saves lie. All coding is very well documented and tools like Claude helped set up the game really fast and with ease.

UEFN strengths: Easy access to art and environmental props, you can easily make something look pretty without too much effort

Roblox weakness: Basic level design functionalities (like hiding props) are missing and its hard to level design with accuracy. Didnt feel fun to design anything, unless it was basic building blocks like boxes. Basic things like selecting actors within groups took a while to understand and generally not very intuitive on that front. I can see why their community generally struggles with art.

UEFN weakness: Unbelievably messy to understand what is happening logic-wise. Even if you manage to set up verse, there are a lot of technical terms like “super concrete” or “fun” lambda, and even though Claude helped me set it up, he encountered a miriad of errors and we had to do back and forths a lot to figure out things because documentation and digests were not sufficient, he even asked me to watch the videos in the doc site because he cant access it. From roblox at least I started learning how lua operates because all the scripts were super simple. Here everything just felt foreign even though I ve done verse coding before. Also trying to set up a simple inventory to show items, I couldnt do it without getting tendonditis in my hand (I am not kidding btw), as the process for a 64 slot inventory (thats not Verse UI) requires me to set up around 262 verse fields, without the ability to copy-paste, and without access to an index. All while I had to rename each manually and then set up all the viewbinding also manually for each of those 262 hooks. And at the end, Claude messed it up and mixed up devices and SG (cause he doesnt understand the difference) and nothing worked. And this solution is not scalable as well, cause the moment I wanted to add more, I had to go through this manual process again.

At the end, I just want to build stuff in UEFN cause it looks so much nicer, but sometimes I just wish we had Roblox’s logic structure and UEFN’s art assets instead of Verse, especially when Epic doesnt want to commit to an interface and help us understand it. Until that happens, verse is not for me.

Outlook of both days of work:

Roblox:

### Session Summary — What We Built

**Phase 1 — World**

* 8 plots with road and borders
* Retro shop shell with checkerboard floor
* Shop front with sliding glass doors, awning, neon CARD CAVE sign

**Phase 2 — Card System**

* 16 cards across 5 rarities (Common → Legendary)
* Weighted pack opening system
* Two pack types (Starter, Premium)

**Phase 3 — Core Loop**

* Player inventory system
* Pack dispenser with ProximityPrompt
* Shelf stocking system with 18 slots
* NPC customers that browse, pick cards and wait at counter
* Counter serving with money + reputation rewards

**Phase 4 — Progression & UI**

* HUD with money, rep, cards counter
* Inventory UI with card grid and STOCK buttons
* Save system with unique slot UIDs
* Full daily cycle — sliding doors, open/closed signs, day bar, end of day report

UEFN:

**UEFN / Verse / Scene Graph / UMG — Session Notes**

**Verse Language Specifics**

* Component classes must use `<final_super>` not `<final>` to satisfy the `component` base type requirement
* Module-level constants use `<internal>` not `<private>` for visibility
* `<private>` is only valid inside classes
* Class fields need `var` to be readable/settable after construction — non-`var` fields are construction-time only
* `message` type cannot be initialized with `""` — declare without a default value
* `player` cannot be used as a regular map key — use `weak_map(player, T)` instead
* `weak_map` handles player cleanup automatically when they leave — perfect for per-player state
* `OnSimulate<override>()<suspends>` is available on `component` subclasses but NOT on `creative_device` — devices use `OnBegin` for async loops
* `fun` inline lambdas don't work at class scope in Verse
* `Subscribe` with direct method references doesn't work — use `OnSimulate` with `Await` loops instead
* `GetComponent[T]` uses `<decides>` so goes inside `if` — no extra `[]` needed
* `AddItem` returns `result(add_item_result, []add_item_error)` — can't unwrap with `?`, use `GetSuccess` or ignore
* `spawn { }` is needed to run suspending functions concurrently from a non-suspending context
* Verse files in the same project share the same namespace automatically — no self-import needed

**Itemization / Scene Graph API**

* `inventory_component` uses `find_inventory_event` (downward, chooses inventory) and `add_item_query_event` (upward, vetoes)
* To reject an item use `add_item_query_event.AddError(your_error{})`
* `add_item_result.AddedItems` is an array — always iterate, never assume single item
* `remove_item_result.RemovedItems` is also an array
* `AddItemEvent` and `RemoveItemEvent` are listenables on `inventory_component` — use `Await()` in a loop
* Native `rarity_component` exists with built-in rarity classes — use `FortniteRarities.Common` etc.
* Native `stackable_component` / `basic_stackable_component` handles stacking, merging, splitting natively
* `item_component` has `GetParentInventory`, `Drop`, `PickUp`, `Equip`, `Unequip`
* Player entities don't automatically have custom components — must be added via `AddComponents()` on join

**Architecture Patterns**

* Per-player state: create on `PlayerAddedEvent`, store in `weak_map(player, T)`, auto-cleans on leave
* Session manager pattern: dedicated `creative_device` owns player state maps, exposes `GetX<public>(Player)<decides>` methods
* Backpack should be created at session level, not on demand — it's used everywhere not just at chest
* For shared team chest: single world entity with `chest_component` — all players reference the same entity so inventory is already shared at data level
* UI sync happens by listening to `AddItemEvent`/`RemoveItemEvent` on the shared chest and pushing updates

**UMG in UEFN — Key Differences from UE5**

* No `OnDragDetected` — native drag and drop is not supported
* No `Horizontal Box` / `Vertical Box` explicitly — use `Stack Box` with orientation setting
* Available widgets: `Custom Button`, `Image`, `Named Slot`, `UEFN Text Block`, `Canvas Panel`, `Grid Panel`, `Overlay`, `Scale Box`, `Scroll Box`, `Size Box`, `Stack Box`, `Uniform Grid Panel`, `Widget Switcher`, `Wrap Box`, `Touch Action Wrapper`, `Action Widget`
* User created: `UEFN Button Loud/Quiet/Regular`, `UEFN Slider`
* `Overlay` as root is better than `Canvas Panel` — saves a draw call, uses padding instead of anchors
* Supported Verse field types for View Bindings: `logic`, `int`, `float`, `string`, `message`, `event`, `color`, `color_alpha`, `material`, `texture`
* Arrays/maps are NOT supported as Verse field types — must declare flat individual fields
* `message` is preferred over `string` for displayed text — localisation support
* No array field support means 74 individual fields for 8 backpack + 16 chest slots (3 fields each + 2 labels)

**Verse Fields / UMG Binding Pattern**

* Verse Fields introduced in v38.00 (November 2025)
* Fields are declared in the UMG widget's **Class Settings** panel
* After compile they appear in `Assets.digest.verse` as a typed Verse class automatically
* The widget class extends `widget` from `/UnrealEngine.com/Temporary/UI`
* Fields are accessed directly: `set Widget.FieldName = value`
* Button events come back as `event(tuple())` fields — `Await()` them in loops
* The widget is instantiated in Verse as `WBP_YourWidget{}` and shown via `GetPlayerUI[Player].AddWidget()`
* No separate viewmodel class needed — the widget IS the viewmodel
* The old MVVM Viewmodels panel is separate and not what Verse Fields uses

**Project Structure**

* `item_data.verse` — `item_stats_component` with Name, Type, Size, Value (all `var`)
* `backpack_component.verse` — 8-slot personal inventory, slot tracking via `OnSimulate` loop
* `chest_component.verse` — 16-slot shared chest, same pattern, plus `GetFreeSlots`/`GetUsedSlots`
* `chest_device.verse` — creates widget per player, shows/hides on trigger, deposit/withdraw routing
* `inventory_manager.verse` — (planned) session-level device owning `weak_map(player, backpack_component)`
* `WBP_InventoryScreen` — UMG widget with 74 Verse fields, split-screen backpack/chest layout

**Where We Left Off**

* All Verse files compile clean
* Widget reflects correctly in digest
* UI shows/hides on trigger (confirmed structure works)
* Backpack component not yet created on player join — `inventory_manager.verse` is the next step
* Slot buttons not yet added to UMG widget — need 8 backpack + 16 chest `Custom Button` widgets
* View Bindings not yet wired — each button needs `On Clicked` bound to a Verse event field, `Render Opacity` bound to `Selected` field, rarity color bound to an `Image` inside each button
* Interactable component on chest box not yet implemented — replacing trigger device approach
* No test items spawned yet — full inventory loop not yet validated end to end
type or paste code here

Interesting test, tells me Claude knows very little about verse as there’s no reason to build more verse fields than there are “inventory slots” to show at one time. Sounds like it tried to hardcode things, instead of building a dynamic display system. I don’t think I know a single language where you’d do that outside of maybe back in the day with HTML “coding”..

Time will tell if somebody or some entity decided to educate Claude, but I think the biggest issue is lack of examples and docs on the language just yet.