Megafunk / MassSample

My understanding of Unreal Engine 5's experimental ECS plugin with a small sample project.
MIT License
682 stars 112 forks source link

Mass AI State Machine Demonstrator #8

Open vorixo opened 2 years ago

vorixo commented 2 years ago

Showcase and documentation on how the Mass AI State Machine works.

A Section for AI specific things is appropriate.

Fangrelle commented 2 years ago

I created a clean fork and made a dfs pathing processor that uses zone graph and displays the path along the zone graph shapes. It uses Mass agent data and two traits (currently hardcoded) for positions.

I thought it might be helpful to show how the Zone Graph system is structured (and how mass AI might use it) since the testing actor provided in the modules is not very easy to understand. I want to know if this is relevant enough to Zone Graph and Mass AI modules.

Planning to clean up some tasks that I have made to show the state machine tree module in conjunction with something like this. Would like to expand it, with proper mass agent setup but I am not sure about what the most stream lined way to do that is.

Path in blue image

vorixo commented 2 years ago

Hello @Fangrelle ! Any additional information on how the zone-graph works for custom use cases is really welcomed specially for the documentation bit, so please, keep us posted with your changes. We will try to find a way to incorporate them upstream once you mature your fork.

However, our main priority right now is to stick first to the built-in stuff and display the functionality of the StateTree. Do you think you could add simplistic behaviour to your entities through a StateTree to make it serve as a complete demonstrator for the MassAI module?

Fangrelle commented 2 years ago

Nice. Currently my plans are to make various StateTree Tasks and then stick them into some different trees with different entities and setup some different examples.

Once I have some of the basic functions and state tree nodes (Tasks, Conditions, Evaluators) setup I will make some documentation with examples.

For now I can only use the premade mass <-> actor sync traits (Transform, orientation, MassTranslators things, ect...) with the StateTree because I don't quiet understand the way syncing/spawning is meant to work yet, I think the main difficulty is the SpawningSubSystem but that's for a later date.

Megafunk commented 2 years ago

Thank you so much for the help!!! I'm not sure how far we should lean into AI stuff but statetrees using the Mass schema can't hurt. They are definitely designed to be used together.

AFAIK, Mass agent syncing works at the beginning and end of the Mass PrePhysics processing phase. At the beginning, data is read from actors: image

And at the end data is written:

image

I assume you add new "translators" by just extending a UMassTranslator and accompanying stuff. I'm not clear on what it actually does besides holding the translator tag bitset. Epic themselves seems shaky on some aspects of the design, like if they really need multiple tags for different data directions etc. Just seems like a bid to avoid repeated work? It's probably mainly just to serve as a simple way for them to subscribe all of the actors to the TMap<TObjectKey<const AActor>, FMassEntityHandle> ActorHandleMap; thing and of course the actor pooling setup. I can give making a new translator a shot. I suppose it would be good to try to extend every one of the extensible processor types at least once. There seems to be a distinction between Actors Mass "owns" or doesn't.

As for SpawningSubSystem it appears to be mainly designed for entities that live in the world from the start like npcs, vehicles, ambient stuff etc. Most of the work it does is finding valid locations to spawn stuff that you define in the Spawner settings. If you just need to spawn stuff from entity traits or configs it's easier to just get their archetype to spawn them and then SetEntityFragmentsValues like in UMSBPFunctionLibarary::SpawnEntityFromEntityConfig. I might need to take another look at the spawner stuff in case I missed something major.

EDIT: I should probably make an issue about exporting this dependency graph... it's from the Mass settings and is a .dot file iirc.

Fangrelle commented 2 years ago

Thanks for the processing phase info, I havent really looked into the processing ordering and this helps.

I looked into the translator setup and from what I can tell there is no need to really use. It appears to be as you said a kind of intermediary for some somewhat similar functionality with keeping certain data up to date on agents and entities. Also I ended up looking into the spawning system and the entity->agent->actor stuff and I figured out the how that TMap<TObjectKey<const AActor>, FMassEntityHandle> ActorHandleMap subscriber setup works. The conclusion I have come too is that sometimes it makes more sense to have classes/boiler plate be inline with the way epic has some things setup (ie:translators and certain subsystem query setups) and sometimes it makes more sense to set it up yourself, ultimately the functionality is similar.

For example (testing spegetti) in this state machine subsystem I am quickly storing an owner of a component with attached entity below: image

Then I can call retrieve this entity handle later and use it to get the actor and do what ever. Eg: I could print a test string from a component and set it as an output in a StateTree Evaluator: image

This is effectively what happens for a lot in other parts of the Mass AI module behind the obfuscation. I am currently working on a bunch of StateTree stuff. I think the translators are not needed, alot of the stuff they seem to do is already done in other subsystems and processors, thier main purpose seems to be to literally 'translate' constantly changing values like Component Transform, Capsule Component Hit.

The extent of the translator: image Like you said it adds some tags.

Anyway im gonna do that ( :

Fangrelle commented 2 years ago

I have setup majority of the test and example stuff for my AI ZoneGraph example, I am going to finish fixing up and adding some the functionality for UMSEntityActorExampleComponent and UMSEntityActorExampleSubsystem as an example of trait->fragment-> const TObjectKey<const AActor> entity caching -> Processors and StateTree nodes and functionality like: Tasks, Evaluators. Like "UMassComponentHitSubsystem (above)" for that is then used in the MassAI StateTree Evaluation Nodes.

Then ill clean up.

Currently there are several AI guys that will walk (with dfs (stupid but makes long paths that make it easy to see the logic)) to the last player location and will not stop until they reach the destination (I havent setup the caching properly yet) and they will run from danger (player press E).

Do you think you could add simplistic behaviour to your entities through a StateTree to make it serve as a complete demonstrator for the MassAI module?

After fixing up the last bits I should encompass most of the currently existing MassAI stuff. Unless my brain as just had a skip in consciousness I should say that as far as I can tell there does not appear to be any actual inbuild A->B pathfinding nodes in MassAI, the current pathfinding functionality consists of active step by step short range pathfinding (run away 1 or 2 lanes away) from danger. But it is setup to easily allow for pathfinding and optimized pathing caching.

Fangrelle commented 2 years ago

Hey, @vorixo and/or @Megafunk I have done most of what I wanted to do for AI ZoneGraph stuff now. Basically used making example to understand the ZoneGraph ECS stuff.

The code logic is basically done I need to change some things here and there to align with none spagetti practices, eg: Processor handling settings.

There is a brief description of the setup on my fork and the AITestMap should work out of the box (I think). If its two off topic im happy to just leach off the ECS stuff here on main. (nice example of niagara-ECS ECS+3Dhashgrid makes me want to make some boids, pefect for ecs).

If you want the example to be added to main tell me and I can update/rejig and request to stick it in. I am happy to create some documentation for the ECS-ZoneGraph stuff and some of the StateTree and AI stuff that is built on the ECS MassZoneGraph.

vorixo commented 2 years ago

Hello @Fangrelle, we are still figuring out how to organize the project to make it accessible to newcomes, specifically we are interested in making the C++ examples self-contained in folders - maybe not in UE modules - but in separate directories that users interested in a specific topic could navigate without many issues.

We are also looking after clear and easy-to-read code and folder hierarchy following Epic's standards. We'll push a couple of commits doing this extra effort, so future contributions will be simpler.

As for the documentation, feel free to append your documentation changes (README.md) in a separate PR, so we can peer-review it separately.

Since this is the first formal contribution that contains relevant code to shape the future of MassSample, we'll go through the following steps that we'll monitor in this post:

Fangrelle commented 2 years ago

Created an initial draft pull request. #19.

Megafunk commented 2 years ago

I added a very simple navmesh statemachine setup to the code. It's super early on and will likely change heavily as I change my assumptions about how both navmesh and mass navigation are supposed to be used.