News › Forums › RAIN › General Discussion and Troubleshooting › Problem Understanding BT nodes
Tagged: AI, Behavior Tree, Nodes
This topic contains 12 replies, has 2 voices, and was last updated by Ibrahim 7 months, 1 week ago.
February 5, 2023 at 3:55 am #40014
I learned to build simple BTs that do simple tasks. But now when I tried to use BTs for my AI characters in the project I found difficulty building the BTs that will execute the behavior I wish to have. I have watched tutorials (all are very basic examples), and also read all the RAIN WIKI but still not able to build what I want.
My game is about fire fighting: For instance, I want my AI (Team Leader) to check if the game started or not, once it started, he should query the GameController script about the first situation to handle, once he get this answer, he should send a message to all Firefighters to go to the fire truck, and once they are all inside it, the fire truck should move to the situation, and then he should command them to line up in front of the Truck, and so forth.. querying about the game from the game environment, receive and send information to other AIs and do some actions.
Every other AI should also has its own BT, that controls his actions, receiving messages, doing actions, sensing and sending messages.
I have started with the following BT for the Team Leader, but I it really seems weak and not working as expected (because of not understanding the nodes rules and how the sequence follow from one step to the next).
<behaviortree version="1.1" repeatuntil="" name="FF_TL_BT" debugbreak="False"><sequencer usepriorities="False" repeatuntil="" name="TL_root" debugbreak="False"><constraint repeatuntil="" priority="" name="Game started? and there is at least one situation to handle?" debugbreak="False" constraint="gameStarted == true && numberOfSituations > 0"><constraint repeatuntil="" name="Far from situation?" debugbreak="False" constraint="distanceToSituation > 50"><sequencer usepriorities="False" repeatuntil="" name="sequencer" debugbreak="False"><action repeatuntil="" priority="" parametervalues="" parameters="" namespace="(global)" name="Send Message to FFs to go to FF Truck" debugbreak="False" classname="SendMessageToFFs" /></sequencer><parallel tiebreaker="fail" succeed="all" repeatuntil="" name="parallel" fail="any" debugbreak="False"><move turnspeed="" repeatuntil="" name="Move to my door in fire truck" movetarget="myDoor" movespeed="3" facetarget="myDoor" debugbreak="False" closeenoughdistance="" closeenoughangle="" /><animate repeatuntil="" name="animate" debugbreak="False" animationstate="Locomotion.WalkRun" /></parallel><constraint repeatuntil="" name="constraint" debugbreak="False" constraint="!ffDetector.active"><action repeatuntil="" parametervalues="" parameters="" namespace="(global)" name="Send message to FF Truck to go to currentsituation" debugbreak="True" classname="SendMessageToFFTruck" /></constraint></constraint></constraint></sequencer></behaviortree>
Any help will be appreciated.February 10, 2022 at 11:36 am #40029
Just letting you know I saw your post, I’ll be back a bit later with some possible solutions for you.February 11, 2022 at 1:11 am #40045
Ok, so let’s lay out an outline of what we need, and we’ll go from there. I’ll jump back on tomorrow and fill these out a bit more after I get some sleep.
So starting with the easiest, the fire truck itself. I would probably start really simple and assume the fire truck does only one thing, head to a destination. Well one main thing, it also gets a message telling it where to go, and then sends a message when it arrives at its destination.
root sequencer custom action (class: GetMessage) // new situation target message move (move target: situationTarget) custom action (class: SendMessage) // reach target message
I’ll come back and define what I think the message class should be like, but for now we’ll just assume it’s fairly simple and will assign any variables that we may need (depending on the recipient). So in this case it assigned our situationTarget.
Next up will be a random fire fighter, not the commander though. Again we’ll start simple, and assume the AI does only a few things: it idles, it gets in the fire truck, it waits until it gets somewhere, it gets out, repeat.
root sequencer parallel (succeed: any, fail: any, tie breaker: fail) custom action (repeat: until success, class: GetMessage) // get in truck message sequencer (repeat: forever) expression (expression: debug("Idling"), returns: success) timer (seconds: 4) sequencer move (move target: fireTruckTarget) custom action (class: SendMessage) // inside truck message custom action (repeat: until success, class: GetMessage) // move to fire message move (move target: fireTarget)
So they do very little fire fighting, essentially they just get in the truck and then get out of it. This is OK at first.
Last tree is the commanders, which will be issuing some of the initial commands to get things going. We’ll start simple with him as well and assume he is waiting for a command from some game component somewhere.
root sequencer parallel (succeed: any, fail: any, tie breaker: fail) custom action (repeat: until success, class: GetMessage) // new situation message sequencer (repeat: forever) expression (expression: debug("Idling"), returns: success) timer (seconds: 4) sequencer custom action (class: SendMessage) // get in truck message move (move target: fireTruckTarget) custom action (repeat: until success, class: GetMessage) // everyone is in the truck custom action (class: SendMessage) // new situation position message custom action (repeat: until success, class: GetMessage) // reached target message custom action (class: SendMessage) // move to fire message move (move target: fireTarget)
So this is still missing a lot, but that is OK. One of the key things to setting up a behavior tree is to start simple. So once we have a GetMessage/SendMessage setup properly, we should have a group of firemen, who get in a truck, drive the truck somewhere, get out of the truck, wait around, repeat.
I’ll be back on later tomorrow to add some more and fix any issues I run into. Gonna put this together with some spheres and a cube.February 11, 2022 at 9:34 am #40047
Thank you Sigil for this in-depth explanation. I really appreciate your effort. I also started to build my AI according to your guidance step-by-step.February 12, 2022 at 1:50 am #40048
I’ll have the next part up in a few hours. I put something together but I need to double check it before posting.
I put together an initial message class and updated the fire truck to match.February 12, 2022 at 2:43 pm #40054
So just an update on this:
So I started out (as is evident by my behavior trees) with this idea that the AI would message each other (similar to what you were trying to start with). This has quickly gotten fairly complicated and isn’t the way I want to go with it. The best AI I’ve put together is also some of the simplest (relatively speaking), so when things start to get complicated I tend to stop and try again.
At this point I’m trying to figure out where the boundary between the behavior tree and the game logic lies. The behavior tree tends to be good at making decisions and following through with simple actions, so I’m trying to work around that. I’ll post back when I have something more concrete.
You wouldn’t think a few firemen would be that complex, but it can quickly get out of control, unless you just script it all from one end to another. That is always an option, but that doesn’t scale well so I try to avoid it.February 15, 2022 at 8:30 am #40063
I always have difficulty distinguishing the boundary between the behavior tree and the game logic. Lately, I was able to implement your approach, and the basic behavior worked fine. However I have some issues:
1- Sending and receiving messages will be used often in my project, I do not know how to implement it correctly. For the time being, I have a class for each custom action, and in this sendMessage classes I update the variables values directly. While in getMessage glasses I check for the wanted value and if it is there, it returns success, else returns failure.
I believe it is not the correct way to do it, do you have any suggestions about sending and receiving messages using Custom Actions?
2- Truck navigation is not using the Navmesh I have!
Again, thank you for your help.
February 23, 2022 at 2:16 am #40105
- This reply was modified 7 months, 3 weeks ago by Ibrahim.
Hello Sigil, any updates?
I know you must be busy with other more important stuff. I just wish if you can explain a bit about the flow of the nodes, and how I should think about it when I try to build more complicated behavior.
Thank you.February 25, 2022 at 5:38 pm #40118
Sorry, got side tracked and hadn’t gotten back to this yet. I’ll take another swing at it tonight/tomorrow and let you know.March 1, 2022 at 4:49 pm #40140
Update on this: I have an example written up but I’m just going to upload the project instead of just posting code. I’ll also explain what I did and why. I don’t have it put together just yet (wanted to change a few names) so I’ll be putting it up later tonight.
I liked this setup enough that I’m going to add it to our starter kit. Some useful behavior trees and it shows how to work between custom elements and the behavior tree.
EDIT: Looks like I accidentally put this together with the wrong version of RAIN. All the code and Behavior Trees are good but I have to redo my scene, so I have to wait till morning.March 2, 2022 at 3:26 am #40142
I appreciate your effort. Thank you.March 2, 2022 at 1:59 pm #40145
Here is the package. Import it into a blank project and try it out. It is fairly simple right now but expandable and a good example of how to simply communicate between several AI. There are firemen, a firetruck, and a firecommander who instructs them on what to do.
I’ll be back later to update with a full post.March 4, 2022 at 4:18 am #40149
I downloaded the package, and studying it now. It is very helpful
You must be logged in to reply to this topic.