目次
オリジナルのボクセルを使って脱出ゲーム制作に挑戦!
用意するもの
- Unity
- VSCode,VisualStudioなど
- 3Dモデル
この記事ではUnity6を使用しています。
アイテムを取得する機能を実装する
前回はLayer機能を使い、ズームとアニメーションを正しい状態で実行するようにできました。
今回はオブジェクトをクリックしたらアイテムを取得し、画面下のUIに画像を表示させるようにします。
複数のデータを管理するためにデータベース機能を活用します。

脱出ゲームには欠かせないアイテム表示!
クリックしたらオブジェクトが消えるようにする
アイテムをクリックしたらアイテムの情報を取得し、オブジェクトが消えるようにします。
アイテムを作成する
アイテム役のオブジェクトとスクリプトを作成します
オブジェクトの作成
まずは新しくオブジェクトのCubeを作成

PickUpObjスクリプトの作成
PickUpObj.cs
using UnityEngine;
public class PickUpObj : MonoBehaviour
{
public void OnClick()
{
gameObject.SetActive(false);
}
}
クリックしたらオブジェクトが消えるメソッド
スクリプトをオブジェクトに反映させる
CubeにEventTriggerとスクリプトを追加しOnClickを設定

Layerに新しい項目「ItemObj」を追加


今回はテストなのでMainCameraのEventMaskのItemObjにチェックを入れる
本来はズームしてからアイテムを取る流れになると思うので、MainCameraの時にアイテムは取れないほうがいいかも
実行
クリックしたら消えた
Itemクラスの作成
何のアイテムを取得したのかわかるようにItemクラスを作成する
Itemスクリプトの作成
「Item.cs」を作成
Unity6の場合
Create→Scripting→EmptyC#Script
(過去のバージョンの場合はMonoBehaviourの継承を削除)

クラスを作成するのでクラスの継承は無しなんだ
Item.cs
using UnityEngine;
using System;
public class Item
{
public enum Type
{
Cube,
Key,
}
public Type type;
}
CubeとKeyの2種類が用意された
オブジェクトのタイプを設定
PickUpObj.csにどのアイテムなのか判別するための変数を作成する
PickUpObj.cs
using UnityEngine;
public class PickUpObj : MonoBehaviour
{
// 追加
public Item.Type type;
public void OnClick()
{
gameObject.SetActive(false);
}
}
CubeのTypeを選択する

publicにしたことでインスペクターから選択できるようになった
アイテムボックスの作成
取得したアイテムを表示するためのアイテムボックスを作成します
UIを作成する
画面下にアイテムの画像を表示するスペースを用意します
Canvas,Panelの作成
UI→Canvasで新しくCanvasを作成する
さらにPanelを作成

最前面に表示させたいので、Canvasの「SortOrder」を他のCanvasより多い数値(今回は1)にする

アイテムを表示させるスロットの作成
Panelの下にCreateEmptyで「Slot」を作成
Slotの下にUI→imageでimageを作成

Horizontal Layout Group
Slotを複製し、Panelに「Horizontal Layout Group」を追加
Child Alignmentを「Middle Center」
Spacingの数値を変え画像の間隔をあける
下のチェックは全部外す

子オブジェクトのSlotが綺麗に並んだ
ItemBoxスクリプトの作成
ItemBox.cs
using UnityEngine;
public class ItemBox : MonoBehaviour
{
public static ItemBox instance;
private void Awake()
{
instance = this;
}
public void SetItem(Item.Type item)
{
Debug.Log(item);
}
}
ほかのスクリプトからアクセスできるようにシングルトン化させ、SetItemメソッドで何のアイテムを取得したかのログを表示させます
PickUpObj.cs
using UnityEngine;
using static UnityEditor.Progress;
public class PickUpObj : MonoBehaviour
{
//
public Item.Type type;
public void OnClick()
{
// 追加
ItemBox.instance.SetItem(type);
gameObject.SetActive(false);
}
}
クリックしたらSetItemにtypeを渡し実行します
実行
実行しクリックしてみる

ログにCubeと出た
データベースの作成
スクリプタブルオブジェクトの作成
ItemDatabaseEntityというスクリプタブルオブジェクトを作成

ItemDatabaseEntity.cs
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "ItemDatabaseEntity", menuName = "Scriptable Objects/ItemDatabaseEntity")]
public class ItemDatabaseEntity : ScriptableObject
{
public List<Item> items = new List<Item>();
}
アセットからデータベースの作成
アセットメニューからItemDatabaseEntityを選択


内容の設定
データベースを開き内容を設定する


今のところTypeしかないけどパラメーターや画像など複数のデータを設定することができる
HierarchyにItemDatabaseを作成

ItemDatabaseスクリプトを作成
ItemDatabase.cs
using System.Threading;
using UnityEngine;
public class ItemDatabase : MonoBehaviour
{
//PickUpObjからアクセスするためにシングルトン化
public static ItemDatabase instance;
private void Awake()
{
instance = this;
}
[SerializeField] ItemDatabaseEntity ItemDatabaseEntity;
public Item Spawn(Item.Type type)
{
for (int i=0; i < ItemDatabaseEntity.items.Count; i++)
{
Item itemData = ItemDatabaseEntity.items[i];
if (itemData.type == type)
{
return new Item(itemData);
}
}
return null;
}
}
Spawnメソッドは、typeが一致するItemを探し、新しいItemインスタンスを作成して返す
他のスクリプトも変更
PickUpObj.cs
using UnityEngine;
public class PickUpObj : MonoBehaviour
{
public Item.Type type;
public void OnClick()
{
//Spawnを実行するものを追加
Item item = ItemDatabase.instance.Spawn(type);
ItemBox.instance.SetItem(item); //引数を変更
gameObject.SetActive(false);
}
}
ItemBox.cs
using UnityEngine;
public class ItemBox : MonoBehaviour
{
public static ItemBox instance;
private void Awake()
{
instance = this;
}
public void SetItem(Item item) //こちらの引数も変更
{
Debug.Log(item.type); //ログも変更
}
}
Item.cs
using UnityEngine;
using System;
[Serializable]
public class Item
{
public enum Type
{
Cube,
Key,
}
public Type type;
// 渡されたItemの情報をコピーして新しいインスタンスを作成
public Item(Item item)
{
this.type = item.type;
}
}
Itemメソッドにより、元のデータ(ItemDatabaseEntity内のアイテム)を上書きせずに使用できる。
ItemDataBaseにItemDataBase.csをアタッチし、
さらにスクリプトにItemDataBaseEntityを設定

実行

データベースを参照しアイテムのタイプがログに表示された
クリックしたら画像を表示させる
アイテムを取得したら、関連した画像をUIに表示させるようにします。
Slot.csの作成
UIのSlot用にスクリプトを作成します
Slot.cs
using UnityEngine;
using UnityEngine.UI; // UIを取得するために追加
public class Slot : MonoBehaviour
{
[SerializeField] Image image;
public void Set(Item item)
{
image.sprite = item.sprite;
}
}
Item.cs
using UnityEngine;
using System;
[Serializable]
public class Item
{
public enum Type
{
Cube,
Key,
}
public Type type;
// 追加
public Sprite sprite;
public Item(Item item)
{
this.type = item.type;
// 追加
this.sprite = item.sprite;
}
}
ItemBox.cs
using UnityEngine;
public class ItemBox : MonoBehaviour
{
// 追加
[SerializeField] Slot[] slots;
public static ItemBox instance;
private void Awake()
{
instance = this;
}
public void SetItem(Item item)
{
// 追加
slots[0].Set(item);
}
}
Slotにスクリプトを追加
SlotにSlot.csを追加し、imageを設定

Slotをプレファブ化
AssetsにPrefabsフォルダを作りHierarchyからドラッグしプレファブ化
再度Slotを複製

CanvasのItemBoxスクリプトのSlotの項目にSlotをドラッグして設定

アイテムの画像をスクリーンショットなどを使い用意する

画像の設定
Texture TypeをSpriteにし、Sprite ModeをSingleにし、Apply

ItemDatabaseEntityに画像情報を追加する
データベースに画像をドラッグして設定

右上の鍵マークを押すと、インスペクターを固定できて操作し易くなるよ
実行
クリックしたらUIに画像が表示された!
ここまでのメソッドの流れ
クリックされたら「type」を基にデータベースから対応する「Item」を取得し、新しい「Item」インスタンスを作成。
取得した「Item」を「SetItem()」で「Slot」に渡し、スロットの0番目にアイテム画像をセットする。その後、クリックされたオブジェクトを非表示にする。
左から順番に画像をセットするようにする
今のままでは一番左の0番目にしかアイテムがセットされないので正しく修正します。
Cubeと同じように球体のSphereを作成してテスト
Sphereの画像は2番目にセットされるようにしたい
Slotが空っぽかどうか判別する
Slot.csにアイテム情報を保持するようにし、空かどうか判定するメソッドを追加します
Slot.cs
using UnityEngine;
using UnityEngine.UI; // UIを取得するために追加
public class Slot : MonoBehaviour
{
[SerializeField] Image image;
// 保持するアイテム情報(ローカル変数)
Item item = null;
public void Set(Item item)
{
// 渡されたアイテム情報をローカル変数に保存
this.item = item;
image.sprite = item.sprite;
}
// スロットが空かどうか判定
public bool IsEmpty()
{
if (item == null)
{
return true;
}
return false;
}
}
ItemBox.cs
using UnityEngine;
public class ItemBox : MonoBehaviour
{
[SerializeField] Slot[] slots;
public static ItemBox instance;
private void Awake()
{
instance = this;
}
public void SetItem(Item item)
{
// Slotを一つずつ確認し、空ならSetメソッドを実行
for (int i=0; i<slots.Length; i++)
{
Slot slot = slots[i];
if (slot.IsEmpty())
{
slot.Set(item);
break;
}
}
}
}
for文を活用し、スロットを左から順に確認し、空のスロットを見つけたらSetメソッドを実行し、ループを抜ける
実行
ちゃんと2番目にセットされた!
ここまでのメソッドの流れ
クリックされたら「type」を基にデータベースから対応する「Item」を取得し、新しい「Item」インスタンスを作成。
取得した「Item」を「SetItem()」で「Slot」に渡し、スロットの0番目(左端)から順番に確認し、スロットが空だった場合にアイテム画像をセットする。その後、クリックされたオブジェクトを非表示にする。
まとめ
データベースを活用すれば、アイテムやイベントの管理が簡単になり、脱出ゲームのバリエーションを増やすことができそうです。
例えば、アイテムに使用できる回数(耐久度)を設定したり、特定のアイテムを所持していたらエンディングが変わる。アイテムの取得でスコアが変わるなど色々できそうです。
とりあえず今回はここまで