1
\$\begingroup\$

Disclaimer: Somewhat long-winded question & new to developing

In my game I have a class called Item which defines what an item is. It contains several fields like the name of the item, the sprite of the item, the item's ID number, etc. I also have little physical objects on the ground that "represent" items, but they aren't really tied to the Item class in the way I want. I'll get back to this point.

So, when an enemy dies in my game, SpawnItem(Item item) is called. Depending on a randomly generated number, SpawnItem(ItemData.sword) might be called or SpawnItem(ItemData.axe) and so forth. SpawnItem itself just instantiates a generic prefab (that little physical object on the ground), modifies some state like bool itemDropped and int numItemsDropped, makes some calculations to determine where to drop the item, and displays that item's name in a UI label above the item.

I'm currently in the process of making an inventory system, and I've realized something. Those physical objects on the ground that are supposed to be items don't really know that they're items (in the sense defined by the class). A sword doesn't know it's a sword, and an axe doesn't know it's an axe (the game object sword doesn't know that it's a sword Item defined by the class) So when I pick up an item, I can probably do some code gymnastics to get the appropriate sprite to appear in the inventory, but that doesn't seem like a smart solution.

So, my question is how do I get my sword game object (just a sphere on the ground representing a dropped item) to be linked to the sword Item? How do I get the sphere to know that it represents a sword with the ID number "1", the name "Sword", a weight of "1.5" etc. so that I don't have to do awkward code gymnastics? After all, when I'm adding an item to my inventory, I don't really think of it as JUST drawing that item's sprite in the first non-empty slot of the inventory. I would think it's much better to get each game object to know what Item it represents than to just try and get that sprite to show up in the inventory.

I might be overlooking something basic, but understand that I'm pretty new to Unity. Anyway, thanks for the time and help!

\$\endgroup\$
  • \$\begingroup\$ You're basically making Minecraft here. So do what Minecraft does: EntityItems (items on the ground) are a separate class from ItemStack (which is what items in the inventory are). EntityItems contain an ItemStack. \$\endgroup\$ – Draco18s Jun 26 '17 at 13:47
2
\$\begingroup\$

Create two prefabs, one for items laying on the floor and one for items in the user's inventory.

Program a MonoBehaviour FloorItem which has a reference to an instance of your class Item.

Add it to the floor item prefab. Whenever you Instantiate the floor item prefab, set the appropriate Item on it. The FloorItem class then sets up the other components on that prefab (like the Renderer and spatial UI.Text) using the information from the Item (name, model, etc.).

When the player picks up a FloorItem, get the Item from it and then Destroy the floor item game object. Then Instantiate the inventory item prefab. This prefab will be an UI object. Put it into the object hierarchy of the inventory UI. Program a MonoBehaviour InventoryItem for that prefab. This component also needs a reference to an Item object. Just as the floor item, it uses that reference to get information about the item it represents and uses it to set up all the visual components on the game object.

Your class FloorItem / InventoryItem class would look something like this:

public class FloorItem: MonoBehaviour {
     public Item item;

     void Start() {
          GetComponent<MeshRenderer>().mesh = item.mesh;                  
          GetComponentInChildren<UI.Text>().text = item.name;
          // ... and other components...
     }
     // ...code to handle interactions during gameplay...
}

The code to instantiate them would look something like this:

 newFloorItem = Instantiate(floorItemPrefab, position, rotation);
 newFloorItem.GetComponent<FloorItem>.item = ItemData.sword;

By the way, if you have your class Item inherit from ScriptableObject, you can handle item types as assets inside Unity and edit their properties with the Unity inspector. This can be quite handy. How to use scriptable objects exactly would be beyond the scope of this question. But we have plenty of questions about this.

\$\endgroup\$
  • \$\begingroup\$ If it's not too much to ask, could you give me a code example of what that reference would look like? You're saying that my game object prefab should reference public class Item? How will it know it's a sword and not some other item? \$\endgroup\$ – embracethefuture Jun 26 '17 at 6:54
  • 1
    \$\begingroup\$ @embracethefuture I added some code examples to the answer. \$\endgroup\$ – Philipp Jun 26 '17 at 7:08
  • \$\begingroup\$ Since you've been so helpful, I'll ask one followup question. I currently have an ItemDrops script attached to enemies and they called SpawnItem when they die before being destroyed. Would you suggest I create a separate MonoBehaviour FloorItem or can I just work these ideas into the ItemDrops script? \$\endgroup\$ – embracethefuture Jun 26 '17 at 7:32
  • \$\begingroup\$ @embracethefuture If you would like to ask a new question, please do so by clicking on "Ask Question" \$\endgroup\$ – Philipp Jun 26 '17 at 7:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.