Unity シリアライズ化されたインスタンスを配列として扱う
シリアライズ化されたインスタンス配列をインスペクターから確認、登録する方法について説明します。
まず、次のリンクにあるインスタンスのシリアライズについて、学習しておいて下さい。
基本となるクラス
次のクラスを前提にインスタンスの配列を作成してみましょう。
class Product
{
// 商品名
public string Name;
// 賞味期限
public string Expiry;
// 大きさの種類
public string[] Sizes;
}
クラスのシリアライズ化
インスペクターで登録できるようにシリアライズ化します。
// 商品のインスタンスをインスペクターに表示させます。
[SerializeField]
Product product;
// 商品クラスをシリアライズ
[Serializable]
class Product
{
// 商品名
public string Name;
// 賞味期限
public string Expiry;
// 大きさの種類
public string[] Sizes;
}
作成したクラスを配列として扱う
基本となるクラスを変更して、配列で管理するようにします。
上記では、
Product product;
と、宣言しているところをProduct型の配列に変更します。
名前は、sをつけ、productsとしています。
Product[] products;
配列をシリアライズ化したコード
変更したクラスが次のようになります。
宣言を配列型にしています!
using System;
using UnityEngine;
public class SirializeClass : MonoBehaviour
{
// 商品のインスタンスをインスペクターに表示させます。productsは、Product型の配列になります。
[SerializeField]
Product[] products;
// 商品クラスをシリアライズ
[Serializable]
class Product
{
// 商品名
public string Name;
// 賞味期限
public string Expiry;
// 大きさの種類
public string[] Sizes;
}
}
インスペクターから、初期値を代入する
ここまでコードを入力したら、このスクリプトを空のゲームオブジェクトにアタッチしましょう。
スクリプトのアタッチ
データの初期値代入
では、この配列のインスタンスに値を代入していきます。
代入は、コードではなくインスペクターから入力する方法を試していきます。
もちろん、コードで代入していく方法でもできます。
2つ目のインスタンスの追加
同じように牛肉を追加しましょう
- Name 牛肉
- Expiry2100/01/10
- Size 100g, 300g, 500g
確認するコード
for文を使って確認
それでは、インスタンスの情報を取り出すコードを書いてみましょう。
まず、シンプルに記述してみましょう。
コード抜粋
void Start()
{
// 全てのインスタンスを表示
for (int i = 0; i < products.Length; i++)
{
Debug.Log($"{products[i].Name} {products[i].Expiry}");
}
}
size(サイズ)の表示がありませんね。sizeは、クラスのメンバーです。型の宣言はstring型の配列です。
なので、確認するには、ネスト(入れ子)されたfor文を使うとうまくいきそうです。
ネストの内側は、sizeの取得になります
コード抜粋(ネスト部分)
// インスタンスごとのサイズを全て表示
for (int j = 0; j < products[i].Sizes.Length; j++)
{
Debug.Log($"{products[商品の要素番号].Sizes[j]}");
}
コード抜粋(ネストのコードをまとめると・・・)
void Start()
{
// 全てのインスタンスを表示
for (int i = 0; i < products.Length; i++)
{
Debug.Log($"{products[i].Name} {products[i].Expiry}");
// インスタンスごとのサイズを全て表示
for (int j = 0; j < products[i].Sizes.Length; j++)
{
Debug.Log($"{products[i].Sizes[j]}");
}
}
}
動作するスクリプト
今回のサンプルでは、Productクラスは、インナークラスを使ってSirializeClassクラスに内包するようにしています。
実際のコードでは、分離しても構いません。
全コード
using System;
using UnityEngine;
public class SirializeClass : MonoBehaviour
{
[SerializeField]
// 商品のインスタンス(配列)をインスペクターに表示させます。productは、Product型のフィールドになります。
Product[] products;
[Serializable]
// 商品クラスをシリアライズ
class Product
{
// 商品名
public string Name;
// 賞味期限
public string Expiry;
// 大きさの種類
public string[] Sizes;
}
void Start()
{
// 全てのインスタンスを表示
for (int i = 0; i < products.Length; i++)
{
Debug.Log($"{products[i].Name} {products[i].Expiry}");
// インスタンスごとのサイズを全て表示
for (int j = 0; j < products[i].Sizes.Length; j++)
{
Debug.Log($"{products[i].Sizes[j]}");
}
}
}
}
実行結果
(参考)foreachで確認する場合
using System;
using UnityEngine;
public class SirializeClass : MonoBehaviour
{
[SerializeField]
// 商品のインスタンス(配列)をインスペクターに表示させます。productは、Product型のフィールドになります。
Product[] products;
[Serializable]
// 商品クラスをシリアライズ
class Product
{
// 商品名
public string Name;
// 賞味期限
public string Expiry;
// 大きさの種類
public string[] Sizes;
}
void Start()
{
// 全てのインスタンスを表示
foreach (Product product in products)
{
Debug.Log($"{product.Name} {product.Expiry}");
// インスタンスごとのサイズを全て表示
foreach (string size in product.Sizes)
{
Debug.Log($”{size}");
}
}
}
}
(応用)インスタンスの特定の情報を取得
C# LINQを使って、データの中から情報を抽出することもできます。
// products配列で、最初に見つかった商品名が牛肉のインスタンスの賞味期限を取得
// 見つからなければ、デフォルト値(stringの場合null)を返します
var expiry = products.FirstOrDefault(product => product.Name == "牛肉").Expiry;
ディスカッション
コメント一覧
まだ、コメントがありません