6th week - dsuz/2019-1st-term-unity-game-development GitHub Wiki

プロジェクトが失われてしまった人は

新しく空の Unity プロジェクト (2D) を作り、5thWeekCompleted.unitypackage をインポートすることで先週の授業終了時の状態になる。

Unity のスクリプト(スクリプト コンポーネント)

Unity 独自の使い方

  • C# のクラス (class) は Unity のコンポーネントである
    • 厳密には、MonoBehaviour を継承し、ファイル名とクラス名を一致させたクラスが Unity のコンポーネントになる
    • コンポーネントであるということは、GameObject に追加(アタッチ)して使うということ
    • もちろん Unity のコンポーネントではない C# のクラスも作ったり使うことができる
  • C# のスクリプトからは、オブジェクト (GameObject) に追加されたコンポーネントを操作できる
  • private メンバ変数に [SerializeField] 属性を設定することで、Inspector から値を設定できる

C# と共通の事柄

  • メンバ変数 - インスタンス内で値を保持できて、コンポーネント内ではどの関数からでも使える
    • public のメンバ変数は外から参照・代入できる
    • private のメンバ変数はクラス(Unity 的にはコンポーネント)内からだけ参照・代入できる
      • public で定義しなければ(何も書かなければ)メンバ変数は private となる
  • メンバ関数 - 呼び出すことでそこにまとめられた命令を実行できる
    • public のメンバ関数は外から呼び出せる
      • 例えば Button をクリックした時 (OnClick) にも呼び出せる
    • private のメンバ変数はクラス(Unity 的にはコンポーネント)内からだけ呼び出せる
  • 関数の引数・戻り値
  • ローカル変数 - 関数を抜けると値はリセットされる
  • データ型(型) - string, int, float や配列など
  • ループ処理 (for, while など) や制御文 (if, switch など) の書き方

コンポーネントへの働きかけ

コンポーネントのプロパティに値を代入したり、関数を呼び出すことでコンポーネントに働きかけることができる。いままで使ったもので重要なものを以下に挙げる。最後に () がついているものは関数、ついていないものはプロパティである。

  • Rigidbody2D.AddForce() - パラメータで与えた力を Rigidbody に加える
  • Rigidbody2D.velocity - 速度ベクトルを代入することで Rigidbody の速度ベクトルを変える
  • UnityEngine.UI.Text.text - 文字列を代入することで表示している文字を変える
  • AudioSource.PlayOneShot - パラメータで与えた AudioClip を鳴らす
  • Transform.position - オブジェクトの座標を代入することでオブジェクトをそこに移動させたり、参照することで座標を取得できる

Unity で頻繁に使う関数

  • Find 系関数 - GameObject またはその配列をシーン内から検索して取得する
    1. GameObject.Find
    2. GameObject.FindWithTag
    3. GameObject.FindGameObjectsWithTag
    4. GameObject.FindObjectOfType
    5. GameObject.FindGameObjectsOfType
  • GetComponent 系関数 - GameObject からコンポーネントを取得する
    1. GetComponent
    2. GetComponents
    3. GetComponetsInChildren
    4. GetComponentsInParent
  • Destroy - GameObject を破棄する

よくある使い方

  1. GameObject.Find("オブジェクト名") で、シーン内から ObjectName という名前の GameObject を探して取ってくる

  2. GetComponent<コンポーネント名>() で、その GameObject に追加されているコンポーネントを取得できる

  3. 以上を組み合わせて、

    GameObject go = GameObject.Find("ObjectName");
    Rigidbody2D rb = go.GetComponent<Rigidbody2D>();
    rb.AddForce(Vector2.up);

    という処理を書くと、「ObjectName という名前の GameObject をシーン内から取得し、(その GameObject に Rigidbody2D が追加されていれば)上向きの力(大きさ = 1)を加える」ということができる

特殊な書き方

以下のような書き方がある。

  • GetComponent<コンポーネント名>() - そのスクリプトが追加されている GameObject に追加されているコンポーネントを取得できる
  • transform - そのスクリプトが追加されている GameObject の Transform コンポーネントを読み書きできる
  • tag - そのスクリプトが追加されている GameObject の tag を取得できる
  • name - そのスクリプトが追加されている GameObject の名前を取得できる
  • Input.GetAxis()/GetAxisRaw() - パラメーターに "Horizontal" を渡すと水平方向、"Vertical" を渡すと垂直方向の入力を受け取ることができる
  • OnCollisionEnter2D()/OnTriggerEnter2D() - その GameObject にコライダーモードの Collider がついていたら接触時に前者が呼び出される。同様にトリガーモードの Collider がついていたら後者が呼び出される。ただし、衝突判定が行われるためには、衝突する(コライダーが追加されている)2つのオブジェクトのどちらかに Rigidbody が追加されている必要がある。

学び方

  • プログラミングやゲーム開発は、「順番に学んですべてを理解する」ことはどうしてもできないので、すべてを理解できなくてもある程度理解したら先に進んで網羅して学び、何周も繰り返し学ぶ必要がある
  • コンピュータは自分の理解できる命令しか受け付けない
    • やりたい事をどうやってコンピュータに伝えるかを工夫することで、プログラミングに慣れていくこと
  • ヘルプを活用すること
  • Google を使うこと
  • 最初は「互いに影響を与えることは当たり判定時 (OnCollisionEnter2D の中) 程度に抑えて、それぞれが独立して動く」ようなものをたくさん作った方がよい

今回使うアセットをダウンロードする

  1. 6thWeekAssets.unitypackage をダウンロードしてインポートする
    • 今回インポートするアセットは以下の通り
      • image

ボールが垂直に往復して進行不可能になることを防ぐ

パドルの端にボールが当たったら、外側に力を加える

  1. Paddle オブジェクトの Tag を Player に変更する
  2. この変更により、「パドルの端にボールが当たった時、外側に跳ね返る」ように力が加わるようになる
  3. この機能は、BallController の 97~102 行に追加されている

説明

  • この機能は、HitFactor を計算することにより、ボールがパドルのどこに当たったのかを判定し、それに応じて力を加えている
  • HitFactor は、パドルの右端が 1、中央が 0、左端が -1 となるように計算している
  • HitFactor に右方向の単位ベクトルを掛けることにより、「外側に力を加える」ためのベクトルを計算している

ボールが水平に往復して進行不可能になることを防ぐ

  1. 水平に近い角度で衝突したら、一定方向に力を加えて水平移動を回避するように処理を加えている
  2. この機能は、BallController の 114~119 行に追加されている

ゲームのループを作る

リスタート機能を作ることで、シーンの実行を止めなくとも繰り返しプレイできるようにする。

  1. 画面内に UI - Button の GameObject を作り、以下のように設定する
    1. 名前を RestartButton に変える
    2. 以下のように、On Click() 時に実行される関数に、ボールのオブジェクトの BallController.ResetGame 関数を設定する
      • image
    3. ボタン上の文字(キャプションテキスト)を Restart に変える
    4. オブジェクトを非アクティブにする
  2. 新しく作った Button のオブジェクトを、ボールのオブジェクトの BallController コンポーネント - Restart Button にアサインする

説明

  1. 得点、得点表示、ボールの位置を初期状態に戻し、TargetBlock を全て消して再生成することでゲームを初期状態に戻している。
  2. これらの処理は BallController.ResetGame() として追加し、GameOver(), GameClear() 内で呼び出している。

ボールの速度を一定範囲内に調整する

  1. ボールの最大速度と最低速度を設定し、ボールの速度がそれを越えないように調整する処理を加えている
  2. この機能は、BallController の 232~244 行に AdjustSpeed() という関数を追加し、それを呼び出すことで実現している

まとめ

  1. Unity の C# では、一般の C# と同じように使うところも多いが、Unity 独自の書き方(Unity がゲーム開発のために C# に追加した機能)もある
⚠️ **GitHub.com Fallback** ⚠️