#gameplay-ai

1 messages Β· Page 172 of 1

pseudo drum
#

Why does UE5 tell me to rebuild the navmesh when I play in standalone?

north oriole
#

Hi guys!i'm using AI sight perception on my character to detect objects it can interact with. Right now it perceives all kinda of actors, what is the best way to perceive only actors which implement a certain interface or with a specific tag?so that when i call getPerceivedActors i already have them filtered out

ocean wren
#

There's a Mass channel on this discord server, suggest you ask there. Plenty of people using it for RTS over there too.

misty wharf
north oriole
misty wharf
#

only pawns register by default with it iirc, and they should have a setting that you can change to turn it off

north oriole
#

I see thats's way it only saw the player, thank you very much!

stiff linden
#

Per player, I have one pawn and one AIController. I want to create & attach a new aicontroller + pawn to any new created PlayerController, but I am having some troubles. What is the recommended way for this?

#

Right now I basically unposses & spawn an ai controller in the pawn in BeginPlay and tell the original controler the ai instance

#

But it seems sometimes there is no controller at BeginPlay for the pawn, probably because it is still being assigned from GameMode::SpawnDefaultPawn

misty wharf
#

You can use On Possess or Possessed or whatever the event was to detect when one is assigned

stiff linden
#

I thought so as well, but the function in the GameMode uses SetPawn() which doesn't seem to trigger an "OnPossessed"

#

at least it didn't for me

#

(the default function)

misty wharf
#

Are you doing this logic within the controller?

stiff linden
#

I tried various locations, currently it's in the pawn

#

Maybe I should just disable auto-spawning and create the pawn manually

misty wharf
#

Odd, it definitely should get possess called at some point

#

But yeah you could manually spawn either the pawn or controller

#
NewPlayer->Possess(NewPlayer->GetPawn());
#

out of curiosity I looked at the gamemode logic, it definitely does possess :)

#

this happens in FinishRestartPlayer which as far as I can tell is always called when a new player is spawned and has its pawn assigned

stiff linden
#

Hu

#

Where is that line?

#

For me it just says

#
    else if (GetDefaultPawnClassForController(NewPlayer) != nullptr)
    {
        // Try to create a pawn to use of the default class for this player
        APawn* NewPawn = SpawnDefaultPawnFor(NewPlayer, StartSpot);
        if (IsValid(NewPawn))
        {
            NewPlayer->SetPawn(NewPawn);
        }
    }

misty wharf
#

it's further down from that

#

although it looks like yours is different from mine ever so slightly, I'm on 4.27 so not sure if it's different - I would assume it would still call possess somewhere

stiff linden
#

I am on 5

misty wharf
#

maybe just try searching for Possess within that file?

stiff linden
#

Will do later, gotta run now. Thanks for the pointers πŸ™‚

misty wharf
#

πŸ‘

flat spade
#

any ideas why RotatetofaceBBentry breaks if i run my pawn around behind the ai?

#

it stalls on the task until i run back into success range

neat heron
#

@ocean wren Oh hell, i thought there was one but i didn't see it. my bad, i'll go check that out, much appreciated!

mint sundial
#

What do you think is happening? Some days ago this haven't happened. It's just a simple Move To Actor sentence...but now.... the ai pawn is colliding with...something?? The mesh even....rotate?!! WTF I can't tell you what is happening , I'm so confuse haha. Thanks for any help πŸ™‚

#

I have cheked every collision setting of every actor...and nothing wierd...

#

UPD: in a new level, the bug is not happening...nice xD

#

UPD2: is happening again xD

mint terrace
fallen otter
#

~~I'm working on a bt and for some reason I can't have a MoveTo node use any of the values on the child as keys. does anyone know why that is?~~The new ones are all "Object" class, I needed to use an actor

minor relic
#

can someone explain these points to me?

mint terrace
stuck slate
#

Is there a way to detect path when he's Blocked?

flat spade
mint terrace
# flat spade good point, it's not actually rotating at all once I took out the moveTo

Rotate to Face BB Entry is implemented using the AIController's "Focus" system (similar to Set Default Focus). AIController uses the focus inputs to determine its Control Rotation. This rotation can be applied to your pawn either directly using the "Use Controller Rotation *" settings, or by the Character Movement Component if you have one (comes built-in to Character) using "Use Controller Desired Rotation"

flat spade
#

just had to find the magic combination of checkboxes to get it working

mint terrace
#

uh huh πŸ™‚

#

But you really want to internalize how this all works

#

Because when you get into more advanced stuff, you will be toggling these checkboxes at runtime to achieve what you need

#

I only came back to ask my own question about these checkboxes

#

What is a good way to implement proper backwards walking using CMC / Navmesh / MoveTo

#

ie, lets say my focus is pinned on, for instance, an enemy, id like to have the AI navigate to a position without turning, by passing the appropriate control input (X/Y) in, so that my ABP can react appropriately (using the appropriate blend space walking states)

#

im suspecting the best path is to override AIController::MoveTo, but maybe someone has another idea

mint terrace
#

Well, I'm learning a lot about the focus system.
Three priorities of focus:

  • "Default" Focus (priority 0): Bottom of the rung, only used if no other focus is available
  • "Move" focus (priority 1): PathFindingComponent sets this during a move operation. Thus, "Default Focus" is always overridden by MoveTo.
  • "Gameplay" focus (priority 2): This is what is set by AIController::SetFocalPoint. No built in BT service to control it, but one can be made.
ocean wren
#

If I recall, there's a checkbox on the moveto BT node to tell it to face the path or to face the focus actor? if there isn't I might have added it πŸ™‚

mint terrace
#

i think you added it πŸ™‚

charred ruin
#

Is it bad design to set the AI state from inside the behavior tree?

Let's say the AI does a short task in a state, and once done, I want to set it back to its last state. Is this fine to do through the BT or is there a better way?

misty wharf
#

There's no right or wrong way. It depends on how your AI works

ocean wren
#

NO STATE! πŸ™‚

#

only data

#

and priority

#

higher priority pre-empts lower

#

so if you're doing something low priority and a higher priority thing becomes available, then you switch to the high priority

#

once that high priority task is no longer available (through conditions) then you'll naturally go back to the lower

#

the point is to avoid thinking of it as states and transitions

#

its just "what is my highest priority right now based on the data"

#

and conditions enable/disable the priority order

#

so you might have a really low priority idle state that just.. noodles around, finds things to look at and looks at them etc.

#

A mid priority that goes to work

#

A high priority that avoids an oncoming train

#

the conditions of when a priority task is available is the key bit.. changes in the BB are how you know the priority can change

#

i.e. "I'm about to be hit by a train" might be a value in the BB, which is a condition on the "get off the train tracks" branch of the tree

charred ruin
#

@ocean wren Thanks for the explanation! Just a question, why would you not check these conditions in code and based on that, you set states which you can use in the BT, like if there's an oncoming train, set the state to avoid train. I know this goes against what you said but it keeps things much more organized and to the point in a BT, so I'm wondering why this is a bad choice?

misty wharf
#

@ocean wren did you do anything interesting with the dalle thing btw? a friend found some "dall-e mini" and I asked it to do William Shatner as Duke Nukem which is probably one of the best results I got out of it lol

ocean wren
#

You can improve things with HFSM and use heirarchy, but BT's try and avoid it by adopting a priority approach, which is actually more reasonable.. if someone shoots at you in real life, you're not bothered about previous states, you're bothered about getting your head down as priority

#

Its a different way of thinking and SHOULD be easier if you can make the mental shift

#

That said, people cling on to states pretty hard πŸ™‚ ask everyone in here πŸ™‚

ocean wren
#

Does take a bit to figure out how to direct it

#

But I've generated hundreds of images now

#

I've been playing with a discord based image generator called MidJourney as well, but Dall-E2 is better imho

#

The problem is, at some point, they're going to notice I'm melting their GPU's πŸ™‚

#

not that they don't have many thousands of course

#

but they're going to throttle me eventually.. then what am I going to do for casual artworks?

#

Weird, discord not likeee

#

Makes me grumpy

#

That was an image I generated for chat this morning when my heating was off πŸ™‚

misty wharf
#

should probably have joined the waitlist the first time I heard of this and not after you talked about it

#

prolly have a hundred thousand people waiting for it by now lol

ocean wren
#

I dunno, its weird.. I suspect they randomly select, because I didn't sign up for the new one until about a month ago

#

mind you, thinking about it, I probably signed up for the previous version a few years back πŸ™‚

#

Figuring out prompts for this stuff is pretty weird, an artform in itself really

misty wharf
#

Yeah

#

I noticed dall-e mini struggled to put certain things together, but if I prefixed it with "imaginary" that somehow made it then do what I wanted

#

it's definitely a lot more crude and limited than what the proper one produces

ocean wren
#

The thing is, you're trying to figure out the latent spaces of a N dimensional vector, where the vectors are in different image and text spaces.. I guess thats always going to be weird until we figure out methods to isolate features (GAN's do a bit of that)

#

What was the prompt you used again?

misty wharf
#

I forget what it was, we were just goofing around by making William Shatner and Steven Seagal do weird things lol

ocean wren
#

one thing I've been doing, is saving the generated images alongside the prompt texts.. so I've got a history of generations for a gallery I'll be doing

misty wharf
#

Yeah that's a good idea

ocean wren
#

Just right click and "save as" the webpage as a complete thing.. it'll save the images and the prompt text as a directory

#

I've been eyeing up a printer to maybe print some of my favourite generated images as art prints for a gallery

#

Havent been into work to check out the large format printers yet though

mint sundial
misty wharf
#

It's a bit hard to say but does the actor that's moving also modify the navmesh?

#

if it has can affect navigation enabled then it will behave erratically

mint sundial
#

thanks! it works

#

the mesh wierd rotation continues....but for the moment I don't care about it hehe

ocean wren
#

One for you Zomg:

#

William shatner as duke nukem

#

Sorry, william shatner as duke nukem, digital art

misty wharf
#

:D

#

interesting that it sort of got shatner but still doesn't know what duke is lol

ocean wren
#

Probably not enough images captioned with duke nukem as a term

#

But look at the quality of the faces, these are definitely art quality, its pretty insane

#

These diffusion models are pretty crazy

#

I'm waiting for access to googles new one too.. Imagen?

#

does more photorealistic stuff

#

Personally, I like the Dall-E one, its got my style of art down

misty wharf
#

Yeah the quality is really impressive

#

I expected it to be the quality of what I posted from dall-e mini because that's been the level of quality these are

#

even dall-e mini can do some interesting styles, for example I asked it to do a few "in style of the simpsons", "as a salvador dali painting" and "in style of H.R. Giger"

ocean wren
#

Thats the difference with the large models, just the vastness of the model gives it more power

misty wharf
#

the quality is much worse but it gets the basic qualities of those styles in there pretty well

#

oh yeah, "in style of minecraft" also produced a reasonably convincing "minecraft fan art" type image lol

ocean wren
#

Yeah, the Clip embeddings are likely the same

#

its the diffusion decoder that's going to be different

#

There's a Dall-E 2 clone on github, some people have been reverse engineering it πŸ™‚

#

Dall-E2 was trained on a dataset called LAION, which you can get hold of.. I'm hoping we'll get an open source Dall-E2 soon. Which then I can run on my GPU πŸ™‚

#

Because I'm paranoid of losing access

misty wharf
#

I wonder how long it'll take to generate something on a single gpu lol

#

...and how much disk space does the whole thing take

ocean wren
#

Well, its just a ML model

#

it has to fit in a GPU

#

and I've got one with as much GPU mem as any other out there I believe

#

48gb on mine.. so it should run, maybe not as fast

#

But remember, these are actually 256x256 images upscaled twice with a diffusion model

#

so not THAT big

#

its the training that's the problem

#

But a pre-trained model is fine.. I reckon a 3090 might even fit one

misty wharf
#

interesting

ocean wren
#

If you get yourself on the MidJourney beta, they actually price some of this stuff up

#

and their model definitely runs on a single GPU per generation

#

They moved the upscaling to different set of GPU's

#

Hmm, it'd be interesting running a model on AWS or Azure thinking about it

#

Weird how this model doesn't like doing hands:

misty wharf
misty wharf
#

@ocean wren I got a request from my friend "Can you do Steven Seagal watering flowers in a pink dress"

#

lol

ocean wren
#

hahaha.. worth a try

#

Anyone know the name of the bad guys from that Vin Diesel film

#

goddam can't remember their name

#

"You keep what you kill" guys

misty wharf
#

He's been in quite many

#

oh that's chronicles of riddick I think?

#

not sure who said it tho

ocean wren
#

yeah, what was the name of the bad guys?

misty wharf
#

I htink Karl Urban was in it at least

ocean wren
#

necromongers!

#

That's steven segal πŸ™‚

misty wharf
#

haha

#

it did get his obsession with asian culture at least

ocean wren
#

The top middle one is kind of interesting proportions wise

misty wharf
#

My friend described the result as "Disney Jason Momoa character" lol

ocean wren
#

I don't think I could get away with that as a prompt sadly πŸ™‚

#

its very censored unfortunately.. lots of taboo keywords

main saffron
#

When debugging EQS, I cannot see the scores using UE5, I had no issues with this in UE4.26 - does anyone know how to show scores?

minor relic
#

Hi, what's difference between Pathing Grid and Grid ?

charred lava
#

How to handle Senses config other then Sight / Hearing / Damage?
I know you have to write your own C++ ReportOtherSenseEvent.
But how do I listen to those events and react to them?
The AIPerceptionComponent OnPerceptionUpdated events doesn't get triggered by those other Senses.

misty wharf
#

You need to write a custom sense class for it

charred lava
misty wharf
#

If you want to report custom sense events, you need to create a custom sense, yes

#

you can inherit from one of the existing ones, or from FAISense or whatever the base class for them was

charred lava
#

I don't want custom senses. Just use the other ones besides Sight / Hearing / Damage which didn't got the same treatment in support.
How can I react to FAITeamStimulusEvent for example? I wished it would automatically trigger the AIPerceptionComponent OnPerceptionUpdated event, but it doesn't when I use my own Report Event function:

void UCustomBlueprintFunctionLibrary::ReportTeamEvent(AActor* Broadcaster, AActor* Enemy, const FVector& LastKnowLocation,
    float EventRange, float PassedInfoAge, float InStrength)
{
    if (Broadcaster)
    {
        if (UAIPerceptionSystem* PerceptionSystem = UAIPerceptionSystem::GetCurrent(Broadcaster))
        {
            FAITeamStimulusEvent Event = FAITeamStimulusEvent(Broadcaster, Enemy, LastKnowLocation,
                EventRange, PassedInfoAge, InStrength);
            PerceptionSystem->OnEvent(Event);
        }
    }
}
misty wharf
#

Ohh that's what you mean

#

Yeah the team sense is a bit of a mystery to me tbh

#

It doesn't seem like it does much anything, it's not documented, so it seems like it might be incomplete

charred lava
#

Similar to the Touch Sense :/

misty wharf
#

I'd say your best bet would be to first try and figure out how to correctly trigger the sense first of all, so that it actually receives the event

charred lava
#

I have a look on how the AI Damage Sense manages it and compare

charred ruin
#

I'm trying to understand node instances and node memory in C++ BTTasks. Any help appreciated.

From what I understand, by default nodes are not instanced, so if you want to save data and use it again, you will need to utilize uint8* NodeMemory. But what if you set bCreateNodeInstance to true, does that mean the node is now instanced and you can store data on it? What is the downside to this?

Basically, how should I know when I should use an instanced node vs when I should use NodeMemory?

misty wharf
#

afaik there is a small performance impact from it

#

instanced nodes can store any kind of data and delegates and whatever on them just like anything else

#

non-instanced nodes have some limits but I've not really fully figured it out - it seems some of the builtin nodes which aren't instanced bind delegates into themselves which seems to suggest they are actually still somewhat instanced (iirc)

#

but at least with non-instanced you're supposed to use the node memory function to store data instead of storing properties on the node itself

charred ruin
#

Ahh I see. Looking at the native tasks, they mostly only finish latent tasks in tick where NodeMemory is accessible. So I should probably stick to instanced nodes unless I'm planning on only using things like tick or other built in methods that pass in NodeMemory

misty wharf
#

Yeah I don't think the perf impact is really an issue for most uses, all BP based BT nodes are instanced afaik

fossil wraith
#

does it cover c++ and BP?

#

does AI really need to be c++

celest python
#

It makes small difference in terms of performance if you are not going wild with high count of enemies or very absurd features. But it makes a huge difference in terms of accessing to features and things not exposed to BP

misty wharf
#

The team support in AI perception, and the sight target interface are useful things that are C++ only, not really sure what else πŸ€”

#

There's some bits for navigation system where you can look at more detail about the path, and delegates for rebuilding navmesh and such but those are maybe a bit more niche

fossil wraith
celest python
#

Whatever you do, always create a prototype first in BP because you are also going to playtest it and modify it later on, on the long run

#

Then if profiler proves any overhead then move it to C++

fossil wraith
#

i mean the max amount of enemies il have even in a huge space is not gunna be above 20 currently as im just working on a larger prototype/ Demo

celest python
#

In normal gameplay programming you might prefer to do most of the things in C++ first but in AI my personal preference is always going wild with BP then moving to C++ unless its some sort of math or any heavy calculation/lookup operation

celest python
#

Use C++ to get 100% benefit of EQS and creating custom systems for low-level things

opal crest
#

There's probably one thing you'll want C++ for: doing more complex targeting for AI Perception: Sight. But that's something you can do much later.

fossil wraith
#

im using c++ for like anything the player is doing A LOT like movment.

#

I do want to do bone targeting based detection in the future

opal crest
#

Yep, that's only exposed to C++, AFAIK.

misty wharf
#

If you want to do it using ai perception yeah, needs IAISightTargetInterface

fossil wraith
#

i want to make a waypoint path system for my AI and i want to be able to in editor and in BP change actions that the actor that goes to that waypoint can do (like play animation, sleep for a certain time, continue walking or Wait for a certain amount of time) can EQS do this? or is this VERY complicated and a c++ thing?

celest python
#

dependsℒ️

#

its not complicated though

#

just can be preferred to do in C++ if its going to be extended

fossil wraith
#

what ive described is pretty much what i want apart from environment changes

#

so like if a guard spots a dead guard or something and obviously the player

ocean wren
#

Once you start down the rabbit hole, you'll realize how deep it goes πŸ™‚

neat heron
#

Howdy, i'm very interested in Smart objects due to how broadly useful "Ai does THING here based on criteria" is. It seems like you could do alot with them, from ambient anims to AI cover-system points, to door opening, ect.
Is there some major limit or hangup to the smart object system i should be aware of?

I know Smart Objects are used VERY broadly in many games, it's something i'd have needed to write on my own but since it's already here in the engine i figure i should just use that.

#

For Example, i'm planning a Star Wars:Republic Commando esk game where you order AI to take up bespoke Defensive Points, where they more-or-less turn into turrets until you tell them to leave. Only 1 unit can be at a point at a time, and most of what changes is they just enter a different state (new anim, don't move, change weapon).

That sounds like a solid use for the smart system. THe reservation means two units won't take up the same spot, and all the spot really needs is just some info for the squad member to read, no logic of it's own.

There's nothing stopping me from just writing a tool like that myself, it doesn't seem complicated, but again since the system is here i figure i should use it?

misty wharf
#

At least for a usecase like yours one thing that comes to mind is that it could end up being kind of static

#

Eg. if you order a squaddie to defend a location, they would just move up to the smart object and do their thing, so you'd end up having to define a lot of them for every single thing that can be done there, and for multiple positions too maybe

#

not saying it's not possible but there might be some design considerations for it

neat heron
#

That's fair, if it was a more robust system with more options then yeah that would be trouble. At least in the thing i'm aping from, there are like 3 different kinds of Defensive Spot, and each spot tells the Squaddie to either Snipe, Throw Grenades, Use Turret, and such. You can tell at a distance which kind of spot it is, there's not much decision making that needs to go on AI wise.

#

I'm trying to keep stuff straightforward and simple, so going for the most static (Green cover is alwyas Snipe cover, in Sniper Cover AI always use Sniper Animation_1, and always uses AI_SNIPER_GUN) seems like a good way to do it. If it was gonna be a more dynamic system, then yeah needing to define so much so often would def be an issue, that's a good point.

stiff linden
#

So, as much as I am looking, there doesn't seem to exist a function that could be called from an aicontrller or a behavior tree that simply turns the character according to a given Rotator.
How would I go about implementing that myself? Still a bit unsure about how things are structured. Basically I'd write an analouge to Move To, so Rotate To I guess?

misty wharf
#

you just set rotation

stiff linden
#

I mean a smooth rotation over time

#

do I use Event Receive Tick AI?

misty wharf
#

iirc there is a value on the character movement comp which controls how fast it can rotate, combined with that I think you can use set focus or something to have it turn facing a certain point

#

or something along those lines

stiff linden
#

right

#

But I don't have such a point, I only have the rotation

#

I mean I guess I can construct one

misty wharf
#

yeah to manually smoothly rotate you can RInterp the rotation over time in tick

stiff linden
#

but that seems like an inefficient way

#

That response can you can add for both your last statements πŸ˜„

#

and the Event Receive Tick AI is the right place for that?

misty wharf
#

if you're doing it in a BT node that would probably work yeah

stiff linden
#

Other question: I used to move my AIController controlled pawn with AI Move To. Now I changed it a bit that the PlayerController references an AIController that owns the Character. However somehow this broke the AI MoveTo function. Broke as in, it just doesn't run at all. No completed, no failed, no movement.

misty wharf
#

just having a ref to the ai controller from the player controller shouldn't do anything like that

#

a ref as in a variable that contains it

minor relic
#

Hi guys, is there a way to avoid casting a Task, I want to call my AIEnemycontroller from the Task that runs the Behavor tree, but I was told that Casting is not recommended and that there are other ways, but I do not know which ones. 😦

astral epoch
#

Anyone have experience with running AI functionality on client-side (i.e. NM_Client)? Entire AI system is not instantiated on the clients by default, but it seems I can enable it with Engine.AISystemBase.bInstantiateAISystemOnClient=True in Engine.ini.

Just wondering if there's any pitfalls/gotchas with turning this on. For example, to run target reticle rendering based on EQS query results, client-side-only.

wet ether
#

Is there some kind of collision that AI can't hear through? Let's say that i want AI not to hear me making loud noises through a specific wall. How do i do that?

teal imp
#

Is ai really the hardest math wise when coding?

#

I've heard it is

#

Let's say like in an fps as an example

neat heron
#

@teal imp I don't think it's any more or less math focused than doing other gameplay coding, but alot of AI is build around complex movement, and movement requires knowing something about vector math.

the difficulty is more about knowing what kind of ai you need to build that's best for the game you're making. "good" ai doesn't really mean anything, it's a matter of if it can solve the problems you need it to solve.

teal imp
#

Alright I think I get it

neat heron
#

The trouble is there's 1000 ways to do it. If a bad guy needs to know where hte player is, there's alot of ways to Get that info, store that info, and share that info. it could be all on the unit, the ai could be talking to some scene observing mastermind, every action anybody makes could be preplanned, it's up to you! And it's not like there's one best answer, each answer is kinda bad and annoying and you just make the best of it.

#

Game Development: Everything is bad and annoying but you make the best of it.

teal imp
#

Thanks

ocean wren
#

If you want maths, you probably want graphics or physics πŸ™‚

ocean wren
keen crow
#

how, if possible, to add custom blackboard property type without editing engine source? πŸ€” I'd really like to have FGameplayTag blackboard key instead of using FName every time

simple crest
#

Stuff it into a struct, the duct tape of unreal utried

#

Err no. Sorry. A UObject. The other duct tape of unreal

keen crow
#

right, I guess I just have to make one of those and register it in every way the other BB types are registered

keen crow
simple crest
keen crow
ocean wren
#

EVERYTHING is possible

#

just.. more or less difficult

#

Hmmmm, so I've got a lil bit of funding to do some unreal engine stuff over summer.. mainly something to do with AI and virtual production, but I want to do something related to PCG too.

#

I really wish epic would get on with things on the metahumans and actually do some decent clothing sets

#

Ok, so maybe nows the time to dogfood some of the PCG stuff and actually make a UE5 game using it.. at least as an experimental game

#

See how far generative art can get me πŸ™‚

#

Goddam this Dall-E 2 thing is... way too fun πŸ™‚

keen crow
#

How do (if they do) exposed UPROPERTY values stay unique on non instanced BT nodes? I want to have a TimeLimit decorator version with blackboard value time instead of direct value. I'm lazy so I'd like to just override the OnNodeActivation method and override the UPROPERTY() float TimeLimit in the child class and then call the parent method. But is it legal? I mean won't it override TImeLimit for every other running BT since the decorator isn't instanced?

misty wharf
#

There was some oddities with it in that they are partially kinda sorta still instanced iirc

#

So try giving it the uprop and see if it works

lean willow
#

Guys please answer me, does anyone know any youtube channel or blog about AI Unreal engine Advanced.?

misty wharf
#

your best bet is to search on google or youtube for the specific problem you're having

ocean wren
#

What specifically do you class as "advanced"?

celest python
#

I wonder how DOOM switches the behaviors when a specific event happens since they are using HFSM. Does the H (hierarchical) part helps in this case? For example AI is in a very deep state where it can not jump to a higher node but you damage it, it becomes something different and starts using completely another behavior. I thought they are switching the FSM asset directly but it also feels a little bit silly πŸ€”

#

If they wouldnt say they are using pure state machines, I'd say they are using something similar to state tree since it can switch nodes easily on a higher level

ocean wren
#

Well, yeah, a HFSM isn't anything particularly fancy. You just have to get your act together and figure out what transitions are allowed.

#

I actually kind of like statecharts which are just a matrix layout version of statemachines, where its a bit easier to figure out transitions

#

But the hierarchy definitely helps seperate out the major states. But doom creatures aren't massively complex anyway

minor relic
#

What is the Grid Path AI controller for?

ocean wren
#

I am guessing moving the agent along a grid path?

#

Think they had them in Fortnite back when it was a tower defence thingy

#

Or maybe in paragon

atomic coral
#

hey all.. anyone know of some way one could increase the cost of traversing a path that requires having the pathing agent rotate to take it? preferably without extending the entire Recast system

ocean wren
#

What do you mean rotate to take it?

#

You can definitely mess with the path cost for entry and exit of a navpoly

atomic coral
#

the actual AI has to rotate to face a path to take it, I'm trying to figure out if there's some way of extending the Filter to increase the cost for nodes that would require the AI to turn 90 or 180 degrees to take

ocean wren
#

nodes?

atomic coral
#

polys, links, areas, whatever we want to call them/nav through

#

basically, if AI is standing at point A, and there's 3 links to point B below, in different directions, I want it to choose the one that requires the least amount of rotation to turn through.

opal crest
#

I don't know of any built-in way to do this. Especially considering that the final turn angles aren't decided until after string pulling.

ocean wren
#

hmm, I guess you could calculate the angles after string pulling, but thats after its already generated the path

atomic coral
#

right now, it will always choose the exit from point A that has the shortest path to point B, but I want it to consider that turning around 90 or 180 should increase the cost

ocean wren
#

No, you'd have to do some custom stuff for that.. I can't really visualize what it is you're wanting.. but its definitely not something I've seen in the code.. wouldn't be a huge issue, but it'd be custom C++ stuff

atomic coral
#

oh, for sure, custom isn't the issue, i just don't want to override the entire Recast system just to add a few points to a cost πŸ˜„

ocean wren
#

The pathing system doesn't have the notion of facing direction.. so there's no support for that

opal crest
#

If the specific angle doesn't matter, but rather the overall straightness of the path, there must be a way to modify the cost function to account for it.

ocean wren
#

Oh you wouldn't have to override recast for this.. just a few functions for the FindPath<whateveritscalled>

#

You're basically walking the navpoly's, not really that difficult

#

If you find the string pulling code, then work your way up from there to the FindPath code.. you should be able to understand the whole of what you need

atomic coral
#

What are you suggesting overriding here zoombapup? I was hoping to find something that would make sense in FNavigationQueryFilter, but i'm not..

ocean wren
#

I think its called FindPathAsync or some such? been a while.. but there's a function I think in the CMC that calls the find... which kicks off the normal pathfinder

#

the final path is returned after string pulling, so right around the handoff to the string pulling is after the initial path is created.. so look at the code that does the string pulling.. it'll basically give you a clue for the structure of that

#

I just did some paths and single stepped the whole way through, until I understood it.. then bodged in what I needed

#

understanding navpoly's and how it calculates costs for entry/exit.. But yeah, it doesn't afaik have any notion of directionality, so you'd have to write a custom FindPathWithFacing or something

#

And in reality you'd have to do a non A* through the navpoly's because the whole point of that is shortest path

atomic coral
#

well, what i'm thinking, is - if i could find where filter actually filters anything - when the query is made, cost a poly that is 180 behind me as 10x, and a poly that is 90 to my left/right as 5x .. and then that should make it Just Work

opal crest
#

If I were doing this in not-unreal I'd just modify the cost function. Normally A* uses manhattan distance or something similar, but you could use a weighted manhattan distance + dot product or something.

ocean wren
#

instinct is telling me that wouldn't work.. but I cant explain why πŸ™‚

#

worth a try πŸ™‚

opal crest
#

Your instincts are going to better than mine πŸ™‚ I wonder if you'd get some non-intuitive results that way.

ocean wren
#

Yeah, feels like the case.. but I'd have to see it in action.. edge cases tend to popup in this sort of thing

atomic coral
#

it's a pretty limited system -- the idea is that you've got a path that you can get into from 4 directions, but you want to exit it going in the same direction you started. There's a set of links for each entrance and exit

ocean wren
#

so its not a navmesh?

atomic coral
#

it's a navmesh, but there's link proxies between parts of it

ocean wren
#

so are you following the navmesh or the proxies? πŸ™‚

atomic coral
#

and if you enter the entrance link from the 'north' facing 'south', i want the AI to use the 'south' exit link rather than the 'east'

ocean wren
#

So you want to increase the cost of backtracking?

#

So its really only the local navpoly's you care about then? not the whole path?

atomic coral
#

ultimately, yes.

celest python
atomic coral
#

I figured if NavQueryFilter could be used as an actual filter, i could just check the distance and direction of a given poly, and if it's close and in the wrong direction, return a much higher cost

#

alternatively, it seems there's something involved in a Detour system, but documentation and internet experiences with it seem to be zero

ocean wren
#

There's a bunch of formulations, but usually there's just a "StateState(stateid)" kind of thing

atomic coral
#

oh. i wonder if i could override the Area to do it

ocean wren
#

As I said, I like statecharts.. which is basically a matrix of states

#

Haven't seen heirarchical statechats now I think about it.. that'd be interesting

celest python
ocean wren
#

Yeah, so setting a state, you'd check if its one of your children, if not you'd exit and it'd pass back up to the root

opal crest
#

I'm trying to find a reference to statecharts, and all I'm finding are UML statecharts, and various XML descriptors for state machines. Nothing that looks like a matrix to me? Am I on the right track?

ocean wren
#

It was a presentation at GDC I was at that discussed them.. might have a different name in other industries?

#

The main takeaway was that it was easier to design because you had all of the states mapped in the matrix and could tell which state transitions to which other state easily

#

We use it in graph neural networks a bit too..

opal crest
#

Right, that sounds pretty powerful. I assume it's a 2d sparse array with states as the X+Y coords and filled cells with one or more transitions?

ocean wren
#

Yeah, exactly

#

So you could tell if you forgot a state transition because the grid cell was empty

#

And could do stuff like making sure a state had something transitioning to it etc..

#

And of course it looked easier for designers, its basically a spreadsheet

opal crest
#

Right, and it would be pretty easy to build a typical visualizataion of that from the matrix (or vv) so you could take in the info in both ways.

ocean wren
#

Probably doesn't work that great for really complex HFSM, but seemed like a really nice usability design tool

#

Poor guy who explained it to the audience was shaking like a leaf though πŸ™‚

#

We were doing some presentations at the AI Summit, so my, this guy (can't remember his name) and another dude

#

me even

#

He had this bit of paper in his hand.. had to discreetly steal it from him, he was so nervous that it looked like he was waving a flag he was shaking so much πŸ™‚

#

I guess having like 500 people watching you got to him

opal crest
#

Ah, I've found the key to googling this. State Table.

#

No Doubt. I've presented to audiences that size and the terror is real.

#

Seems pretty popular in Electrical engineering.

ocean wren
#

Ah yeah, that looks right

#

Yeah, state machines are used in process control logic stuff a lot.. probably from there

#

Weirdly, I find that Behaviour Tree's are actually easier to understand if they're laid out as a tree view rather than UE's top down left right tree

#

Bit like Damian Isla's original halo version.. I just prefer it, I guess because the text of each node is more condensed as its horizontal

#

StateTree system should be good in that regard

opal crest
#

Yeah, that is a lot easier to read.

ocean wren
#

Its super easy to write tools for too, because most UI toolkits have listviews

#

i.e. heirarchical view widgets.. I mean why they didn't go with that is beyond me πŸ™‚

opal crest
#

Once you have something as powerful as EdGraph, why not use it? My current toy project is building a Graph editor for HTN's, so I can see the appeal.

ocean wren
#

Yeah, EdGraph is pretty fun

#

I'm using it for a few plugins, mainly ML stuff

#

It irks me that they don't have support for rounded rectangles.. I'd really love to properly edit the damn UI code πŸ™‚

neat heron
#

Howdy, question about Smart Objects. I went through the tutorial, but when i run it my character will find and activate smart objects, but will Use them without having to actually approach them. So they just play an animation in place, swapping between smart objects.
I've scoured the guide and as far as i can tell nothing's dif (though someting obviously is). When you're dealing with smart object, what in the process actually controls how close you need to be to activate it? It is on the object itself? Something in the Use detection? Is there some obscure Must Approach toggle somewhere?

ocean wren
#

Its on the object in the docs

#

Haven't done it myself, but that was something I saw in an example

neat heron
#

Yeah, that's what i figured. I guess i just find it weird that nowhere in the demo does it specify pathfiding, or moving towards the object, or how they're meant to navigate towards it. (i mean yeah it says put a navmesh down but i think the Use BP just wraps navigation into it??) I guess that's stuff that's hidden in the C++ code for the objects? Seems like a weird thing to not expose?

ocean wren
#

Yeah, haven't looked.. usually for smartobjects you'd give it a starting location/rotation and then just expect the animation system to take care of the rest

opal crest
#

In "Approaching the Smart Object" the docs seem to indicate that the agent is responsible for nagivating to GetSlotLocation.

#

At which point you call UseSlot.

#

But honestly, if you're trying this stuff, you're way ahead of me.

ocean wren
#

Makes sense.. so you can animate your character relative to some fixed offset and then just make sure your world objects have the same offset for the entry point and you're good

neat heron
#

Yeah, that's what i'm gathering, that there's something weird about Use that doesn't really expose the kind of info i think it should. Like my dude is Using them, it's activating, it's just not approaching.

#

i guess i'll scour the city example again, but that also uses stategraph and other tools so it's obscured.

ocean wren
#

Well, you'd approach it first, then use it

#

Normally you'd reserve it first.. then move to the use point.. then use it

neat heron
#

I would presume so, yes.

#

But that step doesn't seem to come up in the quick start guide

#

Which is what's weirding me.

ocean wren
#

I suspect that's because in the city samples their using zonegraphs

#

So the navigation isn't the same as a "normal" BT etc.

neat heron
#

the quick start page shows the final btree, and a gif of it workin' is the thing.

opal crest
#

Maybe BTT_UseSmartObject navigates too? But that would depend on you having the type of navigation it expects set up and working

#

Oh, I see, they have you build it.

#

The QuickStart and the Overview definitely disagree. One of them must be wrong.

ocean wren
#

Probably both πŸ™‚

opal crest
#

Haha.

tardy wolf
#

When creating a task for a Behaviour Tree, is it possible to specify what kind of object a key is? Or do I need to do a cast every single time the task is called?

#

The object in the Blackboard does have a base class set.

neat heron
#

@tardy wolf I might not be getting the question, but could you just get the key, then make a var out of it, and then use that moving forward?

tardy wolf
#

I currently have the keys being passed in as variables and using the Get Blackboard Value as Object nodes.

#

I don't have any Value as Subclass nodes.

#

Unless I'm misunderstanding your suggestion?

#

Tbh I'm not even sure if the cast is that expensive... but I do know that I'm going to be calling this particular task quite a lot so I don't want to find out at a later date that its killing performance.

opal crest
#

You have to have a navmesh, but otherwise the 'Use Claimed Smart Object" node seems to magically know what to do.

#

Yeah, it composes an AIMoveTo gameplay task with the smart object trigger behaviour call.

opal crest
tardy wolf
#

Okay so I take it I will always have to cast if its not one of the above value types?

opal crest
#

Yep. If it's really performance critical you might need to find a sneaky c++ way to providing access to the object without casting. Or provide needed data without using a UObject.

neat heron
#

@opal crest I'll look over my stuff again, maybe something's borked with my char's navigation? god knows. but i'll take another look later, much appreciated.

atomic coral
#

wow. this path filtering code is the absolute most brutal thing i've seen in a long time

neat heron
#

Which in particular?

atomic coral
#

well, i'm figuring that there has to be some way of supplying a filter implementation, without also overriding everything else. Trying to trace it out, unless i'm missing something blatantly obvious, is just not hitting anything though

#

the default filter system clearly functions, but ... how?

#

I think I've found where I want to connect -- FPImplRecastNavMesh::FindPath eventually comes out with a dtQueryFilter... so, what I think I need to do is subclass dtQueryFilter ... somehow point UNavigationQueryFilter to use the new one... and then figure out a way to connect the Owner of the query.... dammit.

#

like.. the whole path following thing is based on costs, and there doesn't seem to be an actual way of changing the cost on a per-nav poly basis at runtime.

mint terrace
#

hmm isnt that what navmodifiers are for

atomic coral
#

as far as i'm aware that's static

mint terrace
#

thats true if you dont use dynamic navmesh generation

#

actually im not sure thats true even with static navmesh generation

#

no yeah you definitely should be able to add/remove/modify nav modifier volumes at runtime

#

well

#

actually im not sure you can move them

#

but you can modify their cost affect

#

If you need them to be added/removed/moved at runtime, then I think only dynamic navmesh generation would work for that

#

at least, with Recast

atomic coral
#

hmm. I think if I can figure out how to extend FRecastQueryFilter i think i can get there

mint terrace
#

have it return your new UNavigationQueryFilter subclass

atomic coral
#

you can just set a DefaultNavigationFilterClass to handle that part of it.. it's figuring out how to alter code that actually affects it -- the calculations appear to only be done the first time a filter is used

#

what even is a class that begins with F .. i thought only ustructs were to begin with F.. but apparently also classes that don't have UCLASS ? hmmm..

mint terrace
#

yeah i think its just "not a UCLASS" but i dunno Β―_(ツ)_/Β―

#

i mean its not like the recast codebase follows unreal conventions very well

#

"dtNavMeshQuery" (well thats detour, but yeah), methods like "updateLinkFilter"

atomic coral
#

right, i see why they're doing a bunch of passing things between layers.. but IMO major oversight not including an actual API that just serves as an actual implementable nav filter, without having to go through.. ::waves hands:: whatever this is

mint terrace
#
#

layering violations

#

if the "dt" is "detour" in dtQueryFilter

#

i feel your pain this code is... something else

#

the post may be outdated, or they missed:

    virtual void InitializeFilter(const ANavigationData& NavData, const UObject* Querier, FNavigationQueryFilter& Filter) const;
#

no actually that couldn't work either with just a reference

#

@atomic coral how did you get your filter in there to start with?

atomic coral
#

set it in AIController as the DefaultNavigationFilterClass for this specific AI

#

the current one is just a blueprint that has some numbers filled in

mint terrace
#

i meant FNavigationQueryFilter but i guess thats the goal

atomic coral
#

Right now I'm trying to do what RecastFilter_UseDefaultArea does ...

mint terrace
#

ok i think im starting to grok this stuff a bit more

atomic coral
#

huh. no idea if what i've got is going to actually work, but it compiles, which is a pretty huge step

mint terrace
#

so youve got it all wired in down to providing a filter implementation (INavigationQueryFilterInterface) in InitializeFilter() for your filter, probably extending from FRecastQueryFilter (which inherits dtQueryFilter and implements INavigationQueryFilterInterface), and then implementing getVirtualCost()

#

But then getVirtualCost() only gets called once?

atomic coral
#

that i'm not sure of. I've just successfully built something that compiles for the first time doing all that

mint terrace
atomic coral
#

previously i was tracing down what was happening inside UNavigationQueryFilter to see if I could hijack that somewhere

mint terrace
#

i think you are on the right track doing what UseDefaultArea does-- getVirtualCost() is probably what you need to override

#

so then its the question of getting your querier down here

atomic coral
#

i should be able to cache that from InitializeFilter

mint terrace
#

oh yep

#

OK i think that works

#

now have fun implementing haha

atomic coral
#

what a mess, and no wonder no one has posted about going that way without also just overriding the rest of it too

mint terrace
#

that poster clearly missed this implementation redirection system

#

i doubt its new

#

i was missing it too

atomic coral
#
#

which seems to indicate that you have to go through overriding the agent and much of the rest of it

#

but i'm pretty sure that this way will work...

#

i overrode and put breakpoints on passVirtualFilter and getVirtualCost just like RecastQueryFilter.h says to do, but no breaks. argh.

mint terrace
#

lol

#

Solution #3 shows you how to subclass dtQueryFilter, but it’s probably not your best solution - unless you’re invested into implementing your own Recast/Detour solution for UE4.

#

that makes no sense

#

Unfortuantely, you would then have to throw out ARecastNavmesh, and start implementing your own subclass of ANavigationData in the same fashion that ARecastNavmesh does - hence why this is the hardest option.

#

this doesn't appear to be correct at all

#

they probably missed the Initialize route with the implementation misdirection too I guess

#

why would you have to throw out detour to reimplement detours query filter

#

the docs themselves say this is possible, but they just don't spell out how to go from unavigationqueryfilter to frecastqueryfilter

atomic coral
#

ok so, i shouldn't need to do anything with FNavigationQueryFilter, other than just fill it in right

mint terrace
#

not sure how passVirtualFilter fits in--- if you break in FindPath, are you seeing your instance?

atomic coral
#

where is this FindPath ..

mint terrace
#

the recast navmesh impl one no?

atomic coral
#

yeah i found it, over in PimplRecastNavMesh... not sure how to tell if it's mine or the original...

mint terrace
#

that guy should be an instance of your class

#

or

#

well

#

FilterImplementation too

#

since

#

That's a weird method there isnt it

#

huh, why do they do that

#

There's no interface magic there, no other implementations, its not virtual

#

would it not be valid to (dtQueryFilter*)FilterImplementation for some reason?

#

i think this is just some convention / "prepared for the future" thing

atomic coral
#

yes i'm sure preparing for the things marked "// @TODONAV"

mint terrace
#

its fine, they had whatever came first, then detour, then recast detour, then detour crowds, and now mass crowds

#

why fix all the bugs

#

or missing functionality

#

when you can just scrap and rewrite leaving the flaming garbage pile you left behind

atomic coral
#

some months ago i was digging around for some feature that i knew was in the code a long time ago, and found the section commented out with "// TODO: reimplement" or some such

mint terrace
#

yeahhhhhh

#

navigation in unreal is a serious mess

atomic coral
#

ok, so, AI controller has the right filter set as default... OH i wonder if i'm overriding it in the MoveTo..

mint terrace
#

right, fighting the attempts of the past

#

im really sorry for the harsh words, to any Epic (or licensee) dev who had a hand in writing this code, as we lambast the work you did during crunch 😦

atomic coral
#

if there was just a simple public interface that was given the poly info and returned a cost modifier, this could be as complex as anyone could possibly ever make it, and it wouldn't matter to me

mint terrace
#

where would you defer the responsibility? im thinking a querier interface or something

#

querier->controller?

#

(im not sure if the querier is the controller or the actor here)

atomic coral
#

passing it up to the UNavigationQueryFilter would be really great

mint terrace
#

im not sure that works

#

the inputs to getVirtualCost are the polys, but the navigation abstractions should support navigation systems that are not polygon based

#

i think operating at this level does require you to be working within the particular details that detour as a navigationsystem implementation requires

#

to abstract it up to UNavigationQueryFilter feels like it would expose that implementation detail and eliminate a lot of potential implementations of the abstraction

#

not that it seriously matters

#

because im not sure its totally possible to skip it all (detour) anyway

#

but i think thats the idea of it

#

honestly given how.... special.... detour and the builtin navigation system is, i bet there are a fair number of licensees totally replacing this system for their games

#

that's why i figure adding an inversion of control as an escape hatch out of the layered implementation for ease of implementation may make sense: basically make this part of detour pluggable without having to subclass the innards

#

but on the other hand -- the docs are pretty insistent that overhead here is highly undesirable, presumably because it gets called every frame on the game thread

#

i wonder if it worked

atomic coral
#

i'm still trying to figure out how to tell what's happening

mint terrace
#

still not seeing your instance in the debugger?

atomic coral
#

unsure, it just says it's a dtQueryFilter

#

which.. duh.

mint terrace
#

I think the object value should show it's class

#

it's definitely not just a dtQueryFilter

#

as that gets subclassed even in the default implementation

#

at least if my understanding is correct

#

regardless, your getVirtualCost should be firing, even if you just check() in there

atomic coral
#

i'm getting an occasional fire of an ensure in AIController::MoveTo that doesn't make sense

mint terrace
#

which one

atomic coral
mint terrace
#

well that obviously shouldn't happen...

#

oh wait there's a !

#

ahhh πŸ€”

atomic coral
#

yeah this has been happening for a little while but i'm the only person who's noticed it for some reason

#

that ensure feels wrong

mint terrace
#

yeahhhhh

#

assert that: either the move request specifies its own navigation filter, or there is no default filter ?

#

that cant be right

atomic coral
#

no default filter should equal the ini default, i think

mint terrace
#

damn

#

I think the intent is: If you specify DefaultNavigationFilterClass then you cant use MoveTo() ?

#

but why

atomic coral
#

that sounds awful

mint terrace
#

oh, rather, you cant use the move request system

#

because MoveToLocation() is fine, it actually uses DefaultNavigationFilterClass

#

still awful

#

Nonetheless, you can still bypass that

#

might be worth it if the ensures are telling you this isnt a good idea

#

after all, i doubt every single actor in your game should be bound by this rule

#

it would be better to gate it at the controller so that you can still use the default behavior when this special behavior is not required

atomic coral
#

well funny thing it eventually sets it all to DefaultNavigationFilterClass if it's not set coming in anyway

mint terrace
#

the move request will have one defined

#

because it just gets it from aaicontroller

#

or do you mean: that itself gets ignored later?

atomic coral
#

my brain is melting switching between Ryder and Visual Studio lol .. Ryder is easier to research things, but doesn't work for me for anything else

#

i also hate Ryder's text editor

mint terrace
#

i use rider myself

#

im not a huge fan of jetbrains but the unreal specific nature, and the very good large codebase symbol caching and general ease of use after the learning curve---

atomic coral
#

that's how much i use it, i thought it was spelled with a Y

mint terrace
#

nonetheless --- the key here is that DefaultNavigationFilterClass is a feature of the default AIController class

#

if you subclass and customize, then DefaultNavigationFilterClass is not a thing

#

i dont know if it matters, but it might be wise to heed the ensures(), until you are sure that the ensure() is the bug

atomic coral
#

yeah.. i think i needed to add it to my behavior tree task that calls moveto .. it was not filling in the filter if none was given, thinking the lower code would fill it in

mint terrace
mint terrace
#

erm

atomic coral
#

ok not getting the ensure now

#

i'm hitting the constructor for my UNavigationQueryFilter several times at startup, but not hitting anything else

#

ok, how should I construct my FRecastQueryFilter? I'm just declaring one in a namespace, like the original does, but .. i'm not hitting anything in it

mint terrace
#

Ohhh--
UNavFilter_AIControllerDefault subclasses UNavigationQueryFilter, and when it implements GetSimpleFilterForAgent() it returns the AIController::GetDefaultNavigationFilterClass(). This is what they mean by the querier-specific filter.

atomic coral
#

one thing i don't see is hitting the constructor in my U filter after i hit play

mint terrace
#

are you actually using that AIController for the agent?

atomic coral
#

it better be, when i changed it he pathed differently

mint terrace
#

oh what filters are you defining on the actors

#

because you just need the default UNavFilter_AIControllerDefault to do it

#

but i wonder if you've changed those

atomic coral
#

defining where?

#

oh i just got a breakpoint hit at startup in my RecastQueryFilter.. i don't think that happened last time. interesting.

mint terrace
#

ugh i thought DefaultNavigationFilterClass was a global-- but you were already doing all of this πŸ˜’

#

its all property-scoped

atomic coral
#

ok it's hitting my InitializeFilter on first path

#

CreateCopy() is creating an instance of my FRecastQueryFilter, apparently

mint terrace
#

that sounds* right

#

or at least a copy constructor

#

if you haven't defined one and it's no-args then yeah

atomic coral
mint terrace
#

black blob means "most anticipated AAA hit :-D

atomic coral
#

it's probably not hard to look me up and find out what i work on lol

mint terrace
#

blade things I'm sure

#

anyway that should be good yeah

#

that thing is the dtQueryFilter

atomic coral
#

i wonder if twiddling with bIsMetaFilter or bInstantiateForQuerier would do anything

mint terrace
#

ohhh

atomic coral
#

i swear i can code, but the layers here.. crazy

mint terrace
#

if you are not getting valid querier in InitializeFilter or InitializeFilter is only running once, then that would make sense

#

i think.... somehow.... that default AIController implementation of the NavFilter is always there

#

even though it seems like you would override with DefaultNavigationFilterClass to replace that i wonder if its not the case

#

bInstantiateForQuerier is protected

atomic coral
#

no change with those

ocean wren
#

If you want to debug it, stick a breakpoint in the constructor, note the address of the this pointer.. then when you come to use the filter, check the address of it in memory

#

Good reading you two figuring this out by the way πŸ™‚

atomic coral
#

@mint terrace ... so.. shouldn't it be hitting the constructor in my FRecastQueryFilter when it goes through CreateCopy() which does a new(*this) ?

ocean wren
#

The reason the recast code looks so weird, is that Mikko, the guy who wrote it, is from the demoscene and one of the things you do there, is just allocate a block of memory and read/write stuff from that.. it kind of forces a different code mentality. That and usually these guys are not CS trained.

atomic coral
#

SetFilterImplementation does
QueryFilterImpl = MakeShareable(InQueryFilterImpl->CreateCopy());

#

CreateCopy does return new FRecastQueryFilter(*this);

#

at that point, I'd expect the breakpoint in my FRecastQueryFilter to hit

#

or.. that's just creating a new pointer isn't it, not a new filter

#

... or...

ocean wren
#

stick a breakpoint in your constructor and look at the call stack? or stick a breakpoint in that CreateCopy func and see what it returns?

atomic coral
#

the FRecastQueryFilter is only being hit at editor startup

ocean wren
#

So does that CreateCopy ever get called?

atomic coral
#

yeah, it's returning a void pointer to 0x000001f4a62de200 ..

ocean wren
#

But that doesn't call the FRecastQueryFilter constructor?

atomic coral
#

it does not

ocean wren
#

Not even the base class?

atomic coral
#

good question

#

ok at InitializeFilter, Filter.QueryFilterImpl is now also a ptr to that same address

#

i can't breakpoint FRecastQueryFilter constructor

#

there is no implementation for a constructor there

#

ope, there it is.. over in PImplRecastNavMesh ..

#

@ocean wren yeah base class constructor isn't hit at game startup or at path find either

ocean wren
#

So heres a question.. your passing your query filter in FPathFindingQuery?

atomic coral
#

it is set as the default query filter for the AI

#

and i'm passing it also

ocean wren
#

Maybe stick a breakpoint on that SetFilterImplementation? see where its called

#

Hmm, seems only two places can call it

#

Well, three if you count the constructor

#

Seems like ANavigationData returns the filter implementation

#

NavFilter->SetFilterImplementation(NavData.GetDefaultQueryFilterImpl());

#

Guess it makes sense, means that Recast version of ANavigationData returns a recast filter, I assume that the grid based pathing returns a grid based filter

mint terrace
#

just finished eating

ocean wren
#

Welcome back

mint terrace
#

that's insightful @ocean wren

atomic coral
#

ok, so, the SetFilterImplementation is giving me a pointer to -- presumably? -- my filter, and FindPath is getting that same pointer as FilterImplementation

ocean wren
#

so you need to test that assumption

#

is it YOUR filter or another one

atomic coral
#

the QueryFilter is... 8 bytes higher

mint terrace
#

wait it's not doing some trickery to skip the constructor is it?

atomic coral
#

the constructor in my FRecastQueryFilter is only hit at editor startup

mint terrace
#

sounds like uclass cdo?

atomic coral
#

it's not a uclass at all ..

mint terrace
#

ohh ok no

ocean wren
#

Where does the call stack on your constructor say its being created?

mint terrace
#

it's the level of indirection

#

that first one is supposed to create the second one that's querier specific, yeah?

#

it's at editor startup because that's engine start

atomic coral
#

yea it's being called in EnginePreInit ... down to LoadStartupModules

ocean wren
#

It seems to me, that the Query filter has the filter implementation provided to it by the navigation data

mint terrace
#

oh wait, getting triggered by the AAIController subclass CDO

ocean wren
#

So the question would be, is there a function to set the impl on the navigation data class

atomic coral
#

am i constructing this thing correctly, by just creating one in a namespace, and then referring to it?

mint terrace
#

the filter implementation (can) be set in InitializeFilter()

#

thats what URecastFilter_UseDefaultArea does, with Filter.SetFilterImplementation()

ocean wren
#

Hmm, so UNavigationQueryFilter is a UObject

atomic coral
#

let's try overriding CreateCopy in my recastqueryfilter and see if that hits

mint terrace
#

oh ok

#

so

ocean wren
#

It looks to me, that the QueryFilter is taken from FAIMoveRequest

mint terrace
#

virtual GetSimpleFilterForAgent(Object &Querier) is probably getting called on your instance

#

have you overridden that

atomic coral
#

i have not

mint terrace
#

thats what zoombapup means by the navdata taking over

#

you want the red path, but the navdata providing is the non-red path:

#

the issue is here, there is no way to memoize the querier?

#

if you return yourself as this TSubclassOf, it would make a new one per agent (read: actor mostly)

#

thats implementing GetSimpleFilterForAgent which is virtual

atomic coral
#

hey! my CreateCopy is the one being called

mint terrace
#

if it is not true that (*SimpleFilterClass), then control falls through to the navdata's choice

#

and the default impl is

ocean wren
#

Ok, here's how I would do it: If you look at AAIController

#

PreparePathfinding

#

Query = FPathFindingQuery(this, *NavData, GetNavAgentLocation(), GoalLocation, UNavigationQueryFilter::GetQueryFilter(*NavData, MoveRequest.GetNavigationFilter()));

atomic coral
#

ok, so, if that's correct, then we need bIsMetaFilter = true

ocean wren
#

Pass your own query filter there

atomic coral
#

this almost makes me want to go back to operating systems development πŸ˜„

mint terrace
#

is it accessible?

atomic coral
#

sure, i'm overriding that class

mint terrace
atomic coral
#

ok, GetSimpleFilterForAgent(*Querier) returns null the first time through

#

and again the second time thru

mint terrace
atomic coral
#

instantiate and metafilter are both protected

mint terrace
atomic coral
#

PreparePathfinding goes to BuildPathfindingQuery .. let's see what's in there

mint terrace
#

the idea is you would override that and do SetNavigationFilter

#

instead of using the default class field

#

it doesn't solve retaining access to the actor/controller though

#

because SetNavigationFilter is still a class

#

and im not sure that it still wouldnt end up in the GetSimpleFilterForAgent() path

#

at which point, youd either have to take it for that querier, or you get the navdata's default which isn't your class

#

ohh wait no you can get the querier its going to the CDO

#

Maybe this isn't actually going to work --- A "meta filter" selects a different filter class given the properties of the incoming agent (querier)

#

No matter what you do, ultimately it will resolve to a "simple filter"

atomic coral
#

ok in GetQueryFilter ... SharedFilter = nullptr regardless of which side of the ternary it takes

mint terrace
#
FSharedConstNavQueryFilter SharedFilter = bInstantiateForQuerier ? nullptr : NavData.GetQueryFilter(GetClass());
atomic coral
#

ooh, gotta wait til the second time thru to get a value there

mint terrace
#

Yeah but its going to go to the NavData and ignore everything you set up on the AAIController

atomic coral
#

efffff

mint terrace
#

and that implementation is not virtual

    /** get cached query filter */
FSharedConstNavQueryFilter GetQueryFilter(TSubclassOf<UNavigationQueryFilter> FilterClass) const;
keen crow
#

is it possible to politely ask epic games to add certain feature to SmartObjectsModule and where would be the best place to do that? github issue? answers.unrealengine.com/? πŸ€”

ocean wren
#

Join the mass channel and let the guys there know, they're talking to the Mass guys right now

#

and SmartObjects is kind of part of mass

#

Theyre talking to the Epic devs of mass that is

mint terrace
#

yes FMegaFunk Enterprises, LTD πŸ˜›

atomic coral
#

ok, so, if we want this to have a hope of getting the right thing, we need GetSimpleFilterForAgent(*Querier) to return something right

mint terrace
#

i think so

#

you can just return your own UNavigationQueryFilter class

atomic coral
#

yeah... this might be the key. did we mention this already? if we did and i missed it or dismissed it, i apologize

keen crow
mint terrace
#

i did mention it... i think?

mint terrace
ocean wren
mint terrace
#

with the meta filter flag enabled

atomic coral
#

why isn't the default implementation for that to return GetClass() or something useful lol

ocean wren
#

If you hang in #mass for a bit, you'll get a better feel for whats in there

mint terrace
#

which btw, is actually still relevant

#

well, eh

keen crow
mint terrace
ocean wren
#

Well, nobody really has a good handle on it yet, MegaFunk and the others in #mass are working it out and doing docs.. the Epic devs are helping them a bit and taking requests

#

absent proper docs and all, a community effort makes sense, but I wish epic would get its shit together and schedule documentation as part of development

mint terrace
#

or at least some more inside unreals

atomic coral
#

@mint terrace ... so... it only hits that path if bIsMetaFilter is true... but then it queries the Default Object, and only hits the useful part of that if it's bIsMetaFilter is false. What?

mint terrace
#

ohhh wow

#

do

#

do they need to be two classes

#

so you can have one metafilter + one regular one?

#

that does seem crazy

atomic coral
#

yes. i.. haven't used DefaultObject much since UE3, so I'm not real sure how that would work

mint terrace
#

thats just the object your constructor sees

atomic coral
#

in UE3, i'd just set the defaultprops to false, and then set it in BeginPlay lol

mint terrace
#

each UClass (class with UCLASS attached) has a CDO (Class Default Object), which is created when the UClass is loaded

#

but that doesnt matter -- you would need 1 class that has bIsMetaFilter=true with your GetSimpleFilterForAgent() implementation in it, and one more that is bIsMetaFilter=false that has your InitializeFilter() in it, where you set the filter implementation

atomic coral
#

that's terrible.

mint terrace
#

at this point im hoping it works because this is a crap load of boilerplate

#

hahahaha

atomic coral
#

i just commented that check out, let's see what happens

mint terrace
#

which check?

atomic coral
#

if (DefFilterOb->bIsMetaFilter == false)

mint terrace
#

ahh custom engine build i guess

atomic coral
#

....

#

you might not believe the results

#

now i know what that does lol

#

it is quite obvious now looking at it what it does.. lol

mint terrace
#

huh?

#

this is like click bait

atomic coral
#

it infinite loops, calling itself

mint terrace
#

that... probably makes sense why you'd need two classes eh

atomic coral
#

or... was returning GetClass() from GetSimpleFilterForAgent not the correct play

mint terrace
#

well like you said

#

it's checking the meta filter param and then delegating a class reference lookup to that meta filter.

#

and it disallows recursive meta filters

atomic coral
#

if i'm not mistaken, this will just cause it to hit the not meta filter path, and return the bad thing anyway

mint terrace
#

I think you're right :-(

#

subclassing UNavigationQueryFilter must only be intended for meta filters

ocean wren
#

I think you guys are overthinking it.. surely PreparePathfinding and overriding the QueryFilter there is all you need to do?

atomic coral
#

NavFilter_AIControllerDefault .. how does that not run into this

mint terrace
ocean wren
#

The query that PreparePathfinding creates then gets passed to: FPathFindingResult PathResult = NavSys->FindPathSync(Query);

mint terrace
#

however, not clear how you could use that to maintain the querier reference, unless that gets attached to the instance for you

#

but that's not solved the other way either.

atomic coral
#

i don't even see what you're looking at zoomba

#

i may have spent entirely too long staring at this

ocean wren
#

Query = FPathFindingQuery(this, *NavData, GetNavAgentLocation(), GoalLocation, UNavigationQueryFilter::GetQueryFilter(*NavData, MoveRequest.GetNavigationFilter()));

mint terrace
#

so i guess

ocean wren
#

When it prepares the pathfingind query, it constructs this Query object

#

Then in requestpathandmove it uses that query object:

#

FPathFindingResult PathResult = NavSys->FindPathSync(Query);

#

Inside the query object is the navigation filter

#

So something like:

#

Query = FPathFindingQuery(this, NavData, GetNavAgentLocation(), GoalLocation, MyNavFilter);

mint terrace
#

PreparePathfinding() is deprecated and unreferenced?

ocean wren
#

No its not

mint terrace
#

what class? AAIController?

ocean wren
#

its got an implementation higher up

#

yeah

atomic coral
#

are you using 4.27?

mint terrace
#

ohhh

#

(5.0.2)

atomic coral
#

it's deprecated in 4.27 too

mint terrace
ocean wren
#

an older version is deprecated

#

because they changed the interface to references

mint terrace
#

the above is a solution wide search for the name of the function

ocean wren
#

look at the code itself

#

although yeah, I might be on a diff version

mint terrace
#

i think its dead

#

its now FindPathForMoveRequest

#

still virtual

#

i think calling super and then overriding the filter class would be the way?

ocean wren
#

Well, you need to look at where that Query parameter is.. its created somewhere in AAIController right?

#

Which version are you guys on?

mint terrace
#

5.0.2 here, i assume they are on 4.27

atomic coral
#

yea i'm 4.27

mint terrace
#

the query is passed in probably with a default

#

but its reference, no const

#

the intention is to set up the query like PreparePathfinding() did, I think

#

just with a different API

#

yeah its the same API as PreparePathfinding() was, but with an additional FNavPathSharedPtr& OutPath tacked on the end

#

ohhhh

ocean wren
#

Yeah, basically, pass a different filter to the Query object, because that's where it gets it from for the pathfinding

mint terrace
#

prepare the query, then pass that query into the super

#
void AMyAIController::FindPathForMoveRequest(const FAIMoveRequest& MoveRequest, FPathFindingQuery& Query, FNavPathSharedPtr& OutPath) const
{
    Query.SetFilterClass(MyFilterClass);
    AAIController::FindPathForMoveRequest(MoveRequest, Query, OutPath);
}
atomic coral
#

so, what we're finding, though, is that even setting up the filter, it still ends up going to the Default Filter. I'm not sure that this would change that

mint terrace
#

it might not

#

its your last best hope

#

if its not this, im sorry

#

its time to reimplement recast/detour* like that fellow said

ocean wren
#

naah, you can defo fudge this

#

especially in a source build

mint terrace
#

well yeah

#

in fact that first post i linked, they did exactly that

#

just make GetQueryFilter() virtual on UNavigationQueryFilter

#

bam

#

do anything you want

#

i assume you for some reason really really dont want to do that

#

because its right there, you already edited out that check

atomic coral
#

yeah but editing that check out was not the answer to get there .. i'm still trying to figure out if there is a correct answer to get there or not

mint terrace
#

yep, try the path of setting the filter class on the move request

#

also holy crap

#

this code is ridiculous

#

trying to be too many things for too many people without the right layers of abstraction

ocean wren
#

needs a refactor for sure

#

but not gonna happen unless you do it yourself πŸ™‚

mint terrace
#

I think @atomic coral is volunteering

#

:-P

#

but that's also never gonna happen

#

it is already too many things to too many people

atomic coral
#

nope, i suspect my boss is going to be unhappy that i haven't found a solution for this in 12 hours, let alone if i took the time to refactor navmesh

mint terrace
#

well the escape hatch is there

#

sounds like y'all aren't afraid of a custom engine build

atomic coral
#

nope not at all.. i'm just not sure what the escape hatch would be there either

mint terrace
#

like I said

atomic coral
#

ah.. yeah could be

mint terrace
#

then just implement it and return your own damned F thing instead of even necessarily needing InitializeFilter

mint terrace
#

yep, try the path of setting the filter class on the move request
sounds like maybe this isnt changing anything?

atomic coral
#

i'm still back a few ideas before that on setting up two different classes

mint terrace
#

your rebuttal to the idea was convincing

#

these will be the same

#

and they aint virtual

#

if they're the same, then you are right, how can it not recurse a second time, and then fall into the default simple filter implementation path

atomic coral
#

i'm not sure what to return from GetSimpleFilterForAgent .. i guess I could add a property to select it from the editor

mint terrace
#

GetSimpleFilterForAgent can only ever usefully return a data-only subclass of UNavigationQueryFilter, so that you can change things like these:

#

and then you can modify what subclass you use based on the state of the actor/controller when the navigation occurs

#

GetSimpleFilterForAgent can only ever [seemingly] usefully return

#

but why is this different?

#

wouldnt this InitializeFilter() forever be useless, even if you assigned URecastFilter_UseDefaultArea's UClass* to whatever filter class property?

#

probably because, in fact, the move request's implementation skips the indirection we've been grappling with

#

hmm i guess its actually Query.QueryFilter = myFSharedConstNavQueryFilter not SetQueryFilter()

#

wait oh crap its not a UNavigationQueryFilter at all

atomic coral
#

nope

mint terrace
#

@atomic coral well that will absolutely bypass all of that crap

atomic coral
#

hmm?

#

yea i think the two class thing is a no go, or if it is, there's something complex and misunderstood about it

mint terrace
#

implement FindPathForMoveRequest(), set Query.QueryFilter to (a value of) FMyNavigationQueryFilter, where that one's constructor sets QueryFilterImpl to an instance of FMyRecastQueryFilter

#

the FMyNavigationQueryFilter constructor could handle accepting the Querier but im not super sure what lifecycles we're talking about here

atomic coral
#

FindPathForMoveRequest should? already be receiving the UNavigationQueryFilter that has been pointing to the FRecastQueryFilter .. i'm pretty sure

mint terrace
#

you mean its pointing to FMyRecastQueryFilter ?

#

aka, your own FRecastQueryFilter sub.... erm struct?

atomic coral
#

yeah to mine .. i'm not entirely certain of that, because eff me if the debugger isn't telling me squat thru these layers

mint terrace
#

yeah but if your own filter class is running

#

then you should be receiving getVirtualCost() calls

#

thats literally the end of the road there

#

once thats in place, getVirtualCost() should be called

atomic coral
#

so, it selects my custom UNavigationQueryFilter, sets up a FAIMoveRequest with that set, then calls BuildPathfindingQuery on that

mint terrace
#

using InitializeFilter() there?

#

to get the FRecastQueryFilter subclass in place

#

if thats working, why arent you getting getVirtualCost()

#

that absolutely should be the case

#

i mean tell me you've tried UE_LOG in there

#

screw the debugger

#

debugger lies

#

especially ryder

atomic coral
#

getVirtualCost consists of a UE_LOG and a return dtQueryFilter::getVirtualCost(....)

mint terrace
#

and that is the dtQueryFilter that is observed in navmesh pimpl

#

same pointer? and when you step into getVirtualCost on that dtQueryFilter?

atomic coral
#

i'm... really not sure

#

ok, so, we have a UNavigationQueryFilter that is bInstantiateForQuerier = false, bIsMetaFilter false, implements InitializeFilter to call Filter.SetFilterImplementation(&EMyRecastQueryFilter::FilterPreferredFacing), which is defined as namespace EMyRecastQueryFilter { FMyRecastQueryFilter FilterPreferredFacing; }

#

FMyRecastQueryFilter is a subclass of FRecastQueryFilter, that is setting bIsVirtual true in it's constructor, and overrides passVirtualFilter, getVirtualCost, and CreateCopy() to do the same things as the base classes

mint terrace
#

as long as your InitializeFilter is called, that should be it, at least to have a custom getVirtualCost implementation

#

if you need the querier (which I have to imagine you do) then you'll need to move to a dynamic instance

#

but there be lifecycle questions

#

start with just getting anything custom returned from that guy and solve the rest later

atomic coral
#

... the UMyNavigationQueryFilter has a Blueprint, which defines some areas. That UMyNavigationQueryFilter is set both as the Default Query Filter in the AIController, and is used in most or all of the calls to BuildPathfindingQuery

mint terrace
#

well I have no idea about what the blueprints are gonna do for it

#

maybe try this on an isolated actor first, get rid of the blueprints

#

test first in isolation

atomic coral
#

ok, so, i just set the base class as the filter.
Initialize Filter called, our CreateCopy returns a pointer to 263a3386c00, then it goes to UNavigationQueryFilter::InitializeFilter() and sets up the Areas

mint terrace
#

sure, sure

atomic coral
#

This chain is being started by a MoveToLocation that calls BuildPathfindingQuery, which goes into GetQueryFilter

mint terrace
#

so youve overridden InitializeFilter as something like

    UNavigationQueryFilter::InitializeFilter(NavData, Querier, Filter);
    Filter.SetFilterImplementation(...);
#

to retain the superclass implementation

#

erm can you use Super there?

#

i dunno, unreal stuff

atomic coral
#
void UMyNavigationQueryFilter::InitializeFilter(const ANavigationData& NavData, const UObject* Querier, FNavigationQueryFilter& Filter) const
{
#if WITH_RECAST
        Filter.SetFilterImplementation(&EMyRecastQueryFilter::FilterPreferredFacing);
#endif // WITH_RECAST

    Super::InitializeFilter(NavData, Querier, Filter);
}
mint terrace
#

wow not that its relevent to solving the problem but... do you actually need WITH_RECAST?

#

how does that work anyway

atomic coral
#

i'm guessing that if you don't have the recast module building, that won't be set. it was in the original

mint terrace
#

ahh right

misty wharf
#

Probably unnecessary if you're just making this for your own game where you would always have recast :)

atomic coral
#

probably true yes

mint terrace
#

yeah that was my thought heh

#

"just in case we ship without it! you never know!!"

#

zomg hey, any thoughts here?

#

its been an all night battle

misty wharf
#

seems like it would always exist in all environments, unlike say ENABLE_VISLOG or whatever that one was

#

how far up do I need to scroll?

#

lol

mint terrace
#

ill sum it up

#

the goal is to modify the costs of nav mesh path segments (via detour navmesh polys) based on how much of a rotation will be required to get to it

misty wharf
#

ah yeah I think I saw the start of the conversation last night :D

mint terrace
#

the less rotation, from point A to point B, the less cost

#

the idea is to get down to subclassing dtQueryFilter

atomic coral
#

yeah this has been about 12 hours now

misty wharf
#

I haven't dug that deeply into the navigation system but at least it sounds like you're on the right track

mint terrace
#

...which is really just FRecastQueryFilter

#

that just takes dtQueryFilter and makes it implement INavigationQueryFilterInterface

#

the goal is to have getVirtualCost() get called passing in the relevant polys

#

wait a minute

#

@atomic coral you dont need the actor

#

the first point in the navigation path is the actor location

atomic coral
#

ultimately, the situation as it is right now, is i have three levels of navmesh. You start on one level, you nav to the middle level, and we want you to most likely exit out moving in the same direction you came in

mint terrace
#

hmm thats new

#

i see

atomic coral
#

if you enter the middle travelling east, we want you to exit travelling east, even if your goal has changed so that the shortest distance would now be to turn around and go north

#

because that 90 degree turn will take more time than hitting the exit you're facing

mint terrace
#

i see so you really do need the properties of the agent

#

because its not just about whatever path got computed

atomic coral
#

right, i want to add cost weight depending on other factors that aren't static

mint terrace
#

we have not yet established that youve got code running in the right place though

atomic coral
#

right

mint terrace
#

you have UE_LOG in getVirtualCost(), and it is not executing

atomic coral
#

just recapping in case zomg or someone else comes in with a completely different idea

mint terrace
#

yeah

#

We went down a lot of rabbit holes

atomic coral
#

because i will absolutely take an idea that doesn't involve changing path costs if it works

mint terrace
#

like how UNavigationQueryFilter supports "meta filters"

misty wharf
#

how complex are your levels? because a basic waypoint system comes to mind lol

atomic coral
#

yeah wtf is a meta filter, and a simple filter

mint terrace
#

i think a simple filter just changes those UPROPERTY on UNavigationQueryFilter and thats it

#

and a meta filter just chooses a UNavigationQueryFilter subclass to use based on the querier (controller)

atomic coral
#

ok, some of that makes sense when you explain it with a purpose

mint terrace
#

but then the GetQueryFilter of UNavigationQueryFilter is what goes from UNavigationQueryFilter to FNavQueryFilter (by way of a FSharedConstNavQueryFilter which is a const TSharedPtr)

#

and its not virtual

#

which means you must use the cache system

#

it calls InitializeFilter() to prepare your instance for a particular filter class, and then it goes a level of indirection down to an Implementation

#

FNavigationQueryFilter is really just a wrapper, apparently

#

SetFilterImplementation() accepts a INavigationQueryFilterInterface, and its this which would inherit from dtQueryFilter

atomic coral
#

OK, so, this run BuildPathfindingQuery hits GetQueryFilter(), which calls InitializeFilter, and that sets me up with my filter at e086980 .. and then it returns some other filter on the other side of the planet address wise

mint terrace
#

the only usage is here

#

in GetQueryFilter() as you say

#

it cant return anything but the SharedFilter that comes out of InitializerFilter

#

well assuming that Get() is returning a persistent pointer

#

it is dereferenced and then referenced.... ehm

#

should be mutable in place right?

#

it has to be, because the only reference to this in the codebase, is itself exactly what we want

#

other than instantiating something there to convey the Querier

#

here they use some static instances

#

i think possibly the debugger is tripping you up. if you are just jumping from place to place with breakpoints, perhaps there's other instances that arent using your AAIController

atomic coral
#

There's nothing in this setup except for the AI, it's pawn, and some world decorations

#

what is the relationship between the UNavigationQueryFilter and the FNavigationQueryFilter?

tardy wolf
#

Got this in a task

#

And I can see the task firing both in the Behaviour Tree and characters doing stuff in game

#

Any idea why the ticks aren't firing?

misty wharf
#

I don't remember if tasks tick by default, did you change the settings on the node to have it tick?

tardy wolf
#

Both the character and AI controller have tick enabled.

midnight scroll
#

You're sure that the task has not finished, and is being reached in the tree?

tardy wolf
#

Its lit up in the tree. It finishes when they reach the location which its definitely not doing in a single frame.

#

Actually gonna double check that.

midnight scroll
#

That's odd. Definitely should be ticking then.

tardy wolf
#

Okay some of them are finishing. There's 25 characters though and definitely not 25 strings being printed.

#

Yeah just tested with a single character. When he wasn't close enough to trigger the finish node it still wasn't hitting tick.

#

And when his pathfinding breaks (which is what I need the tick for) it does actually count the task's runtime up.

flint trail
#

I can't find any info about how to make flying AI 😦 Just something like Cacodemon from Doom. Any tips ?

misty wharf
#

Depends really on complexity of your levels and how it needs to behave

#

at simplest it could literally just follow your regular navmesh except in the air

flint trail
#

the part "in the air" is what I don't get

#

how do I make it not drop on the floor?

misty wharf
#

if it uses CMC, turn off gravity

#

in CMC settings

#

or set its movement mode to flying, that would probably be more sensible lol

flint trail
#

so, disable "can walk" and enable "can fly" ?

#

cuz I tried just enabling "can fly" in addition to other modes and it still drops to the ground

#

or do I have to disable gravity regardless ?

misty wharf
#

set the default movement mode to flying

#

pretty sure it had a dropdown for that

opal crest
#

I'm really pulling for all of you trying to customize the NavFilter. My first foray into UE C++ took me into the navigation code, and it's nuts.

visual silo
#

I have this AI setup already which seems to work but I'm trying to convert this to be not state-based due to some of your recommendation that BT's strength really comes in when you stop thinking about it as a state machine.

#

So I've made this version, which has all the same behavior but I'm missing the investigate--

#

Investigate in the original triggers when the AI hears something. How do I communicate this to the BT?

#

It seems like I need to push a "heard something event" and then maybe clear it in the BT side so it doesn't create bad behavior later. (The agent is supposed to walk over to the spot they heard something and then hang out for a little before going back to patrolling)

#

but that sounds a lot like state machine transitions 🀣

#

Any recommendations on how to architect this to add the investigate? Am I thinking about BTs right yet? 🀣

visual silo
#

Feels like I should clear the blackboard value after "consuming" it