あいりすすすすすすすすすすすすすs

あいりすがなんかするブログ

キーツを救いたい【Part2】

この記事は Girak Advent Carender 14日目の記事です

 



 はじめに



今回もUnityやっていくわけですが・・・・・

前回のスクリプト ItemのIDの型が間違っていたので修正しておきました

なんで記事書いてから間違いが見つかるんだよって感じですが

たまたま今週のやることが増えてしまいなかなか作業できず今もこの記事を書いてる暇なんてないんじゃないかってぐらいやることがあります



 今日作るもの



 

 今日作るのはこんな感じです!

  • UI周り
  • アイテムをドラッグアンドドロップできるようにする
  • ウィンドウを開き所持アイテムを見ることができる
  • アイテムの個数を表示する

今回できるのは時間的にもこれくらいだと思います。クラフトだったりだとかはもう時間的に間に合わないなーって思って諦めました

そのほかのスクリプトは時間があれば後日また書くかもしれません


 UIの配置



f:id:IriSValkyrie:20201215210723p:plain
  • ①インベントリのパネル
  • imageコンポーネントのColorを黒にして一番後ろの背景に使ってます

  • ②アイテム用のパネル
  • imageコンポーネントのColorを白にしてインベントリの白い背景に使っています

  • ③インベントリの背景
  • インベントリのスロットの背景をグループ化しています

    スロットを整列するためにGridLayoutGroupを使用して整列しています

  • ④クラフト用パネル
  • パネルのColorを白にして背景に使っています

    クラフト用のスロットと+や=などのテキストを入れています

  • ⑤インベントリのアイテムの画像や個数
  • 各スロットにパネルの中にアイテムのアイコンが入るRawImageと個数を表示するTextが入っています

    Imageじゃない理由はSpriteじゃなくTextureで読み込んでるからです

    親オブジェクトにGridLayoutGroupをアタッチして配置するのがおすすめですが

    そのままにしておくとアイテムのドラッグアンドドロップのスナップが効かなくなるので

    ③の位置と重なったら親のGridLayoutGroupを削除し、各パネルのRectTransformの

    Anchorsをcenter middleに設定してください

スクリプトを作成後に再生するとこうなります

f:id:IriSValkyrie:20201215215810p:plain

アイテムの画像や個数はスクリプトで取得するので配置だけ行ってください


 インベントリを開くスクリプト/アイテムの表示



 アイテムを開く

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の中に数を追加するようにしています



 アイテムをドラッグ&ドロップする



アイテムをマウスでドラッグアンドドロップできるようにします。

クラフトのスロットで離すとスナップするようにしてそれ以外の場所で

離すと元の位置に戻るようにしたいと思いますこれがとっても簡単に設定できるコンポーネントがあります

それがこちら

f:id:IriSValkyrie:20201215223744p:plain

 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関数で取得した初期位置に戻ります

実行するとこんなかんじです

f:id:IriSValkyrie:20201215230507g:plain

 あとがき


本来は間に合うはずがいろいろな予定で一日遅れてしまった・・・

クラフトは作ってみたもののバグだらけでまともにうごかなかったのでまた今度ということで・・・・

次回はおそらくきゃねぽよサーバーのアドベントカレンダーで投稿すると思います

明日(今日)はメガホンさんです。どんな記事か楽しみにしています!



ここまで見てくれた皆さんありがとうございました。キーツが今年度Unityを触るのか楽しみにしてます