Alright so, after a lot of back and forth, trial and error, an extra couple grey hairs I have come to a solution that i’ll share in case one day maybe it helps someone else out.
What follows probably isn’t what most would consider the “best” solution, but it’s what i’ve come up with after trying to get answers from different sources and good ol’ fashion elbow grease, but i’m very happy for any feedback or pointers as a nooby if anyone has some to give.
First things first, handling your spawned actor taking an action is both much easier than it appeared, though met with a couple issues.
Simply put, the SpawnActor node’s return value is a reference to said actor, so form there I just created a function in said enemy called “Spawn Actions” that you can call once you have said reference.
*Note that in the long run I intend to turn this into a Blueprint Interface to avoid casting to specific objects here, but this is my “get it working on the screen” fix as I only have one functional enemy at the moment.
Now the hard part here is I couldn’t technically complete the actions I wanted to within a function.
The goal is for the enemy to spawn offscreen and walk onto it before the AI controller (and thus the Behavior Tree) takes effect.
Issue #1 - My original implementation of just kind of passing in a side of the screen left a lot to be desired and required a lot of calculation / data passing that wasn’t easily handled directly in the manager, things like spawn position, where to spawn, and what will likely be more info in the future as the game expands.
To get around this I ended up creating a BP_SpawnActor actor that is an object placed in the world, with a set of them as an array attached to the Battle Event that has an enum to represent it’s position relative to the battle event. This should in theory allow for a designer to come in an easily set up battle events without knowing any code, you just set # of waves, enemies to spawn in said wave, and which position they spawn at and when the event manager triggers a wave it just cycles through the spawners to find one that matches with the position it should spawn at and initiates SpawnActor.
This makes it a lot easier for me in the long run to determine decisions in the spawning itself, like which direction they should walk towards the player (as they may not have a valid target yet)
Issue #2 - Making the enemy walk onto the screen was a lot harder than it seemed it should be. I wanted them to spawn and complete their action before the spawner is allowed to be in use again which necessiated two things, a move function and a callback (as other enemies like a boss may also play an animation and sound effects before their “spawn action” is complete)
While there are some Move To functions you can call, you can only call AI MoveTo (which provides a callback to when the move is finished) inside the main event graph since async options don’t work inside a function, so what you can see from above is I get some necessary information and then call a “SpawnEvent” that then runs the async options I want to happen.
Definitely note the stop and start logic there. One thing that was tricking me is the AI MoveTo does not work unless an AIController is already spawned for the enemy, so I needed to do that for that function to work, however the Behavior Tree would immediately kick in resulting in the AI MoveTo being immediately disregarded in favor of the other actions the behavior tree expects to do. So to get around that thankfully we have access to the Stop and Start logic functions which essentially acted as my “AI Controller take back control after I do the initial custom thing when you spawn”
One option that was suggested to me as well was in the Behavior Tree have a Bool Blackboard Key “hasCompletedSpawnLogic” that is it’s own mini behavior tree section to do all the things I want and then turn that bool object to true so the rest of the behavior tree functions as normal. While I don’t mind this solution it was proving rough to implement as i’m not amazing with behavior trees and was just taking me too long.
I am also very tempted to test out and potentially switch over to State Trees as they look more intuitive to how I want to make the AI work that I didn’t want to get bogged down in the Behavior Tree since I was already kinda planning to refactor it out if my research into State Trees shows I like them better.
Now it’s definitely not perfect and I’m already aware of some issues i’ll need to handle with more polish in the long run, like how to handle a spawned enemy being beat up before it’s spawn action is complete and i’m sure other things, but I was at least happy to kind of get my initial idea into a working state.
So here’s a GIF of it working in action!