ユニティちゃんの2D横スクロールアクション(その2:キャラの移動)【チュートリアル】

ども、ゴコーです。
前回の続きです。今回は前回作成したキャラを歩かせてみましょう。
今回もある程度触ったことのある人向けに書いて行きます。

移動はRigidbody2Dを使います。理由はTransformを使って移動させるとめりこみとか色々とバグが起こるからです。
検証はまたの機会に。
と言うことでRigidbody2Dを使って移動用のスクリプトを書いてみましょう。

移動に必要な要素は

  • 入力に応じて左右に動くこと
  • 重力があること
  • 当たり判定があり地面に立てること

くらいでしょうか?

UnityChanController.cs

[csharp]

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))]
public class UnityChanController : MonoBehaviour {

public Rigidbody2D cRigidbody2D
{
get
{
if(!_cRigidbody2D)
_cRigidbody2D = rigidbody2D;
return _cRigidbody2D;
}
}
Rigidbody2D _cRigidbody2D;

public float moveSpeed = 5;

void FixedUpdate()
{
Move();
}

void Move()
{
cRigidbody2D.velocity = new Vector2(moveSpeed * Input.GetAxisRaw("Horizontal"),
cRigidbody2D.velocity.y);
}
}

[/csharp]

こんな感じでしょうか。上の3つの要素について見ていきます。


  •  重力があること

これはRigidbody2Dがあれば解決します。

[csharp]
[RequireComponent(typeof(Rigidbody2D))]
[/csharp]

を書いておけばコンポーネントのアタッチ忘れや、間違えてRemoveComponentすることも避けられます。


  •  当たり判定があり、地面に立てること

当たり判定もBoxCollider2Dがあれば解決です。

[csharp]
[RequireComponent(typeof(BoxCollider2D))]
[/csharp]

を書いておけば(ry


  •  入力に応じて左右に動くこと

入力にはInputクラスを使います。

[csharp]
Input.GetAxisRaw()
[/csharp]

は上下左右の入力に対応しています。
GetAxis()がジョイスティックなどでの半倒しと言った、中途半端な入力でも受け付けて0~1を返するのに対して、
GetAxisRaw()は0か1しか返しません。
今回は”Horizontal”で左右の入力の値を返してね、というのを指定しています。

実際の移動にはRigidbody2Dのvelocityに代入することで活用します。
FixedUpdate()内で実行しないのは、後でバグが出たときに確認しやすくする、切り分けておくと拡張しやすい、などの理由ですね。


Rigidbody2Dを使う時に、いつも使っている時は

[csharp]
rigidbody2D
[/csharp]

ではないでしょうか?
この時、毎回処理的に重いと言われているGetComponent<>()が走ってるので予めキャッシュしておくことをオススメします。
さらに、プロパティにしておけば呼ばれた瞬間に1回だけGetComponent<>()するからStart()内などでまとめて行うのと比べてタイミングも被らない(=軽くなる)し、読み取り専用。
という感じで大変素晴らしいわけです。

分からない人はとりあえず書いておきましょう。解説はまたの機会に。


とまあこんな感じです。

分からない人はコピペでも良いですね。
初心者の失敗として

「スクリプトを丸ごとコピペしたけどスクリプト名と一致させるのを忘れる」

というものがありますので注意して下さい。僕は良くやってました。


Unityのエディターに戻りましょう。
いくつか設定しておく事があります。

まず、前回作成したユニティちゃんのオブジェクトの名前を「ユニティちゃん」に変えておきましょう。

uni-tuto-2-0

名前の変更は僕の知っている限りで3つ方法があります。
オブジェクトをヒエラルキーウィンドウで選択後

  • ちょっと間を空けてから再度クリック
  • F2キーを押す
  • インスペクターウィンドウで一番上に表示される名前をクリック

で名前が選択されます。ちなみに僕はF2派です。
後は好きにリネーム、今回なら「ユニティちゃん」ですね。


次に地面を作りましょう。

uni-tuto-2-1

ヒエラルキーウィンドウの左上から
「Create > Cube」の順に選択して下さい。

すると Cube が設置されました。
選択してインスペクターウィンドウから場所をユニティちゃんの下の方に、スケールのXを大きめに設定してみて下さい。

「Cube黒くて不気味だな…」とか思う人はCubeと同じようにDirectional light を設置しておきましょう。

ここで、ユニティちゃんに先ほどのスクリプトをAddComponentしたか確かめてから一度実行してみてください。

uni-tuto-2-2

この画像のようにCubeを突き抜けてしまった人が正解です。

Unityには当たり判定を簡単に付けられる機能が揃っていますが、2D用の当たり判定と3D用の当たり判定はぶつかりません。
これは、そもそもぶつかるように作られていないので当たり前です。
Cubeには元々当たり判定がついていますが、それが3D用の当たり判定だったのでぶつからなかったのですね。

そこで、Cubeの当たり判定を入れ替えましょう。

uni-tuto-2-3

まずは、元々ついている当たり判定を消します。
上記の様に、2Dと3Dは一緒に使える設計にはなっていないので最初にAddComponentしようとしても無理だからです。

uni-tuto-2-4

その後AddComponentです。
BoxCollider2Dを選択しましょう。


これで地面を歩けます。実行してみましょう!
が、地面から少し浮いてしまっている上に、棒立ちのままですね…。
修正を加えましょう。

cRigidbody2Dの下に2行ほど空けて

[csharp]

public Transform cTransform
{
get
{
if(!_cTransform)
_cTransform = transform;
return _cTransform;
}
}
Transform _cTransform;

[/csharp]

と書いて下さい。
こちらも上記のRigidbody2Dの時と同じようにTransformをキャッシュしてます。


次にMove()の一番上に

[csharp]

if((cTransform.localScale.x > 0 && Input.GetAxisRaw("Horizontal") < 0)
|| (cTransform.localScale.x < 0 && Input.GetAxisRaw("Horizontal") > 0))
{
Vector2 temp = cTransform.localScale;
temp.x *= -1;
cTransform.localScale = temp;
}

[/csharp]

と書き加えて下さい。
これの内容は、キャラが右を向いている様に見える時(=localScale.x > 0)に左を押された時、またはその逆の時はスケールを反転させる、と言うものです。

uni-tuto-2-6 uni-tuto-2-7

C#の場合、JavaScriptとは違い、Vector2の様なUnity既存の構造体の x だけ書き換える、みたいなことはできません。

そこで、今回はローカル変数に一時的に値を取っておいて反転してから返す、というやり方で反転させてます。


これで左右の反転はするようになりました。
次に、微妙に浮いている問題を解決しましょう。これは簡単です。

uni-tuto-2-5

ユニティちゃんを選択するとシーンウィンドウで当たり判定が表示されます。
それを見つつBoxCollider2Dの Size という値の X と Y をキャラにあった大きさに調整するだけです。

なぜこんな大きさなのかという話。
このユニティちゃんは元々スプライトという、大きな画像を分割した画像の中の1つでした。
ユニティちゃんの周りには見えないけれど画像情報(透明)があります。
そして、当たり判定はその画像情報を元に作られます。

だから当たり判定はユニティちゃんより大きくなってしまうんですね。
見た目と同じになる3Dとは違う点です。

さあ、これで左右反転が自由にできるようになりました。
アニメーションがまだですが、それはジャンプができてからにしましょう。

では、また。

なんだかんだで初心者を意識してがっつり書いてることに気づく。じ、時間が…足りぬ

Comments

comments

スポンサーリンク
336*280px

コメント

  1. micro より:

    ユニティーちゃんの移動はできましたが、浮いたままです。
    どうしたらいいでしょうか?

    • backlight1144 より:

      では
      ・Rigidbody2Dコンポーネントがアタッチされているか確認する
      ・Rigidbody2DのisKinematicが有効になっていないか確認する(有効だと物理挙動できない)
      ・gravidyScaleが0になっていないか確認する(これが0だと重力が0になってしまう)
      等を試して下さい。
      あとは、
      cRigidbody2D.velocity = new Vector2(moveSpeed * Input.GetAxisRaw(“Horizontal”),
      cRigidbody2D.velocity.y);
      の部分が正しく書かれているか確かめてください。

  2. ガンダム より:

    いきなりで申し訳ありません
    Assets/UnityChanController.cs(1,11): error CS0178: Invalid rank specifier: expected ,' or ]’
    とでてしまいうごいてくれません。どうすればよいでしょうか??

  3. ガンダム より:

    連投すみません;改のほうの記事の方法をしたらそれっぽくできました;すみませんでした;エラーはでたのですがそれっぽい処理をできたので大丈夫です;申し訳ありません。チュートリアルの続編楽しみにしています^^

  4. gonta-ga より:

    ありがとうございました!
    めっちゃ助かりました