Unity

【脱出ゲーム制作7】アイテムを使用するシステム

オリジナルのボクセルを使って脱出ゲーム制作に挑戦!

アイテムを選択し、使用する機能を実装する

前回はオブジェクトをクリックしたら画面下のUIにアイテムの画像を表示させる機能を実装しました。

今回は画面下のアイテムをクリックし、使用できるようにします。

アイテムを選択できるようにする

まずは画面下のUIの画像をクリックしたらアイテムを選択している状態にします

選択中とわかるようなUIにする

どのアイテムを選択しているかわかるようなUIにします

画像に背景を追加する

Slotオブジェクトのプレファブを開き、UI→image名前を「Back」にする

上からBack、imageの順に配置し、WidthとHeightをimageより大きくする
Backの色をItemBoxPanelと違う色にし、わかりやすくする

ItemBoxPanelを灰色にし、Backを黒にしました

スクリプトの修正

クリックしたら背景のBackを表示するようにします

Slot.cs
using UnityEngine;
using UnityEngine.UI;

public class Slot : MonoBehaviour
{
    [SerializeField] Image image;

    //  背景(Back)を取得
    [SerializeField] GameObject backPanel;

    Item item = null;

    // 開始時にHideBackPanelを実行し背景を非表示にする
    private void Start()
    {
        HideBackPanel();
    }

    public void Set(Item item)
    {
        this.item = item;
        image.sprite = item.sprite;
    }

    public bool IsEmpty()
    {
        if (item == null)
        {
            return true;
        }
        return false;
    }

    // 選択したら背景を表示する
    public void OnSelect()
    {
        // なにもなかったら選択しない
        if (item == null)
        {
            return;
        }
        // 背景(Back)を表示する
        backPanel.SetActive(true);
    }

    // 背景(Back)を非表示にする関数
    public void HideBackPanel()
    {
        backPanel.SetActive(false);
    }
}

Backをシリアライズフィールドで取得
ゲーム開始時にBackを非表示にするためのStart関数と、選択した時に実行するOnSelect、Backを非表示にするHideBackPanel関数を追加

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)
    {
        for (int i=0; i<slots.Length; i++)
        {
            Slot slot = slots[i];
            if (slot.IsEmpty())
            {
                slot.Set(item);
                break;
            }
        }
    }

    // スロットをクリックした時
    public void OnSlotClick(int position)
    {
        // 一度すべて非表示にする
        for (int i = 0; i < slots.Length; i++)
        {
            // slots[i]の背景をなくす
            slots[i].HideBackPanel();
        }
        // クリックしたスロットの背景を表示する
        slots[position].OnSelect();
    }
}

スロットをクリックした時に実行するOnSlotClick関数を追加

imageにEventTriggerを追加し、PinterClickを選択
ItemBoxCanvasをセットし、ItemBox.csの「OnslotClick」を選択

引数の欄は一番左のスロットが「0」、2番目が「1」3番目が「2」・・・と入力する

実行

いい感じ!

選択したアイテムを使用する

アイテムが選択できるようになったので、次はアイテムを使用する機能を実装します

クリックしたらドアが開くアニメーション

現在、ドアをクリックしたら条件なしで開くようになっています

アニメーションの作り方はこちら

DoorSet(親オブジェクト)にドアにズームするためのコライダーやEventTrigger、スクリプトがセットされている
Layerは「CameraZoomObj」

DoorSetの下のGameobjectにコライダーとEventTriggerとDoor.csのスクリプト

その下にドアの3Dモデルを配置します

Door.cs
using UnityEngine;

public class Door : MonoBehaviour
{
    [SerializeField] Animator animator;

    public void OnClickObj()
    {
        Open();
    }

    void Open()
    {
            animator.Play("OpenDoor");
    }

クリックしたらドアが開くアニメーションを再生するためのスクリプト

なぜこのような階層構造なのか

ドアの3Dモデルに直接コライダーやスクリプトを付けてもいいのですが、ドアが開いたときにコライダーも一緒に動いてしまいます。

例えば、ドアを開けた後もう1度クリックしドアを閉める時、3Dモデルにコライダーが付いている場合コライダーがほかのオブジェクトに埋もれてクリックしにくくなってしまいます。

なので3Dモデルの上に親オブジェクト作成し、そちらにコライダーやスクリプトを設定しドアが開いても動かないようにします。

アイテムを使用し、ドアを開ける

鍵を選択しているときにドアが開くようにする

スクリプトの修正

各スクリプトを修正します

Slot.cs
using UnityEngine;
using UnityEngine.UI;

public class Slot : MonoBehaviour
{
    [SerializeField] Image image;
    [SerializeField] GameObject backPanel;

    Item item = null;

    private void Start()
    {
        backPanel.SetActive(false);
    }

    public void Set(Item item)
    {
        this.item = item;
        image.sprite = item.sprite;
    }

    // スロットの中身と背景を消す
    public void RemoveItem()
    {
        item = null;
        image.sprite = null;
        HideBackPanel();
    }

    // itemの中身を返す
    public Item GetItem()
    {
        return item;
    }

    public bool IsEmpty()
    {
        if (item == null)
        {
            return true;
        }
        return false;
    }

    public void OnSelect()
    {
        if (item == null)
        {
            return;
        }
        backPanel.SetActive(true);
    }

    public void HideBackPanel()
    {
        backPanel.SetActive(false);
    }
}

itemの中身を返すGetItemメソッドと、アイテムを使用したらUIからアイテムを消すRemoveItemメソッドを追加

ItemBox.cs
using UnityEngine;

public class ItemBox : MonoBehaviour
{
    [SerializeField] Slot[] slots;

    public static ItemBox instance;

    // 選択したスロットを保持する変数
    Slot selectSlot;

    private void Awake()
    {
        instance = this;
    }

    public void SetItem(Item item)
    {
        for (int i=0; i<slots.Length; i++)
        {
            Slot slot = slots[i];
            if (slot.IsEmpty())
            {
                slot.Set(item);
                break;
            }
        }
    }

    public void OnSlotClick(int position)
    {
        for (int i=0; i<slots.Length; i++)
        {
            slots[i].HideBackPanel();
        }
        slots[position].OnSelect();

        // 選択スロットを変数へ入れる
        selectSlot = slots[position];
    }

    // 送られてきたアイテムタイプを選択しているかどうか判定する関数
    public bool CheckSelectItem(Item.Type useItemType)
    {
        if (selectSlot == null)
        {
            return false;
        }
        // 同じものか判定する
        if (selectSlot.GetItem().type == useItemType)
        {
            return true;
        }
        return false;
    }

    // 使ったアイテムを消す
    public void UseSelectItem()
    {
        selectSlot.RemoveItem();
        selectSlot = null;
    }
}

CheckSelectItemメソッドで選択しているアイテムと同じものか判定する
今回の場合useItemTypeは「Key」

UseSelectItemは使ったアイテムを消すメソッド

Door.cs
using UnityEngine;

public class Door : MonoBehaviour
{
    [SerializeField] Animator animator;

    public void OnClickObj()
    {
        Open();
    }

    void Open()
    {
        // Keyアイテムを選択したら
        if (ItemBox.instance.CheckSelectItem(Item.Type.Key))
        {
            // 使用したアイテムを消す
            ItemBox.instance.UseSelectItem();
            
            animator.Play("OpenDoor");
        }
    }
}

ドアをクリックしたらOpenメソッドからCheckSelectItemメソッドを実行
選択しているアイテムのタイプが「Key」ならUseSelectItemで鍵を使用し、ドアを開ける

実行

鍵を使って開けることができた!

まとめ

今回の実装では、アイテムの選択機能を追加し、それを使ってイベントを発生させる仕組みを作成しました。アイテムをスロットに格納し、クリックすることで選択状態を管理し、特定のアイテムを使用することでイベントが発生するようになっています。

この仕組みを活用すれば、特定のアイテムを持っている場合のみ進めるギミックアイテムの組み合わせによる新しい要素の追加など、ゲームの幅を広げることができます。

今後は、アイテムの使用条件を増やすUIの演出を強化することで、より直感的で面白いシステムに発展させることができそうです。

とりあえず今回はここまで

参考にさせていただきました。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です