前回は、羊から羊毛(wool)オブジェクトが出てくるようになりました。
前回の記事↓
今回はその刈り取った羊毛(Wool)の売却処理を実装していきます。
Walletの作成
まず手持ちのお金を管理・表示するオブジェクト用意しましょう。
お金が入っているのはWallet(財布)なので、Walletオブジェクトを作ります。
Hierarchyの第2回で作成したCanvas/Panel(Header) を選択し、UI→Text を追加します。
追加されたTextは以下のように設定しておきます。
- 名前 Text(Wallet)
- RectTransform
- Anchor Min X:0 Y:0
- Anchor Max X:1 Y:1
- Left 0 Top 0 Right 0 Bottom 0
- Text
- Font : ShigotoMatomegaki-Regular-1-01
- Font Style:Bold
- Font Size:48
- Alignment: 中央寄せ(水平センタリング・垂直センタリング)
- Wallet スクリプトを追加 (Add Component → New Scripts → Wallet)
では、Walletスクリプトをそのまま修正していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using System.Collections; using System.Collections.Generic; using System.Numerics; using UnityEngine; using UnityEngine.UI; public class Wallet : MonoBehaviour { public BigInteger money; [SerializeField] private Text walletText; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { walletText.text = money.ToString("C0"); } } |
まず、using を2行追加しています。
using System.Numerics; は BigInteger (後述)を使用するために、 using UnityEngine.UI; は Text をスクリプトで使用するために宣言しています。
次に所持金を管理するために BigInteger
で money
を宣言しています。
この BigInteger
というのは int(Integer:整数)の桁数が多いバージョンです。 クリッカーゲームをやった事ある方はご存知かと思いますが、どんどんと所持金(クッキーなど)の増加量が増えてきてインフレしていくのが魅力の一つです。
そうなってくると、普通のint
での表現できる数(-2,147,483,648 から 2,147,483,647)を超えてしまう可能性があります。
では、long
にすれば?というと、long
でも表現できる数は-9,223,372,036,854,775,808 から 9,223,372,036,854,775,807 になります。
これでも足りない可能があるので、理論上上限が無い BigInteger
を使う事にします(考えすぎかもしれませんが) 。
そして、
1 2 |
[SerializeField] private Text walletText; |
でInspectorから所持金を表示するためのTextをセット出来るようにしています。
この、walletTextに表示する所持金をセットしているのが Update関数の中にある
1 |
walletText.text = money.ToString("C0"); |
になります。
ここで、BigInteger型の変数 money を ToString メソッドで文字列に変換しているんですが、“C0”という引数が渡されています。 これは、書式指定というものになります。
色々な指定があります(参考:https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-numeric-format-strings)。
よく使うのは D (Decimal:10進数)やN(Number:数値)ですが、今回はC(Currency:通貨)を使っています。 通貨を表すための書式指定なので
- 勝手に \ や $ が付く
- 桁区切りの「,」が入る
といった特徴があります。 Cの後ろの0 は小数点以下の数を指定しています。 0なので、小数点以下は無し。という意味です。
BigInteger
は 本当は System.Numerics.BigInteger
が正式なクラス名ですし、 Text
は UnityEngine.UI.Text
が正式なクラス名です。 この「フルネーム」を毎回書くのが大変なので、先に苗字(
System.Numerics
や UnityEngine.UI
など)だけをusing で宣言しておいて、実際のプログラムでは末端の名前だけで済むようにしている。というわけです。
【学歴不問・高卒、元ニートでも挑戦できる】
売却ボタンの作成
では、次に籠に溜まった羊毛(Wool)を売却できるように、売却ボタンを作りましょう。
先ほどのPanel(Header)にTextを追加したのと同様に、Canvas/Panel(Sell) を選択し、今度はUIボタンを追加します。
追加されたButtonは以下のように設定しておきます。
- 名前 Button(Sell)
- RectTransform
- Anchor Min X:0 Y:0
- Anchor Max X:1 Y:1
- Left 0 Top 0 Right 0 Bottom 0
- Button(Sell)子要素のText
- Text:売却
- Font : ShigotoMatomegaki-Regular-1-01
- Font Style:Bold
- Font Size:48
- Alignment: 中央寄せ(水平センタリング・垂直センタリング)
この時点で、実行画面は以下のようになるはずです。
もちろん、売却ボタンを押してもなにも起きません(何もスクリプトを書いてませんしね)
GameMainオブジェクトの作成
では、この売却ボタン(Button(Sell)) をクリックしたら、実際に籠に溜まった羊毛(Wool)を売却できるようにしていきます。 HierarchyでCTRL+SHIFT+Nを押し、新規オブジェクトを作成します。
- 名前:GameMain
- AddComponent → New script → GameMain でスクリプト追加
このGameMainスクリプトを作っていきます。
メンバ変数
まず、「売却ボタンを押したら」という処理を組みたいので、InspectorでButtonを受け取れるように 変数 sellButton を [SerializeField]で宣言しておきます。
1 2 |
[SerializeField] private Button sellButton; |
次に、売却するということは、財布(Wallet)のお金(money)を増やすという事なので、同じくInspectorでWalletオブジェクトが受け取れるように、変数 wallet を [SerializeField]で宣言しておきます。
1 2 |
[SerializeField] private Wallet wallet; |
売却メソッド
売却用のメソッド SellAllWool() を用意します。
1 2 3 4 5 6 7 8 9 |
private void SellAllWool() { var wools = FindObjectsOfType<Wool>(); //画面上の全てのWoolスクリプトが付いたオブジェクトを検索してWool配列woolsに格納 foreach (var wool in wools) { wallet.money += 100; //TODO 本当は羊毛毎に金額を変えたい Destroy(wool.gameObject); } } |
メソッド内ではまず FindObjectsOfType<Wool>()
で(コメントに書いてある通りではありますが)画面上のWoolスクリプトが付いているオブジェクトを全て探索して、woolsに格納しています。 それを foreach で全て回し、
- walletのmoneyを(とりあえず)100増加
- Destroy で削除
させています。
ボタンクリックイベントの追加
まだこのままでは、ボタンをクリックしてもSellAllWoolは呼ばれません。
おさらいと次回予告
今回は羊毛オブジェクトの売却処理を作りました。
次回は、羊オブジェクトを作り込んでいきます。
次回の記事↓
コメント
はじめまして。こちらの講座を購入し現在学習を進めています。
今まで細々と個人で調べたりして学んでいましたが, 先にタワーディフェンスの方も学ばせて頂き,
独学では思いつきもしなかったやり方など, 色々と学べて大変参考になっています。
ところで一つ質問です。
こちらのクリッカーの講義を一応最後まで進めたのですが,
どうしても売却ボタンを押した後, 再度羊をクリックした際にエラーが出てしまいます。
[羊をクリックする→羊毛を出す→売却ボタンを押す→再度羊を押す(エラー発生, 羊毛未出現,)]
↑の様なことになってしまいます。
一応もう一度講義の最初からやり直して, 再度コードをコピペで確認してみたのですが
[羊毛(Wool)の売却金額設定]の手前のところまで講義を進めて再生・確認してみると同様のエラーがでてしまいました。下記がその内容です。
[エラー内容]
MissingReferenceException: The object of type ‘Wool’ has been destroyed but you are still trying to access it.
一応,コードの打ち間違えやプレハブの紐づけ先, オブジェクト名, ブランケットの位置関係など何度も確認しているのですが, 一向に原因を特定できず困っています。
上記エラー内容を調べてみると, Sheepをクリックした時にWoolがDestroyされてnullになったのをそのまま参照しているのが原因とありますが,
売却を押した際にヒエラルキー上の元々のWoolオブジェクト(Cloneでない)も削除されているので, そこらへんが原因かなどと素人ながらに考える事しかできません。
お忙しいところ恐縮ですが何かアドバイス頂ければ幸いです。
タワーディフェンスゲームに引き続き取り組んでいただきありがとうございます!
質問に関してですが、正しく組めていた場合そのエラーは出ないはずです。
ヒエラルキー上の元々のwoolオブジェクトが売却の際に削除されるのは問題ないです。
削除された後に参照してエラーが出ているようなので、SellAllWool()メソッドのあたりに間違いがないか、Button関係のアタッチなどが間違っていないかなどを再度チェックしてみると良いかと思います。
既に複数人で追試済み&完成までいけた読者さんも多いため、組む際のミスかと思います。
恐縮ですがどうしてもわからない場合、文章のやり取りだと限界があるのでサポートサービスなど利用してもらう形になります
解決できたら幸いです。
返信頂きありがとうございます。
頂いたアドバイスを元に色々と見直してみた結果, 無事解決しました!
Sheepオブジェクトのスクリプトの[Wool Prefab]項目の参照先を, PrefabのWoolにしていなかった(ヒエラルキーの方のWoolにしていた)のが原因でした。
考えてみればめちゃくちゃ初歩的なミスでお恥ずかしい限りなんですが, 悩んでる時は本当にわかりませんでした。。。
コメント大変助かりました本当にありがとうございます。
講義はお陰様で一応最後まで完了しました。こちらの内容は繰り返し学んで自分の制作に生かしたいと思います!