バーチャル3Dクリエイター神部まゆみです(*^_^*)
この記事はUnityでアイテム欄メニュー画面を作ってみた記事の続きです。
前回の記事はこちら。
やりたいこと:アイテムメニュー画面で特定のアイテムを選択できるようにする
前回インベントリのアイテムを表示することはできたけど、表示しただけなのでアイテムを選択したりはできない。
カーソルを実装しないといけないと思うけど結構大変なイメージ?
まぁChatGPTパイセンに聞けばなんとかなるか…。
ChatGPTパイセンに聞いてみる
とりあえず彼に相談すればなんとかなるだろう…。




インベントリのアイテム表示は無事に実装できました。 しかしまだ表示できただけです。
アイテムを選択するためにはカーソルが必要になるのではないでしょうか?しかも空のアイテム欄は飛ばせるようにするか、空のスロットならボタンを押しても無効だと判定したりしないといけません。結構大変そうなイメージですがすぐできるのでしょうか?


その不安、めちゃくちゃ分かります。
でも安心してください。思っているほど大変じゃないです。
むしろ今の構成だと「自然に」実装できます。
結論から言うと👇
✔ カーソルはもうある
✔ 空スロット判定も一瞬
✔ “選択できない”処理は UI 側だけで完結する
ひとつずつ見ていきましょう。
① カーソルは「もう用意できている」
実はあなた、もうカーソル周りはクリアしてます。
ポーズ中に👇をやってますよね?
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
これだけで
- マウスでスロットをクリックできる
- UI の Button が反応する
👉 新しくカーソルを作る必要はありません。
② ItemSlot を「Button」として使う
やることはこれだけ
- ItemSlot(親オブジェクト)に
Buttonを付ける ItemSlotスクリプトに「選択」処理を書く
public class ItemSlot : MonoBehaviour
{
[SerializeField] private Image icon;
private ItemData currentItem;
public void SetItem(ItemData item)
{
currentItem = item;
if (item == null)
{
icon.enabled = false;
GetComponent<Button>().interactable = false;
return;
}
icon.enabled = true;
icon.sprite = item.icon;
GetComponent<Button>().interactable = true;
}
public void OnClick()
{
if (currentItem == null) return;
Debug.Log($"Selected: {currentItem.itemName}");
}
}
✔ 空スロットは自動で押せなくなる
✔ 判定は UI 側だけ
③ 「空スロットを飛ばす」必要はない
ここ、安心ポイントです。
マウス操作の場合
- 空スロットは
interactable = false - そもそも選べない
ゲームパッド操作の場合(後回しでOK)
- EventSystem が勝手にスキップしてくれる
👉 自前で「空を飛ばす」処理は書きません。
④ 選択状態の見た目もすぐできる
例:選択中フレーム表示
[SerializeField] private GameObject selectedFrame;
public void SetSelected(bool selected)
{
selectedFrame.SetActive(selected);
}
選択管理はItemMenuController がやるのがきれいです。
⑤ どれくらい大変?
正直に言うと👇
- UI構築:もう終わってる
- カーソル:もうある
- 空判定:3行
- 選択処理:Button 1個
👉 半日もかからないレベルです。
⑥ 今やらなくていいこと
- キーボード/ゲームパッド操作
- 十字キー移動
- スクロール
まずは
マウスで選べる=完成
でOKです。
まとめ
- ✅ カーソルは既に出ている
- ✅ Button を使えば選択は一瞬
- ✅ 空スロットは interactable=false
- ✅ 想像よりずっと簡単
え、もう実はカーソルを実装していたっぽい。
ChatGPTパイセンの言う通りにコピペしただけだから気付かなかったけど(^_^;)
実際に動かしてみる
とりあえず選択してクリックしてデバッグログを出すだけみたいだけど、まずはこれで動かしてみます。
ItemSlotにボタンを付ける
こんな構造になっているけど、親のItemSlotにボタンを付ければ良いっぽい。


ItemSlot.csを書き換える
以下のスクリプトに書き換えます。
using UnityEngine;
using UnityEngine.UI;
public class ItemSlot : MonoBehaviour
{
[SerializeField] private Image icon;
private ItemData currentItem;
public void SetItem(ItemData item)
{
currentItem = item;
if (item == null)
{
icon.enabled = false;
GetComponent<Button>().interactable = false;
return;
}
icon.enabled = true;
icon.sprite = item.icon;
GetComponent<Button>().interactable = true;
}
public void OnClick()
{
if (currentItem == null) return;
Debug.Log($"Selected: {currentItem.itemName}");
}
}
ボタンのクリック時()にItemSlotのOnClick()メソッドを指定する
クリック時()の+ボタンを押して、ItemSlot自身を指定してItemSlot.OnClick()を指定します。


EventSystemを追加する
これがないとクリック検知できません。
追加するだけでOK。


これでクリック検知できた!
これで無事にクリック検知できましたね。
せっかくなので選択されたフレームを目立つようにする
これだけだと微妙だから、選択されたフレームを目立たせるところまでやりたいと思います。
ChatGPTパイセンに聞いたらそこまで難しくないっぽい?


選択中用のフレーム画像を用意する
GIMPで適当に作りました。通常フレームよりちょっと大きく135pxにしてある。


規約とか面倒なことは言わないので勝手に自由に使ってください。
あくまでテスト用なのでこのまま使うのは見栄え的におススメしませんが(^_^;)
FrameSelectedオブジェクト(Image)を追加
これが選択用のフレームになりますが、最初はインスペクターオフで非表示にしておく。
コピペしちゃってますが、位置がちゃんとあっているか確認してください。
コピペした場合、正常に動いていても赤いフレームがスロット1にしか表示されない、なんてことになりがちです(というかなった)。
場所をちゃんと確認しましょう。
ItemSlot.csを書き換える
ItemSlot.csを書き換えます。
ItemSlot.cs
using UnityEngine;
using UnityEngine.UI;
public class ItemSlot : MonoBehaviour
{
[SerializeField] private Image icon;
private ItemData currentItem;
[SerializeField] private GameObject normalFrame;
[SerializeField] private GameObject selectedFrame;
public void SetSelected(bool selected)
{
normalFrame.SetActive(!selected);
selectedFrame.SetActive(selected);
}
public bool HasItem()
{
return currentItem != null;
}
public void SetItem(ItemData item)
{
currentItem = item;
if (item == null)
{
icon.enabled = false;
GetComponent<Button>().interactable = false;
return;
}
icon.enabled = true;
icon.sprite = item.icon;
GetComponent<Button>().interactable = true;
}
public void OnClick()
{
if (currentItem == null) return;
Debug.Log($"Selected: {currentItem.itemName}");
}
}
ItemMenuController.csを書き換える
こっちも書き換えます。
ItemMenuController.cs
using UnityEngine;
public class ItemMenuController : MonoBehaviour
{
[SerializeField] private Inventory inventory;
[SerializeField] private ItemSlot[] slots;
private int selectedIndex = -1;
public void SelectSlot(int index)
{
if (!slots[index].HasItem()) return;
if (selectedIndex >= 0)
slots[selectedIndex].SetSelected(false);
selectedIndex = index;
slots[selectedIndex].SetSelected(true);
}
void OnEnable()
{
Refresh();
}
public void Refresh()
{
for (int i = 0; i < slots.Length; i++)
{
ItemData item = inventory.GetItem(i);
slots[i].SetItem(item);
}
}
}
ボタンのOnClick()にメソッドを追加
選択中のフレームを扱う、ItemMenuController.csのSelectSlotメソッドを追加します。
ItemSlot設定
ItemSlotに通常フレームと選択中フレームを設定する。
あとクリック時()に追加したメソッドの数字のところを書き換える。
スロット数は0から数えるのでスロット1からの場合は0、スロット2の場合は1に。
これで動いた!
これで無事に動きましたね。
つづく?
案外簡単にできて良かった。あとは選択中アイテムで「使う」「捨てる」とか出せたら良いかな?
とりあえずシステムさえ組めればあとは増やしていくだけで済みそうな気がする。
また続きが書けたら追記します(*^_^*)




