【簡単】Unityで3Dゲームを作ってみた

#はじめに
この記事は、この記事は、[SLP KBIT AdventCalendar2021] (https://adventar.org/calendars/6706) 16日目の記事です。
unityを使って、簡単な3Dゲームを作っていきます。

作ったゲーム→[ここをクリック](https://github.com/tus18/Mummy-Mon-Game)

# 目次
[1.用意するもの](#1-用意するもの)
[2.アセットの配置](#2-アセットの配置)
[3.キャラクターを動かす](#3-キャラクターを動かす)
[4.ゲームオーバー判定](#4-ゲームオーバー判定)
[5.クリア判定](#5-クリア判定)
[6.カメラの追尾設定](#6-カメラの追尾設定)
[7.シーンの遷移](#7-シーンの遷移)
[8.アニメーション](#8-アニメーション)
[9.おわりに](#9-おわりに)

# 1. 用意するもの
Unity Asset Store から必要なものをインポートします。必要なものは以下のものです。
・3Dキャラクター
・罠のアセット
・風景
どのアセットでもいいのですが、今回は無料の「[Free Mummy Monster](https://assetstore.unity.com/packages/3d/characters/free-mummy-monster-134212) 」、「[Dungeon Traps](https://assetstore.unity.com/packages/3d/environments/dungeons/dungeon-traps-50655)」、「[Free HDR Sky](https://assetstore.unity.com/packages/2d/textures-materials/sky/free-hdr-sky-61217)」を使います。

# 2. アセットの配置
まずは、シーンを作成します。
・Assets > DungeonTraps > Scene_DungeonTraps を開き、file > Save As… をクリックし「GameScene」と名前を付けて保存
・ステージのCubeをZ軸に拡大
・Cube の名前を「Ground」に変更
・Main Camera > Inspector から Animator を消去

次に、GameScene 内にアセットを配置していきます。
・Assets > amusedART > Mummy_Mon > Mummy_Mon をシーン内にドラック&ドロップで配置
・Assets > Skybox > Materials > Skybox_Sunset をシーン内にドラック&ドロップで配置
![2021-12-14 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/f8f7b005-8886-01d7-def9-a590a5b20c52.png)



# 3. キャラクターを動かす
キャラクターを動かすための作業をしていきます。
・Hierarchy > Mummy_Mon を選択
・Inspector > Add Component で Rigidbody 、Capsule Collider を追加
・Capsule Collider をキャラクターが中に入るように移動
・Project で右クリックし create > C# Script をクリック、「Move」と名前を付ける
・MoveスクリプトをMummy_monに取り付ける

```c#:Move
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move : MonoBehaviour
{
    public Rigidbody rd;
    //接地判定
    public bool OnGround { get; set; }
    // 前進速度
    public float forwardSpeed = 7.0f;
    // 後退速度
    public float backwardSpeed = 2.0f;
    // 旋回速度
    public float rotateSpeed = 2.0f;
    // ジャンプ威力
    public float jumpPower = 5.0f;
    //キャラクターの移動
    private Vector3 velocity;

    // Start is called before the first frame update
    void Start()
    {
        rd = GetComponent<Rigidbody>();
        rd.constraints = RigidbodyConstraints.FreezeRotation;     //転倒を防止
        OnGround = false;
    }
    // Update is called once per frame
    void Update()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        velocity = new Vector3(0, 0, v);
        velocity = transform.TransformDirection(velocity);
        if (v > 0.1)
        {
            velocity *= forwardSpeed;       // 移動速度を掛ける
        }
        else if (v < -0.1)
        {
            velocity *= backwardSpeed;  // 移動速度を掛ける
        }
        transform.localPosition += velocity * Time.fixedDeltaTime;
        transform.Rotate(0, h * rotateSpeed, 0);
    }
    private void FixedUpdate()
    {
        //接地判定時にジャンプ
        if (Input.GetKey(KeyCode.LeftShift) && OnGround)  //Shiftでジャンプ
        {
            rd.velocity = transform.up * jumpPower;
            OnGround = false;
        }
    }
}
```

このままでは接地判定が「true」にならないので、接地判定の続きを作ります。
・Mummy_Mon の足元に Cube を配置し、Mummy_Mon の子オブジェクトにする
・Is Trigger にチェック
![2021-12-14 (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/b4274bc6-d196-2c8c-cb49-e4749ad7e6bc.png)
・Project > Create > Materialをクリック、「Transparent」と名前を付ける
・Color>Aを0に変更
・Transparent を Cube に付ける
![2021-12-14 (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/1c86d449-c1ef-340a-9409-25f79846324b.png)

・Ground に「OnGround」タグをつける
・「GroundChecker」スクリプトを作成、 Mummy_Mon 足元にある Cube に取り付ける

```c#:GroundChecker
using UnityEngine;
using UnityEngine.Events;

public class GroundChecker : MonoBehaviour
{
    //接地した場合の処理
    public UnityEvent OnEnterGround;
    //地面から離れた場合の処理
    public UnityEvent OnExitGround;
    //接地数
    private int enterNum = 0;

    private void OnTriggerEnter(Collider collision)
    {
        Debug.Log("OnGround!");
        enterNum++;
        OnEnterGround.Invoke();
    }
    private void OnTriggerExit(Collider collision)
    {
        Debug.Log("ExitGround!");
        enterNum--;
        if (enterNum <= 0)
        {
            OnExitGround.Invoke();
        }
    }
}
```

・Inspector > GroundChecker を次のように変更
![2021-12-14 (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/4a7edf2e-9b7b-238b-2e95-1985f541b784.png)
これでキャラクターを動かすことが出来るようになりました。

# 4. ゲームオーバー判定
キャラクターがトラップに当たった時、ステージから落ちた時に「GameOver」と表示されるようにします。
・Ground の下に新しく Cube を配置し、「GameOverArea」と名前を付ける
・GameOverArea を Ground より大きくし、Transparentを取り付け透明にする
・GameOverArea に「GameOver」タグをつける
![2021-12-14 (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/a454f2b9-a361-09f0-62d3-0cc731ecfa13.png)
・「GameOverScript」を作成

```c#:GameOverScript
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameOverScript : MonoBehaviour
{
    public Text gameOverText;

    private void OnTriggerEnter(Collider other)
    {
        //死亡
        if (other.gameObject.tag == "GameOver")
        {
            Destroy(this.gameObject);
            gameOverText.text = "GameOver";
        }
    }
}
```

・Textを作成、「GameOverText」と名前を付ける
![2021-12-14 (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/1f685462-366d-bca9-eb19-6e22f567e53f.png)
・テキストが画面中央に表示されるよう調整する
調整が出来たら、テキストを消しておきます。

・Mummy_Mon > GameOverScript > GameOverText に GameOverText を付ける
![2021-12-14 (14)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/7bd1f3a2-6962-378d-7386-20ea4c6b1866.jpeg)
これで、ステージから落ちたら「GameOver」が表示されるようになりました。

次に、トラップに当たっても「GameOver」が表示されるようにします。
・トラップ一つ一つに Collider を付ける
基本 Box Collider を使います。形に合わない場合、Mesh Collider を付けるとトラップの形通りになります。しかし、Mesh Collider は重いためなるべく使わないようにしています。

・Collider > Is Trigger にチェックを付ける
・GameOver タグをつける

これでゲームオーバー判定は完成です。

# 5. クリア判定
ゲームをクリアした時、「Congratulations」と表示するようにします。
・コースの最後に Cube を配置、大きさを変更する
・「Congratulations」と名前を付ける
・「Congratulations」タグを付ける
・「CongratulationsScript」を作成、Mummy_Mon に付ける

```c#:CongratulationsScript
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CongratulationsScript : MonoBehaviour
{
    public Text CongratulationsText;
    private void OnTriggerEnter(Collider other)
    {
        //クリア
        if (other.gameObject.tag == "Congratulations")
        {
            Destroy(this.gameObject);
            CongratulationsText.text = "Congratulations";
        }
    }
}
```

・新しく Text を作成、「CongratulationsText」と名前を付ける
・Mummy_Mon > CongratulationsScript > CongratulationsText に CongratulationsText を付ける
![2021-12-14 (17)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/8fdeeeca-e574-a16a-2349-64782d7c400c.jpeg)
これで、クリア判定は完成です。

# 6. カメラの追尾設定
カメラがキャラクターについて行くように設定します。
・Main Camera を Mummy_Mon の子オブジェクトに設定
・Main Camera の位置、向きを変更
![2021-12-14 (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/d25569bb-ab5c-0084-e424-1b00ee0d60ee.png)

# 7. シーンの遷移
「R」ボタンでリトライ、「Escape」でゲーム終了の設定をします。
・「TransitoinScript」を作成

```c#:TransitoinScript
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class TransitoinScript : MonoBehaviour
{
    
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
#if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;   // UnityEditorの実行を停止
#else
            Application.Quit();                                // ゲームを終了
#endif
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            SceneManager.LoadScene("GameScene");
        }
    }
}
```

・Create Empty をクリック
・Game Object に TransitoinScript を付ける

次は、タイトルシーンを作り「Enter」でゲームをスタートする設定をします。
・Create > Scene をクリック、「TitleScene」と名前を付ける
・新しく「TransitionScript2」を作成
・Create Empty をクリック
・Game Object に TransitoinScript2 を付ける
![2021-12-15 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/e1543980-7ecc-580f-6a9e-9fe61e5abfaa.png)
（デザインは自由に作ってみてください。）

・File > Build Settings > Scenes In Build に GameScene , TitleScene を追加する
![2021-12-15 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/3f1422f8-67ec-c311-22b4-3b04756f9f43.png)


# 8. アニメーション
キャラクターが歩いているアニメーションを再生する設定をします。
・MUmmy_Mon > Animator > Contorollar に Mummy_Anim を付ける
![2021-12-15 (3)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367410/2e9e56ac-ba5d-5bc6-12d5-7fb2d330a1ba.jpeg)

# 9. おわりに
今回は、Unityの基本操作は省いています。詳しく知りたい場合は自分で調べてみてください。
読んでくださりありがとうございました。

参考サイト

Unity　キャラクター接地判定（空中ジャンプ禁止）
https://ingentity.hatenablog.com/entry/2018/04/30/182217
【Unity C#】ボタンをクリックすると画面が閉じるしくみ
https://futabazemi.net/notes/unity-button_exit/
【Unity C#】落下したらゲームオーバーになる仕組み
https://futabazemi.net/notes/unity-naraku/