🕹️

Unityで3Dゲームを作成

2024/10/11に公開

右クリックしてWASDで移動が可能

フィールドの大きさを変更する

全部100にする

地形を作れる

色をつける

ディティールこれは地面に草を生やすことができる

草を生やした結果がこれ

Unityアセットストアからダウンロードする

https://assetstore.unity.com/

Add My Asetをクリック

Open in Unityをクリック

ダウンロードします

木を生やす
真ん中のマークをクリックしてEdit Trees->Add Treeをクリックして木のモデルを選択します。
Brush Sizeを決めてステージをなぞると木を生やせます!!

空を選択する
window->rendering->Environment->Skyboxを選択することで空を変えることができます

好きなスカイボックスを選択しましょう!!

Unityちゃんを配置する

ダウンロードすると色んなフォルダがありますが、今回使用するのはPrefabを使います。

ピンク色になっているので手直しが必要です。
一つはただのモデル
もう一つはdynamicになっています

Modelsを選択して

マテリアルズを開いてbodyを選択します

エラーシェーダーになっているのを治していきます


ボディー以外にもエラーシェーダーになっているものを修正していきます。

transpanrentじゃなくてstandardにすることで目が見えるようになります

Unityちゃんを自分たちで制御するためにインスペクターでチェックを外します

このままでは宙に浮いているので重力を設定してあげます

当たり判定を追加します

Edit Colliderで当たり判定を編集します

足元が丸くて転けちゃうのを防ぐ

スクリプトを追加する

アセットの下にscriptフォルダを作成する
ファイル名をPlayerMoveにして作成する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    // Update is called once per frame
    void FixedUpdate()
    {
        // 移動量を表す変数
        // XYZの3Dを表すための型です
        Vector3 move = Vector3.zero;

        // 前に移動
        // 指定されたキーば押されているか判定
        if (Input.GetKey(KeyCode.W)) {
            move.z = 50.0f;
        }
        // 後ろに移動
        if (Input.GetKey(KeyCode.S)) {
            move.z = -50.0f;
        }
        // 左に移動
        if (Input.GetKey(KeyCode.A)) {
            move.x = -50.0f;
        }
        // 右に移動
        if (Input.GetKey(KeyCode.D)) {
            move.x = 50.0f;
        }

        // moveの移動量をもとにキャラクターを移動
        Rigidbody rb = GetComponent<Rigidbody>();
        rb.AddForce(move);
    }
}

Add Componentで先ほど書いたスクリプトを追加します

カメラを制御する

カメラの情報を取得するスクリプトを書きます

GameObject camera;
// Start is called before the first frame update
void Start()
{
    // カメラの情報を取得
    camera = GameObject.Find("Main Camera");
    
}

カメラのベクトルに合わせてキャラクターを移動させるようにプログラムを修正しましょう。

void FixedUpdate()
{
    // XYZの3Dを表すための型です
    Vector3 move = Vector3.zero;

    // 移動量を表す変数
    // 正面
    Vector3 front = camera.transform.forward;
    // 右方向
    Vector3 side = camera.transform.right;
}

if (Input.GetKey(KeyCode.W)) {
    // 軸に沿っての移動しかできない
    // move.z = 15.0f;

    // ベクトルで示された方向に移動
    move += front * 15.0f;
}

カメラをキャラクターに追随するようにする

ヒエラルキーからカメラをキャラクターの下に移動する

カメラをマウスに合わせて操作する

まずはマウスの感度を調整する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMove : MonoBehaviour
{
    // カメラ感度の調整
    public float mouseSpeedX = 1.0f;
    public float mouseSpeedY = 1.0f;
    // Start is called before the first frame update
    void Start()
    {
        // この中で書くのがゲームのロード画面
    }

    // Update is called once per frame
    void Update()
    {
        // マウスの移動量を取得
        float mx = Input.GetAxis("Mouse X");
        float my = Input.GetAxis("Mouse Y");

        // カメラを回転させる
        transform.RotateAround(Vector3.up, mx * mouseSpeedX);
    }
}

transform.RotateAround(Vector3.up, mx * mouseSpeedX);
一つ目の引数では回転する軸を指定して、二つ目では回転量を表します

しかしこのコードではカメラがキャラクターの位置に関係なく、回転してしまいます。
キャラクターを中心に回転させるように修正していきましょう


public class CameraMove : MonoBehaviour
{
    // カメラ感度の調整
    public float mouseSpeedX = 1.0f;
    public float mouseSpeedY = 0.5f;

    GameObject player; // プレイヤーの情報
    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.Find("Player");
    }

    // Update is called once per frame
    void Update()
    {
        // マウスの移動量を取得
        float mx = Input.GetAxis("Mouse X");
        float my = Input.GetAxis("Mouse Y");

        // カメラを回転させる
        transform.RotateAround(
            Vector3.up, // 回転する軸の指定
            mx * mouseSpeedX // 回転する量
        );
        // 横回転した後に縦回転
        // 上下45度まで回転できるように制限
        transform.RotateAround(
            transform.right, //カメラの右方向
            my * mouseSpeedY
        );

        // カメラの位置を調整
        // カメラをプレイヤーと同じ位置に配置
        transform.position = player.transform.position;
        // 足元を映してしまうので、胸の高さまで移動
        transform.position += Vector3.up * 1.5f;

        // カメラの正面方向と反対の方向に移動
        // カメラをプレイヤーの後ろに配置
        transform.position += transform.forward * -3.0f;
    }
}

キャラクターにアニメーションをつける

右クリックしてMake トランディションで線を繋げるとアニメーションを切り替えることができる

手動でUnityのエディタで切り替えることはできますが、プログラムでやらせたいです。

アニメーションが1週してからじゃないと切り替わらないのを修正します
ここのチェックを外します

プレイヤーにジャンプさせる

ファイル名をPlayerMoveを編集

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    // UpdateはEditor上ではPCが出せる最高性能で動作する
    // FixedUpdateは実行ファイルと同じ速度で動作する
    void Update() {
        // ジャンプを追加する
        Rigidbody rd = GetComponent<Rigidbody>();
        if(Input.GetKeyDown(KeyCode.Space)) {
                rb.AddForce(0.0f, 10.0f, 0.0f, ForceMode.Impulse);
        }
    }

    void FixedUpdate()
    {...}
}

このままでは空中でもジャンプできてしまいます。そのため、地面に触れているかの判定でRayを飛ばして判定します。レーザーを足から飛ばして帰ってくる時間?で判定するものです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    // UpdateはEditor上ではPCが出せる最高性能で動作する
    // FixedUpdateは実行ファイルと同じ速度で動作する
    void Update() {
        // Ray(直線, 光線)
        // 地面にいるか判定
        Ray ray = new Ray(
            transform.position,
            new Vector3(0.0f, -1.0f, 0.0f) // 光線の出発点、光線の方向
        );

        // Rayのレーザーを使用して何かにぶつかったか判定
        RaycastHit result;
        bool isGround = false; // 地面にいるかフラグ
        // ray - 飛ばす光線の元データ
        // result - ぶつかった時の詳細な情報
        // 3.0f - 光線を飛ばす距離
        if(Physics.Raycast(ray, out result, 3.0f)) {
            // 地面までの距離を調べる
            if(result.distance < 0.3f) {
                isGround = true;
            } else {
                isGround = false;
            }
        }

        // ジャンプを追加する
        Rigidbody rd = GetComponent<Rigidbody>();
        if(isGround && Input.GetKeyDown(KeyCode.Space)) {
                rb.AddForce(0.0f, 10.0f, 0.0f, ForceMode.Impulse);
        }
    }

    void FixedUpdate()
    {...}
}

敵キャラクターを追加する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.AI;

public class Enemy : MonoBehaviour
{
    NavMeshAgent ai;
    GameObject player;
    // Start is called before the first frame update
    void Start()
    {
        ai = GetComponent<NavMeshAgent>();
        player = GameObject.Find("Player");
    }

    // Update is called once per frame
    void Update()
    {
        ai.SetDestination(player.transform.position);
    }
}

攻撃用のたまを追加する


ヒエラルキーを右クリックして3Dオブジェクトからスフィアを追加します。
リジッドボディーを追加し、ヒエラルキーからProjectにドラッグ&ドロップしてプレファブを作ります

マウスをクリックしたら弾のコピーを作成する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerShot : MonoBehaviour
{
    // 弾の情報を保存
    public GameObject prefab;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.Mouse0)) {
            Instantiate(prefab, transform.position, Quaternion.identity);
        }
    }
}

Instantiate(prefab, transform.position, Quaternion.identity);
第一引数がコピーするもの
第二引数がコピーする場所
第三引数が角度です。
キャラクターに先ほど作ったスクリプトを追加します。
そしてスクリプトにプレファブをドラッグ&ドロップで適用してあげます。

弾を飛ばすための処理を追加


    void Update()
    {
        if (Input.GetKey(KeyCode.Mouse0)) {
            GameObject copy = Instantiate(prefab, transform.position, Quaternion.identity);
            Rigidbody rb = copy.GetComponent<Rigidbody>();
            rb.AddForce(transform.forward * 100.0f, ForceMode.Impulse);
        }
    }

敵キャラクターを倒す処理を追加

ぶつかったものを削除する

public class Bullet : MonoBehaviour
{
    // 弾が何かに当たった時に呼ばれる関数
    void OnCollisionEnter(Collision collision) {
        Destroy(collision.gameObject);
    }
}


このままでは的キャラクター以外も消えてしまうので敵にタグを追加する

// 弾が何かに当たった時に呼ばれる関数
void OnCollisionEnter(Collision collision) {
    if (collision.gameObject.tag == "Enemy") {
        Destroy(collision.gameObject);
    }
}

カメラの方向に向けて弾を発射する

public GameObject camera;
rb.AddForce(camera.transform.forward * 40.0f, ForceMode.Impulse);

コードを追加したらプレイヤーのインスペクターのcameraにMain Cameraをセットします

Discussion