FRONTIER SAGA
Frontier Saga is a 3D Action-Adventure game I developed with the help of 3 other developers for my capstone project at university. The development process lasted 4 months, from the beginning of April 2022 to the end of July 2022.
Summary
Players are placed in a world where bosses are running rampant. They must traverse through various areas to defeat these bosses and save the city in time. This adventure can be played solo or with up to 3 friends co-op. Abilities are unlocked through a skill tree, which allows players to customize their playstyle.

PLAY THE GAME
*** If you want to play the game for yourself, consider the link(s) below. ***
Game Installer: https://mctigerr17.itch.io/frontier-saga
Complete Game Instructions: https://docs.google.com/document/d/1GRZM-M2ikYzQyl9Gkc9Lqodtqx8xR30DKkxnTIrJdZw/edit?usp=sharing
MY ROLE | What I Worked On
AI
- Enemy attacking behaviors. How the AI detects, chases, attacks, and keeps their distance from players during combat.
Gameplay
- Ranged combat system
- Some player abilities such as the Stealth Ability and the Charged-Shot Ability
Back-end
- Networking/Multiplayer
- The Save/Load system
- The Game Manager
AI
As an AI Programmer, I made the attacking behaviors of the enemies. I was also in charge of everything for 3 of our enemies: Summoner, Summoner's Skeleton Minions, and Archer. This included finding models, animations, sounds, and visual effects for the enemies and putting it all together.
Summoner Enemy
The summoner enemy behaves kind of like a ranged enemy. When a player is within its attack range, the summoner spawns the skeleton minions. These skeleton minions are melee enemies that will chase and attack the player. The summoner spawns 3-5 minions every 5 seconds, however, it will not have more than 5 minions spawned present at a time. For example, if it has already spawned 3 minions and they are still alive, when it comes time to attack again, the summoner will only spawn 2 more minions.
The summoner itself does not do any damage to the player. Instead, it relies on the minions to do the "dirty work". The player must defeat the summoner or run away outside of its sight range, otherwise, it will keep spawning minions and sending them to attack the player.
I made sure that the summoner keeps track of all the minions it spawns and whether or not they are still alive. If a minion despawns or is killed by the player, the list containing the summoner minions will resize, hence preventing null references.

Model and animations from Mixamo
Summoner's Skeleton Minions
The summoner's skeleton minion is a melee enemy. When it is spawned(instantiated) by the summoner it will detect, chase, and attack the closest player. The minions have a larger sight range than the summoner. If a player is no longer within sight range, the minions will run back to the summoner enemy who summoned them. If there is no player in sight for 10 seconds they despawn. The minions have lower health than the other enemies and are easier to kill, however they are problematic when they attack in numbers.
On the attacking side, I made sure the minions can only deal damage to players during a certain part of the attacking animation. This prevents players from taking damage in situations that don't make sense, such as taking dagame when colliding with the minion.
All skeleton minions have reference to the summoner who summons them, and vice versa
The most challenging part of creating this enemy was programming what to do if a player is no longer "visible" to it.

Model and animations from Unity Asset Store
Archer Enemy
The archer (ranged enemy) was the first enemy I created. The archer patrols certain areas in the world, when a player enters its sight range it will start firing arrows at the player. when a player approaches, the archer will slowly move backward, retreating, while continuing to fire arrows. One of the most challenging parts of this enemy was getting the arrows to fire to the player with the correct trajectory and having all of that sync up with the animations (especially when the archer is moving backward and firing arrows at the same time).

Model and animations from Mixamo
Gameplay
As a gameplay programmer, I made the player's Ranged Combat system. The ranged combat system allows players to attack enemies from a distance using a bow and arrows. I also created 2 of the player's abilities/skills, the Charged-Shot ability and the Stealth ability.
Ranged Combat System
The player's Ranged Combat System was by far one of the most challenging systems I create for the project, second to Networking. The system was created to give players a different way of engaging in combat other than just melee with the sword. The ranged combat system gives players a bow that can be used for attacking enemies from distance. If a player hit an enemy with a bow from distance the enemy will start going toward the player ready to attack.
​
I created the UI elements and their animations for this system (cross-hair, weapon icons). When a player switches between sword and bow, the weapon icons in the bottom left corner of the screen switch and execute their animations. In addition, the weapon that the player is holding also switches.
When the bow is equipped the crosshair appears in the middle of the screen. By default, the crosshair is a grey color. When the player draws the bow and gets ready to fire, the crosshair's color will change to green. If the crosshair is hovering over an enemy, the color will change to red.
The most challenging part of this system was getting arrows to go to the correct locations when fired. Being that our game is in 3rd person perspective made it that much harder because I couldn't just fire arrows from the middle of the screen (crosshair location). In addition, for our ranged combat, we chose to do bow-and-arrows instead of guns; which added yet another level of difficulty for getting this right. I needed to find a way for the arrows to get instantiated from the tip of the bow and travel to the location/position that the reticle is pointing to, while also applying bullet drop -- or in this case, arrow drop -- physics. This was achieved by using ray casts. I fired a ray cast from the center of the screen and whichever object it hits in the world, that's the location I fired the arrow to (WOW! That sounds so easy on paper hahaha). Valid raycast hit positions were determined by which layers they occupied. For example, game objects that are on the "Ignore Raycast" or "UI" layer will be ignored by the raycast, while others that are on the "Enemy" or "Ground" layer will not be ignored.
​
​



Charged-Shot Ability
Amongst the development team, the Charged-Shot ability was the most liked player abilities/skill. This was an ego boost for me to see that everyone really enjoyed what I did.
The charged shot ability can only be used when you have the bow equipped. When using the charged-shot ability fire the bow as usual. When drawing the arrow there will be a circle that appears around the crosshair to signify the arrow is charging. The longer the player holds the button to draw the bow, the faster and more powerful it will be on release. Releasing the arrow when it is fully charged will deliver the maximum speed and damage. To top it all off the charged-shot ability also deals area of effect (AEO) damage on impacts. This makes it possible to kill multiple enemies with one arrow (if they are close to each other)

Stealth Ability
The stealth ability can be very useful when the player needs to get away from a dangerous situation. For example, If the player is at very low health and is surrounded by enemies, the stealth ability allows them to go "invisible" and become undetectable by the enemies for a short period of time. While this ability is active, the player model has a transparent look which communicates that they are invisible. If the player uses this ability during an engagement with enemies, the enemy AI will react, looking around and confused.
​
The stealth ability was the first ability I created. The stealth ability was one of those tasks you think will be easy to implement, but end up taking wayyy longer than expected. Just get the character model's mesh material, change the alpha value to give it a transparent effect, and change it back when the ability is over. Because of how Unity handles its materials and colors, this did not work. After a week or 2 of struggling, I reached a solution. I had to create an entirely new material, replace the character model's Skinned Mesh Renderer with that material, and add the original Skinned Mesh Renderer back to the character when the ability duration was over. It was crucial that I stored all the original mesh materials and apply them back in the correct order and at their exact same locations

Back-End
As a gameplay programmer, I made the player's Ranged Combat system. The ranged combat system allows players to attack enemies from a distance using a bow and arrows. I also created 2 of the player's abilities/skills, the Charged-Shot ability and the Stealth ability.
Networking/Multiplayer
If players want to play through the story with friends or other players, they have the possibility to do so by selecting multiplayer from the main menu. Frontier Saga has a co-op multiplayer system that allows players to create/join rooms and play together.
​
Networking and multiplayer was the most challenging system to implement. No one on the team had networking/multiplayer experience and for some weird reason, and despite being warned of its difficulty, we all decided it would be a good addition to the game -- crazy right?
Using the Photon Pun 2 Unity package, I was in charge of everything multiplayer; Creating and managing connections, creating and managing lobby/rooms, connecting players to lobby/rooms, syncing player/enemy movement, syncing player/enemy positions, syncing skill/abilities, making sure players spawn next to each other, player nametags, even the UI(buttons, visual, etc)
​
When a player creates a room they become the host of the room. When everyone else joins the room and the game is started, the save/load system will load the host's progress (level, quests completed). However, everyone's attributes (skills, XP) will also be loaded. As the players progress and defeat bosses, that progress will only save for the host, but if the other clients level up and gain new skills, those will be saved to that client save file -- meaning if they(not the host client) leave multiplayer and load into their single-player save, whatever they aquirred in multiplayer will carry over and be loaded into their single player progression. When it comes to saving/loading, the only difference between the host and other clients is that story progression( level, bosses defeated, quest log) is only saved for the host.
​
Establishing Connection/Joining Lobby, Room, and Game
Syncing combat and abilities
Loading different levels and disconnecting
Save/Load System
The Save and Load system was created to manage and maintain the player's progress throughout the game. It saves and loads the player's health, skills, abilities, XP, level/location, stat increases, etc. Player data can be saved manually via the 'Save' button on the pause menu. Player data is also saved when players reach a checkpoint or when players transport to another level.
​
I really wanted to work on this system because I found the topic interesting and I wanted to know how it works. This system was achieved by representing all the player's attributes with base data types and storing them in a custom binary file. Custom binary files are hard to read and modify which makes this a secure way of saving player data.
Saving/Loading level positions and XP
Checkpoints and Saving/Loading abilities
Game Manager
I was the only person on the team who had already worked on a Game-Manager before so taking on this task was a no-brainer. This system was used to keep track of things happening in the game. This is a singleton system; there is only one instance of it and it is carried over from scene to scene without being reloaded or destroyed. The Game-Manager keeps track of so many things, for example, are we in single-player or multiplayer, which bosses have been defeated, how many players are in the scene, is the current level a playable level (can we move the player around and perform actions), etc.
I had a lot of fun working on this system and I think it's the system that has had the most work done on it

Some of the Game-Manager's Functions
Game-Manager object in a scene (Unity editor) ---------------->>>
