アイテムを拾う

3D シーンの配置できるコインと鍵を拾って、Timmy が持っているアイテムを追跡しましょう。

コイン

シーンにコインを一つ作ろう(後ほどプレハブにして、何個も配置できるようにする)。まず、「Coin」の名前で空のオブジェクトを作成する。拾う処理を確認しやしくするため、Timmyの近くに配置してください。

次、「Coin」の子オブジェクトとして、3Dモデルを追加しましょう。Meshes の中にある「coin-gold」を「Coin」の中に挿入し、位置は 0, 0, 0 にしてください。

最後、3Dモデルとの接触を確認できるため、SphereCollider 型の トリガーを追加してください

image.png

※注目:3Dモデル coin-gold の位置は「親に対して 0, 0, 0」であることを確認してください。3D空間の中で動かすのは、親の Coin である!

アニメーション

コインが浮くアニメーションを作成しましょう。coin-gold を選択し、アニメーションパネルを表示してください。ここで2つの値をアニメーションで更新しましょう:位置と回転

フレーム 0 60 120
位置 0, 1, 0 0, 0.5, 0 0, 1, 0
回転 0, 0, 0 0, 180, 0 0, 360, 0

タグ

何を拾ったのかを確認したいので、SphereCollider が付いている coin-gold には「Coin」というタグを付けてください

プレハブ化

最後、親の「Coin」を新しく作った「Prefabs」フォルダーの中に入れ、プレハブ化にしてください

image.png

インベントリ

つぎ、主人公のインベントリ(アイテム管理クラス)を作成しましょう。このクラスは OnTriggerEnter を活用し、タグを確認する。「Coin」だったら、持っているコインの数を増やす。Debug.Log で確認しましょう:

スクリプト

using UnityEngine;

// アイテムを管理するインベントリ
public class Inventory : MonoBehaviour
{
    // コインの数
    private int coinCount;

    // トリガーが発動した
    private void OnTriggerEnter(Collider other)
    {
        // コインなの?
        if (other.CompareTag("Coin"))
        {
            coinCount++;
            Debug.Log($"コインの数:{coinCount}");
        }
    }
}

このスクリプトをPlayerにアタッチし、実行してみてください。

アイテム削除

一応、これで正しく数えられることが確認できるが、コインが消えないので、何度も拾うことができてしまう。拾った後に、アイテムをシーンから廃止しましょう。ここの注目ポイントは、削除するのはコインの「親」であること(コライダーは子オブジェクトにあるから)

// トリガーが発動した
private void OnTriggerEnter(Collider other)
{
    // コインなの?
    if (other.CompareTag("Coin"))
    {
        // コライダー「の」トランスフォーム「の」親「の」ゲームオブジェクト
        Destroy(other.transform.parent.gameObject);

        coinCount++;        
        Debug.Log($"コインの数:{coinCount}");
    }
}

いくつかのコインを配置し、確認してみてください。

コインと同じ手順を従い、鍵のプレハブを作成してください。ただし:

にしてください。そして、Inventory クラスは:

using UnityEngine;

// アイテムを管理するインベントリ
public class Inventory : MonoBehaviour
{
    // コインの数
    private int coinCount;

    // 鍵の数
    private int keyCount;

    // トリガーが発動した
    private void OnTriggerEnter(Collider other)
    {
        // コインなの?
        if (other.CompareTag("Coin"))
        {
            // コライダー「の」トランスフォーム「の」親「の」ゲームオブジェクト
            Destroy(other.transform.parent.gameObject);
            coinCount++;
            Debug.Log($"コインの数:{coinCount}");
        }
        
        // 鍵なの
        else if (other.CompareTag("Key"))
        {
            Destroy(other.transform.parent.gameObject);
            keyCount++;
            Debug.Log($"鍵の数:{keyCount}");
        }
    }
}

インベントリの改善:統一処理を一体化

この処理で、すぐ眼立つのは、似たような処理2回現れる

この作り方は大きな問題2つがある:

できる限りに、統一している処理を一体にすると、ゲームの整備が楽になる!このため、新しい C# のクラス「Dictionary」を紹介

なんでも指数として使える"配列"「Dictionary」

今まで、2つのコレクションを学んできた:

いずれにしても、それぞれの要素を「指数」でアクセスする形になる。先頭の要素を「0番目」の要素であり、そこから連続に次々の要素をアクセスができる。

// 配列、またはリストは「指数」でアクセス
int [] numbers = new int[5];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
// など…

連続にデータを処理する場合は、配列、またはリストは最適であるが、今回のインベントリのように、連続で整理するよりも、何かの「キーワード」でアクセスしたい。具体的に、それぞれのアイテムの数を、そのアイテムの名前でアクセスしたい。

// これをやりたい…
items["Coin"] = 10; // コイン10個ある
items["Key"] = 0;   // 鍵がない

これがあれば、アイテムごとの変数(coinCount, keyCount)を別々で作成する必要がない。この特別なコレクションに新しい "アイテム"を追加すれば、処理が統一できるようになる。

このコレクションは「ディクショナリー(Dictionary)」といい、リストと同様に、変数を作るのは1つだけで、中には要素を自由に追加ができるが、違いとしては、0から連続にアクセスするではなく、何かの「キー」で要素を探す。

ここで「キー」にできるのは、ほとんどなんでもOK!

書式

ディクショナリーの宣言は、以下のようになる:

Dictionary<キーの型、要素の型> ディクショナリー名;

そして、新しいディクショナリーを作るには:

ディクショナリー名 = new Dictionary<キーの型、要素の型>();

例えば、文字列→整数のディクショナリーは

// 学生の点数
// キー:文字列
// 要素:整数
Dictionary<string, int> studentScore = new Dictionary<string, int>();

// 代入
studentScore["太郎"] = 75;
studentScore["大原"] = 91;

// 読み込む
int score = studentScore["太郎"];
Debug.Log($"太郎さんの点数は{score}");

または、列挙→文字列でもOKですし:

// 武器の列挙
public enum Weapon
{
    Sword,
    Pistol,
    Axe,
    Rock
}

// 各武器の日本語表示 
// キー:武器(列挙)
// 要素:文字列
Dictionary<Weapon, string> weaponName = Dictionary<Weapon, string>();

// 代入
weaponName[Weapon.Sword] = "剣";
weaponName[Weapon.Axe] = "斧";

// 読み込む
int name = weaponName[Weapon.Pistol];

Inventory クラスの改善

では、Dictionary を使用し、処理を一体化しましょう:

using System.Collections.Generic;
using UnityEngine;

// アイテムを管理するインベントリ
public class Inventory : MonoBehaviour
{
    // アイテムの数(タグ → 数)
    private Dictionary<string, int> itemCount;

    private void Start()
    {
        // ディクショナリーを作成
        itemCount = new Dictionary<string, int>();
        
        // 有効なアイテムとその初期の数
        itemCount["Coin"] = 0;
        itemCount["Key"] = 0;
    }

    // トリガーが発動した
    private void OnTriggerEnter(Collider other)
    {
        // 相手のタグを求める
        string itemTag = other.tag;

        // そのタグあるかないかを確認
        // "ContainsKey" は、ディクショナリーの中に
        // 定めた「キー」があると、「true」を返す
        bool isItem = itemCount.ContainsKey(itemTag);

        // 有効なアイテじゃなければ、何もしない
        if (!isItem)
            return; // 終了

        // コライダー「の」トランスフォーム「の」親「の」ゲームオブジェクト
        Destroy(other.transform.parent.gameObject);
        itemCount[itemTag]++;
        Debug.Log($"{itemTag}の数:{itemCount[itemTag]}");
    }
}

Revision #3
Created 2026-05-04 08:13:10 UTC by Menendez Francisco
Updated 2026-06-01 06:22:28 UTC by Menendez Francisco