Drag and Drop ENEMY AI With Scriptable Objects in Unity

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

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

  • @clarencetinator3782
    @clarencetinator3782 2 года назад +12

    Dood I was literally making a game rn, and figuring out how can I use scriptable objects to organize my enemy ai behaviors . Then this video got recommended to me like youtube is reading my mind and I realized this video was just uploaded 5 hours ago lol . What's more funny is I just subscribed to you like 15 hours ago.
    Anyways, keep up the good work man !!

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

      Haha thanks! Let me know of theres any specific topics youre looking for

  • @mandamoon9149
    @mandamoon9149 2 года назад +4

    Bmo big brain 🧠 super helpful AI tutorial!

  • @FyresGames
    @FyresGames 2 года назад +4

    I've just used this idea to remake the AI in a game project. What we expected to take a month to rebuild. We did a working base in less than 2 days. Best idea ever to make modular behaviours. Old AI was over 1500 lines. The new one with all behaviours so far combined 260 lines.
    Update. We still use this system as base for our new Enemy AI, but with all the stuff we've covered we found out a few little limits.
    Pro:
    -Making modular AI behaviours easy to switch with another.
    -Specific behaviours for specific enemies.
    Con:
    -You can't use Async or IEnumerator in a scriptable object. They do work but for exemple 2-3 enemies die at the exact time, only one will trigger the Async or IEnumerator. You need to put them in the main script and use the the scriptable object behaviours to call it.
    -Start and update function doesn't exist in scriptable obj. Possible to create a ''fake'' update function called from the main script calling the update on the active behaviours.

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

    Great vid as always! This is my fave way to do AI in unity. You can also pass the target directly as a parameter. I also like to pass "context" (list of surrounding objects) as a parameter to allow boid like behaviors ☺

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

    You deserve so many more subs!
    Great video

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

    Honestly if I hadn't been subscribed already, that last bit would've earned it regardless haha! Keep up the good work and sense of humor! I have learned a great deal from your tutorials already!

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

    Thank you youtube recommended for this blessing.

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

    Showing love! 🔥🔥

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

    Thank you for the tutorials. Making my way through them all, including the occasional BMO "Ted Talk" videos.

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

    This seems really good! I will try it. If I want to create different behaviors and have conditions for switching between them, would you contain the logic for switching between states within each scriptable object?

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

    Thanks! I didn't think you could use those with AI.

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

    muito bom, justamente oque eu estava procurando.

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

    How do you make it that you want the enemy to go for an objective but if the player gets inside his range he go for the player and if the player ran (out of his range) he goes back to his objective?
    There is also when the enemy collides you can just push him back and it just does not chase you anymore.

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

    BIG BRAIN!!!!!!!

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

    Nice video! Thanks a lot for the tutorial, now my enemy becomes very flexible. But one problem tho, when I duplicate the enemy, all of the enemies suddently becomes very weird, but when I duplicate the behaviours, all of the enemy works fine. Is this becouse a behaviour act as all of the enemies brain? If so is there any way that I can make the enemy to have different brains without having to duplicate everything?

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

    Awesome.

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

    Does this concept replace the need for a State Machine then?

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

    I don't like this system because of the assets duplication (base script + scriptable object per single behavior), but I use scriptable objects for stats management and let machine states or behavior nodes do the actual behavior, that's probably a way less cluttered method if you don't mind dealing with code to "register" each enemy behavior in a dictionary so they can be found by a name passed in a manager class

    • @deseanteneves8026
      @deseanteneves8026 10 месяцев назад

      Would you mind explaining this to me? Im currently making an rpg and one thing im trying to figure out is how i wanna handle stats and other things ect.

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

    Once again another amazing video !?! I was just wondering if you have any videos on this... I have a pick up item (call it a perk) that give me a super jump automatically.... but I wanted it so u could scroll through different perks and then picking one to enable the super jump... if that makes sense.. kinda like a weapon list but for a perk lol

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

      Hmm not directly, you could modify something from my Powerup vid but Ill add this to my video idea list

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

      @@BMoDev thank you so much ! Keep up the great work love your content !

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

    Great explanation, only thing you probably dont want to do is the FindGameObjectWithTag() in the update. for me i went around this issue:
    by creating another function in my "Brain" and "ChaseBrain" scripts. i called it InitializeThink. inside the "ChaseBrain" i use this function to search for the player tag and pass it to the target variable.
    in Brain: "public abstract void InitializeThink(EnemyBehaviour behaviour);"
    in ChaseBrain:
    " public override void InitializeThink(EnemyBehaviour behaviour)
    {
    chaseTarget = GameObject.FindGameObjectWithTag(chaseTargetTag);
    }"
    inside "Enemy Thinker" i simply put "brain.InititalizeThink(this)" into the start function. so basically my InitializeThink is my ChaseBrains Start function now wich is pretty handy.
    in Enemy Thinker: "brain.InitializeThink(this);"
    of course you can do other stuff there as well. but its sure better than calling things every frame if we dont need to.
    i hope this helps someone,

    • @user-ts3rv5hb7u
      @user-ts3rv5hb7u Год назад

      Where does it take enemy behaviour as an argument

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

      @@user-ts3rv5hb7u it's been a while since i wrote this but I think it's in InitializeThink where you would give the enemy behavior as an argument
      I'm not a pro or anything but it worked for me

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

    good video, thanks. But, lots of using FindgameObjectswithTag and GetComponent in every Update call

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

      yeah was thinking the same, but thats something we can easily improve on luckily

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

    Nice video, however I really don't understand the difference with scriptable object vs regular scripts?
    It's just using an abstract class which we are inhereting from. This can be done using regular scripts.
    How is inhereting from scriptable objects different?
    (really trying to grasp it😂)

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

      Id watch the talk i have linked in the description it shows the advantages with scriptable objects over monobehaviors.
      These things can definitely all be done with regular scripts but using scriptable objects gives you better modularity/testability in a lightweight serializable asset you can play around in in the unity editor. Because its an asset its not confined to being in a scene at runtime like monobehaviors

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

      @@BMoDev thanks for the answer, I'll check it out :)

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

    Speedrunning Scriptable Objects Any%

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

    Neat concept, but calling GetComponent in Update makes my brain hurt (pun not intended). Don't do that if you care about performance.

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

    FindObjectWithTag in the update function? Do better! That should be cached on start or only run if not target it found.

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

    Interesting approach and one I might give it a try,
    I have to say though you do a GetComponent and FindGameObjectWithTag on Update which are both very heavy. It would be best to pass the parameters on Start to the Scriptable Object on its own parameters.

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

      You are 100% right. passing it in is good, storing target results in a dictionary for constant time lookup is another good option - the architecture is the focus and more important than the actual demo logic

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

      @@BMoDev yeah sure I know you were showing a demo and that part of the code was not important to Scriptable Objects. I feel, however, like it should be noted in case someone sees this it and tries to copy it

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

      You could do something similar to Unity Atoms (register the object with the tag and then have a static dictionary, so you can do something like this in your brain once
      AtomTags.OnInitialization(() => target = AtomTags.FindByTag(_tagToTarget.Value).transform);

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

    Running "find object by tag" inside "think" which is called every frame inside an Update function call? I don't see how this degree of abstraction is helpful (the example is too simple) and surely running gameobject.find on the update call of every enemy object is very wasteful? I just don't get it. I bailed at 7:30 once it became clear you were calling find so often - this could kill a game with lots of enemies?

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

      The abstraction becomes beneficial the more types of AI behaviors you have, the more behaviors you have the more you can tweak parameters that define those behaviors (e.g. you can use a slider in the inspector to determine the range before an enemy ai will chase the player, or the variance in accuracy when shooting at the player) these things can be done without modifying a single line of code, and can be plugged into different enemy types at will.
      In regards to the performance that's just a fault of me trying to keep the tutorial under 30 mins without fleshing out more of a system, and the intent was to showcase the architecture rather than the implementation.
      Calling GameObject.FindObjectByTag can actually be perfectly fine in update, given on the first call you store the results in, say, a dictionary giving you constant time lookup, and as long as you have a value that lookup will not be performed again.
      Alternatively, it could be completely unnecessary because you could actually pass in the target without needing to perform a lookup at all.
      All things I could have illustrated better and explained more - much of this will have to be setup for your specific game, so the deeper into an example I go the less general the information becomes