I’m working on creating items (specifically weapons) for a game. Each item will have a min & max damage, attributes, a sprite, etc. Overall the differences between these weapons will be numbers and files, with the base code being the same across them all.
My question is this: Would it be best practice to create a single ‘weapon’ script that handles functionality, or to create a separate script for each object?
Create a single weapon script. Inherit it and override any methods you need to for specific weapons. Store all the stats for weapons in a custom weapon resource.
I had a link to a course I used for this, but it got flagged as spam by someone, so if you want the link, send me a message.
I don’t know if there is a thing such as best practices in game development because the architecture being good or bad depends on the specific needs of the game. Nonetheless Godot prefers the composition design pattern over inheritance.
To answer your question, I would go for maybe both approaches. Having scripts the are used for multiple nodes and having specific ones only for specific nodes. Then use the composition design pattern to build the weapons as scenes.
As everyone else said, each iteration for each object is a real dilemma that can be solved with classes, but if the weapons are complexIt would be very helpful to divide them into several components, even then you can create the same components from the same class, but converting the whole into a single class in this dimension is not very useful, Godot offers very good capabilities to divide one scene into other scenes that make the design really enjoyable for these tasks.
“item” is a very broad term.
also, think of EVERYTHING that this item should do in your game and write it down. It sounds like you don’t have specifics nailed down yet.
the more features you add, the more difficult it will be to code, so try to keep it simple. specially since you seem to be new to this.
using classes is a way to do it.
but since all you are using is variables, I would instead use godot’s metadata.
it’s a button at the bottom of the inspector. you can add properties to your node without needing a script, you can then access them with get_meta("name_of_my_metadata", 5) where 5 would be the default value to return if the metadata doesn’t exists. this way you can check any node even if it “has a script” or is of any type.
I would do this for things like coins, and other items, where a coin can have a value of 1, but can also have a value of 5. then create a scene for each item.
if however we are talking about more abstract items, you need an array containing all items that you access by id.
so a node would have an id 7, and you would access the location 7 in a Array in an autoload. the node can then be a template that you fill with an image, values, name, etc. for this the Array would be filled with a custom Resource containing all these values.
not true. godot uses inheritance for the node system.
and in the case of composition, you do need inheritance. if properly encapsulated, you can override the methods of a base class to allow this swapping of a node or resource.
As I see no one else linking to this I will just leave it here. I always suggest reading from the Godot docs first if they have the articles on the topics you are interested in and then continue on other sources.
For anyone else with a similar question, I’ve read more and have the actual “best practices” solution (at least for my use case).
The best way to do this is to create a basic weapon scene to handle the functionality of each weapon, and then create a new resource that will handle the specifics of each weapon. This allows for editing and changing functionality across each weapon simultaneously instead of creating scenes for each and having to tweak each one by one. This video goes over the workflow (It’s the same for 2d and 3d) and it should work for any items, not just weapons.
This video is completely free and gives the full workflow.
There IS such a thing as best practices. The fundamentals of programming don’t change with what you’re creating.
Metadata is a weird workaround to avoid using export variables for some reason.
Storing all weapons in an array would be ABSOLUTELY unhinged, especially when objects are an option.
Okay, but that is not an argument to invalidate the truthiness of my statement. One thing is how the engine nodes are designed and the other is the preferred way of using them to build.
Well, you were asking about best practices in the context of your specific case not in a broader sense of programming. It would have been more accurate if you asked for architecture suggestions for your specific case rather than for best practices.
not weird and not a workaround. and avoid exports if you can. exports are shared between instances of a scene.
if you instantiate a scene in game and try to change the export, the other instantiated scenes will have it changed too.
you never specify WHAT you are trying to do or what you want. storing weapons in an array can be used for an inventory system like in an RPG, where there are no physical weapons but an item that is assigned and a graphic that is updated.
I also used this for cards in my card game.
It’s also better for performance, objects take up space in memory.
there is no such thing as fundamentals. there are approaches, design patterns, and each is useful for a different case.
there can be good practices with a language, but there is nothing absolute, Assembles uses GOTO. everything is relative.