actionScript書きの日記

アラフォーFlashデベロッパのブログ。actionscriptやobjective-cを経て、現在はUnity、Spine、AfterEffectsがメイン。

Unityちゃん (2D)を使用して、2Dゲームを作ってみる その5 床を配置する

一通りキャラクターの動き等やユーザー入力の受付が出来たので、いよいよ実際のゲームステージの作成の準備に入る。まずは、床の作成方法を確認していく。

 

固定床の作成

こちらは簡単に作成が可能になっている。Unityちゃん付属のドキュメントにも記載はあるが、こちらでもまとめておきたい。

まず、床として配置したいオブジェクトを作成する。任意のコライダーが付与されていれば、床として機能させることが可能だ。

 

今回は機能確認のみだったので、空のGameObjectを作成し、そのGameObjectにBoxCollider2Dを付与した。視認できるように、GameObject内にCubeを配置している。GameObjectの名称は「Floor」とした。 

f:id:goodbyegirl1974:20180422213050p:plain

 床として機能させるオブジェクトは、レイヤーをGroundに設定する必要がある。

自分はUnityちゃんのデータをインポートしたらレイヤーに「Ground」が自動で追加されていたが、ない場合は主導で追加する。

f:id:goodbyegirl1974:20180422213045p:plain

最後に、配置したPrefab「UnityChan2D」に付与されている「UnityChan2DController」のプロパティ「whatIsGround
」にレイヤー名「Ground」を設定する。

f:id:goodbyegirl1974:20180422213959p:plain

これで、設置した床に、Unityちゃんが着地するようになる。

移動床の作成

次に、移動する床をどのように設定するかを見ていきたい。

プラットフォーマーにおける移動床は、80年代の初代マリオから実装されている機能であるが、Unityちゃん2Dで移動床を実装しようとしたら個人的にはかなり苦戦した。色々試行錯誤した結果実装は可能になったが、改めて見てみると「なんでこんな単純な内容にあんなに苦戦したのか」と自分の能力のなさを嘆くばかりである。

ただ、そうした内容を記載しておくのも何かの役には立つかもしれないので、ここにそのプロセスを記載しておくことにする。

RigidBody2Dを使用する

まず、RigidBody2Dを床に付与し、そのRigidBody2D内のvelocityに任意の移動用のVector2の値を渡すという方法を試みた。以下のような処理。

public Rigidbody2D Rb2d;
void Start () {
   Vector2 vec = new Vector2();
   vec.x = 0.0f;
   vec.y = -3.0f;
   Rb2d.velocity = vec;
}

これで床は下降するようになるが、下降しはじめの際にキャラが一瞬浮いてしまう。


physics

床が方向転換して下降に転ずる際に、一瞬キャラのジャンプのアニメが再生されている。キャラクターの重力落下よりも床の下降速度が早いために、こうした現象が起こる。

次に 床に「SliderJoint2D」を付与し、そのMotorSpeedの値を変化させることで上昇・下降を制御しようとしたが、これも同様の現象が起こり、断念せざるを得なくなった。

そもそもがUnityChan2Dに付与されているRigidBody2Dの「Mass」(質量)の値をかなり小さくしないと、Unityちゃんが床に乗った際に床が揺れるなどの影響が出てしまう。意図的にそうした影響を出しているのならばよいが、意図しないものが出てしまうのはまずい。ことここに至って、RigidBody2Dを使用した物理演算によって床を動かすという方法は断念せざるを得なくなった。

ただ、Unity2017からはプラットフォーマーでの床を実装するための「Platform Effector 2D」なるコンポーネントが実装されている。 こうした機能が充実していけば、移動床に関するコンポーネントも早晩出てくるかもしれない。

Transformを使用して動かす

RIgidBody2Dを使えないとなると、Transformを使用して動かすしかない。具体的には、床に付与したスクリプトの「Update」関数内で、Transform.Translateを実行する。

「Start」関数内
vec = Vector3.up * 0.03f;
「Update」関数内
trf.Translate(vec);
    if(trf.position.y > 3.0f)
    {
        vec = Vector3.down * 0.03f;
    }
    else if (trf.position.y < -3.0f)
    {
        vec = Vector3.up * 0.03f;
    } 

「Start」関数内でvecの初期値を設定した後、「Update」関数内でvecを引数としてTranslateを実行し、必要に応じて方向転換の処理を入れる。これで床は動くようになるが、毎フレーム床はテレポートしているような状態になるので、物理演算の影響下には置かれなくなる。

この状態だと、やはり下降する際にキャラが浮いたりするので、キャラが床に着地した際にキャラの親オブジェクトを床に設定する。今回は床側のScriptに以下の処理を入れたが、本来はキャラの側のScriptに入れるのが筋だろう

//trfは床のTransform
private void OnCollisionEnter2D(Collision2D collision)
{
   collision.gameObject.transform.SetParent(trf);
}

private void OnCollisionExit2D(Collision2D collision)
{
   collision.gameObject.transform.SetParent(trf.parent);
}

この場合、「collision.gameObject」がキャラとなり、その親に床(のtransform)を設定する。床とキャラが離れた際には、キャラの親を元に戻している。

本来は、衝突判定が発生した相手がキャラであることを、タグやレイヤーなどを使用して確認、分岐する必要があるが、今回は確認用のファイルで床とキャラのみを配置している状態だったので、そのまま書いた。

この処理を入れることで、縦・横両方向の動きに対応する。床とともにキャラクターも移動してくれる形となる。

次回は、これらの床の機能を使用して、ゲームステージを設計してみる。