Créer un système de Drag and Drop sur Unity

post-thumb

Réflexion sur le système de Drag and Drop et celui du Split

Étant donné que j’ai trouvé l’exercice plutôt simple, je me suis dit “Je veux mordre la poussière !” Et j’ai eu la merveilleuse idée de faire un système de drag and drop et de split … ça va être sympa, c’est moi qu’il vous le dit !

Je ne savais pas comment réaliser ce système, il y avait tellement de choses à penser pour un système si simples à première vue. Prendre le slot, le déplacer, changer sa position dans la hiérarchie, copier les données etc.

Pour cela, je me suis fait de petits croquis de mon côté pour voir le système global, comment le joueur pourrait interagir et comment le système va réagir en conséquence. J’ai beaucoup regardé comme exemple l’inventaire de Minecraft. Ce jeu mythique plein de bonnes ressources !

Le Drag and Drop

Schéma sur le comportement Drag and Drop

J’ai conçu mon inventaire autour des systèmes d’interface d’événements. J’ai utilisé le PointerEnter, PointerClick etc.

Pour commencer, à quoi peut-il servir ce fameux PointerEnter !?

Ce que j’ai appris a été très intéressant ! Cette méthode nous permet de récupérer les données que la souris survole, clique, etc. lorsqu’elle se trouve sur un élément d’interface (UI). Et étant donné que l’inventaire ne fonctionne qu’avec des éléments d’interfaces, cette méthode nous facilite la tâche pour la récupération des données au niveau des Slots.

Après avoir vu ce qu’était ces méthodes et comment elles s’utilisent. Je me suis lancé sur le système drag and drop.

Il y avait 2 choix et bien sûr, j’ai testé les deux !

La première était de glisser / déposer le slot sur un autre, puis de changer leur emplacement, c’est-à-dire que le slot A prend la position du slot B et inversement, la problématique ici est que nous pouvons rencontrer un potentiel décalage dans la position s’il y a la moindre erreur.

La deuxième méthode consiste à glisser / déposer le slot sur un autre puis de le cloner. Le slot A devient alors le slot B et vise versa. Ce qui est bien avec cette méthode est le fait que nous pouvons plus facilement rassembler les mêmes items et les slots restent à leur place initiale (sauf pour le slot que l’on glisse / dépose). La problématique ici est qu’il faut les cloner correctement, sinon on peut avoir des surprises !

Je vous montre mon code :

void Update()
{
	if (!isDragging)
	{

		slotDivisionCount.Clear();

		slotCraftDivisionCount.Clear();

		itemCount = 0;

		return;
	}

	transform.position = Input.mousePosition;

	transform.SetAsLastSibling();
	
	
	if (Input.GetMouseButtonDown(0))
	{
		//Toute la partie verification pour le drag and drop
	}
	
	if (Input.GetMouseButton(1))
	{
		//Toute la partie verification pour le Split
	}
} 

public void OnPointerClick(PointerEventData eventData)
{
	if(eventData.pointerClick.GetComponent<SlotDragAndDrop>() == null)
		return;

	if (inventoryItem != null && inventoryItem.GetAmountItem() == 0 ||
	craftSlotItem != null && craftSlotItem.GetAmountItem() == 0 )
	{
		return;
	}


	orinalPostion = rectTransform.anchoredPosition;

	canvasGroup.blocksRaycasts = isDragging;

	isDragging = !isDragging;

	eventDataClick = eventData;

}

public void OnPointerEnter(PointerEventData eventData)
{
	eventDataEnter = eventData;
}

Refactorisation

Avant de refactoriser, je me suis posé la question si je garde mon système dans cette même logique de fonctionnement. Après plusieurs temps de réflexions, je voulais changer la manière de procéder.

Le fait que chaque slot ait son propre script possédant à la fois le système de drag and drop, une partie du système de vérification ainsi que celui du Split me semble un peu bizarre.

Pour cela, j’ai créé un nouveau script "**DragAndDropManager**" et comme le nom l’indique, c’est lui qui va se charger de vérifier si les slots peuvent être glissés / déposés et split. Il récupère les données envoyées lors de l’interaction avec un des slots, puis il va traiter l’information pour modifier ce dernier.

À savoir également que j’utilise le New Input System pour créer les interactions, cela est plus simple à mettre en place et à implémenter.

J’ai également profité pour supprimer CraftSlotItem pour tout mettre dans InventoryItem avec un enum pour différencier les deux. J’ai fait de cette manière, car ils se ressemblaient comme deux gouttes d’eau.

À la fin, je me suis rendu compte que c’était plus logique dans la manière de procéder et puis que le code était beaucoup plus lisible.

Le Split

Mon système de Split ne m’a pas pris beaucoup de temps à réaliser. Armé de ma feuille de papier (en réalité plusieurs) et de mon crayon de bois (bien sûr sans gomme, car toutes recherches réalisées peuvent nous resservir). J’ai réalisé ceci :

Schéma sur le comportement du Split

Suite à ça, il ne me fallait plus qu’à l’intégrer.

La méthode SplitItem va nous permettre de paramétrer notre slot lorsque nous faisons la division de nos items.

public void SplitItem(Sprite sprite, int _amount)
{
	amountItem = _amount;

	itemImg.sprite = sprite;

	itemImg.color = new Color(255,255,255,255);

	itemNumberTxt.text = amountItem.ToString();
}

La méthode Split permet de diviser nos items par rapport au nombre de slots que nous avons sélectionnés.

Nombre d'items par slot = Nombre d'items dans le slot sélectionné / nombre total de slot sélectionnés

Par exemple : 2 = 6 / 3 sois 2 items par slot.

void Split(InventoryItem _slot)
{
	_slot.SetItem(inventoryItem.GetItem());

	int num = itemCount / (slotDivisionCount.Count );

	int numFinal= 0;

	foreach (InventoryItem slotDivision in slotDivisionCount)
	{
		slotDivision.SplitItem(inventoryItem.GetImageItem().sprite, num);

		numFinal += num;
	}


	if (numFinal != itemCount)
	{
		int extra = itemCount - numFinal;

		for (int i = 0; i < extra; i++)
		{
			slotDivisionCount[i].AddItem(inventoryItem.GetImageItem().sprite, 1);
		}
	}
}

Comment faisons-nous si nous avons un nombre à virgule ?

Pour cela, j’ai simplement fait une variable où nous allons lui ajouter le nombre d’items par slot à l’aide d’une boucle. Comme ça, je peux la comparer avec le nombre d’items qu’il y aurait dû avoir normalement.

Et si le nombre une valeur à virgule, nous faisons nombre d'items total - nombre d'items total mis dans les slots.

J’ai 8 items dans mon slot que je glisse, je souhaite le diviser sur 2 slots (ce qui fait 3 avec le slot actuel).

2 = 8 / 3 ce qui fait 2 items par slot mais il m’en reste 2 à ajouter parmi mes 3 slots :

if (6 != 8) alors : 8 - 6 = 2

Donc mes deux premiers slots auront 1 item en plus.

Pour finir, j’obtiendrais l’extra d’item qu’il me reste pour l’ajouter dans les slots. À savoir que cet extra ne peut être que de 1 jusqu’au nombre de slots sélectionnés.

Résultat

Tu pourrais aussi aimer