どもです、としです。
UnityLearnの項目ごとに記事も分けた方が分かりやすいかなと思い分けてみました。
と言いつつ、1は1章の導入と2章が一緒になっていますし、
この記事は4章と5章を一緒にしています。
(前回はこちら)
(今回のやる項目)
1.体力システムを作る
このステップだけではなかなか動作は確認できませんが、
キャラクターに体力を作るのがこのステップです。
この辺からコードが増えてきてわからなくなってくる場合が出てくるので、
コメントで変数とコード内容を後の自分が見ても大丈夫なようにしておくと便利です。
今は覚えられても何か月、もしくは何年か空ける可能性があるので、
覚えているやろーではなくちゃんと書いておいた方がいいです。
Unityではpublicで変数を定義するとInspecterで編集できるようにはなりますが、
基本的には他のコードで呼び出せれば変更することができる変数ということです。
publicが付いてない変数はそのコード内でしか直接読み書きできないです。
次のコードは体力を変更するメソッドを作成します。
ただ、今の段階ではどこからも呼び出すことができないので動作は確認できません。
またこのメソッドは引数付きなので、呼び出す際にはカッコの中に数字を入力しないと
エラーになります。
Mathf.Clampは1つ目引数の計算式を行った際に2つ目(最小)と3つ目(最大)の値を超えないようにする関数です。
この場合0からmaxHealthの範囲内でcurrentHealthにメソッドの引数を足す命令になっています。
(足すって言ってもマイナスを足せば引けます。)
最後にキャラクターのスピードもInspectorでいじれるようにpublic変数を作ってこのステップが終わります。
2.回復アイテムを作ろう
体力があるゲームは回復がやっぱり必要なので、構築がてらトリガーによる当たり判定を学ぼうというのがこのステップです。
始めに説明通りに画像の設定を行い、Scene上に配置します。
この時画像が大きいのでサイズ調整をしてからBoxCollider2Dを設定します。
ここでBoxCollider2DのオプションでInTriggerにチェックを入れるように書いてありますが、
チェックを入れてから起動すると以前とは違いトリガーとして機能しているのでキャラクターは通過します。
ただ、トリガーに対して何も命令がないので、次のステップでコードを作成しています。
新しいコードを作成後に作った回復アイテムのオブジェクトにアタッチして、
OnTriggerEnter2Dメソッドの中身を書きます。
このメソッドはオブジェクトが持っているColliderに何か別のオブジェクトが入ることによって、
メソッド内の命令を実行するものになっています。
デバッグログのステップが終わったら、次に本格的にコードを書いていきます。
まず、初めのコードは当たったオブジェクトのPlayerControllerを取得するためのコードになります。
これによりこのコードでPlayerControllerの中身にアクセスできるようになります。
次のif文でcontrollerの中身がnull(何も入っていない)かどうかをチェックしてから、
PlayerControllerのChangeHealthを呼び出します。
しかし、今の状態だとアクセスできないということでエラーになります。
そのためにPlayerControllerのChangeHealthメソッドにpublicを付けて、
他コードからでもアクセスできるようにします。
次のDestroy関数でこのコードがあるゲームオブジェクト自身を削除します。
すべてのコードが書けたらステップに従ってテストを行います。
テストが終えられたら、作ったオブジェクトはPrefab化しておきます。
3.体力がMaxなら取れなくする
前のステップのコードだと体力がMaxでも取れてしまうので、
Maxの時には取れないように仕様を変えるのがこのステップです。
始めにアイテムを取った時のコードの方でアイテムを取った後に、
今の体力が最大体力より低い時というif文を追加しています。
(controllerはnullじゃないよー->controllerの体力は最大値より下だよーの2条件)
このまま進めてもいいのですがif文が2つで長いコードになってしまっているので、
&&で2条件を両方満たした時に実行するように変更してコードの短縮化も行います。
このコードを入力するとcurrentHealthがアクセスできないというエラーが出るので、
前みたいにpublic変数にすればすぐに解決できます。
しかし、場合によっては内部変数を外に出したくないということもあるので、
このステップでは別の方法でこの問題を解決しています。
PlayerControllerの方で新しくhealth変数を作成していますが、
見慣れない方法で作成されています。
詳しくはリファレンスなどを参考してもらった方がいいのですが、
簡単に言えばこの変数は常にcurrentHealthの値が入っているという感じです。
(うまく使えば常に計算した値を入れられるかも。)
これのコード追加にともない先ほどのif文も変更することで、エラーが発生しなくなります。
4.ダメージ判定
増やす方があれば減らす方も作らないといけません。
このステップではダメージ床を作るみたいです。
始めに前のステップでチェック用に変更したコードを元に戻します。
ダメージ判定のコードはチュートリアル的には以前の復習として、
課題としてコードはまず答えを見ずに自分で書くようなっています。
アイテムを取る時の当たり判定を理解できていればすぐです。
ただ、このままでは入ったときにコード内容が実行されますが、
チュートリアル的にはダメージゾーンに入っている間はダメージを食らうようにしたいということです。
なのでここではOnTriggerEnter2DをOnTriggerStay2Dに変更します。
ただ、このままではすぐに体力が無くなってしまうので次のダメージまでの無敵時間を追加するみたいです。
まず、PlayerCharacterのRigidBody2DのSleepingModeをNeverSleepに変えます。
説明がチュートリアルに書いていますが、
初めの設定ではオブジェクトが止まっているとRigidBodyが停止してしまって演算がされなくなるから
静止状態でも動かすようにしようということみたいです。
次にダメージを受けた時の無敵時間を追加するコードを書きます。
Bool型の変数isInvincibleがオン(True)になったら無敵時間の値をクールダウン時間に代入して、
毎フレーム、クールダウン時間からTime.deltaTimeを引いて0以下になった時に
isInvincibleをオフ(False)に変えるという感じです。
ステップのコードに従ってコードを追加すれば大丈夫です。
確認できれば次に行きます。
5.体力を表示するUIを作る
ここから章が変わります。
今までコンソールで体力などの数字を見ていましたが、
こういう数字は遊んでいる人に見せないといけないものなので、
このステップは体力バーを作るみたいです。
以前のRuby'sAdventureチュートリアルやUnity2020までぐらいの書籍では、
Hierarchyで右クリックしてUIからテキストや画像など目的のものを探して編集していました。
このチュートリアルではUIToolKitを使用してUIを作成していくみたいです。
前のUIをuGUIといい、UI自身もゲームオブジェクトとして扱っていくスタイルということらしいです。
今回やるUIToolKitはHTMLやCSSなどと似たアプローチで作れる新UIシステムということらしいのですが、
とりあえずステップを進めてどんな感じか見ないとわからないです。
チュートリアル通りにアスペクト比を合わせたい場合は設定を先に変えておくと
同じようにできます。
UIToolKitは基本的にはGUIベースで設定していくみたいで、
基本的にSceneと切り離して作業ができる感じです。
ステップ通りに一通り作成できたら、Scene上に配置してみます。
メイン画面の方のHierarchy(UIToolKitの方にもあるので)で、
UIToolKit->UIDocumentを選択してからSourceAssetに先ほど作ったUIDocumentファイルを割り当てると
Game画面の方で作ったUIが出てきます。
あとはステップ通りに進めていきます。
PanelSettingはメイン画面の方のUIDocumentを選択して、
InspectorのPanelSettingのところをダブルクリックして開けます。
次は顔グラフィックを先ほど設定したバーの上に置きます。
一応ステップ通りにやっても数字が変わってしまうかもしれませんが、
慣れていくしかなさそうです。
今のところは形になるように調整できれば次に進んでもいいかもしれません。
6.UIToolKitのUIをコードで動かす
旧UIシステム(uGUI)の時はUnityEngine.UIを追加していましたが、
UIToolKitではUnityEngine.UIElementsを追加するみたいです。
uGUIの時はオブジェクト単位でGetComponentして変数を作成して変更していた覚えがありますけど、
UIToolKitの場合は全体のUIDocumentをGetComponentで代入してから、
要素単位でそれぞれ変数を作っている感じみたいです。
コロンの数で区切る数は増えていますが、UI全体がUIDocumentに格納されていると思った方がよさそうです。
始めのコードができた時点でチェックをしてみますが、
ステップの参考画面ではHealthバーは満タンになっていますけど、
実際は半分の大きさになっていればここまでできています。
次はチャレンジとしてコードの変更をしますが、
難しければ答えのコードを読みながら理解した方がやりやすいです。
(英語を訳すのがめんどくさいというのは言い訳にしたい。)
このチャレンジでコードを変更したことによって、
バーの大きさの変更が他からも呼び出せるようになりました。
次のステップでは作ったコードを静的メンバーにしようという話ですが、
動作の度にメモリに呼ばれて終わったらメモリから出ていくのではなく
ずっとメモリに滞在していつ呼ばれてもいいようにするということらしいです。
Awake関数はUnityが起動したときにStart関数よりも先に実行する関数で、
処理によってはこの関数で行わないとエラーが出てしまうこともあります。
ここで追加したコードで作ったUIHandlerを常駐させることで、
わざわざGetComponentで呼び込むことなくUIHandlerのpublicに設定しているものにアクセスできるようになったという感じです。
コード的にはUiHandlerにある自分自身が格納されたinstanceの中身を変更するという感じです。
動作チェックをしてバーがダメージによって変われば、このステップは完了です。
まとめ
Healthシステム自体は前のRuby'sAdventureの時とあまり変わらなかったのですが、
UIシステムがUIToolKitに変わったのでその辺が以前とは違う点でした。
UIToolKitの方が感覚的に使えそうな気がするので、
こっちをマスターした方が今後いいかもしれません。
Ruby'sAdventureの時はバーの画像に対してマスクをかけることもやりましたが、
この新しいチュートリアルでは今のところやっていないので、
その辺を見つけておくようにしておけばあとあといいかもしれません。
次は敵キャラとアニメーション周りですが、ある程度は復習になるかもしれません。
やってみないとなんとも言えないですけど。
ということで今日はこれにて!
では!