ミニゲーム作成2　地面とプレイヤーの作成 (GapDush_2)

こんにちは．

↓ 前の記事

https://qiita.com/tdtiger/items/73b18b575e306bcd3819

今回は，タイトルにもあるように地面とプレイヤーを作成していこうと思います．
では早速，地面から始めていきます．

## 地面
まずはUnity Hubを開いて，このゲーム用のプロジェクトを作成します．
NewProject → All templates → 2Dを選択します．
すると，長い長いロードの後，下の画像のような画面に遷移すると思います．
![Unityの画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/3758a474-1f06-435a-7d16-777f6d06a99a.png)

この画面の説明や，細かい設定等はたくさんの方がわかりやすい説明記事を公開されていますので，そちらを参考にしていただくことをお勧めします．

次に，ヒエラルキービュー(画面右半分の内，一番左のタブ)内で右クリック，もしくは"+"ボタンをクリックすると，以下のようなウィンドウが表示されると思います．
![オブジェクト等の作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/dfb41a17-6fcc-7a73-686e-3d13eb4e4d11.png)
ここから，2D object → Sprites → Squareを選択します．
すると，以下のように，画面左下の青背景しかなかった部分に白い正方形が現れます．
![スクリーンショット 2024-11-04 160336.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/4a4dd9c8-dda7-536c-d36c-2955155d7008.png)
この時，名前が変更できるようになっているので，わかりやすい名前を付けておきましょう．(ここでは，"Ground"としました．)
あとはこの正方形が選択されている状態で，画面一番右のインスペクタービューで座標，スケール，色等を変更してやると，以下のようになります．
![各パラメータの値](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/4480798e-e274-9c6d-5459-d38534f8de06.png)
各パラメータの値
![ゲームビュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/62bd4641-cdc4-2047-3f7c-e869ce554c63.png)

このままでは当たり判定が存在しないため，後にプレイヤーを作成したとしてもすり抜けてしまいます．
そのため，インスペクタービュー下部より， Add Component → Box Colider 2Dを選択してオブジェクトにアタッチすることで当たり判定を付与します．(特にパラメータの値を変更する必要はありません．)

https://docs.unity3d.com/ja/2021.3/Manual/class-BoxCollider2D.html

これで一先ず，地面の作成は完了です．

## プレイヤー
まず，プレイヤーの素材の絵を描きました．

![human.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/bfbd993c-9f62-3b24-cb26-c8db8166fb31.png)←仮作成として，こんな絵を描きました．小さくてごめんなさい．

絵の描画には，「TAKABO SOFT」さんの「EDGE」という無料のソフトを使用しました．
過去に大学の講義で自分のパソコンにインストールしていたため，その時のものを利用しました．

https://takabosoft.com/edge

素材が準備できたらUnityでの作業に移ります．
地面と同じようにSquareを作成し，名前を変更します．(ここでは，"Player"としました．)
そして，座標やスケールを調整した後，こちらにもBox Colider 2Dをアタッチします．
それに加えて，Rigid Body 2Dというコンポーネントもアタッチします．
これは，簡潔に言うとオブジェクトに物理法則を適用するためのコンポーネントで，アタッチすることにより，スクリプト等で力を加えたときにオブジェクトを動かせるようになります．

https://docs.unity3d.com/ja/2018.4/Manual/class-Rigidbody2D.html

状態として，"Dinamic"，"Kinematic"，"Static"の3つがあり，それぞれの仕様を簡潔にまとめた表を以下に示します．
| 状態 | 仕様 |
|-|-|
| Dinamic  | 重力など，すべての力の影響を受ける  |
| Kinematic  | 重力などの力を受けないが，スクリプトによる位置指定で動かせる  |
| Static | 外部からの影響を一切受けず，全く動かないが，処理は軽い|

続いて，プレイヤーを操作するためのスクリプトを作成します．
整理のために，プロジェクトビュー内のAssetsフォルダ内にScriptsというフォルダを作成し，その中で右クリック → Create → C# Script でC#スクリプトを作成します．
ここでも，オブジェクトを作成したときと同様に名前が変更できるので，アタッチする予定のオブジェクトと同じ名前にしておきます．(ここでは"Player"としています．)
その状態で，ヒエラルキービュー内の"Player"を選択し，先ほど作成したPlayerスクリプトを"Add Component"ボタンのあたりに向かってドラッグ&ドロップすることで，Playerオブジェクトにスクリプトをアタッチできます．

以下のようになっていればOKです．(1枚の画像内に収めるために全てのコンポーネントの設定画面を閉じています．)
![Playerの現状](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/99c0bcc7-fcdf-1892-dcc5-5ad2d408165a.png)

それではいよいよ，スクリプトを記述していきます．
先ほど作成したPlayerスクリプトを選択し，インスペクタービューの"Open"をクリックする，もしくはエクスプローラーから直接ファイルを開きます．
![スクリプトを開く](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/25d2d896-ba5e-06aa-9188-4d3f71faa416.png)

すると，初期状態では以下のようになっていると思います．
``` C#:Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
    
    }
}
```
`Start()`関数は，そのオブジェクトが生成されたタイミングで一回だけ実行されるものと解釈しています．(誤りがあったらすみません)

https://docs.unity3d.com/ja/560/ScriptReference/MonoBehaviour.Start.html

`Update()`関数は，オブジェクトが有効である間，毎フレームごとに呼び出されます．

https://docs.unity3d.com/jp/current/ScriptReference/MonoBehaviour.Update.html

独自に追加したい変数や関数がある場合は，Playerブロック内に記述します．
それでは，必要な記述を終えた後の`Player.cs`の内容を以下に示します．

``` C#:Player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField]
    private int moveSpeed;
    private Rigidbody2D rb;

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

    // Update is called once per frame
    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        rb.velocity = new Vector2(horizontal * moveSpeed, rb.velocity.y);
    }
}
```
まず，7，８行目に`[SerializeField]`という記述とともに，`moveSpeed`という`int`型のプライベート変数を宣言しています．これは，方向キーが入力された時にプレイヤーをどれだけ移動させるのかを設定するための変数です．
ここで，`[SerializeField]`は，直下で宣言した変数の値をUnity側で変更できるようにするための記述です．このように記述することで，Playerオブジェクトのインスペクタービューに`moveSpeed`が表示され，わざわざスクリプトを書き直さずとも値を変更できるようになります．便利．

![スクリーンショット 2024-11-06 161918.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922668/5c7e4059-db38-5c11-2cd8-97ea15980533.png)

↑一先ず値は2にしています．

9行目では，`RigidBody2D`型(という表現であってるのか?)の`rb`という変数を宣言しています．これは，先程PlayerオブジェクトにアタッチしたRigid Body 2Dを操作するための変数です．
14行目にある，`Start()`関数内の記述によって，`rb`でPlayerオブジェクトにアタッチされているRigid Body 2Dを操作できるようになります．

https://docs.unity3d.com/ja/2018.4/ScriptReference/GameObject.GetComponent.html

20行目では，`float`型の`horizontal`という変数を宣言しています．これは，右辺の`Input.GetAxis()`により取得した値を格納するための変数です．
この`Input.GetAxis()`は，キーボードの矢印キーが押された時に，そのキーに応じて値を返す関数です．引数として`"Horizontal"`が渡された場合は左右の入力に対応し，`←`が入力されたときは-1以上の負の値を，`→`が入力されたときは1以下の正の値を返します．`Vertical`が渡された場合は上下の入力に対応し，`↓`が入力されたときは-1以上の負の値を，`↑`が入力されたときは1以下の正の値を返します．
どちらも，極小の値から始まり，キーが押されている時間が長くなるにつれて，-1あるいは1に値が近づいていきます．
そして，21行目が実際にプレイヤーを動かす部分です．
左辺の`rb.velocity`は，あらかじめ取得したPlayerオブジェクトのRigid Body 2Dコンポーネントのvelocity，すなわち速度にアクセスすることを意味しています．ここに格納されるのは，`horizontal * movespeed`という値をx成分に，`rb.velocity.y`という値をy成分にもつベクトルです．
    x成分について，`Input.GetAxis("Horizontal")`によって得られる，左が負の値，右が正の値という関係は，座標空間(数直線と言うべきか?)における正負の関係と一致しているので，それに移動量を表す`moveSpeed`をかけてやればよいという訳です．
    y成分については，特に上下の移動を変更させる必要はないため，y方向の速度をそのまま代入しています．つまり0ですね．


## まとめ
今回は，地面とプレイヤーの作成を行いました．
画面上部中央にある，再生ボタンをクリックすれば，プレイヤーを`←`キー，`→`キーで操作できるようになっているのではないかと思います．
次回は，ゲームマネージャーの細かい機能を除いた，基礎部分を作ろうと思います．

スクリプトの説明はどうするのが最適なんだろう．．．
あと，改行とかどの程度入れるべきなのかを他の方の記事を見て勉強しないと．

↓次の記事

https://qiita.com/tdtiger/items/1f6b78ce35b34c61f375

## 参考にさせていただいた記事

https://mogi0506.com/unity-rigidbody2d/

https://mogi0506.com/unity-rigidbody-bodytype/

https://tech.pjin.jp/blog/2021/01/13/unity_csharp_getaxis/

https://qiita.com/RyotaMurohoshi/items/7868752a3f056affa2df