One in the quiver is a 2D roquelike project I have been working on on my own, with some really exciting features. I use behaviour trees for AI logic, A* pathfinding for finding the paths of the AI for patrol and locomotion. A lot of inheritance based logic and classes for the player, and a pretty satisfying feel to the game already. The art is not there but the mechanics are, thats what is most important to me.


AI Behaviour tree
The AI in this project uses behaviour trees, “So the clue is in the name. Unlike a Finite State Machine, or other systems used for AI programming, a behaviour tree is a tree of hierarchical nodes that control the flow of decision making of an AI entity” (Simpson, 2023). At each end of the tree there is tasks for the AI to complete or enact upon. I chose behaviour trees because they have a few advantages. Firstly they are highly itterative, you can start with basic behaviour and then you can create new branches that deal with new and other situations, the AI can then switch to the correct behaviour in the correct situation. And that makes the second point, they are really easily modulair and expandable. You can have the basic behaviour and easily add new behaviour for a special enemy. The third reason is that it helps with spaghetti code and lose references, the tree is neatly organized and is easily debuggable.
The earlier mentioned source helped me with understanding behaviour trees, it is written by the creator of Project zomboid a zombie survival game with a lot of complex AI behaviours. I used this source and this unity tutorial to start on a code solution instead of a pre-made plugin, why? Because I wanted to learn!
With this tutorial and blog post in hand I made a basic behaviour tree that now controls the AI! This is how it works:
Behaviour tree logic
The Behaviour tree (BT), has a few moving parts, the BT (Behaviour tree) It’s self, which do the most high level logic.
Composite nodes
Selector and sequence composite nodes, these nodes have children nodes (tasks or other selectors and sequences) but handle them differently.
The sequence will loop through all the child nodes in order, and let them run through their logic, it will return failure when a child fails or succes when every child has completed their tasks and logic succesfully.
The selector will loop trough the children and is the opposite of the sequence because it searches for the first node that succeeds, when the first nodes succeeds all the other nodes will fail. This is like a OR gate.
Nodes and tasks
The Nodes are the heart of the BT, these can be evuluated and will return a status. This is the logic the rest of the BT is build upon. Tasks are at the bottom of the tree, this is the logic the AI will use when in that state, like: walk to this position, turn around 90 degrees, walk to that position. This all is a task the AI can perform. The tree uses these nodes and tasks to form complex behaviour.
Example
Here you can see the enemy patrolling and when the player has been sighted starting to run towards the player. This is because the BT is looping through a selector nodes that checks if the player is in sight, this will always return fail, only when the sight to the player is not blocked and in range does the enemy “see” the player


This is the tree in question, its a lot of code but if you look into the code it are just sequences selected by a selector when they return a SUCCES.
A* pathfinding
For the pathfinding I wanted to use A*, this a algorithm to search for the shortest path from a start to a end point. There is not that much reason behind choosing A*, it is really performant and is widely used. But I could also just have used Unity’s AI navigation tools. But there is no learning in that, so I wanted to work on a code from stratch solution, with my big friend sebastian lague’s tutorials
A* explaination
Consider a square grid having many obstacles and we are given a starting cell and a target cell. We want to reach the target cell (if possible) from the starting cell as quickly as possible. Here A* Search Algorithm comes to the rescue.
What A* Search Algorithm does is that at each step it picks the node according to a value-‘f’ which is a parameter equal to the sum of two other parameters – ‘g’ and ‘h’. At each step it picks the node/cell having the lowest ‘f’, and process that node/cell.
We define ‘g’ and ‘h’ as simply as possible below
g = the movement cost to move from the starting point to a given square on the grid, following the path generated to get there.
h = the estimated movement cost to move from that given square on the grid to the final destination. This is often referred to as the heuristic, which is nothing but a kind of smart guess. We really don’t know the actual distance until we find the path, because all sorts of things can be in the way (GeeksforGeeks, 2025).

Implementation

With implementing I followed and learned from Sebastian’s video series and made the A* solution. With that A* solution there is a path requesting manager, the AI will request the path when they have reached their destination or have no destination. This is all handled with the behaviour tree from earlier.
The manager will return a path for the AI to follow, this can be a path to a patrol point or to the player.
Inheritance based weapon and projectile systems
weapon system
I wanted the abillity to easily add new weapons without writing the same logic over and over again. So I opted to use inheritance for my weapon system. This will consist of a base class with the generic logic and functions that a weapon needs to function. On this base class I can build new weapon types and weapons, like ranged weapons and melee weapons.
Design
Here you can see the design of the weapon system, it is a really simple design but works great. The base class has all of the generic classes and logic that can be called for any weapon. And those ranged and melee weapons all inherit from that one single class.

Projectile system
Because this project is intended to be a roguelike, with a focus on a player who only has 1 arrow. I wanted there to be a small projectile system where I can tweak a lot of variables and stats of the projectiles being shot. But also of the projectiles that the enemies shoot. This will make it really nice for me to implement different projectile types.

I wanted to achieve this by using inheritance and scriptable objects. This will get the effect I want. The BaseProjectile handles the locomotion and collision logic, using the data from the scriptable object, this allows me to give different speeds and damage to each projectile easily.
The arrow inherits this and adds some of it’s own logic: being able to be picked up.
CCD (Continuous Collision Detection)
The projectile is moving really fast, and will sometimes miss collision detection because the projectile has moved further than the object that it wants to hit, and will not register the collision
To counter act this I am using CCD (Continuous Collision Detection), this means I am casting a ray between the projectile’s current position and the previous position of the last frame. This will detect any missed collisions!

Collateral penetration system

I want the player to be able to damage more than 1 enemy with one arrow, so i designed a penetration system. Each enemy has a penetration protection variable, and the arrow has a penetration value, when you hit a enemy this penetration protection value will be deducted and the arrow will do damage and continue, when the arrow can’t penetrate any more it will stick.
