Unityに関連する記事です

 画像の情報をデータベースとして登録できるように、画像用のスクリプタブル・オブジェクトを作成します。



設計


 画像の情報をデータベースとして管理できるようにしておくことで、情報の編集をまとめて行える環境を作ります。
また画像をデータベースに登録しておくことにより、スクリプトからの参照してもらった際に、必要な情報を提供出来るようにします。


 

画像を元にマテリアルを作成する


 データベースに登録するための画像と、その画像を設定したマテリアルをいくつか作成しておきます。

 画像を使ったマテリアルの作成手順については、AR空間に画像付きのオブジェクトを生成するを参考にしてください。


クラスの考え方 ー複数のデータを関連して管理する方法ー


 例えば、プレイヤーの情報やアイテムの情報などデータを扱う場合に、複数のデータを1つのまとまりとして管理できる方法があると扱いが楽になります。

 以下のように、野球選手やサッカー選手1名分をデータとして扱うことを考えてみてください。

<野球選手の場合>
 ・背番号
 ・得意な守備位置
 ・打率
 ・走力
    など



<サッカー選手の場合>
 ・ポジション・役割(ゴールキーパー、ディフェンダー、ミッドフィルダー、フォワード)
 ・体格
 ・シュート力
 ・ドリブル力
 ・走力
    など

 このように、1つの選手のデータを管理するにあたっては複数の情報が必要ですが、それらはバラバラになっていては関連性が分かりません

 プログラムではこのようなデータを管理するためにクラスが用意されています。
 
 クラスの役割は変数の宣言とメソッドの宣言が行えることですが、変数の部分を、それぞれの選手の情報を扱う値として利用します。

 このような観点で選手用のデータを管理するためのクラスを作成し、その中に関連している複数のデータを変数として宣言して管理することで、
1つのクラスで選手の情報を表現することができます。

 野球選手を例にすると、このようなクラスになります。

public class BaseBallPlayerData {

    public int uniform number;          // 背番号
   public string defensivePositon;     // 得意な守備位置
   public float battingAverage;        // 打率   
   public float runSpeed;              // 走力

}

 このようにクラスを活用することで、1つの情報を構成するために必要な複数のデータを管理することが可能になります。

 この考え方をベースに、今回の場合には、画像関係のデータを管理するためのクラスと、それを束ねてデータベースにする機能を作成していきます。
 

コレクション機能


 先ほど野球選手のデータを BaseBallPlayerData クラスとして表現しました。

 このクラスには選手1名分のデータを管理することができます。ですが、野球やサッカー、それ以外のものの多くは、1つのデータだけでは情報が足りません。
少なくても野球の場合には9名(相手も必要なので18名)分の BaseBallPlayerData が必要になります。
なぜなら、BaseBallPlayerData には1名分のデータしか管理出来ませんので、それを人数分用意しなければならない訳です。



 こうしたとき、同名のクラス群を1つのまとまりとして管理できる入れ物のようなものがあると扱いが楽になります。
9名分の BaseBallPlayerData クラスの変数を9個用意したのでは管理していることにはなりません。

 BaseBallPlayerData クラス9名分を1つの変数でまとめて管理してくれるものとして、C# ではコレクションという機能を利用することで実現できます。

 C# のコレクションには、List、Dectionary という機能が用意されています。(配列はコレクションではないので注意してください。)


<各クラスを1つずつ宣言 → これは1つの変数にまとまっていない>
 BaseBallPlayerData player0;
  BaseBallPlayerData player1;
  BaseBallPlayerData player2;

    :

  BaseBallPlayerData player8;
 
  ↓

<コレクション機能を使い、1つの変数で同クラスの異なるデータを表現する>
 List<BaseBallPlayerData> playerList;  // List



 Unity ではこのうち、ScriptableObject クラスと List の機能を活用して作成できるスクリプタブル・オブジェクトという機能が用意されています。
このスクリプタブル・オブジェクトの機能を利用することで、データベースを作成することができます。

 なお、コレクション機能はあくまでも複数の同クラスの情報をまとめて管理することがメインです。
そのため、コレクション機能を使えばそれがデータベースになる、ということではありません
あくまでも Unity の用意している ScriptableObject クラスと List を活用することでデータベースを作成しています。

 この部分の認識を間違えないようにしてください。


参考サイト
MicroSoft
コレクション


 知らない単語が出てきたときには積極的に、ネットに公開されている公式のマニュアル、わかりやすくまとめた記事などを見つけて調べてみてください。


スクリプタブル・オブジェクト


 スクリプタブル・オブジェクトを作成するためには、専用のスクリプトを作成する必要があります。その作成方法を学習します。

 今回作成するスクリプタブル・オブジェクトは画像関連のデータを管理する目的で作成を行います。
そのため、スクリプト内には、画像関連のデータをまとめるための ImageData クラスを用意します

 ImageData クラスは、画像関連のデータを1つにまとめている情報群です。
画像の通し番号、画像のマテリアルなど、これらを1つのデータ群としてまとめて管理するためのクラスになります。

 この ImageData クラスは、ゲームに登場する画像の数だけ用意することになりますので、それを管理するために List 機能を利用します。

 この2つの情報を管理して完成するのがスクリプタブル・オブジェクトになります。
そのためにクラスとして、ImageDataSO クラスを作成します。

 どのような構成になっているかはスクリプト作成後に説明をしていますので、そちらをしっかりと学習しておいてください。
真似をして作ってみたり、復習を重ねていくことでプログラムは理解が深まり、処理のイメージがわくようになり、書けるようになります。


ImageData スクリプトの作成


 ImageData スクリプトを作成します。

 using の宣言は不要です。
またクラスは継承しませんので、MonoBehaviour クラスは削除してください。

 スクリプタブル・オブジェクトを作成した際、インスペクターから ImageData クラスの情報を設定できるように
[System.Serializable] 属性をクラスの上に付与してください。


ImageData.cs

<= クリックすると開きます。


 スクリプトを作成したらセーブします。


[System.Serializable(シリアライザブル)]属性


 入れ子になっているクラスの1行上には上記の宣言があります。[ ]で宣言された設定値は「属性」と呼ばれる情報になり、特別な意味を持ちます。

 今回利用している[System.Serializable]属性は、Systemに含まれている設定値であり、こちらを宣言することで入れ子クラスの情報をインスペクターに表示することが出来ます。
これを書き忘れてしまうと、インスペクターに ImageData が表示されず、データをインスペクターから登録することが出来ません
using System; を宣言している場合には [Serializable] とだけ記述すれば適用されます。
宣言していない場合には [System.Serializable] と記述する必要があります。


ImageDataSO スクリプトの作成


 スクリプタブル・オブジェクトを作成するために必要な ImageDataSO スクリプトを作成します。
スクリプタブル・オブジェクト専用の ScriptableObject クラスを継承し、[CreateAssetMenu] 属性を記述することで作成可能になります。
 
 スクリプタブル・オブジェクトでは、指定したデータを複数のデータとしてまとめて管理することが出来ます。
そのため、データベースとしての役割を果たすことが可能になっています。

 今回指定して管理したいデータは画像関連のデータです。
そのため、スクリプタブル・オブジェクト内に必要な情報は以下の2つです。

 1.画像関連の情報単位でのデータ(画像データの通し番号、画像のマテリアル、サムネイルに使う画像などのデータ群)を扱うクラス
 2.画像関連のデータをまとめる List(リスト)と ScriptableObject を継承したクラス

 このうち1は先ほど作成した ImageData が当たります。
ここでは2のスクリプトを作成します。



 ImageDataSO スクリプトを作成します。
このスクリプトを利用することで、ImageData を束ねたスクリプタブル・オブジェクトをアセットとして作成することが出来ます。

 [CreateAssetMenu]属性の付与と、ScriptableObject クラスを継承することを忘れないようにしてください。


ImageDataSO.cs

<= クリックすると開きます。


 スクリプトを作成したらセーブします。


ImageDataSO スクリプトの構造について


 処理の内容について、順番に確認していきます。

 1.画像関連の情報単位でのデータ(画像データの通し番号、画像のマテリアル、サムネイルに使う画像などのデータ群)を扱うクラス
 2.画像関連のデータをまとめる List(リスト)と ScriptableObject を継承したクラス


1.画像関連の情報単位でのデータ(画像データの通し番号、画像のマテリアル、サムネイルに使う画像などのデータ群)を扱うクラス

利点は、1つの ImageData クラス内には1つ分の画像関連の全データが登録できることです。
そのため、画像データの通し番号用、画像のマテリアル用というように変数を個別に作る必要はなく、
ImageData の id、ImageData の textureMaterial という形で ImageData を参照して利用できる部分です。

 例えば、ImageData.id と記述すれば、それはその ImageData クラスに登録されている id の値を参照することになります。

 ここからはピリオドによる参照処理が増えていきますので、しっかりと処理を読み解いていきましょう

[System.Serializable]  // ← クラスに System.Serializable 属性を付与する
public class ImageData
{
    public int id;           // 画像データの通し番号
    public Material textureMaterial;  // 3D空間に作成したゲームオブジェクトに使うマテリアルの登録用
    public Sprite spriteImage;     // ボタンのサムネイルに使う画像のスプライトの登録用

    // TODO 他にもあれば追加する

}

 このように画像関連の情報に必要になるデータをクラスとしてまとめておくことで管理と利用が容易になります

 また、管理する情報を増やしたい(画像の登録した日にち、誰の画像かわかるように名前など)場合には、
この ImageData クラス内に 型と変数を追記すれば、好きなだけ増やすことも出来ます。


2.画像関連のデータをまとめる List(リスト)と ScriptableObject を継承したクラス


 ImageData クラスには画像関連の情報をまとめて登録できるようにしました。
このデータは画像関連1つ分ですので、もしも複数のデータを用意して登録したい場合、
この ImageData クラスを複数用意して、それを管理するための変数が必要になります。

 こういった1つの同じデータ群をまとまったものをコレクションといいます。
C# にはコレクションを管理する方法として、Dictinary(ディクショナリー)List(リスト) があります。



 List クラスは <T> にジェネリック型(任意の型)を指定して、同じデータ型をまとめて管理するコレクション機能を持つクラスです。
配列と異なり、要素を自由に追加・削除できます。(要素数が可変する)
List はサイズ(長さ)が可変可能な配列のイメージです。

 List を利用する場合には配列と同様に初期化が可能ですが、Listでは初期化時に要素数の宣言が不要です

<配列の初期化>
  ImageData[] ImageDatas = new ImageData[3];       // <=  要素数の宣言が必要

<List の初期化 
  List<ImageData> ImageDataList = new List<ImageData>();   // <=  要素数の宣言が不要

<List の初期化◆,海舛蕕任盻藉化できます>
  List<ImageData> ImageDataList = new ();   // <=  要素数の宣言が不要

 そのため基本的には、予め要素数の確定しているデータを扱う場合には配列を、要素数が未確定であったり可変長であるデータについてはListを利用するように考えてください。


参考サイト
.net column様
【初期化の方法】C#で配列やリストを初期化するには?



 public 修飾子にて List を宣言することで、インスペクター上でサイズの変更が可能です

 例えばデータを3つ分作って登録したい場合には、インスペクターで List のサイズを 3 に設定すれば
ImageData クラスが 3 つ、Element 0 〜 Element 2 として作成されますので、ここに画像関連のデータを1つずつ、合計3つ分登録することが出来ます。

<ImageData クラスを扱う List>
    public List<ImageData> ImageDataList = new ();


ImageDataSO スクリプタブル・オブジェクトの作成


 ImageDataSO スクリプトを元に ImageDataSO スクリプタブル・オブジェクトを作成します。
ImageDataSO スクリプトに用意してある ImageData 型の List である ImageDataList 変数がデータベースの役割を持っています。

<クラスのリスト化によるデータベース作成>

 ImageData クラスは1つのデータ情報を扱うことが出来ます。今回であれば画像関連の1つ分の情報です。
そのため複数の画像関連の情報を扱う必要がある今回のような場合には、その分だけ ImageData クラスを追加して作成しなければなりません

 それらを管理するために ImageData 型の List を作り、まとめて管理を出来るようにしています。
ここで大切なことは、1つ1つの別の変数に個別に ImageData が存在していたのではまとめて管理していることにはなりません
ImageDataのリストとはすなわち、ImageDataをまとめて扱っているデータの集合体になりますので、ここにデータベースとして役割を成立させることが出来ます



 スクリプタブル・オブジェクト作成前に、Project 内に Datas などのフォルダを作成しておくと管理しやすくなります。

 Datas フォルダ内で右クリックをしてメニューを開き、Create → Create ImageDataSO を選択します。
フォルダ内に ImageDataSO スクリプタブル・オブジェクトのアセットが作成されます。名前はそのままで問題ありません。


メニュー



Datas フォルダ


 このアイコンの形が違うファイルがスクリプタブル・オブジェクトになります。
これはアセットとして取り扱われるようになる情報であることを示しています。


登録


 作成された ImageDataSO スクリプタブル・オブジェクトを選択してインスペクターを確認します。
ImageDataSO スクリプトにて宣言した ImageDataList 変数がインスペクターに表示されて、 Sizeが 0 になっています。
これがスクリプタブル・オブジェクトの中身です。

 Size に任意の数を入力すると、同数の Element が作成されます。これが List で管理する ImageData クラスの情報群になります。

 ImageDataSO スクリプタブル・オブジェクトのアセットを選択し、インスペクターから ImageData にアイテムの情報を登録します。

 まずはデータを3つ分登録しておきたいと思います。
ImageDataList 変数の Size を 3 に変更してください。Element 0 〜 2 が下に作成されます。

 Element とは List の要素(中身)のことです。
そのため、Element 1つが ImageData 1つになります。Element の番号は 0 から始まります。

 以上のことから、1つの Element には1つの ImageData クラスの内容を設定できるようになっています。
このとき、ImageData クラスの上に [Serializable] 属性を宣言しているので、ImageData クラスの内容がインスペクターに表示されています。
[Serializable] 属性を活用することによって、インスペクターから情報を1つずつ、ImageData 単位で登録出来るようになっています。



 まずは id 変数を 0 から連番で設定し、同じ番号を使わないようにしてください。
 各数値や画像は任意ですが、No の値だけは異なる番号で設定してください。できれば 0 から連番が理想です。
この番号はデータ用の個体番号として利用する可能性がありますので、同じ番号を重複して設定してしまうと、
同じ番号の個体が複数存在することになり、番号によってデータを特定することが出来なくなります。

 textureMaterial 変数には、作成したマテリアルをアサインします。
このマテリアルを3Dのゲームオブジェクトのマテリアルに適用して見た目を変えます。

 spriteImage 変数には、マテリアルに登録している画像と同じ Sprite ファイルの画像をアサインしてください。
この画像がボタンのサムネイル画像として利用されます。


インスペクター画像(サンプル。この画像のようにする必要はありません)



 このように、マテリアルとボタンの画像の情報を1つのデータ内がまとめて管理しておくことで情報同士の関連性が出来ます。
それを id 番号で指定して利用するような仕組みになります。


DataBaseManager スクリプトの作成


 作成したスクリプタブル・オブジェクトのアセットは、そのままではスクリプトで参照して利用できません。
スクリプタブル・オブジェクトの型の変数を宣言してアセットをアサイン出来るようにします。

 管理の方法はいくつかあり、今回は今後もスクリプタブル・オブジェクトが増えることを想定し、
複数のスクリプタブル・オブジェクトを管理するための専用のクラスとして DataBaseManager を用意しています。

 スクリプタブル・オブジェクトはデータベースとして利用できますが、必要なデータを見つけることが出来なければ活用していることになりません
そのため、スクリプタブル・オブジェクト内の情報を検索し、必要な情報を抽出するための処理を、メソッド単位でまとめて用意しておく必要があります。

 検索する機能を有した使い方を想定しているため、DataBaseManager クラスはシングルトンクラスとして作成しています。
シングルトンクラスとすることにより、外部のクラスからのアクセスが容易であるため、
利便性の高いクラスに今回のような検索用のメソッドを作成しておくと、非常に使い勝手のよいクラスになります。


DataBaseManager.cs

 <= クリックすると開きます。


 スクリプトを作成したらセーブします。


<List.Find メソッド>


 Listには Find というメソッドが用意されてます。
List 内の要素を先頭から検索して、指定した条件に合致した最初の要素1つを取り出して戻り値として返してくれる処理です。
Find メソッドは foreach 文で記述する内容と同じ処理を1行で処理できます。

Find の場合
    /// <summary>
    /// 指定した番号のマテリアルの取得
    /// </summary>
    /// <param name="dataNo"></param>
    /// <returns></returns>
    public Material GetMaterial(int dataNo) {
        return imageDataSo.imageDataList.Find(x => x.id == dataNo).textureMaterial;
    }

foreach で同じ処理を書いた場合
  foreach (ImageData data in imageDataSo.imageDataList) {
      if (data.id == dataNo) {
          return data.textureMaterial;
      }
  }

 この2つの処理は同じ内容になります。
最初に合致した値が対象になりますので、まとめて複数取得したい場合や、合致する条件を満たす要素が複数ある場合には、この処理だけでは実装できません。


参考サイト
Samurai Blog様
【C#入門】Listの要素を検索するFindの使い方(FindAll/FindIndex)


DataBaseManager ゲームオブジェクトの設定


 新しく宣言した ImageDataSO 変数に、Datas フォルダにある ImageDataSO スクリプタブル・オブジェクトのアセットをドラッグアンドドロップしてアサインします。

 これにより、ゲーム内(スクリプト内)で、ImageDataSO スクリプタブル・オブジェクトの情報を利用出来るようになります。


インスペクター画像




 以上でこの手順は終了です。

 => 次は AR空間にリストから選択した画像のオブジェクトを生成する です。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



プログラムの基礎学習

コード練習

技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

3Dトップビューアクション(白猫風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます