カメラ・背景の設定をしよう のバックアップ(No.2)


はじめに

ひつじを動かしてみる その2の続きです。
ひつじをRigidBodyコンポーネントを用いて左右に移動できるように改良しました。
次は縦方向の移動手段 ジャンプ を作ります。
ジャンプを作るにあたり、まずはジャンプの仕様を考えます。

仕様1 スペースキーが押されたらジャンプをする
仕様2 空中ではジャンプできない

次に、この仕様を実現するために必要な処理を考えます。

処理1 スペースキーが入力されたかを調べ、押されたときに処理2以降の処理を開始する。
処理2 ひつじが地面に触れているかを調べ、地面に触れている場合に処理3以降の処理を行う。
処理3 ひつじに上方向の加速度を一回与える。

これらの処理を一つずつ実装し、ひつじのジャンプを作っていきます。

 

キー入力を一度だけ受け取る

キー入力の受け取りを実装します。
ひつじを動かしてみる その2の時と同じようにしてスペースキーの入力も検知できます。
MoveSheep.csのUpdateメソッドの中にif文でスペースキー入力の検知を追加しましょう。

  1. // 略
  2.  
  3. public class MoveCamera : MonoBehaviour
  4. {
  5.     //ひつじの参照先を保存しておく変数
  6.     private GameObject sheep;
  7.  
  8.     void Start()
  9.     {
  10.         // ひつじのゲームオブジェクトを取得し保存用の変数に代入
  11.         sheep = GameObject.Find("hitsuji_dot");
  12.     }
  13.  
  14.     //略
  15.  
  16. }

これでよさそうな気もしますが、このままでは、「キーが押されている間、毎フレームジャンプの処理が行われる」ことになります。
30fpsとすれば0.1秒押し続けているだけで3回もジャンプが行われるわけです。
このままではひつじが空のかなたに消えてしまいそうなので、「キーが押されたときに一回だけジャンプの処理を行う」ように改良します。
今回は、Input.GetKey() の代わりに Input.GetKeyDown() メソッドを用いることでこれを解決します。
Input.GetKey() が、「キーが押されているとき」Trueになるのに対し、GetKeyDown() は「キーが押されたときに一回だけ」Trueになります。

  1. public class MoveCamera : MonoBehaviour
  2. {
  3.  
  4.     // 略
  5.  
  6.     void Update()
  7.     {
  8.         // ひつじの座標を取得
  9.         Vector3 pos = sheep.transform.position;
  10.         // ひつじの座標のままだと 俯瞰して見られないので、z座標を-10だけずらす
  11.         this.transform.position = pos + new Vector3(0.0f, 0.0f, -10f);
  12.     }
  13. }
 

ひつじに上方向の力を与える

はねる という動きをUnityのRigidBodyで再現したい場合、AddForce()メソッドのImpulseモードが便利です。
AddForceは文字通り、オブジェクトに「力を加える」メソッドです。
AddForceには
・継続的に力を加え続ける(加速させる)Forceモード
・瞬間的に力を加える Impulseモード
などのモードがあり、力の加え方を決めることができます。
ここではImpulseモードで上方向に一瞬だけ力を加えることで上に飛ぶ動作を再現します。

void Update()
  {
      /* 前回までのコード(略) */

      // ジャンプ
      // スペースキーの入力チェック
      if (Input.GetKeyDown(KeyCode.Space)) {

          // AddForceは物理演算でオブジェクトに力を加えるメソッド

          // AddForce(力の方向※Vector2型, モード※省略可)

          // モードは ForceMode2D.Impulse, &size(16){ForceMode2D.Force};&size(16){のように指定};

          rigidBody.AddForce(new Vector2(0, jump), ForceMode2D.Impulse);
      }

  }

これで、スペースキーが押されたときに上方向に飛び上がるようになります。

 

設置判定

地面に触れているか は Tilemap にひつじの下面が触れているか
と考えて作ります。
通常の当たり判定では、どの方向がTilemap当たっているかを調べることができません。
そこで、新しくひつじの足元にオブジェクトを作り、そのオブジェクトがTilemapに触れているかを調べることでこの問題を解決します。

設置判定用のオブジェクトを作る

hierarchyからひつじ
を右クリックし、メニューから create empty を選択して
空のひつじの子オブジェクトを作ります。
名前はGroundCheck にしておきます。

 

#画像

 

ひつじの子オブジェクトにすることがポイントです。
Unityでは、子オブジェクトは親オブジェクトを基準に座標が計算されます。
つまり、特にスクリプトを書かずとも、子オブジェクトは親オブジェクトとの位置関係をキープし続ける
勝手についてきてくれる
というわけです。

 

オブジェクトを作ったら、
GroundCheckにAdd ComponentでBox Colliderを追加します。

 

#画像

 

そのままではひつじと同じ大きさの当たり判定になってしまい、足元だけの判定にならないので、
Inspector > Edit Colliderを押し
sceneビューでcolliderの大きさを調整します。
(横幅はひつじの半分程度、縦幅は小さく、位置はひつじの足元になるように)

 

#画像

 

横幅を小さくしておかないと、横の壁も地面と判定されてしまうので注意です。

 

調節できたら、
InspectorからBoxColliderのisTriggerにチェックを入れます。

 

#画像

 

ColliderコンポーネントのisTriggerオプションは、他のColliderと反発するかしないかを決めるオプションです。
チェックを入れると反発しなくなります。
設置判定用のオブジェクトが地面と反発すると親子の位置関係を保とうとしてひつじのほうが浮いてしまうのでisTriggerで反発を無効化しておきます。

 

設置判定用のスクリプトを作る

GroundCheckを使ってMoveSheep内で設置判定を受け取るには、

GroundCheckのなかに public でフラグを作り、設置していればフラグをTrueにする。
MoveSheepからGroundCheckのフラグの値を読み取る。

という方法が考えられます。

 

まずはGroundCheckのスクリプトを作ります。

 

GroundCheckにAddComponent>NewScript で「GroundCheck」というスクリプトを追加します。
追加したらスクリプトを開き、StartやUpdateは消して、代わりにアクセス修飾子public をつけて設置判定の結果を入れるフラグを作ります。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class GroundCheck : MonoBehaviour
  6. {
  7.     //地面と当たっているかのフラグ
  8.     public bool isGround = false;
  9. }

初期値にはfalseを入れておきます。

 

次に、肝心の設置判定を作ります。
Colliderの当たり判定はスクリプトから受け取ることもできます。

  1. //略
  2.  
  3. public class GroundCheck : MonoBehaviour
  4. {
  5.     //地面と当たっているかのフラグ
  6.     public bool isGround = false;
  7.     //地面と触れたときにフラグをtrueに
  8.     void OnTriggerEnter2D(Collider2D col)
  9.     {
  10.         if (col.tag == groundTag) {
  11.             isGround = true;
  12.         }
  13.     }
  14.  
  15.     //地面から離れたときにフラグをfalseに
  16.     void OnTriggerExit2D(Collider2D col) {
  17.         if (col.tag == groundTag) {
  18.             isGround = false;
  19.         } 
  20.     }
  21. }