top of page

NIMDA: Rust In Peace

Game summary

NIMDA is a two-player co-op, rouge-lite shooter. It is played from an angled top-down perspective in split screen using either a controller or keyboard. The goal consists of fighting and surviving hordes of different robots with varying behaviours while gathering enough resources for crafting and upgrades to be able to reach and defeat the final boss. The game features a fully custom graph-based navmesh, dynamic AI enemies utilising an extensive behaviour tree system

A short gameplay trailer for NIMDA, showing off many areas of the game. Including the AI enemies and the final boss

Development

NIMDA was developed in a team of eight students for a university class focused on game mechanics, patterns and their implementation. For me and many of the other students it was the first proper opportunity to work on a big coordinated project with a larger focus on more specilised roles. With the aforementioned focus on game mechanics the team was mandated to fullfill certain requirements for the game, and as such neither I nor the other students had completely free hands when it came to what to focus on and how to implement it. 

​

My contribution

My initial endeavour in AI led me to create two notable projects, offline A* pathfinding and Gomoku minimax algorithm. Building on this foundation, I directed my expertise towards NIMDA, a more intricate AI project, where I prioritized:

​

  • Developing a robust A* algorithm

  • Enhancing this algorithm to accommodate multiple agents and fluctuating goal positions

  • Introducing a binary heap to prioritize agents and implementing parallel pathfinding via the C# jobs system

  • Creating a flexible graph that expands and contracts as needed for optimal pathfinding

  • Establishing a standard AI behaviour tree and a scriptable object node system to facilitate integration by team members

  • Crafting various enemy AI behaviors

 

Additionally, I contributed to system decoupling by incorporating a generic event system design pattern, created a foundational finite state machine, and developed a platforming character controller.

​

NIMDA’s complexity posed several challenges, with optimizing the A* pathfinding for numerous agents being the most demanding. Initially, agents were denied direct path requests; instead, a pathfinding manager, using a binary heap, prioritized requests based on agent proximity to goals. However, this method faltered when agents converged, necessitating an additional solution. A provisional remedy involved restricting path requests for agents near their goals, mitigating excessive requests but introducing new complications. The ultimate resolution emerged from integrating binary heap prioritization, a cutoff distance, and multithreading through the Unity C# jobs system. This approach enabled simultaneous path updates for high-priority agents, marking a significant enhancement despite implementation challenges.

​

Given additional time, I would explore jump point search or a sophisticated navmesh system to further refine the AI’s efficiency and responsiveness.

From left to right: Dynamic A* graph on a small scale, same but large scale, Enemy AI with strafing behaviour

Dynamic Graph/Navmesh class

bottom of page