Créer un système d'inventaire sur Unity

post-thumb

Réflexion sur le système

Pour mon système d’inventaire, je ne savais pas trop où commencer. Je savais juste qu’il fallait récupérer les informations des items ramassés, puis de les trier.

J’ai conçu ce petit croquis de ce que cela pourrait donner :

Schéma inventaire

Après avoir conçu mon chef-d’œuvre, je me suis lancée petit à petit dans mon inventaire.

Mise en œuvre de l’inventaire

Item

Suite à la conception du système de détection en parallèle, je prévois mon système d’inventaire. Pour cela, je commence par créer des items puis je les catégorises. C’est à ce moment-là que je comprends le principe de l’héritage !

Je vous montre ça ! L’héritage est comme un arbre généalogique ou encore un arbre technologique. Le script mère va être la base de tous ses enfants, ces derniers vont tous hériter du script mère.

Exemple

Petit exemple : un véhicule, ça peut aussi bien être une voiture qu’un avion. Et pourtant ce n’est pas la même chose. Mais tous les deux sont des véhicules. Une voiture va hériter de véhicule tout comme un avion.

Les items, c’est la même chose. Mon script Item va être une abstract ce qui signifie comme quoi, on ne peut pas avoir d’objet Item, car c’est Abstrait. Item sera mon script mère de tous les enfants héritant d’Item

Ces enfants auront : Un nom / une description / un nombre d’item / un nombre maximum stockable dans l’inventaire / une image / une fonction DropItem().

public abstract class Item : MonoBehaviour
{
	public string name;
	public string description;
	public int amount;
	public int amountStockableMax;
	public Sprite icon;

	public virtual void DropItem()
	{
		Debug.Log("Drop mon item");
	}
}

La magie arrive ! Chaque class est un enfant du script Item, mais chacun à ses propres fonctionnalités. Une potion peut s’utiliser alors qu’une arme peut s’équiper.

public abstract class Ressource : Item
{

}

public abstract class Potion : Item
{
	public virtual void Use()
	{
		Debug.Log("Je bois une potion");
	}
}

public abstract class Weapon : Item
{
	int damage;

	public int strength { private get; set; }
	public int get_damage() { return damage; }

	public virtual void Equip()
	{
		Debug.Log($"Tu as équipé une arme");
	}
}

public abstract class Equipement : Item
{
	public virtual void Equip()
	{
		Debug.Log("Je suis entrain de m'équiper");
	}
}

Le virtual permet de réécrire la méthode dans un script enfant de celui-ci.

InventoryItem

Une fois que j’ai fini avec les items, j’ai conçu des slots comportant un script “InventoryItem” Ce script, que va-t-il faire ?

// Nombre d'items dans le slot
[SerializeField] private int amountItem;

// Image de l'item affiché
[SerializeField] private Image itemImg;

// Texte d'affichage du nombre d'item
[SerializeField] private TextMeshProUGUI itemNumberTxt;

// Type d'item
[SerializeField] private Item item;

Ce script permet juste de stoker et de renvoyer les données qu’ils contiennent à “Inventory”.

Inventory

Je vais vous expliquer ce que fait le script “Inventory”.

Ce script s’occupe de la gestion de l’ensemble de l’inventaire. Il va trier et gérer les items dans les différents slots “inventoryItem”.

Je vous mets un petit croquis :

Schéma inventaire

Ce qui est en violet représente le bois que nous ramassons, le script “Inventory” va se charger de récupérer les informations qu’on lui donne à propos de l’item ramassé. représenté en Vert et en Rouge).

Le système sait qu’il peut mettre 100 items maximum dans un slot avec cette ressource. Or cette dernière comporte 225 bois.

Il va procéder à une soustraction pour chaque slot jusqu’à qu’il ne possède plus d’item :

Item = 225 (Nombre d’item ramassés)
Extra = Item - (NbItemMax - Slot.ItemAmount) = 225 - (100 - 0)

{

	// 75 - (100 - 75) = 50
    // On soustrait le nombre d'item que nous avons récupérés avec le nombre maximum de stockage de ce dernier puis avec le nombre d'item que possède le slot où nous souhaitons le ranger.
	extraItem = _item.amount - (_item.amountStockableMax -  _inventoryItem.GetAmountItem());

	Debug.Log("extraItem : " + extraItem);

	// Si nous ne possédons plus d'item alors nous ajoutons le reste et il n'y a pas/plus d'extra d'item 
	if(extraItem <= 0)
	{
		_inventoryItem.AddItem(_item.icon,_item.amount);

		extraItem = 0;
	}
	
	// Si nous avons un extra alors nous ajoutons le nombre d'item ramassés soustrait par l'extra. 
	// Puis nous déposons le nombre d'extra dans l'item correspondant.
	// Ensuite, nous recommençons à chercher un autre slot avec RangeItem()
	if (extraItem > 0)
	{
		// 75 - 50 = 25

		_inventoryItem.AddItem(_item.icon,_item.amount - extraItem);
		_item.amount = extraItem;

		RangeItem(_item);
	}
}

La méthode RangeItem() sert à ranger les items dans la liste de Slots tout en faisant des vérifications.

public void RangeItem(Item _item)
{

	foreach (var myInventoryItem in inventoryItems)
	{
	
		Debug.Log($"On récupere un item dans l'inventaire ");

		if (myInventoryItem.GetItem() != null &&
		myInventoryItem.GetAmountItem() != _item.amountStockableMax &&
		myInventoryItem.GetItem().name == _item.name)
		{
			Debug.Log("Ajout d'un item deja existant !");

			//myInventoryItem.AddItem(_item.icon,_item.amount);

			VerificationAmountItem(myInventoryItem, _item);

			break;
		}

		if (myInventoryItem.GetItem() == null)
		{
			Debug.Log("Nouvel item !" + _item);

			myInventoryItem.SetItem(_item);

			//myInventoryItem.AddItem(_item.icon,_item.amount);

			VerificationAmountItem(myInventoryItem, _item);

			return;
		}
	}
}

J’ai passé énormément de temps dessus, j’ai dû recommencer plusieurs fois le code et son architecture. Maintenant, je suis très satisfait du résultat.

Ensuite, je vais vous montrer comment fonctionne le système de choix sur les Items. Chaque Slot va contenir “InventoryItemUI” qui contient les panels d’affichage et qui se charge de les placer. Les panneaux d’affichage vont s’actionner lorsque le joueur passe dessus. La description et le panel de choix s’ouvre lorsqu’il clique.

OnPointerEnter et OnPointerDown

Pour afficher les bonnes actions, il faut vérifier l’item et pour cela, j’ai fais “ChoiceActionItem” se chargeant de regarder le slot que j’ai cliqué (grâce au InventoryItemUI).

J’ai longuement réfléchi sur comment j’allais mettre en place un système de vérification le plus logique par rapport à mon système. Une armée de “if” ne serait pas l’ideal ! Donc pour cela, j’ai utilisé les Switch pour regarder de quel type était l’Item dans le Slot correspondant.

void CheckType()
{
	switch (item)
	{
		case Weapon weapon:
			weapon.Equip();
	
			Debug.Log($"Vous avez pris une arme !");
	
			break;

		case Ressource resource:
			Debug.Log($"Vous avez pris une ressource !");

			break;

		case Equipement equipement:
			equipement.Equip();
	
			Debug.Log($"Vous avez pris une equipement !");

			break;
			
		case Potion potion:
			potion.Use();

			Debug.Log($"Vous avez pris une potion !");

			break;
			
		default:
			Debug.Log($"Vous n'avez rien pris ...");

			break;
	}
}

Si l’Item est de tel type, alors, nous faisons telle action, c’est aussi simple que ça ! Bien sûr, avec ceci, j’ai dû paramétrer des boutons par rapport à leurs actions : Drop, Use, Equip etc…

Après cette belle aventure du rangement des Slots avec les actions allant avec, il fallait partir à la conquête du Drag And Drop et du Split des Items dans l’inventaire !

Résultat

Tu pourrais aussi aimer