[Unity]Unity4.3の2Dツールを使ってみる -Physics2Dスクリプト編その2-

サンプル完成

こんにちは!布浦です。
Unity2D企画、6回目です。

今日は、
「6. キー操作によるキャラクターの移動を実装する(Physics2Dスクリプト編その2)」
をやっていきたいと思います。
今回でサンプル完成です!

  1. 画像をSpriteとして画面に配置する
  2. Spriteにコマアニメを設定する(Animation View の使い方)
  3. 複数のアニメを切り替える仕組みをつくる(Mecanim)
  4. 2D物理エンジンでキャラクターを動かす(Physics2D設定編)
  5. 地面に当たったかどうかを判定する(Physics2Dスクリプト編その1)
  6. キー操作によるキャラクターの移動を実装する(Physics2Dスクリプト編その2)

物理演算が適用されたオブジェクトをプログラムで動かす

キャラクターは物理演算で動いているので、単純に座標を移動させてしまうと、
物理演算による衝突判定などの動きと噛み合なくなります。
不自然な動きになったり、当たり抜けが発生したりします。

void Update ()
{
     Vector2 pos = (Vector2)transform.position + Vector2.right;
     transform.position = pos;
}
めり込むことり

物理演算で本来壁に衝突するところを、無理にプログラムで座標を動かすとめり込んだりする

そこで使うのが、AddForceという関数です。
物理演算が適用されている物体に対して、力を加えることができます。

例えば、「キャラクターに右方向の力を加える」というコードは以下のようになります。
力を加えた結果の動きは物理シミュレーションによるものなので、
カベなどとの衝突判定も動きます。

void FixedUpdate ()
{
     rigidbody2D.AddForce(Vector2.right * 10);
}
壁で止まることり

壁で止まる

UpdateとFixedUpdate

Unityでは、描画の更新が行われるUpdateと、物理シミュレーションの更新が行われるFixedUpdateという2つのUpdate関数があります。
AddForceのように、物理シミュレーションによる物体の動きに作用するような処理はFixedUpdate関数内に書きます。

void Update ()
{
     /*下記以外の処理*/
}

void FixedUpdate ()
{
     /*物理演算による物体の動きに作用するような処理*/
}

矢印キーの入力を取得する

今回は、矢印キーによる移動(左右キーで移動、上キーで飛ぶ)を実装します。
矢印キーの入力具合は、Input.GetAxis という関数で取得できます。
縦方向と横方向の入力に対して、-1~1という扱いやすい数値で取得できるので、
これをつかって、力を加える方向をコントロールします。

key

Kotori.csに、下記のコードを追記します。

void FixedUpdate()
{
     //左右キーの入力
     float h = Input.GetAxis("Horizontal");
     //上下キーの入力
     float v = Input.GetAxis("Vertical");

     //左右キーの入力にあわせて、横方向の力を加える(歩く)
     rigidbody2D.AddForce(Vector2.right * h * 30f);
    
     //もし、上キーの入力だったら(下キーは無視する)
     if(v > 0)
     {
          //上方向の力を加える(飛ぶ)
          rigidbody2D.AddForce(Vector2.up * v * 50f);
     }
}

何もキーを押してない状態では、Input.GetAxisが0を返すので、何も力を加えないということになります。
物理シミュレーションなので、急に停止するのではなく、デフォルトで設定されている摩擦によって減速して止まります。
自然な動きが少ないコードで実装できるので便利です。

再生して、動かせるか確認しましょう。

動き回ることり

画面上を動き回れるようになったことり

速度に上限を設定する

キャラクターがキー操作に合わせて動くようになりました。
もう少し、自然な動きになるように工夫したいと思います。

AddForceは文字通り力を加えて物体を動かす関数ですが、
単純に繰り返しAddForceを使うと、
力を加え続けることになるので、物体はどんどん加速します。

キーを押しっぱなしにしているとき、加速をするのはいいのですが、
上限なく加速し続けると操作しづらくなってしまいます。

加速することり

velocityを出力してみると、速度が上がり続けるのがわかる

これを解決するために、制限速度をつくります。

– 制限速度を超えているときはAddForceを行わない
– 制限速度を超えているときは速度を制限速度に合わせる

この2つの処理を追加したコードが以下です。
各種パラメータは、GUI上で調整できるようにしました。
しっくりくる操作感になるように、調節してみてください。

//publicなグローバル変数にしておくとGUI上で調整できる
public float walkForce = 30f;
public float flyForce = 50f;
public float maxWalkSpeed = 3f;
public float maxFlySpeed = 5f;

void FixedUpdate()
{
     float h = Input.GetAxis("Horizontal");
     float v = Input.GetAxis("Vertical");

     //制限速度以下だったら、という条件を追加
     if(rigidbody2D.velocity.x < maxWalkSpeed)
     {
          rigidbody2D.AddForce(Vector2.right * h * walkForce);
     }
    
     //制限速度以下だったら、という条件を追加
     if(v > 0 && rigidbody2D.velocity.y < maxFlySpeed)
     {
          rigidbody2D.AddForce(Vector2.up * v * flyForce);
     }

     //制限速度より大きかったら
     if(Mathf.Abs(rigidbody2D.velocity.x) > maxWalkSpeed)
     {
          //自分の速度を制限速度に合わせる
          //飛ぶ動きは、重力がかかって勝手に減速するので、そのまま
          //Mathf.Sign -> 値の符号を取得
          rigidbody2D.velocity = new Vector2(
               Mathf.Sign(rigidbody2D.velocity.x) * maxWalkSpeed,
               rigidbody2D.velocity.y
          );
     }
}

進む方向に合わせてSpriteを反転する

キャラクターは、色々な方向に動けるようになりました。
右に進んでいるときは右、左を進んでいるときは左を向くようにします。

Spriteの反転ですが、Sprite はtransform のscale値が適用されるので、localScale.xを移動方向に合わせて変更します。

//右を向いているかどうか(初期値はtrue)
private bool facingRight = true;

void FixedUpdate()
{
     /* ... */

     float h = Input.GetAxis("Horizontal");

     //右を向いていて、左の入力があったとき、もしくは左を向いていて、右の入力があったとき
     if((h > 0 && !facingRight) || (h < 0 && facingRight))
     {
          //右を向いているかどうかを、入力方向をみて決める
          facingRight = (h > 0);
          //localScale.xを、右を向いているかどうかで更新する
          transform.localScale = new Vector3((facingRight ? 1 : -1), 1, 1);
     }
}

再生して、操作してみましょう!移動方向に合わせて、向きが切り替わるはずです。

右往左往

あとは、適当にCubeなどを置いて、ステージをつくってみてください。

3Dも

そういえば今回、ちょっと手抜きをして壁などをCubeでつくりましたが、カメラを切り替えると・・・

kotori3d

あっという間に、ステージだけ3Dに!これはこれで、いいかも。
(背景色は、Cameraの「Background」というプロパティで変えられます。)

Unityの2Dは、3Dとコードの違いもあまりなく、2つを簡単に混ぜることができるので、色々な表現が考えられて楽しいです。

記事は全6回と結構多くなってしまいましたが、コード自体は少ないので、
ここまで、慣れれば2〜3時間程度でできてしまうと思います。

サンプルのプロジェクトはこちらからダウンロードできます。

また、今回のサンプルはAssetStoreで公式で配布されているチュートリアルプロジェクト「2DPlatformer」を参考に制作しました。
一般的なジャンプの処理など(ことりは飛べるようにしてしまったので・・・)をつくりたい、という方は参考にしてみてください。
2Dのワークフローを紹介している、こちらも公式の、動画もあります。(日本語字幕つき!)

2dplatformer

2DPlatformer

年明けから、Unity講座第5期が開講されます。
「書籍やWeb上の情報だけではわからないことが多い」「1からしっかり勉強したい」という方におすすめです。
受講生募集中です!詳しくはこちら↓
unity講座バナー