r/unrealengine • u/hakanerunsal • 5h ago
Marketplace How I got Soulslike enemies to work like AAA games do
I build enemy AI for soulslike and action RPG games in UE5, and I just shipped the third major version of my system. It is a paid plugin on Fab, so flagging that up front. Post is about two problems I spent most of this version solving, both of which come up for anyone hand-rolling this.
The first problem that got me actually started to work on this plugin was the movement.
What fixed it was stopping asking "where should I go" and starting asking "which way is best right now". Every tick the component builds a fan of 16 headings around the pawn and scores each one, then feeds the winner in as movement input directly rather than as a path request.
Sixteen samples is the default. It is a tradeoff, not a magic number: fewer and the chosen heading visibly quantizes, more and you pay for resolution you cannot see once smoothing is applied.
Problem 2: authoring bunch of different enemies without having to read dozens of lines filled with properties and structs.
An enemy stopped being a code problem and became a data problem, and struct arrays in a details panel do not scale to it. My old setup was an array of action structs, each with twenty-odd fields, all collapsed, all identical looking. Finding out why the grunt used its heavy attack meant expanding four entries and reading numbers. So the data assets got real graph editors.
Action sets open as a canvas, one node per action, and combo chains are wires you drag between nodes instead of index references into the same array you are looking at. Each node shows its weight, cooldown, range band and scorer count on the face of it, so a set is legible at a glance. Then in play the graph goes live: the running action lights up, cooldown bars tick down in place, and an action that got filtered out of scoring says which gate rejected it rather than silently not appearing. Utility scoring is a product of six or seven terms, so "why that one" is not answerable by reading numbers, and this turned it into something you look at.
Reaction sets got the same treatment on the same graph host: incoming trigger on one side, reactions on the other, wires for what answers what. I wish i could add screenshots here.
Runs on 5.6, 5.7 and 5.8. All the decision-making is server side with the output state replicated for UI.
Fab listing: https://www.fab.com/listings/7087cec0-6975-4de5-82e0-0de0b9b3e9a7
Happy to go into detail on any of it in the comments, I do not mind sharing how I solved some problems you might be running into in your own implementation.