AQUARIØS
Project Status
Finished
Project type
School assignment
Project Duration
8 weeks
Software Used
Unity
Languages Used
C#
My Role(s)
Lead programmer
It is included in my portfolio because
It includes some common survival systems.
AQUARIØS was created within 8 weeks for a school assignment. It was made with a team of 4 people, where I took the role of lead programmer. This project teached me to create SOLID systems.
Full playthrough
Inventory System
The inventory system or actually item storage system is an important part of any survival/gather game. It was important that this system could be used for any type of storage, for example chests, backpacks, etc. This has been done through inheritance and polymorphism. Although it could be done with interfaces, inheritance and polymorphism is a powerful combination and especially with a game that is fairly small in size.
I do think that using inheritance is also the best way an item storage system in a survival game, since that guarantees that interactions between different types of storage systems are the same and have the same functionality.
This would perhaps be a different case if the game had creative or very custom storage systems.
Code snippet - Inventory System
In this code you can see how item stacking and taking works in the inventory. Items are stored in an ItemSlot.
When adding an item each item slot is checked to see if the item already exists in the inventory, if this is the case then the quantity is increased.
If the quantity is bigger than the maximum quantity of the item it is added to the next item slot. With each item having their own max quantity, I could also easily create non-stackable items, by setting the max quantity to 1.
1 //Returns the total amount of one item
2 public int AmountOf(int itemId) {
3 int total = 0;
4
5 for (int i = 0; i < itemSlots.Count; i++) {
6 if (itemSlots[i].itemID == itemId)
7 {
8 total += itemSlots[i].Quantity;
9 }
10 }
11
12 return total;
13 }
14
15 /// <summary>
16 /// Adds item is possible, returns true if item was added succesfully
17 /// </summary>
18 /// <param name="itemId"></param>
19 /// <returns>True if item was added</returns>
20 public virtual bool AddItem(int itemId, int quantity = 1) {
21 if (items.Contains(itemId)) {
22 do
23 {
24 ItemSlot sd = GetItemStackWithRoom(itemId);
25 if (sd == null) {
26 return AddNewItem(itemId, quantity);
27 } else if (sd.HasRoom(quantity)) {
28 sd.Quantity += quantity;
29 break;
30 } else {
31 int temp = (sd.MaxQuantity - sd.Quantity);
32 quantity -= temp;
33 sd.Quantity += temp;
34 }
35 } while (quantity > 0);
36 } else {
37 return AddNewItem(itemId, quantity);
38 }
39
40 return true;
41 }
42
43 public void RemoveItem(int itemId, int removalQuantity) {
44 if (!items.Contains(itemId)) {
45 Debug.LogError($"Tried to remove item ID: {itemId} while it doesn't exist");
46 }
47
48 do {
49 ItemSlot sd = GetItemStack(itemId);
50 int sdQuantity = sd.Quantity;
51
52 if (sdQuantity >= removalQuantity) {
53 sd.Quantity -= removalQuantity;
54 removalQuantity -= removalQuantity;
55 } else {
56 removalQuantity -= sdQuantity;
57 sd.Quantity -= sdQuantity;
58 }
59
60 } while (removalQuantity > 0);
61 }
62
63 private bool AddNewItem(int itemId, int quantity) {
64 if (HasRoom()) {
65 items.Add(itemId);
66 ItemSlot sd = GetEmptyStack();
67
68 sd.AssignItem(itemId, quantity);
69
70 //If for some reason the quantity is bigger than a full stack, fix it
71 if (quantity > sd.MaxQuantity) {
72 sd.Quantity = sd.MaxQuantity;
73 quantity -= sd.MaxQuantity;
74 return AddItem(itemId, quantity);
75 }
76
77 if (sd.OnStackEmpty == null) {
78 sd.OnStackEmpty += RemoveItemStack;
79 }
80
81 occupiedDisplays += 1;
82 return true;
83 } else {
84 return false;
85 }
86 }
87
88 private void RemoveItemStack(int itemId) {
89 occupiedDisplays -= 1;
90 int index = items.IndexOf(itemId);
91 items.RemoveAt(index);
92 }Weapon System
In AQUARIØS there are around 7-8 different types of weapons, with some being completely different mechanically compared to others. The game has crossbows, shields, hammers, daggers, spears, etc. With weapons I decided to use an interface, which allowed me to create all of these different workings while the player does not need to know the mechanics of each weapon.
1 public interface IWeapon {
2
3 Animator PlayerAnim { get; set; }
4 float AttackInterval { get; }
5 void DoAttackAnimation();
6 void Attack();
7
8 }Shield preview
Code snippet - Shield
1 public class Shield : MeleeWeapon {
2
3 public override void DoAttackAnimation() {
4 PlayerCombat.OnChangeHpPlayerEvent += Block;
5 base.DoAttackAnimation();
6 }
7
8 public override void Attack() {
9 PlayerCombat.OnChangeHpPlayerEvent -= Block;
10 }
11
12 private void Block(int damage) {
13 if (damage < 0) {
14 PlayerCombat.HealingPlayerEvent?.Invoke(Mathf.Abs(damage));
15 StunEnemy();
16 }
17 }
18
19 private void StunEnemy() {
20 if (CheckForHits(out Collider[] hits)) {
21 for (int i = 0; i < hits.Length; i++) {
22 hits[i].GetComponent<IDamagable>().Stun(1.5f);
23 }
24 FMODUnity.RuntimeManager.PlayOneShot(attackSFX, transform.position);
25 }
26 }
27
28 }Hammer preview
Code snippet - Hammer
1 public class Hammer : MeleeWeapon {
2
3 public override void Attack() {
4 if (CheckForHits(out Collider[] hits)) {
5 for (int i = 0; i < hits.Length; i++) {
6 var hit = hits[i].GetComponent<IDamagable>();
7 hit.TakeDamage(damage);
8 hit.Stun(1f);
9 }
10
11 FMODUnity.RuntimeManager.PlayOneShot(attackSFX, transform.position);
12 }
13 }
14
15 }Spear preview
Code snippet - Spear
1 public class Spear : RangedWeapon {
2
3 public override void Attack() {
4 base.Attack();
5
6 if (!UIManager.Instance.inventory.Contains(ammo.id)) {
7 ItemOptionMenu.Instance.UnEquip();
8 }
9 }
10
11 }