A Talk about the current state and implementation decisions of Scene Graph Items

I am a little sad about the custom inventory and items that was presented to us, and how it was done/implemented.
In short, what was released was basically just a “bridge” so they can make old systems (existing items, game systems and actor-based stuff) compatible with scene graph tech, and also making the custom SG items compatible with old systems for backward compatibility.
While I understand the reasons why they choose this approach, I believe that it can be evasive and limiting long term if we want to use the provided itemization API (Besides in the future we being able to create this from scratch ourselves).


To be honest, I was already aware of how custom items were supposed to work already on lots of updates ago (I keep track of internal digest changes on each game update), so how the implementation was intended to work was not a mystery at all and I even had written example pseudo-codes with friends many months before its actual experimental release.

That being said, since some time was past after the experimental release, I think it should be time for me to comment about the topic:

The Problem:

Fortnite has lots of “blueprint items” that was carried for the entire game lifetime. These items are not compatible with Scene Graph, and recreating all these thousands of items with new APIs and functionality from scratch would take much time (developing new tech needed, interactions, functionality, time spent, interfaces, keybinds and so on). This is absurdly unpractical to do, at least on short term.

What they did:

To “address” that problem, and keep support of old non-SG item/inventory systems, they choosed to create the “Itemization” module for SG (part of UE and Fortnite modules).
But all the utility provided by this module is nothing more to provide the “bridge” between old blueprint/hardcoded tech and the new Scene Graph, so creators could keep using old items “without issues”.

Some examples of this are:

  • fort_item_pickup_component => This is to “bridge” old items tech actor on world (as the name says, the pickup logic, including the interface, interaction, animation and so on)

  • item_component => Don’t need to exist at all (at least I could not find a obvious reason for), but needing to exist just to be able to interact with the custom inventory_component they made on the Itemization module

  • item_details_component and item_icon_component => To “bridge” with old items tech providing data-driven details, such as having a hardcoded place where the internal systems can “look” the icon and text data to display on interfaces

  • item_category => Also only needed to exist to provide existing old hardcoded sytems the rules (such as pickaxe slot, traps, ammo, and even creative phone during edit mode)

  • inventory_component => Only needed to exist to be able to use as bridge to hardcoded data definitions and internal old systems/logic, such as attaching to non exposed game rules, input mappings and so on…

  • fort_inventory_component and fort_inventory_XXXX_component => Subclasses of base inventory, specifically made for fortnite internal systems, also with the reason of providing hardcoded data driven and/or compatibility with old systems and logic (such as the base game config and container data)

  • Itemization Configuration Asset => This is the “root” itemization configuration on the experience, when the island is set to use one, it will replace the old items config (quickbar/inv screens and keybinds) with the custom data-driven configuration defined inside the asset.
    While I believe that we will be able to make our own variants of this asset on the future, this is still just another way they made to bridge old tech to the new itemization system in a hardcoded way (also explaining the need of other components above to link on internal systems).

These same rules also applies to unreleased/internal components:

  • item_ability_component, item_attributes_component, item_rarity_component, item_type_component => All these just exist to provide bridges to non-SG tech, such as data-driven “where to look for this data” on non existing systems (for example to display item info on UI).

­Basically all this were already possible before. The current provided Itemization API is just wacky workarounds with basically no new features.
Inventories are basically just container classes that holds data and interactions written in logic directly on code, other components that are also data-only we can make it all from scratch. The same with item definitions itself (both inside inventories or dropped on the world), we could do that from scratch by using other provided components, such as interactable_component for example.
­
While I understand the needs of this design choice on short term, I still think that the showcased state of custom items were made as an excuse like “implement items as fast as possible” while other proper scene graph tech and editor utility is not finished, or not ready for the public yet to make itemization in a better way.


The real utility to make custom items that were not possible before was not given at all, this include already planned unreleased features and future components tech, some examples are:

  • screen_space_ui_display_component => Used to render a UI on player screen, but anchored to a world position (to recreate the fort_item_pickup_component interface)

  • presentation_component and replication_component => Used to define custom replication and visibility rules (ex. make item visible or interactive to only certain players)

  • item_attachment_component => Used to attach entities in a specific way (such as to bones or sockets of a skeletal mesh, like to make player “hold” the item). This is also not even something that is item exclusive functionality, for example, the component could have been named just attachment_component and being part of the core tech instead of itemization tech.

  • item_owner_pose_modifier_component => Used to provide modifiers to the player current pose while holding or having the item. This is also not needed to be related to itemization, should be part of core functionality to assign custom poses to the player regardless of being items or not. This is one of the most important tech needed to make new gameplay (together with other future planned tech such as skeletal mesh components and animation sequences)

  • Property Interfaces => Data Assets to provide data-driven functionality between UMG Widgets and Verse, allowing more complex, detailed and powerful interfaces being made (since widgets in verse don’t have all properties and functionality that the same widgets in UMG has). This is used for everything needed, from the in-world pickup UI, to the Quickbar, Specific Item Details (such as durability and cooldown), Entire Inventories and other HUD screens as the developer need and/or want.

  • Input Mapping Contexts and Input Actions => This is to manage player input (such as keybinds, values, priority and per-platform rules), providing the interaction that can be used in verse to make anything wanted (user interface shortcut for buttons, ability keybinds for items and so on). Currently we have some VERY limited epic-curated actions and mappings, without possibility of modifying, disabling, making new ones or even configuring priority. This is also one of the most important tech to make custom items and abilities possible.

  • Any data-only component (such as item icon, item details, rarity, type, attributes) can already be made by just making our own simple component to hold it, or even attaching the data somewhere else outside a component! The same for other functional behaviors such as attaching input mappings for example.

Again, basically all of the current Itemization API is just to provide internal bridges with old tech in a unflexible hardcoded way.

With the combination of the components and tech listed above (all mentioned already exist but is internal or unfinished), we could basically recreate the entire Itemization modules from scratch! And even better: we would not be limited by the current problems of itemization, such as relying on epic adding fields and customization for properties or functionality (One example is: we can’t change how the pickup popup ui looks, gravity and anims).


With the current state and how it was implemented, we will always be relying on epic providing the functionality or exposing more things to interact with the internal/hardcoded API…
Sure, Epic can improve the itemization module over time, adding more flexibility and features, but it would still be on Epic hands, instead of being on creators hand (which is totally possible), where epic could have provided only the necessary hardcoded data on their part (such as existing items and native fortnite inventories), instead of making the entire itemization tech relying on their own “core module” for all creator implementations of it even when not needed.

Don’t get me wrong, I am not talking that epic providing templates or a guide on how to make custom items are useless, but it could be done completely differently while also being more flexible. I understand the needs to keep support to old existing items/weapons, but making the entire scene graph itemization as a bridge for the old stuff was not a good thing for flexibility, and some details seems to even go against what scene graph promises…
Would be much better to just finish these mentioned internal components, and giving examples using them to build the custom items and inventories with it, instead of doing all the wacky workaround for backwards compatibility that could have been done in other less intrusive ways.


Obviously, in the future we could also do our own itemization module from scratch if we wanted (like using the components mentioned), but that would lead to more and more problems due to incompatibility with the epic given itemization, fragmentation of the functionality and more side effects of that decision later on.

If we compare with Creative 1.0 Devices, we have not received entities/components with the hardcoded devices functionality, as epic plans to deprecate the current actor devices over time and port the functionality to their own core engine components in the future so we can make it from scratch (While epic also can provide templates and examples of devices if wanted). Why they have done it differently with items, in a even more intrusive way?
They also removed the bridge_component which was available before (A component that allowed us to attach blueprint actors as child of scene graph entities), with the exact same excuse that bridging actors and blueprint functionality was not in fit with scene graph design desicions on long term and they did not wanted to push that usage.


The same can be thought about backwards compatibility of items: Instead of making hardcoded api to bridge them, why not doing the inverse? Such as working on new necessary tech/components mentioned to make the core functionality. And, to add support for old blueprint items while not ported to scene graph, we could have other alternatives such as making all fort items classes in verse holding interfaces with the item details on it (such as icon, name, category, durability and so on).

This way we could read the item data from the old system if we want to make it work with new systems made by ourselves, not needing any of the “bridge” related tech on core SG functionality, and only having the exposed items and its data, even being able to be something like /Fortnite.com//Temporary/Itemization to be deprecated on the future if wanted…
This would be fine to epic having the hardcoded functionality related to backwards compatibility to blueprint items, while still providing the flexibility of allowing creators decide how they want to design their items, inventories and which features/usability these can have.
The existing “core tech” of item_component, inventory_component and related utility could have just been a example/template project with the implementation in raw “user written” verse to be reused across projects.


Conclusion: While I understand most of the reasons behind lots of these decisions, I think that the current implementation can cause a chain-reaction as time goes on, due to the core tech being ruled by internal epic-driven functionality instead of relying on non internal implementations (such as only bridging the items itself). The current state has lots of room to improve, limitations to address, and I think that if epic communicated better with what developers expect before deciding the priority or design of some features, it would be much better for the future of the platform.

For example, if someone asked me if I prefered “itemization template module” sg tech, or the unfinished components that I listed above, I would have answered that I prefered the components mentioned, since they were providing more powerful usage cases, and would also cover custom raw implementation of basically all needed custom items (and even weapons) functionality.

I started this talk so we can discuss and talk about the implementation, suggestions and use cases to give feedback to epic.

I know this topic about the design choices is a double edge sword: Some creators want easy-to-use preset APIs/Templates.
While this is good for most people, it would be the opposite and very bad for the experienced or more technical users. And I also think that with different implementations would be possible to make it better for both general and technical creators (such as letting the developer of a team making the easy-use of their own itemization design, community sharing it online as snippets, or even epic making project templates like they did with other feature examples).

So, feel free to anyone who want to discuss about this topic, to give more details or feedback to my texts above, I would love to see what other people may think about what I said and possible new ideas related to the current scene graph itemization in general.

1 Like

We will be able to make our own itemization from scrach in the near future based on some extra components (some of it is even already possible for a while).

BUT, that would add more problems like I mentioned: we would need to do the communication between two different itemization modules (our own and epic provided), migrating data, usability, inventory management, keybinds and so on… This will lead to much more work, prone to more bugs, and at the end would not be needed at all if the Epic implementation were a little different…


I don’t know what exactly would be the best alternative, but when I saw how it was currently done, I thought about something like a fort_item_component, where on that component having all the data related to the items (such as icon, stats, name), even being able to be on interfaces if wanted (has_icon, has_description)… This would allow access to old blueprint items data while they have not been migrated to scene graph yet (functionality rewritten as components and behaviors).

That’s why I said it could even be a Temporary module, if they want to deprecate or update in the future… This way the “bridge” stays only on the old blueprint items, and not on the core scene graph api, and much less on user made implementations and design choices of inventories/items.

For example, if epic wanted to make a itemization module, nothing would prevent them of doing it as a snippet template with the same inventories and items setup, posting on forums or example projects, like they did before… Would be much more flexible, and at the end, still optional (the developer can chosoe if want to follow epic template or make one by its own)


The itemization core module (base item and inventory related stuff) are part of the /UnrealEngine.com/ module, and only some stuff are part of the /Fortnite.com/ module… This means that they planned to use that same itemization on the entire Unreal Engine, and not only in Fortnite to cover these old blueprint item bridges…

In normal UE is not even a much big problem. Since a game developer will make its own game from scracth, nothing would prevent him from ignoring the unreal engine itemization entirely, and making and using his own itemization from scratch… That would not cause problems since his game would not need to even touch the itemization provided by the engine at all if he don’t want.

The same thing does not happen with Fortnite: since they are forcing that module and that specific implementation with existing/old items, we UEFN creators will be always forced to use that module (regardless of we making our own or not). Unless we completely ignore all thousands of existing fortnite items on our projects, there is no much flexibility at all on the current implementation.

This is why I said that the implementation may have been planned a little different, It was also added as a non Temporary module, which means that this is the final/end product design they planned, instead of just a temp workaround while fortnite items are still blueprint based…


The accessibility and prebuild tools are a huge discussion topic (not only about items but anything on the ecossystem). But, for custom items and inventories, like I said, nothing would prevent the same modules they made from being published as templates and snippets instead of hardcoded core functionality, giving freedom to experienced users while also covering default implementations and starting-points for beginners to use.

This is specifically due to most itemization functionality (the already released part) being data-only containers and interactions/functions on the code, (not needing core functionality on the engine part). And even some of the “core” functionality, it is already planned in their own components or future SG designs that is more flexible than the current usage, so the itemization could have been just a /Fortnite.com/Temporary/Itemization/ to bridge old fortnite item data, instead of a full implementation on the engine module level…


Some stuff also seems off, for example, they implemented a failure_reason class but it is submodule of itemization, that is a thing that should be core unreal or even core verse, since it can be used for non item implementations if we want (as the class name implies, it defines a generic failure reason data/container)…

1 Like

If I was tasked to make the api design with backsupport, I would have done some stuff very differently (even if it means waiting a bit more time, specifically for stuff like other components I mentioned that need to be released)

What I would do would be something like:

  • :x: Remove /UnrealEngine.com/Itemization module entirely (Most stuff here would be moved to /Fortnite.com/Temporary/Itemization or written as template code later)

  • :white_check_mark: Add all bridging functionality on Fortnite module, as temporary (if we want to deprecate in the future, ex. when converting item behaviors/functionality to scene graph) (Something like the example attached as file):

  • :white_check_mark: Make Snippets on Epic Forums, or a Project Template with example implementation of custom items and inventories. These snippets/project would have itemization logic written from scratch in verse (since all interactions are data-only on the code, basically making here the base inventory_component and item_component with its other interactions/functionality).
    ­
    If made on a project template, could also give more examples such as reading existing Fortnite items data to display and how to manage it. And in the future this could add examples of managing input actions to open inventory screens, change quickbars, item powerups/cooldowns, in-world interact popups, inventory blueprint widgets with property interface examples and so on… All being much more flexible for customization and adaptability since all would be non-hardcoded modifiable code.

  • :white_check_mark: Rethink lots of the internal (currently unreleased) itemization related components. As explained, lots of things are just data only for bridging, that could be placed on its own fortnite exclusive module instead of core unreal engine module, or even avoid them entirely


On Island Settings, an option “Initial Inventory Configuration”, with being able to select between:

  • “NativeOnly” → Keep existing Creative/UEFN configs (Inv/Quickbar UIs, Input Mappings, Keybinds), with limited functionality (would not be able to handle custom user made items)

  • “Blank” → Completely empty (no Input Keybinds, no Default UIs at all), the user would need to make everything from scratch if wanted. (Most of it is already possible, but some such as input mappings and property interfaces are still unreleased)

  • “Custom” → A configuration where you can map your custom itemization module data to existing native fortnite UIs, could also expose some data driven config for inventory UI with view models and keybinds, but the core functionality being already implemented. (Part of this is already done by the Inventory Configuration Asset, just is not fully exposed to us)

Notes:

  • Currently, if we left the Inventory Configuration ‘blank’ on slot settings (no asset set at all), it acts as the “NativeOnly” mentioned above (Native Inv Widgets, sg custom items don’t work/show up, native UIs are shown, only old fort items work).
  • If we set it to the “Empty Preset” asset, player will not have any inventories, but still has the input mappings to navigate quickbar and open inv (Itemization Inv Widgets, no default inventory, both fortnite old items and scene graph custom items work after adding inventories ourselves).
  • If we set to the “BRStyle” Preset, is the same as Empty preset, but with default inventories already applied (we don’t need to apply manually)

This is an example of what I was thinking about scoping the “bridge” functionality to the fortnite module only:

# Fortnite.digest.verse
Temporary<public> := module:
    Itemization<public> := module:
        fort_item_component<native><public> := class<epic_internal><final_super>(component):
        
        fort_item_details_component<native><public> := class<epic_internal><final_super>(component, has_description):
        fort_item_icon_component<native><public> := class<final_super>(component, has_icon):
        ... # Other Fort Item Data Bridge Components so we can read the values if we want
    
        FortniteItemCategories<public> := module:
            fort_item_category<native><public> := class<castable><concrete><unique><final>:

            WorldItem<public>:fort_item_category
            Ammo<public>:fort_item_category
            Trap<public>:fort_item_category
            ... # Other hardcoded categories
        
        AbsoluteDoomItems<public> := module:
            fort_item_chainsaw<public> := class<final>(entity):
            fort_item_modular_sovereign_shotgun_legendary<public> := class<final>(entity):
            ... # Other Items from this season
        ... # Other Modules With Other Seasons Items


    NativeInventory<public> := module:
        fort_inventory_component<native><public> := class<epic_internal><final_super>(component):
            # Adds items to the inventory. Fails if items don't have `fort_item_component`.
            AddItem<native><final><public>(Item:entity, ?AllowMergeItems:logic = external {}, ?AllowPartialItemMove:logic = external {})<transacts><decides>:void
            ... # Rest of Native Inventory API (Find, Get Items, Rules and so on...)

        fort_inventory_weapon_hotbar_component<native><public> := class<epic_internal><final_super>(fort_inventory_component):
        fort_inventory_trap_component<native><public> := class<epic_internal><final_super>(fort_inventory_component):
        ... # Other Hardcoded Inventories

        ... # Rest of Native Inventory API (Classes, Events, so on...)
1 Like

This is one example of the side effects due to bridging blueprint items under the hood:

1 Like

When item entities gets “picked up”, they get removed from world (level_entity that is on round_lifetime_simulation_entity), and added to inventory_root_entity (that is on game_lifetime_simulation_entity)

This leads to weird behaviors that we can’t control, such as:

  • The entities cycle their lifecycles (of all components) even if we don’t want that happening (Stop and Start simulation again)
  • Item.GetSimulationEntity[] returns different simulation entities while on world or inventory (round and game sim entities)
  • Wacky interactions related to the attachment changes
  • Modifies the scene tree without giving us a way to control or even customize it
  • Expose access to the game_lifetime_simulation_entity, that I believe is not intendeed at all (we have filters on the engine to prevent getting it from the normal level_entity and round_lifetime_simulation_entity, but seems that this filter does not exist or are not working with inventory_root entity since it is already outside the round lifetime entity)

This is some parts of the scene tree from my testing project:


Note how the inventory root is structured on a running game (I was alone in the session, but I believe when other players joins, other inventory roots get generated)

Also, we need to rely on lots of undocummented behavior, basically needing to do “reverse engineering” to know how the implementation works in details, both to understand its concepts, to use it properly, or even just avoid possible bugs related to the design and/or usage…

This is the type of things that should be documented, even if not finished or subject to change, so creators don’t get lost while using the experimental features (and consequently leading to wrong bug reports, invalid feedbacks, or even just difficulting usage and learning). Don’t need to be in deep details, just simple notes are already enough, such as “item entities also simulate while inside inventories”, “they get removed from world but they don’t get removed from the scene”

(extra note: I may have explained wrong the functionality of screen_space_ui_display_component on my first post, sorry! The functionality of it is a bit different from what I said. But there is other ui related components internally with different purposes)

1 Like

I made the following test setup:

These are the results of the 3 tests made:


It leaded to inconsistent behaviors (outside and inside the scene), data loss when splitting stacks, wrong descriptions on the digest, and lack of flexibility or customization.

Due to this, would not be better to let us create the new stack instances and data ourselves, like we already always need to do? mesh_components, materials, entities itself and any other class, we always needed to create new instances of it ourselves, then copying the data manually field by field. The ItemComponent.Take[] seems redundant related to that


All this, chained with more non documented scene tree implementation details, is only accumulating more and more questions over time, at the point of us verse devs spending more time trying to undestand how it works than actually developing systems and new content…

1 Like

Hiya Sprintermax

That is a comprehensive thread! Perhaps we can chat more about the specifics later, but first I can hopefully provide some high-level context.

The purpose of the Custom Items and Inventories feature (the Itemization module) is to provide a foundation for items and inventories inside any Verse platform, not just Fortnite. It does that by defining a new set of components, such as inventory components and the various item components. These are foundational parts we are building underneath Fortnite, not bridges across to it.

Many existing systems have been updated to use these components, and even existing items provide access via them. The important part is that we are now building on those new components, not the old.

Over time, the functionality in the new components will supplant the current system. This cannot be done just in the Fortnite parts of the code, as we don’t want to limit these features solely to Fortnite.

We are still developing and testing components beyond those publicly available, with an aim to provide all the pieces need to easily make a typical item. It’s also important to us to provide enough power in the API so that anyone could write similar components, without requiring special Epic powers. We know we’re not there yet in the first experimental release. Also bear in mind that some of the things you have seen in the digest might not ever be made public.

The aim of the experimental features program is to give better visibility to the direction of our APIs to you sooner. We are really grateful for the feedback on the early view of this. :slight_smile:

Lastly, additional documentation and examples should begin to appear over the next few days. We completely understand the value of these!

5 Likes

Just wanted to post to echo Alex’s thoughts and say thanks! Really appreciate the detailed feedback as we continue to develop Itemization!

2 Likes

I think that one of the most frustrastions (not only from me) are related to no technical details about the implementations, plus the lack of control of some hardcoded behavior.


The technical implementation details were already explained a little above, and I’m glad to know that it will be aimed to be improved in the future! Some details that I think is very important are:

  • How is the relationship between items in world and items in inventory? According to my tests, the items in inventory is still on scene, they still simulate, but are not rendered and/or not replicated on the world (as I saw, looks like it lives outside level/round simulation “scope”). Can we know why that was the goal behind? Will us be able to control it in the future? This caused lots of questions across many people experimenting with custom items.

  • Every entity reattachment (moving EntityA from ParentA to ParentB) cycles the lifetime of all the moved hierarchy. The digest and docs says that entities only cycle the required lifetime functions “until reaching the matching state of the new parent”, but this is not what we see during usage: According to this, if entities were already matching their state during the reattach, it would not need to cycle at all, which is currently happening.
    This is another example of unclear technical detail, if is intendeed (and diggest comment wrong), or if is an actual bug that we must report. I wonder if we ever will have a way to reattach the hirarchy without recycling all the lifecycles (end sim → start sim again), since this may not be always wanted (ex. hard to keep track of all states and resume after doing it, more prone to bugs and edge cases, and so on)…

  • I know Agent Entities will be coming in v38.00, would love to have more details about it, implementation, replication rules and so on… (Will inventory root be transfered to be child entities of agents for example?)

  • The Scene Tree has lots of internal components and entities, even if we not having access to them, would be cool to understand what is each one for. For example, should I attach my prefabs and world buildings to the ‘level_entity’ or is safe to attach everything directly to round_simulation_entity? And how future-proof these implementation details will be/how they will affect our future projects? When we call .GetSimulationEntity[] from inventories, we get the game_lifetime_simulation_entity instead of the round_lifetime_simulation_entity, which can cause lots of problems and confusion, specially since these are not documented…

  • What are the implementation details of both round and game simulation entities? And level entities? The name gives some hints, such as maybe multi-worlds and so on… But would be great to have that noted down (ex. “only stuff onder level entity is physical, outside it don’t exist on scene but simulate as “virtual” entities”), their lifetime, hardcoded behaviors and specific details of each one… What entities and components are safe to be messed with or not?


Now, about the limitations and side effects of current itemization, there are some more questions:

  • From the tests, MyItem.Take[] makes a copy just of the item_component itself, it does not preserve subclasses, other components, interfaces, data and even the structure. Is this intendeed? (Ex. Should we reconstruct our logic/data from scratch every item “split” we make? I don’t see how much advantage that would be…)

  • Looks like some functionality does not work properly on some cases (.Take only working if entity was already simulated at least once before), it is hard to know if some of these behaviors are intendeed or bugs to make a report about.
    The same applies to other things, such as the new generated entity after taking a copy having extra item components that were not present originally (idk if would be ok to call it “bloated”).

  • One of the biggest drawbacks in verse in general (not only about items), is not being able to freeze objects, make copies as values, or control if we want to pass them as pointers or values. This is absurdly important on OOP, and specially with scene graph entities, prefabs, components and now itemization, doing every copy by hand with non-parametric hardcoded code written for it, while is not fully blocking, it still is a huge wall for many use cases, slowing down development and being a possible source of bugs…

  • Lots of functionalities of custom items are harcdoded and with no customization still, one of the best examples of it is the pickup component, where we can’t configure things like affected by gravity, pickup animation time, hud display, being attached to fortnite round (don’t work outside game mode), hitbox and so on… As I explained on the original texts, I would love to have that functionality as granullar as possible. In my opinion, this is one of the components that could even be completely removed, and having that functionality made in other ways (such as the interactable_component plus other new components instead)

  • There is no preset to completely remove inventory and quickbar if we don’t want them, even if we left the island settings option for the configuration empty, it shows the “non-itemization” ui instead of having everything blank… I would love to have a preset for not having anything at all (not even keybinds for native inventory and no default quickbar). I know that in the future we will probably be able to make our own configuration assets, but this would be a good built-in preset to have…


These are some of the most important details that I could remember. Probably there is lots more that is not comming to my mind right now, but I will try to keep this updated over time, with questions and new suggestions.

Hi @Sprintermax! Another late reply I’m afraid, I need to setup automatic notifications for replies…

  • Vanilla inventory_component will not make any changes to the items it contains, by default. There will be different requirements for changes and components to affect, so we don’t want to impose any limitations there. Fort_inventory_component however, which is intended more as a default BR-like inventory setup, will disable any meshes on items entering it by default (and no other changes). We will be looking at ways to make this behavior easier, either through example code or standard components. We’ll try & make this clear in the docs.
  • Entities and components will uninitialise when they detach from a parent entity (e.g. leaving an inventory) and re-initialise when re-attaching to a new entity. This has caught me out as well :slight_smile: Point taken about the naming and documentation not making this clear.
  • Agents-as-entities is out, and we’ve updated the docs to reflect this! We’ll be building on this in future updates, now we have something to link inventories to.
  • Take is tricky, as there’s no support for arbitrary cloning. What we’re likely to end up with is a virtual function, where a class can provide a ‘new stack’ item. This should be covered in the documentation.
  • If Take doesn’t work before a simulation tick, that is a bug! Any limitations we’ll call out in the comments or docs.
  • Can you ‘freeze’ Verse objects by removing them from the SG but keeping a pointer (to avoid them being GCed)? Outside the Scene Graph they should not be ticked.
  • Pickup component is getting a refresh due to several issues, such as the ones you point out. Watch this space.
  • That’s a really good point. We wanted to allow that option… That sounds like a bug, as setting the “None” inventory config should really have exactly that effect (no HUD).

Thank you for the comments - it’s so useful getting feedback like this.

1 Like

Hey @AlexThomProd, Thanks for the extra details!

Lots of things were much clear with these extra information you gave. Some we already knew by reverse engineering and testing different usages/cases, but is great to have confirmation about these, instead of just speculations without us knowing if is intendeed or a bug that should be reported!

However, there is still some details that I would love to talk about:


  • What you explained about inventory_component/fort_inventory_components and how it will handle items makes much more sense now! So basically fort_invs have hardcoded behavior such as disabling visibility, while our own custom ones does not, right?
    I am ok with that, it makes sense to work this way, I assume on the custom inventories we will probably have a way to listen for new pickups and call disable/enable behaviors to change visibility and other functionality as we may want! But related to the fort inventories, will it be exposed to us so we can disable that if wanted? (or if not, will we be able to completely remove the existing fort inv and replace with our own inv to do that?) Or that logic will be handled on each item individually instead of the inventories?

  • I was already aware that Entities and Components cycle their lifetime methods when reparenting to other entities on the scene, I am ok with that, but I feel like it can be a huge problem when needing to handle states and conditions inside the logic (We needing to listen for removed from scene, store all states, then when adding to scene reading these states if existed and continuing where left), this can cause lots of user errors and adds absurdly extra complexity on lots of setups. I already saw many members of the community getting confused due to this behavior and not handling it correctly…
    On lots of cases, recycling the lifetime methods can be useful and intendeed for some behaviors, but would be awesome to have alternatives that does not do that, for example:
    – Imagine a NewParent.AddEntities(ChildEntity) → This cycles all lifetime methods (stop simulation, remove from scene, added to scene, start simulation again)
    – Then also having something like NewParent.AddEntities(ChildEntity, ?Resimulate := false) → This would just change the Hierarchy/Tree Organization of the scene so the child is attached to the new parent, but WITHOUT cycling the lifetime methods (unless it is needed to match the parent lifecycle one). This would not change world-position (just local position to match it), also not changing origin (if has one set), and so on… This would be awesome to define and organize the parent/child relationships during runtime without affecting the simulation of things already on the scene…
    One example case would be like a factory with conveyor belts, where objects moving between conveyers gets reatached to the current belt (not origin, just to dehine parent/child relationship). So we can make logic such as “delete/move the parent, all childs gets deleted too” without needing to deal with extra listeners, state handlings and so on…

  • Agents as Entities are amazing! This was a huge step forward! We also have fort_character_component and pawn entities (that is another entity not the same as the agent one), but I heard this is going to be changed in the future through a redesign, I am curious about how it will be! (Lots of people from the community had confusion understanding the difference between the pawn and the agent, I hope it gets easier to understand with the docs)

  • The functionalities such as Take[] needing to be handled manually to “recreate” new item entities I already knew it was like that, and makes much sense being it! I even helped explaining other devs about on the past, but glad to finally have a confirmation about its behavior and not just speculations. :stuck_out_tongue: We also got some good changes related to it on the recent updates. :slight_smile:
    It not working before being simulated at least once was defenitely a bug then! I have not checked on the recent updates if it was already fixed or not… (It should be fixed since how the functionality also changed to overridable functions entirely)

  • With “freeze” I was meaning related to a mutex that “locks” the object and denies changes to it under certain conditions or until unfrozen (or like in javascript you can object.freeze(MyObject) to return a copied instance where you can’t set its values anymore)…
    But, besides this freezing behavior, I still think that having pointers is ABSURDLY important for optimization and better management in a more advanced way, specially related to memory and execution times. I understand lots of limitations related to not being able to copy classes and some types, but many other types are already passed as value copies instead of pointer references (structs/primitives/arrays/maps are passed as values, classes/interfaces are passed as pointer references).
    I am ok with classes and interfaces always passing as pointers due to this limitation, but for other types that can be copied (and already does that currently), I think we should have the ability to choose between “passing as copy” and “passing as pointer”. Some use cases would be working with massive arrays without duplicating all its values for no reason when passing through function parameters…
    I am not sure how it works exactly but I saw we already have some stuff related to pointers in verse (iirc it is ref and ^ keywords).
    I was thinking about something like (just quick idea about how I imagine it working):
<#>
    `ref t` ->
        If specified, will act as pointer to the reference (both for access and assignment), if not specified, will be the local instance or copy of the value.
            Ex:
                MyValue := ref OriginalValue # Pointer Reference
                MyValue := OriginalValue # Local Copy of the Original Value

    `mutable(t)` ->
        Identifier of a value that can be mutated (defined as `var`). Can be casted to ensure and confirm mutability.
            Ex:
                mutable(string) -> It is `var Something : string`
                ref mutable(string) -> Is a pointer to a `var Something : string`
                mutable(ref string) -> It is `var Something : ref string`
                ref mutable(ref string) -> Is a pointer to a `var Something : ref string`
                mutable[Something] -> Succeeds if `Something` is mutable, fails if not.

    Classes and Interfaces are always passed as pointer references (like already currently happens), regardless of specifying `ref` or not.
        Ex (both acts the same, being references and not copies):
            MyClass := ref MyClassInstance
            MyClass := MyClassIntance
    They can also be mutable or not depending on usage.
        Ex:
            MyClassInstance := my_class{...} # non mutable
            var MyClassA : my_class{...} # mutable
            var MyClassB : MyClassInstance # mutable

# Structs And Classes can hold non-mutable copies, pointer references (mutable or not), or explicit mutable pointer references on their fields
my_struct := struct {
    SomeField : []int # non mutable local copy of the value
    SomeFieldPointer : ref []int # non mutable pointer reference (the reference can or can't be mutable, checked with mutable[SomeFieldPointer])
    SomeFieldMutablePointer : ref mutable([]int) # non mutable pointer reference of a mutable value
}

MyConstantStructInstance := my_struct{...} # Constant, This struct value itself and its fields are not mutable, the references on these fields may or may not be mutable.
var MyMutableStructInstance := my_struct{...} # Variable, This struct value itself and its fields are mutable, the references on these fields may or may not be mutable.

# Same applies for any other types (using arrays here as example)
ArrayOfInts : []int
var VarArrayOfInts : []int

RefOfArrayOfInts : ref []int
var VarRefOfArrayOfInts : ref []int
ArrayOfIntRefs : []ref int
RefOfArrayOfIntRefs : ref []ref int
var VarRefOfArrayOfIntRefs : ref []ref int

# Params passed on this function will always be copies of the input values,
# regardless of the passed value being static (const) or mutable (var)
SomeFunction(Input:[]int):void = {
    set ref Input += array{25, -40, 90} # Err: input value is not a mutable pointer reference

    if (MutableInputRef := mutable[ref Input]) { # Since this is a local copy, `ref Input` points to itself
        # will never succeed, local input is not mutable (static param)
    }

    set Input = array{} # Err: local input is not mutable (static param)

    if (MutableInput := mutable[Input]) {
        # will never succeed, local input is not mutable (static param)
    }
}

# Params passed to this function will be pointer references (non copies),
# The passed value can be both static (const) or mutable (var)
OtherFunction(Input:ref []int):void = {
    set ref MutableInput += array{25, -40, 90} # error: can't set non mutable value

    if (MutableInputRef := mutable[ref Input]) {
        # will success if the pointer reference value was able to be casted to mutable

        set ref MutableInputRef += array{-25, 742} # works, it is a mutable pointer reference
    } else {
        # will fail if pointer reference value was not mutable
    }

    set Input = array{} # Err: local input is not mutable (static param)

    if (MutableInput := mutable[Input]) {
        # will never succeed, local input is not mutable (static param)
    }
}

##########

### Pass as new copied values, always read only (how already works)
SomeFunction(ArrayOfInts) # works, function will take a copy of the value as non mutable
SomeFunction(VarArrayOfInts) # works, function will take a copy of the value as non mutable

OtherFunction(ArrayOfInts) # works, function will take a reference pointer to the constant. Will fail when trying to cast to mutable[]
OtherFunction(VarArrayOfInts) # works, function will take a reference pointer to the variable. Will succeed when trying to cast to `mutable[]`



########## OTHER EXAMPLE USAGES ##########



# Params passed to this function will be pointer references (non copies).
# It requires the passed value to also be mutable (var)
AnotherFunctionA(Input:ref mutable([]int)):void = {
    set ref MutableInput += array{25, -40, 90} # works, it is a mutable pointer reference

    set Input = array{} # Err: local param is not mutable (static param)

    if (MutableInput := mutable[Input]) {
        # will never succeed, local input is not mutable (static param)
    }
}

# Params passed on this function will always be copies of the input values,
# regardless of the passed value being static (const) or mutable (var)
# The local param itself is mutable, so it can be reassigned to a new value
AnotherFunctionB(var Input:[]int):void = {
    set ref Input += array{25, -40, 90} # Err: input value is not a mutable pointer reference

    if (MutableInputRef := mutable[ref Input]) {
        # will never succeed, input is not a pointer reference
    }

    set Input = array{} # works, local param is mutable (dynamic param)

    if (MutableInput := mutable[Input]) {
        # will always succeed, local input is already mutable (static param)

        set Input = array{} # works, local param is mutable (dynamic param)
    }
}

# Params passed to this function will be pointer references (non copies).
# It requires the passed value to also be mutable (var)
# The local param itself is mutable, so it can be reassigned to a new value
AnotherFunctionC(var Input:ref mutable([]int)):void = {
    set ref MutableInput += array{25, -40, 90} # works, it is a mutable pointer reference

    ConstantCopiedValue := Input # makes a copy of the value at the pointer (will be of type `[]int`)
    OriginalReference := ref Input # makes a copy of the local reference (will be of type `ref mutable([]int)`)
    var MutableCopiedValue := ref Input # makes a copy of the value at the pointer (will be of type `mutable(ref mutable([]int))`)

    set Input = array{} # works, local param is mutable (dynamic param)

    if (MutableInput := mutable[Input]) {
        # will always succeed, local input is already mutable (static param)

        set Input = array{} # works, local param is mutable (dynamic param)
    }

    <#> At this point on this function example we now have:
        - Input -> the local mutable function param (It was set/overriden on this example, now is a completely new local value, its ref now points to itself)
        - ConstantCopiedValue -> a copy of the value at the original pointer reference (the one before Input was set/overriden)
        - OriginalReference -> a copy of the old pointer reference (the one before Input was set/overriden), still pointing to the original reference that was passed as function param
        - MutableCopiedValue -> a mutable copy of the value at the original pointer reference (the one before Input was set/overriden)
}

  • I love to hear about the pickup_component rework! It was one of the biggest points that most people felt unflexible on the current implementation.
    Just for some additional feedback, this is how I expect it to work:
    — No vanilla “pickup_component” anymore, for that, we make our own from scratch (combination of interactable component + widget override/in world widget display). We handle the logic, attaching to inventories, enabling/disabling, states and so on all on our own logic from scrath as we may want.
    — Existing fortnite items having a “fort_pickup_component” that is child of “interactable_component”. This is necessary to exist to brigde the existing fortnite items pickup behavior. Internally it would do the same as our own custom one (managing interactible rules, adding/removing the world anchored widget and so on), but with the hardcoded behavior already done for the fortnite items compatibility.
    — If we want, we could remove the fort_pickup_component from fortnite items, and adding our own instead to replace the native functionality with our own logic not being limited by the fortnite one.
    Some pseudo code would be:
my_custom_item_entity := class(entity) {
    Components := array{
        item_component{...} # main item definition component, with rules, handling and so on...
        interactable_component{...} # if no "world_anchored_widget_component" exists, show default builtin interaction prompt, if it exists, uses its widget instead (if the widget comp is disabled, show nothing at all but is still interactable)
        world_anchored_widget_component{ # renders a widget in world space. Can be disabled/enabled if wanted to show/hide and so on
            Widget := WBP_MyWidget{} # we use our own widget visuals for the interaction popup, with we managing everything such as keybinds it will show, colors, layout, progress bars and so on... We can store this widget reference somewhere else to give data driven updates and changes to it
        }
    }
}

some_fortnite_item_entity := class(entity) {
    Components := array{
        item_component{...}
        fort_pickup_component{...} # child class of interactable_component, with the hardcoded logic for pickup behavior related to existing fortnite items. We can remove it and add our own custom interactable from scratch if we want...
        world_anchored_widget_component{...} # this by default would hold the native pickup widget, but we can also change to a new widget if wanted
    }
}

The only drawback that I think about this, is the fortnite existing items maybe not working properly with Take[] and so on, due to how it would construct new instancies on splitting stacks… This can be fixed iff we override the item component with custom rules from scratch, but I still think it is better than having a “bridge fort_pickup_component” with all logic (interaction + widget) hardcoded inside it instead of the more granullar “from-scratch” approach of my example…


  • I can’t wait for the “No Preconfigured Itemization Inventories” option on island settings! I really want to start from absolutely scratch with no prebuilt UIs/rules/keybinds and so on!
    (I know that this would take a little more time due to we needing more access to Input Actions and so on, but I really like that this is a planned thing!)

////
Unrelated to itemization, but since we mentioned about island settings, any plans to deprecate IslandSettings in the future? imo it is bloated with lots of options and configurations that we don’t want or need, and since it “adds everything to the island” without granularity, we need to manually disable/configure each aspect of it all the time…
I know this may be really long plan because of how integrated the environment currently is with fortnite systems, but I would love to have some different setups from “starting a project from scratch”, such as for example:

  • Instead of Island Settings Actor, we being able to launch session without noting set at all (no health, no teams, no default huds, no round configuration/timers, maybe even without player pawns, just scratch “simulation running” like in normal UE…)
  • We being able to add features one by one, only (and just only) if we really need/want them. This could be in some ways such as through scene graph components being registed to the world itself (think of “fort_team_definition_component”, “fort_round_manager_component”, “default_player_pawn_type_component” and so on), or even without scene graph like on normal UE, we having a “GameMode Definition File” that we attach to the world asset itself, and inside it we configure default pawn class, simulation rules, logic entrypoint and so on…
  • Additionally, lots of things that is setup on the island settings, should not be Island Settings at all (most related to HUD, Teams, Classes, Health and so on). I think that these should need to be broken up into individual components, and attached individually to each player/agent only if wanted instead of being globally (then if wanted, a global player pawn manager component that handles the setup stuff on player join)…
  • Sure, this will be more for highly advanced users, I see it as a template “Start From Scratch” when creating a world or island/project, like is on normal UE, then for other users that prefers to continue with the existing system for ease of use (can also be backwards compatible), having a “Fortnite Base Gameplay” template world with the basic fortnite functionality already set up (pawn config, health, huds, rounds and so on)

I know that I maybe have switched topics to outside itemization on this last part, but I am really curious about the future and its possibilities on the ecossystem xD
Can’t wait to see how it will end up!

1 Like