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

こんにちは!布浦です。
Unityの2D機能をつかう企画、5回目です。

今日は、
「5. 地面に当たったかどうかを判定する(Physics2Dスクリプト編その1)」
をやっていきたいと思います。

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

地面に足がついているかを判定する仕組み

UnityのPhysicsクラスは、当たり判定を動的に便利な関数が揃っています。
使うのは、「Physics2D.Linecast」という関数です。

Physics2D.Linecastは、指定した2つの座標の間に線を引くイメージで、この線上にColliderが貼られたGameObjectがある場合trueを返してくれます。
この関数を利用して、キャラクターの足下付近に地面があるかどうかを調べます。

linecast

linecastによる接地判定

地上ならtrue、空中ならfalse

前々回、「キャラクターが地面に足がついているかどうか」を条件に、アニメーションを切り替える準備をしました。
前回、キャラクターに物理演算を適用して、重力で下に落ちるようにしました。
今回は、この2つを組み合わせて、物理演算で動くキャラクターのアニメーションが、状態によって切り替わるようにします。

スクリプトを書いてみる

キャラクターの動作用のコンポーネント(名前はなんでもいいです。サンプルではキャラクターが「ことり」なので、Kotoriクラスとしています)をつくって、キャラクターのGameObjectにはりつけます。

Kotori.cs

Kotori.cs

Kotoriコンポーネント

ことりにはりつけておく

using UnityEngine;
using System.Collections;

public class Kotori : MonoBehaviour
{
     //毎フレーム呼ばれる
     void Update()
     {
          //接地しているかどうかを判定する
          //自分の基点の少し上と少し下の2点を渡して、その間にColliderがあればtrueが返る
          bool grounded = Physics2D.Linecast(
               transform.position + transform.up * 1,
               transform.position - transform.up * 0.1f
          );
          //接地状態を出力する
          Debug.Log("grounded ->" + grounded);
     }
}

コードが書けたら、再生してみます。

Trueしか出力されない

空中でも地上でも、True しか出力されない・・・

この状態だと、1つ問題があるので、ずっとTrueとしか出力されません。

キャラクターのLayerを変更する

問題というのは、Physics2D.Linecast が、ことり自身のColliderも判定してしまうことです。

ことり自身のCollider

ことり自身のColliderは、常にLine上にある

Unityでは、GameObject にLayer を指定することができます。
主に当たり判定や描画の対象を絞り込むために使われます。

今回は、Physics2D.Linecastの引数でLayerを指定することで、接地判定するLayerを絞り込みたいと思います。
Kotoriクラス内のコードは以下のように修正します。

//接地判定する対象のLayer
public LayerMask groundLayer;

void Update()
{
     bool grounded = Physics2D.Linecast(
          transform.position + transform.up * 1,
          transform.position - transform.up * 0.1f,
          groundLayer
     );

     Debug.Log("grounded ->" + grounded);
}

UnityのGUI上で、「groundLayer」プロパティに値を入れます。

GroundLayerを設定

「Default」にチェック。ちなみに複数のLayerをチェックすることもできる

そして、キャラクター自身のLayerを、上記で「groundLayer」に指定したLayerとは別のものに変更します。

layer_default

Inspectorの上の方にLayerというプロパティがある

layer_addlayer

layer_chara

User Layer に名前を入力すると、Layerがつくられる

layer_charalayer

Layerをつくっただけで、指定していないということがよくあるので注意

再生して、ログを見てみると、
地面についた瞬間、trueになっています。

空中のことり

空中はFalse

地上のことり

地上はTrue

Animatorのパラメーターにプログラムで値を設定する

接地判定ができたので、アニメーションのパラメータに適用します。
ログを出力していた部分を書き換えます。1行だけです。

public LayerMask groundLayer;

void Update()
{
     bool grounded = Physics2D.Linecast(
          transform.position + transform.up * 1,
          transform.position - transform.up * 0.1f//,
          groundLayer
     );

     //Debug.Log("grounded ->" + grounded);
     
     //Animatorコンポーネントの「Grounded」プロパティに取得した接地状態を渡す
     GetComponent<Animator>().SetBool("Grounded",grounded);
}

再生してみましょう!
着地したときに、アニメーションが「Fly」から「Walk」に変化します。

ことり着地

次回、キー操作を追加して、サンプル完成です。

unity講座バナー
unity講座第5期、受講生募集中です〜