Cave Ambush was my first attempt at a game made in Unity utilising the features of the 6000.0.19 version. The game took place inside of a cave where the player would need to fight off hordes of enemies until the time ran out. The player also had access to an upgrade system to help them survive. This game was coded in C# and I took inspiration from other roguelike titles such as Enter the Gungeon and Vampire Survivors.
The mechanics in this game were a blast to create as using Unity was a fantastic experience and has cemented itself as one of my favourite game engines to work with.
Upgrade System
This was a crucial aspect the game needed to be an effective roguelike. This system allows the player to get more powerful over the course of their attempt and they have a few options at their disposal; dash distance and cooldown time as well as attack cooldown and damage. This was in addition to a general health restore for the players who are taking a beating. I created this system by creating a series of sub menus and using a script to control said menus.
public void Attack_Damage_Chosen()
{
int Amount = m_PlayerScore.Get_Score();
if (Amount >= 150)
{
Time.timeScale = 1;
m_PlayerDamage.Increase_Damage(20);
m_PlayerScore.Sub_Score(150);
m_AttackMenu.SetActive(false);
}
else
{
m_AttackMenu.SetActive(false);
m_CantAfford.SetActive(true);
m_UpgradeMenu.SetActive(true);
}
}
Enemies
I made two kinds of enemies, one more common enemy that could be killed in five shots that resembled a mushroom, and one more rare enemy that took seven shots and resembled a flying golem creature. These are the threats in the game which had to be carefully balanced to ensure they were not to hard to deal with or to easy. This was even more important as the enemies would spawn on a timer so they could build up fast.
void Start()
{
StartCoroutine(SpawnEnemy(m_MushInterval, m_EnemyMushPrefab, m_MaxEnemies));
StartCoroutine(SpawnEnemy(m_GargInterval, m_EnemyGargPrefab, m_MaxEnemies));
}
//Spawns an enemy every couple seconds depending on there interval time at a random position. Will infinitely loop.
private IEnumerator SpawnEnemy(float interval, GameObject enemy, float max_Enemies)
{
yield return new WaitForSeconds(interval);
GameObject Spawned_Enemy = Instantiate(enemy, new Vector3(Random.Range(-4f, 30f), Random.Range(-8f, 10f), 0), Quaternion.identity);
Debug.Log(Spawned_Enemy.transform.position);
StartCoroutine(SpawnEnemy(interval, enemy, max_Enemies));
}
Dash Mechanic
Creating the dash mechanic was a blast as I got to work with coroutines to time my changes in speed exactly when I needed them. This was so that the animation that played when the roll began matched the speed changes.
void Dash()
{
while (m_DashCooldown == false)
{
Vector2 Dash_Direction = m_LastDirection;
if (Dash_Direction == Vector2.zero)
{
Dash_Direction = Vector2.down;
}
StartCoroutine(Dash_Move());
}
}
IEnumerator Dash_Move()
{
m_DashCooldown = true;
m_PlayerSpeed = m_DashForce;
yield return new WaitForSeconds(m_DashTime);
m_PlayerSpeed = 300;
yield return new WaitForSeconds(m_DashCooldownTime);
m_DashCooldown = false;
}
Shooting Mechanic
I created a shooting mechanic that would allow the player to survive. This mechanic was hard to implement the first time around as the maths behind finding where the player was where the mouse was ended up being very confusing. However, I figured it out with some help and was able to make a decent shooting system.
m_MousePos = m_MainCamera.ScreenToWorldPoint(Input.mousePosition);
Vector3 direction = m_MousePos - transform.position;
Vector3 rotation = transform.position - m_MousePos;
m_RB.linearVelocity = new Vector2 (direction.x, direction.y).normalized * m_Speed;