A BETTER way to make a RPG Turn Queue: How-To Techlog #1


NOTICE: This was made with using Godot 3.3 in mind, but may be applicatable to other engines.


Since the beginning of time, indie devs have pondered, "how do I design a turn-queue-based-system without selling my soul to the devil?"
I made the mistake of jumping down that rabbit hole so you don't have to.
This isn't the absolute be-all-end-all solution, but I found a solution that I feel confident is a good approach with using Godot.


I started with a Control named Battle as the root of the scene. This Node can be a Control, Node2D/3D, or anything else really, we'll come back to this in the next step.

<span class="mceItemHidden" <the="">TurnQueue</span> will be its own Node too and can be any other Node type as the code isn't really specific to any one node.

Under the Battle node, add two nodes named Player and Enemy. Add them to a group named "player" and "enemy"

Attach a script to the Battle node with the following code (or change it to your liking, this is just for the demonstration):

This, being the top node, will pass information down to its children. It will get both parties (nodes in the groups player and enemy) and pass it into the TurnQueue's initialize function as arrays.

Attach a script to both the Player and Enemy node with this code:

Now, attach a script to the TurnQueue with this code:

The initialize function will append the passed in array's into its own _queue and _new_queue array.

It will then connect its signal handler, _on_turn_end() to each Battler's turn_finished signal, and hold a reference to the currently active battler, and call it's _start_turn() when it's done being initialized.

The Battler object will then run its start_new_turn() function and emit the turn_finished signal after a second

When the TurnQueue receives the turn_finished signal it will then get the next available Battler in the queue and then start the next turn.

With this way, the system for storing and calling objects to start turns is a bit more cleaner than using yield() functions in-between objects. Using a more signal based route also opens this up to expand more on this, as the TurnQueue only cares that the object it's calling on is a Battler object, and waits for it to emit a signal ending it's turn.

Leave a comment

Log in with itch.io to leave a comment.