This is my checklist for making a drag and drop inventoryItem that can interact with other inventoryItems or the world. Im looking for you experienced guys to tell me if im thinking correctly since im not very familiar with Unity OR 3D.
List inventoryitems holds the inventory. InventoryItems is a base class from which Wood and Gold is derived.
OnGui all inventoryItems are drawn up as buttons.
When a button is clicked i flag the InventoryItem as dragged and draw its texture wherever the mouse pointer is. The inventoryItem would contain a Texture2D and i would use GUI.DrawTexture() to draw it and Event.mousePosition for its location.
When the drag flag is up the next mouse click will look for a gui object that is clicked to look for another inventory item that the current dragged item will be matched with. (I dont know how to do this, id need some form of method that returns whatever is intersecting the mouse).
Id also need a way for the dragged inventoryItem to be released in the 3d world and matched with a object there. Camera.ScreenToWorldPoint to determine where in 3d space the click lands, but how do i determine what object is hit by the mouse click?
My 2 cents (I’ve done this a couple of times before, but the needs vary from one game to another…)
- Have a base class that any item in the inventory inherits from (or an interface, though usually a class will work better since it can contain base functionality too).
- OnGUI() in unity is not the easiest or best part of Unity. Thats why Unity announced a new GUI in one of the next releases. I suggest not using OnGUI(), instead you can use Unity’s new 2D sprites. What I do, is create a new layer for GUI items, create a separate camera that displays only GUI items, and then use Sprite objects to build the interface I want. Then each inventory item can have a sprite in it that depicts it’s appearance in the inventory.
- If you have stackable items (it sounds like you do with wood & gold), then better to use a
InventoryItemStack class that contains a reference to the item, and the amount available. Then you can use a list (or better - array if the size of the inventory is preset) of item stacks to depict the contents of each slot in your inventory.
- Separate the inventory item class which depicts the item itself, its name, sprite, and different aspects of the behavior, from the MonoBehaviour class that will be used to display the item in the inventory. That way, you can use a different MonoBehaviour for your inventory than how the item appears in the world view, but the item itself has a single class. The sprite of the monobehaviour can be taken from the inventory item that it references.
- Drag & Drop functionality goes to the MonoBehaviour class of course. You can use the monobehaviour events OnMouseDown, OnMouseDrag and OnMouseUp. In OnMouseDrag you can move the object’s location to the mouse position, and in OnMouseUp place it in it’s new position. Not much to it. Don’t forget to add a collider to any object that has one of the OnMouse events for it to work.
- In OnMouseUp, when you put it in it’s new location, you can check if it’s already occupied and do whatever interaction you require depending on the current contents of that slot. You could create an abstract method
void InteractWith(InentoryItem other), and in each item class you would define what happens when two specific items interact with each other. Call this method when you try to drop one item in a cell occupied by another.
- OnMouseUp will only be called only on the closest object if I’m not mistaken, in your case probably the dragged object. So you will have to manually check when releasing the object if there is any other object there. Use Camera.ScreenPointToRay using the mouse position to create a ray pointing from your camera to the mouse position, and then use RayCastAll() to find all the objects in the ray, which will include any item in the world (it will not include the inventory object if you use a 2d collider. That will require Physics2d class).
Hope this helps. It’s not easy to create your own inventory system for the first time, but start there, and ask questions as you go along (ask separate specific questions to get the best help, not one big thread).