Unity入門7
Space Shooter④
(スペースシューター)
前回までで【弾】と【岩】と【プレイヤー】の動きや、それぞれの当たり判定ができました。
次は【岩】を倒すとスコアが上がるようにしましょう。
状況確認
スコア表示
最初に、スコアの表示部分から作ります。
これは、今まで2種類の方法をやりました。
1つ目は、UIオブジェクトを作って表示する方法(ボール落としゲームの時に使いました)
2つ目は、スクリプトだけで作る方法(コイン落としゲームで使いました)です。
基本的にスクリプトだけで作る方法に慣れたいので、今回もスクリプトで作りたいと思います。
記載する場所は
【
GameController
】ファイルで大丈夫なので、ここに追加していきます。
まずは以前のスクリプトを確認します。
こんな感じでしたね。このコードで
【画面左上を基準に左に40の余白
、上に10の余白の位置に
、横幅200、高さ50の長方形の枠
】
【文字色が黒】
【残りコイン:変数という文字】を表示。
というスクリプトでしたね。これを修正して使いましょう。次へ。
スコア表示
これで【文字色を白色】【スコア:変数】という表示に変わります。
※当然score変数も用意しておいてください。
この段階で確認しておきましょう。以下の画像のようになっていたらOKです。
まずは以下のように修正してみましょう。
スコアを増やす
次は、スコアを増えるようにします。
これも以前やったコイン落としのスコアと同じ感じに作ってみましょう。
まずは
【
GameController
】ファイルに以下のメソッドを追加しましょう。
また、今回も点数を保存する変数(score)は、直接イジることはできないようにしたいので、privateにしてください。
※これをカプセル化と言うんでしたね。
スコアを増やす
後は、岩が破壊された時に先ほど作った【
ScoreUp()
】メソッドを呼び出せば良さそうです。
岩が破壊された処理は【
DestroyByContact
】に書いていましたね。
別クラス(ファイル)のメソッドを呼び出すには、まずそのクラスを代入するための変数が必要でした。
【
DestroyByContact
】に以下のように【
GameController型
の変数
gameController
】
を用意しましょう。
スコアを増やす
次に
【
ScoreUp()
】メソッドを呼び出す部分を追加します。
後は、インスペクタビューから
【
変数
gameController
】に【
GameController
】オブジェクトを代入すればOKでしたね。次へ。
スコアを増やす
【
DestroyByContact
】スクリプトがアタッチされているのは、
Prefabの【
Asteroid
】ですね。
では
【
Asteroid
】
のインスペクタビューから、
【
gameController
変数
】に【
GameController
】オブジェクトを放り込みましょう。
やってみるとわかりますが、実は放り込めません。次へ。
スコアを増やす
実は、Prefabの変数にオブジェクトは代入出来ません。そのため、別クラスのメソッドが呼び出せない状況になってしまいます。
※コイン落としの時は、Prefabではなくオブジェクトの変数だったので代入することが可能でした。
このような場合、スクリプト側で工夫する必要があります。
【
DestroyByContact
】
以下のコードを追加してください。
解説です。
まず【
gameControllerObject
=
GameObject
.
Find
(
"
GameController
"
)
】の部分で、【
GameController
】という名前のオブジェクトを探してきて、それを【
gameControllerObject
】という変数に代入しています。
つまり【
gameControllerObject
変数
】には【
GameController
オブジェクト】が入った状態です。
次に下の【
gameControllerObject
.
GetComponent
<
GameController
>()
】の部分で、【
GameController
オブジェクト】の【
GameController
コンポーネント
】だけを、【
gameController
変数
】に代入しています。
こうすることで、Prefabから別クラスのメソッドを利用することが出来るようになります。次へ。
スコアを増やす
これで試してみましょう。ちゃんとスコアが増えるはずです。
これで、だいぶゲームの基礎部分が出来ましたね。
ついでに
【
gameController
変数
】はpublicである必要がなくなったので、privateにしておきましょう。
さて、今後のことも考えて【
ScoreUp
メソッド
】をもう少し改良したいと思います。
現在、ScoreUpメソッドは必ず1しか増えないようになっていますが、これでは不便です。
引数を使えばScoreUpメソッドを呼び出す際に、増える数を指定出来るように出来ますね。これを改良しましょう。次へ。
試してみよう
以下のように
ScoreUpメソッドを呼び出すと、引数に指定した数(10)だけスコアが増えるようにしてください。
ヒント:戻り値ナシ、引数アリのメソッドにすれば良いですね。
ゲームオーバー
次は、プレイヤーがやられた時に「
GAME OVER
」の文字が表示されるようにしましょう。
スコアの時と同じように【
OuGUI()
】メソッドを使います。
新しく作る必要もありませんので
【
GameController
】ファイルの【
OuGUI()
】メソッドに追加で書いていきます。
文字を表示するために必要なのは以下の2行でしたね。
この部分をゲームオーバー分も作ってあげれば良いわけです。次へ。
ゲームオーバー
とりあえず、コピベして下の感じにします。
当然、今はエラーになります。(変数名
label
が被っているので)
【label】と【label2】などにしておきましょう。
次へ。
後は、表示内容と、表示場所を指定するだけですね。以下のようにしてください。
ポイントは表示場所の指定です。
【
Screen
.
width
】は画面のヨコ幅、【
Screen
.
height
】は画面のタテ幅のプロパティです。
これに【 / 2】をつけることで、それぞれの【半分の位置】を指定出来ます。
ヨコ幅(
Screen
.
width
)にだけ、【-40】もつけているのは文字を、ちょうどど真ん中に表示したいため、文字の開始位置を半分の位置からではなく、少し左側からにしています。
次へ。
ゲームオーバー
下のような感じになればOKです。
現時点では、ゲームオーバーじゃなくてもGAME OVERが表示されていて大丈夫です。
ゲームオーバー
とりあえず表示は出来ましたが、なんか文字も小さいですし、色を変えたり、もっと柔軟に表示方法を変えられるようにしたいと思います。
まず、以下の型の変数を追加してください。
文字スタイルを変える
【
GUIStyle
】という型(クラス)は、文字のスタイルを指定できる型です。
これを以下のように【
GUI.Label()
】メソッドの引数に指定します。
また、【
GUI
.
color
=
Color
.
white
;
】の部分は不要になるので、削除してOKです。※下ではコメントアウトしています。
一旦【
GameController
】のインスペクタビューを見てください。
【
Score Style
】と【
Game Over Style
】といいう項目が増えていると思います。
文字スタイルを変える
各変数名のヨコの三角を押し、展開すれば、色々な項目が出てきます。
ここから文字のスタイルを設定できます。
次へ。
項目が多すぎるので、最低限変えときたいところだけ説明すると、文字の色を指定する【
Text Color
】と、文字の大きさを指定する【
Font Size
】です。
文字スタイルを変える
とりあえず、この2つだけは変えておきます。
次へ。
ここでは、下の感じで進めます。※別に同じにしなくてOKです。
また、サイズを変えると、文字の位置もズレるので調整しています。
※文字の位置もGUIStyleから調整出来ますが、逆にややこしいのでスクリプトで指定してます。
文字スタイルを変える
では、次はGAME OVERの表示を【プレイヤーがやられた時】だけ、表示させるようにしましょう。
つまりは【
GAME OVERの表示に条件をつける】という考え方です。当然if文を使います。
以下のようにif文を追加してください。追加したら次へ。
文字の表示タイミング
文字の表示タイミング
後は、【
条件
】の部分をどう設定するか?です。
これは、単純に以下の形にしたいと思います。
変数【
gameOver
】を作って、その値の【trueかfalseか】で、判断させるということですね。
変数【
gameOver
】はprivateにして作っておきましょう。
ここまでくれば、後なにすれば良いか想像できるのではないでしょうか?
試してみよう
以下の画像のように、ゲームオーバーになった時だけ【GAME OVER】が表示されるようにしてください。
条件①:【
if
(
gameOver
)
】部分は変更しないでください。
条件②:【
gameOver
】変数は必ずprivateにしてください。
ヒント①:スコアアップと同じように、
【
gameOver
】変数の値を変えるだけのメソッドを用意すると良いですね。
ヒント②:ヒント①で作ったメソッドを、プレイヤーが爆発する判定のスクリプトから呼び出せば良いですね。
リスタート
次は、ゲームオーバーになった後、もう一度スタート(リスタート)できるようにしましょう。
これも今までやっていない処理ですが、難しくはありません。
【
GameController
】ファイルの【
Update
】メソッドに以下のように追加しましょう。
※元のコードは消さないように注意。
外側のif文はGAME OVERの表示と同じです。
内側の【
Input
.
GetKeyDown
(
"
r
"
)
】は、見たまんまで、キーボードのRキーのが押されればtrueになります。
ポイントは【
SceneManager
.
LoadScene
(
"
Level01
"
)
;
】です。
これは初登場の「Sceneを読み込むメソッド」です。もしScene名が【Level01】ではない場合は、その名前にしておいてください。次へ。
リスタート
【
SceneManager
.
LoadScene
(
"
Level01
"
)
;
】とすることで、【
Level01
】という名前のSceneが読み込まれます。
今まであまり意識していませんでしたが、UnityではSceneごとにオブジェクトがあり、その【Sceneが読み込まれる】ということは、【そのSceneの最初からスタート】ということになります。
←を見てもわかるように、すべてのオブジェクトはSceneの中に含まれています。
ただ【
SceneManager
.
LoadScene
(
"
Level01
"
)
;
】はこのままだとエラーで使えませんので、名前空間を追加して上げる必要があります。
次へ。
リスタート
【
using
UnityEngine
.
SceneManagement
;
】を追加して上げましょう。
これで、ゲームオーバーになった時にRキーを押せば、リスタートできるようになります。
試してください。
リスタート
ゲームオーバーの時に、下の画像のように「Rキーを押せばリスタートできる」ことがわかるように文字を表示させてください。
※文字の内容は自由です。
条件①:文字サイズ、文字色は自由ですが、【
スコア
】と
【
GAME OVER
】の文字と同じにはせず、必ずサイズか、色は変えて表示させてください。
岩の種類を増やす
次は、岩(asteroid)の種類を増やしましょう。
このアセットには3種類の岩が用意されています。そのすべてがランダムに出現するように作ってみましょう。
まず【
GameController
】の【変数asteroid】部分を見てください。
この変数に岩Prefabを指定していましたね。
同じように【変数asteroid02】とか作っても良いのですが、後々の処理をラクにしたいので、今回は配列で管理したいと思います。
【
public GameObject asteroid;
】を消して、以下のように変えてください。
配列の宣言だけの状態ですね。
後ほど、岩以外の敵もここに入れますので、名前を【
hazards
】にしてます。
次へ。
岩の種類を増やす
この時点では、エラーが出てしまいます。下記の項目が原因です。
これを以下のように変えてください。
これで保存したらinspectorビューを見てください。
岩の種類を増やす
inspectorビューの表示が下のような感じになっていると思います。
sizeの項目は配列の要素数の事です。つまりここに3を入れれば、3つの要素をもった配列になります。やってみましょう。
要素が出来ましたね。
この【
Element〜
】にそれぞれのPrefabを入れればOKですね。
まだ岩01のPrefabしかないので、他のPrefabを用意しましょう。
次へ。
岩の種類を増やす
Prefabの増やし方はカンタンです。
まずは、Prefabフォルダの中の、【
Asteroid
】をHierarchyビューにドラッグ&ドロップして、オブジェクトにします。
次に、
【
Asteroid
】を
右クリック、【
Duplicate
】を選択して、複製を作ります。
【
Asteroid
】と【
Asteroid(1)
】の状態になるので、それぞれ名前を【
Asteroid02
】と【
Asteroid03
】にしておきます。
後は、中身の画像(model)だけを入れ替えます。
次へ。
岩の種類を増やす
まずは現在の岩の画像(model)を削除します。
【prop_asteroid_01】を右クリックし、【Delete】で削除です。
※【Asteroid◯◯】自体を削除しないように注意。中身だけです。
下のようなウィンドウが開くので、【
Continue
】でOKです。
2つとも削除したら、modelを入れ直します。次へ。
岩の種類を増やす
1つ目の岩と同じように、Projectビューから【
Models
】フォルダを開き、
【
Asteroid02
】には【
prop_asteroid_02
】を、
【
Asteroid03
】には【
prop_asteroid_03
】を、
それぞれドラッグ&ドロップで放り込みます。
最後に、この2つのオブジェクトをPrefabに放り込み、元のオブジェクトは削除します。
次へ。
岩の種類を増やす
Prefabに下のように3つとも入っていることを確認してください。
オブジェクトは下のように削除されていることも確認しておきましょう。
岩の種類を増やす
これで、先ほどの配列【
hazards
】に入れる準備が整いました。
それぞれのPrefabを
【
hazards
】の要素に放り込んでください。
上の感じになればOKです。
※【Asteroid】を【Asteroid01】にしておいても良かったですね。変えたい場合は自由に変えてください。
後は、スクリプトからこの3つの岩をどう出すかを考えましょう。
次へ。
岩の種類を増やす
3つの岩の出し方に関しては、色々なパターンが考えられますが、今回はお手本ゲーム通り【岩が作られる時にランダムでどれかを出す】方法で作りましょう。
現在は以下のようになっていますので、1つ目の【Asteroid】だけが出てくる状態ですね。
もちろん、これでは今までと同じなので、ランダムに変えたいと思います。
次へ。
試してみよう
3種類の岩がランダムに出るようにしてください。
ヒント①:
SpawnWaves()
メソッドに引数を持たせ、呼び出す際にランダムな値を設定するのが一番キレイです。
ヒント②:【
Random.Range()】
メソッドと、
【配列名.Length】
メソッドを組み合わせましょう。
※これには色々な方法がありますので、どんな方法でも構いません。
完成像です。
(わかりにくいので、岩の出現スピードを1秒毎にしています)
少し難しいかもしれませんが、そろそろこれぐらいのロジックは組めるようになりたいので、時間の許す限りチャレンジしてみましょう。
敵を作る
次は、岩以外の敵キャラを作ってみましょう。
まずは、空オブジェクトを作成し【
Enemy01
】 にしておきます。
ここに、【
Models
】フォルダから【
vehicle_enemyShip
】をドラッグ&ドロップで放り込みます。
敵を作る
エンジン噴射のエフェクトも用意されているので、これもつけておきます。
【
Prefab
】→【
VFX
】にある【
engines_enemy
】を【
Enemy01
】に放り込みます。
ゲームを開始してみると、今はプレイヤーと重なった位置にいると思います。
【
Enemy01
】の【
Transform
】をイジって、上の位置(z14)ぐらいにしておきます。
敵の向きもおかしいので、【
vehicle_enemyShip
】の
【
Transform
】をイジって、y180に回転させておきます。
次に、Asteroidと同じように【
Rigidbody
】と【
CapsuleCollider
】をアタッチします。
【
Rigidbody
】は【
UseGravity
】をオフにして重力で動かないようにしてください。
【
CapsuleCollider
】は
【
Radius
】を0.8ぐらいにして、当たり判定を見た目と合わせてください。
また、敵が岩にぶつかっても素通りしてほしいので【
isTrigger
】はオンにしておきます。
敵を作る
あとは、動きです。まずは縦方向の動きを試してみます。
これは岩と同じように、【
Mover
】スクリプトをアタッチし、Speedを設定すれば良いですね。
ここまでで、下のようになっていると思います。
敵を作る
さて、実はこの敵の動きは一番の難所です。見た目以上に複雑な処理がされています。
もっと単純な動きにしても良いのですが、せっかくなのでサンプルゲームの通りに作っていきたいと思います。
次へ。
お疲れ様です
では、次回、敵の動きを作り込んでいきましょう。
【
スペースシューター⑤
】へ続く。