# Inventory Manager
**Technology**: The inventory system is implemented through the Observer pattern
**Assets** are sourced
![[DESIGNS/TOYS/InventoryObserver.gif]]
## Code
#### Observer Manager
```cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arcade_II_Observer : MonoBehaviour
{
private string _weaponName;
public string WeaponName => _weaponName;
public Action<string> OnWeaponSelection;
public static Arcade_II_Observer Instance; // Similar to singleton void Start()
private void Awake()
{
// Similar to Singleton -- preserves clones
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
}
public void DisplayWeapon(string weaponName)
{
OnWeaponSelection?.Invoke(_weaponName);
}
}
```
#### Player Controller
(1) Inventory panel follows the player when it moves
(2) When the weapon is dragged to the player's hands, it moves with him
(3) Player movement
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arcade_II_Player : MonoBehaviour
{
[Header ("Movement")]
public float moveSpeed = 5f;
public float jumpForce = 4f;
private Rigidbody2D rb;
private bool isGrounded = false;
[Header("Inventory")]
public GameObject[] invWeapons = new GameObject[3];
public GameObject[] invWeapPositions = new GameObject[3];
public GameObject inventoryPanel;
private bool inventoryOpen;
[Header("Hands")]
public GameObject hands;
private int handsTurnValue; // for when the avatar turns left and right
private string currentWeaponInHand;
[Header("Hands Mockups")]
public GameObject m_bomb;
public GameObject m_knife;
public GameObject m_gun;
[Header("UI")]
public GameObject gameOverPanel;
void Start()
{
rb = GetComponent<Rigidbody2D>(); // Get the Rigidbody2D component
handsTurnValue = -1;
Arcade_II_Observer.Instance.OnWeaponSelection += ShowWeapon;
}
void Update()
{
MoveAvatar();
FixRotation();
FollowPlayer_Hands();
OpenInventory();
if(inventoryOpen) FollowPlayer_Inventory();
}
public void GameOverUI()
{
gameOverPanel.SetActive(true);
}
/// <summary>
/// INVENTORY
/// </summary>
private void OpenInventory()
{
if (Input.GetKeyDown(KeyCode.I))
{
if (!inventoryOpen)
{
inventoryPanel.SetActive(true);
inventoryOpen = true;
inventoryPanel.transform.parent = null;
}
else CloseInventory();
}
}
private void CloseInventory()
{
inventoryPanel.SetActive(false);
inventoryOpen = false;
}
private void FollowPlayer_Inventory()
{
Vector3 newPos = new Vector3
(gameObject.transform.position.x, gameObject.transform.position.y + 3.5f, 0);
inventoryPanel.transform.position = newPos;
}
private void FollowPlayer_Hands()
{
Vector3 newPos = new Vector3
(gameObject.transform.position.x + handsTurnValue, gameObject.transform.position.y, 0);
hands.transform.position = newPos;
// So that the weapon in hands turns in a related direction
hands.transform.localScale = new Vector3(
0.4f * -handsTurnValue,
gameObject.transform.localScale.y,
gameObject.transform.localScale.z);
}
private void ShowWeapon(string weaponName)
{
currentWeaponInHand = weaponName;
DeactivateWeapondInHand();
ActivateInventoryIcons();
if (weaponName == "Bomb") m_bomb.gameObject.SetActive(true);
if (weaponName == "Knife") m_knife.gameObject.SetActive(true);
if (weaponName == "Gun") m_gun.gameObject.SetActive(true);
CloseInventory();
}
private void DeactivateWeapondInHand()
{
m_bomb.gameObject.SetActive(false);
m_knife.gameObject.SetActive(false);
m_gun.gameObject.SetActive(false);
}
private void ActivateInventoryIcons()
{
foreach (GameObject weapon in invWeapons)
{
if (weapon.name != currentWeaponInHand)
{
weapon.SetActive(true);
}
}
}
/// <summary>
/// MOVEMENT
/// </summary>
/// <param name="collision"></param>
// Detect ground using collision
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
private void MoveAvatar()
{
// Get horizontal movement input
float moveInput = Input.GetAxis("Horizontal");
// Move left & right
rb.velocity = new Vector2(moveInput * moveSpeed, rb.velocity.y);
// Turning left / right
if (moveInput < 0)
{
handsTurnValue = -1;
gameObject.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
}
if (moveInput > 0)
{
handsTurnValue = 1;
gameObject.transform.localScale = new Vector3(-0.4f, 0.4f, 0.4f);
}
// Jump when SPACE is pressed & only if grounded
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
isGrounded = false; // Prevents double jumping
}
}
private void FixRotation()
{
gameObject.GetComponent<Transform>().rotation = Quaternion.Euler(0, 0, 0);
}
}
```
#### Weapon Manager
(1) Notifies the observer which weapon is in hands
(2) Allows dragging weapons on mouse
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arcade_II_Weapon : MonoBehaviour
{
public Transform avatarTr;
public Transform handsTr;
public Transform inventoryTr;
public GameObject defaultPosObj;
private Vector3 defaultPos;
private bool isDragged;
private bool inHands;
private void Start()
{
defaultPos = defaultPosObj.transform.localPosition;
}
public void OnMouseDown()
{
isDragged = true;
if (inHands)
{
gameObject.transform.localPosition = defaultPos;
inHands = false;
}
}
public void OnMouseUp()
{
isDragged = false;
gameObject.transform.localPosition = defaultPos;
if (inHands)
{
Arcade_II_Observer.Instance.OnWeaponSelection(gameObject.name);
gameObject.SetActive(false);
}
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.CompareTag("Hands"))
{
inHands = true;
}
if (col.gameObject.CompareTag("Key"))
{
Arcade_II_Weapon weaponScr = col.gameObject.GetComponent<Arcade_II_Weapon>();
weaponScr.inHands = false;
weaponScr.OnMouseUp();
}
}
/// <summary>
/// DRAGGING
/// </summary>
private void DragObject()
{
if (isDragged)
{
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
transform.Translate(mousePos);
}
}
private void Update()
{
DragObject();
}
}
```
#### Fighting Controller
Performs different attacks on F (fire) button
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arcade_II_Fighting : MonoBehaviour
{
public string weaponName;
public GameObject hands; // to understand the direction
public GameObject detail;
public GameObject detailPos;
private GameObject newDetail; // for instantiations
private void Update()
{
if (Input.GetKeyDown(KeyCode.F)) Action();
}
private void Action()
{
if (weaponName == "Bomb") BombAction();
if (weaponName == "Knife") KnifeAction();
if (weaponName == "Gun") GunAction();
}
private void BombAction()
{
Arcade_II_Bomb bombScript = gameObject.GetComponent<Arcade_II_Bomb>();
// The argument defines which direction the avatar is facing
if (hands.transform.localScale.x > 0) bombScript.ThrowBomb(false);
if (hands.transform.localScale.x < 0) bombScript.ThrowBomb(true);
}
private void KnifeAction()
{
Animator knifeAnimator = GetComponent<Animator>();
knifeAnimator.SetTrigger("play");
}
private void GunAction()
{
newDetail = Instantiate(detail, detailPos.transform.position, Quaternion.identity);
Arcade_II_Bullet newDetailScr = newDetail.GetComponent<Arcade_II_Bullet>();
// Define direction
if (hands.transform.localScale.x > 0) newDetailScr.direction = Vector3.left;
else if (hands.transform.localScale.x < 0) newDetailScr.direction = Vector3.right;
}
}
```
##### Bomb
Controls the bomb weapon's explosion
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arcade_II_Bomb : MonoBehaviour
{
public GameObject bombPiece;
private GameObject newBombPiece; // for instantiations
public GameObject hands;
private Vector3 handsPos;
private Rigidbody2D rb;
private CircleCollider2D cCol;
private Vector3 bombForce;
public void ThrowBomb(bool facesRight)
{
gameObject.transform.parent = null;
rb = gameObject.AddComponent<Rigidbody2D>();
cCol = gameObject.AddComponent<CircleCollider2D>();
if (facesRight) bombForce = new Vector3(5, 3, 0);
if (!facesRight) bombForce = new Vector3(-5, 3, 0);
rb.AddForce(bombForce, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.CompareTag("Ground"))
{
//gameObject.GetComponent<SpriteRenderer>().enabled = false;
for (int i = 0; i < 20; i++)
{
newBombPiece = Instantiate(bombPiece,
gameObject.transform.position, Quaternion.identity);
int forceX = Random.Range(-4, 4);
int forceY = Random.Range(3, 8);
Vector3 forceVec = new Vector3(forceX, forceY, 0);
newBombPiece.AddComponent<Rigidbody2D>().AddForce
(forceVec, ForceMode2D.Impulse);
}
gameObject.transform.parent = hands.gameObject.transform;
gameObject.transform.position = hands.transform.position;
Destroy(rb);
Destroy(cCol);
}
}
}
```
#### Enemy Generator
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arcade_II_EnemyGenerator : MonoBehaviour
{
public GameObject enemyPref;
public float repeatRate = 5;
private GameObject enemyInstance;
private Vector3 enemyPos;
private void Start()
{
InvokeRepeating("InstantEnemy", 2, repeatRate);
}
private void InstantEnemy()
{
int x = Random.Range(-7, 7);
enemyPos = new Vector3(x, 6, 0);
enemyInstance = Instantiate(enemyPref, enemyPos, Quaternion.identity);
}
}
```