ScriptableObjectの使い方をマスター! 羊パラメータの作成

Unity 放置インフレ系クリッカーゲームの作り方 (スマホ化対応)


Unityの本格ゲーム制作講座はこちら
【30日間の全額返金保証付き】

前回は、羊オブジェクトの生成・移動処理を作りました。

前回の記事↓

羊オブジェクトの移動と生成処理 クリックアイテムを動かそう
前回は、売却ボタンの作成と、羊毛(Wool)の売却処理を実装しました。 前回の記事↓ 今回は羊オブジェクトの生成・移動処理をメインで作っていきます。 改めてクリッカーゲームのルール設定について さて、もう5回目となりちょっとずつ...

今回は羊オブジェクトのパラメータを管理するオブジェクトを作っていきます。


【Unity入門の森の最新ゲーム開発講座もお届け】

羊パラメータの作成 ScriptableObjectの使い方をマスターしよう

さて、ちょっとずつ画面がにぎやかになってきましたが、まだ羊が1種類しかいません。

クリッカーゲームはインフレが特徴なので、お金をためて、違う種類の羊を買っていけるようにしていきましょう。
この「違う種類の羊」を表すために、少なくとも色は変えられるようにしたいところです。

その他色々考えると

  • 羊の色
  • 初期値段
  • 1頭追加するごとに上がる値段の額
  • 何頭まで購入できるか
  • 羊が持つ羊毛の量

が、生成する羊の初期設定で必要です。

これらの初期データを設定するために「ScriptableObject」というものを作成したいと思います。

ScriptableObjectの作成

ScriptableObjectというのは、普段よくSceneに配置しているGameObjectPrefabから、位置情報など(Transform)を抜いて、データを保持することに特化したもの。(位置などが無いので、Sceneに直接置けないPrefab?)だと思ってもらうとちょっと理解しやすいです。

Scriptable Objectはインスペクター上で設定できるデータファイルなわけですね。

同じようなデータ構造が色々出てくるものを一括でまとめておけて、コードをいちいちいじらずにデータ編集できるので便利です。例えばRPGだったら敵モンスター、魔法やアイテムのデータなどをScriptable Objectでファイルとして保存できます。

実際に使ってみるのが一番理解しやすいものでもあるので、早速作っていきましょう。

Assets/Scriptsを右クリックして、「Create」→「C# Scirpt」でスクリプトを追加します。

スクリプトファイルは名前変更状態になっていますので、「SheepData」という名前に変更します。

では早速、SheepDataスクリプトを修正していきます。

まず、最初は以下のような状態になっていると思います。

Unityでスクリプトを作ると、勝手にMonoBehaviourを継承した、GameObject用のスクリプトがテンプレートとして作られてしまいますが、今回は ScriptableObject を作りたいので、

SheepData : MonoBehaviourSheepData : ScriptableObject に、

StartメソッドやUpdateメソッドも必要ないので消してしまいます。

そして先ほど挙げた、羊データに必要なものを全てメンバ変数で宣言していきましょう。

  • 羊の色 → Color color;
  • 初期値段 → int basePrice;
  • 1頭追加するごとに上がる値段の額 → int extendPrice;
  • 何頭まで購入できるか → int maxCount;
  • 羊が持つ羊毛の量 → int woolCnt;

(※ コメント(“//”の後ろ)は大変なら書かなくても良いです。 できれば書いた方が良いですが)

そして、ScriptableObjectはこの単体では意味が無く、このスクリプトをベースに「Asset(アセット:Projectに配置出来るファイル)を作る必要があるため、クラスの宣言のひとつ前に1行、メニューからAssetを作れるように属性(Attribute:アトリビュート)を追加します。

さて、ではスクリプトを保存して、UnityEditorで実際にSheepDataAsset(ファイル)を作っていきます。

まず、SheepDataを置くためのフォルダを作りましょう。

Assetsフォルダを右クリック→ Create → Folder  で、「SheepDatas」フォルダを作りましょう。

(ついでに、スクリプトファイルがAssets直下に散らばっているようでしたら、Assets/Scriptsに移動させて、整理整頓しましょう。(私も忘れがちですが))

ここにスクリプトファイルいっぱい置かれていませんか・・・?

作ったAssets/SheepDatas フォルダで右クリックをし、Create→SheepData という追加されたメニュー項目を選択します(この右クリックメニューに追加するために[CreateAssetMenu] という属性(Attribute)を追加しました)

すると、このようにSheepDataAsset(ファイル)が作られます。名前は Sheep1とでもしておきましょう。

Inspectorで各データがセット出来るので、以下のように設定します。

Color 薄い灰色
Base Price 10
Extend Price 5
Max Count 10
Wool Cnt 5

気を付けたいのは、Color(色)は最初、透明度を示すアルファ値が0になっていて、まったく透明な状態になっている事です。しっかりと、アルファ値の値も設定(255で良いです)しましょう。

なお、色も全くの白ではなく、ちょっと灰色にしました。一番安い羊なので、ちょっと薄暗く(汚れた感じ?)にしてみたわけです。

とりあえず、羊の初期データが1つできました。では、次のちょっと高い羊のデータを用意します。

今作ったSheep1を選択して、CTRL+D(複製)します。

すると、Sheep2が作られましたね。

Sheep2はちょっと全体的に高くなります。色は何でもいいですが、パステルカラーの方がキレイなので、白に近い薄い色にしておきましょう。

Color 薄いピンク
Base Price 100
Extend Price 50
Max Count 10
Wool Cnt 40

これで、SheepDataがとりあえず2つ出来ました。最終的にはもっと増やしていきますが、とりあえずは以上でよいです。

では、SheepオブジェクトはこのSheepDataを受け取って、初期設定が出来るように直していきます。

Sheepスクリプト修正

では、Assets/Scripts/ に入っているSheepスクリプトを修正していきましょう。ダブルクリックしてIDEを開きます。
(見当たらない方は Assets/直下にあるかもしれません、小まめに整理整頓で移動していきましょう)

今時点では、Sheepオブジェクトは以下のようになっているはずです。

 

まず、先ほど作ったSheepDataを受け取るための変数sheepData
また、羊毛の量用の変数 woolCntを変数に追加します。

この時、sheepDataはInspectorや外部からセットされて欲しいのでpublicに、woolCntは外から勝手に変更されては困るのでprivateにしておきます。

次に、初期化用メソッド(Initialize)で、渡されている(はずの)sheepDataを元に羊の色(sheepRenderer.color)のセットや、羊毛の量(woolCnt)をセットします。

そして、刈り取りメソッド(Shaving())は以下のように修正します。
(コメントをちょっと過剰に書いているので、不要な方は適宜省略してください)

書いてあるコメントの通りではあるのですが重要なところだけ解説していくと、大体3回クリック(実際には押しっぱなしでも良いのですが)ぐらいでどの羊も全て刈り取れるように、30~40%ずつ刈るようにしています。
(この辺りの数値はレベルデザイン次第でもあるのでいくらでも調整して構いません。まだ先の話ではありますが、お金で羊の購入だけではなく、アイテムで「高級ハサミ」を購入したら、1回で刈り取れる羊毛の割合を増やす。といったゲーム性も持たせられますね。そういう意味ではポイントになりうる箇所です。)

ただ、今持っている羊毛の量よりも多く刈り取ることは出来ないので(それを許容するゲーム性もあるとは思いますが) if(woolCnt < shaveingWool) で、今から刈り取ろうとしている羊毛の量と、保持している羊毛の量を比較して、上限を決めています。

 

この2行は

ちょっと工夫(Mathf.Min:引数で渡された値の小さいほうを返却) すると、1行に圧縮できます。

なぜ一緒の意味になるのか。
ちょっと考えてみると面白いかもしれません。

 

そして、woolCntが0になった場合は、もう刈り取ることは出来ない。 という事を改めてプレイヤーに示す必要があるため、画像をカットされた羊に差し替えるようにし、羊毛はもう無いので色を白(Color.white)に戻しています。

最後に //TODO という形で、「本当はやりたい事」が書いてあります。
本当はここで生成した羊毛(Wool)オブジェクトに今回刈り取った羊毛の量色情報を渡す必要があるのですが、まだWool側にその仕組みが存在しないため、未来の自分へのメモとしてこの//TODOコメントというものを書いています。

最終的にSheepスクリプトは以下のようになります。

では、保存をしてHierarchyのsheepオブジェクトを選択し、InspectorのSheepDataへAssets/SheepDatas の Sheep1かSheep2 をセットしてみて、確認してみましょう。

確認するのは以下の点です。

  • 羊にセットしたSheepDataの色が付いているか
  • 羊毛が無くなった羊からは羊毛が取れなくなっているか
  • 一周した羊はまた毛が復活しているか

問題がなさそうでしたら、またScene上のsheepとprefabにしてあるsheepで差が発生していますので、Overides→Apply All で、変更をprefabの方にも適用しておきましょう。

Sキーを押して羊を生成してみて、エラー等出てないかも確認しておくと良いです。

おさらいと次回予告

今回は羊オブジェクトのパラメータをScriptableObjectで作成しました。

次回は羊の購入処理を作っていきます。

次回の記事↓

羊購入ボタンの作成 クリックアイテムを増やす処理
前回は、羊オブジェクトの初期パラメータをScriptableObjectで作成して、羊の色替えなどを行いました。 前回の記事↓ 今回は羊の購入UIと購入処理を実装していきます。 SheepGenerator修正 まずSheepG...

【Unity入門の森の最新ゲーム開発講座もお届け】

コメント

  1. ベー より:

    最終的なスクリプトの68行目ですが、「 }」が
    コメントに入っていますが、これは66行目の「{ 」と
    ついになっていると思いますがあってますか?

    • ばこ@Unity入門の森 より:

      合ってます!執筆時のミスですね汗
      修正しておきました。
      教えていただきありがとうございます^^

  2. リヨン より:

    ScriptableObjectについてここ最近いろんなサイトで勉強中のものです。

    ScriptableObjectを使うとメモリの節約になる。という文言が多くのサイトに記載されていたのですが、これは値をオブジェクトのプロパティに直接した場合メモリがその分食われるので、値をプロパティに書かずにScriptableObjectから値を取得してプロパティにセットする。という認識であっていますでしょうか?

    xmlやjsonといった外部ファイルからデータの注入だったとしても、ScriptableObjectでデータ注入した場合とメモリ使用上に変わりはないと思うのですが、他サイトを調べていると「ScriptableObject=メモリ節約」といった書き方のサイトが多くて、xmlやjsonといった外部ファイルからデータの注入もScriptableObjectからのデータ注入もメモリ上は変わりはなく、色々と便利なScriptableObjectでやった方いいよーということなのでしょうか?

    • ばこ@Unity入門の森 より:

      ScriptableObjectは用途も色々あってややこしいですよね汗
      自分もUnity内部を作った人ではないので完全に理解できてるかはわからないですが、
      ScriptableObjectについて改めて書籍・公式ドキュメント・他ブログなど含め色々調べてみました。

      結論から言うと、その認識でほぼ合っていると思います。
      メモリ節約の観点では
      ・ScriptableObjectはGameObjectではないためインスタンス化して使う際に余計なコンポーネントが付いてこない。
      ・データとして変更を加えなければ呼び出し先がいくつあっても参照機能により内部では一つのデータを共有する
      ↑変更したものを別途作ることもできるのがややこしいですね。
      また、メモリ節約以外でも処理の観点で
      ・ScriptableObjectはゲームエンジン内部でC++で作られているため、xmlやjsonやエクセルファイルよりも高速読み込みが可能になる。
      このあたりが利点となり利用されるのかなと思います。

      必ず使わないといけないわけではないですが、使えると便利といった位置づけですかね。

      • リヨン より:

        ご丁寧に調査までして頂きありがとうございます><
        利点を改めて列挙して頂くとメリットと利用方法、利用範囲が理解しやすくなりました!

        データ管理はScriptableObjectを利用できる場面があれば上手く利用してみようと思います。

        #数々のブログの記事にはお世話になっています。これからも参考にさせて頂きます!

タイトルとURLをコピーしました