Skip to content

Ji-Rath/MassAITesting

Repository files navigation

MassAITesting

A project primarily used to test UE5 Mass AI system

Simple gather entities (Currently called RTSAgentTrait in CPP)

AI process

  • Entities go to smart objects (tree/rock) and 'collect' the resource
  • Entities then go back to their 'house' which is their initial location
  • Repeat until there are no more resources to gather

Behind the scenes

  • Entities use the SmartObjectSubsystem to communicate with smart objects
  • This ensures that entities wont fight over a single resource
  • Smart objects use simple gameplaytags to determine what is a rock and what is a tree
MassAITesting-GatherAI2.mp4
MassAITesting-Simulation.mp4
MassAITesting-GatheringEntities.mp4

Discoveries

Mass Visualization

  • Visualization Trait
  • Mass Viewer Info Fragment
  • Mass Actor Fragment (For actor visualization)
  • Mass Visualization LOD Processor (Index 41)
  • LODCollectorProcessor is disabled by default for some reason, which is needed when entity counts are high

Mass LOD

  • Mass LOD Collector Trait
  • Mass LOD Collector Processor (Index 17)

Agent Radius

  • Using Assorted Fragments and Agent Radius Fragment will allow you to override the default radius of agents for the entity

Movement Trait

  • The height is simply interpolated based on the target location and current height. It should not be relied on to give completely accurate results when the distance is far. A possible solution would be to update the target location z during movement.

General Mass Information

  • Fragments hold data (FMassFragment)
  • Filter entities using tags (FMassTag)
  • Traits contain fragments/tags (UMassEntityTraitBase)
  • Processors use fragment data to perform tasks on entities (UMassProcessor)
  • StateTree and Fragments are sortof like BehaviorTree and Blackboard
  • ObserverProcessors can observe more than one fragment/tag by overriding the Register() function.

State Tree Information

  • Evaluators basically gather data to be used in the state tree
  • Enter Conditions are used on leaf nodes to see whether a leaf should be executed
  • Tasks from ST are like BT, execute logic
  • Transitions allow the state tree to go to other branches based on a condition
  • Reference: https://docs.unrealengine.com/5.0/en-US/overview-of-state-tree-in-unreal-engine/
  • Category for UPROPERTY in InstanceData determines what kind of value it is (Input, Output, Parameter)
  • State Tree will throw an ensure when there are fragments missing for a task to execute. The only way I know to debug which fragments are missing is to goto the task and look for TStateTreeExternalDataHandle in the header file.
State Tree Experimental Findings
  • Tick on StateTree Tasks are only ran once and with subscribed signals (see UMassStateTreeProcessor)
  • I found no feasable way to subscribe signals in MassStateTreeProcessor. As a hacky solution just reuse one of the hardcoded signals
  • A SmartObjectDefinition needs USmartObjectMassBehaviorDefinition and ALL default tag filters to show on Mass SmartObject Eval evaluator.
  • UseSmartObjectTask will only execute USmartObjectMassBehaviorDefinition, meaning only C++ logic for the time
  • Destroying a smart object safely in USmartObjectMassBehaviorDefinition should be done using PushCommand(). Lets the SmartObjectUseTask release the smart object before destruction. (may be source of ensures being fired, need to investigate further)
  • Empty states with transitions seem to produce unexpected behavior. The state tree also always needs to be in an active state, even if idle.
  • SmartObjectUseTask modifies MassMoveTarget around line 163-164, caused a headache since entities would not move after using a smart object.

Smart Objects

  • FMassSmartObjectHandler should be used rather than directly getting the smart object subsystem in mass....i think (seems to be used in~~~~ state tree tasks).

Instanced Static Meshes and Visualization

  • Its possible to apply unique textures to each instance through an atlas and getting a random num to choose the frame - dont forget to use Vertex Interpolator and use a small float to fix precision issues.
  • Vertex animation can be achieved by a similar tactic of using instance custom data to determine which animation to play
  • To setup vertex animation, I used Vertex_Anim_Toolset and a UE5 fork
  • In the processor, order is important when giving instance custom floats. FMassRepresentationFragment, FMassRepresentationLODFragment, and RepresentationSubsystem should be all you need to get started with instance custom data. (See URTSAnimationProcessor)

City Sample and AnimToTexture Plugin

This is in regards to how ISM processors get anim data and update custom data

  • Processors get their data from MassRepresentationSubsystem. At some point, actor templates are added via FindOrAddTemplateActor(). (Update: This is done for us most likely somewhere in the visualization/representation processors if you have actor visualization)
  • The CDO is then retrieved via GetDefaultObject() and data can be retrieved. In this case, it is a CrowdCharacterDataAsset.
  • A FCrowdCharacterDefinition is generated based on the data asset which contains the key info for animation among other things. (its a little more complex than described since the data is really retrieved from the FCrowdCharacterDefinition, just selected based on the human's properties)
  • Finally, the animation data (UAnimToTextureDataAsset) is saved to the entities FCrowdAnimationFragment for future use in processors
  • Note: Data assets appear to be added to the character BP (high actor visualization), this is why the data can be accessed.
  • The actor can be retrieved using FMassRepresentationFragment.HighResTemplateActorIndex and RepresentationSubsystem->GetTemplateActorClass
  • To be honest, a simple SharedFragment is probably sufficient for simple use-cases. I definitely might change my mind when I attempt to sync actor/ISM animation
  • Actual anim state index is updated in UMassProcessor_Animation and custom data is updated at UMassCrowdUpdateISMVertexAnimationProcessor::UpdateISMVertexAnimation in various processors

HashGrids

  • TPointHashGrid3 performance is considerably worse compared to THierarchicalHashGrid2D
  • This could be caused by the extra dimension, testing scenario, or more efficient logic for mass (as THierarchicalHashGrid2D is used in MassAvoidance)
  • Worst case scenario for similar search query: 235.9μs -> 8μs (x30 performance boost!)

TODO

  • Find a way to use Mass SmartObject Eval effectively in the State Tree (DONE)
  • Convert logic in RTSMovementProcessor to State Tree (KINDOF DONE)
  • Agent gets stuck after using one smart object, find out why (DONE)
  • The UseSmartObject task also messes with the MoveTargetFragment. It seems to be doing some stuff in ActivateActionAnimate() at MassZoneGraphNavigationUtils too. (DONE)

About

A project primarily used to test UE5 Mass AI system

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published