Search Unity

Feedback Inventory inheritance

Discussion in 'Game Foundation' started by jrmobley, Jul 16, 2020.

  1. jrmobley

    jrmobley

    Joined:
    Feb 16, 2013
    Posts:
    8
    Hello,

    I've been using GameFoundation for a few weeks now. I started with currencies and transactions and I found that to work pretty well. I'm working with version preview.2 - 0.6.0 now. I just started looking into how to use the inventory system for my inventory objects, and I'm not finding the data model for InventoryItemDefinition to be a very good fit.

    Basically, I need inheritance. As I see it, an InventoryItemDefinition is effectively a class, and an InventoryItem is an instance of a class. To use the RPG scenario as an example, you might put a mutable property "durability" on a Sword definition. But really you will have many sword definitions for different kinds of swords and they *all* need a durability property. And so do your other weapons, and your armor, etc.

    With even a moderate number of item definitions with a moderate number of common properties, maintaining the inventory catalog without an inheritance mechanism is error prone and tedious.

    Is anything of this sort on your roadmap?

    -JR

    p.s. While thinking of InventoryItemDefinitions this way, as classes with inheritance, and when thinking about your plans for code generation, I wonder if maybe it shouldn't be the other way around? What would it look like if we wrote C# classes for our InventoryItemDefinitions, and GameFoundation used introspection to work with them?
     
    saskenergy likes this.
  2. mingz-unity

    mingz-unity

    Unity Technologies

    Joined:
    Oct 12, 2017
    Posts:
    63
    Hi @jrmobley thanks for reaching out.

    We're looking into a few ways to make things easier for item definitions that share a similar schema, like the scenario you described. The 'inheritance' concept you're suggesting could apply to an editor-based workflow or at native C# level, so I need to understand how you plan to use Game Foundation to work with your inventory items and what makes most sense.

    I want to go through two options we're exploring and get your thoughts:

    1) Editor-based workflow: we can provide a way for you to define 'blueprints' of item definitions which will include both static and mutable properties, and then when you define items of a specific item type (or the 'item class' as you are referring to), you can start from that 'blueprint' instead.

    Here's a quick video to illustrate what it looks like using your Sword property scenario:



    2) Inheriting / extending on the C# classes related to item classes: in the editor-based option above, you're still using the InventoryItemDefinition for all these items you created, and the concept of a Sword only exists in the Game Foundation editor sandbox, while we allow you to reuse the schema when definition variations of an existing item type.

    Since you also mentioned writing your own c# classes for item definition, if you're looking into bringing your own custom Sword class into Game Foundation for storing as inventory item, that will involve a more flexible inventory API. For that, we do need to understand a bit more how you plan to implement those custom item classes, and how you want Game Foundation to manage those inside the inventory system?

    The inheritance solution you suggested may not work well in all cases, as some developers want to use raw C# class, scriptable object, or any other type of base class instead for their item classes, and forcing everything to be based on InventoryItemDefinition could be problematic.

    Like you suggested, we can wrap around your custom class and convert a definition based on C# reflection to extract the properties / fields you defined in your own custom item classes, if you do need to rely on your custom item type classes. In this case, the inventory system do need to know a bit more what custom class you plan to use, so instead of using the existing API, you will have to do things like InventorySystem<YourCustomItemTypeClass>. The runtime class being created will still be of an InventoryItem derived instance, i.e. InventoryItem<YourCustomItemTypeClass>, so the main benefit in this case would be to reuse the C# custom types you already defined. Would this be what you're looking for?

    For the code-generation you mentioned, it actually works the other way around, i.e. providing a C# strongly typed reference to the concepts you define in the sandboxed Game Foundation item catalog system, so it works best when you start your development defining your item concepts inside Game Foundation, and then use the code-generated c# reference in your custom gameplay, instead of defining your c# custom classes first and try to bring that to GF (which is what we try to look at here). Let us know which scenario is closer to what you try to achieve.

    In either case, if you still want to use Game Foundation to define and manage more item definitions under that custom item type from your custom class, you can then use the editor-based workflow (see above) for that.

    Let us know your thoughts on this. Thanks
     
    saskenergy and erika_d like this.
  3. jrmobley

    jrmobley

    Joined:
    Feb 16, 2013
    Posts:
    8
    Thank you for the very thorough reply and the workflow mockup video!

    I'll start with some questions about Archetype tab in the workflow video. It looked to me like each Archetype can in turn have its own Archetype, so that a deep heirarchy of (arche)types can be created. Is that correct? In the video, the Archetype editor shows Tags, Static Properties, and Detail Definitions, but you mentioned static and mutable properties for 'blueprints'. Can I assume that Archetypes and blueprints are the same thing? And can I assume that the Archetype editor would eventually also have a Mutable Properties section?

    If 'yes' to all of the above, then I would say that is pretty much what I was wanting.

    Speaking of which, I'll try to describe my actual inventory item needs. I'm not making an RPG at all, it just seemed like the standard example for Game Foundation so far. ;)

    My inventory items are stamp cards (like you might might get at a sandwich shop to count up your sandwich purchases toward getting a free sandwich). Here is an abridged version of the classes in my non-GF implementation:

    Code (CSharp):
    1. // Conditions define what user actions are required to earn stamps.
    2. // There are several subclasses of Condition.  Conditions define type and
    3. // contain parameters, and are responsible for creating StampCard instances.
    4. public abstract class Condition : ScriptableObject {
    5.     public abstract StampCard CreateCard(StampCardTemplate template);
    6. }
    7.  
    8. // Award is a reference to a Game Foundation item.
    9. [Serializable]
    10. public struct Award {
    11.     public enum Type { Currency, Inventory }
    12.     public Type type;
    13.     public string id; // ID of Game Foundation item to award.
    14. }
    15.  
    16. // Each Stamp object defines how many times the user must satisfy the Condition
    17. // in order to earn the stamp, and how many units of the Award they get for earning
    18. // the stamp.
    19. [Serializable]
    20. public struct Stamp {
    21.     public int eventCount;
    22.     public int awardQuant;
    23. }
    24.  
    25. // StampCardTemplate simply aggregates a Condition, an Award, and a list of Stamps.
    26. // There are no subclasses of StampCardTemplate.
    27. public class StampCardTemplate : ScriptableObject {
    28.     public Condition condition;
    29.     public Award award;
    30.     public Stamp[] stamps;
    31. }
    32.  
    33. public class CardTemplateCatalog : ScriptableObject {
    34.     public StampCardTemplate[] dailyCards;
    35.     public StampCardTemplate[] careerCards;
    36. }
    37.  
    38. // StampCard keeps track of the number of times the Condition has been satisfied
    39. // and the number of Awards the player has claimed.
    40. // There is one subclass of StampCard corresponding to each subclass of Condition.
    41. // The StampCard subclasses implement the actual logic of testing Conditions.
    42. // StampCards are serialized into the saved game state.
    43. public abstract class StampCard : Object {
    44.     [SerializeField] RallyAward _award;
    45.     [SerializeField] RallyStamp[] _stamps;
    46.     [SerializeField] int _eventCount;
    47.     [SerializeField] int _claimCount;
    48. }
    49.  
    For a GM implementation (assuming the Archetype feature is available), some of the conversion looks pretty obvious to me:
    • Create a StampCard Archetype with 'eventCount' and 'claimCount' mutable properties.
    • Create InventoryItemDefinitions in the GF editor instead of creating StampCardTemplate assets.
    • Use 'daily' and 'career' tags to classify my cards into two groups.

    Other steps are less clear to me.

    I think would create various sub-Archetypes to represent StampCards with various Conditions.
    But maybe instead I should somehow reference my Condition assets. Maybe with an Asset Detail Definition? Or maybe with a Static Property string identifier?

    I have several ideas about what to do with Award and Stamp. Together they represent something like a GF Transaction. Maybe I could use transactions, but how could I add a list of transactions to an inventory item definition? If I didn't use transactions, could I have a property type that referenced another catalog item for my awards? Could I have array or list properties? Or I could stuff it all into JSON Detail Definitions. That seems error prone, and I would have a bunch of parsing and validation to do at runtime to transform that JSON into useable objects.

    There is another aspect of my system that is not apparent from the classes above. When I create a StampCard from a StampCardTemplate, some properties values are chosen randomly, and not in a simple way. I think I would just handle that myself after the inventory item had been created. It's a little weird, because I would have to use a mutable property to hold my randomized value, even though it should never change after initialization. But it is definitely not a static property in the GF sense. Meaning it is not shared by all instances created from the definition. Its more like a C# readonly property. Maybe something like an initialization callback could be passed to InventoryManager.CreateItem?


    Regarding my p.s. and a C# class workflow, I haven't thought about it carefully at all. I just had a weird feeling like I was using the GF UI to define something that was very much like a C# class (with properties, static properties, object references, etc), and GF would generate the code for an actual C# class from that schema... and I thought, what if you skipped all that and just used C# classes to start with? I think I understand most of what you wrote about the complexity of that approach. For sure I can see that we (game devs) would have to write our item definition classes within very strict constraints. I'm sorry I don't have much helpful to say about it. I probably should not have brought it up.

    Thank you!
    -JR
     
    erika_d likes this.
  4. mingz-unity

    mingz-unity

    Unity Technologies

    Joined:
    Oct 12, 2017
    Posts:
    63
    Hi @jrmobley - Thanks for the reply.

    Yes deep heirachy of any level is supported, and indeed archetype / blueprint is the same thing here for supporting schema-based editor workflow. Also a yes that it should eventually have a mutable properties section as part of the schema definition (but keep in mind that mutable property is only relevant for Inventory right now while Archetype can be used in all systems).

    And thanks for sharing your specific example. Some quick comments from looking at your current schema that hopefully can be helpful:

    StampCardTemplate seems to be the 'static' aspect of your stamp card system, i.e. what your catalog of stamp card ultimately is based on, while each instantiated version of that class I assume would be a variation of that, for specifying the conditions and how much reward you give out etc.

    While you also have StampCard class which is the 'runtime' aspect of your stamp card.

    For the purpose of schema-based definition, you can probably think of including both classes into an inventory item definition. Your starting point could be to create the static properties and mutable properties (i.e. from both of your existing classes) as Archetype, and then create specific variations as actual item definition instances under Inventory Item. Game Foundation editor tools essentially become your item catalog editor. Then at runtime, as you create each card, you can track the status of awards being collected for each stamp card. And if you want to have your own custom card creation logic, you can retrieve the new inventory item being created and use the set properties methods to modify it however you want.

    Hope this helps explain the second part of your answer (the less clear part) better now. And let me know if you have more questions on this.
     
    erika_d likes this.
  5. jrmobley

    jrmobley

    Joined:
    Feb 16, 2013
    Posts:
    8
    Hi @mingz-unity.

    Your description matches my understanding of how I will be able to use the inventory system. That's great!

    I also finally noticed the following point in the 0.6.0-preview.2 release notes:
    That is also great! I'm looking forward to it.

    -JR
     
    mingz-unity and erika_d like this.
  6. Dunmord

    Dunmord

    Joined:
    Aug 15, 2013
    Posts:
    40
    Hey @mingz-unity,

    I'd like to +1 this feature. Is there an official issue we can +1? I have been going through defining skills and there is no easy way for me to use an archetype for all my skills. I have to manually go and add every duplicated static/mutable property 10s of times.
     
  7. erika_d

    erika_d

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hi @Dunmord,

    Thanks for your interest in the archetype inventory concept! We don't have an official/public issue for it, unfortunately. To be totally honest with you, a full archetype style feature is probably aways off yet, as the video shown was a mockup of what it could look like in the future. However our next release does include the ability to duplicate a created item, including all of its properties, as a step in that direction. While it doesn't go as far as creating a hierarchical relationship between different items, we hope that it will help in the initial creation process with not having to add the same properties to each item over and over again. Instead you can create one inventory item, add all the properties, then duplicate and edit it to create the others.