Intro to Goal Oriented Action Planning (GOAP)

Поделиться
HTML-код
  • Опубликовано: 10 ноя 2024

Комментарии • 70

  • @ThisIsVini
    @ThisIsVini  3 года назад +4

    Hello!
    When I was going through the code I realised I was repeating myself, so I decided to leave the code part more high level. If you'd like to analyse it better check the repository github.com/viniciusgerevini/godot-goap. There you can also find a link for the live demo.

    • @EnricLlagostera
      @EnricLlagostera 2 года назад

      Hey, thanks for the video! Just wanted to let you know that the GitHub link on your comment is broken (it has an extra parenthesis at the end). Cheers!

    • @ThisIsVini
      @ThisIsVini  2 года назад

      @@EnricLlagostera thanks a lot

  • @LordQuadros
    @LordQuadros 11 месяцев назад +7

    I think this is what you call a rare timeless coding tutorial, because no matter what language or engine you're using, the base logic still applies. Well done.

    • @ThisIsVini
      @ThisIsVini  10 месяцев назад +1

      Thank you! I definitely try to explain these things in an engine agnostic way. I'm glad you found so. Cheers

  • @BlenderKiel97
    @BlenderKiel97 3 года назад +5

    Thank you Sir for your contribution to Game AI in Godot :)

  • @taphousegames
    @taphousegames 8 месяцев назад

    Nice intro, and thanks for making the code publicly available!

  • @Alexey_Pe
    @Alexey_Pe 4 месяца назад +1

    1:37 What about choosing a plan with more points? For example, it costs more points, but the NPC will get "pleasure" from it and will take on a more difficult plan because of it.
    I think it's worth changing the concept of "cost" to "profit", then it will be possible to make different ideas about profit for different NPCs, for example, when all vital needs are satisfied - depending on the resource behavior, the NPC will choose plan to idle or explore/etc.

    • @ThisIsVini
      @ThisIsVini  4 месяца назад +2

      Hey, good thought exercise. The trade off doesn't seem worth it to me though. I think one good thing of thinking as "cost" is that 0 will always be the least effort / most desirable action. If we invert the scores, when adding a new most desirable action we will need to know what is the current highest score and there is no guarantee that action will remain being the most desirable one. It should still work, but I think it would require more maintenance. However, that doesn't invalidate your idea of making the plans cheaper using other variables (i.e. pleasure). This can be achieved with dynamic costs without needing to invert the scores.
      Also for your example of choosing the idle/explore plan, that is usually defined by the plan priority and not for the plan cost. What I mean is that if the vitals are satisfied, idle or explore will become the highest priority goal, so only plans to achieve idle/explore will be considered. Thanks

  • @dandymcgee
    @dandymcgee Год назад

    Analog Studios has some amazing CC-0 artwork. Thanks for shouting them out in your video!

  • @lee1davis1
    @lee1davis1 Год назад +2

    Nice. This actually helped me better sort out my game mechanics. Thanks

    • @ThisIsVini
      @ThisIsVini  Год назад

      Thanks for sharing. I'm glad it was helpful. Cheers.

  • @rafayeah1
    @rafayeah1 3 года назад +2

    Hey Vini, just wanted to drop a huge YOU'RE AMAZING here. Great content, I hope you keep up with them -- thanks! :)

    • @ThisIsVini
      @ThisIsVini  3 года назад +1

      Thank you. It' s nice of you. This kind of videos usually take more time to make than my normal devlogs, that's why I don' t do them as often. But I intend to keep making them whenever I find an interesting subject. Suggestions are welcome :)

  • @jugibur2117
    @jugibur2117 2 года назад +1

    Wow, heavy stuff but very fascinating, thanks for sharing!

  • @KryyssTV
    @KryyssTV 6 месяцев назад

    Thanks for making this. It looks to me like a hybrid approach is needed whereby a behavioir tree handles general logic and then GOAP can exist within a constrained state for more dynamic behavioir. This would ensure undesirable outcomes are isolated within a particular state.

    • @ThisIsVini
      @ThisIsVini  6 месяцев назад +1

      Thank you! Yeah, that would be a nice approach to cover scripted and unscripted behaviour and play with both strengths

  • @DonatemangaCom
    @DonatemangaCom 3 месяца назад

    Very good video - thanks

  • @beidero
    @beidero 3 года назад +4

    Very interesting, actually never heard of goap before. Sadly doesn't fit well into my current project but will certainly test it out in the future if I do a project where this would fit well.

    • @ThisIsVini
      @ThisIsVini  3 года назад

      Thanks. Yeah, same with me. I think it works best for systemic games that can benefit from unpredictable complex behaviours.

  • @guilhermetramontina8222
    @guilhermetramontina8222 3 года назад +1

    Very cool! 👏
    It reminded me of Fred George’s Need Pattern, used in event-driven systems.

    • @ThisIsVini
      @ThisIsVini  3 года назад +1

      Interesting. I haven't read about Need Pattern yet. I'll look it up.

  • @greg7987
    @greg7987 3 года назад

    Yeah! Thanks for this video. I tried to make my own goap thing in Godot but that was not successful. Thank you so much.

    • @ThisIsVini
      @ThisIsVini  3 года назад +1

      Thanks Greg. I hope this helps with your implementation. Cheers

  • @InfernalWAVE
    @InfernalWAVE 8 месяцев назад

    wow this was a big help getting me started, thanks!

  • @XibalbaProgramming
    @XibalbaProgramming 2 года назад

    Thanks a lot for this man, you're awesome

    • @ThisIsVini
      @ThisIsVini  2 года назад

      Thank you. Nice of you to say that :D

  • @segue2ant395
    @segue2ant395 2 года назад

    Nice concise overview, thanks :)

    • @ThisIsVini
      @ThisIsVini  2 года назад

      Thanks. I'm happy you find so. :)

  • @TackerTacker
    @TackerTacker 3 года назад

    Thank you, great video 👍

  • @finnbunker6
    @finnbunker6 7 месяцев назад +1

    Hello, Vini. Is there any chance you can change the renderer of the project to compatibility as my laptop can't handle the OpenGL3 Renderer. It's all good if not, I just wanted a better idea of how the project works as I'm struggling with implementation. Thanks!

    • @ThisIsVini
      @ThisIsVini  7 месяцев назад +1

      Hello @fznbu. I might be missing something, but you can change the renderer in your editor. That will require a restart but things should work. Cheers

  • @benjaminbirdsey6874
    @benjaminbirdsey6874 3 месяца назад

    It seems that the biggest drawback for this method is the inability to predict the future. For instance, if the fire pit will burn out before the satyr can get wood to build another pit, that is a failure and the satyr should not spend any time chillaxing but should go to get firewood. Similarly, if the troll is near and there are two possible sanctuaries, the satyr should be able to determine which one would allow them to flee the troll better.
    Again, not a critique on your specific method, just pointing out that evaluating the GOAP only based on the *now* lacks planning for the future.

    • @ThisIsVini
      @ThisIsVini  3 месяца назад

      That's a very good point. Indeed this video only covers a simplified reactive behaviour. Thanks for the comment and for the example.

  • @JayFolipurba
    @JayFolipurba 4 месяца назад +1

    How do you let the ai know to prioritise something lower priority when it's easier to get? Like here, the character was hungry the whole time, but didn't prioritise it until it got too much, when quickly just picking up a mushroom while going from A to B would have been super simple

    • @ThisIsVini
      @ThisIsVini  4 месяца назад +3

      I think this is just because of the priorities I defined for this project. In the example the hunger was being ignored because I deliberately made the "relax" goal priority way higher than the other ones so it's basically unstoppable. However, in a real game indeed we might want the hunger to at some point surpass the need to hide. That can be achieved by adjusting the dynamic priority for that goal.
      One other idea (I didn't put much thought on that) would be maybe allowing goals with tied priorities to be calculated together. That might be too complex and likely have performance drawbacks, but might work. The idea is that if two goals (i.e. "Calm down", "keep fed") have the same priority, we calculate plans for both of them and pick the cheapest one. In your example, as the mushroom is so close, the agent could prioritize feeding over hiding.
      Having said that, before implementing anything crazy I'd definitely try to tinker with the priorities. Cheers.

  • @fabiolemos123
    @fabiolemos123 3 года назад

    Great video, I’ve learnt a lot 👏

  • @haxtrad
    @haxtrad 8 месяцев назад +2

    I've watched this through a couple of times and read through the code and i can't really understand how you'd make this work with multiple bots? So much of how ti operates seems bound to just working with one blackboard.

    • @ThisIsVini
      @ThisIsVini  7 месяцев назад

      Hello @haxtrad. That's correct. The planner will always work with only one blackboard. When instantiating multiple agents, each one will have their own planner, working with their blackboard instance in isolation.

  • @collinvisser7108
    @collinvisser7108 Год назад

    Very neat - thx

  • @plopsis
    @plopsis 3 года назад

    This was a great video.

    • @ThisIsVini
      @ThisIsVini  3 года назад

      Thanks. I'm glad you liked it.

  • @Mriganka2S
    @Mriganka2S 2 года назад +2

    Hey Vini! I was curious about the code base and tried importing it but I am getting a bunch of errors. Do you know I am getting those errors? (like: indentation errors, stack-overflow errors - after fixing the indentation etc)

    • @ThisIsVini
      @ThisIsVini  2 года назад +1

      Hello. Sorry the late response. That's weird. Maybe something broke with the new releases. I've definitely seen some stack overflow while developing it, because the implementation does not handle circular dependencies, but the code as-is shouldn't cause it. I'll take a look as soon I have time. Thanks for letting me know :)

  • @gonderage
    @gonderage 4 месяца назад

    Personally, I'd still use variables instead of methods because they get exposed in the inspector. There's also custom set/get methods one can define with the variable, too, so one wouldn't lose out on the custom logic.
    anyway, cool vidoe :>

    • @ThisIsVini
      @ThisIsVini  4 месяца назад

      Nice! The set/get tip is a great suggestion. Thank you.

  • @squirrelzar
    @squirrelzar Год назад

    One of the things that seems to elude me is how you pick the initial goal to then send through GOAP. But maybe I’m misidentifying the utility of GOAP and in a simplistic situation of you have an enemy AI only has two goals, kill or flee then you can simplify the logic to pick the higher order goals? Idk

    • @ThisIsVini
      @ThisIsVini  Год назад +1

      Oh yeah. If the behaviour is too simple I guess GOAP might be unnecessary complexity. Having said that if you have multiple ways to achieve the "kill" or "flee" goals it might still be useful.
      For how to pick the goal, it's all about dynamic priorities. I guess your flee goal would have an increased priority if HP is low, while the kill goal priority could increase if the player is too close. For two goals only it's hard to justify, but if you throw another goal in the mix things start becoming more interesting due to unplanned emergent behaviour.

  • @blocklib1932
    @blocklib1932 Год назад +2

    Very nice project. Could you perhaps port it to Godot 4? I just tried to let Godot 4 convert it but it was not functional afterwards. As I am new to Godot I do not know how to fix it. Thanks!

    • @ThisIsVini
      @ThisIsVini  Год назад +2

      Hello there! Yeah, of course. I'll try to set some time aside next week to convert it. Thanks

    • @blocklib1932
      @blocklib1932 Год назад

      @@ThisIsVini That would be great!!! :) Could you answer to this post, when you were able to convert the project? Thank you so much!

    • @blocklib1932
      @blocklib1932 Год назад

      @@ThisIsVini Did you already have time to convert the project? I hope I do not bother you too much, but I would really be excited to experiment with a Godot 4 version. Thanks in advance!

    • @ThisIsVini
      @ThisIsVini  Год назад +4

      @@blocklib1932 Hello there! I migrated it this afternoon. The main branch has the Godot 4 code now. github.com/viniciusgerevini/godot-goap . It seems to be running correctly, but let me know in case you find issues. Cheers.

    • @blocklib1932
      @blocklib1932 Год назад

      @@ThisIsVini Thank you so much!! :)

  • @nikitabelyaev2356
    @nikitabelyaev2356 Год назад

    Thanks for this, works great. One thing I'm missing though is making the actions perform for an amount of time, not instantly. For example, an NPC cooking food for 5 seconds. How would I go about making this? I tried just adding await but it broke everything.

    • @ThisIsVini
      @ThisIsVini  Год назад

      In my example the `perform` method in the GoapAction returns true when finished and false when it is still going. Your actor.cook() method would be the one to control if the action is finished or not. You could also have a property actor.is_cooking used in the action which is set to true when cooking starts and set to false once the timer completes.
      The caveat with doing only that is that this does not prevent your planner from replacing your current plan with something more important and stop it mid cooking. If that is a concern to you, you could have some kind of flag in your actor, like actor.is_busy which would stop the GoapAgent from calling the planner while the actor is busy.
      I hope that's helpful. Cheers.

  • @andrewvickerman1940
    @andrewvickerman1940 2 года назад +1

    With this code, if you add another Satyr they share current goals because stuff like is_frightened is set in the World State. How do you suggest making each actor behave on it's own?

    • @AshleyKampta2
      @AshleyKampta2 2 года назад +1

      You could create member variables that hold all the necessary enemy states and keep them all in an Enemy class which would become the parent class of every Enemy type, and with every instance of an Enemy in that class, you'd get individually editable variables for each Enemy. Of course, every different type of Enemy would have to have a script that extends this Enemy class in order to get access to those variables.

    • @ThisIsVini
      @ThisIsVini  2 года назад +2

      Hello Andrew. That's a really good question. I didn't think about that when I was making this experiment. The first thing that comes to my mind is changing the goals and actions to no look into the raw world state, but into a projection of it. Basically, world state wouldn't include actor related info. The goal would access a local world state that would contain the global world state and be hydrated with all relevant info from the actor. This local world state would then be passed to the actions and goals. This would require some extra thought as it raises other questions like, how to keep both states in sync? Or, who decides which actor's info is relevant?
      Thanks for the question. That makes me want to revisit the problem and come up with a better solution. Cheers.

    • @byj5970
      @byj5970 2 года назад +1

      @@ThisIsVini that's exactly what I want! thank you so much!!

    • @byj5970
      @byj5970 Год назад

      @@ThisIsVini In the current plan, adding multiple Satyr will still share goals and actions. Is it possible to assign a different PLANER to each npc? I have reviewed the introduction related to Goap, and my understanding is that each different NPC will have its own PLAENER and a copy of WORLDSTATE? But my code level is terrible, I really can't do this🥲. Firstly, thank you very much for your work on AI in Godot. Would you like to continue updating this system? Can each NPC have different goals and actions? This is very important to me

  • @hidemat5141
    @hidemat5141 3 года назад +2

    Could we get a tutorial from scratch? Regardless, thanks for this. Nice vid

    • @ThisIsVini
      @ThisIsVini  2 года назад

      Thanks. What do you mean from scratch? Including the planning logic? I feel that one is better to check the code for it. I added a bunch of comments to make it easier to understand.

    • @hidemat5141
      @hidemat5141 2 года назад

      @@ThisIsVini Cool. I'll look at the code. Thanks.

    • @charg1nmalaz0r51
      @charg1nmalaz0r51 2 года назад +2

      @@ThisIsVini he probably means seeing it implemented. I often find it best to learn to see how someone is arriving at the decisions rather than it just being put out there with comments. You would not believe just how much you can learn seeing it done in real time rather than heres my code and this is what it does.
      So if you didnt mind doing a tutorial series of implementing it with commentary i know i and many others would appreciate it.
      otherwise fantastic video

    • @ThisIsVini
      @ThisIsVini  2 года назад

      @@charg1nmalaz0r51 that makes sense. Thanks for the suggestion. I'll consider it. Cheers

    • @charg1nmalaz0r51
      @charg1nmalaz0r51 2 года назад

      @@ThisIsVini you have any idea how to make these plans with data you dont know about. For example say i placed a building down that requires resources to build. I would want my plan to check a building is placed, what material from its requirements and for the next step of the plan to then know what this material is so it can check if its in the players inventory. In all the examples i have seen its assumed your only working with a small handful of pre existing data and if theres a procedural check its just to make sure a target isnt null. I tried something by adding in a function in the planner to perform a check which told each thing to add a precondition but i kept stumbling on the thing not knowing what thing wanted what item because its its own action.

  • @charg1nmalaz0r51
    @charg1nmalaz0r51 2 года назад

    I would love to give this a try, does anyone know of some good c# implementations of this, or some good step by step tutorials on this subject rather than a general overview. I learn better when i see the process take place rather than it being briefly explained.

  • @m0391n
    @m0391n 2 месяца назад

    I think it may be interesting, I created a GOAP sample inspired by this video, but in Unity. It is in the GOAP section in github.com/m039/CommonUnitySamples You can try it in a browser. I used the same goals (bonfire, hunger / mushrooms, fear / troll), but I've added procedurally generation and the house where a bot can store food or wood (and take from it too). You also can click on the bot and see all his properties.

    • @ThisIsVini
      @ThisIsVini  2 месяца назад

      Thanks for sharing. I don't use unity myself, but it's great to see other implementations. Cheers.