としるみSoftの制作ブログ

主に作っている作品の紹介や今やっている活動の紹介を書いています。おすすめポイントですらなくなっちゃった。

(UnityLearn)Adventure Gameを作ってみた4

どもです、としです。

1月も終わったのでそろそろこのチュートリアルも終えられるようになんとか頑張りました。

2章分まとめてやったので、なかなかの長文記事になっています。

 

(前回はこちら)

toshirumisoft.hatenablog.com

 

 

1.敵キャラクターを作る

learn.unity.com

ここからこの内容に入っていきます。

まずは敵キャラクターを作る段階です。

ほとんどプレイヤーキャラクターを作るのと同じ感じで始められますが、

動きをプログラミングしないといけない部分に気をつければすぐだと思います。

キャラクターの設定は説明通りにやればいけますが、

プレイヤーキャラクターでやった所もあるのでその辺は少し省略されています。

重力は下にかからないためのGravityScaleを0と

変に回転しないようにするためのFreezeRotationZのチェックを忘れないようにすれば大体大丈夫です。

コードを書いてまっすぐ横に進めば、ここまでは説明通りにできています。

垂直に移動させるコードも書きますが、ほとんど判定用のBool変数とif文を書けばすぐにできます。

次のステップでは行ったり来たりと巡回するようにコードを書いていきます。

コードとしてはタイマーを設定して規定時間が来たらdirectionを反転させることで、

移動させる方向を逆転させるということです。

(プラスにマイナスをかけるとマイナス、マイナスにマイナスをかけるとプラスという基本です。)

このあと衝突をしたら体力を減らす設定をするのですが、

なんかうまくいかない場合があるかもしれないです。

最初にトリガーをオンにしていたのがややこしいことになっていて、

OnCollisionEnter2Dでは反応しないです。

トリガーを無効にしたら反応しますが、敵キャラクターを押せてしまうので仕様としては変です。

OnTriggerEnter2Dで書けば反応しますが説明文と違うようになってしまうので、

次の説明を見ながら直していく感じで進めます。

(とりあえず両方あってもいいけど、いらない方をコメントアウトして読み込まないようにした方がいい。)

 

2.アニメーションコントローラを作る

敵キャラクターのアニメーションを作ることでアニメーションを学んでいくステップです。

ディレクトリは指定の場所を開けば大丈夫ですでにファイルがいくつかありますが、

ステップ通りにアニメーションコントローラを新規作成すれば問題なしです。

EnemyにAnimatorを追加して先ほど作ったコントローラをアタッチします。

場所はここ

コントローラにアニメーションクリップを作成して追加するのですが、

AmimationClipというディレクトリがありませんし、

そもそもコントローラを作ったディレクトリにすでに完成したクリップがありますけど、

あーだこーだやるのはめんどくさいのでここはすでにあるアニメーションを上書きして進めます。

アニメーションクリップに指定された画像を挿入した時にキャラクターが小さくなりますが、

とりあえずは無視して次に進んだ方がいいです。

ステップに従って右方向が出来たら次に進みます。

なお、アセットに最初からアニメーションクリップがあった理由がここで説明されていて、

このあと必要に応じてそのまま使うことになっています。

作ったコントローラをAnimatorを開いて、初めにBlendTreeを作成します。

右クリックで出てくるよ

その後作ったBlandTreeをダブルクリックすれば、説明されている画面に行けます。

始めからあるアニメーションクリップは削除するように指示されているので、

削除しておきましょう。

この状態で終えよう



ここで設定を行えばこのステップは終了で、残りの作業は次のステップでやっていきます。

 

3.アニメーションを制御する

あまり説明はされていない感じですが、すでに上下のアニメーションもできている状態で話が進んでいます。

まだ上下のアニメーションが設定できていない場合は、

アセットにあるアニメーションクリップをAnimetorでドラッグドロップで持っていけば大丈夫です。

必要なアニメーションクリップがアニメーションコントローラに入ったら、

ステップ通りに2つのパラメータを作ります。

パラメータを作ったらBlendTreeをダブルクリックして詳細画面を出し、

Inspectorのパラメータに作ったパラメータを設定します。

その時に値が0ではなくNaNとなっていれば、0を必ず入れておきます。

(ほったらかしだとエラーになると思う)

こうなっていればいい

次はMotionFieldを作成して、説明通りに値とアニメーションクリップを割り当てていきます。

説明の画像は間違っているので、文章通りにパラメータは入力してください。

あと、次のコードで実際のゲーム画面でちゃんと反映させるので、

この段階では説明の動画みたいにならなくても大丈夫です。

Inspector上でパラメータを動かして変更されているかが確認出来たら、

次のコード入力のステップに行きます。

ここで追加するコードで先ほど設定したパラメータを変更させて、

アニメーションと動作を合わせるようにします。

アニメーターの変数を作ってGetComponentをするのは毎回お馴染みですが、

その後のパラメーターの入力で説明ではUpdateに入れると書いていますが、

あとあとのコードチェックを見直すとFixUpdateに入っています。

ここはFixUpdateの方に追加するようにコードを書きます。

BlendTreeで設定したパラメータは””で囲って書くので、

設定した名前を間違えなければ難しい所は少ないです。

コードが書けたら、ゲーム画面でもアニメーションが変わるかチェックして次に行きます。

敵キャラクターが設定できたので、次はプレイヤーキャラのアニメーションを設定します。

このステップではアニメーションコントローラはすでにあるアセットのコントローラを使用します。

その後説明通りにアニメーターの設定を行っていきます。

チェック時にアニメーションの推移の説明がされていますが、

これはアニメーションのどのタイミングで次のアニメーションに切り替えるかの設定になっていて、

うまく使うことでアニメーションの移行がスムーズにできるみたいです。

パラメータのLook X、Look Yにスペースがあるのを確認したりできたら次に進みます。

PlayerControllerにアニメーター用の変数が書けたら、Updateに条件文を書きます。

指定されている条件文にはMathf.ApproximatelyというAとBの数字が近似値であればTrueを返す関数を使っています。

ここでは初めに!を付けることで「~ではない」と逆の条件に設定してあり、

||でもう1条件を付けてどちらかがTrueであればif文の中に行くようになっています。

中身ではアニメーション用のVector2変数にmoveの値を代入したあと、

正規化して値を1にするようにしています。

その後Look XとLook YにmoveDirectionの値を入れ、

Speedにmoveのベクトルの長さを入れています。

あとはダメージを受けた時のコードにもう1つコードを挿入します。

ここではFloat型の値を変更ではなくTriggerを立てるだけなので、

間違えないようにすれば大丈夫です。

動作チェックして問題なければ次に進みます。

 

4.攻撃動作を増やす

ここではボタン操作によってキャラクターから敵キャラクターを攻撃するアイテムを

射出する動作を追加します。

まずは指定されている画像を見つけて、画像設定を指定されている数値に変えてゲームオブジェクトとして追加します。

その後BoxColliderとRigidbody、コードを追加して、指定通りの設定を行った後Prefab化します。

PrefabにできたらHierarchyから削除します。

このステップではキャラクターの位置でSceneに無いオブジェクトを

Prefabのデータを使って作成する流れになります。

コードを書く作業ではGetComponentがAwakeメソッドで行っています。

これはゲームが始まった時にはこの攻撃用のオブジェクトはSceneに存在しないので、

Startではうまく読み込めないからみたいです。

(Updateメソッドを消そうと説明にはありますが、後のコードを見るとたぶんこれはStartメソッドを消そうの誤りだと思います。Updateは使います。)

現段階ではコードが書けてもSceneに無いので、次はPlayerControllerを編集して作ったゲームオブジェクトを出せるようにします。

新しくPublicなGameObject変数を作成しましたが、これは後で作ったPrefabを格納するための変数です。

これはInspector上で操作するので、値の代入は今はしません。

その後は新しく作ったメソッドでPrefabを生成して、

生成したオブジェクトから作ったコードを変数に代入し、

代入した変数から指定のメソッドを呼び出している感じです。

まだこの段階では攻撃はできないので、次のステップはキーの設定を行っています。

まずは説明通りに新しくキー用の変数を作成してから保存し、

キーアサインを設定します。

歯車マークでこの画面は出ます

InputActionの場合はStartメソッドで有効化しないと実行できないので、

まずはそれを行うようにします。

コードを書けたら大体発射できるようになるのですが、

ここら辺でまたまたあまりよろしくない動きが発生すると思います。

本当はここでは発射したらプレイヤーに当たって消えちゃったから、

レイヤー設定をしなきゃという流れですが、

当たるどころか判定も行われないのでどんどんオブジェクトが増えてしまいます。

なんか最後の確認コードも説明していることと違う流れになっているので、

ここはまたまたProjectileコードの方でOnTrigggerEnterに変えるべきなのかもしれません。

変えたら直りました。

次はレイヤー設定です。

何をするかというとレイヤーを作ることで異なるレイヤーで当たり判定を制御できるので、

それを設定してプレイヤーに弾が当たらないようにしようということです。

レイヤー名はコピペで貼り付けて問題ないです。

それぞれ設定できたらProjectSettingを開いて説明通りにPhysics2Dを設定します。

旧バージョンでは少し違うかも

これでプレイヤーと当たることは無くなりました。

確認ができれば次に進みます。

 

5.攻撃を敵キャラクターに当たるようにする

敵キャラクターに前のステップで作ったオブジェクトを当てる判定をこのステップではやるみたいです。

EnemyControllerの方でBool型の変数を作成してそれをPublic型のFixメソッドを使って操作する感じですが、

Fixメソッドは弾の方のProjectileで衝突判定が行われた時に実行するようにするという流れです。

EnemyControllerのFixUpdateでBool型変数がfalseの時にreturnで返すことで中身を実行しないことになっています。

ここでもよくわからないようなミスが見受けられていて、

Projectileの当たり判定の部分でEnemyControllerを代入する時に

other.collider.Getcomponent<EnemyController>()で説明では記載されています。

このまま入力するとエラーが発生してしまいます。

説明文のコードでは当たったオブジェクトのotherのcolliderの中にあるEnemycontrollerを取れというないものを取ろうとしている命令になっています。

なので、修正としてother.gameObject.Getcomponent<EnemyController>()と記載して進めることにしました。

次は当たり判定とぶつからなかったProjectileが一度作成されるとゲームが終わるまで

Sceneに残ってしまっている問題を解決するステップです。

今の状態だとメモリを圧迫してゲーム自体を破綻させてしまうので、

不要になったオブジェクトを自動で廃棄する命令を説明通りに追加します。

発射されたオブジェクトのベクトルの距離が100を超えたら自動で削除するようになっています。

次は挑戦してみようと書かれていますが、アニメーション処理はサンプルの時に行われていたのでやっておきます。

説明があるので説明通りに直った時のアニメーションクリップをAnimetorにドラッグドロップして有効にし、

Fixedトリガー作成とトランザクションをBlendTreeから伸ばしてから矢印をダブルクリックして設定を出し、

Conditionsに作ったトリガーをセットしてHasExitTimeのチェックを外す感じです。

こういう感じにする

設定が出来たらコードでアニメーション用のトリガーを立てるようにすれば完成です。

 

6.NPCを作成する

このステップではRaycastを使った当たり判定を使い、NPCの会話を実装するみたいです。

Raycastは判定用の光線を伸ばして、当たったオブジェクトに対して動作を行うみたいです。

(リファレンスや詳しい別Webページを参考にしていただいた方がもっとわかりやすいです。)

画像の設定を説明通りに済ませた後、配置やColliderの設定、アニメーションなどを設定します。

アニメーションは分割した画像をすべて選択して、そのままSceneに追加すると自動でクリップが作られます。

設定ができてPrefab化したらコードを書くステップに行きます。

まずは会話するボタンの設定で、前の弾を発射するアクションと同じようにキーを設定します。

設定したあとはRaycastを使用するコードを書きます。

Physics2d.Raycastの引数は始点、方向、距離、レイヤーの順番になっていて、

キャラクターの位置から向いている方向に距離1.5を伸ばしてNPCレイヤーに所属しているものに当てるという感じみたいです。

他のコードも入力したらテストをして、デバッグログが確認出来たら次に行きます。

次は表示させる用のUIを作成するステップです。

説明通りにまずは新しいUIDocumentを作成して、中身を作っていきます。

中身が出来たら説明通りに配置していきます。

配置ができたらコードを入力していきます。

とりあえずUIの方のコードが入力できたら、動作をチェックしてメッセージウィンドウが消えていれば大丈夫です。

始めのコードではメッセージウィンドウを非表示にするコードをしていて、

新しく作ったPublicのメソッドを呼び出すことでウィンドウを表示するようになっています。

次はRaycastの時に書いたPlayerControllerのデバッグログのコードを消して、

UIを呼び出すためのコードに書き換えます。

判定用に中身のない新しいコードを作ってNPCオブジェクトにアタッチし、

Raycastで読み取った(要するに中身があればいい)オブジェクトがあればUIを表示するという感じです。

テストをしてNPCにRaycastを当てたらウィンドウが出て消えれば大丈夫です。

 

7.カメラ設定

ここから最終章です。

learn.unity.com

さすがに文字数が多くなってきましたが、最後までやっていきます。

ここから先はカメラ、エフェクト、ミュージックの追加をやって、

最後にビルドまでやってしまう感じです。

 

まずはカメラ設定ですが、前のRuby'sAdventureの時もそうだったのですが、

UnityLearnではカメラ設定をCinemachineでやる印象が強いです。

ということでまずはプロジェクトにCinemachineを追加します。

これを入れよう

入れたらGameタブでどんな感じかチェックしてから、説明に従って設定を変えてみます。

変えた部分がどうもカメラの拡大率を変える部分みたいです。

次の説明はUnityのカメラは遠近法と正投影モードがあり、2Dでは正投影モードでカメラを使う方法について説明しています。

次のステップではカメラのフォローについて説明がされていて、

フォローに入ったGameObjectを中心にカメラが動くようになります。

ここ

外まで見えちゃう

ただ今の段階では絶対に中心にキャラクターを配置してしまうので、

見られてはいけない部分まで見えてしまいます。

次のステップではCinemachineの拡張機能でConfiner2Dを使い、

カメラの移動を制限するみたいです。

移動を制限するために制御用の空オブジェクトを作り、

BoxColliderやPolygonColliderを作成して端っこを作ってあげます。

(プレイエリアを囲ってあげる感じ。Polygon推奨みたい、むしろそうじゃないとダメ。)

ただこのままだと衝突判定が行われてしまい、キャラクターが弾き飛ばされてしまいます。

なので、レイヤー設定して当たり判定を無くしてしまいます。

動作が確認出来たら次に行きます。

 

8.オーディオを付ける

効果音やBGMがあった方が盛り上がるので、ここではオーディオについて説明があるみたいです。

まずはBGMについて説明していますが、ここでは空のオブジェクトにAudioSourceを追加しています。

BGMのオーディオクリップとPlay on AwakeとLoopにチェックを入れて、

起動するとサウンドがなります。

この状態だとBGMの制御は特になく単に起動したら音楽が流れ、

曲の終わりになったら自動で最初から再生し直すようになっています。

次は効果音などを追加するステップになります。

効果音は特定のタイミングで流すものなので、コードを使って制御しています。

まずはプレイヤーキャラクターのオブジェクトにAudioSourceを追加します。

(Cilpはなしでいい、Play on Awakeのチェックは外す。)

その後効果音再生用のコードを追加します。

この段階で起動しても音はならないので、次の回復アイテムの効果音で初めて音を鳴らせます。

回復アイテムのコードにオーディオクリップの変数を追加して、

セットした効果音をプレイヤーのオーディオクリップで再生する感じになります。

次は敵キャラクターの音を設定しますが、近さによって音量を変えることについての説明があります。

ここではSpatialBlendを3Dに寄せることで3Dオーディオを使ってやるみたいです。

もっと詳しいことはAudioListenerなどを使ってやるみたいですが、

ここでは説明が中心で実際にはやらないです。

実際3Dの時の設定なので2Dではこの状態だと流れません。

次はチャレンジで敵キャラクターに弾が当たったときに鳴っている効果音を停止するようにします。

コードでAudioSourceの変数を作ってGetComponentして止めるだけなので、

そこまで難しくないと思います。

(直った時の効果音を流して止められたら、なおいいかも。)

最後に音の減衰の問題を解決するためにAudioListenerを説明通りに配置して、

ここは終わりです。

余裕があったら他の効果音も付けてみてもいいかもしれません。

 

9.パーティクル(視覚効果)を付ける

このチュートリアルでは簡単だけど、パーティクルシステムを使って視覚効果(VFX)を追加するみたいです。

VFXについては違うチュートリアルで詳しく解説しているみたいですが、

今はまだやらないです。

learn.unity.com

始めのステップでは効果に使う画像の設定を行います。

画像分割はここまでで何度かやってきたので、ここは復習になります。

次のステップではHierarchy上で新しくパーティクルシステムを作成します。

Effectsの中にあるのですぐに見つかると思います。

説明通りにTextureSheetAnimetionのチェックをオンにし、

ModeをGridからSpriteに変更して先ほど分割した煙の画像を両方格納します。

StartFrameを2つして値を説明通りに変更して、FrameOverTimeを説明通りに変更します。

次のステップではShepeのパラメータを変更しています。

パラメータを変更すると煙の広がる角度がかなり変わります。

次はStart周りを変更するみたいです。

パラメータが2つあるのはその範囲内でランダムで発生させる感じで、

LifeTimeはパーティクルを描画する時間(消すまでの時間)、Speedは速度、Sizeは大きさという感じみたいです。

ColorOverLifetimeは終わる時の色合いの設定、SizeOverLifetimeは終わる時のサイズ変更の変化具合で、

この辺の設定も説明通りにやって進めていきます。

できたら作ったパーティクルシステムをPrefabにしてから削除します。

その後作ったPrefabをEnemyのPrefabの子に配置します。

配置したPrefabの位置を調整してから起動して、敵から作ったパーティクルが出ているか確認できたら次に進みます。

SimulationSpaceを変更するように説明がありますが、これを変更することで煙が移動に合わせて移動するようになります。

(ローカル座標からワールド座標に変更したからかも)

その後コードを変更して敵が直った時にパーティクルシステムも止めるようにします。

PublicでParticleSystemの変数を立てたことで、直接中身を指定している感じになります。

自分のコンポーネントならGetComponentで取れますが、子オブジェクトなのでこの方法で取っているのだと思います。

テストをして問題なければ次に進みます。

 

10.手書きアニメーションの導入

ここは基本的に手書きアニメーションをプロジェクトに導入するにはというコラムチュートリアルになっています。

他のソフトなどでアニメーションのコマを作って、

それをUnityで再現するために活用できそうなので読み進めていきます。

基本的には他のアニメーションが作れる画像ソフトなどを使って、

コマを1つずつ作っていくのが前提でこのチュートリアルは進んでいます。

歩行モーションで説明がされていて、接地モーションと通過モーションでアニメーションになっているという感じで説明がされています。

基本的にこの辺が原画と中割りの関係になっていて、その説明なんだと思います。

どっちにしてもUnityでは1コマ単位でキーフレームとして扱うので、

キーフレームが何秒間でどのぐらい配置されるかで動きが変わるという感じです。

あとは1画像にすべてのコマを配置した時など、1コマに対する画像の大きさについても書かれています。

画像のサイズは2のn乗を意識して配置するとベストみたいです。

どっちにしてもまずは基本的なアニメーションを作れるようにならないと、

この辺の話はまだまだ先になりそうです。

 

11.ビルド

ゲームができたらアプリケーションとして使えるようにしないといけないです。

ここでは出力する方法、ビルドについて説明しています。

Unityエディタをインストールした時にモジュールを追加しましたが、

このモジュールでどの端末に向けてビルドをするかを決める感じです。

モジュール自体は後で追加はできます。

ProjectSetting->Playerでアイコンやゲーム名、バージョンの設定が可能で、

ここで細かい範囲が決められます。

名前を決めよう

設定ができたら、File->BuildSettingから説明通りにビルドをしてみます。

Sceneの追加を忘れずに

ここでBuildに含ませるSceneの指定をしていますが、

コードなのでシーン切り替えを行う場合は右のシーンナンバーを使うので、

この画面は今後お世話になるかもしれないです。

 

ビルドができたら内容をチェックしてこのチュートリアルコースは終了です。

 

まとめ

とりあえず基本的に英語でいい加減な具合で解釈して進めてきましたが、

なんとか終わらせました。

いくつか自分が書いている部分もあっていない部分もありますけど、

それよりも公式のコードが結構間違っていたり、

そのコードでは動かないよというのがあったりしました。

初学者目線から言うとこうなるとかなり厄介で、挫折する要因になりそうなのであまりこういうことは無いようにして欲しいです。

とにかくこのチュートリアルは誤植がない書籍などを1度読み切った経験がないと、

きついなとは思えました。

 

まだ他にやってみたい項目もありますがこのWeblogと並行してやるのも少し辛くなってきたので、

前の更新で言った通りに自分のノートだけでまとめる方式に変えたいです。

ただ、気づきのポイントとかがあればいくつかまた書いてもいいかもしれません。

 

とにかくそろそろクソゲーを作らないとぁ。

 

ということで今日はこれにて!

では!