i-school - 2D放置ゲーム 手順18
 複数回の手順に分けて、お使いの成果として褒賞を獲得できるようにします。

 この手順では褒賞のデータベースを作成し、今後運用できるようにデータの登録を行います。
 

<実装画像>



手順18 −褒賞用のデータベースの作成−
29.褒賞用のデータベースとして利用するスクリプタブル・オブジェクトを作成するための準備を行う −RewardType スクリプトと RewardData スクリプトと RewardDataSO スクリプトを作成するー
30.RewardDataSO スクリプトを利用して RewardDataSO スクリプタブル・オブジェクトを作成し、褒賞のデータを登録する



 新しい学習内容は、以下の通りです。

 ・enum だけのスクリプト・ファイルの作成
 ・スクリプタブル・オブジェクトの作成とデータの登録



29.褒賞用のデータベースとして利用するスクリプタブル・オブジェクトを作成するための準備を行う −RewardType スクリプトと RewardData スクリプトと RewardDataSO スクリプトを作成するー

1.設計


 お使いが完了した際に生成されるキャラのゲームオブジェクトをタップすると、今回のお使いの成果として褒賞を獲得できるシステムを設計して実装します。
今回はデータベースの作成作業を行っていきます。

<褒賞獲得までの手順>
 〇獲得した褒賞の情報を表示してプレイヤーに伝えるための褒賞表示用ポップアップ・ゲームオブジェクトと、そのゲームオブジェクトを制御するスクリプト
 〇キャラをタップした際に、褒賞表示用のポップアップ・ゲームオブジェクトを生成する処理
 ◆褒賞の内容を登録するためのデータベースの作成(今回の手順で作成)
 ・お使いの難易度に応じた褒賞のデータをランダムで抽出する機能
 ・褒賞表示用ポップアップ・ゲームオブジェクトに、ランダムで抽出された褒賞のデータを送り込んで表示させる機能
 ・セーブしてあるお使いのデータと、 OfflineTimeManager スクリプトの List 内から削除する機能



 お使いの情報や褒賞などのデータなどを扱う場合に、複数のデータを1つのまとまりとして管理できるデータベースのようなものがあると扱いが楽になります。

 Unityにはスクリプタブル・オブジェクトという機能(こちらはアセットとしてデータベースを扱う方法)がありますので、今回はこの機能を利用していきます。

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

 今回作成するスクリプタブル・オブジェクトは褒賞のデータを管理する目的で作成を行います。
そのため、スクリプトとしては、褒賞のデータをまとめるための RewardData クラスを用意します

 RewardData クラスは、褒賞1つ分のデータを1つにまとめている情報群です。
褒賞のポイントや抽出する確率といった値を1つのデータ群としてまとめて管理するためのクラスになります。

 この RewardData クラスは、ゲームに登場する褒賞の数だけ用意することになりますので、それを管理するために List 機能を利用します。
こちらはまた別の RewardDataSO スクリプトを作成し、その中で用意を行います。

 この2つの情報を管理して完成するのがスクリプタブル・オブジェクトになります。(1つのスクリプトでまとめて作成する方法もありますが、今回は分けて作成します)
どのような構成になっているかはスクリプト作成後に説明をしていますので、そちらをしっかりと学習してください。

 まずは最初にスクリプタブル・オブジェクトを作成するために必要な褒賞の希少度の種類を登録する RarityType を enum にて作成してから、
スクリプタブル・オブジェクト用のスクリプトを作成します。


2.RarityType スクリプトを作成する


 enum (イーナム) を利用して、褒賞の希少度の種類を事前に登録し、この情報を褒賞の持つ情報として RewardData クラス内に設定できるようにします。
enum のみでスクリプトを作成する場合、using の宣言や、MonoBehaviour(モノビヘイビア) クラスの継承は不要です
そしてどのスクリプトからでも変数の代入なしで利用可能になります。

 enum ではゲーム内に登場させたい種類の情報を、列挙子(れっきょし)という形で種類を作成できます。
今回は、褒賞の希少度の種類、という情報を RarityType という名前で作成し、その中に希少度の種類を登録しておきます。
これは追加可能な情報ですので、先々に希少度の種類が増えても対応できます

RarityType.cs

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


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

 2つ以上の情報を管理する場合には、enum でその種類を登録しておくことをおすすめします
enum を利用する場合、その登録してある列挙子からしか情報を指定できませんので、
例えば、文字列と異なり、指定に際して打ち間違えが発生しませんので、不備の値が入ることも防ぐことが出来ます。

 ゲームの内容に応じた enum を考えて作成して運用します
プレイヤーの状態用(毒、混乱、痺れとか)、アイテムの種類(消耗品、武器、防具、など)、
ゲームの状態管理(ゲーム開始前、ゲーム中、ゲーム終了)など、非常に応用が利く機能です。



 なお enum では各列挙子に自動的に整数の番号が与えられます一番上から 0 で連番になっています
今回の場合であれば、Talk には 0、Search には 1 の数字が与えられています。

 この番号は見えない情報ですが、列挙子を int 型にキャストを行うことで取得して利用出来ます
下記の例の場合、rarityValue には 0 が代入されます。

<enum の列挙子のキャスト>
int  rarityValue = (int)RarityType.Common;

 また、列挙子の宣言時に数字を指定して代入することも可能です。その場合には連番ではなく、指定した数値を取得出来ます。

<数字の代入の例(今回この方式は利用しません)>
RarityType.cs
public enum RarityType {
    Common  = 100,     
    Uncommon = 200,   
    Rare = 0
}

 上記のように代入されている場合には、列挙子を int 型にキャストすると、代入してある値が取得出来ます。
今回は数字の代入は行っていませんので一番上の列挙子には 0 から順番に採番されています。


3.RewardData スクリプトを作成する


 褒賞のデータを登録するための変数群を束ねるクラスを作成します。
このクラスも MonoBehaviour クラスの継承がないクラスですので、ゲームオブジェクトにはアタッチできません。
オブジェクトとしてインスタンスを行って利用していくクラスになります。


RewardData.cs

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


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


4.RewardDataSO スクリプトを作成する


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

 今回指定して管理したいデータはイベントのデータです。
そのため、RewardData 型の List を作成して、管理を行える状態として作成を行います。



EventDataSO.cs

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


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


5.RewardData スクリプトと RewardDataSO スクリプトの構造について


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

 1.褒賞1つ単位でのデータ(褒賞の通し番号、希少度、表示する画像などのデータ群)
 2.褒賞のデータをまとめる List(リスト)


1.褒賞1つ単位でのデータ(褒賞の通し番号、希少度、表示する画像などのデータ群)

 褒賞に関連する情報(変数)をクラスにまとめる利点は、1つの RewardData クラス内には1つ分のイベントの全データが登録できることです。
そのため、通し番号用、画像登録用というように変数をRewardData の 通し番号、RewardData の画像登録用の情報という形で RewardData を参照して利用できる部分です。
例えば、RewardData.rarity と記述すれば、それはその RewardData クラスに登録されている rarity の値を参照することになります。

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

[System.Serializable]
public class RewardData
{
    public int rewardNo;            // 通し番号
    public RarityType rarityType;   // 希少度
    public int rarityRate;          // 度合
    public Sprite spriteReward;     // 画像
    public int rewardPoint;         // 獲得できるポイント 
}

 このように褒賞単位で1つ分に必要になるデータをクラスとしてまとめておくことで管理と利用が容易になります
また、褒賞の情報を増やしたい場合には、この RewardData クラス内に 型と変数を追記すれば、好きなだけ増やすことも出来ます。


2.褒賞のデータをまとめる List(リスト)

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

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



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

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



 今回実装したように、public 修飾子にて List を宣言することで、インスペクター上でサイズの変更が可能です
例えば褒賞のデータを3つ分作って登録したい場合には、インスペクターで List のサイズを 3 に設定すれば
RewardData クラスが 3 つ、Element 0 〜 Element 2 として作成されますので、ここに褒賞のデータを1つずつ、合計3つ分に分けて登録することが出来ます。

<RewardData クラスを扱う List>
 public List<RewardData> rewardDatasList = new List<RewardData>();


30.RewardDataSO スクリプトを利用して RewardDataSO スクリプタブル・オブジェクトを作成し、褒賞のデータを登録する

1.設計


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


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


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

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


3.RewardDataSO スクリプタブル・オブジェクトを作成する


 最初に、スクリプタブル・オブジェクトを管理するためのフォルダを作成しておきます。
Project 内で右クリックをしてメニューを開き、Datas フォルダを作成してください。
この中に作成されたスクリプタブル・オブジェクトを入れて管理します。



 Unity の左上のメニューより、Assets => Create => Create RewardDataSO を選択します。
新しく RewardDataSO というファイルが作成されます。名前はそのままで構いません。

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

 RewardDataSO スクリプタブル・オブジェクトを Datas フォルダへ移動してください。
今後もスクリプタブル・オブジェクトを作成したら、Datas フォルダ内で管理するようにします。


<フォルダ管理>



 早速スクリプタブル・オブジェクトを活用して、イベントのデータを登録していきましょう。


4.RewardDataSO スクリプタブル・オブジェクトの設定を行う


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

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


インスペクター画像



 褒賞用のデータを6つ分登録しておきたいと思います。
rewardDatasList 変数の Size を 6 に変更してください。Element 0 〜 5 が下に作成されます。

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

 以上のことから、1つの Element には1つの RewardData クラスの内容を設定できるようになっています。
このとき、RewardData クラスの上に [Serializable] 属性を宣言しているので、RewardData クラスの内容がインスペクターに表示されています。

 試しにこの属性をコメントアウトしてみてください。RewardData が一切インスペクターに表示されなくなり、編集できない状態になります。



 下記の画像のように設定を行ってみてください。
spriteReward 変数には画像を登録できます。自由な画像を登録してください。
今回はイースターをモチーフにし、卵を褒賞として貰うように設定しています。

 もしも1枚の画像に複数の画像データがまとまっている場合には、
事前に Sprite Editor の機能を利用して分割しておくことで1つの画像単位で利用出来るようになります。


画像データ



インスペクター画像



 各数値や画像は任意ですが、No の値だけは、各イベントの種類ごとに異なる番号で設定してください。できれば 0 から連番が理想です。
この番号はイベント用の個体番号として利用する可能性がありますので、同じ番号を重複して設定してしまうと、同じ番号の個体が複数存在することになり、
通し番号によって褒賞を特定することが出来なくなります。



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

 次は 手順19 ーお使いの難易度に応じた褒賞のデータをランダムで抽出する機能の実装ー です。