Very good tutorial. Most tutorials focus on implemeting the ability, but not about scaling your whole game to implement multiple systems, and this is really lacking in most tutorials. Thanks !
Oh this was great! I'm planning out a magic based game where there will be enemy magical users who will be using the same abilities as the player, and there may be magical creatures too. So this whole set up would make it much easier to do this without writing custom character code over and over for the same abilities.
Dang Man. This is Amazing. Been looking for some thing like this for a while You could even go one step further and make the UI reflect the config options and have it be a system which go from code to no code and all be modular. Love it.
The "move" ability takes parameters for the movement direction, so the appropriate Entity needs to know that. If the Entity using the abilities needs to know how to call each ability, it seems like it's not achieving the goal.
It could be modularized even more, but I still feel like it's achieving the goal perfectly. The entity is responsible for WHERE it wants to move, not HOW to move. Separating logic from state, as intended. Going further is semantics and we'd have to really look at a specific case before being able to say which method is best. Even then, it's never perfect. There are always benefits and drawbacks for every sensible approach.
I agree with your concern. I think it is still an interesting approach to have modular abilities. But I would remove any extra parameters from the execute() method and just pass only the Entity. I think, I would add two methods to Entitiy "get_move_vector()" and "get_aim_vector()". Then the ability can call these functions as needed. The ability shouldn't handle tracking the mouse position, that is part of the player mechanic. NPC AI can then implement other approaches where to aim at. When thinking about enemy AI, I see some additional problems. I guess, the AI script must know exactly what abilties it has and how to use them effectively, like dash away from an attack using blink or blink towards the player and doing a melee attack. Not sure if such a system is suited for every style of game, but I will try to play with it.
@@dav2dev im making arpg with stoneshard system in mind where every character can have same ability as player (mostly for bandits, mercenaries etc) great tip for when I try to implement it to enemy's. THX🙏
Subbed. Amazing. I am tweaking this for Godot 4 and if I upload a modified/updated version, I will credit you thoroughly. This was brilliantly done, and it curtails the hazards of making long switch case statements without any structure in how one organizes their overall project. For anyone interested in a poor example -> See Undertale for examples of how to NOT structure.
A bit improved ability loading would be to export variables for a PackedScene type. Because that does the preloading automatically and you can pass it to AddAbility() function... But then again why not just have them already in the player controller scene, that's inherited from the Entity scene? This system works, but I don't like the fact that entities need to know about the ability. In my opinion, for the ability to be modular, it should work by itself and affect its entity. So when an ability is ready it should fetch the reference of its entity, then go it's way. Then entity doesn't need to control abilities and abilities could control their own cooldown.
this system loses its modularity when you introduce any entity-wide state, for instance a can_move variable. this can be solved by a property accessor that looks for entries in a dictionary and initializes one if it doesnt yet exist and the entry is removed when all abilities that reference it are gone
Just watched this and a great introduction, one question how would you introduce temporary abilities rather than permanent ones through this approach. For example say I want to allow a weapon to have extended range for a number of turns?
You could probably have the state be a parameter of the ability call, so the ability is responsible for keeping track of whether it should stay instantiated or not.
How would you go about coding an ability that would require some functionality of the entity/player to stop functioning? For example a channeled ability that would stop you from moving/using other abilities while you're casting it.
Just bouncing an idea. Maybe there is a way for a child node in Godot to restrict properties of its parent node and then give a list of acceptable properties which can still be changed?
You would only need to send a reference of the entity using the ability that the ability can then refer back to to set any parameters you need. For example, the ability can set the player velocity to null while a timer on the ability is still running.
Inside any ability have a check for that. Let's say a bool is true for abilities that lock the player in place, although generally you wouldn't want to let the player call 8 abilities on the same frame. Maybe a system that's similar to a behaviour tree where you have abilities that need to be fully executed before anything else happens, or abilities that run regardless of any other inputs made by the player, etc.
A question: Why do you instance the abilities in script and not do a more dynamic instancing? As of now i i want to bar player access to an ability i would need to have it load in anyways and the use a bool or deactivate the node to lock access to it. But if i would create an array of attacks, i would only need to write a loop which iterates through the array positions and uses the load_ability function to instance the abilities as children. Thus i would be able to add key-value pairs to the array to extend the list of available abiliities and reduce the amount of code if i had something like 100 abilities that could possibly be used by the player. I wouldnt even need a hardcoded list of what abilities the player has since i could just add them to the players array when they interact with something for example. The only CON i can see here is you dont have an easy grab for the ability. Tho you have the array as a library anyways so not a problem i see. Do you think an alternative solution would work better? Thank you for the guide, it touches on many important design matters like factorys and inheritance which are crucial in designing a well functioning modifiable game
I have watched this video, as well as your scalable video several times and have enjoyed them both tremendously. I'm currently attempting to get better utilizing the godot engine to begin building games. I have already (in godot 3.4) created a completely separate dedicated multiplayer framework and am in the process of slowly trying to recreate it within the 4.0 alphas that are slowly being released. My goal is to build a "base", upon which I can implement "upgrades" which will expand upon the base. New characters, abilities, places, npcs, etc..., but I am wondering about the entity script. My game will be sci-fi based, and will have normal humanoid-based characters, it will have 4 legged, 6 legged, and 8 legged entities, all with different defaults. I'm thinking I will need to utilize a different entity base for each type of character and though this seems just too easy to me, would I only need to implement, for example, entity2.gd, entity4.gd, entity6.gd, and entity8.gd from which to inherit to different characters, then just make sure each character inherits from the proper entity script? This just seems like it would be too good to be true as it would appear, to be far too easy. Would it actually be that easy, or am I missing something entirely?
Would need to know more about your setup, but there are some coding ways to handle this using overrides and overloads. Where the entity4 inherits entity.gd but then overrides some of the features or just adds more methods. You could also just add overload methods to the entity.gd script like if you had: regen_mana(amount) you could add a new method called regen_mana(amount, numOfLegs) this would extend this entity method to allow for code specific around the number of legs. or you can refactor regen_mana to always take in a numOfLegs but default if its not provided to humanoid. regen_mana(amount, numOfLegs = 2) not sure the syntax in godot but this is something that is done but you can end up in iheritance hell if you not careful.
tweens are supposed to be able to change any property of any object over time. if you create a modular set of functions that run tweens on location/rotation, might be able to reuse those functions on any set of objects. i am trying to see if i can do this to tween between shape keys of my objects, will see how it goes.
How much more complicated will this get if the ability needs to invoke a certain character state? For example, if I want the ability to make the player jump on execution?
I know this video is very old but it would not hurt to try, I have a problem starting the physics of falling. I called the gravity project variable within entity.gd, but the method ,if not is_on_floor(): velocity.y += gravity does not work within the player or within move.gd :(
The font is too small to read in a phone's screen..i've been enjoying the contents of your channel but I can't do that using a mobile phone. Please kindly increase the font size in the text editor, thanks!
Very good tutorial. Most tutorials focus on implemeting the ability, but not about scaling your whole game to implement multiple systems, and this is really lacking in most tutorials. Thanks !
Oh this was great! I'm planning out a magic based game where there will be enemy magical users who will be using the same abilities as the player, and there may be magical creatures too. So this whole set up would make it much easier to do this without writing custom character code over and over for the same abilities.
Dang Man. This is Amazing. Been looking for some thing like this for a while
You could even go one step further and make the UI reflect the config options and have it be a system which go
from code to no code and all be modular.
Love it.
Just a bit bigger text in editor would be great! :)
Really amazing tutorial!
Created an ability shop where heroes can pick custom abilities. It's highly inspired by your method, thank you very much!
Nice, elegant approach. It would be helpful if this video was in your Godot playlist.
also use relative file paths! so that line isn't dependend on where you put the ability folder
7:47
var ghost = preload("./ghost.tscn")
damn b thats a great idea
@@ygypt i hope that this b stands for boy.
@@hiiambarney4489 it stands for bingus
That is sooo smart, outside the box thinking
Cool tutorial, also sounds like a neat idea for a game, you should do Dev logs on it!
The "move" ability takes parameters for the movement direction, so the appropriate Entity needs to know that. If the Entity using the abilities needs to know how to call each ability, it seems like it's not achieving the goal.
Markov Chains?
It could be modularized even more, but I still feel like it's achieving the goal perfectly. The entity is responsible for WHERE it wants to move, not HOW to move. Separating logic from state, as intended. Going further is semantics and we'd have to really look at a specific case before being able to say which method is best. Even then, it's never perfect. There are always benefits and drawbacks for every sensible approach.
I agree with your concern. I think it is still an interesting approach to have modular abilities. But I would remove any extra parameters from the execute() method and just pass only the Entity.
I think, I would add two methods to Entitiy "get_move_vector()" and "get_aim_vector()". Then the ability can call these functions as needed. The ability shouldn't handle tracking the mouse position, that is part of the player mechanic. NPC AI can then implement other approaches where to aim at.
When thinking about enemy AI, I see some additional problems. I guess, the AI script must know exactly what abilties it has and how to use them effectively, like dash away from an attack using blink or blink towards the player and doing a melee attack.
Not sure if such a system is suited for every style of game, but I will try to play with it.
@@dav2dev im making arpg with stoneshard system in mind where every character can have same ability as player (mostly for bandits, mercenaries etc) great tip for when I try to implement it to enemy's. THX🙏
Wow, that was such a great tutorial, thanks for your effort!
very well designed. excellent work!
55:00 "a game where you start as a _primitive_ adventurer"
@
player character is literally a square 🤣
Dude I clicked, this video has less than 55 minutes
Great system, will implement it right away thanks :)
Subbed. Amazing.
I am tweaking this for Godot 4 and if I upload a modified/updated version, I will credit you thoroughly.
This was brilliantly done, and it curtails the hazards of making long switch case statements without any structure in how one organizes their overall project.
For anyone interested in a poor example -> See Undertale for examples of how to NOT structure.
Very good tutorial it is very interesting. I was wondering how you would handle animations. Do you play them from the ability with the self or not ?
A bit improved ability loading would be to export variables for a PackedScene type. Because that does the preloading automatically and you can pass it to AddAbility() function... But then again why not just have them already in the player controller scene, that's inherited from the Entity scene?
This system works, but I don't like the fact that entities need to know about the ability. In my opinion, for the ability to be modular, it should work by itself and affect its entity. So when an ability is ready it should fetch the reference of its entity, then go it's way. Then entity doesn't need to control abilities and abilities could control their own cooldown.
nice - have you looked at resources files to do the same thing ?
Thank you, this will be very helpful :D
this system loses its modularity when you introduce any entity-wide state, for instance a can_move variable. this can be solved by a property accessor that looks for entries in a dictionary and initializes one if it doesnt yet exist and the entry is removed when all abilities that reference it are gone
you are the best
Just watched this and a great introduction, one question how would you introduce temporary abilities rather than permanent ones through this approach. For example say I want to allow a weapon to have extended range for a number of turns?
You could probably have the state be a parameter of the ability call, so the ability is responsible for keeping track of whether it should stay instantiated or not.
Hi Andrew, very nice that youtube algorithm recommended your channel to me!
Is there a link for your code?
How would you go about coding an ability that would require some functionality of the entity/player to stop functioning? For example a channeled ability that would stop you from moving/using other abilities while you're casting it.
Just bouncing an idea.
Maybe there is a way for a child node in Godot to restrict properties of its parent node and then give a list of acceptable properties which
can still be changed?
You would only need to send a reference of the entity using the ability that the ability can then refer back to to set any parameters you need. For example, the ability can set the player velocity to null while a timer on the ability is still running.
Not sure if tags are a thing? You could have a dictionary of tags that an ability should cancel when it's activated.
Inside any ability have a check for that. Let's say a bool is true for abilities that lock the player in place, although generally you wouldn't want to let the player call 8 abilities on the same frame.
Maybe a system that's similar to a behaviour tree where you have abilities that need to be fully executed before anything else happens, or abilities that run regardless of any other inputs made by the player, etc.
How do I package the modular abilities to load them in runtime...
A question: Why do you instance the abilities in script and not do a more dynamic instancing? As of now i i want to bar player access to an ability i would need to have it load in anyways and the use a bool or deactivate the node to lock access to it. But if i would create an array of attacks, i would only need to write a loop which iterates through the array positions and uses the load_ability function to instance the abilities as children.
Thus i would be able to add key-value pairs to the array to extend the list of available abiliities and reduce the amount of code if i had something like 100 abilities that could possibly be used by the player. I wouldnt even need a hardcoded list of what abilities the player has since i could just add them to the players array when they interact with something for example.
The only CON i can see here is you dont have an easy grab for the ability. Tho you have the array as a library anyways so not a problem i see.
Do you think an alternative solution would work better?
Thank you for the guide, it touches on many important design matters like factorys and inheritance which are crucial in designing a well functioning modifiable game
I have watched this video, as well as your scalable video several times and have enjoyed them both tremendously. I'm currently attempting to get better utilizing the godot engine to begin building games. I have already (in godot 3.4) created a completely separate dedicated multiplayer framework and am in the process of slowly trying to recreate it within the 4.0 alphas that are slowly being released. My goal is to build a "base", upon which I can implement "upgrades" which will expand upon the base. New characters, abilities, places, npcs, etc..., but I am wondering about the entity script. My game will be sci-fi based, and will have normal humanoid-based characters, it will have 4 legged, 6 legged, and 8 legged entities, all with different defaults. I'm thinking I will need to utilize a different entity base for each type of character and though this seems just too easy to me, would I only need to implement, for example, entity2.gd, entity4.gd, entity6.gd, and entity8.gd from which to inherit to different characters, then just make sure each character inherits from the proper entity script? This just seems like it would be too good to be true as it would appear, to be far too easy. Would it actually be that easy, or am I missing something entirely?
Would need to know more about your setup, but there are some coding ways to handle this using overrides and overloads.
Where the entity4 inherits entity.gd but then overrides some of the features or just adds more methods. You could also just add overload methods to the entity.gd script like if you had:
regen_mana(amount)
you could add a new method called
regen_mana(amount, numOfLegs)
this would extend this entity method to allow for code specific around the number of legs. or you can refactor regen_mana to always take in a numOfLegs but default if its not provided to humanoid.
regen_mana(amount, numOfLegs = 2)
not sure the syntax in godot but this is something that is done but you can end up in iheritance hell if you not careful.
How would you handle animations on the character with this system? For example, how would you play the idle animation since it's not an ability
tweens are supposed to be able to change any property of any object over time. if you create a modular set of functions that run tweens on location/rotation, might be able to reuse those functions on any set of objects. i am trying to see if i can do this to tween between shape keys of my objects, will see how it goes.
@@udippatel6147 pretty sure they mean like spritesheet animations. tweens are irrelevant there
How much more complicated will this get if the ability needs to invoke a certain character state? For example, if I want the ability to make the player jump on execution?
I know this video is very old but it would not hurt to try, I have a problem starting the physics of falling. I called the gravity project variable within entity.gd, but the method ,if not is_on_floor():
velocity.y += gravity does not work within the player or within move.gd :(
is it working for godot 4 3d?
Hi. It is good video , but how i can do health and mana regen every 1 second? I not see game master .gd script.
What happens when you need things like pathfinding on a tilemap
The font is too small to read in a phone's screen..i've been enjoying the contents of your channel but I can't do that using a mobile phone.
Please kindly increase the font size in the text editor, thanks!