5th week - dsuz/unity-game-dev1-1st-term-2020 GitHub Wiki

今回のテーマ

今回のテーマは「他のオブジェクトに働きかける」です。

  1. オブジェクト (GameObject) を検索・取得する
  2. オブジェクトにアタッチされたコンポーネントを取得する
  3. コンポーネントの関数(メンバ関数・メソッド)を呼び出す

プロジェクトの準備

今回のプロジェクトをインポートすると、/Assets/Scenes/GameScene が上書きされます。そのため、GameScene で作業していた人は、これまでの作業内容が失われないように Duplicate (Ctrl + D) して作業内容を退避しておいてください。

  • 前回までのプロジェクトがない人は、新しくプロジェクトを作って 4th_week_finish.unitypackage をプロジェクトにインポートすれば、「前回終了時のプロジェクト」になります
    • ブロック崩しのシーンは /Assets/Scenes/GameScene です
  • 前回までのプロジェクトがある人は、5th_week_assets.unitypackage をプロジェクトにインポートします

GameObject を検索・取得する

動作確認

  1. シーン "/Assets/Scenes/Exercise" を開き、実行する
    • 以下のような動きをすれば正しく動作しています

重要な関数 GameObject.Find()

この動きは C# スクリプト コンポーネント "ExerciseController" によって行われており、それは GrayRightWall にアタッチされている。

スクリプトの中身を見ると、Start() 関数内で "BlueLeftWall" という名前のオブジェクト (GameObject) を取得している。GameObject.Find() に引数として文字列でオブジェクト名を渡すと、その名前のオブジェクトを検索し、取得してくれる。(同名のオブジェクトが複数ある場合は、最初に見つかったものが取得される)

最重要関数 GetComponent()

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 している。

GameObject.Find() の類似関数

オブジェクトを検索・取得する関数は以下の3つがある。場合に応じて使い分けることができる。

  1. GameObject GameObject.Find(string name) - 名前で検索し、最初に見つかった GameObject を一つ返す
  2. GameObject GameObject.FindWithTag(string tagName) - タグ名で検索し、一致した名前のタグを持つ GameObject のうち最初に見つかったものを返す
  3. GameObject[] GameObject.FindGameObjectsWithTag(string tagName) - タグ名で検索し、一致したタグを持つ GameObject すべてを配列で返す
  4. GameObject GameObject.FindObjectOfType(Type type) - コンポーネント名で検索し、そのコンポーネントがアタッチされた GameObject のうち最初に見つかったものを返す
  5. GameObject[] GameObject.FindObjectsOfType(Type type) - コンポーネント名で検索し、そのコンポーネントがアタッチされた GameObject すべてを配列で返す

課題(各5点)

  1. 現在は BlueLeftWall が左に弾かれるが、それに代わって RedLeftWall が弾かれるようにプログラムを変更せよ
  2. RedLeftWall が右に弾かれるようにプログラムを変更せよ
  3. GrayRightWall にアタッチされているコライダーをトリガーモードにし、Ball が GrayRightWall に「接触」した時に RedLeftWall が弾かれるようにプログラムを変更せよ
  4. Ball が GrayRightWall に接触した時に RedLeftWall は右に、BlueLeftWall は左に弾かれるようにプログラムを変更せよ

発展課題(各10点)

  1. Ball が GrayRightWall に接触または衝突した時に、いずれかのブロックの色を変えるようにプログラムを変更せよ
    • ヒント: SpriteRenderer コンポーネントを使う
  2. タグ 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を加算している。

次回ではこの得点を画面に表示する仕組みを学ぶ。

課題 7(5点)

現在はブロックを1つ壊すごとに3点が加算される。これを「ブロックを1つ壊すごとに100点が加算される」ようにプログラムを変更せよ。

まとめ

  1. GameObject.Find() でオブジェクトを名前で検索・取得できる
  2. 取得したオブジェクトからコンポーネントを取得し、プロパティを読み書きして設定を取得・変更したり、関数を呼んで機能を呼び出すことができる
  3. 自分で作ったコンポーネントも、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
⚠️ **GitHub.com Fallback** ⚠️