Unity 箱庭経営シミュレーション×農場ゲームの作り方 #4 複数アイテムの収納・取り出しを丁寧に解説 | Unity入門の森 ゲームの作り方

Unity 箱庭経営シミュレーション×農場ゲームの作り方 #4 複数アイテムの収納・取り出しを丁寧に解説

Unity 箱庭経営シミュレーション×農場ゲームの作り方

現場レベルのゲーム制作が、すべてここで学べます。

【永久会員チケット】

永久会員チケット|Unity入門の森

全講座を見放題で学ぶ

ソースコード・素材・プロジェクトすべて公開。
Unityの基礎から応用まで、一生使えるスキルを体系的に習得。

この講座ではUnityを使って「箱庭経営シミュレーション&農場ゲーム」を作成していきます。
今回はその第4回目です。

前回はプレイヤーがアイテムを拾ったり落としたりできるシステムを作成しました。

前回の記事:

【Unity】箱庭経営シミュレーションの作り方 #3|アイテムを拾う・落とすシステムをDOTweenで実装する
この講座ではUnityを使って「箱庭経営シミュレーションゲーム」を作成していきます。今回はその第3回目です。前回は、プレイヤーを操作できるようにスクリプトで制御&マップにコライダーを設定して、正しく当たり判定が機能するようにしました。前回の...

第4回では、前回までの実装をさらに応用してアイテムをまとめて持てる機能を実装します。

3D空間の農場で一つ一つ手でニンジンを運ぶのはとても大変です。一気に複数のニンジンをバケツに入れて運べたらとても嬉しい。

ですが、3Dモデルを別の3Dモデルに入れて運ぶのはやろうとしても意外とやり方がわからない・・・

今回はそんな状態から3Dモデルのアイテムを別の3Dモデルに入れて運ぶ方法や、3Dゲームで複数個のアイテムをまとめて扱えるスキルを習得していきましょう。

【ゲームの作り方講座プレゼント中!】

アイテムを複数入れるための箱を作成する

まずは、操作対象となる「箱」のオブジェクトをシーンに配置します。

Projectウィンドウから、次のパスを開いてください。

AssetHuntsl > GameDev Starter Kit – Farming > Assets > Prop > Props_Bucket_01

表示された Props_Bucket_01 を、
Hierarchy ウィンドウへドラッグ&ドロップしてください。

シーン上にバケツの3Dモデルが配置されます。

配置した箱のオブジェクトを選択し、
Inspectorに表示されている Transform を以下のように設定してください。

今回はこのバケツを複数アイテムを持てる箱アイテムにしていきます

複数アイテムを持てるようにするスクリプトを作成しよう。

今回はあくまで前回の応用編です。
前回作成した「ItemBase」と「ItemInteractor」をベースにして、新しいスクリプトを作っていきます。

ItemBaseを使って「BoxItem」スクリプトを作成しよう

まずは、ボックス本体が収納しているアイテムを管理するスクリプトを作成します。

Projectウィンドウで Assets を開き、Scripts フォルダを開きます。
フォルダ内で右クリックして Create > MonoBehaviour Script を選択し、名前を「BoxItem」にしましょう。

作成できたら、そのスクリプトをダブルクリックで開き、以下の内容を書き込んでください。

BoxItem.cs

スクリプトの解説

これは「箱=アイテム」そのものが、中身(他のアイテム)を保持できるコンテナとして振る舞うための ItemBase 派生クラスになっています。

主な機能は3つ

  1. 収納管理(データ)
    • 何が何個入っているかを storedItems で管理
    • 最大収納数 maxItems による制限もここで判定
  2. 見た目(箱に吸い込まれる/出てくる演出)
    • DOTweenで「スロットに吸い込まれる」演出
    • 取り出し時に「元のサイズに戻る」演出
  3. 物理・当たり判定の安全化
    • 収納中は Rigidbody を止めて kinematic化&重力OFF
    • Collider をOFFにして箱の中で暴れないようにする
    • 取り出し時に全部元に戻す
クラス全体の役割

ItemBase は箱そのものがアイテムとして持てる機能を提供する抽象クラスでした。そのItemBaseを継承し、さらに中に別のアイテムを収納/取り出しできるクラスがBoxItemです。

フィールド(変数)ブロックの役割
  • maxItems:アイテムの最大収納数
  • itemSlots:箱の中の“置き場所”(空スロットに入れる)
  • contentRoot:スロットが足りないときにまとめて入れる親

例えば…

  段ボール 紙袋
maxItems 6 6
itemSlots

右下、右真ん中、右上

左下、左真ん中、左上

計6箇所

紙袋上部、右と左

計2箇所

contentRoot 設定しなくてもいい

袋の真ん中(見えない部分)

この時それぞれ6個のにんじんを収納したとき以下のようににんじんが収納されます。

段ボール

  • itemSlots … 6個
  • contentRoot … 0個

紙袋

  • itemSlots … 2個
  • contentRoot … 4個

このようにすることで視覚的表現が必要ない箱などでも対応することができます。
例えば100個収納できるリュックがあったときに視覚的表現は必要ないので

  • itemSlots … 0個
  • contentRoot … 100個

このようになります。これをInspectorで設定したとき、もしitemSlotsしかなかったらスロットを100個用意しないといけません。しかしcontentRootを用意することで設定一つで対応することができます。

今回サンプルゲームで作るバケツの箱の場合はスロット3、maxitems3で設定するので収納可能数と表示アイテム数が一致するパターンですが、数値を調整すると視覚的に見えないところに収納することも可能です。

例えばバケツの箱にレベルシステムを導入し、レベルアップしたら収納数が増える!なんていうシステムも今回の作り方なら対応できます。

  • storedItems:中に入っている ItemBase を順番付きで保持(リスト)
  • originalScales:縮小演出に使うので、元のスケールを保存する辞書
  • storeDuration / takeOutDuration:収納/取り出しの演出時間
  • storeEase / takeOutEase:動き方(イージング)
プロパティ(状態を返すだけの“小関数”)

maxItems が 0 やマイナスでも最低 1 になるように安全化。

今箱に収納されてるアイテムの数。

“中身があるか”の判定。UIで「取り出す」ボタン表示に使える。

“空きがあるか”の判定。UIで「収納」ボタン表示に使える。

“満杯か”の判定。「満杯」表示などに使える。

収納機能の実装:TryStoreItem(ItemBase Item)

役割:引数の Item を箱に収納する(できたら true、無理なら falseを戻り値で返す)

① 収納できるかチェック
  • null防止
  • 二重収納防止
  • 満杯なら収納不可
② 入れる場所(親Transform)を決める
  • まず空いてるスロットを探す
  • なければ contentRoot

  • それもなければ箱自身を親にする(最悪のケース)
③ 元スケールを保存(取り出しで戻すため)

アイテムを収納しているときと取り出されてるときでオブジェクトのサイズが異なるための対応処理です。

箱を使用する際にはこのように入れるアイテムを小さくして収納しています。
例えば、にんじんのサイズはそのままで箱を大きくした場合、箱がでかすぎてしまいゲーム全体で見た時箱のサイズに違和感が生まれます。逆もまた同じでニンジンを小さくしてしまうと、小さすぎて扱いづらく、プレイヤーのストレスになってしまいます。

このような問題を解決するためににんじんと箱のサイズを同じくらいにしておいて、収納するときはにんじんを小さくして収納しています。

④ 物理を止める(箱の中で暴れないように)

こちらで物理を止めておかないと以下のようになってしまいます↓↓↓

↑実行例です。現段階ではまだこのようには動きません。

⑤ ColliderをOFF(箱内部で衝突不要)
⑥ 一旦、箱の子にする(ワールド座標維持)

演出中に親が無い/別親だと位置計算が崩れやすいので、まず箱の子へ。

⑦ DOTweenで収納演出 → 最後にスロットへ確定
  • Move / Rotate / Scale を同時に実行(Join)
  • 完了したら最終的な親を targetParent にして、ローカル位置・回転をきれいに揃える

↓このようにDOTweenでスムーズな演出ができます。

↑実行例です。現段階ではまだこのようには動きません。

⑧ レイヤーを箱に合わせる
  • 箱が Hand レイヤーなら中身も Hand へ
  • そうでなければ箱と同じレイヤーへ

もしこれをしなかったら…

↑実行例です。現段階ではまだこのようには動きません。

このようにバケツのみが”Hand”レイヤー(最前面に表示されるレイヤー)になってしまいます。

⑨ リストに登録して完了
空スロット検索:GetFreeSlotTransform()

役割: itemSlots の中から“空いてるスロット”を探して返す。なければ null

  • childCount == 0 → そのスロットに何も入ってない
  • 最初に見つけた空スロットを返す(先着順)
取り出し:PopLastItem()

役割:最後に収納したアイテムを1つ取り出して返す。空なら null

① 中身チェック → 最後の要素を取り出す
② null保険
③ 元スケール取得(戻す用)

④ 親から外す
⑤ レイヤーを元に戻す

もしこれをしなかったら…

↑実行例です。現段階ではまだこのようには動きません。

このようにアイテムが取り出し後も“Hand”レイヤー(最前面に表示されるレイヤー)になってしまいます。

⑥ 物理を戻す

収納中に止めたものを復帰

⑦ ColliderをONに戻す
⑧ 元サイズへ戻す演出

↑実行例です。現段階ではまだこのようには動きません。

⑨ 取り出したアイテムを返す
ドロップ時:OnDropped(Vector3 forward)

「箱を落とした時」の挙動を ItemBase の処理に任せる

ここまででBoxItemのスクリプト解説は終了です。

ItemInteractorにBoxの処理を追加しよう

次に ItemInteractor にBox 関係の処理を追加して、プレイヤーが箱に干渉できるようにします。
Projectウィンドウから Scripts フォルダを開きItemInteractor を見つけたらダブルクリックして開きましょう。

開けたら、以下のマーカー部分を書き込んでください。

続きを読む
このコンテンツはパスワードで保護されています。 コンテンツを読みたい方はUnity入門の森ショップ(https://unityforest.shop/)で講座閲覧権を取得してね。

まとめ

今回は、前回作成したプレイヤーがアイテムを持てる基本システムを応用し、バケツで農作物のにんじんを複数持てるようにしました。

次の講座では、箱庭シミュレーションとして重要な農作物が畑から生えてくるシステム、畑システムを作成しましょう。

次の記事:

 

【ゲームの作り方講座もプレゼント中!】

現場レベルのゲーム制作が、すべてここで学べます。

【永久会員チケット】

永久会員チケット|Unity入門の森

全講座を見放題で学ぶ

ソースコード・素材・プロジェクトすべて公開。
Unityの基礎から応用まで、一生使えるスキルを体系的に習得。

コメント

タイトルとURLをコピーしました