今回のテーマは、「宝箱を開けてアイテムをドロップさせる方法」です。
RPGやアクションゲームでは欠かせない宝箱を開いたらアイテムが出現するといった実装を紹介します。今回利用するアセットを使うと比較的簡単に実装できるのでぜひチャレンジしてみて下さい。
利用するアセット
Animated Cartoon Treasure Chest
フリーノアセット「Animated Cartoon Treasure Chest」を利用します。Demoシーンも入っていてわかりやすく機能的にも扱いやすいです。
「Animated Cartoon Treasure Chest」にはデフォルトで以下のような機能があります。
- アニメーションで宝箱がジャンプしながら待機する
- コリジョンで判定し宝箱がオープンする
- キーを押したときにオープンする
- インスペクターで渡したGameObjectを引き渡す
Assetをサイトより入手して、Unityのプロジェクトに「Windows>Package Manager」よりDownload及びImportをしておいて下さい。
Standard Asset
キャラの動作用にいつも利用している「Standard Asset」を利用します。
Assetをサイトより入手して、UnityのプロジェクトにWindows>Package ManagerよりDownload及びImportをしておいて下さい。
また、少し古いAssetのためそのまま利用しようとエラーになります。数行変更するだけで治りますので、以前の記事で直し方を紹介しているのでそちらを参考にして下さい。
宝箱からアイテムをドロップさせる。
キャラが宝箱に近づいたら宝箱があいてアイテムをドロップするという流れで作成します。
各アセットの読み込みと配置
床の配置
Hierarchy>+>3D Object>Planeで床を作成します。
宝箱の配置
Package Managerで読み込んだ「FS Loot Boxes」から、「Assets>FS Loot Boxes>Assets>Prefabs」より「TreasureChestPrefab」をドラッグアンドドロップで実体化します。
キャラの配置
Package Managerで読み込んだ「Standard Assets」から、「Assets>Standard Assets>Characters>ThirdPersonCharacter>Prefabs」より「ThirdPersonController」をドラッグアンドドロップで実体化します。
さらにStandard Assetsのカメラを配置します。「Assets>Standard Assets>Camera>Prefabs」より、「FreeLookCameraRig」をHierarchyにドラッグアンドドロップします。
そしてインスペクターの「Free Look Cam(Script)>Target」に先程実体化した「Hierarchy>ThirdPersonController」をドラッグアンドドロップでセットします。
初期からHierarchyにあったカメラは不要なので削除します。
これで以下のような状態になりました。
宝箱の設定
位置の固定
そのままセットしただけの宝箱は物理演算で動いてしまうので、位置を固定します。
「TreasureChestPrefab」のインスペクターを開き、「Rigidbody>Constraints」の項目に対して全てチェックをし位置や回転を固定します。
宝箱の開く際の設定
「TreasureChestPrefab」は「Loot Box>Opening Method」から以下の3つの選択肢から開封メソッドを選択できます。
- Open On Collision…コリジョンの判定をフラグにする
- Open On Key Press…キー入力をフラグにする
- Open On Touch…マウスクリックをフラグにする
今回は、宝箱に近づくことで開封するモーションにしたいので、「Open On Collision」を選択します。
これで動作させてみるとキャラが近づくだけでもう宝箱が開くようになります。
ドロップするアイテムオブジェクトの作成
まず、ドロップするアイテムオブジェクトを作成します。今回は、簡単に3Dオブジェクトのキューブと球をアイテムとして扱います。
まず、「Herarchy>+>3D Object」から「Cube」と「Sphere」を作成します。
そのままだと大きいので、Transformからサイズを0.3程度にしておきます。
物理演算が効くようにRigidBodyをコンポーネントに追加しておきます。
これらは、最初から実体化している必要はないので、Hierarchyから「Cube」と「Sphere」を 「Project>Assets」へドラッグアンドドロップしてプレハブ化します。
プレハブ化した後は、Herarchyの「Cube」と「Sphere」は不要なので、削除します。
※このままでは味気ないので以下では適当にマテリアルをセットしています。マテリアル自体は動作上不要なので割愛します。
アイテムオブジェクトを宝箱にセットする
「TresureChestPrefab」にはデフォルトで「GameObject」をセットできるようになっています。
ここに作成したアイテムをセットしていきます。
「TresureChestPrefab」のインスペクターを開き、「Loot Box>BoxConents」の値を2にします。その後、「BoxContens」の詳細を開いて、Element0~1のLootに先程作成したアイテム(CubeとSphere)をドラッグアンドドロップします。
また、「Drop Chance」を指定することができます。ここでは、どの程度の確率でそのアイテムをドロップするかを指定できます。今回は、必ずでてくるように設定を1にしておきます。
アイテムが出現するようにコードを修正する
「TresureChestPrefab」には、アイテムをドロップするような機能はありません。そのため、コードを少し修正します。
代わりに、Playerに対して設定していたアイテムを引き渡すようなサンプルがDemoに入っていますので、RPGのようにアイテムのみを引き渡したい場合はそちらを確認してみて下さい。
「FS Loot Boxes>Assets>Scripts」の「LootBox.cs」をエディタで開きます。
ソース内の「Open」関数を確認し、以下の様に修正します。
/// <summary>
/// Open the box.
/// </summary>
public void Open ()
{
// avoid opening when it's already open
if (isOpen) return;
isOpen = true;
// play the open animation
if (animator) animator.Play("Open");
// calculates the chance of each loot inside the box
// and pupulates a list with all received treasures
// creates a temp list to store the earned items
List<GameObject> loots = new List<GameObject>();
// check each prize in this box
foreach (Loot loot in boxContents)
{
// roll the dice for a chance to win
float chance = UnityEngine.Random.Range(0.0f, 1.0f);
// if win add the item to the temp list
if (loot.dropChance >= chance)
{
// Debug.Log("You got " + loot.loot.name);
loots.Add(loot.loot);
}
}
// empty the box
boxContents.Clear();
// calls the OnBoxOpen event and deliver the
// earned GameObjects on temp list
//OnBoxOpen?.Invoke(loots.ToArray());
// 設定したアイテムを宝箱の1m上から落とす
foreach (GameObject lootItem in loots)
{
Instantiate<GameObject>(lootItem, transform.position + Vector3.up, Quaternion.identity);
}
}
変更箇所は以下の部分です。
// calls the OnBoxOpen event and deliver the
// earned GameObjects on temp list
//OnBoxOpen?.Invoke(loots.ToArray());
// 設定したアイテムを宝箱の1m上から落とす
foreach (GameObject lootItem in loots)
{
Instantiate<GameObject>(lootItem, transform.position + Vector3.up, Quaternion.identity);
}
アイテムを引き渡すために利用されている「OnBoxOpen?.Invoke(loots.ToArray())」をコメントアウトして、代わりに、「Instantiate」を使って宝箱から取得したアイテムを宝箱の少し上で実体化しています。
これで完成です。実行してみます。
まとめと今後の実装について
今回、「宝箱を開けてアイテムをドロップさせる方法」を紹介しました。
アクションゲームではこういったアイテムがドロップするという表現が多いかなと思いますので実装してみました。あとは、キャラクターがそれらに近づいたら引き寄せられてアイテムを回収したりだとか、アイテムの出現をもう少し自然に表現できたら良いなと思っています。
またそういった方法の記事も書かせて頂きますので楽しみにしていて下さい。
今回の記事が、皆さんの技術力向上につながると嬉しいです。
以上、おつかれさまでした!