概要
今回はinventorySlotをドラッグ or クリックしたときにハイライトで強調されるようにします。
開発環境
IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10
UnityEditor上の設定
Slotのプレハブにハイライトをのオブジェクトをあることを確認します。
実装のポイント
共通
UIInventoryBarクラスについて
ClearHighlightOnInventorySlotsとSetHighlightedInventorySlotsメソッドを加えます。
ClearHighlightOnInventorySlotsメソッドは格InventorySlotクラスのisSelectedをfalseにしハイライト画像をのアルファ値を0(透明)にします。
SetHighlightedInventorySlotsメソッドは、UIInventorySlot.isSelected=trueの時ハイライトのアルファ値を255(不透明)にします。
UIInventorySlotクラスについて
bool型の変数isSelectedを加えます。trueのときはハイライトが表示されます。
SetSelectedItem、OnPointerClickメソッドを加えます。
SetSelectedItemはisSelected=trueをにします。
OnPointerClickはオブジェクトをクリックした時に実行されます。
ハイライトを表示する処理
ドラッグ時の処理
クリック時の処理
ハイライトを非表示にする処理
ドラッグを終了した時
ハイライトされているslotをクリックした場合
コード部分
UIInventorySlot
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UIInventorySlot : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler,IPointerEnterHandler,IPointerExitHandler,IPointerClickHandler
{
private Camera mainCamera;
private Canvas parentCanvas;
private GameObject draggedItem;
private Transform parentItem;
public Image inventorySlotHighlight;
public Image inventorySlotImage;
public TextMeshProUGUI textMeshProUGUI;
[SerializeField] private UIInventoryBar inventoryBar = null;
[SerializeField] private GameObject inventoryTextBoxPrefab = null;
public ItemDetails itemDetails;
[SerializeField] private GameObject itemPrefab;
public int itemQuantity;
[SerializeField] private int slotNumber = 0;
[HideInInspector] public bool isSelected;
+ private void SetSelectedItem()
+ {
+ inventoryBar.ClearHighlightOnInventorySlots();
+ isSelected = true;
+ inventoryBar.SetHighlightedInventorySlots();
+ }
+ private void ClearSelectedItem()
+ {
+ inventoryBar.ClearHighlightOnInventorySlots();
+ isSelected = false;
+ }
private void DropSelectedItemAtMousePosition()
{
if (itemDetails != null)
{
Vector3 worldPosition = mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,
Input.mousePosition.y, -mainCamera.transform.position.z));
GameObject itemGameObject = Instantiate(itemPrefab, worldPosition, Quaternion.identity, parentItem);
Item item = itemGameObject.GetComponent<Item>();
item.ItemCode = itemDetails.itemCode;
InventoryManager.Instance.RemoveItem(InventoryLocation.player, item.ItemCode);
}
}
public void OnBeginDrag(PointerEventData eventData)
{
if (itemDetails != null)
{
Player.Instance.DisablePlayerInputAndResetMovement();
draggedItem = Instantiate(inventoryBar.inventoryBarDraggedItem, inventoryBar.transform);
Image draggedItemImage = draggedItem.GetComponentInChildren<Image>();
draggedItemImage.sprite = inventorySlotImage.sprite;
+ SetSelectedItem();
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (draggedItem != null)
{
Destroy(draggedItem);
if (eventData.pointerCurrentRaycast.gameObject != null && eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>() != null)
{
int toSlotNumber = eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>().slotNumber;
InventoryManager.Instance.SwapInventoryItem(InventoryLocation.player, slotNumber, toSlotNumber);
DestroyInventoryTextBox();
+ ClearSelectedItem();
}
else
{
if (itemDetails.canBeDropped)
{
DropSelectedItemAtMousePosition();
}
}
Player.Instance.EnablePlayerInput();
}
}
+ public void OnPointerClick(PointerEventData eventData)
+ {
+ if (eventData.button == PointerEventData.InputButton.Left)
+ {
+ if (isSelected == true)
+ {
+ ClearSelectedItem();
+ }
+ else
+ {
+ if (itemQuantity > 0)
+ {
+ SetSelectedItem();
+ }
+ }
+ }
+ }
}
UIInventoryBar
using System.Collections.Generic;
using UnityEngine;
public class UIInventoryBar : MonoBehaviour
{
[SerializeField] private Sprite blank16x16sprite = null;
[SerializeField] private UIInventorySlot[] inventorySlot = null;
public GameObject inventoryBarDraggedItem;
[HideInInspector] public GameObject inventoryTextBoxGameObject;
+ public void ClearHighlightOnInventorySlots()
+ {
+ if (inventorySlot.Length > 0)
+ {
+ for (int i = 0; i < inventorySlot.Length; i++)
+ {
+ inventorySlot[i].isSelected = false;
+ inventorySlot[i].inventorySlotHighlight.color = new Color(0f, 0f, 0f, 0f);
+ }
+ }
+ }
private void ClearInventorySlots()
{
if (inventorySlot.Length > 0)
{
for (int i = 0; i < inventorySlot.Length; i++)
{
inventorySlot[i].inventorySlotImage.sprite = blank16x16sprite;
inventorySlot[i].textMeshProUGUI.text = "";
inventorySlot[i].itemDetails = null;
inventorySlot[i].itemQuantity = 0;
+ SetHighlightedInventorySlots(i);
}
}
}
private void InventoryUpdated(InventoryLocation inventoryLocation, List<InventoryItem> inventoryList)
{
if (inventoryLocation == InventoryLocation.player)
{
ClearInventorySlots();
if (inventorySlot.Length > 0 && inventoryList.Count > 0)
{
for (int i = 0; i < inventorySlot.Length; i++)
{
if (i < inventoryList.Count)
{
int itemCode = inventoryList[i].itemCode;
ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);
if (itemDetails != null)
{
inventorySlot[i].inventorySlotImage.sprite = itemDetails.itemSprite;
inventorySlot[i].textMeshProUGUI.text = inventoryList[i].itemQuantity.ToString();
inventorySlot[i].itemDetails = itemDetails;
inventorySlot[i].itemQuantity = inventoryList[i].itemQuantity;
+ SetHighlightedInventorySlots(i);
}
}
else
{
break;
}
}
}
}
}
+ public void SetHighlightedInventorySlots()
+ {
+ if (inventorySlot.Length > 0)
+ {
+ for (int i = 0; i < inventorySlot.Length; i++)
+ {
+ SetHighlightedInventorySlots(i);
+ }
+ }
+ }
+ public void SetHighlightedInventorySlots(int itemPosition)
+ {
+ if (inventorySlot.Length > 0 && inventorySlot[itemPosition].itemDetails != null)
+ {
+ if (inventorySlot[itemPosition].isSelected)
+ {
+ inventorySlot[itemPosition].inventorySlotHighlight.color = new Color(1f, 1f, 1f, 1f);
+ }
+ }
+ }
}
参考
C#
Unity Editor コンポーネント
Unity スクリプト
eventData.button
PointerEventData.InputButton.Left
OnPointerClick
Image.color
その他
Section 32 Select Items On The Inventory Bar
github コミット分(個人確認用 privateなので見れません)