バーチャル3Dクリエイター神部まゆみです(*^_^*)
この記事はUnityでアイテム欄メニュー画面を作ってみた記事の続きです。
前回の記事はこちら。
やりたいこと:捨てたアイテムを落とす
前回アイテムを捨てる処理を実装したので、捨てたアイテムを落とす処理を作りたいですね。
Fallout4だと捨てて落としたアイテムを解体したりできたけど…さすがにそこまでは作らないかな(^_^;)
ChatGPTパイセンに聞いてみる
とりあえず彼に聞けばなんとかなるだろう…。




次は落とす処理を実装したいです。
落とすには3Dモデルを用意する必要があると思いますが、とりあえずはざっくり回復系、武器系などのくくりで共通の3Dモデルを指定すればいいかなと思います。これはアイテムデータのScriptableObjectに項目を増やして3Dモデルを指定できるようにすれば管理しやすいでしょうか?
とりあえず捨てたアイテムを落とすスクリプトをお願いします。


その考え方、めちゃくちゃ良いです。
「共通モデル → 前方に出現 → 重力でコトッ」
TPSとして正解の体験設計だと思います 👍
結論から言うと👇
👉 はい、ItemData(ScriptableObject)に“落とす用Prefab”を持たせるのが最も管理しやすい
そして今の構成と相性も最高です。
全体設計(まずここが大事)
役割はこう分けます👇
| 要素 | 役割 |
|---|---|
ItemData | 落とすPrefabを保持 |
DroppedItem | ワールドに存在するアイテム |
ItemDetailPanel | 捨てる指示を出す |
Inventory | データ削除 |
DropItemSpawner | 実際に前方に生成 |
① ItemData に「落とす用Prefab」を追加
ItemData.cs
using UnityEngine;
[CreateAssetMenu(menuName = "Game/Item")]
public class ItemData : ScriptableObject
{
public string itemName;
public Sprite icon;
[TextArea]
public string description;
[Header("World Drop")]
public GameObject dropPrefab;
}
👉
- 回復系:薬瓶Prefab
- 武器系:武器箱Prefab
など 共通でOK です。
② 落とされたアイテム用スクリプト
DroppedItem.cs
using UnityEngine;
public class DroppedItem : MonoBehaviour
{
public ItemData itemData;
public void Setup(ItemData data)
{
itemData = data;
}
}
③ 前方に落とす処理(Spawner)
DropItemSpawner.cs
using UnityEngine;
public class DropItemSpawner : MonoBehaviour
{
[SerializeField] private Transform player;
[SerializeField] private float forwardDistance = 1.2f;
[SerializeField] private float heightOffset = 0.5f;
public void Drop(ItemData item)
{
if (item == null || item.dropPrefab == null) return;
Vector3 spawnPos =
player.position +
player.forward * forwardDistance +
Vector3.up * heightOffset;
GameObject obj = Instantiate(item.dropPrefab, spawnPos, Quaternion.identity);
var dropped = obj.GetComponent<DroppedItem>();
if (dropped != null)
{
dropped.Setup(item);
}
}
}
④ Prefab 側の必須構成
dropPrefab(共通でOK)
- Mesh / Model
- Collider
- Rigidbody(Use Gravity ON)
- DroppedItem.cs
👉 これで「コトッ」と落ちます。
⑤ ItemDetailPanel に組み込む
ItemDetailPanel.cs(変更部分のみ)
[SerializeField] private DropItemSpawner dropSpawner;
public void OnClickDrop()
{
if (currentItem == null) return;
dropSpawner.Drop(currentItem);
inventory.Remove(currentItem);
menuController.Refresh();
Hide();
}
⑥ Inspector 設定チェック
ItemDetailPanel で👇
- Inventory → プレイヤーの Inventory
- MenuController → ItemMenuController
- DropSpawner → DropItemSpawner(空オブジェクト)
DropItemSpawner 側で👇
- Player → プレイヤー Transform
⑦ これで起きる挙動
- メニューで「捨てる」
- プレイヤー前方・空中に出現
- Rigidbody で落下
- ワールドに残る
「あ、捨てたな」感がちゃんと出ます。
拡張がめちゃくちゃ楽な構成です
このまま👇が自然にできます。
- 拾う(DroppedItem → Inventory)
- レア度で色変更
- 落とせないアイテム
- エフェクト追加
結構簡単にできそう?
まぁやってみます。
実際に実装してみる
彼の言う通りやってみます。
これまで割とサクッと進んだのでたぶんできると思います。
ItemData.csを書き換える
ItemData.cs に3Dオブジェクト用のパラメーターを追加します。
using UnityEngine;
[CreateAssetMenu(menuName = "Game/Item")]
public class ItemData : ScriptableObject
{
public string itemName;
public Sprite icon;
[TextArea]
public string description;
[Header("World Drop")]
public GameObject dropPrefab;
}
これでDrop Prefabという項目が増えたので、ここに指定した3Dモデルのプレハブが落ちます。


Drop Prefabに指定するプレハブの必須項目
3Dオブジェクトならメッシュレンダラーかスキンメッシュレンダラーは自動で追加されてるのでMesh/ModelはOK。
落とすためにコライダーとリジッドボディが必要で、後述のDroppedItem.csスクリプトもアタッチしておく必要がある。


プレハブの作り方
とりあえず3Dモデルをシーンに配置して設定し、
コライダーの大きさを設定して、
適当なフォルダにD&Dして、シーンに配置したオブジェクトは削除すればOK。
プレハブを再度編集したい場合は、プレハブファイルを選択してインスペクターの「開く」を押せばOK。
コライダーの黄緑色ギズモが表示されない場合はこちらを参照。
作ったプレハブをItemDataのScriptableObjectに指定する
作ったプレハブはここに指定します。


シーンにあるプレハブにしたオブジェクトは削除し、プロジェクトフォルダにD&Dしたプレハブを指定しないと不具合が出る可能性があるみたいなので注意。
DroppedItem.cs を追加
以下のコードをコピペしてDroppedItem.csを作ります。
using UnityEngine;
public class DroppedItem : MonoBehaviour
{
public ItemData itemData;
public void Setup(ItemData data)
{
itemData = data;
}
}
DropItemSpawner.cs を追加
プレイヤーの前方に落とす DropItemSpawner.cs を追加します。
using UnityEngine;
public class DropItemSpawner : MonoBehaviour
{
[SerializeField] private Transform player;
[SerializeField] private float forwardDistance = 1.2f;
[SerializeField] private float heightOffset = 0.5f;
public void Drop(ItemData item)
{
if (item == null || item.dropPrefab == null) return;
Vector3 spawnPos =
player.position +
player.forward * forwardDistance +
Vector3.up * heightOffset;
GameObject obj = Instantiate(item.dropPrefab, spawnPos, Quaternion.identity);
var dropped = obj.GetComponent<DroppedItem>();
if (dropped != null)
{
dropped.Setup(item);
}
}
}
ItemDetailPanel.cs を書き換える
以下のスクリプトに書き換えます。
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class ItemDetailPanel : MonoBehaviour
{
[SerializeField] private Image icon;
[SerializeField] private TMP_Text nameText;
[SerializeField] private TMP_Text descriptionText;
[SerializeField] private Inventory inventory;
[SerializeField] private ItemMenuController menuController;
private ItemData currentItem;
[SerializeField] private DropItemSpawner dropSpawner;
public void Show(ItemData item)
{
if (item == null)
{
gameObject.SetActive(false);
return;
}
currentItem = item;
icon.sprite = item.icon;
nameText.text = item.itemName;
descriptionText.text = item.description;
gameObject.SetActive(true);
}
public void Hide()
{
currentItem = null;
gameObject.SetActive(false);
}
// ★捨てるボタン用
public void OnClickDrop()
{
if (currentItem == null) return;
dropSpawner.Drop(currentItem);
inventory.Remove(currentItem);
menuController.Refresh();
Hide();
}
}
空のオブジェクトを追加、ItemDetailSpawnerコンポーネントを追加して設定
指定するのはプレイヤーオブジェクトだけ。
ItemDetailPanelにItemDetailSpawnerを付けたオブジェクトを追加
DropSpawnerって項目が増えているので、DropItemSpawnerコンポーネントを追加したオブジェクトを追加します。


これで無事に落とせた!
これでちゃんと落ちましたね。
案外ここまで実装してあるゲーム少ないから、結構ゲームっぽくなってきたかな?
つづく?
案外手軽に実装できて良かった。
次は拾う処理を作ってみたいかな。
続きが書けたら追記します(*^_^*)





