5th week - dsuz/unity-game-dev1-1st-term-2020 GitHub Wiki
今回のテーマは「他のオブジェクトに働きかける」です。
- オブジェクト (GameObject) を検索・取得する
- オブジェクトにアタッチされたコンポーネントを取得する
- コンポーネントの関数(メンバ関数・メソッド)を呼び出す
今回のプロジェクトをインポートすると、/Assets/Scenes/GameScene が上書きされます。そのため、GameScene で作業していた人は、これまでの作業内容が失われないように Duplicate (Ctrl + D) して作業内容を退避しておいてください。
- 前回までのプロジェクトがない人は、新しくプロジェクトを作って 4th_week_finish.unitypackage をプロジェクトにインポートすれば、「前回終了時のプロジェクト」になります
- ブロック崩しのシーンは /Assets/Scenes/GameScene です
- 前回までのプロジェクトがある人は、5th_week_assets.unitypackage をプロジェクトにインポートします
- シーン "/Assets/Scenes/Exercise" を開き、実行する
- 以下のような動きをすれば正しく動作しています
この動きは C# スクリプト コンポーネント "ExerciseController" によって行われており、それは GrayRightWall にアタッチされている。
スクリプトの中身を見ると、Start() 関数内で "BlueLeftWall" という名前のオブジェクト (GameObject) を取得している。GameObject.Find() に引数として文字列でオブジェクト名を渡すと、その名前のオブジェクトを検索し、取得してくれる。(同名のオブジェクトが複数ある場合は、最初に見つかったものが取得される)
OnCollisionEnter2D の中では、BlueLeftWall オブジェクトから Rigidbody2D コンポーネントを取り出している。つまり、GrayRightWall に何かが衝突すると、あらかじめ取得しておいた BlueLeftWall から Rigidbody2D を取り出し、操作している。
Rigidbody2D を取り出した後は、その取り出した変数に対して Rigidbody2D.AddForce() を(Impulse モードで)呼び出して、(急激な)力を加えている。このために BlueLeftWall は左に弾かれて台から落ちている。
この GetComponent は this.gameObject.GetComponent() と同じものである。this.gameObject.GetComponent は this.gameObject つまり「このコンポーネントがアタッチされている GameObject」から GetComponent するが、今回の GetComponent は「検索・取得してきた GameObject」から GetComponent している。
オブジェクトを検索・取得する関数は以下の3つがある。場合に応じて使い分けることができる。
- GameObject GameObject.Find(string name) - 名前で検索し、最初に見つかった GameObject を一つ返す
- GameObject GameObject.FindWithTag(string tagName) - タグ名で検索し、一致した名前のタグを持つ GameObject のうち最初に見つかったものを返す
- GameObject[] GameObject.FindGameObjectsWithTag(string tagName) - タグ名で検索し、一致したタグを持つ GameObject すべてを配列で返す
- GameObject GameObject.FindObjectOfType(Type type) - コンポーネント名で検索し、そのコンポーネントがアタッチされた GameObject のうち最初に見つかったものを返す
- GameObject[] GameObject.FindObjectsOfType(Type type) - コンポーネント名で検索し、そのコンポーネントがアタッチされた GameObject すべてを配列で返す
- 現在は BlueLeftWall が左に弾かれるが、それに代わって RedLeftWall が弾かれるようにプログラムを変更せよ
- RedLeftWall が右に弾かれるようにプログラムを変更せよ
- GrayRightWall にアタッチされているコライダーをトリガーモードにし、Ball が GrayRightWall に「接触」した時に RedLeftWall が弾かれるようにプログラムを変更せよ
- Ball が GrayRightWall に接触した時に RedLeftWall は右に、BlueLeftWall は左に弾かれるようにプログラムを変更せよ
- Ball が GrayRightWall に接触または衝突した時に、いずれかのブロックの色を変えるようにプログラムを変更せよ
- ヒント: SpriteRenderer コンポーネントを使う
- タグ ActionWallTag を追加し、RedLeftWall と BlueLeftWall にそれを設定せよ。そして GameObject.FindGameObjectsWithTag() 関数を使って ActionWallTag が設定されたオブジェクトをすべて検索・取得して、それら全てになんらかの命令(例:弾かれる、色が変わる)を実行せよ
ブロック崩しのシーン "/Assets/Scenes/GameScene" を開き、実行してください。ブロックを崩すごとに Score が Console に表示されます。これの仕組みについて説明する。
得点の加算の仕組みは、TargetBlockController と ScoreManager に追加している。ScoreManager ではメンバ変数として整数値 m_score を保持し、public 関数の AddScore() が呼ばれると、パラメータとして渡された整数値を m_score に加算し、ログに出力している。
TagetBlockController では、ScoreManager コンポーネントがアタッチされたオブジェクト "GameManager" を取得し、オブジェクトから ScoreManager コンポーネントを取り出して AddScore を呼び出して得点を加算している。また BlockBreakCounter プロパティに1を加算している。
次回ではこの得点を画面に表示する仕組みを学ぶ。
現在はブロックを1つ壊すごとに3点が加算される。これを「ブロックを1つ壊すごとに100点が加算される」ようにプログラムを変更せよ。
- GameObject.Find() でオブジェクトを名前で検索・取得できる
- 取得したオブジェクトからコンポーネントを取得し、プロパティを読み書きして設定を取得・変更したり、関数を呼んで機能を呼び出すことができる
- 自分で作ったコンポーネントも、Rigidbody2D などと同じようにプロパティや関数を使うことができる
- GameObject.Find()
- Unity の教科書: 4-6, 5-9-2, 5-9-3, 8-7-3
- 楽しく学ぶ Unity 2D超入門講座: 4.5
- GetComponent()
- Unity の教科書: 5-9-3, 6-5-1