キーツを救いたい【Part1】
この記事は Girak Advent Carender 6日目の記事です
キーツ........Unityやらないか?
はじめに
さて、一年ぶりのアドベントカレンダー今回は今年から僕が始めたUnityについて
自分の勉強も兼ねて書いていこうかなと思います。
元々キーツが麻雀しててなかなかゲーム制作に手を付けないことに乗っかってこの記事を書こうと思いました、初心者が書くプログラムですのであんまり綺麗にかけてないかもしれないですが許してください。
(ちなみに名前の使用許可は取りました)
開発環境
- Unity2019.3.14f1
どんなものを作るか
キーツが言うにはこういう機能のあるゲームが作りたいらしいです
- 3人称視点のゲーム
- ワールドにアイテムがポップアップしてプレイヤーがそれを回収できる
- ウィンドウを開き所持アイテムを見ることができる
- アイテムをクラフトできる
- アイテムをクラフトすることで機械をつくることができる
- 機械をワールド上に設置できる
- 機械は何かしらのエネルギーを消費してアイテムの生成効率を上げる機能がある
マイクラじゃねえか!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
今回作る機能について
さすがに今回だけですべてを作ることは僕のスケジュール的にも不可能なので
APEXのランクとか回せてないから回したいとか言えない
今回は
- アイテム管理
- インベントリ周り
- アイテムのポップアップ
- アイテムの回収
らへんをやっていこうかなって思います
アイテムの生成
まずは動かすキャラクターと地面を用意しましょう
今回はUnityちゃんを使って動かします
実際に動かすスクリプトなどは省きますが一応参考になりそうなサイト貼っておきます
今回登録するオブジェクトを追加します
今回追加するオブジェクトの種類は上のようになっています
実際にワールド上に生成させるのは1,2,3番のアイテムです
これをプレハブ化します
プレハブ化する前にアイテムに付いているColliderコンポーネントのisTriggerにチェックを必ずつけてください
これを付け忘れると僕のスクリプトではアイテムを回収できなくなります
hierarchyからProjectのResourcesにドラッグ&ドロップで入れてください(ない場合は作成してください)
入れたらhierarchyの中にあるアイテムオブジェクトはすべて消してください
次にアイテムを生成するスクリプトを書いていきます
アイテムを生成する場所はx軸とz軸が50から-50です、y軸は0.5に固定してます
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemGenerator : MonoBehaviour { [SerializeField] ItemData ItemDataBase; //アイテムの一覧 [SerializeField] GameObject[] FieldItem = new GameObject[20]; //フィールド内のアイテムが入る変数 float x; //ワールドのx軸の変数 float y = 0.5f;// y軸 float z;//z軸 float counttime;//アイテム再生成のクールタイム // Start is called before the first frame update void Start() { GenarateObject(); counttime = 10f; } // Update is called once per frame void Update() { counttime -= Time.deltaTime;//クールタイムから1フレームにかかった時間を常に引く if(counttime <= 0.0f)//クールタイムが0になったら再生成を実行 { counttime = 10; GenarateObject(); } } void GenarateObject()//アイテムを生成する関数 { int itemnum;//アイテムの配列の番号 for (int i = 0; i < FieldItem.Length; i++) { if (FieldItem[i] == null)//フィールドのアイテムが消されてnullになっている場所にアイテムを生成する { itemnum = Random.Range(0, 3);//どのアイテムを生成するかランダムで決める x = Random.Range(-50,50);//指定した範囲内でのx軸をランダムに決める z = Random.Range(-50, 50);//z軸を決める FieldItem[i] = Instantiate(ItemDataBase.item[itemnum].Object,new Vector3(x,y,z),Quaternion.identity);//Instantiateで指定したアイテム番号のアイテムを生成する Debug.Log(ItemDataBase.item[itemnum].Name); } } } }
再生ボタンを押すとこんな感じに動作します
アイテム3が出ていないのですが導入する前の動画だったので生成されていませんが
ちゃんと動作しています
またアイテムを大量に導入する場合アイテムをランダムで選出するところをDirectoryのKeyなどで選出して
アイテムの生成はエリア分割を行いそのエリアで決められたアイテムが出現するようにするといいかもしれません
アイテム要素
まずはアイテムの要素を作っていきます
今回アイテムの要素は
- 名前
- オブジェクト
- ID
- アイテムの種類
- アイテムの説明文
- アイテムのアイコン
で構成していこうと思います
他に入れたいものがあれば任意でここに書き加えてください
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Item { /*アイテムの中身を設定する場所*/ public string Name;//アイテム名 public GameObject Object;//実際のオブジェクト public string ID;//アイテムのid public ItemType type;//アイテムの種類 public string Description;//アイテムの説明文 public Texture2D icon; //アイテムのアイコン public enum ItemType //enumでアイテムの種類を切り替えて入れれるようにしています { item, machine, } public Item(string name, GameObject itemobject, string id, ItemType itemtype, string desc)//Itemをインスタンス化し外から呼び出して使う { Name = name; Object = itemobject; ID = id; type = itemtype; Description = desc; icon = Resources.Load<Texture2D>("item" + id); //Resourcesフォルダから ファイル名 <item0000> (0000はアイテムid)を取得して代入する } }
今更ですが構造体にしてもよかったかもしれないです。(どっちでもいいと思っている)
今回の規模のゲームであればどっちでもいいとは思います
iconですがResourcesフォルダ内に名前を "item○○○○" という名前で入れておいてください(〇にはそのアイテムのIDが入ります)
public enum ItemType { item, machine, }
この部分ですがenumを使用しているのでItemType.itemと入力するとアイテムの種類がitemになります
enum今まで使ったことなかったんで勉強になりました
アイテム一覧データ
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemData : MonoBehaviour { /*実際にアイテムを保管する場所*/ public List<Item> item = new List<Item>(); // Start is called before the first frame update void Start() { item.Add(new Item("item1",Resources.Load<GameObject>("item1object"),0001,Item.ItemType.item,"このアイテムはitem2とクラフトするとitem3になります")); item.Add(new Item("item2", Resources.Load<GameObject>("item2object"), 0002, Item.ItemType.item, "このアイテムはitem1とクラフトするとitem4になります")); item.Add(new Item("item3", Resources.Load<GameObject>("item3object"), 0003, Item.ItemType.item, "このアイテムはitem4とクラフトするとmachine1になります")); item.Add(new Item("item4", Resources.Load<GameObject>("item4object"), 0004, Item.ItemType.item, "このアイテムはitem3とクラフトするとmachine1になります")); item.Add(new Item("machine1", Resources.Load<GameObject>("machine1object"), 0005, Item.ItemType.machine, "このアイテムはitem3とitem4を入手すると獲得できる機械です地面に設置できます")); }
オブジェクトはResources.LoadでResourcesフォルダ内にあるオブジェクトを持ってくることができます
もしアイテムを持っていきたいスクリプトがある場合はItemDataをインスタンス化して持ってきてください
最後に空のオブジェクトにItemManagerと名付け
ItemData.csをアタッチすれば完了です
アイテム回収
アイテムを回収するスクリプトはプレイヤーを動かすスクリプトの中に入れておきます
ここではアイテム回収に必要のない部分のコードは省きます
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { /*アイテム関連*/ [SerializeField] Inventory inventory;//インベントリのスクリプト [SerializeField] ItemData itemdata;//アイテム一覧のスクリプト private void OnTriggerEnter(Collider other)//何かに当たるたび動作する { Debug.Log("衝突"); for(int i = 0; i < itemdata.item.Count; i++)//アイテム一覧のアイテムの数だけ繰り返す { if(other.name.Contains(itemdata.item[i].Object.name))//衝突したオブジェクトの名前にアイテム一覧の配列のi番目のオブジェクトの名前が含まれていたら動作する { Debug.Log(i+"番目と一致"); inventory.AddItem(itemdata.item[i].Name);//インベントリにインスタンス化した配列の中に追加する Destroy(other.gameObject);//落ちてるアイテムを消す } } } }
まず今回はOnTriggerEnterで衝突を判定します
衝突したオブジェクトとアイテム一覧のアイテムの名前を比較して追加するのですが
なぜContainsで判定しているかというと
衝突した後拾ったオブジェクトはプレハブを生成したものとなり、Inspector上の表記が○○○(Clone)となってしまって名前をうまく取得できないため
名前が含まれているかで判定しています
インベントリ
最後はインベントリです
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Inventory : MonoBehaviour { public List<Item> inventory = new List<Item>(); [SerializeField] ItemData itemdata; public void AddItem(string itemname) { for(int i = 0; i < itemdata.item.Count; i++) { if(itemname == itemdata.item[i].Name) { inventory.Add(itemdata.item[i]); Debug.Log(inventory[inventory.Count - 1].Name +"を獲得しました"); } } } }
プレイヤーがアイテムを回収するとInventoryのAddItem関数を実行します
あとがき
僕の担当2日あるので今回はこの辺で終わります
Unityやらない人にとってはマジでどうでもいい内容だったけど普通に俺が勉強なったからよかったです
まだまだ技術不足なこともありますが頑張っていこうと思います
次(12/7)の記事はきゃねぽよ/kyaneeku⭐️⭐️くんが書いてくれます
どんな怪文書か楽しみにしてます
最後に
キーツここまでやったからにはUnityやれよ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!