#gameplay-ai
1 messages · Page 77 of 1
I think Siggi mentioned something about being able to inject subtrees maybe that's something that could be used?
I have a complicated BT-based system on some of my NPC's, where the NPC's have a set of tasks and each task has an associated BT... The NPC runs a "top level" BT and if it goes into the "do tasks" part of the BT, it uses the task-specific child tree
The tasks are always ran through but it could be selected via utility score also
nice
(It generates them when the NPC spawns)
oooooo
Im just cracking into state trees
but ive been a fan of utility ai system for some time
I also have a newer ST based system which does something similar, but based on a shared task queue where the NPC picks tasks to execute from :)
thats cool
Blackboard for state tree? Could you be more specific?
You can create a BB comp in the AI controller, and create custom ST tasks which read values from it and allow using them from the ST
interesting
Okay
that seems cleaner than storing random vars on the character BP
Yeah it depends on what you're doing but it could be an option
You could in theory also use a custom state tree context to hold values, but it's a bit more involved
hm yeah hey
I think I will just store the variables in my aicontroller
state trees are cool tho, I like the hybrid design
its like best of both worlds
utility state selection, and rule based
I was trying to mash something up between STRIPS/GOAP and utility ai
and i think state trees are similar to what I was trying to do with that
maybe not exact but ye
Does anyone know how the navmodifiers work internally? I'm trying to figure out which part of the navmesh generation they slot in to, but I've only been able to make guesses. Like if I mark something as a null area, it properly erodes the polygons, but it never seems to call the erode part of the navmesh generation? Or where does it re-triangulate the polygons when a modifier is added?
when the nav modifier is added to the scene:
- its bounds are added to the nav octree
- the tiles affected are marked as dirty
- a rebuild is called for the dirty tiles
- new polys are created for said tiles
- nav poly flags (always for the area and sometimes for the poly) are changed
You can do a quick test to track all that down:
- in the level blueprint listen to some key input and spawn a nav modifier (you can just spawn an empty bp with a nav modifier component)
- set a breakpoint in FRecastTileGenerator::GenerateTile
- spawn the actor
When are you going to write a dang blog post Bruno? We need this stuff recorded.
It's taking me months of skipping morning gym to finish an article about our AI, then I might prepare a talk about it.
Next is the blog but... takes so long...
NavigationWizards.mp3
You ain't skippin' the gym. You're just gettin' swole with your brain muscle. 💪
XD
At some point I will post all this in a blog and share my neat flow graphs about nav generation
such an easy system to map
(irony off)
See, that's why it takes you months. You put effort into graphs.
that thing is my insurance. I can't rely on my memory
Hm this does not seem to be the case for navmodifier only navmeshes
ummm what? let me do a quick test
Then again maybe UE is trying to bamboozle me I'll try running it with performance off..
check setting a breakpoint in FRecastNavMeshGenerator::EnsureBuildCompletion
ah ok sorry I got things mixed up.
Set a breakpoint in ARecastNavMesh::OnNavMeshTilesUpdated and that will trigger. You can follow from there
you will end up in FNavigationDirtyAreasController::Tick
and this is the stack that happens before it due to pending octree updates (that's when the bounds of your modifier are added to the octree)
[Inlined] FNavigationDirtyAreasController::AddArea(const UE::Math::TBox<…> &, ENavigationDirtyFlag, const TFunction<…> &, const FNavigationDirtyElement *, const FName &) NavigationDirtyAreasController.cpp:135
FNavigationDataHandler::AddElementToNavOctree(const FNavigationDirtyElement &) NavigationDataHandler.cpp:237
FNavigationDataHandler::ProcessPendingOctreeUpdates() NavigationDataHandler.cpp:648
UNavigationSystemV1::Tick(float) NavigationSystem.cpp:16167```
Nice charts :D
And yeah it's pretty complicated. I managed to figure out how to create a custom navmesh
Basically in my game I needed to determine whether player placed objects are reachable by NPC's based on certain rules... I ended up doing a navigation query starting from a certain point and ending at the object. If it was possible to navigate, then it was reachable.
But this needed certain custom rules like what objects should be ignored for this query, which was separate from how they should impact actual navigation, so I needed to generate a custom navmesh for it :P
Okay yes it does call generate tile.. hmm my assumption was that navmesh modifiers don't regenerate the entire heightfield, but only modify the compact heightfield and re-tesselate from there
That I'm not sure. Never looked into it
ahhhh I see what's going on, I think I may yet be correct! When it generates the tile after a nav modifier moved it sets "regenerate compressed layers" to false, so it doesn't do the whole navmesh process, it just generates the navigation data
My theory is that navmodifiers don't do any erosion, they just expand the convex hull by the radius of the agent
That you know more than I do. I have no idea about the low level generation aside some stuff in the detour library. It's a pending topic for me
This was the bulk of my overhead. It's a spline relative position call that I run once per frame for every pawn. And was calling it again whenever needed in my tasks. Now I am just grabbing the cached value off the pawn and cut my frame time down to ~200-300us for each AI...or about 90%. Huge. I still want to optimize further though.
Curious how much efficiency could be gained by moving everything to c++. Any insight?
In my experience there can be quite significant savings from converting BP ST or BT nodes into C++ if they are being called often enough
Anything math related is way faster in c++
There are some videos about the topic
Watch this video presented by Enduring Games to find out the code that’s best kept in C++ versus the code that can live in the Blueprint visual scripting system in your UE projects.
Unreal Engine’s Blueprint system puts intuitive gameplay scripting tools in the hands of designers via a node-based interface. Flexible and powerful, this syst...
In this short test, I compare the execution speed of C++ and Blueprints in Unreal Engine 5 by running a nested summation function. The function computes the sum of numbers from 1 to N for each value up to N, measuring how long each method takes.
■ Blueprints are great for quick prototyping, but how do they compare in raw performance? Watch to...
That last one is off because that's in editor, which you should never use to measure performance. Bp's in Package builds are much faster
So having an issue which is when the player actor is moved elsewhere in the world the AI seems to on them moving still think they can see them when they cant any ideas what might be happening ?
If you are following it and the move to is to the player, the move to task re-adjusts the path to it
I found the issue I was having race condition
when I was trying to clear the sense target it seems in the same frame it was also setting it
adding a delay though for like 0.0 forces the clear of the sensed target to be nulled so all good
Tbh I almost always profile in editor lol
It probably isn't giving a good comparative time, but at least so far it does seem to tell me if my code is taking longer than it should even if it does have some editor overhead :D
is there a way where I can force the Nav mesh to be a bit more into the centre away from the sides ??
at the moment AI is taking the path literally hugging the wall
only thing I need to keep in mind is theres doors that well it needs to get through so I can't really quash it down and is there a way to do it where if they are chasing the player they kind of ignore the edge being off limits is a way
And just like that... I hate you. Hahaha yeah, it's true that for a general sense is ok. But very far from the reality of a build
You can add nav modifiers with null to your hallway walls
and then can I have it ignore them when chasing the player ?
bassically so the player can't hunker down near edge of the wall and it not be able to get them
anyone have and tips/ a video recommendation to make my ai move? now it just stays at the same place and wiggels 😛 the world is procedural generated like minecraft, so it wont stop expanding aslong as you run 😛
is there a way to add navmeshbounds to the player controller? or something?:P
Thanks. That's good to hear since a lot of my tasks are math based. AI needs to be as lean as possible since it's a racing game and I'm going for high fps.
No that's gonna be trickier.
arrr
You could could try different approaches. You could have another nav aganet defined with a bigger radius. Use that to patrol/move and the green one you already have to attack/chase the player
the other option is I make a system that has it follow points in the world and them points are places say in centre of cross parts
I think I tried a while ago another navagent cause I think I wanted say some of my AI to be able to use vents where as others can't but I don't think I could ever get it working
It's a but tricky because you need to pass the info to the move to request to choose the nav data you want to use, and that's only possible in c++ if I'm not mistaken
my project is cpp so I don't mind doing that just be a cpp task I'd have to make
Another option is to post-process the path to move it away from corners. Unreal has some functions for it. Also in c++
hmm i might try the first one initially and see how I go
if that fails I'll attempt the second option you've mentioned
Hey everyone,
I'm currently working on simulating a realistic daily routine for NPCs in Unreal Engine (Blueprint only).
Each NPC has a Schedule array containing structs (NPC_ScheduleEntry) with fields:
Hour (Integer)
Activity (GameplayTag)
I get the current in-game time via Ultra Dynamic Sky → TimeOfDay, and store it as an integer CurrentHour (e.g. 900 = 9:00 AM).
What the logic is supposed to do:
Loop through the Schedule array (using ForEachLoop).
For each entry: check if Entry.Hour ≤ CurrentHour.
If true, save the entry as LastValidEntry.
After the loop, use LastValidEntry.Activity to set CurrentTask.
** The issue**
Even though CurrentHour = 900 and the only schedule entry has Hour = 900,
→ LastValidEntry ends up being None,
→ so CurrentTask is never set correctly.
I’ve confirmed that the schedule array has the correct entry and format. I suspect:
either the ForEachLoop condition isn’t working as intended,
or the assignment logic is firing incorrectly.
Maybe I should use ForEachLoopWithBreak instead?
Any ideas what might be causing this or how to fix it?
(Screenshot attached)
Where are you saving it to last valid entry? In your first screenshot, you have a set node for it, but nothing is connected to the input pin
I'm gonna guess that that's probably the problem :)
A few games are already doing this 🙂 we added functionality recently to make this easier to do, take a look!
https://github.com/EpicGames/UnrealEngine/commit/d5b44e9281bdcebbbb9fc79f58259a7b1af633ab
As already mentioned above, BP call overhead isnt very noticable except on code you call very frequently like on ticks. I recommend Ari's talk here that goes a bit into and measure the exact overhead.
https://www.youtube.com/watch?v=S2olUc9zcB8
Watch this recorded session from Unreal Fest Seattle 2024 that uncovers the truth behind Unreal Engine best practices.
Are Ticks really that problematic? Should you make all your meshes Nanite? Is the ChildActorComponent truly cursed? Should you never use Cast?
You've probably heard many of these so-called ""best practices”. Check out this...
Did you remember to call Finish Task?
Yes, i changed my task a bit
now it looks like this, what is this green arrow?
now its stuck between 2nd & 3rd
Time to bust out the visual logger
yeah good point, btw
look at this, a friend of mine told me to hook both the On Success & the On Fail to the Success (True)
I feel like this is wrong
but my friend is really much more advanced so I thought this is a good practice
I mean, I wouldn't say the task succeeded if the moving portion failed - but that's just me.
(And probably a whole host of other people 😛)
the person who told me this uses it in all his tasks
Don't mean it is right
When the task reports that it is a success, even though it actually isn't, it can screw up the actual logic of the BT
Sequence - execute each task left to right until the first one FAILS
Selector - execute each task left to right until the first one SUCCEEDS
So - by you saying that every result succeeds - you will always move to the next task in a sequence, even if you end up in an invalid state due to the move to failing.
(I probably worded it weirdly, but the point remains)
what im trying to do is, make a chicken move in a more realistic manner, I was hoping of making this chicken have more complex logic, than just move from random radius to radius
like for example
- give birth to other chickens
- eat
- sleep
that's mostly it
i've heard of that
and yes I think its a good idea
This video is still relevant today
https://www.youtube.com/watch?v=iY1jnFvHgbE
In this presentation, Epic's Paulo Souza uses Unreal Engine's built-in AI features to build smart enemy behaviors for a game with stealth-like mechanics.
By relying on the Gameplay Framework in Unreal, we're able to quickly create convincing AI using Behavior Trees. Behavior Trees are great for creating complex AI that can be presented in a way...
Goes through the main AI tools
I saw this video btw
Watching and understanding are two different things
And I've read this documentation too, but still struggle to implement
exactly
Then you should've been able to tell your friend that he was wrong in his advice.
I dont undertand it until i actually implement it
Also for what it is worth - the far right sequence will never run.
I also have more problems than that 😂
my chicken doesnt look at realistic anyways even with the way it moves now
because of the animation blend space
and the model is just kinda OFF
I might need to first learn how to rig or something
but i've been on this for 1 year now
The chicken? Godspeed 🫡
My game is almost done in terms of everything else but the AIs
yes, and the bear 🐻 🐻❄️
which is the bad guy mostly
but I haven't set much logic into him, he just follows you around and gets in front of your face till you wanna break your monitor & keyboard with your head but thats pretty much it
yes at the moment it doesn't work indeed
do you think this will be easier to make with state trees?
somehow my brain is able to understand everything else & work with everything else just fine except for this AI programming related shit.

I hate AI programming the most out of anything in Unreal so far 😂 😭
Personally - I don't think STs are easier than BTs right now. But I may be in the minority on that. But I also don't think the tool is the problem.
they say STs are less complicated
Yeah, people like new & shiny things.
Here is my most recent gab about the two tools #gameplay-ai message
question about youtube videos, when following youtube videos that are not exactly always applicable like Ali Enzoheri's videos, there are over 20 videos in one of his playlists with 1 hour long videos each, he has his own assets, he often pulls his own little examples that have zero application to my problems, so there are so many videos made by him, not so much by other users, but besides that it's maybe even less than 5% of those things can be useful.
And most of the other videos on youtube made by popular UE youtbers are just the simple patrol - chase AI basic logic which they copied this from the official devs.UnrealEgine.com which is provided by UE documentation itself but they're not adding anything new unfortunately, most of the videos are kinda like this, and ytb is soooo limited in terms of AI programming😕
I'll give that a go tho, I think it now has more value to offer than I initially thought when I watched it few months ago
So uhhhh - what's the question? lol
oh I forgot to ask the question 😂 😭 😆
I guess no question, I guess thats it, just wondering how or why it is like that
seems like behavior trees have been around for so long too, almost as much as UE itself
kinda disapointing actually
thats it
🤔
BT has been around for at least a decade (at least in UE). As for why no one has done a good in-depth tutorial about it? Because the people who know how to use it are too busy working on games.
Applicable to:
- gas for Multi player
- navigation
- path following and detour crowd control
seems like 90% of those videos on youtube are just showing you how to make a car but not how to make the engine, let alone help you understand how the whole thing actually works 😂
Seems like digital era snake oils salesmen some of them videos
I watched a little of Ali's stuff because a lot of people praised it - but early on, he makes some mistakes that can easily cause problems. So I attribute his popularity more in his teaching style than content. He does do more than the average person who does a one-off video on AI though. I'll give him that. Like, he actually show off how he approaches doing ranged combat and stuff. As well as mixing everything together. So there is at least some exposure.
or maybe its mostly about the views & likes not really even capable of teaching you how to tie your own shoelaces or smth
As for all the other AI videos that just show you how to chase the player for the 82934298457259th time... 🤷
yes I think Ali is a little bit more experienced than the Gorka's of youtube
Won't find someone altering the path points in a YT video - that's for sure.
I've been wanting to do an actual in-depth video/series, just...no time for the level of quality that I want.
I even have my notes saved somewhere on my computer.
Plus - the general audience of YT doesn't want actual solutions, because they can be quite time consuming to implement AND explain. They want to solve their problem here and now.
If I ever start explaining stuff for the shake of giving back to the community, this is why I will never do videos. Good old GitHub tutorial with gifs and code you can copy and things I can correct if needed
I already did an attempt I never updated, so it's probably not accurate anymore. That was for a "simple" thing and took forever to post. Can't imagine posting actual complicated stuff
I realized despite tutorials saving you time in the moment, it totally breaks apart when you want to do something on your own
Yeah, that's learning in a nutshell
It is a bug from nav modifier which does not update nav mesh when actor is attached.
Attached to what? The player to the volume or what do you mean?
There is a spawner actor that spawn these collision actor at default transform and then attach snap to spawner. Nav modifier at default transform does not removed. It is reproduce on UE.
Not sure I follow:
- a spawner spawns the nav bounds volume at a default location
- snaps the nav bounds volume is then move to snap the spawner location
- a nav modifier volume is not removed.
But where's that nav modifier volume come from?
Sorry, Spawner spawn collision actor that have scene component as root, a box collision and a nav modifier component.
Then snap collision actor to spawner and observer that nav modifier does not clear at old location.
Ah ok, so the nav modifier is moved but the nav is not re-built upon moving it?
It is still re-build at new location, but not at old location.
Aaaah OK ok. That's strange. If you debug it, do the old tiles get marked as dirty?
As I debug, the nav modifier still report nav area at old location because child component not yet updated at that moment. I make a dirty fix by set timer next frame in UNavModifierComponent::OnTransformUpdated
In USceneComponent::PropagateTransformUpdate method, TransformUpdated is broadcast before UpdateChildTransforms that make nav modifier get wrong location of child component.
Is the nav modifier a child actor or a nav modifier component?
it is nav modifier component.
hiya!
im new to ai, been following a bunch of tutorials. im trying to do a simple third person ai that just sees my player when they are detected by the sight perception. i am running into an issue where the the player is nto being detected if they are behind some geometry that goes roughly to their waist.
i tried raising eye height of ai but that didn't really fix anything. any ideas? is the sight perception line tracing to the bottom of the player collider?
By default the trace goes to the actor's origin. The eye height is used as the starting point for the trace, but it doesn't impact the end point. To change the target, you need to implement IAISightTargetInterface on the actor being targeted https://zomgmoz.tv/unreal/AI-Perception/IAISightTargetInterface
@misty wharf awesome thank you!
I think it will be a good idea
btw my chicken ai was kinda working before
but I decided to change it once again just so that I can kind of learn how different things work by playing around
I realized that I still have no clue how this fucking TargetActor is Set works
or what it means
its a boolean, I get that,but where is this logic at?
I haven't hooked up any logic to it
so how is my editor gonna favor this one in some cases if the chicken for example sees the player
& then I can also add a BTTask_flee
for example the blackboard right now never gets activated at all
I still dont really know how this works either
but it kind of gets the job done (almost) but I still need to learn how it works because Im gonna need to add more complicated stuff in the future
Difference between (default)AI Move To Vector vs Actor? Move to vector is convenient but updating a moving target made me switch to move to actors (empty actors existing simply for moving navigation goals). Any insights?
state trees are so great! this robocop ai works so well now
Tho they can kind of be a pain to debug, even with the debug tools
It is a decorator. Pretty much, you will go into that branch IF the BB Key TargetActor is set (so not null). Otherwise, you won't. The logic for setting the TargetActor - that is somewhere else in your code. Typically it is handled by AI Perception. But that isn't the only way.
Hi Siggi: I implemented my StateTree Task like this
USTRUCT()
struct FStateTreeSetGlobalResourceAndDepositBaseTaskInstanceData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, Category = Context)
TObjectPtr<AActor> Actor = nullptr;
using ResourceNodeRef = TObjectPtr<AAResourceNode>;
UPROPERTY(EditAnywhere, Category = Parameter)
TStateTreePropertyRef<ResourceNodeRef> ResourceNode;
using DepositBaseRef = TObjectPtr<ABaseBuilding>;
UPROPERTY(EditAnywhere, Category = Parameter)
TStateTreePropertyRef<DepositBaseRef> DepositBase;
};
in the task's EnterState:
auto ResourceNodePtrRef = InstanceData.ResourceNode.GetMutablePtr(Context);
*ResourceNodePtrRef = ResourceComponent->GetCurrentResourceNode();
auto DepositBasePtrRef = InstanceData.DepositBase.GetMutablePtr(Context);
*DepositBasePtrRef = ResourceComponent->GetDepositBaseTarget();
I got a compilation error:
StateTreePropertyBindings.h(969,57): Error : no member named 'IsValid' in 'UE::StateTree::PropertyRefHelpers::Validator<TObjectPtr<ABaseBuilding>>'
My question is: how to set and get the global parameter of a object reference in the task?
Thanks a lot
Ugh I thought I was being smart implementing GameplayTaskOwner on a Behavior Tree task, so that the BT task could auto-cancel any gameplay tasks launched from it... but of course the interface's function aren't getting called 🤔
Man, this is kinda annoying. Looks like in theory it works - if you use NewBTAITask in C++
So I have kind of elaborate logic that I needed for my AI, and I put it into a singular BT task, instead of splitting it into multiple tasks... because it would've become kinda noisy in the tree, and making choices in the BT tree isn't very nice either, but I can just easily do it in regular BP logic in the BT node
But because of that I need to do more bookkeeping of any AI tasks that I'm running from the node which is kinda annoying :P
Would've been great if it would've been able to track those easily which feels like the whole point of the BT task being a gameplay task owner, but I guess not
if the bt task is the owner, doesn't it force you to have the task instanced?
Possibly yeah
It's currently implemented in BP's so it's gonna be instanced anyway :)
What kind of type is ResourceNodeRef? btw if the only thing you are using your task for is to get an external type, its probably easier for you to just use binding functions.
Property refs are useful for modifying properties that are already defined in the state tree (in another task, state or global parameters).
Thank you thats it!👌
Ok so in that case my BB key perhaps didnt work because I dont have any function made to handle that in the AI perception BP?
oh wait but I got this one right here
IIrc I followed a tutorial for this, kind of a weird setup
I thought there would be a decorator blueprint where those things would need to be set up
or a blackboard blueprint or something
So all of these things here will be connected exclusive to the AI controller?
does that mean I can also set up "services" tpye of functions or whatever in the AI controller and it will work as if im creating a service
and how will I know when those things will FIRE up?
I can make a million functions & corresponding blackboard keys and they will never function or work if they're not somehow connected to anythin g
Ok as I see it this is hooked up to an actual event here
but these are the only type of variables that can be hooked up to actual events
There is a lot to unpack here
As I see it I get certain events based on the kind of actor components I've set up here?
Decorator is its own class. You can create custom decorators that test some condition if you want. But Epic provides some pretty useful ones out of the box. Such as making sure some BB key is valid. Which is what you're doing right now. Making sure TargetActor != nullptr pretty much (might be an IsValid() check under the hood, but its old code so not sure)
Service is also its own class. You use them primarily for the tick support. So you can do things while the node is running.
These two things are for the Behavior Tree itself. Not for an AI Controller or pawn or w/e else.
When you communicate to the BT from outside of it, you will mostly go through the AIController because it has access to the blackboard. Other things can obviously get the reference if desired - but it is game dependent.
AI Perception is something unrelated to the BT - but it is often used to update values in the BB.
So you could use w/e you want to communicate to the BB (doesn't have to be the AI Perception stuff)
Im double clicking on these blackboards, and nothing opens up, I think i've seen that in youtube where the creator is double clicking on the blue & takes him to a graph
Because those blue nodes are in C++
You didn't write them
They're provided to you by Epic
You need to have an IDE up (and maybe the debug symbols?)
If that even works for them
But if you make a BP decorator and double click on it - it'll take you to that.
Im supposed to have a BP decorator here am I not?
Why?
because if not then how else will this selector work?
By making sure the TargetActor is not set (so set to nullptr in the BB)
so is it set or is it not set?
It isn't. This is just setting up the BB
wtf does being set mean here 😂
If it has a value
Your logic for setting it is currently being handled in your AIController
so how can I set it?
that means my blackboard is set up wrong
and it will never work, right?
What is the difference between State Tree and State Tree AI in components?
State Tree is generic and State Tree AI gives you the AI Controller in the context.
ok so I assume this is the node that sets up my blackboard value
are you seeing a character or are you not seeing a character
technically any other actors are also characters, so perhaps I'd need to set up logic to confirm if it's a player chaaracter VS if it's another AI character
I left the SpottedActor variable unconnceted so perhaps this is forcing the 2nd one to be forcible UNSET
it needs to remove the value to be correct on the 2nd one
This is how the BT will flow:
The selector will first check the first sequence node and see that it has a decorator on it. Then it will run a method on the decorator that performs the test (I forget what the method is called). If that test returns true - it will then go into the sequence node and start executing the tasks left to right. If the sequence successfully executes each task, it reports that it was a success and then the BT will start the process over again. If one of the tasks fails, it stops right there and starts this whole process over again.
If the decorator returns false, then the selector will go to the next branch (your middle sequence node).
Rinse and repeat.
I followed a ytb tutorial for this too. So I didn't know 100% what I was doing
Probably because they didn't explain it. Or glossed over it very quickly.
isn't it gonna stay in the selector first and follow all the selected pathways?
Only if the decorator evaluates to true. And then it'll follow the sequence logic.
ok maybe not actually, because selector only selects one thing, and then moves on to business as usual
Once the sequence does its evaluation, the tree repeats the entire flow.
so what are some other types of blackboard conditional variable examples that can be set up with this?
Just look through the decorators
are the possibilities unlimited or they are kind of forced limited to what the events are in this blueprint
for example for move completed, I can make a float variable
Those events have nothing to do with the topic
for On Instigated any damage, I can make an integer variable, on Possesses Pawn Changed I can set up an actor variable, on Actor Begin Overlap -> actor variable again...
On Clicked --> boolean variable
etc.
I don't understand what you're trying to convey.
but the decorators have to be connected to these events
can I set up these decorators outside of the AI controller?
There is no connection to be had
yes
I mean, blackboard variables can only be validated here, thats what i was asking
No
You can validate the BB variables anywhere
It is just a bag of variables
Grab one by name and test it
You just need access to the BB
The decorators are just there to be able to do tests.
So the sky is the limit on how you want to do tests
(Before Bruno comes in and ackutallys me - you can do more with decorators due to inherited functionality, but they're most often just used for test logic)
😛
You use one of the Epic provided ones if they fit your requirements. Otherwise, make your own.
Ok so in this episode of Myth Busters I've set up here on my first person character some keys, on the 2nd key its supposed to invalidate it, right? lets see how this magic works
Im pressing both but it's not really changing or affecting anything, perhaps blackboard chicken is invalidated, and I might need to cast it or something
The blackboard itself may be invalid
Ok Im pressing both keys
it's stuck on the Is Not Set
& waiting
Ok so for now I need to cast it
Im not sure how I should be doing these casts tbh
never worked with blackboards or chickens or whatever
I guess I'll do Get actor of class
It works but reallyyyy slow
I guess thats because it first has to finish the waiting time
which is very wrong
it seems like the wait is very unecessary or kind of breaks the natural flow of processes
perhaps I could be doing the wait through the Ai controller blueprint too, so that it can be later overrided by blackboard based variable
I'm following a tutorial on state trees, 2 years old, and when he creates override event -> Enter state, he gets a function. Whereas I just create a general event tick (in event graph). Which means I don't have the Return node with return value (succeeded etc.)
Where has this been moved?
this is his vs mine
I mean I could just use the state tree finish task node i guess, if that's the same. However I can't find an equivalent for the "Running" enum
Gimmie a bit - very busy. I'll recap and respond later tonight.
Wasn't "moved". It was changed entirely. They're now events instead of functions.
For it to return "running" - you just don't call finish task
One thing that I really hate about STs or BTs is that everything is inside of something else and its really hard to describe it to someone, it's not what you're used to when for your whole life for example you've been programmign in blueprint and then you come into BTs and they make it so in such a way that nothing is intuitive in the least intutive way possible
To be fair - you didn't know what "set the variable" meant. That isn't a BT problem.
Thanks for the explanation 🙂
'''
using ResourceNodeRef = TObjectPtr<AAResourceNode>;
'''
It is a object reference to AAResourceNode.(AAResourceNode is a subclass of AActor)
And Yes I have declared a global parameter in the StateTree.
This is the global parameters
And Btw, I need to use the global parameters of ResourceNode and DepositTarget to determine where the StateTree goes ("FindAndSetTarget" or "CollectAndFill")
Do we have any stat commands for the state tree?
another ai question...
the default ai sight collision channel is set to Visibility, but both capsule component and the character mesh are set to ignore trace responses on the visibility channel.
(using the third person template)
what is the "normal"/"common" way to have this setup?
Perception assumes no collision from trace == visible
So it should work with that setup
Never seen one but there is stats for sure i saw some in Insight
Thanks :)
is there a way for a recast nav thing to hold it's settings so for instance if I tick on draw poly edges and Enable Drawing ?
at the minute loading into different maps I have to toggle them two options on for the one recast nav thing
I don't understand what you mean at all.
What are you trying to do exactly?
so I have two recast in my world cause I have two nav agent types
showing navigation only shows one of then, for the other to show I have to enable following options
and the show poly edges
Aaaah yeah. That's shit. I had that problem in a project and zi needed up doing a console command to show one or the other
I was wondering is there a way for these recast to keep them settings so I don't have to keep going in to have all of them show when I turn on show navigation, it's fine if not
I think I can dig the code I did for swapping the debug. But I'm not at home. Will take some time until I sit down on my pc again
why is ai pawnsensing not working for me? it worked intially but now its just not working.
here's my code:
Hard to say, you need to debug it. Eg. add prints or breakpoints to help you see what is happening. In general, you should use AI Perception instead, Pawn Sensing is old and has been superceded by AI Perception
Man, I wish there was more information on how to best utilize gameplay and ai tasks 🤔
I've been debugging a bunch of issues in some of my NPC systems, mainly caused by the complex interactions between them and a bunch of other things
For example, there's an issue currently where an NPC has a "pickup item" AI Task, but due to the complex interactions with the game systems, there are some cases where another pickup task is started before the previous one gets finished or canceled (because it seems that BT tasks might not actually abort on the same tick)
but it kinda looks like with the right settings, the gameplay tasks component can actually handle this 🤔
I did some research and found that:
TStateTreePropertyRef<T>Parameter;
InstanceData.Parameter.GetMutablePtr(Context);
using the above code to set a global parameter of a StateTree in a custom task can succeed, Only if the parameter's type is one of the few basic types(int, bool, float, FText, FString).
I think this definitely needs to be improved.
Making accessing external variables unnecessary complex.
I havent had time to test your case just yet, but did you try any of the other PropertyRef variants? I know property ref has been used for actor refs in the past, and even the code docs has an example
` * // Reference to Vector, TArray<FVector>, AActor*, TArray<AActor*>
- UPROPERTY(EditAnywhere, meta = (RefType = "/Script/CoreUObject.Vector, /Script/Engine.Actor", CanRefToArray))
- FStateTreePropertyRef RefToLocationLikeTypes;`
I recommend you take a look at STateTreePropertyRef.h
So I'm trying to wrap my head around the new navlink builder functionality, but I think I'm missing something with how the navmesh generation works..
The navlink builder seems to run on the navmesh tile generator, what I don't understand is how can it generate links that span multiple tiles this way? (Which you can easily see is the case if you look at the navmesh in any decently complex level with this navlink generation enabled)
Hi Siggi
- Property ref allows to get a pointer to selected property in StateTree.
- The expected type of the reference should be set in "RefType" meta specifier.
- Meta specifiers for the type:
-
- RefType = "<type>"
-
- Specifies a comma separated list of type of property to reference -
- Supported types are: bool, byte, int32, int64, float, double, Name, String, Text, UObject pointers, and structs
For folks working with State Trees, would any of you be able/willing to share some documentation/tutorials that go over Considerations?
I have been using this document from Epic, but something about it is just not clicking with me and I would love some examples to look at: https://dev.epicgames.com/documentation/en-us/unreal-engine/state-tree-selectors-overview#considerationtypes
but if the type is TObjectPtr<AActor> then it is not supported
Yes, and did you have something not supported by those? An actor is a UObject
Maybe its a compiler/syntax issue, did you try using AActor* instead?
AActor* is Okay
So what is the problem then? 🙂 Just use that. Or ideally if you can, use a weak pointer
TWeakObjectPtr<AActor>?
yes
Oh it is also worked..
why TObjectPtr<AActor> failed?
Can you tell me a little about what you find confusing or what issues you are running into? We are evaluating some changes here for 5.7
Might just be a bug. Do you have the option to test in 5.6 ?
np! Hope it all works out 🙂 just remember that weak pointers can become null if the actor you point at is destroyed, so plan your code accordingly
okay sure
hello, How can I link my StateTree's Node to a linked asset like the picture below at runtime?
Thanks a lot~
Currently you need to create your own C++ base class and add the function, but they are here in 5.6:
https://github.com/EpicGames/UnrealEngine/commit/d44c23e4d18aa65d8bd2d3841ca66eb243e0391e
Thank you Siggi. you are Epic
Yes, I can try my best! I will walk you through the steps I went while trying to work with them and what I thought each step. If you want to jump straight to the question instead, check the bolded area.
1.) In the State Tree, I pressed the button for New Consideration, picked the base, saved the new consideration, and opened it.
Note: This felt straight-forward.
2.) Inside of the new State Tree Consideration Blueprint Base, I notice the EventGraph is empty, which tells me to next check the FUNCTIONS category to see if it is a blueprint where the functions are intended to be overridden. I see GetScore and GetDescription, and create overrides for them.
Note: After spending time with Unreal, this felt somewhat straight-forward as well.
3.) I check out the functions, starting with GetDescription. I see that it is as advertised, and just for putting a description. I then check GetScore. GetScore confuses me a little, but I keep seeing in the documentation that we are primarily working with 0 and 1, and as a float, so I assume it is like 0% to 100%. I create what I figure to be a simple test (see Figure 01).
Note: I suppose here I am confused on what is done with the Return Value in GetScore.
4.) In wondering what to do with the Return Value in GetScore, I decide the next step should be to add it via the Selection Utility for two Scenarios (see Figure 02).
Note: You can see how each Scenario is configured in Figure 03 (Scenario_A) and Figure 04 (Scenario_B).
5.) I run the test with the State Tree Debugger window open and take a sample to look at. I notice in Trigger Transitions, it outputs the warning "Could not trigger completion transition, jump back to root state.", where the intention was the have it go to TestWait.
Note: I assume this is not to do with Considerations, but probably the task, Debug Text, not returning as completed?
So what I am not exactly clear on, is the float intended to be sort of how weights are used? And if so, with both Scenario A and B are set to a Weight of 0.5f, how does the Weight get used after the Consideration is performed?
Thank you in advance!
bClaimRequiredResources = true;
AddRequiredResource(UKotAIResource_NPCAction::StaticClass());
ResourceOverlapPolicy = ETaskResourceOverlapPolicy::StartAtEnd;
Damn I think this just solved the annoying synchronization problems I was having with my NPC's
This makes it so that if there's an existing AI or GameplayTask running on the NPC with the NPCAction resource claimed, it just waits for it to finish/cancel before activating another - and it works with the latent node for gameplay tasks so you don't need to deal with it at all
Just need to use GameplayTask derivatives for latent NPC actions
I recommend reading up on Utility AI before going further, if you havent already. Generally a state is scored by combining the score of multiple consideration (one works, but is generally less useful). For example scoring range or health of target to decide the final score of the utility of attacking.
Then the state selector simply selects the state with the highest score and runs that.
Nicely done, it is simple
Yeah I knew the gameplay tasks component had a bunch of stuff in it but never looked at it in much detail other than seeing the comment that claims it has something to do with gameplay abilities lol
which it really doesn't
Gotcha, will do, thank you Siggi.
There are multiple GDC talks and books on the subject, and probably a lot of YT videos too 🙂 My favorite authority on this is Dave Mark.
ETaskResourceOverlapPolicy, this code is for UGameplayTask subclasses
Okay. Thank you 😁
I will dig into those right now!
I was curious what exactly does an AITask do on top of a GameplayTask - it turns out, almost nothing
void UAITask::Activate()
{
Super::Activate();
if (OwnerController == nullptr)
{
AActor* OwnerActor = GetOwnerActor();
if (OwnerActor)
{
OwnerController = GetAIControllerForActor(OwnerActor);
}
else
{
// ERROR!
}
}
}
// ERROR!
yeah its just a bit of added ai controller stuff, both gameplay tasks and ai tasks serve the same purpose: Tasks that can run async
Yeah
I think that the limitation is not whether the nav link is more than one tile away but how are the tiles set in the binary tree.
hm not sure where a binary tree comes into play here, my understanding was that the tile generator only runs on data based within the boundaries of a single tile
Based on FRecastTileGenerator::BuildTileCacheLinks at least
Maybe there's a step that occurs after that I haven't found
I'm super new to this feature and it's another team memeber the one that worked with it just Friday (he changed the code so we only generate nav links in tiles under special volumes placed by desigers), but looking at the code, looks to me that bGenerateLinks is enabled in every tile when using the tool within RecastNavGeneratior.
Then there's this step (image) where it seems to regenerate the CompressedLayers data if you want to generate links
So I guess the first time it will do the whole nav data, then only the tiles modified and, by checking the polyRef of the nav link end, it will also re-work the end-tile within GatherGeometry
Yes that's the flag you have to enable on the navmesh settings to enable link generation, its probably propagated to the tile gnerator
probably in FRecastNavMeshGenerator::Init(). I know some stuff is passed to the active tile generator in that function, like number of worker threads.
Maybe?
Sorry if I'm just guessing here. I'm trying to help you and me both. You are asking some few deep questions I also have myself but didn't have the chance to check
My guess is that, since all the tiles are marked to generate tiles, nothing really needs to be passed to the tile generator. It only needs to read data from the tile to know if nav link generation has to be done on the Pending Tiles (PendingElement in the image)
Ah, seems that this is also part of the equation
Yes that is the part I have been talking about
Since its within the tile generator, it should only have access to tile specific data, not neighboring tiles
I think it marks up portal edges for later processing though, I'm currently looking through the code flow
Yeah, looks like it just marks data like "hey, this nav link starts in this nav edge and ends here" for the linkBuilderConfig
An looking at it, it seems that this is where the tree limitation I was talking about comes into place (I know about it because I have suffered it). I thing the tiles need to be neighbours
Never mind. I think just marks a "this is where the nav link starts/ends" and that's it
Said limitation might not exist anymore (I suffered it in 4.27)
it would be awesome to know the difference XD
Between those types of configs? Jump over is probably akin to jumping over a bench or something and staying at the same height at the end of it
dtCreateNavmeshData is as far as I've gotten, I do think there must be a post process step to stitch together navlinks crossing tiles 🤔
my only guess is that the nav link data generated is stored in the general data (outside the tile generator) once it's returned and, upon processing the other tile (the end point of the nav link) the data is "stiched". Educated guess of course
Yes its definitely integrated into the data it returns in the create navmesh data step, however I haven't seen anything in the navmesh generator that implies a step after doing so
I don't think there's a step, just another TileGenerator for the End Tile. If you place a nav link in the level I think it's treated the same way a nav modifier is and both sides' tiles are marked as Dirty and tile generators are run for eache
then one tile generator will say "I'm the starting tile and this is the start edge", the other generator will say "I'm the end tile and this is the end edge"
And "somewhere" there's a common nav link identifier to grab the other edge when a nav link start/end is found during path finding
Why complex low level systems always gotta be unreadable 😢
beats me. If you have access to any AI (chatgpt free daily tokens suffice) you can copy/paste code and get a bit of general help with what the code does. I have done it for detour copule times as a sanity check
you can try this from a cheat
{
None = 0,
Default = 1,
SomeOtherNav = 2
};
void ACustomBaseRecastNavMesh::EnableDebugDraw(bool Enabled)
{
#if !UE_BUILD_SHIPPING
bEnableDrawing = Enabled ? 1 : 0;
#endif
}```
`void UXXXX::EnableDebugNavData(ENavDebugFlag NavDataIndex)
{
APlayerController* playerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (!IsValid(playerController))
{
return;
}
UNavigationSystemV1* currentNavSystem = FNavigationSystem::GetCurrent<UNavigationSystemV1>(playerController);
if (!IsValid(currentNavSystem))
{
return;
}
if ((NavDataIndex == ENavDebugFlag::None && CurrentNavDebugFlag != ENavDebugFlag::None)
|| (NavDataIndex != ENavDebugFlag::None && CurrentNavDebugFlag == ENavDebugFlag::None))
{
playerController->ConsoleCommand(FString::Printf(TEXT("Show Navigation")));
}
// this ensures we create the nav Render component without making it visible
currentNavSystem->VerifyNavigationRenderingComponents(false);
// This is the default recast nav data generated by our default nav agent type. We generate our own Recast object, derived from ARecast
if (ACustomRecastNavMesh* aiNavData =
Cast<ACustomBaseRecastNavMesh>(currentNavSystem->GetNavDataForAgentName(TEXT("Default"))))
{
aiNavData->EnableDebugDraw(NavDataIndex == ENavDebugFlag::Default);
aiNavData->RenderingComp->SetVisibility(NavDataIndex == ENavDebugFlag::Default);
}
// this is the nav data type generated from our other nav agent config. It derives from our custom Recast Data (ARecast <- CustomRecast <- CustomDerived)
if (ACustomDerivedRecastNavMesh* otherNavData =
Cast<ACustomDerivedRecastNavMesh>(currentNavSystem->GetNavDataForAgentName(TEXT("SomeOtherTypeName"))))
{
otherNavData->EnableDebugDraw(NavDataIndex == ENavDebugFlag::SomeOtherNav);
otherNavData->RenderingComp->SetVisibility(NavDataIndex == ENavDebugFlag::SomeOtherNav);
}
CurrentNavDebugFlag = NavDataIndex;
}`
this logic relies on you using different Recast Data generated per nav agent (which I guess is mandatory? I'm not sure, haven't been in a project with different recast objects in a long time)
okay I think I might have found it: dtNavMesh::addTile is called during EnsureBuildCompletion of the Navmesh Generator. I assume that gets called after all tiles have finished building.
There's a piece of code commented "connect with neighbor tiles" in there, that might be it
dtNavMesh::connectExtLinks specifically
I assume this is the reason we can't have links that span more than one tile, it just checks all neighboring tiles and connects the links if possible
ooooh nice find. Ok so my theory was comletely wrong. Good thing you trhow some facts there. Thanks a lot for sharing all this
No worries, yeah I'm currently looking at finding a way to calculate the full size of tile cache layer areas, however these are generated per tile.. So I need to find a way to connect these over multiple tiles to calculate the true area size (in case they are connected over multiple tiles)
What's the use case? Why do you need to know that?
Can't go into too much detail, but its similar to this feature described in mikkos blog around crouch areas (which was never implemented it seems) https://digestingduck.blogspot.com/2009/09/area-progress.html
You typically don't want small patches of "crouchiness" so you need to remove areas that are too small
Yeah I think there are very few or no games that have areas both the player and npcs can crouch under (without being simple enough to just have a navlink)
Anybody got any tips or pointers for how to handle AI being able to path in sublevels that are unloaded?
I am thinking, that say that we are loading/unloading parts of a level for performance, but still want the AI that was in that level to be able to get to the player into the currently loaded level
I assume the AI would always be spawned in the persistent layer, but how can I make it so that they don't fall through the ground and so that there is pathing still available
If you need them to "path" and the level isnt loaded, the only way you can really do that is to build a static graph or use something like ZoneGraph.
Basically simulate an approximation, and ideally without spawning the full actor. Then when the player gets closer and the level is loaded, you "upgrade" it to a full actor that navigates on navmesh.
I see. There might be a missunderstanding on my part about the frequency of sublevels needed within a map to where I am overcomplicating the AI logic and navmesh for this. I was thinking that essentially sectioning of smaller rooms into their own section, would allow for far better performance than just normal visibility culling, do you know anything about that?
Hello guys, I got a question here just out of curiosity:
"Object Reference" in the image, Is it a TObjectPtr or a TWeakObjectPtr?
TObjectPtr
I don't know if it's possible to explicitly declare/reference weak pointers in blueprints
Thanks a lot😁 . why is it not possible~~
Hey guys,
Any advice for a good architecture to create squad system for an RTS game?
@chilly nebula sorry for the ping but these Dave Mark GDC hour long each presentations have been excellent and are allowing me to pull together concepts from my other autonomous programming work for concepting AI in UE. Thank you again so much, these are exactly what I have been wanting for a long time, and makes sense I could not find them since they aren't on youtube to my knowledge!
Im very happy to hear that, glad you are enjoying the talks! Did you watch the "Making a better Centaur" one?
huh I never heard of ZoneGraph until now, looks very interesting.. It looks like its been experimental since 22? Is it still being developed?
Its not being actively developed, no.
Can't recommend that talk enough too
I started it, but he quickly mentioned he recommended people watch Architecture Tricks Managing Behaviors one first, so I pivoted to it to cover that material before returning.
Hello,
Beginner with AI here,
I'm trying to make my AI Move and shoot at the same time with StateTree
I use the same Task to do it with Event Start -> Move To Location
And Even Tick -> Shoot at target
But it seem's that when the AI is in MoveToLocationOrActor Node it lock AiLogic until he reach the destination point is their a way to bypass it ?
If i uncheck it in the Blueprint he just stay in place and shoot.
Two tasks (any of them is asynchronous) in the same state execute concurrently
If you uncheck lock ailogic box
You could put the 2 tasks in 2 states and trigger the transition to shooting state when arrived
Btw there’s an excellent explanation of the execution of state tree tasks in the sever
And I quote
If Task_A finishes immediately and you want to use the result in Task_B,
The problem can be solved by simply placing Task_A and Task_B in the same State and giving Task_A a variable whose Category is Output.
But this can only be used in the limited case where Task_A terminates immediately.
It's much more common for this not to be the case, so I'll write it below.
If you need sequential tasks, where the next task uses the result of the previous task, you can do the following:
- Parent
- Child_A
- Child_B
- Let Parent own StateParameter.
- Child_A updates the StateParameter of Parent. Once the update is complete, Child_A will transition to NextState.
- To do this, Child_A's Task must have
TStateTreePropertyReforFStateTreePropertyRef.The built-inFStateTreeRunEnvQueryInstanceData::Resultis a good example.
- To do this, Child_A's Task must have
- Child_B uses StateParameter of Parent.
Learned a lot from it
Thank's, I've split the task in two as you said and running them at the same time seem's to have fix the problem 🙂
Hi everyone. I've been working on implementing Sekiro-style AI using State Trees for a while. State Trees work well for handling combos and their transitions, but I'm running into trouble when it comes to logic involving timers, counters, and interrupts. For example, I want the AI to do a turn-around attack when the player is behind them, or trigger a sweep attack after the player blocks successfully a certain number of times(and then maybe dodge back and idle for a few seconds). These kinds of reactive behaviors are hard to represent cleanly in a State Tree. Any advice or thoughts for handling this type of combat-heavy, condition-based AI?
Hello everyone.
I struggle recreating the bad AI system that i had and i don't know how can i switch between :Idle ,Move To Arena,Strafe,Move To Portal states
how is the best way to switch between them?
I had an enumerator with this states and used it in the old system ,but i don't know if this approach is good or no
The selector works but i have no idea how to implement the states below
and also when i tried to connect this one ,it made by default the idle state,and after finishing the monologue,it was stuck at root
Counters and timers are best to setup as parameters either on a parent state that wont change (ie Combat) or global, and pass them in as ref (see discussion on TStateTreePropertyRef above) to a task to modify/refresh them. Then setup a condition to check their value.
"Check for number of blocks" can be done that way, with a task that resets the counter on a failed block/parry and another to increment.
Timers can be set as time stamps, so when you enter a certain state you save the current time, and in your condition you check if current time is higher than saved timestamp + whatever time you want to wait.
Interrupts can be done with a transition with a condition, but you might need to do some of that as a ticking transition. 5.6 is bringing new features for better async tasks that could help here.
Hello, I'm trying to make so that my AI patrols along a spline following the CurrentPatrolPointIndex. However, I want it to pick the closest point when it starts patrolling. E.g., if it leaves the combat, I want it to pick the closest one. If it finished moving towards one patrolling point, and tries to pick the next one, I do NOT want it to pick the closest one, but use the one in the CurrentPatrolPointIndex.
I have patrolling as a separate BT for ease of use. I thought about using something like a service or a decorator to check whether the BT has switched to something else, so that I can pick the closest point. However, all the ReceiveActivationAI, ReceiveExecutionStartAI etc seem to be called anytime I start executing the patrolling BT in general, so it looks like I can't achieve this using either service or a decorator.
How would you try to achieve something like this?
Is there any reason for AI not to go to this location even if i see that the wires are active and Portal location is valid?
I use similar logic to this one and it works fine
but this one doesnt work,why?
do timers work in BTTasks? Asking just in case.
Does the node run?
If you print the location (debug draw) is it actually a valid location?
yeah they work,cuz this one works
ill try it
Also check visual logger navigation and path following categories, let's see what the debug says
you mean the nav mesh bounds volume?
i hear the first time about path following categories and visual logger navigation
open visual logger, hit record and play your logic, then check the log categories.
If you don't know what visual logger is, there are lots of info online about it
cant figure out what's wrong, everything seems to work, judging by string prints, but enemyai actor doesn't go to "covers", it just stands still
there is NavMesh btw
Ugh, why can nothing with AI ever be simple lol
It just occurred to me that I need to support resuming smart object behaviors... because if the game is saved while an NPC is using one, it needs to be able to continue what it was doing when loaded
Is that blue sphere your locatiom to go?
This is the kind of things we would force a designer to change hahaha
I was just about to say - "just uhhh...cancel it"
heh
I solve all my saving issues by just not saving 👍
Yeah I mean majority of my SO's aren't going to have a problem with that I think, but I have some which might
I already limit saving to certain points because of this kind of things, but it's going to be problematic to cancel it entirely for some 🤔
They would still need to keep track of what they canceled and resume it
You can save the memory of a tree and restore it later. It causes issues with nodes that clean memory upo exit (we don't restore engine ones, just ours). If you track everything in the BB, it's even easier
I'm using custom gameplay behaviors insteado f BT's because some of the behaviors would probably be pretty annoying to model in BT's with all the logic and choices :)
But I think I can make it so that if an NPC tries to activate the SO again, the SO can detect from its own internal state that it needs to actually do something slightly different
it's kind of a faff I wish I didn't have to save but it's the kinda game where that can happen :P
the blue sphere is nearest cover location for the actor
not player
btw
seems like hes moving
but very odd
why doesnt he use other covers?
these
Hello, is there an easy to way to randomize one of the three tasks in a selector? I want a way to randomize my AI actions, like strafing, guarding, making a thrust or a slash, or any other type of attack randomly, and with a little bit of weights depending on the environment and the type of target it's facing
You need to build some kind of utility composite node. There isn't anything out of the box for BTs. But there is something for state trees.
The thing is that you can't create your custom composites since 5.4
There are also 3rd party solutions that have it already.
Iirc there's an example of creating a random or utility BT composite somewhere on the internets
For instance?
I have made that in 5.1, but now that I'm on 5.4 it doesn't compile
Classic Epic just breaking shit cos they forgot an API macro
And even rejecting the pull request to fix that
Probably just the bot closing PRs that nobody bothered to look at
But what 3rd party solutions are out there?
oh, so should I try to re-open it?
Ones that have a utility composite node or decorator.
Maybe, but it might just get closed by the bot after no human looks at it :D
hmm actually
AIMODULE_API virtual void InitializeMemory(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTMemoryInit::Type InitType) const override;
AIMODULE_API virtual void CleanupMemory(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTMemoryClear::Type CleanupType) const override;
this is what the functions look like in 5.5
maybe it was done?
It's past .1 and .2 so it seemed fine to me so far :D
Alright, I'll try it out, thank you for letting me know that they have fixed it
He y there
I’m working on a UE5 project where NPCs walk on a spherical planet, using custom gravity to stick them to the surface. Orientation and gravity are functioning great, but I’m stuck on getting AI pathfinding to work all around the globe.
i can only generate nav-mesh at the very top of the sphere, everything else is considered too steep (or otherwise unwalkable).
Has anyone successfully wrapped a UE5 NavMesh fully around a sphere?
That sounds like an enormous amount of changes you'd need on the generator code and everything else 🤔
Damm, i jsut saw some plugins do it but they are really pricy
You could try your luck emailing the plugin author :)
Yeah, but is it really that imposible
Maybe there's some other solution to it, at least if the navigation isn't necessarily that complex
Eg. you could maybe generate points manually on the surface of the sphere, and navigate using those instead
Thanks, i might try something like that 🙂
but how can i make the ai move without using ai move to
the move to location or actor doesent seem to work
You'd probably have to build a custom solution to steer it towards the points
shit okay thank you
This one was closed since it was already addressed in another CL 🙂 before creating a CL, always check the latest version of the codebase
Oh yeah, I definitely should've
Are you projecting that location onto the nav or passing it straight to the move to node?
second
Can anybody help me, i dont udnerstand why this always fails to move?
https://blueprintue.com/blueprint/-9_pv_ea/
The map is on a sqhere. The youtube video said that it would work on a sqhere too. THis is the youtube video https://www.youtube.com/watch?v=TtEZrKM4Ue0
Thanks 🙂
Then that's probably your problem. That pint is very far from the nav. Use the project point to nav node and pass the result point to the move to node.
Let's see if I can unravel all the goodies @chilly nebula has been loosely advertising 😎
Looks like a toggle that we can do to have a task be evaluated for transition or not
I wonder if this is what Siggi was referring to when he said we could make the ST fully event based?
Its part of the puzzle yeah 🙂 also notice the "Any" dropdown there which is the same as the old default, but you can now also set the transition to only trigger when All tasks that are being considered are completed.
This + tick optimizations and scheduling, and the new task delegates and listeners (more coming for those in 5.7 too).
Yeah - I saw that too. Thought it was a little awkward of a placement, but not like I have any idea on where a better place for it would be. Or maybe there just needs to be like "Completion ....something" kind of text next to the dropdown. I just didn't mention it because you've already shown it.
Haven't looked at any of the new task delegates and listeners.
UI will continue to be improved 🙂 the delegates are opening up some new patterns that are causing us to rethink things on a bigger scale. You can basically create task graphs by chaining tasks together now.
I'll see if I can find those task delegates and listeners. I was mainly just looking at the BP STT stuff.
Siggi are you guys going by heart or following some paper/pattern for how/what you implement?
Found it
A lot (most really) of what we do is driven by something internal or a licensee we are working closely with.
How State Tree started I don't have the full picture of, since that was originally Mikko's baby.. but I know performance and scale were at the heart of that, and driven by City Sample demo.
I appreciate you Siggi. Just sayin'.
key thing about delegates is they are bound like properties. You setup listeners and dispatchers on your tasks, and then hook them up via the bindings UI.
Got it. So no payload is expected to be supported? Events should be used with those.
Undecided yet, its something we are discussing internally. At least not in 5.6 🙂
So now, what we can do is something like:
State A
- Child B
Have A run a task that has some delegates. Then B can listen for those delegates on the enter state method. And respond in kind.
Man I hate Discords formatting sometimes. But you get the idea.
So A could set up all the data needed for its child states and then broadcast the delegate when it is done.
yep! + you can setup so the delegate triggers a transition
Yeah - saw that too.
What we are working on now (related to the payload discussion) is how to best deliver result of an async task that signals completion.. like a run EQS task. There are some issues with the current approach that we want to improve
I'd imagine y'all have until like November 😅
Can't imagine 5.6 would be the only version released this year.
So, some quick impressions - seems like this is a nice self-contained way to handle more event-y stuff. Because outside systems have no access to the delegate stuff it looks. So Events would still be preferred if outside systems need to communicate to the State Tree
@misty wharf was it you who had issues with the RunEQS task and had to build your own? Sorry if Im mixing up who it was, from a few weeks ago.
We have some fixes in 5.6 for it (and the MoveTo) task, hopefully addressing the issue you had.
https://github.com/EpicGames/UnrealEngine/commit/c8c4f0baaae39b7b5664724911b9481405a38b42
It was me
ah ok 🙂 even better then
What was the problem?
For some reason - the data just wasn't being transferred.
So the EQS result wasn't going to the move to vector
A typical pattern we see is a ST task that registers to an external delegate and has an internal callback that broadcasts the task delegate. No need for events from outside
Thus causing the Move To to fail
However, when I wrote my own (using the BP EQS nodes) it worked perfectly fine.
Interesting, good to know if I happen to run into it
yeah we've identified a few issues around that, some are fixed in 5.6 but at least one is related to the thing I mentioned above with needing a payload. The issue is if you have a task in a child state binding to a parameter of an async task in a parent state, it might prematurely copy the bound value and not update it in all cases when the async task finishes.
This is probably a better approach honestly. I was just thinking of it backwards 🤣
This might be because of the BP itself or a Tick or State Enter or Exit firing and updating the bound value.
So, these three things - already 👌
Duro Im curious if you try to set up your EQS+MoveTo again in 5.6 if it works or not. If it doesnt, I really want to get an internal repro so I can be sure we'll get that fixed.
The tick scheduling and optimizations aren't something that are within my purview as I've not had issues with those before.
Will do. I'll do it tonight after my day job.
Basically anything that was ticking before will now automatically tick less, and only when it needs to 😉 + you can set lower freq ticks, or schedule the next tick directly. Like the delay task knows from the delay value when next to tick
I saw the wait for next tick or something just before I shutdown the editor.
But also - nice. Looks like we can employ the service pattern from BTs better now. (Controlling the tick rate was the big thing from it)
happy to hear that 🙂 I expect we will adopt more and more of the useful patterns from BTs even though the VM and general structure stays the same.
Minus the BB, I think that handles most (if not all) of the ways to set up a BT. Because we could already use "decorators" as an enter state conditon. Replicating Services just needed to be able to control tick frequency. Because they're essentially just a task that ticks with some safeguards (which can be handled with the enter/exit state stuff). And to get the sequence logic, it is literally just having states transition to the next state on state success.
And selector logic is enter conditions and/or transitions on failure.
yes, or you can chain tasks together to run in sequence.. but we need to improve our debugging tools to better support that 🙂
Can the tasks listen to delegates from other tasks on the same state?
Dont forget you have state selectors in STs, but perhaps writing custom ones isnt as easy as it maybe could be
yes
Well, I did forget. So there is that.
I think the only requirement is they appear higher in the list.. the task order matters from the binding perspective.
That is fine by me and makes logical sense.
There is nothing preventing you from setting up a whole task hierarchy inside one state now, ie a state that triggers 2 other tasks, and those trigger X many and so on and on...
Only downside Im aware of atm is the debugging tools dont show this very well
That would be hell. But nice that it is supported. Does this mean that y'all guarantee (at a minimum) that the Enter State function will be called sequentially?
<@&213101288538374145>
I dont think there is anything currently that sets that up, but that is a good point. However with the bindings going through property binding it should work, unless you have some init dependencies between the tasks?
I'm just thinking of a situation where, let's say Task A has a delegate and Task B has a listener. Task B needs to, on Enter State, set its callback method with that Receive Callback (or w/e the BP node was named. Only looked briefly) to some function.
What happens if Task A broadcasts the delegate on like the 3rd node call in the enter state function. IE - Enter State -> Do something -> Do something -> Broadcast.
As I type this out, this has nothing to do with what I actually brought up with sequential Enter State calls. So ignore I said that part 🤣 (because it would still fail)
The issue being - task B hasn't set up the callback function yet, but task A already triggered the delegate.
Mind you - I don't know if the listener property has a way to bind to a function in the property bindings part. I only had time for like 5 minutes of snoopin' around because I had to get back to work.
I'll have to check if this can happen, but I think its unlikely that an external async callback will fire before the rest of the tasks can run their Enter State. If so, I think the processing order will take care of that and not process the task delegate broadcast until after all the OnEnter have run.
That is one of the race conditions that come to mind with the sequential task setup you described.
Hi, new to State trees and wanted to ask what’s the best approach to handle two different enemy types (range/melee with distinct tasks for each). Does a single AI controller with two states trees make the most sense? If so would you override the trees or just destroy the ST component and re-add that component with a different set on the controller when possessing? Or just one big state tree, and inside each task check what enemy type it is and execute the fitting attack?
I think you could watch the video Siggi recommend
Im very happy to hear that, glad you are enjoying the talks! Did you watch the "Making a better Centaur" one?
..?
Did my tests - works now. Only as a sibling state though. Which is perfectly fine. Still doesn't really work all that well in the situation you described about child state binding to an async task param in the parent. Thanks for looking into this though! 🥳
Please watch this video
For heat you need to do you don't need infinite axis utility AI, which is what that video explains (or any kind of utility AI for that matter).
A common approach is to have a melee bt (or st in your case) and a ranged bt/st. Then each type of enemy uses the appropriate one.
Within each tree there will be concepts like "approach location/target", "attack" and others.
Inside said actions you can then plug in sub trees (linked trees in the case of st's) and have custom behaviors for each unit sub-type. Ie: a sniper ranged enemy will behave differently than a shotgun ranged enemy. When looking for a shooting location, the sniper will move far and behind cover while the shotgun will move closer to the target. That would be the "approach location" part.
When attacking, the sniper might aim, shoot, reload, repeat and the shit gun might just aim, empty the shotgun (2 bullets) and reload, being the reload much longer
The trees will look the same within a type, but the execution of the parts will be different and held in a different tree
That's a common approach
You could even have one general tree for all, but usually ranged look for cover points, try to pisition themselves out of the way of other ranged enemies etc. Their bt's are usually a bit deeper than melee
btw I followed up on your race condition scenario, and it can indeed happen currently.
Hi, i'm currently trying to build a realistic daily routine system using Behavior Trees, where the NPC walks to a bench and sits down.
Setup:
A Blackboard Key (BankLocation, type: Vector) is correctly set at runtime.
The NPC has a Sequence in the Behavior Tree that contains:
MoveTo → target: BankLocation
BTTask_PlayInteractionAnimation → should play a sitting animation
Problem:
The NPC walks toward the bench but stops shortly before reaching it.
What could be the issue?
Use smart objects for that
I don't see the stop you mention.
What I see:
- approaches the bench until the capsule touches it
- plays the animation (which for some reason is making the AI go away)
yeah that makes sense 🙂 if you trigger a transition to a sibling/child state with the delegate the result data will be updated once you enter the new state. If you have a task in the same or child state registering to a delegate on a task in parent state, then the result data wont be updated in all cases when the delegate triggers listener code in the child task.
@slow bobcat i checked with the visual logger and here is the message it wrote
I hope you have some intern doing UML graphs for documentation about this flows. Us peasants will consume them eagerly
Yeah. It can't project the point to the nav mesh. It's probably too far or not so far but you are not passing a good projection extent
its because of the collision or i need to rise it a bit ?
I see this as a bug that we need to fix, not something that users should learn 🙂
your door is affecting the nav and creating a hole in it. The point is within said hole and you are not using any extent (allegedly) to project that onto the nav.
Project the point onto the nav and use the result in the move to node.
Or you can set the bCanAffectNavigation flag to false on the door (might cause other issues like AI's getting stuck when the path goes throuhg it)
ah fair enough. Missed the bug part (catching up with the Durox conv)
yeah i succeeded,just added a billboard component on the teleport actor and used it as the location
Thanks for introducing me to a new tool
the bildboard component is not going to work in a build. That's an editor only component. I suggest you use a scene component
Thanks for the suggestions. I tried setting up two ST’s in the same AI controller but can’t seem to get it to work- any idea if it’s not something that can be done with BP?
Edit: Yeah, looked it up a bit and unfortunately seems like you can’t set a state trees on runtime.
Found this, I’ll give it a go:
https://github.com/gamedevkirk/UnrealEngine-ExtendedStateTreeComponent
Rather than setting 2 ST's in the AI controller, you can just set the one based on the enemy type, make it more data driven.
You could do this on Posses before running anything else I believe.
The StateTreeRef is protected in the State Tree Component.
You could have a child of the component with a SetStateTreeRef being called OnPosses before calling the Super:: part of it that callls InitializeComponent() on it
hahah ok, just opened your link. Yep, exactly that
Haha yeah thanks for the confirmation
Really wondering why Epic isn't providing a native implementation of it
But oh well 
Because it's very dependant on how you initialize things. If you were to swap the tree at some point, you will need to call the init functions again.
One thing you can do is just have linked trees in your main tree and use those depending on the enemy type
I think that's the idea in general: rely on linked trees
In our game we have the State Tree Component running several trees because parallel tree didn't exist and linked trees where a bit messy.
I wanted to use linked trees but I just couldn't find solid documentation in the engine for it
the code is your documentation
well I'm trying BP first when possible.. and going to the online UE documentation to look things up
But realistically lots of times there jut aren't any
I think this code could be implemented by blueprint
.
I also implemented the similar code. I think I was just coping the blueprint version of it
I wasn’t sure. It was weeks ago
We do, in 5.6 🙂
Is it auto-handled? What I mean is: does it Initialize the tree etc?
void UStateTreeComponent::SetStateTree(UStateTree* InStateTree)
void UStateTreeComponent::SetStateTreeReference(FStateTreeReference InStateTreeReference)
Hi look at that, I just got a 5.6 preview notification 😄
Lets fire it up and see if these sweet ST setters are there
😉 yup Preview was just released, enjoy!
I was wondering if it is bad practice to have a loop in a state tree where states are selected by tags that are set in a selector state within the loop.
I could use the Selection Utilities here, but I specifically want those states to be used based on cooldowns, timers, distance etc.
They are. When I originally wrote my own (all you had to really do was inherit from the component and then make a public function), I asked myself the same question. Then looked at ue5 main and saw that it was there. This was some months ago.
And I followed up on the tick frequency thing. I was expecting it to be settable per task - but it looks like C++ only? Because I didn't see way to alter it in BP.
Unless I'm more blind than Ray Charles.
There is a setting for the tick behavior (scheduled vs something else).. I cant remember the exact name or where that setting is, maybe it was on the state itself? I can check later today once Im out of meetings
btw the 5.6 roadmap is up 🙂
https://portal.productboard.com/epicgames/1-unreal-engine-public-roadmap/tabs/124-unreal-engine-5-6
Yup. We've been talking about it in #programmer-hangout
Looks like my exploratory stuff hit all the stuff that is coming for STs
And the main focus, gameplay wise, was ST and Mass for this release.
I dont see a problem with that 🙂 but since you need to set the tag (presumably in a task), is there a reason you aren't using transitions instead?
Mover 2.0 got a lot of improvements too 🙂 + gameplay cameras and other stuff
Doesnt mean there was no work done 🙂
Oh, definitely not. I'm not including stuff like the async streaming stuff for world partition or the zen improvements or the motion design stuff or anything like that. I was talking strictly about the gameplay framework section.
This got me excited. Maybe next game...
And all the new stuff for level streaming and data layers looks awesome too
Yeah - maybe this is what is needed to get the gaming community to stop calling UE the stutter engine 😅
But it won't be realized for awhile. Because I think games are still mainly releasing on like 5.3 and lower.
Using transitions instead seems to work well and makes the inner loop look cleaner
Tbh The stutter issue is on the dev side more than the engine.... That said, the engine doesn't make it easy to improve it
Well, yeah - but that doesn't mean anything to the end user.
To them - because so many UE games are plagued with it, it is the fault of the engine.
Fucking gamers. They ruined gaming. Games should be done and then kept within the company server XD
You should link the talks to be honest
If they've proven to be so useful
Then we can bother the mods to pin it
@chilly nebula I finished these three talks
-
https://www.gdcvault.com/play/1012410/Improving-AI-Decision-Modeling-Through
-
https://gdcvault.com/play/1018040/Architecture-Tricks-Managing-Behaviors-in
-
https://www.gdcvault.com/play/1021848/Building-a-Better-Centaur-AI
I also took notes, about 16,528 words with some drawings haha
Wrap them in <> to not have the embed pics
These really filled in the gaps for what I was missing. They also allowed me to tie together a lot of my current systems, at least conceptually, since I was building with the intent of modularity from the start.
So thank you
and thank you Duroxxigar for the tips there
<@&213101288538374145> Can we get these talks pinned?
honestly? yeah. AI is a ham beast, and I feel as though it should be required learning
Happy to hear you liked them 🙂 if you want to go deeper, Dave Mark also wrote a book on the subject.
For State Tree we have a utility based selector, and are looking into some improvements for 5.7 so I'm looking forward to your feedback if you decide to play around with that.
how to open this window in Learning Agents Interactor? I dont have it
nwm, I found it in "window"
it was hidden by default for some reason
where can I find good q-learning tutorial for ue5.4?
grok, chatgpt and gemini have very strange info about learning agents plugin, it doesn't stick with reality
You'll probably have more luck in #generative-ai
idk if this would be interesting to pin for new state tree users
notes of the basics of state trees with a list of other talks about it (most of them comes from the 2024 unreal fest)
https://notes.hzfishy.fr/Unreal-Engine/AI/State-Tree
Hello , i'm trying to have my AI to move Physic Item to hide behind it what would be the best way to do it ? Put Tag on mesh able to move ? Overlapping Event with Collision on the AI ? any idea ?
Hello Ive been playing with AI and UE5. Well Im thinking that AI is actually the one playing with me. :/
do you mean like opening a door and hiding behind or flip a table and use it as cover?
Thanks a lot!
i think this is the best channel for this question
how did you guys resolve problem of dealing dmg through walls? i mean case like melee AI attacking with long sword/hand whatever, how do you check if the dmg should be dealt or not?
trace from hand to dmg place to check if there is wall in the middle is the easiest solution, but i dont belive its good or safe, and may cretae more problems than solutions, so what other options did you try?
I'm assuming the reason for this in the first place is that you're using some kind of overlap check which just ends up going on the other side of a wall because of its size -- to me it seems you could do a linetrace from the actor to the point that was hit, and check if something is between them. This seems like it oughta work, although I've not faced this specific problem myself.
In my opinion there is not really a good simple solution to this if the thing you trace from can be inside of the geometry that you consider blocking
My dumb idea would be to just trace from inside of the movement capsule against things that block movement in order to have a better chance of starting the trace above a surface rather than inside of it
Flip a table en use it as a cover
I woiuld look into smart object, they are designed for that kind of stuff. You can claim the table, play the anim, reposition the AI etc
you could always keep overlap for damage in one collider and have another at the same location with the same geometry (let's say a capsule) that does physics collision block against walls, furniture etc (basically anything in the Static channel). The sword will not pass the wall. You can only enable the physics collison while the AI is doing the attack animation and disable it later (or as soon as it applies damage)
thanks for ideas, will check them again
+1 on what people said above 🙂 Last I dealt with this problem was exactly this, a trace from "eye level" location within collider capsule to impact point to verify "reachability" of the point being hit.
I absolutely will. And I will see about getting that book, he seems to be a good teacher.
I could be testing this wrong... But I am confused.
Version UE 5.5.4
"I do not sense the Target." behavior = Try Select Children With Highest Utility
Screenshot indicates neither Idle nor Patrol have Considerations added to them, but the weight is adjusted for each.
I imagined that If:
Idle is set at a lower weight (0.9f), without a Consideration applied, that it would treat it like 1.0f*0.9f=0.9f
Patrol is set at a higher weight (1.0f), without a Consideration applied, that it would treat it like 1.0f*1.0f=1.0f
So by that logic, I would have thought it would default to selecting Patrol, never Idle.
However, it always picks Idle. Does this mean the "default" without a consideration is 0.0f, so then weights are multiplied against 0.0f, essentially zeroing them out, and since both would be Zero, and in the case of a tie, Try Select Children With Highest Utility would then select Idle?
I added a Consideration to both. A simple one that always outputs "1.0f".
I kept the weighting I had set, and now it selects Patrol every time.
Btw always look at the debugger, it should give you insight into why something is selected.
My guess is there might be bug where this doesn't work without a consideration, since they are very central to how the scoring works.
Can you tell me a bit what you were trying to do here, and why you thought the utility would work without a consideration? If you only have a static weight, it will always select the same path.
btw. if you just want a weighted random, there is a separate state selector for that.
Hi all, small question regarding StateTree - what is the current status of evaluators? AFAIK they were to be deprecated in favor of global tasks, but they are still in.
They are still there, we cant really remove them without breaking existing trees. They are becoming pretty much the same thing now.
Are there any cases where you prefer evaluators over global tasks?
Nope, just wanted to clear this thing 🙂
So i'm having odd issue where a AI Move TO node is aborting but I can't work out way
the place it's trying to go to is valid
so i think I've found issue it seem to be choosing a non valid Smart object
Hello, I've been using EQS queries in my BehaviorTree so that my Ai characters can find Actors of particular classes. Howver, I now have 20+ classes that my Ai might need to find and I feel like there must be a better solution. I want to pass an Actor class variable to the Ai character and have the character go to the nearest instance of that class. I've seen suggestions where I write a function in the character class to search for the class, and then (if I need to do more Ai stuff with it) pass it to the EQS as an EQS Query Context. Is this the easiest way to do what I'm trying to do? And a bonus question: is there a reason EQS Queries don't have an Actor input parameter? This feels like it'd be useful!
HI guys, Im new to unreal. New to state tree. Im struggling with a simple setup.
Idle: Move to Random Location > Wait for 1 sec > loop
Chase: Move to Player when distance to player is < 250 unit
Back to Idle: when distance to player is > 250 unit
From my animation gif has shown. When player is <250 unit. The AI does chase, But if I move out of 250 unit before the AI get to the player. It gets back to patrol as expected. But when it get to the "wait" state, it'll try to get to the player again eventhough the player is out of its trigger range. It is like it hasn't been able to reach to the destiny and it keeps trying during the wait state. I have no idea why.
I did a search in here and haven't found this yet, so I'll ask here:
I'm trying to come up with a generic function that can run for an AI character to locate objects in a certain radius that updates frequently and has a memory. I want to take those locations and put them in arrays for AIPerception to use as reference, and pipe these into data that BTTasks can use. In addition, I want to use the same generic function to highlight objects near the player that they can use in the world.
Let's say our NPC is currently unarmed and needs to find a weapon. We run this check to figure out what is nearby to use, and how to use it.
Say there's a knife and a gun. The knife is closer to hand than the gun, but the gun fits the more immediate need of a ranged opponent. But the ranged opponent is close enough that the knife can be grabbed on the way to the enemy to attack.
So we need to store some data-
The nearby objects as ObjectsInSearchArea(array)
Distance to each object from our starting position as DistanceToObject(array)
Types of objects as defined in a weapon class like BP_Weapon_Pickup
and reference these in the Task executed in the tree.
So I want to compare the generated list to what is seen in AIPerceptionSight() and get the closest object to move to it. I guess if I was to expand it to have more "decision making" I'd need to get the enemy's location via perception or their last known location and set distance values such that if the unit is close enough to attack quickly in melee to prioritize the knife, and further than that distance to priortize the weapon and getting to cover. Does any of this code even look close or am I way off?
I guess maybe this would make more sense in a GOAP system but I'm trying to reduce my learning overload by concentrating purely on what I can do with BTs for now
unless StateTree would be a better fit for functionality like this?
//revised
(ignore the tick usage, I will probably try and make this into a BT Service)
You could use gameplay tags on the actors for an EQS query rather than checking for specific classes.
The Debugger window in the State Tree editor is very useful for tracking down why you are transitioning unexpectedly to the different state. It'll show you the values in question and why it transitioned to your Chase state unexpectedly.
It is still not making sense. it is clearly in the wait state. and the wait state has only 1 delay task. why is it moving towards the player.
Hey all!
I'm messing with Smart Objects, and I was wondering how I could get my AI to stop trying to move to and use a Smart Object after it's slots have been disabled? My AI is trying to move to and eat an item, but If the player picks the item up (it gets attached to the player's hands), I'd like the AI to stop trying to go to the object and abort it's task and un-occupying the slot. Any ideas appreciated ^_^!
You can write your own eqs generator that looks for actors of class X within radius (or whatever you need). The generator can use a Query Context that will provide the class type. That query context can return the actor class you passed to the AI character.
That said, this is a much better approach. G.tags for the win. You can make your generator based in g.tags
while there are many approaches, your requirements would fit in an Utility System where you score the weapons to pick one
Apparently Utility AI is a part of StateTree as of 5.5. Some more learning is in order
That would be more to weight decision making. Like "go pick a weapon or run away" rather than choosing what to pick.
I don't know in BP's but in code you could funnel all this through EQS, have your own scoring system etc. Then run the EQS when needed and get your results already ordered by scores. Then pick the best one from there
So could I just do something like sensing the class of the nearby weapons, and then picking the highest class with the shortest distance?
that's what an EQS would do yeah.
- A generator will produced a raw set of data. ie: all the weapons within 25m (our give you all the available guns to pick in the game and a test will discard the ones further than X meters)
- then a test will score them based on distance (the closest the higher) <- this the engine already has
- another test will score them by how dangerous they are (a gun is more dangerous than a knife) <- this you will need to create by reading the Dangerous value from your weapon
When the eqs is done, it will give you back an array of weapons (items in EQS lingo) ordered by their score
why I cant use attack function from enemy blueprint?
and how to use conditions in behaviour tree?
Behavior Trees can only use nodes created for behavior trees. If you want to use a function from your actor, you need to create a new Behavior Tree Task which wraps the call of the function.
For conditions, you would typically use decorators, but the way all this works in BT's is not quite the same as using if/else in BP's. If you don't know how this works, it would probably be good to read the docs on how Behavior Trees evaluate.
Hey @harsh storm sorry for the late reply on this 🙂 If you change the "Scheduled Tick Policy" on the Schema settings on the tree to "Allowed", the custom tick rate settings on state will appear.
Its per state and affects child states as well.
That was a lot of meetings.
Apologies for the delayed reply! I was trying to toy with it more and some work came up. I was more so just trying to understand how it is selecting states, with and without considerations.
For why I thought it would work without a consideration, I assumed that the weight value is being supplemented as "chance" even without a consideration, and assumed that without a consideration, all default base scores were a value of 1.0f
However, it appears the "default" of the setup without a consideration is to be treated as though it were a zero, as weight holds no impact without a consideration as you mentioned.
Unrelated to the weighting, I was also noticing that with a consideration, they seem to not really accept Input variables?
But only sort of?
They can take in the Actor/Controller/Global Params, but if you create params on the State itself that "set" variables within the scoring method, it seems as though it just straight up breaks the Consideration.
Example: in the screenshot, I have the Input Var STC_TestBool, and the default value is true. Having that variable in the first place setup with a binding in the state tree is problematic, as the state tree seems to skip over the state entirely if it exists, with no clear messaging indicating so.
I understand the method is Read only after compiling, so I need to get used to that, that's entirely on me. Plus it would be messy anyways managing variables within Considerations.
Though, it does raise a question, since print to log statements don't seem to work within the considerations (if using custom messages from the state parameters), how can I see the scoring during run time? I feel it would help a bit to see that history. I have the debugger window open in the state tree and the blueprint debug window to watch variables, but I imagine at scale, it can get a bit harder to catch that historical information for the exact time it happened and try to piece it together.
or I am overthinking things ha
Anyone good at or knowledgeable with Smart Objects able to help any? 🥺
Yes except if that's about SmartObject entrance, i need to do some research in the next few days
Not me but my other half in the AI team knows quite a lot. I can pass him the quesito tomorrow if nobody else knows the answer
I’d appreciate it lots!! Thank you guys 😭
Isn't this a problem in the BT rather than the smart object itself? If I get this right:
- AI picks the item and moves to it
- player is faster picking it up
- the AI doesn't know about the player
Aren't you missing some callback for when the player picks it up?
I’m unsure if I’m understanding this right but the SOclaim handle is the reason why the ai moves and uses the object and how it knows where to go. I could add a delegate/event for when it gets picked up, but I don’t know I I can link it back to the behavior tree task to make the ai end the asynchronous task of it moving to the object (in the picture)
I disable the slot when it gets picked up and hoped that it would fix it but the AI continues moving to where the item was to use it even if it’s not there anymore
You need to have a decorator aborting the move to branch when the player picks up the SO. Not sure what that decorator should check. I guess if an SO Claim handle exists for it
so maybe this combined with a for loop to iterate through a list of weapon types (AR top priority, then shotgun, then pistol) before declaring a move? I don't know how to make a custom EQS query and the information I've found on the subject seems to indicate more coding knowledge 💀
or maybe a composite?
This one might do for now, it basically it testing if we can see/reach the weapon most efficiently which is probably "good enough" for a first game
I think maybe a sorting method is probably doable with gameplay tags?
I'm trying to call SendStateTreeEvent to trigger a state transition in 5.5. I have on-screen "print statements" surrounding the C++ SendStateTreeEvent call (so I know it's getting past that point in the code at least), and my actual state tree transition looks like the attached. The "AI.Aggroed" tag is declared / defined in C++ so there shouldn't be a typo issue. Is there anything else I'm missing? Do I need to have something for the Payload Struct value? I have a task in the Idle state (the state in which this event resides) that continually prints out "Is In Idle State", so I know at least the tree is running and the first state is active. I also have a similar printing task in the Combat state that never appears; the state remains Idle.
This is the C++ for what it's worth
DEBUG_PRINT("Target was successfully sensed.");
AggroTarget = Cast<ALegendCharacter>(Actor);
if (StateTreeAIComp && StateTreeAIComp->IsRunning())
{
const FGameplayTag AggroTag = UGameplayTagsManager::Get().RequestGameplayTag(FName("AI.Aggroed"));
const FStateTreeEvent Event(Tag_AI_Aggroed);
StateTreeAIComp->SendStateTreeEvent(Event);
DEBUG_PRINT("sent event");
}
else
{
DEBUG_PRINT("didn't send event");
}
Some questions:
- where and how are you declaring the tag in c++? The fact that you mention a typo rises concerns since tags are not written by hand, they are chosen from a menu. I see it selected in the picture but just in case
- where is the event transition set? Is it in the Idle state that is running?
- have you checked the state tree debugger to see if there's any extra info there?
My zombies, when attacking, knock my character into the air. Is there a way to prevent this? I've tried to ignore impulse on damage but it's still happening
Deleted my last message, was not for this chat or the person tagged
I just want to say, thank you
Hello ! I tried to do some weird stuff with SmartObject parameters 👀 (Unreal 5.4)
It turns out that the smartObject rendering component debug display the entrance properly in editor when sliding the value but not when validating the input 😔 It fallback to its original position
It looks like it should be doable to update the debug position since the smartObject entry turns blue when it is on a right position compared to navmesh
Is there a way to have a customizable entrance location per SmartObject instance?
Okay it turns out that my actor was wrongly setup
I reparented my actor as a GenericSmartObject actor and it works well !
Hey,
as the state tree seems to skip over the state entirely if it exists, with no clear messaging indicating so
I just tested this and it worked for me? Are you categorizing the parameter as Input ?
Regarding ways to debug the scoring, I'm asking internally.
Pretty good overview video of the new State Tree features in 5.6:
https://www.youtube.com/watch?v=bvWHU5nvU-0
A Quick Look at the New Features and Updates for State Trees in Unreal Engine 5.6.
From Custom Tick and State Control Flow, to the New Delegate Dispatchers and Listeners now available, and more...
NEW Gameplay Camera System In Unreal 5.5: https://youtu.be/oT9uSfET3nU?si=_XtqtDWPh0BiPZIA
Unreal Engine Beginner Videos To Watch Next: https://you...
- The tag thing became a red herring, apologies. I mentioned typos to assure I wasn't getting the tag via
RequestGameplayTag(and its typo-able FName arg). I have my Tags set using UE_DECLARE_GAMEPLAY_TAG_EXTERN / UE_DEFINE_GAMEPLAY_TAG in a single header/source file-pair.
I'll back up a bit and explain my setup.
- BP_NpcCharacter blueprint class. Details panel, I set the pawn's AI Controller Class variable to:
- AMyAIController C++ class / BP_MyAIController. In C++- I declare
StateTreeAIComplike so
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI")
TObjectPtr<UStateTreeAIComponent> StateTreeAIComp;
and in the blueprint details panel, set the StateTree asset, ST_Aggressive.
The original code I pasted is within AMyAIController's OnTargetPerceptionUpdate. This is how I have the sense configs set up:
AIPerceptionComp = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("AIPerceptionComp"));
AIPerceptionComp->SetComponentTickInterval(1);
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("SightConfig"));
SightConfig->SightRadius = 2000;
SightConfig->LoseSightRadius = 2200.0f;
SightConfig->PeripheralVisionAngleDegrees = 60.0f;
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
SightConfig->DetectionByAffiliation.bDetectFriendlies = true;
AIPerceptionComp->ConfigureSense(*SightConfig);
AIPerceptionComp->SetDominantSense(SightConfig->GetSenseImplementation());
- The event transition is within Idle. The "debug task" is:
etc Tick(FStateTreeExecutionContext&, float) const override
{
GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Yellow, TEXT("Still in Idle"));
return EStateTreeRunStatus::Running;
}
"Running" to stop re-doing Root->Idle. "Succeeded" has same result. A duplicate task in Combat.
- "debug0" attachment shows it entering Idle. The markers are the same, see "debug1". "states" shows the tree. Sorry for huge message 😄
@slow bobcat See ^^^. Somehow it became not a "reply" after an initial error sending the message. Thx!
Is there some kind of bug with StateTreeTask Run EQS Query that exits the state before other tasks are complete?
States will trigger those kinds of transitions as soon as any task completes
I think 5.6 adds the option to choose whether you want any or all to complete before anything is triggered
before 5.6? completely normal, you're supposed to handle EQS Query in a separate state and bind query result as a parameter in that state's parent state and then use it in a sibling state to the state where you handle EQS Query
Is it supposed to feel inconsistent or do I not understand some subtlety? You can share a delay and a debug text task and the delay will complete, for example.
Because the debug text task probably never actually "finishes"
It's also the opposite of how mass states work WRT selecting and using SO objects where the usage must be an inner state, no?
So no transition would happen
Yeah you have to design it with this in mind, 5.6 might change it I guess but perhaps it'll still be necessary to consider it for some cases
Wait you're right. debug text will block completion if its the only task on a state 🤯
This is my suggestion for how to deal with this: https://zomgmoz.tv/unreal/State-Tree/Custom-StateTree-tasks#task-design
All of this is fixed in 5.6, where we added controls for what tasks will contribute to state completion. You as the designer can toggle on/off per task, set completion to trigger on any or all tasks and so on.
Task authors can also set default, and if a task will ever contribute to completion.
FYI - Almost all tasks should complete, that is the right pattern from now on.
Regarding EQS, the best pattern is to trigger a transition on completion and read the result in a child state.
Ah nice, it also allows changing on a per task basis
I actually thought about implementing it as a bool for some tasks, whether it should finish or not, so this definitely makes sense
one sec, I'll show you a new screenshot from today
That green + icon there shows the task is currently contributing, clicking it turns it into a - (this icon is a star in Preview release)
btw someone asked about this recently, this is what the configurable tick rate looks like 🙂 it appears as soon as you change the policy on the schema
Nice, this is a good improvement
I can delete most of the text in the custom state tree tasks page lol
Some good changes for sure. I guess I was tripped up by the different behavior for FindSmartObject Mass task and the EQS Query task.
So just to be clear, the child task for Run EQS Query should not work currently and needs to be a sibling task in 5.5?
Hi, wanted to ask for some advice on how use a python RL algorithm on a agent.
My agent is a archer that can move around the room, rotate, and shoot ( these are the actions that is getting from the python script)
I am sending to the script his location, the enemy location, the distance to him, the angle between the agent and the enemy and a variable that will tell if he can shoot or not.
I am quite new in this, and I trying to create an PPO as continuous action space, basically I want my agent to learn how to shoot the enemies in the room.
My issue is that it doesn't learn anything in time, and sometimes the mu values reach Nan values, do you have any advice?
We did some fixes in 5.6 and I have recently confirmed it works there, but I honestly cant remember which pattern worked correctly in 5.5. Did you set this up with both tasks in the same state, sibling or child state? Splitting the MoveTo to a child state is the correct pattern at least
kk thanks for the help
Trying to leverage the AI perception component to implement Thief-style hearing, surprisingly harder than I thought
How so? Haven't tried this but it feels like you could probably trigger sound events with varying settings based on surface or something 🤔
Oh, the surface stuff is the easy part, I use an anim notify for footsteps and such as well as a data table for different surfaces for footsteps, the tricky part is the way loudness works
Ah
It's still something I'm getting to grips with
const float ClampedLoudness = FMath::Max(0.f, Event.Loudness);
const FVector::FReal DistToSoundSquared = FVector::DistSquared(Event.NoiseLocation, Listener.CachedLocation);
// Limit by loudness modified squared range (this is the old behavior)
if (DistToSoundSquared > PropDigest.HearingRangeSq * FMath::Square(ClampedLoudness))
{
continue;
}
// Limit by max range
else if (Event.MaxRange > 0.f && DistToSoundSquared > FMath::Square(Event.MaxRange * ClampedLoudness))
{
continue;
}
Yeah looks like it uses loudness as part of the distance check
Which I guess is okay for sounds that are actually loud enough to be heard from a distance but not so good for being able to sneak up on someone without them hearing unless the loudness is literally zero
Yeah, tbh it feels like it might be easier to just use distance. Either they hear the sound or not.
A bit abstract question - working on AI that can attack player owned structures or capture points. So far came with an idea make them visible to AI using perception, basically giving them team id. On top of that when AI sees a player structure, and sense adds it to threat list, it gets some initial threat so enemies keep attacking it if unattended. For capturing probably will go with ECS or something.
Does this approach sound sensible?
Yeah that generally sounds good
Yeah, for my buildings/objects that can be attacked I have a combat component that implements IAISightTargetInterface while the outer building actors have the IGenericTeamAgentInterface setup. Just manually call RegisterSource with the AIPerception system when they come active and unregister when they get destroyed.
Seems good, unless we are talking about many enemies and things to perceive. Then it is not. The Perception system struggles when it has to process high numbers.
How it works internally: each perceived stimuli is added to a collection (I don't recall if it's an array or a map). When processing it, the system checks how long is taking to process said collection within the frame. When reaching the time limit, it stops and waits for the next frame.
Every time said stimulis change location, new ones show up or the listener actor moves, they are added to the collection and the collection can change order.
If this happens often in high numbers, you can end up in a situation where some stimulis are not being processed ever.
This happened to me in a project. We had over 30 enemies being detected in some situations (top down arpg twin stick shooter). We had bug where some enemies were never processed (generally the ones added at the end). I got confirmation from epic (udn) that the system was never written for high volumes of stimuli happening. I ended up changing the system to disable stimulis (enemies mostly) that were further away than the vision radius.
My advice: think of a different way you can control.
- the team id is a good idea, but you don't need perception for it. There's an interface and an API for teams in unreal you can use
- structures might have different points to be attacked. Ie: is you have a castle, you probably want to attack the entrance wooden door rather than a wall. But if a wall is half-destroyed already, you probably whan to attack that. To do that, you need to check paths to specific locations in the castle. Consider options like adding interesting pints to an Octree (unreal has an octree API but it mostly supports adding, not removing. That you need to implement (it's not difficult). An octree is a super fast way to check locations within radius and obtain world data.
- every time a new player's building or capture point spawns in the world, you can add it to the octree. Your AI's can check every 2s if there's a new point of interest using the octree.
- all this can be done in eqs's that you control or in multi-thread async tasks that each AI can run making it cheap
To sumarize: if you plan on having many AI's checking on many things (other AI's, players, buildings (and within buildings, attack points), capture points... Consider an approach detached from the Perception System
If its going to be basic "yeah, the player is going to have 2/3 buildings and that's it", the Perception will be ok
Agree with this. A good flow adding/removing or enabling/disabling things is crucial for a healthy usage of the Perception system
I keep pondering how I would handle writing ai perception 2.0 with #mass but the line tracing is where I typically stop at. Mainly due to lazinesss and not really "needing" it myself
We don't use line traces for vision in our games. We use a coffin approach like in Siphon Filter and the lines
We do use it for hearing though
I was also thinking of switching to EQS entirely. As game base is also top down shooter with up to 30 enemies on a screen and only handful of player structures/points of defense. Need to cone up with an idea how to handle threat table for them though. But in general EQS can just run some simple tests on top of a list of players/structures snd update threat system I suppose.
Sounds a like a better approach to me
Thanks for advices folks 🙂
I'm unfamiliar with that approach
Game AI Pro 2, chapter 28 explains it, the vision coffin of the player
https://www.gameaipro.com/
Home of the book Game AI Pro
I figured Game AI pro would've had it, just was not at my PC to look.
YOU LIED TO ME
This one I do know
I have read this one - but even so, they still use raycasts.
The sight stuff already does a distance and dot product check before doing the line trace tests. So, I don't know how valuable it actually would be to move that stuff to mass and then just tell mass to tell the actor when to do the line trace tests.
That would require the actor to update the backing entities position, which sounds like it would defeat the purpose of even using Mass.
I've lightly talked to Mieszko about at least EQS being powered by Mass as well.
Sorry. I betrayed you!
Yeah for walls etc yeah, but you can do some volume overlap tests etc. It's not physics free
Hey, anyone know how to get around this error? This is being thrown when I try to destroy an AI controller running a state machine (even if logic has stopped). I assume it's because there are tasks that haven't finished being completed.
[2025.05.17-15.30.50:456][582]LogWindows: Error:
[2025.05.17-15.30.50:456][582]LogWindows: Error: [Callstack] 0x000001a524934f5a UnrealEditor-StateTreeModule.dll!TStaticArray<FStateTreeSharedEvent,8,8>::TArrayStorageElementAligned::~TArrayStorageElementAligned() []
[2025.05.17-15.30.50:456][582]LogWindows: Error: [Callstack] 0x000001a5249f6fda UnrealEditor-StateTreeModule.dll!`eh vector destructor iterator'() []
[2025.05.17-15.30.50:456][582]LogWindows: Error: [Callstack] 0x000001a5249280f8 UnrealEditor-StateTreeModule.dll!DestructItems<FStateTreeFrameStateSelectionEvents,int>() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Templates\MemoryOps.h:102]
[2025.05.17-15.30.50:456][582]LogWindows: Error: [Callstack] 0x000001a524926855 UnrealEditor-StateTreeModule.dll!UScriptStruct::TCppStructOps<FStateTreeTransitionResult>::Destruct() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Public\UObject\Class.h:1368]
[2025.05.17-15.30.50:456][582]LogWindows: Error: [Callstack] 0x00007ffae0c45a1f UnrealEditor-CoreUObject.dll!UScriptStruct::DestroyStruct() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp:3736]```
eh vector destructor
It's those darn canadian vectors again
Us Canadians always use Canadian vectors you know 🙂
I've never seen this myself and I've used ST's a bunch... have you tried looking at the callstack in your IDE?
No, that's probably the next step though. This is happening during level teardown when I'm trying to head back to my main menu.
Are you using any custom state tree tasks or just the builtins?
All custom tasks
Right - just makes me wonder if it's something to do with cleaning up the task which is then causing a problem somewhere
And to make it more fun, they're all written in C++ on FStateTreeTaskCommonBase
I'm not sure if the blueprint versions have extra cleanup built in
In my experience there isn't anything special you'd need to do with them, but if you were storing something unusual on the task struct instance or perhaps in the instance data, that could do it I suppose
Anyone knows why nav-mesh doesn't generate on geometry script made meshes? I know it works, just if there's some check box somewhere
Nothing too unusual on the task instance data... Actor pointers, basic types. A TArray of actors and a TMap of <AActor* , float> about the most complex thing
I think I'll try debugging through VS, as you suggested, maybe set up some breakpoints around the destroy events
Yeah that's probably the best place to start, could be so many things affecting it 🤔
I still haven't really used them - maybe you have to commit them or finalize them or something?
Are you registering to any external delegates? This looks like either a delegate firing when the ST is being destroyed, or ST trying to access an actor being destroyed (better to use weak ptrs for external refs)
Ive been really busy so i hadnt been able to mess with the project, but i finally got to it! The decorator wasnt checking every tick, so i decided to use a service instead! i tried adding a check into the task itself, but the problem is that the task's Receive Tick isnt executing at all. I might just have to add a blackboard key that is a bool and add a decorator anyways.
Quick question on Nav Modifiers. I have a map that is tile based, using 500x500 tiles for road tiles, grass tiles, etc.. Each tile is an actor with a Nav Modifier component to change the modifier area on for allowing where NPC's can and cant walk obviously. But im wondering if this is bad to do? Because lets say my map gets big enough and end up with 2000 tiles made up of roads and grass and sidewalks, that means there's 2000 nav mesh modifiers too. Curious on if they will cause performance issues with that sheer amount? I am using Static nav generation though. So I guess it's a one time build thing and never have to worry on it?
Pic for reference on what I am currently doing. Red is parts the AI cannot walk. The green is the sidewalks where they can walk.
All of this map is approx 1500 tile actors. (Which means 1500 nav mesh modifiers too as stated above)
Not using any delegates, but maybe the latter? Should I be converting these to TWeakObjectPtr?
struct MRACE_API FStateTreeSetThrottleInstanceData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, Category = "Context")
TObjectPtr<ARacingAIController> AIController = nullptr;
UPROPERTY(EditAnywhere, Category = "Context")
TObjectPtr<AVehicleBase> Actor = nullptr;
};```
Try it and see if that fixes the issue, then update your code to check IsValid on those before using them.
Do nav modifiers work at runtime with static nav mesh? I thought that was only for dynamic with nav modifiers only and dynamic
Yeah they seem to work. During the build process in editor it will create the static map with those modifiers involved.
But Im guessing any changes at runtime, nothing will change, is basically what I believe.
But I wonder if there is a significant cost to using A LOT of modifiers like what i've done above, using a tiled mesh map.
Ah I see.
Sincr they are not working in runtime, aside from the extra actir per level you are streaming, I don't see any other impacts in performance
Sweet! All shall be good then. 🙂
I thought to myself, if it's static, that means its baked Nav Mesh that doesn't need recomputing. But UE will be UE, always best to ask if what I'm doing is overkill lol. It's just that my map setup is a different approach to many. No landscape involved haha
Hey all, just curious if anyone knows why I would be experiencing this:
If I swap the "order" of them in the State, it still triggers the Move to Location breakpoint first.
I wonder if there's a defined "intended" behavior for this to begin with
Because a lot of the mentions of tasks in states is that they "run in parallel"
So I don't know should you assume that they will run in the order you've defined them in
the fact that you can bind properties of later tasks to earlier tasks in the list implies an order, doesn’t it?
Oh that's true, I guess it would
Hmmm... This likely will get me the behavior I am wanting, but it feels somewhat cluttery?
I do feel like I frequently run into questions on State Trees, but I promise I have worked on each of my problems for a while (95% of the time)
is there a reason that StateTree doesn't allow running bits of logic attached to particular transitions? i feel in state machine code it's very typical to have like if (LostPlayerPerception) { CurrentTarget = nullptr; Cooldown = 5.0f; RequestNextState( ... ); } but StateTree doesn't permit it?
you can work-around by having a one-tick intermediate state with an Enter task, but the extra tick in between could often be problematic
Task execution is not sequential, so you cannot have a MoveTo task right after EQS in the same state. You need to setup a child state with the MoveTo and trigger a transition once the EQS task is finished.
So under the hood, for any single given state one should never assume any specific order for the tasks?
Was there a specific architectural reason for that behavior? What are the upsides/ downsides as opposed to guaranteeing an order (unless were flirting with threadding?)
Is it possible to expose a gameplay tag picker in the state tree gui?
Anyone know why my Receive Abort events aren't firing for this UseSmartObject node i've got?
I think the issue here is just that you’ve assigned the variable the “Input” category, which means that manual data can’t be assigned to that variable, it can only be bound to a property
(When I first learned about magic categories and their mysterious implications I was not happy lol 😤)
Oh thanks, removing the category allows me to set it now
There's nothing in your decorator calling abort. You have implemented what to do when abort calls but not When/Why abort should call
I have this as the condition check, it doesnt automatically abort when this is false?
The flow control for the decorator is set to Aborts self
Does that logic run while your sequence's children run?
I'm trying to remember something about the rules of abort. There's something related to how the nodes are setup in composite nodes I can't recall now.
Yes, it's constantly checking ( i didnt think it was checking on tick at first til i retried it a day later LOL)
But yeah when it goes false, its not aborting or anything idk why exactly
yeah that's only checking the condition in the decorator. Nothing there is related to abort.
That's only a "does this decorator pass its condition?", but you are not calling abort specifically.
For example, this is what the blackboar decorator does internally
In the end, it's just calling RequestBranchDeactivation
I always work in c++ so not sure how to implement abort in BP's
They run init and tick in correct sequence, not sure why you think they would not? I was pointing out that a task relying on the async output of another task should not be in the same state.
You can easily verify this just by printing out a string in InitState or task Tick and writing out a string set in the task.
ah my bad, it was about async
Im still getting to grips with the whole thing and had some faulty assumptions
Ah I see, so far while testing, the abort event has only been called when the AI gets destroyed. I'll try and see if theres a solution for blueprint 😭 thank you though!!
the floor you are using, does it have the flag bCanAffectNavigation set to true?
Thank you, this helps a ton when worded this way
hey guys noob question about state trees: we are thinking about setting the value of a Global Param in a state tree (it will point to a behavior tree) from C++ in a component (not the state tree component).
If I have the StateTreeRef of said tree, is there a function to set the param value in it?
Haven't look very hard, but on a simple search I don't see any obvious function to do it.
I would imagine it implies something with the GetMutableGlobalParameters in UStateTreeInstanceData?
For smart objects, how do you integrate the player into the mix so that if the player wants to say, sit on a bench, he follows the same check for occupancy->claim->approach->play animation flow?
It's been awhile since I looked, but I think you're right.
Any chance you have an example at hand? And yeah... I'm in lazy mode XD
I do not. But I think EQS task does it.
I'm at my day job, so can't pop open UE unfortunately.
If your pc is not controlled by an AI controller, you would probably have to come up with some kind of custom solution for it. I don't think there's inherently anything in the SO system which would prevent it, but you would need to take it into account when building the SO behaviors (eg. you probably can't use BT based behaviors)
Creating a custom Use Smart Object gameplay task to replace the AI Task based one could make it more convenient
I guess temporarily possessing it with an AI Controller for the duration could be an option as well
Take a look at UStateTreeFunctionLibrary::K2_SetParametersProperty here to start you off:
Is having the player character controlled by an AI controller something that is done normally?
Depends on what you're doing. One case would be if you control the pc by clicking, and it automatically paths to the targeted location - this would be easy to achieve by having an AI controller possess the character.
yea no not that simple im afraid typical third person
Right, if you're not using BT-based behaviors in your SO's, it shouldn't be too hard to manually claim and activate the behavior
It will require C++ though in case that's a problem
nope i can do c++ its just the smart object system in particular im unfamiliar with
Take a look at the AITask for it, it's called something like AITask_UseGameplayBehaviorSmartObject
It should contain the logic to claim the SO, and to get the GB from it. Unless I completely misremember, this logic shouldn't require an AI controller
Oooh nice. Thanks dude
I have a sight sense set up which works fine for detection and when the player moves away Stimulus.WasSuccessfullySensed() triggers as false which is what I want. If the player just stands in place and the AI walks past the detection starts but end detection never triggers
For the perception system these both should behave exactly the same, so this could be an issue with how you've set up the detection logic
found this on the forums, seems max age doesn't count down if “auto success range from last seen location” is set, changed this to -1 and works as expected
Ah, yeah I never used those myself, I've also heard the forget related settings can be kinda hard to correctly configure
From my earlier post, I figured out the issue. I was putting some tasks into the "Combat" state, which had child states, but critically, none were enabled. Because of this, the Combat state is never entered even though the transition event registers (maybe a safety valve of sorts since Combat itself, has no transitions or (enabled) children, it just nopes back to root?) In any case, if the tree looks like the attached, no transition happens. If I take the Debug Text / Delay tasks and put them into an Enabled child state, the transition works.
Hi guys! I'm kind of in the need of some guidance on how I'd go about having an AI climb when they reach this Nav Link that I have on my wall with a custom trace channel, "Climbable".
Currently I've made it so that when the AI reaches the link, the AI's movement mode is set to fly and will trace the wall up until it gets to the top of the climbable wall and can no longer climb. I've been going off of this Gorka tutorial > https://www.youtube.com/watch?v=F_g_AnDyWi8&list=PLiSlOaRBfgkcPAhYpGps16PT_9f28amXi&index=31
I was wondering if there'd be a better way to do this somehow! Please let me know! 😊 (For reference, I'm trying to get the AI to run simple obstacle courses with swimming, climbing, and running, like in Chao Garden races)
Hello guys, in this quick and simple tutorial we are going to continue with my UE5 RPG Tutorial Series in Unreal Engine 5!
↪️Just opened my Discord Server, join NOW: https://bit.ly/GorkaGamesYouTubeDiscordServer
➡️Whole Series: https://www.youtube.com/watch?v=FNTyIWkv5k8&list=PLiSlOaRBfgkcPAhYpGps16PT_9f28amXi
👉Awesome Unreal Engine...
Hello, does anybody know how to access the currently active states in a StateTree. Ive tried some things but none of them gave me a representation of the active States. Maybe it is possible to use the Visual Debugger via cpp to get those values since it displays them, but i could not find any functions or info in the documentation.
Is there some particular purpose you need this for? There is a state tree debugger in the state tree editor which should show this, and as you said visual logger should also contain this information
If you need the currently active state in code from anywhere
You can implement this function in StateTreeComponent (or a custom child of this class)
⚠️ I coded that in 5.4, not sure it still the same in 5.5/5.6
TStringBuilder<256> stringBuilder;
if (StateTreeRef.IsValid())
{
const FStateTreeExecutionContext& stateTreeExecutionContext = FStateTreeExecutionContext(*GetOwner(), *StateTreeRef.GetStateTree(), InstanceData);
for (const FName& stateName : stateTreeExecutionContext.GetActiveStateNames())
{
stringBuilder.Appendf(TEXT("[%s]"), *stateName.ToString());
}
}
Apart from that
I'm currently playing with SmartObject + Gameplay Interaction StateTree
Anyone can confirm that in 5.5, the StateTree calling "Use SmartObject" and the SmartObject StateTree still run in parallel ?
It seems to work differently from LinkedAsset which is running the StateTree calling the "LinkedAsset state" and kind of inject the StateTree asset within it (Another point is that it is hard to debug for now)
I guess it's because it's two different systems and they were developed at different time frames.
I noticed that if i send a StateTree Event to the AI, it will receive it in the main StateTree but not in the SmartObject one 😔
Yea, i need to display the active states in an UI Element (Maybe even a full-blown tree) at runtime.
Thank you
If you are in 5.5, you should rely on state tags if you want to display some User Facing Text (by doing a TMap <Tag, FText>, but maybe there is a better way to achieve that)
But yeah the code that i shared should be sufficient for now
Look at UStateTreeComponent::GetActiveStateNames()
oh thanks alot
I vaguely recall it might run separate, ST's have the capability to do that much more easily than BT's (which was one of the big problems I had with BT-based SO tasks, it can't even resume the previous BT from where it left off) - easiest way to find out for sure would be to look at the GameplayInteraction Smart Object Behavior's code, it should be fairly obvious if it executes the ST there
quick question about State Tree Event's payload: am I supposed to be able to retrieve the payload somewhere?
Let's say I send an Event with a Payload.
That Event triggers a transition to a State with a condition.
I would like to grab said payload to check something in the condition
And if the condition passes, I want to use the rest of the payload data in the Task run by the State.
Is that possible?
I'm seeing functions like
void SetCollectExternalDataCallback(const FOnCollectStateTreeExternalData& Callback);```
and since the Payload is a ConstStructView...
```const FConstStructView Payload```
Is that how you catch the payload of an event?
I'm always super confused about how the Struct stuff works for State Trees. Any good documentation/examples anywhere to understand how is this used? It's completely Alien to me
did you implement that directly in StateTreeComponent and built from source or separately in a child class? I just wondered whats easier
Okay i got it working, thanks dude
Easier is a child in your project code with a child of the class
But on my side i can easily change the source code and share it so both are easy
What do you mean the struct stuff?
Event Payload struct? PropertyBinding? StateTreeTask InstanceData (which can be a struct or an UObject depending your needs 👀)?
What I mean is: the whole State Tree system is built on top of the StructUtils: InstancedStruct (and the containers), PropertyBag, StructArrayViews and some other related code.
I have no idea how any of that works. While I can map the whole State Tree System and do complicated stuff, I fail to understand its core technology when I hit that wall.
I need some proper teaching about how the Struct Utils things work.
But my most immediate problem is to understand how to retrieve and handle passed payloads in an Event
on this topic, the comments help but I'm still eager for a simple example (looking into StructArrayViewTest.cpp as we speak)
Hello, in the behavior tree when I use a blackboard based condition which is an enum, when I choose for example "State A" and "Not equal" does that mean the task will activate only when this enum isn't equal to state A ?
yes
Okay thanks
Are you using 5.4 or 5.5?
In 5.4 event payload are not properly supported within StateTree while in 5.5, payload are sent as PropertyBag that you can use within sibbling/child states
5.5. Been waiting for it to be implemented and now I'm in a good position to look into it.
AAAAh as a property bag? nice to know.
I'm debugging sending one and see what happens within the state (and its task) when called
I suppose this is a property bag like StateTree Global and state parameters
(here is a screenshot from the roadmap page : https://portal.productboard.com/epicgames/1-unreal-engine-public-roadmap/c/1494-state-tree-ux-and-events)
https://www.youtube.com/watch?v=FH2Af5s734A And it seems to be setup in Enter Condition "Required event to enter" and states should have access to the payload
umm ok. This gives clues. I'm in c++ so I guess I would grab this info from the FStateTreeExecutionContexton EnterState within the task?
I guess somewhere here?
So your entire StateTree is in c++?
no, but: state tree component, conditions, tasks and some other stuff is. Designers compose them using the UI like anybody else, but we handle most of the stuff in c++. It's rare we have to use anything but our custom stuff
Here is an example of what I have going on that is what Siggi linked to
hey guys, do people usually use the level blueprint to spawn actors when needed or create a seperate actor spawning blueprint?
I see you are doing it from within a node (a task/condition) and that you are able to grab the property ref.
But what if I'm doing this outside a tree?
I'm in a component, I have the statetree ref and I want to change a global param in it.
How would I proceed?
We're trying something like this
if (stateTree)
{
FInstancedPropertyBag& InstancedPropertyBag = stateTree->GetMutableParameters();
FStructView PropertyBagView = InstancedPropertyBag.GetMutableValue();
const UPropertyBag* PropertyBag = InstancedPropertyBag.GetPropertyBagStruct();
if (PropertyBagView.IsValid() && PropertyBag)
{
if (const FPropertyBagPropertyDesc* PropertyBagDesc = PropertyBag->FindPropertyDescByName(FName("InputTree")))
{
if (const FProperty* TargetProperty = PropertyBag->FindPropertyByName(PropertyBagDesc->Name))
{
void* TargetPtr = TargetProperty->ContainerPtrToValuePtr<void>(PropertyBagView.GetMemory());
TargetProperty->CopyCompleteValue(TargetPtr, feInstanceData.InitialActionBehaviorTree);
stateTree->SetPropertyOverridden(PropertyBagDesc->ID, true);
}
}
}
}```
But I have the feeling that we should be getting the property bag from the instance data or a on-the-go context like this
```FStateTreeInstanceData& treeInstanceData = ownerStateTreeComponent->StateTreeInstanceDataMap.FindOrAdd(stateTree->GetStateTree());
const FStateTreeExecutionContext context(*GetOwner(), *stateTree->GetStateTree(), treeInstanceData);
start by learning UScriptStruct and reflection types first, and reflection in general. FInstancedStruct and its related types are reflection wrappers of UScriptStruct on surface level
oh well just saw your last message, appearently you're already ahead
Back before the property references were a thing, I believe I tried something similar with c++ functions, and was finding it unreliable/cumbersome to try to modify that stuff externally (Though, part of that could have been from juggling a pooling tool at the same time). If I were to try to do what you are attempting now, I feel like I would try to go about it the same way one would go about modify widgets.
So I do not over explain, are you familiar with "Widget Controllers" as a concept?
not ahead by a long shot. Good advice that is being taken. Thanks a lot
Widget controllers: not sure what you mean. Are you suggesting some form of AI tool?
Idk what ST does, but BP event graph for example is a very, very fancy runtime generated UScriptStruct that contains all function return values, local variable memory etc. - probably ST does this more programmatically but I dont think Epic "wants" you to modify things externally when it comes to ST memory
No, I imagine another name for them exists as the name "Widget Controller" sounds like an actual npc/player controller, but they are not. They are more like a middle man object that exists to hold variables and broadcast changes out for listeners on Widgets (so widgets don't need to hold the logic of how to get all the data it needs to display).
So what I am proposing is for an object to be spawned that is just a default, no mesh object, to serve as the "Controller", and have a global task that listens for stuff broadcast out from the "Controller", then apply the changes to the State Tree Properties/Parameters.
yeah... this is one of those cases where I need to "pee against the wind" once again.
it should be very possible to do this if I have the Instanced data etc. I feel that we are missing a step here and we are just changing the copy of our property bag, not the actual properties in the tree instance
aaah you mean that. Yeah that's not feasible right now. Long to explain, but not feasible.
We have a plan B, but we really would like to understand the low level of state trees as we understand the BT's low level. Otherwise we will not be able to do cool stuff with them.
no worries, I trust ya. Was a shot in the dark without game context
the worst part is that I'm sure that knowledge has been discussed and solved here already, but I can't find it
Don't see how this is related to #gameplay-ai necessarily, probably a better question for #blueprint - but a different actor. I don't really use the level BP all that much.
idk about that, pretty heavy components are added/updated each Unreal Version as of the last few (at least in my opinion). So new stuff is added constantly. Despite that, I am still sticking with State Trees, I find them far easier to work with than behavior trees for my use-case.
it's a case by case thing definitely.
To me understanding the flow of execution and how things are handled behind the veil is getting hard with State Trees. Check StateTreeExecutionContext::Tick and you will jump straight into the rabbit hole
@slow bobcat Have you gotten to the capabilities talk (from Hazelight) in your GDC backlog yet?
yeah. It's interesting, but if you are used to GAS, gives you nothing really.
Impressive gameplay iteration process though
well you made me curious
Funny - I heard the opposite from former Hazelight devs who work with GAS now.
Theirs is the same but simpler. They have GA's (capabilities), modifiers (GE's), g.tags to block/allow capabilities...
They have a nice layer of Angel Script which seems to be super nice (They don't dig into it) and their "GA's" tick.
But aside that, it's pretty much a custom GAS