ひつじを動かそう その2 のバックアップソース(No.5)

#contents
*はじめに [#caf03486]
&size(18){[[ステージを作る]]};の続きです。
#br
これまでで羊をキー入力で操作できるようにして、ステージまで制作しました。
しかし今のままでは、ひつじの動きとステージがあっていませんね。
そのでこのページでは、ゲームに合わせたひつじの動きの完成版を作りましょう。
#br
*本格的にひつじを動かそう [#pb64733a]
#br
現段階ではひつじはA,Dキーの入力で左右に動かせるだけです。
しかしこれでは、ゲームになりません。
あと必要そうな機能は、
 1.重力の力を受ける
 2.キー入力に合わせてひつじの向きを変える
 3.キー入力でジャンプする
 4.ひつじにカメラ・背景が追従する
  があります。
では、1つずつ実装していきましょう。
#br
**ひつじに重力を与える [#u3672806]
#br
これは一度[[プロジェクトの作成]]でやりましたね。
ひつじのオブジェクトにインスペクターから「RigitBody2D」のコンポーネントを追加します。
追加の方法は覚えているでしょうか。
インスペクターの一番下にある「AddComponrnt」から「RigitBody2D」を探してクリックしてやればいいんでしたね。
これで重力が追加されたはずです。
実際動かしてみましょう。
ちゃんと、ステージのうえに立って、キー入力で左右に動くようになりましたか?
#br
しかし今の段階では、いくつか問題があります。
それは、
 ① 坂を上り下りしようとするとひつじが回転してしまう
 ② 壁に突っ込むとめり込んでしまう恐れがある
 ③ パソコンの性能差でひつじのスピードが変わってしまう
   というものです。
#br
①の問題は、坂に当たった時の物理演算をz軸に関しても行っているせいで坂とひつじの間の摩擦力によって回転してしまうのです。
そのため、z軸に関する物理演算を止めてあげる、つまり、ひつじをz軸回転しないように固定してあげる必要があります。
固定する方法は簡単で、ひつじのインスペクターからRigidBody2D > Constraints > FreezeRotation > Z にチェックを入れてあげます。
これだけです。
#br
②の問題は、「RigitBody2D」の物理演算の結果が、ひつじを左右に動かそうとするときに再計算されて衝突計算が無効になってしまうせいで起こります。
詳しく説明すると、「RigitBody2D」の物理演算は「MoveSeap.cs」の中にあるUpdate関数よりも先に計算されるようになっており、Update関数の中にある「Transform.position」による移動で衝突計算を再計算するようになっているんです。
この問題を解決するには、Update関数内で移動の計算を行わないようにしなければなりません。
ということで、以前作成したひつじを動かすプログラムの「MoveSeap.cs」を直していきます。
#br
#geshi(csharp,number){{
…
    private Rigidbody2D rigidBody = null;

    // Start is called before the first frame update
    void Start()
    {
        rigitBody = this.GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    { 
        Vector2 pos = rigitBody.position; //<=「This.transform」から「rigidBody」に

        if (Input.GetKey(KeyCode.D)) 
        {
            pos.x += speed;
        }

        if (Input.GetKey(KeyCode.A))
        {
            pos.x -= speed;
        }

        rigitBody.position = pos; //<=「This.transform」から「rigidBody」に
    }
}
}}
#br
このように書き換えてください。
Start関数の上にかいた "private Rigidbody2D rigidBody = null;" というのは、前にも一度やった変数の定義となります。
今回は、「Rigitbody2D」という型に「rigitBody」という名前を付けて定義しています。
#br
最後にある「null」というのは、「無効な値、何もない、ゼロ」という、無効な参照を表す特別な値です。
詳しくはこの後にやりますが、この変数にはゲームオブジェクトのコンポーネントを格納するために使います。ですが、ここではまだそのコンポーネントを取得していないので、一旦「null」という値を置きます。(特に書かなくもデフォルトで「null」が入ります。)
#br
最初の「private」というのは、アクセス修飾子の一種です。
アクセス修飾子というのは、簡単に言えばその変数を利用できる権限レベルを指定するためのものです。今回付けた「private」は最も厳しい制限で、このクラスの中でしか使えないようになります。
これがつくと、Unityのインスペクターからも見ることができない(もちろん編集できない)変数として定義することができます。
今回定義する変数は、ひつじの物理演算を司るコンポーネントを格納するということで、基本的に中身が変更しない変数になります。このような、変更のない変数、或いは変更されては困るような変数を定義するときに使います。
(以前使った「public」もアクセス修飾子の一つで、一番権限レベルの易しいものになります。ほかのプログラムやインスペクターからも操作できるため、中身を変更することがある場合は「public」をつけましょう。)
#br
次は、Start関数の中の"rigitBody = this.GetComponent<Rigidbody2D>();"です。
これは、ひつじについている「RigitBody2D」のコンポーネントを取得して、先ほど定義してあげた「rigitBody」に入れる、という操作になります。これで、「rigitBody」という、変数を通じてひつじについた「RigitBody2D」設定をゲームの最中でも変更できるようになりました。
#br
最後に、Update関数の中に2か所あった「This.trsnform」を「rigitBody」に置き換えてあげます。
こうすることで、これまでのゲームオブジェクトの位置を直接変える操作から、「RigitBody2D」の物理エンジンによる操作に切り替えることができます。
これで、キー入力での左右の移動を、これまで先に計算されていた「RigitBody2D」での物理演算と一緒に演算できるようになりました。
つまり、衝突演算等が再計算されることはなくなったわけです。
このように、ゲームオブジェクトに物理的な操作(重力、衝突など)をする際は、できるだけ「transform」による操作よりも「RigidBody」による操作をするようにしましょう。
#br
最後に③の問題を解決しましょう。
#br
#geshi(csharp,number){{
…
    //Update関数の中

        if (Input.GetKey(KeyCode.D)) 
        {
            pos.x += speed * Time.deltaTime; //「* Time.deltaTime」を追加
        }

        if (Input.GetKey(KeyCode.A))
        {
            pos.x -= speed * Time.deltaTime; //「* Time.deltaTime」を追加
        }
…
}}
#br
このように、「position」の加減の際に「Time.deltaTime」をかけてあげます。
少し説明すると、「Time.deltaTime」とは、前回のフレームから現在までの時間を表します。
Unityでは、処理の負荷が軽くかったり、重かったりするとフレームの長さが変わってしまいます。
またゲームをプレイするデバイスの性能差によっても、距離能力の差でフレームの長さにばらつきが出てきます。
そこで、加減の際に「speed」に「Time.deltaTime」をかけてあげることで、フレーム間隔が短いときはその分遅く、長いときは早くしてあげることで、フレームの長さに関係なく一定の速さで動くように見せることげできます。
#br
**キー入力で左右で反転させる [#f790d98c]
#br
次は、ひつじの画像を進む方向が正面になるようにキー入力に合わせて反転させる機能を追加します。

#br
**ジャンプできるようにする [#w0f37d00]
#br 

#br
次は、キー入力によるジャンプ機能を追加します。