キーツを救いたい【Part2】
この記事は Girak Advent Carender 14日目の記事です
はじめに
今回もUnityやっていくわけですが・・・・・
前回のスクリプト ItemのIDの型が間違っていたので修正しておきました
なんで記事書いてから間違いが見つかるんだよって感じですが
たまたま今週のやることが増えてしまいなかなか作業できず今もこの記事を書いてる暇なんてないんじゃないかってぐらいやることがあります
今日作るもの
今日作るのはこんな感じです!
- UI周り
- アイテムをドラッグアンドドロップできるようにする
- ウィンドウを開き所持アイテムを見ることができる
- アイテムの個数を表示する
今回できるのは時間的にもこれくらいだと思います。クラフトだったりだとかはもう時間的に間に合わないなーって思って諦めました
そのほかのスクリプトは時間があれば後日また書くかもしれません
UIの配置
- ①インベントリのパネル
- ②アイテム用のパネル
- ③インベントリの背景
- ④クラフト用パネル
- ⑤インベントリのアイテムの画像や個数
imageコンポーネントのColorを黒にして一番後ろの背景に使ってます
imageコンポーネントのColorを白にしてインベントリの白い背景に使っています
インベントリのスロットの背景をグループ化しています
スロットを整列するためにGridLayoutGroupを使用して整列しています
パネルのColorを白にして背景に使っています
クラフト用のスロットと+や=などのテキストを入れています
各スロットにパネルの中にアイテムのアイコンが入るRawImageと個数を表示するTextが入っています
Imageじゃない理由はSpriteじゃなくTextureで読み込んでるからです
親オブジェクトにGridLayoutGroupをアタッチして配置するのがおすすめですが
そのままにしておくとアイテムのドラッグアンドドロップのスナップが効かなくなるので
③の位置と重なったら親のGridLayoutGroupを削除し、各パネルのRectTransformの
Anchorsをcenter middleに設定してください
スクリプトを作成後に再生するとこうなります
アイテムの画像や個数はスクリプトで取得するので配置だけ行ってください
インベントリを開くスクリプト/アイテムの表示
アイテムを開く
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { /*アイテム関連フロント*/ [SerializeField] GameObject InventoryCanvas; void Update() { Inventory(); } void Inventory() { if (Input.GetKeyDown(KeyCode.Tab)) { if (InventoryCanvas.activeSelf ==false)//閉じていた場合 { Cursor.visible = true; Cursor.lockState = CursorLockMode.None; InventoryCanvas.SetActive(true); } else//開いていた場合 { Cursor.visible = false; Cursor.lockState = CursorLockMode.Locked; InventoryCanvas.SetActive(false); } } }
とっても簡単ですね
canvasを取得してキー操作でオンオフしてるだけです
アイテムの画像の表示
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class InventoryIcon : MonoBehaviour { [SerializeField] RawImage texture; public Texture2D image; void Start() { texture.texture = image; }
手動でTextureを入れているだけです
この辺に関してはIDで指定しようと思いましたが思いつかなかったので
これでいっかってことになっています
アイテムの個数の表示
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Linq; using UnityEngine.UI; public class Inventory : MonoBehaviour { public List<Item> inventory = new List<Item>(); [SerializeField] ItemData itemdata; public Dictionary<string, int> dic; string itemid; public Text panel0001num; /*panel2*/ public Text panel0002num; /*panel3*/ public Text panel0003num; /*panel4*/ public Text panel0004num; /*panel5*/ public Text panel0005num; /*panel6*/ public Text panel0006num; /*panel7*/ public Text panel0007num; /*panel8*/ public Text panel0008num; /*panel9*/ public Text panel0009num; /*panel10*/ public Text panel00010num; 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 +"を獲得しました"); itemid = itemdata.item[i].ID; CountItem(itemid); } } } void CountItem(string itemid) { dic = new Dictionary<string, int>(); foreach( Item item in inventory) { //Debug.Log(item.Name); if (dic.ContainsKey(item.ID)) { dic[item.ID]++; } else { dic.Add(item.ID, 1); } } foreach(string key in dic.Keys) { Debug.Log(key + " = " + dic[key]); } updateNum(); } void updateNum() { foreach (KeyValuePair<string, int> tmp in dic) { switch (tmp.Key) { case "0001": panel0001num.text = "x" + tmp.Value; break; case "0002": panel0002num.text = "x" + tmp.Value; break; case "0003": panel0003num.text = "x" + tmp.Value; break; case "0004": panel0004num.text = "x" + tmp.Value; break; case "0005": panel0005num.text = "x" + tmp.Value; break; case "0006": panel0006num.text = "x" + tmp.Value; break; case "0007": panel0007num.text = "x" + tmp.Value; break; case "0008": panel0008num.text = "x" + tmp.Value; break; case "0009": panel0009num.text = "x" + tmp.Value; break; case "00010": panel00010num.text = "x" + tmp.Value; break; } } } }
はい、馬鹿ですね
panel○○○○numにはスロットのアイテムの個数を表示するTextを入れています
アイテムが10個固定という前提で書いているのであればこれでも問題ないのですが
さらに多くのアイテムを扱うとなるとめんどくさくなります
対策としてはアイテムの中身に個数の要素を作って個数を追加する関数を作ることでさらに扱いやすいスクリプトができると思われます
今回はこれが原因でクラフトの要素がややこしくなり作るのが困難になりました
アイテムの中身を作るときはちゃんと考えてから作りましょう;;;;;;
アイテムの個数を数える部分に関しては
スクリプト内で宣言したdictionaryをアイテムを数える関数ないでインスタンス化してインベントリ内のアイテムのIDをKeyとして順番に登録していき
IDが重複するとValueの中に数を追加するようにしています
アイテムをドラッグ&ドロップする
アイテムをマウスでドラッグアンドドロップできるようにします。
クラフトのスロットで離すとスナップするようにしてそれ以外の場所で
離すと元の位置に戻るようにしたいと思いますこれがとっても簡単に設定できるコンポーネントがあります
それがこちら
EventTrigger君です!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
このコンポーネントはアタッチされているオブジェクトがクリックされた時やドラッグされた時また他オブジェクトがドロップされた時などいろいろな条件を簡単に実装してくれるガチで便利なコンポーネントです
今回初めて使ってみました
インベントリ画面で必要なのはドラッグ&ドロップだけなので DragとEndDragのみを追加してください
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class InventoryIcon : MonoBehaviour { [SerializeField] RawImage texture; public Texture2D image; [SerializeField] GameObject initParent; Vector2 initPos; int itemquantity; // Start is called before the first frame update void Start() { texture.texture = image; initPos = transform.position; //Debug.Log(initPos); // Iteminfo(); } // Update is called once per frame void Update() { } public void OnDrag() { this.transform.position = Input.mousePosition; } public void OnEndDrag() { List<RaycastResult> results = new List<RaycastResult>(); PointerEventData pointer = new PointerEventData(EventSystem.current); pointer.position = Input.mousePosition; EventSystem.current.RaycastAll(pointer, results); foreach (var hit in results) { Debug.Log("検索中" + hit.gameObject.name); if (hit.gameObject.CompareTag("SnapUI")) { Debug.Log("SnapするUIを検出"); transform.position = hit.gameObject.transform.position; this.gameObject.transform.SetParent(hit.gameObject.transform); break; } else { this.transform.SetParent(initParent.transform); this.transform.position = initPos; } } Debug.Log("検出されませんでした"); } }
ドラッグをする時はマウスの位置にオブジェクトの位置を同期させているだけです
ドラッグを離すとマウスの位置のUIにRayCastAllをしてすべて取得します
クラフトのスロットにはSnapUIというタグがつけられているので
取得したオブジェクトのタグがSnapUIであればそのオブジェクトと親子関係に設定するというスクリプトになっています
もしもなければStart関数で取得した初期位置に戻ります
実行するとこんなかんじです
あとがき
本来は間に合うはずがいろいろな予定で一日遅れてしまった・・・
クラフトは作ってみたもののバグだらけでまともにうごかなかったのでまた今度ということで・・・・
次回はおそらくきゃねぽよサーバーのアドベントカレンダーで投稿すると思います
明日(今日)はメガホンさんです。どんな記事か楽しみにしています!
ここまで見てくれた皆さんありがとうございました。キーツが今年度Unityを触るのか楽しみにしてます