Resource Based Inventory - Godot 3.2 Intermediate Tutorial
Вставка
- Опубліковано 23 вер 2020
- Thanks for watching my video!
Here is the source code (MIT License): github.com/uheartbeast/invent...
If you are interested in taking a deeper dive into the Godot game engine you can buy my 1-bit Godot Course at this link: www.heartgamedev.com/1-bit-go...
Check out my Patreon: / uheartbeast
Follow me on Twitch for GameDev livestreams: / uheartbeast
Twitter: / uheartbeast
Facebook: / heartgamedev
Thank you all so much for your support! - Навчання та стиль
Here is the source code (MIT License, download the images here): github.com/uheartbeast/inventory-tutorial
I've got some plans for a new Godot series (similar to my GameMaker 2D Hack-n-slash series but not using the Grave resources).
I'm still working through the details for that series but hopefully I can start making videos for it soon!
Here is the link for the fall sale of my Godot course: www.heartgamedev.com/1-bit-godot-course-fall-sale
Have a great weekend!
- Ben
You are the hero we need but don't deserve
Good tutorial, but if your script doesn't need any code exept base class then why you never set proper option when crating new script? You should change "Template" from "Default" to "None" and save yourself deleting all this junk comments + _ready function. With template set to "None" every script has exactly one thing inside: "extend Base_Class_Name".
When are you making another videos of the action rpg?
if you're using Godot 4.0, the code at 23:45 has new syntax. I got the error code invalid argument for "connect()" function and switched the code to the following:
func _ready():
inventory.connect("items_changed", Callable(self, "_on_items_changed"))
update_inventory_display()
which fixed the error :) happy coding everyone!!
Even easier syntax for 4.x: inventory.items_changed.connect( _on_items_changed)
In Godot 4 exporting is done with @export var name : String = ""
@export var texture : Texture
For the get_drag_data function, it seems to work better to use (var item = inventory.items[item_index]) instead of (var item = inventory.remove_item(item_index) because removing it before the drop means that if you move the item off screen, that it will disappear into the void. Testing with print(inventory.items) in drop_data it seems that the swap items already handles moving the data around so there's really no need to remove the item if it never gets to the drop_data function.
19:10 the Vseparation and Hseparation are now in Theme Overrides -> Constants instead of Custom Constants. I'm using Godot 3.4.2
sweeettt! have no need for a inventory but need something to manage custom decks in a card game
Make a card resource and place the cards into an array.
Im already seeing this video being one of the most useful godot tutorial you ever did. Custom Resources are really useful. Nice work!
Not only i learned a good way to use Resources, but also how to make a simple UI inventory! Thanks a bunch!
i'm glad i looked for your tutorial, i literally searched for "godot intermediate" so that i wouldn't get 10 videos of people repeating what is a node to my face and i'm glad i did it, i'm reading the documentation along with your video and you're ready to explain more than the tutorial requires, you're a great content creator
Another great tutorial! I'm incredibly thankful for all the content and tutorials you've put out. I'm sure your content is, and will be, a springboard for many future games and gamedevs.
Cheers to you and your efforts!
Awesome, never tried to actually create an inventory system but Godot's workflow is surprisingly simple and intuitive, thanks for the vid!!
Thanks for the video! Inventory is one of the things I had a hard time imagining how would work.
20 seconds in and i'm already loving it!
Thank you so much for this!
There are a couple Godot tutorials on inventory I've seen, but either they don't fit what I need or they're a bit hard to understand. I really liked the way you used resources here rather than json, the solution is really neat and easy to understand. (Also really easy to expand upon) c:
Would love to see more on inventory systems from you, since you always explain everything so well. Thank you again for another great tutorial.
This video was a great introduction to resources in Godot while implementing a nice inventory system. I feel like it opened a world of possibility for me.
I already added healing potions that restore player's health when right-clicked from the inventory.
This was immensely helpful, thank you
Amazing tutorial, just what i needed!
I hope you realize you have saved me alone hundreds of hours on my life in my game development, not to mention everyone else who watches your videos.
That's not even a finished inventory. Just like he didn't finish the APRG tutorial
@@Yoni123 Well with a few simple additions I have turned it into one. So it works as a base.
@@Yoni123 I'm a little late on this, but the thing you have to realize about tutorials is that they're not always going to be finished, or updated. Considering this is free content, this should be more than enough of a basis to get started. There are plenty of people about there who get stuck for days, weeks, months, maybe even years trying to wrap their head around starting programming systems like this. While others, it can only take moments after looking at the documentation and logic.
Personally, I'd like to take the time at some point and try and dissect this video and its code to boil it down to be more readable and understandable for beginners, and brainlets(such as myself).
I spent more than a month studying ways to make a simple inventory, yours is still better than what I got. I wish I had found this video before, hahaha. now i think i will redo it from scratch.
Just what I was looking for from you! Thanks for the video :)
I recently looked for a similar tutorial again, thank you very much!
your videos are the clearest and easiest to understand godot tutorials i've come across. i know it's probably very basic stuff but i'd love to see a video on how to set animations correctly in 8 way movement and/or setting NPC movement paths
thanks for all the great content ^_^
I'm not even working on a game with an inventory system or even use godot (I use unity) but I still really enjoyed this video. I really like seeing how you organize and structure your code and it's also very calming. Great content man!
Very nice tutorial, didn't know about the import presets for 2d pixel images! makes things much sharper!
This is just what I need just when I need it! SO much easier than ue4! :D
Thank you so much for making this tutorial!
thank you this is really helpful, please make a follow up video about equipping items to a player from inventory i couldn't find any tutorial about that. keep up the good work :)
I never needed such a system, or inventory in general, but now Ill have to start a new project around it.
Well THANKS, Ben! xD
wow, your tutorials are always interesting and useful
Thanks!
Hey Ben! This is such a huge improvement to what I had, thanks for creating this series! Question about your `drop_data` implementation at 36:00 - calling `swap_items` and then `set_item` seems a bit unintuitive, since conceptually 'swap' should handle the movement of both items. It also results in our "items_changed" signal being fired twice in a row. Going to take a stab at refactoring on my end, but curious if you had any thoughts.
Yeah, it is a bit strange. That is a good question. So the swap will swap the item in the target drop slot with the null that is in the slot we picked up our item from. Then we set the drop slot to have the item we are dragging. I guess I did it this way cause it skips a step.
The alternative would be to get the item in the drop slot and set the slot we picked up our item from to be that item. Then set the drop slot to contain the item we are dragging. Hope that makes sense.
@@uheartbeast thanks for the great the tutorial! I adapted your code to fit my use case.
In ran over the same "problem" as @DevDuck and found the following solution: instead of removing the item when calling _get_drag_data( ) I set the item sprite to invisible. Later when dropping the data, I set it to visible again. That way when I call the swap method both items are still on there actual place and I don't to call set_item( ).
I use this because it allows me to also prevent the user from dropping the item outside of the inventory. When the left mouse button is released I just make all invisible items visible again. If I would remove the item from the inventory and the player drops it outside the inventory I would loose the reference.
@@RACOONLPs hey, I did almost the same! I didn't set it to invisible, I set texture to empty slot texture. And then swap_items method restored it all back to normal! Except when dropping outside the inventory, haven't found a good way to handle it yet ):
@@wall_k If I remember it right, I have added a flag "dragged" to the item slot, that controls the visibility or the texture in your case. Whenever the player drags the item in the slot I set it to true and turn the item invisible. Then I check for a mousebutton released event. If the mouse button is released and dragged is true I set it to false an make it visible. Provided you swapped it with another slot the correct item (or none if only moved to an empty slot) should be visible. But if you draggeg it on an invalid space its still in the slot but invisible and you just have to set dragged to false and visible to true again.
You could also implement logic that allows you to drop items on the map using the mousebutton released event.
Hope that can help you. ;)
@@RACOONLPs yeah, that makes sense, thank you!
Brilliant! I learned so much!
Thank you, Mr. Heartbeast. I always look forward to your Godot tutorials. The development of my game wouldn't be nowhere near as far without your help!
You're welcome :) Feel free to send me screenshots or a trailer of your game when you feel ready to share it. I'd love to check it out.
@@uheartbeast Thank you for offering me an opportunity to show my work! I will send you pictures of it soon!
@@drbuni Wish you luck with your game, man! Don't forget to send a link for your game when you upload it.
@@veselinborisov369 Thank you
Just started with godot and you are one of the reasons I am able to speedrun the learning process. Thank you
So how did that speed run go? Been a year haha
@@Mysterygamer420 Made a pixel topdown multiplayer game about knights with MP5s in a randomly generated dungeon with endless waves. Took me about an hour to get used to shortcuts and stuff, about a week for GDscript and all different classes (like tf is an AStar). Few more days digging through networking documentation and tutorials and that's about it. I want to continue working on a new iteration with bosses and "tinykeep generation" but my whole year was consumed by college : (
Hello, I’ve just started your course in Udemy. It’s super cool. Wish you the best.
I'm going through your godot course right now and this is just one more thing to add to my toolbelt!
This is so good! Thanks HeartBeast!
I avoided having a to add a script to the InventoryContainer to "catch" data dropping outside of the InventorySlot by doing the following:
instead of removing the item from the inventory inside get_drag_data, just get the item with inventory.items[item_index]
then, on drop_data, you can do:
func drop_data(_position, data):
var item = data.get("item")
var item_index = data.get("item_index")
var my_index = get_index()
inventory.swap_items(my_index, item_index)
Underrated comment for sure. Less scripts to track the better!
How do we move items if we have different arrays?
Great video!
You are dope bro! Damn , thank you so much, subbed
This is pretty cool, when i created an inventory, it was just a bunch of auto-generated panels and buttons
This video is really great and (with the help of a couple comments) wasn't hard to convert for Godot 4 (mostly adding the _ before _get_drag_data, etc.) but wanted to share something that took me hours to figure out. My items are a Sprite2D sprite sheet w/ 38 images and I tell it from the Resource what frame and hframe to use. But for the drag image, you can ONLY use a Control node, not a Sprite2D node. A TextureRect is a Control node, but you can't set hframes and use a sprite sheet and I really didn't want to individually export all 38 items just for the drag.
I figured out the solution and it still took me a couple more hours to crack it, but here's the code if you want to get a Sprite2D to drag:
var preview_texture = Sprite2D.new()
preview_texture.texture = _drag_texture
preview_texture.hframes = _drag_hframes
preview_texture.frame = _drag_frame
var preview = Control.new()
preview.add_child(preview_texture)
set_drag_preview(preview)
I tried to just use my current sprite_2d.texture, etc. but I'm pretty sure that gets deleted right before the drag preview is made, so I had to add the _drag_texture etc. global variables and set those in the display_item(item) function. Works now and I'm relieved.
Anyways, thanks Heartbeast.
Man, I remember starting out in high school learning game maker 8 using an inventory tutorial.
And now I'm back again but with Godot instead ^^
That moment you start to understand many new things even after having made some games
the moment you called a function that didn't exist yet, I felt that
I love how you are always concerned about the audio of the recording. Rest assure it is top notch.
1:14 to anyone confused about what the height/width and test height/width settings are doing:
height/width refers to *render* height and width.
test height/width refers to *window* height and width.
these properties will likely be given more fitting names in a future release of godot. more detail here: github.com/godotengine/godot/issues/16863
so basically
if not test is 1x1 and test is 2x2, it will be not test scaled to 2x2?
am i right
13:50 The swap_items() implementation only requires 1 local variable, like so:
var target_item= items[target_item_index]
items[target_item_index] = items[item_index]
items[item_index] = target_item
emit_signal("items_changed", [item_index, target_item_index])
Thank you! Great video.
awesome
if anyone is looking for how to have the dragged item be centered with your mouse cursor
# set_drag_preview seems to put the top left corner where the mouse is
# to fix this create a container, then add the texture as a child
# then set it's rect position which is relative to parent
var previewCon = Control.new()
previewCon.add_child(dragPreview)
dragPreview.texture = item.texture
dragPreview.rect_position -= dragPreview.texture.get_size() * .5
set_drag_preview(previewCon)
You've proven that reading the youtube comments can be good after all. :)
If we have another container like chest or item bank, it means we'll make another array. How do we move items in that scenario?
in godot 4.0 rect_position is now just position or global_position so. "dragPreview.position -= dragPreview.texture.get_size() * .5"
"Tall shields are the best shields"
>SEETHES IN ROUND SHIELD
I believe it's better to handling unsuccessful drags in slot script:
In _get_drag_data(...) instead of removing item, just hide the TextureRect. In _notification(...) handle NOTIFICATION_DRAG_END, check with is_drag_successful() if the drag was successful, if not show the TextureRect. And in _drop_data(...) remove item inventory.remove_item(data.index), when it is reliably known that the grag was successful.
I found a pretty horrible way of 'fixing' the bug at the end. Just add a 2nd ColorRect above the Inventory Container on the tree, make it absolutely massive so you can't drag your mouse away from it and then attach the same script we added to the InventoryContainer. You will need to add a control node at the parent to everything though.
It would be nice if there was a better way of resolving this but i don't even get information returned from any of the functions if it is dragged outside of the container.
anyway thanks for the tutorial, I learned a lot.
how do you add and remove items in the array for when you want to pick them up and remove them in the game (instead of dragging the .tres files into the array)?
9:33 The array can be export with the following code @export var items : Array[Resources} = [ ]
Here, \o/ have a hug u nice Internet person
Very nice tut. Glad you posted it, but i take it this means the walker videos are done?
Here's an unintuitive solution to the "dropping items" problem:
dragPreview.tree_exiting.connect( _on_drag_end.bind(item) )
This will cause the drag preview to call some function (_on_drag_end in my case) when it disappears, with the argument 'item'.
The called function can make use of the 'is_drag_successful' function, which returns false if we dropped the item somewhere that could not accept its data:
func _on_drag_end(item):
if not is_drag_successful():
inventory.set_item(get_index(), item)
I feel like this solution is very clean as it does not require a new script and can be reused if we put the slot display somewhere else.
What if we have more than one containers to store items?
A quick question: When setting the drag preview, I get an error:
Invalid type in function 'set_drag_preview' in base 'CenterContainer (InventorySlotDisplay.gd)'. The Object-derived class of argument 1 (StreamTexture) is not a subclass of the expected argument class.
Something I did wrong with the item resources and texture settings?
If I want to store some "transient" info, like keeping a "condition" for a sword that is different between instances, how would the best way be?
I'm losing myself when trying to store these infos while switching scenes like Inventory -> Dropped -> Inventory -> Equipped while still having the advantage of the resource inheritance... I tried having a ItemResource with a custom_properties = {} but didn't go well :c
Ples ples ples make a new third video tutorial going more into this, I love how it look so much but after finishing the second video I'm still left confused on how to properly use the items and add it to my game.
Can you tell me how to make the item selection function? So that you can left-click and the item is saved to a separate variable? I just want to implement descriptions and item interaction for my quest
Hi HeartBeast, will this video be part of an episode or is it a standalone video without a sequel?
I'm using Godot 4.0.3 and it was working all the way until the get_drag_data() and the other two functions, turns out in Godot 4 the syntax is with an underscore at the start so get_drag_data() is now _get_drag_data()
preciate you big dog
Hey friends
Needed some help
i want to move my character through area2d or any other node
And I want to make my character appear double or more
Like the game SKY by ketchapp
Most relatable tNice tutorialng ever
How can I make the drag preview appear in a better spot? Like, the center of it being centered on the cursor. Because I don't like dragging the image by the top left corner.
I have not tested this, but since it's a control you can set the preview texture rect_pivot_offset to be its rect_size / 2 and that should work.
this method works in 3.5? beacuse I loved so much this tutorial, I want to put a pause screen in this style.
I'm having a strange offset issue, when I drag the item it appears far away from the mouse cursor, and when I move around (which moves the camera) the offset changes. I have a RemoteTransform2D, when I turn off "Use Global" the drag offset stays the same, but it is still far from the item. Anybody else notice this?
I wonder who hard is to combine it with your old Mobile RPG project... And i really wanted something like a update and expansion of that tutorial, maybe with how put more character at same time or extra exploration elements.
Very cool tutorial. I am new to Godot, but have done a lot of experimenting with Unity. Godot has caught my attention though. With regards to this inventory tutorial, how would this work with a save system? Obviously, if I save and quit then when I come back later I want the inventory to match what I saved. Would I just need to set all of those items in the Inventory resource at runtime when I load my save file? I'm thinking I would just save the index and resource path for each slot in the save file somehow. Anyway, some guidance on how you persist the inventory would be helpful.
My guess is that you just need to make sure you save the array that holds all the items from inventory.tres.
What did the preview part actually do? I think I missed that. Either way, great tut, can definitely use that! Didn't know the drag and drop was that simple.
The preview is what adds the picture of the item near the mouse, otherwise you would drag just your mouse. It makes it easier to see what you're hovering over to drop your item in a new slot basically
i love you ♥
wow i never thought that resource can be save the array node.
before i do it the same but i have to make one scene for save and load arrays data
If i wanted to have multiple inventories or chests/other types of slots how would i go about adding those without getting index errors when moving between containers?
I'm getting just that exact error.
Have you found any solution?
Share it, please
I'm having an issue with the InventoryDisplay.gd
I can't run Inventory.tscn because of this error message:
"Script inherits from native type 'GridContainer', so it can't be instanced in object of type: 'CenterContainer'",
but then if I change the extends to CenterContainer I get an error saying the opposite:
"Script inherits from native type 'CenterContainer', so it can't be instanced in object of type: 'GridContainer'"
How to make this work with a gamepad instead of a mouse?
when my swap the item changed but the icon not change.. whats wrong? i think the code work and similiar
How would I use this with a hot bar or a crafting system? I am trying to figure it out, but it seems like I keep getting errors!
Have you found a solution?
can you pls make a video on item stacking? P.S. amazing video, was exactly what i was looking for
I was actually planning on having that in this video but had to cut it because of time. I'll see what I can do about getting a second video with stacking in it :)
@@uheartbeast thank you, cant wait :D
thank you. the code is ... oddly very comprehendible. that was not the case with other tutorials i could find on youtube and thank god it takes care of swap.
"Tall shields are the best shields". *REEEEEEE's in Tower Shield*
If I wanted to add functionality to an item, would I have to create a new class that inherits from item and make it a resource? for example, if I wanted my potions to actually increase the players health, should I make a Potion class that inherits from Item, then create the resource and add it to the inventory?
Hey, did you find a good solution to this problem?
@@valentinocerutti8764 sadly no
So, lets say I use this inventory and need to have equip slots in the same display...do I have to make ANOTHER inventory for the equipable slots? Same with item types: equipable, consumable, quest items, etc? If that the case, it will make my life perposterously easy :P
Have you found the answer for that?
12:04 filling an array with null kind of hurts because I know I will forget the null check at some point😂
9:00 why cant we write we want a spesific type of resource like this:
export (Array, Item) var items
godot STILL doesn't support custom class export types T-T
20:49 Make sure you drop in the actual .tres files and not the .png files here like I did 🤦
I dont see point of using swap_items function inside drop_data() because we dont actually swap anything. It's just more convoluted way to set_item inside inventory
inventory.swap_items(my_item_index, data.item_index)
inventory.set_item(my_item_index, data.item)
->
inventory.set_item(data.item_index, my_item)
inventory.set_item(my_item_index, data.item)
works same
Do you prefer Godot over Gamemaker?
please make a followup
Here i come again
Can you make a farming video
this method works using keyboard instead of mouse?
Items is one of those words that very quickly lose all meaning if you read it too often lol
Wow. This comes out like a week after I finish working on an inventory system.
Really like this video helps me see what I got right and wrong.
The only thing I didn't like is that it uses drag and drop. Would have preferred it be click to pick up and then click to drop. I think most games have it like that instead of drag and drop. Right?
most games uses drag and drop from what I have seen. Also that way its easier to port to mobile/touch devices
@@vickylance I didn't think about mobile games. Agree drag and drop would be better in that context. I guess i was remembering old RPGs like Diablo... I think Stardew valley is also the same right?
this sounds hard but could u find out how to make a crafting system
Now if I actually had a clue how to use that in a game project?
Hi Do you have separate day job for a living?
Can you make Godot. Hack and slash game tutorial
This is interesting, but how can you use this in another system . EX: You have this inventory on your character, but also want to have another inventory on a chest. If you put the same thing on the chest even though you instantiate-it it as a new scene, when opening the " chest " inventory it's the same inventory because of the inventory.tres.
From what I've tested you must have another scripts to handle that second inventory, and If you have less slots in the chest then again it's trouble because moving an item from index 3 in your character to index 0 in the chest inventory get's buggy .
Wondering if someone tried this yet ? :)
ITEMS!!!!
can we see a tutorial implementing this into a game?