Open madeleineostoja opened 10 months ago
Realised I can extend UtilityAISTNode
to emit signals on enter, exit, and tick to patch this pattern. Feels like this kind of basic signalling could be unified between all the different nodes? And in general could lean more on signals vs methods on inherited classes to be more godot-like
I can add these signals to the agent behaviours, I'll have to do a bit of thinking regarding the behaviour tree leaf nodes. The difference to the State Tree nodes will be that currently I'm not passing any user_data
.
There's also an example scene, "making use of actions", where the action-node is extended with a script has methods start_action(actor)
and end_action(actor)
and also the method execute_action(actor, delta)
. The AI update code is then like this:
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# 1. Sense
var dist_to_cursor = (get_viewport().get_mouse_position() - position).length()
sensor_distance_to_cursor.sensor_value = dist_to_cursor / 1000.0
sensor_wait_time.sensor_value = wait_time / 10.0
# 2. Think
ai.evaluate_options(delta)
ai.update_current_behaviour()
# 3. Act
# This time we have extended the Action nodes with the logic,
# and let them handle the entity update. Action is switched
# in the signal handler below.
if current_action != null:
current_action.execute_action(self, delta)
# This is called when an action is chosen. We simply
# end the current action (if any) and start the new.
# The start does preparations needed to execute the
# new action and end any cleanup for the previous one.
func _on_utility_ai_agent_action_changed(action_node):
if current_action != null:
current_action.end_action(self)
current_action = action_node
if current_action != null:
current_action.start_action(self)
current_action_label.text = current_action.get_name()
This also achieves the decoupling. In the example scene I've used inherited scenes for the actions but that isn't really necessary, you just need to extend the action node with a script.
The difference to the State Tree nodes will be that currently I'm not passing any user_data.
That wouldn’t be needed, because the signals would be connected to the actor so you’d already have all the context you need. Which is another reason I think this pattern is cleaner than extending individual nodes
Fwiw an implementation of signals for state I really like is state charts (docs on state node events). Basically what I described above, leads to nice decoupled logic without anything dirtying up your core _process
, lots of node scripts that need context passed around, or any huge switch statements
Also a seperate bug I can file an issue for if I get a chance to debug a little and provide more context — when trying to use the ST setup (for extending those leaf nodes with signals) my game crashed on startup if I had considerations under STNodes and evaluation method set to utility considerations. If I changed considerations to resources it stopped crashing but didn’t actually work.
I didn’t go any further because I just switched back to the standard agent, since it can do everything I would have the ST setup do. All on Mac if it helps
I've now added the following signals to the Agent Behaviours:
There are also behaviour_group/behaviour/action_exited-signals added on the agent.
For the STNodes I had a pointer I hadn't initialized to null, which caused the problems. That is now fixed. Thanks for letting me know about the bug!
I've attached MacOS builds, could you try it out and see if the signals work as you expected? Please do take a backup of your project first, and then you just need to copy the folders "libutilityai.macos.template_debug.framework" and "libutilityai.macos.template_release.framework" over the folders of the same name in the /addons/utility_ai/bin folder.
Hey sorry for the radio silence, work got crazy in the new year and I haven’t had time for gamedev. I’ll pull down the latest builds soon and let you know.
Great to see all those signals added in v1.6, makes structuring logic for behaviors and actions much more flexible. Also had a read of the updated documentation, much easier to follow 🙌🏼
It would be really helpful if individual actions and behaviors emitted signals like
entered
,exited
,action_processing
, etc so that they could be dealt with in a decoupled fashion, rather than a big switch statement in the top levelaction_changed
/behavior_changed
signal