Announcement

Collapse
No announcement yet.

Item-Object (for pickups/drops) and best practices

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Item-Object (for pickups/drops) and best practices

    This is about best practices on how to implement a proper item system, with in-world actor representation but at the same time items should be suitable for storage. I've experimented quite a bit with different classes now and how this all works together with replication, but im not satisfied with what i currently have. The things I tried and the according problems are like so:

    1st Attempt: Spawn an Actor in the world, which keeps a custom UObject with Item properties
    Problem: The UObject does not get repliated. Since the actor requires some properties (like what static mesh, what inventory icon, etc.), this becomes an issue. I am fully aware that i could override UObject Properties with C++ to replicate them, which is probably what i will end up doing.

    2nd Attempt: Spawn an Actor in the world, which keeps an ActorComponent (Instead of an UObject) with Item properties
    Problem: I cant easily collect these, like "picking up" an item. If i refer to the ActorComponent inside the Actor for the Item properties, they would disappear if i destroy the original parent Actor. In a way i could bypass this by just removing the physical in-world representation of the Static Mesh Component in the Actor and then just collect an Array of Actors - but thats alot of work and a bit overly compliated.

    I would probably take the 1st attempt with a custom replicated UObject, what are your thoughts on this - are there any better options for this?

    #2
    Hi Tymax,

    I haven't used the methods you outlined but I have found success using class inheritance.

    Basically a parent class has the core functionality for the player to interact with (OnPickup, OnUse, etc.) and whatever common information the items have in a struct (display name, icon texture, child class, etc. ) then the child classes have the more specific functions.

    This way your character and inventory only have to know about the parent item class but you can still have unique functionality in the child classes. The player inventory would just add the struct information to an array and use the array to display the carried items in the inventory widget.

    Replication is also fairly simple to implement since they're all AActors and can be implemented in the parent class rather than all the unique child classes.

    I hope this is helpful!


    Comment


      #3
      I agree with Arlyn.

      To expand just a bit, you can make a structure which contains all the information necessary, including the model to display in the world. Upon interacting (picking up, using, etc) you would simply reference the structure itself for key information regarding the interactions.

      Example:

      Structure with Name, Description, Icon, Model, Child Class, Holding Player, etc. (already mentioned by Arlyn) -- all information you want to hold with this item/object belongs here, so long as it should persist with the object instead of the player.

      To spawn this randomly in the world, simply reference the structure for the model, instantiate an actor (probably a custom actor with a mesh and particles, or whatever you prefer), set the model in the actor to that of the structure, and pass the structure itself into the actor. When someone interacts with it, if it should simply be added to their inventory, that logic exists in the class you defined and you would reference a function for this logic. Handle your inventory logic as normal, but also pass in the structure for this item in the inventory. When a player picks up the item, set the Holding Player variable to the player who just picked it up, and when dropping it, unset the variable. For tooltips, simply reference the structure for the name/description and anything else you put in the structure that you'd like your players to see.

      Then, you also have the power of creating child classes for items that add buffs/debuffs when carrying the item in inventory as well. A function inside of the class can handle this logic, and you can very easily reference the player who is holding the item because you set Holding Player when the item was picked up.

      Basically, the concept is to always have this structure passed wherever this item would be. Whether it's existing in the world as an actor, or in the inventory of a player, you have this structure available. Want ambient sound/particles while the player is holding the item? Great, the structure can store which sound(s) and particle(s) should fire off. Passing the structure in every step of the way will ensure that you always have all the pertinent information necessary to handle all interactions.

      This also makes item pools incredibly easy. You can make a structure which is an array of the item structures (we store this array in a structure so we can reference it anywhere, totally independent of characters, modes, levels, etc.). In this example, it would basically be however you want to structure it. You could have an array of normal items, an array of rare items, epic, legendary, etc. Then have your loot randomization (if you are even doing that) simply reference these arrays. Or, you could make array for certain chests, bosses, etc. The challenge will be consistency across all loot tables, and not having to type in a title/description and all values of the items everywhere that you use it. This is why a lot of games use a master loot table, and then pull from that loot table programmatically. That way, they define an item once, and any changes made to the item will carry over to all areas which reference the item.

      A word of caution, since you mentioned replication. Never rely on the client's version of the structure. Doing so will expose your game to hacks which are incredibly easy to pull off using simple memory manipulation. Always use the server's information, and replicate that back to the client. If the client picks up a basic item, then changes their memory so the item in the inventory is a Legendary Epic Item of Awesomeness, your game shouldn't care and should know exactly what item it truly is. I'm sure you know this, and if so I apologize for any redundancy here. However, I like to include details for any future searchers.

      Comment


        #4
        Thanks for your replies!
        I basically already have what you describe, just that i solved my interactions with a basic actor - and my item infos with an UObject instead of a struct. Dont get me wrong here, Items are only spawned by the server and then replicated to clients, but the thing is that my UObject Items are not in the world (thus no direct replication - same with structs!), which forces me to use components to replicate.

        Comment

        Working...
        X