It’s Alive!!!

Project Duration: 1 Week (Follow Up Iteration In Progress)

Introduction:

  • This project was made as part of the 2025 Epic Mega Jam. The game jam theme was “Here We Go Again”. To fit this theme I made a roguelike where you play a monster inspired by Frankenstein.

My Role:

  • Game Designer (Single Member Team)

Key Contributions:

  • Player Character

  • Player Upgrade System

  • Enemy AI

  • Data Driven Enemy Spawning System

Unreal Engine 5

Tools Used:

Unreal Engine Blueprints

Unreal Engine Data Tables

Git Source Control

Trello

In Further Detail

Mechanics Breakdown:

  • Player Character:

    • When developing the player character, I began by creating the top-down movement system. I ensured that the player’s speed did not disorient or make players feel motion sick, as this was an issue I noticed with Unreal Engine’s base top-down movement. I then tweaked the camera follow lag to further improve the game feel.

    • I created a melee combat system in which animation notifies would tell the weapon when to begin tracing for collisions to hit enemies. If an enemy was hit, they were added to an array of “Recently Hit” actors so they would not take damage multiple times in a single swing.

    • When developing the health system, I knew I would reuse it for the enemy AI, so I built it as an actor component. Two functions were created for this system: Add Health and Reduce Health. Whenever an actor lost health, an overlay was applied to their mesh, making them flash red to indicate they had taken damage.

    • The Roar ability applied a weaken effect to actors caught within its radius. This effect was implemented as an actor component, and while attached to an actor, it reduced that actor’s movement speed by half. It also listened for when the owning actor took damage, and upon receiving damage, an event would fire to subtract an additional portion of that actor’s health.

      • The purpose of this ability was to give the player a way to strategically time when to apply a status effect to surrounding enemies. It provided options, slowing enemies when the player needed to escape or increasing damage output when the player wanted a power boost. The lengthy cooldown on this ability encouraged the player to think carefully about when to use it.

    • The final ability the player had was a passive tether that connected to nearby enemies and shocked them for a small amount of health. This ability tracked enemies within range, and when one of the player’s limited tethers became available, it would select a target and begin dealing damage. This continued until the target was dead or out of range.

      • The purpose of this ability was to allow players to attack multiple enemies simultaneously without having to physically turn away from others they were fighting. It also enabled faster enemy clear times as players leveled up and increased the number of available tethers.

  • Player Upgrades System:

    • For the upgrade system, I used unique data tables for each type of upgrade (four upgrade types). These data tables stored the level associated with each upgrade, the values tied to the aspects of the character or ability being upgraded, a name for the upgrade, and a flavor message to accompany it.

    • The player’s upgrade levels were stored in the game instance as integers. The player would then pull the current upgrade level from the game instance and use that value to find a corresponding row in the data table, setting values such as health, movement speed, ability range, and more.

  • Enemy AI

    • The enemies in the game focused around having three types of enemy AI, each with a passive state and a combat state.

    • For each character type, the passive state had them walk around and patrol within a given location. This helped the world feel more alive.

    • The civilians wore grey so they could be easily identified by players. In combat, civilian enemies would flee within a certain radius around the player and run away.

    • Having these characters run away kept the player engaged in the chase and often led to them alerting more enemies that could fight back. Keeping them within a certain range of the player while fleeing ensured that the player would not get frustrated, as the civilians were always catchable—even if the player had to fight armed enemies first.

    • The melee characters wore blue, as the color was easy to discern from the colors found in the rest of the world. The melee enemies’ combat state had them run up to and chase the player. Upon reaching the player, they would quickly swing their weapon and attack before moving just out of range. This ensured that while they were on cooldown, they would not be easily attacked.

    • The archer characters wore green, as the color is commonly associated with fantasy archers and helped players further distinguish them from the other two enemy types. The archer enemies’ combat state had them maintain a consistent distance from the player. They would take short pauses while moving to line up their shots and fire arrows at the player.

  • Enemy Spawning System

    • I used data to drive the enemy spawning system by tracking a variable I called “World Chaos” in the game mode. When crafting each enemy type, I gave them a value to add to the World Chaos, and on death, it would be passed to the game mode.

    • The game mode would take World Chaos into account when spawning enemies and would use this variable to find a row in a data table I named “Enemy Waves.”

    • The Enemy Waves data table row would inform the game mode of what type of enemy to spawn and whether it should start the game in combat.

    • The game mode would then use the array of potential enemies in the data table to choose which enemy to spawn.

    • This system allowed me to keep enemies constantly spawning and evolving in the world without needing to settle for a round-based system that halts combat. This also works better than a time-based system, as the game’s difficulty will only increase when the player actually kills more enemies, which indicates that they are performing well.

    • For the constant enemy spawning system, I built into the game mode a method for tracking the number of enemies in the world. This was done by tracking a variable called “Enemies In World.” This variable would be increased by an enemy actor on Begin Play and then decreased by the enemy actor during the death event.

    • This system ensured that there was never an excessive number of enemies in the world at any given time, and that we never ran out of enemies to fight.

My Biggest Challenge:

Top Down Camera

  • The initial camera would be blocked by obstacles taller than the player and this caused issues as the player would have no idea where they were standing.

  • My solution to this was to make it so the camera spring arm would zoom in following the player getting too close to an object that would obscure them. This worked, but only kind of as small objects like other characters, fences, etc. would trigger the zoom in effect. This could get incredibly disorienting.

  • I was finally able to fix these issues by adding a new collision mode to the game and making it so I could designate on an object by object basis if it should make the camera zoom in, or ignore the camera.

Previous
Previous

Kart Racer- SysEval: Iteration Protocol

Next
Next

2D Physics Platformer- OVER-POWDERED SHELLS