So right now I am working on an item system, and I have a hard time figuring out in my head how to represent the items.
The item should have three states - On the ground, in inventory, placed in crafting grid(active).
I am only asking about the representation of the item itself.
I have created two very sketch like “UML” diagrams attached.
One of them represent items as a single object with all logic attached to said object. - I fell this will be way too messy.
The other is dividing states out in different objects. - This will provide the problem with multiple classes with the same name and the need to “convert” one object to another in the case of a state change.
Outside of the sketches, I also thought the item with a state enum, but I am not sure how that will differ from option 1.
Also looking into item implementing the states as interfaces. But again, not really sure this solves the problem.
Any help would be much appreciated. Let me know if more information is required to better answer me.
Thanks in advance.
1 Like
I certainly wouldn’t create different subclassses for dropped, held, and on-the-crafting-table items. These seem to me to be just different states/locations, not different kinds of items. Classes (if needed at all) should represent different kinds.
Any time you find yourself frequently converting one object into another object, just because somebody has done something with it (e.g. dropped it), I think that’s a bad code smell and you probably want to reconsider.
I’d start by backing up and asking: how exactly do items differ from one another? If you can represent those differences as data, then great, you just wiped out an entire aspect of your class hierarchy.
And finally, it doesn’t seem that you’ve really embraced component-based architecture here. If you really feel that putting the data & logic for an item held, dropped, or on the table is too messy, then maybe each of these should be a separate component on the same object. You can then just enable/disable these components based on the item state. E.g., when somebody picks up an axe, you disable its DroppedItemBehaviour, and enable its HeldItemBehaviour.
(DroppedItemBehaviour, HeldItemBehaviour, and CraftingItemBehaviour could be interfaces, allowing you to implement different versions of them for different kinds of items if you can’t capture those differences as data.)
Hello Joe.
Thank you very much. This is also why i went and asked for help. I did not want to separate the item class more than necessary.
As I mentioned in my first post, I already thought about doing it’s with interfaces, but I am not quite sure how I would go around doing that.
Do you have any resource future explaining this? I don’t need a whole system, just the idea.
Thanks 
EDIT: I found Unity: Now You're Thinking With Components | Envato Tuts+ which I believe is exactly what I need.
1 Like
That is a good article on the component design, but depsite this line by the author:
Components and interfaces aren’t necessarily exclusive. They often can go hand in hand. Take the author’s example of a health component. Your player might have his own little health script (component) that handles tracking his health and nothing more. Maybe enemies have their health components as well. But each of these scripts can also implement an IHealth interface that might look something like this:
This code would be in its own file and not attached to a GameObject
public interface IHealth
{
void TakeDamage(float amount);
}
You would have both your enemy and Player health component scripts implement this interface. That way you could say have a bullet flying around that does a check like this when it hits something:
void OnTriggerEnter(Collider col) {
IHealth other = col.gameObject.GetComponent<IHealth>();
If (other != null)
{
other.TakeDamage(this.damageFactor);
}
}
This way your bullet doesn’t have to know anything about what it hits. It just checks if what it hits implements IHealth. If it does, it knows for a fact that it can call TakeDamage. It will let the Health Component script of that other object decide what TakeDamage does (Player TakeDamage could do something different from Enemy TakeDamage). So I would still highly suggest looking into interfaces and what they are and how they work. I believe they go hand in hand with components and the ECS (entity component system) of design.
Edit: Just to be clear on what implementing an interface is it would look something like this:
public class PlayerHealthComponent : Monobehaviour, IHealth {
// stuff
public void TakeDamage(float amt)
{
// Take some damage
}
}
3 Likes