top of page

Rot & Prowl

Rot & Prowl is a 3D stealth survival horror game for Windows developed by a team of 9 in Unity.

Play as a mouse being hunted by a possessed cat, desperate to escape the abandoned wizard's house with your life and your cheese.

Octicons-mark-github.svg.png

Project Overview

Length

 

Feb 2026 - Mar 2026

Tools

Unity

JetBrains Rider (C#)

GitHub Desktop

Role(s)

AI Programmer

Contributions

  • Created and managed GitHub repository, utilizing Git Large File Storage and GitHub Desktop to enable efficient real-time collaboration with a 9-person team in Unity.
     

  • Practiced manual continuous integration with Git to effectively avoid merge conflicts within the repository.
     

  • Gained knowledge of and experience with Agile methodology, particularly Scrum.
     

  • Created a Behavior Tree in C# with 3 base behaviors for the enemy AI to simulate patrolling, hunting, and resting.

AI Logic Breakdown

A mix of a behavior tree and state-tracking logic was used for this project to create dynamic and realistic enemy behavior.

image.png

The cat has custom-defined states that can be expanded as needed.
These states inform the behavior tree about the cat's current and previous actions, which is then used by the tree to determine what action the cat will be taking next.

These states are also utilized to determine which animation and sound effect should be playing at any given time.

image.png

The behavior tree only has 3 nodes it constantly switches between: 
"Hunt", "Patrol", and "Rest"

Using the information provided by the state-tracking logic, the tree "selects" a node to execute in order of priority from first-added to last-added. In this case, "Hunt" takes priority.

The tree and state logic dictate that the cat cannot repeat its previous action (with the exception of hunting).
Thus, the cat's behavior loops in a sequential pattern:

 

Hunt → Patrol → Rest

image.png

After the initial behavior tree setup, the tree will be processed in Unity's built-in "Update()" method, which runs any logic within it every frame.

The reason the tree is constantly running is because the cat needs to be able to switch between behaviors and states quickly; if at any point the player is spotted, the cat needs to stop what it's doing and prioritize chasing the player.

At the same time, the cat has a consistent behavioral routine when the player is not spotted, which is ultimately why I chose to use a mix of the behavior tree structure and state-tracking logic.

Hunting

"Hunt" is the first node processed every loop of the behavior tree. This is because if the player is spotted, this takes priority above all other actions.
 

Hunting only occurs if the player has been spotted.

The "hunting" behavior is separated into 4 distinct methods with their own purpose.

image.png

The "Hunt()" method is the behavior tree node itself, which reports on the state of the cat and lets the behavior tree know whether its behavior is successful (player has been caught) or unsuccessful (player got away). Depending on whether the action succeeded or failed, the behavior tree chooses what behavior to execute next.

This node also stops any actively-running coroutines to ensure a seamless transition from any action into chasing the player.

image.png

The "Hunting()" coroutine constantly runs while the player is in the game scene. It repeatedly calls the "FieldOfViewCheck()" method after a specified delay to prevent crashes and game lag.

image.png

The "FieldOfViewCheck()" method ultimately is what decides if the player has been "seen" by the cat while it hunts. Every time it is called, it checks for any colliders overlapping with the "field of view" of the cat.


Calculations and raycasts are then used to determine if the player can actually be "seen" by the cat, meaning there are no obstacles in the way and the player is not behind the cat or otherwise out of its "line of sight".

image.png
image.png

Finally, the "LookAfterHunting()" method runs, which waits for the cat to arrive at its destination before calling the "LookAround()" method.
"LookAround()" is not unique to the hunting behavior because it is also utilized by the patrolling behavior, hence why the actual "looking around" is modularly separated into its own method.

 

These two methods combine to simulate the cat "looking around".

This gives the player the impression that the cat is searching for them.

Patrolling

After hunting, the cat goes back to patrolling. This is to ensure there is constant pressure on the player and incentivizes them to pay attention to the cat's "routine behavior".

Just like hunting, the patrolling behavior is split into several methods with their own purpose.

image.png

The "Patrol()" method is the behavior tree node itself, which reports on the state of the cat and lets the behavior tree know whether its behavior is successful (finished patrolling) or unsuccessful (patrol interrupted). Depending on whether the action succeeded or failed, the behavior tree chooses what behavior to execute next.

image.png
image.png

The "Patrolling()" coroutine executes the actual patrol behavior.
The cat is given a set of patrol points throughout the map to move between.

 

Once the cat finishes moving to all of its patrol points and finishes "looking around" when arriving at those points, it will move on to its next behavior.

Resting

Resting is the final behavior in the tree before the cycle repeats.
 

This behavior was made to alleviate some of the pressure the player faces; if the cat were to patrol nonstop, the player would never get a chance to explore the level and reach the end. 

Because the cat only has 2 patrol points due to the limited scale of the level and this project, the cat would be unbalanced and too aggressive if it were to constantly patrol those two areas.

 

Additionally, the resting behavior rewards players for paying attention to the cat's routine and utilizing the game mechanics effectively.

image.png

Just like the previous 2 base behavior nodes, the resting behavior begins in the "Rest()" behavior tree node and method.
 

Similar to the previous nodes, this node will only execute if the player has not been spotted, the cat's last action was not resting or hunting, and the cat is currently idle.

image.png

The "Resting()" coroutine, similar to "Patrolling()", executes the actual logic for the cat's resting behavior.

The cat moves to its assigned bed location and once it arrives, it rotates so that its back is not to the wall.

bottom of page