【基本操作】倉庫番~2/2 オブジェクト制御【パズル】

●プレイヤー制御

▷スクリプト整理

スクリプト格納用のフォルダを作成します。

【スクリプト整理】スクリプト格納用のフォルダを作成
  1. プロジェクトの「Assets」を右クリックし、「作成>フォルダー」をクリック
  2. 「Scripts」と入力し、ENTERキーを押す

▷ゲーム管理作成

空オブジェクトを作成し、ゲーム管理とします。

【ゲーム管理作成】空オブジェクトを作成し、ゲーム管理とする
  1. ヒエラルキー左上の「+」をクリックし、「空のオブジェクトを作成」をクリック
  2. 「GameManager」と入力し、ENTERキーを押す
  3. CTRLキーを押しながらSキーを押す

▷プレイヤー認識

プレイヤープレハブにタグ「Player」を割り当てます。

【プレイヤー認識】プレイヤープレハブにタグ「Player」を割り当てる
  1. ヒエラルキーの「Player」右端にある「>」をクリック
  2. インスペクターのタグドロップダウンを開き、「Player」をクリック
  3. ヒエラルキーの左上にある「<」をクリック

▷プレイヤー移動

スクリプト「GameManager」を作成し、ゲーム管理に割り当てます。

【プレイヤー移動】スクリプト「GameManager」を作成し、ゲーム管理に割り当てる
  1. プロジェクトの「Assets>Scripts」を右クリックし、「作成>C# スクリプト」をクリック
  2. 「GameManager」と入力し、ENTERキーを押す
  3. ヒエラルキーの「GameManager」をクリック
  4. プロジェクトの「Assets>Scripts>GameManager」をインスペクターの「コンポーネントを追加」にドラッグ&ドロップ
  5. CTRLキーを押しながらSキーを押す

▷プレイヤー移動

プロジェクトの「Assets>Scripts>GameManager」をダブルクリックし、プレイヤーを動かすスクリプトを記述します。

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

public class GameManager : MonoBehaviour
{
    GameObject player;
    Vector3 prevPos;
    Vector3 nextPos;
    int count;
    int maxCount = 16;

    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        prevPos = player.transform.position;
        nextPos = player.transform.position;
        count = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (prevPos == nextPos)
        {
            Vector3 addPos = new Vector3(0, 0, 0);
            addPos.x = Input.GetAxisRaw("Horizontal");
            if (addPos.x == 0)
            {
                addPos.z = Input.GetAxisRaw("Vertical");
            }

            nextPos = player.transform.position + addPos;
        }
    }

    void FixedUpdate()
    {
        if (prevPos != nextPos)
        {
            count++;
            if (count == maxCount)
            {
                player.transform.position = nextPos;
                prevPos = nextPos;
                count = 0;
            }
            else
            {
                Vector3 addPos = (nextPos - prevPos) * (1.0f / maxCount);
                player.transform.position += addPos;
            }
        }
    }
}

▷動作確認

プレビューし、プレイヤーがオブジェクトを無視して上下左右に動くことを確認します。

【動作確認】プレビューし、プレイヤーがオブジェクトを無視して上下左右に動くことを確認
  1. エディタ上中央の「▶」をクリック
  2. 矢印キーでプレイヤーが上下左右に動くことを確認
  3. 壁や荷物を無視して進むことを確認
  4. エディタ上中央の「▶」をクリック

●オブジェクト制御

▷荷物認識

タグ「Pack」を作成して荷物プレハブに割り当てます。

【荷物認識】タグ「Pack」を作成して荷物プレハブに割り当てる
  1. ヒエラルキーの「Packs」左にある「▶」をクリック
  2. ヒエラルキーの「Packs>Pack」の右端にある「>」をクリック
  3. インスペクターのドロップダウン「タグ」をクリック、「タグを追加…」をクリック
  4. インスペクターのタグ右下の「+」をクリック
  5. 「Pack」と入力し、ENTERキーを押す
  6. ヒエラルキーの「Pack」をクリック
  7. インスペクターのドロップダウン「タグ」をクリック、「Pack」をクリック
  8. ヒエラルキーの左上にある「<」をクリック
  9. CTRLキーを押しながらSキーを押す

▷壁認識

タグ「Block」を作成して壁プレハブに割り当てます。

【壁認識】タグ「Block」を作成して壁プレハブに割り当てる
  1. プロジェクトの「Assets>Prefabs>Block」をダブルクリック
  2. インスペクターのドロップダウン「タグ」をクリックし、「タグを追加…」をクリック
  3. インスペクターのタグを展開し、右下の「+」をクリック
  4. 「Block」と入力し、ENTERキーを押す
  5. ヒエラルキーの「Block」をクリック
  6. インスペクターのドロップダウン「タグ」をクリックし、「Block」をクリック
  7. ヒエラルキーの左上にある「<」をクリック

▷移動制限

プロジェクトの「Assets>Scripts>GameManager」をダブルクリックし、壁や荷物にぶつかったら進めないようにするスクリプトを記述します。

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

public class GameManager : MonoBehaviour
{
    GameObject player;
    Vector3 prevPos;
    Vector3 nextPos;
    int count;
    int maxCount = 16;

    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        prevPos = player.transform.position;
        nextPos = player.transform.position;
        count = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (prevPos == nextPos)
        {
            Vector3 addPos = new Vector3(0, 0, 0);
            addPos.x = Input.GetAxisRaw("Horizontal");
            if (addPos.x == 0)
            {
                addPos.z = Input.GetAxisRaw("Vertical");
            }

            GameObject obj = GetObject(player.transform.position + addPos);
            if (obj == null)
            {
                nextPos = player.transform.position + addPos;
            }
        }
    }

    void FixedUpdate()
    {
        if (prevPos != nextPos)
        {
            count++;
            if (count == maxCount)
            {
                player.transform.position = nextPos;
                prevPos = nextPos;
                count = 0;
            }
            else
            {
                Vector3 addPos = (nextPos - prevPos) * (1.0f / maxCount);
                player.transform.position += addPos;
            }
        }
    }

    GameObject GetObject(Vector3 pos)
    {
        GameObject[] packs = GameObject.FindGameObjectsWithTag("Pack");
        for (int i = 0; i < packs.Length; i++)
        {
            if (packs[i].transform.position == pos)
            {
                return packs[i];
            }
        }

        GameObject[] blocks = GameObject.FindGameObjectsWithTag("Block");
        for (int i = 0; i < blocks.Length; i++)
        {
            if (blocks[i].transform.position == pos)
            {
                return blocks[i];
            }
        }

        return null;
    }
}

▷動作確認

プレビューし、壁や荷物にぶつかって進めないことを確認します。

【動作確認】プレビューし、壁や荷物にぶつかって進めないことを確認
  1. エディタ上中央の「▶」をクリック
  2. 矢印キーでプレイヤーが上下左右に動くことを確認
  3. 移動先が壁や荷物の場合、進めないことを確認
  4. エディタ上中央の「▶」をクリック

▷荷物移動

プロジェクトの「Assets>Scripts>GameManager」をダブルクリックし、押した先に何もなければ荷物を押せるようにするスクリプトを記述します。

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

public class GameManager : MonoBehaviour
{
    GameObject player;
    Vector3 prevPos;
    Vector3 nextPos;
    int count;
    int maxCount = 16;
    GameObject pushPack;

    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        prevPos = player.transform.position;
        nextPos = player.transform.position;
        count = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (prevPos == nextPos)
        {
            Vector3 addPos = new Vector3(0, 0, 0);
            addPos.x = Input.GetAxisRaw("Horizontal");
            if (addPos.x == 0)
            {
                addPos.z = Input.GetAxisRaw("Vertical");
            }

            GameObject obj = GetObject(player.transform.position + addPos);
            if (obj != null && obj.CompareTag("Pack"))
            {
                if (GetObject(player.transform.position + addPos + addPos) == null)
                {
                    pushPack = obj;
                }
            }

            if (obj == null || pushPack != null)
            {
                nextPos = player.transform.position + addPos;
            }
        }
    }

    void FixedUpdate()
    {
        if (prevPos != nextPos)
        {
            count++;
            if (count == maxCount)
            {
                player.transform.position = nextPos;
                if (pushPack != null)
                {
                    pushPack.transform.position = nextPos + (nextPos - prevPos);
                    pushPack = null;
                }
                prevPos = nextPos;
                count = 0;
            }
            else
            {
                Vector3 addPos = (nextPos - prevPos) * (1.0f / maxCount);
                player.transform.position += addPos;
                if (pushPack != null)
                {
                    pushPack.transform.position += addPos;
                }
            }
        }
    }

    GameObject GetObject(Vector3 pos)
    {
        GameObject[] packs = GameObject.FindGameObjectsWithTag("Pack");
        for (int i = 0; i < packs.Length; i++)
        {
            if (packs[i].transform.position == pos)
            {
                return packs[i];
            }
        }

        GameObject[] blocks = GameObject.FindGameObjectsWithTag("Block");
        for (int i = 0; i < blocks.Length; i++)
        {
            if (blocks[i].transform.position == pos)
            {
                return blocks[i];
            }
        }

        return null;
    }
}

▷動作確認

押した先に何も無ければ荷物荷物が押せることを確認します。

【動作確認】プレビューし、壁や荷物にぶつかって進めないことを確認
  1. エディタ上中央の「▶」をクリック
  2. 矢印キーでプレイヤーが上下左右に動くことを確認
  3. 移動先に壁が無ければ荷物を押せることを確認
  4. 移動先に壁がある場合は荷物が押せないことを確認
  5. エディタ上中央の「▶」をクリック

●ゲーム制御

▷クリアUI作成

クリア用のUIテキストを非アクティブで配置します。

【クリアUI作成】クリア用のUIテキストを非アクティブで配置する
  1. ヒエラルキー左上の「+」をクリックし、「UI>テキスト – TextMeshPro」をクリック
  2. TMP Importerの「Import TMP Essentials」をクリック
  3. TMP Importerを閉じる
  4. ヒエラルキーの「Text (TMP)」をクリック
  5. F2キーを押して「TextClear」と入力し、ENTERキーを押す
  6. インスペクターを以下のように設定
  7. ・RectTransformの左上にあるアンカープリセットをクリックし、「stretch – stretch」をダブルクリック
  8. ・RectTransformの「上下左右」を(0, 0, 0, 0)に設定
  9. ・TextInput下のテキスト入力を(Clear)に設定
  10. ・Font Styleの「B」をオンにする
  11. ・Auto Sizeにチェックを入れる
  12. ・Vertex Colorにあるカラーバーをクリックし、色ダイアログの16進数を「FFFF00」に設定
  13. ・色ダイアログの右上にある「×」をクリック
  14. ・Alignmentの「Center、Middle」をオンにする
  15. ・Outlineにチェックを入れる
  16. ・OutlineのColorにあるカラーバーをクリックし、HDRカラーダイアログのRを(255)に設定
  17. ・HDRカラーダイアログの右上にある「×」をクリック
  18. ・OutlineのThicknessを(0.2)に設定
  19. インスペクター左上のチェックを外す
  20. CTRLキーを押しながらSキーを押す

▷床認識

タグ「Floor」を作成して床プレハブに割り当てます。

【床認識】タグ「Floor」を作成して床プレハブに割り当てる
  1. プロジェクトの「Prefabs>Floor」をダブルクリック
  2. インスペクターのドロップダウン「タグ」をクリックし、「タグを追加…」をクリック
  3. インスペクターのタグ右下の「+」をクリック
  4. 「Floor」と入力し、ENTERキーを押す
  5. ヒエラルキーの「Floor」をクリック
  6. インスペクターのドロップダウン「タグ」をクリックし、「Floor」をクリック
  7. ヒエラルキーの左上にある「<」をクリック
  8. CTRLキーを押しながらSキーを押す

▷クリア制御

プロジェクトの「Assets>Scripts>GameManager」をダブルクリックし、全ての荷物が置場におかれたらクリアUIを表示し、動きを止めるスクリプトを記述します。

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

public class GameManager : MonoBehaviour
{
    public GameObject uiClear;
    public Material matPlace;

    GameObject player;
    Vector3 prevPos;
    Vector3 nextPos;
    int count;
    int maxCount = 16;
    GameObject pushPack;

    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        prevPos = player.transform.position;
        nextPos = player.transform.position;
        count = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (ClearCheck() == true)
        {
            uiClear.SetActive(true);
            return;
        }

        if (prevPos == nextPos)
        {
            Vector3 addPos = new Vector3(0, 0, 0);
            addPos.x = Input.GetAxisRaw("Horizontal");
            if (addPos.x == 0)
            {
                addPos.z = Input.GetAxisRaw("Vertical");
            }

            GameObject obj = GetObject(player.transform.position + addPos);
            if (obj != null && obj.CompareTag("Pack"))
            {
                if (GetObject(player.transform.position + addPos + addPos) == null)
                {
                    pushPack = obj;
                }
            }

            if (obj == null || pushPack != null)
            {
                nextPos = player.transform.position + addPos;
            }
        }
    }

    void FixedUpdate()
    {
        if (prevPos != nextPos)
        {
            count++;
            if (count == maxCount)
            {
                player.transform.position = nextPos;
                if (pushPack != null)
                {
                    pushPack.transform.position = nextPos + (nextPos - prevPos);
                    pushPack = null;
                }
                prevPos = nextPos;
                count = 0;
            }
            else
            {
                Vector3 addPos = (nextPos - prevPos) * (1.0f / maxCount);
                player.transform.position += addPos;
                if (pushPack != null)
                {
                    pushPack.transform.position += addPos;
                }
            }
        }
    }

    GameObject GetObject(Vector3 pos)
    {
        GameObject[] packs = GameObject.FindGameObjectsWithTag("Pack");
        for (int i = 0; i < packs.Length; i++)
        {
            if (packs[i].transform.position == pos)
            {
                return packs[i];
            }
        }

        GameObject[] blocks = GameObject.FindGameObjectsWithTag("Block");
        for (int i = 0; i < blocks.Length; i++)
        {
            if (blocks[i].transform.position == pos)
            {
                return blocks[i];
            }
        }

        return null;
    }

    bool ClearCheck()
    {
        GameObject[] floors = GameObject.FindGameObjectsWithTag("Floor");
        for (int i = 0; i < floors.Length; i++)
        {
            Renderer renderer = floors[i].GetComponent<Renderer>();
            if (renderer.sharedMaterials[0] == matPlace)
            {
                GameObject obj = GetObject(floors[i].transform.position + new Vector3(0, 1, 0));
                if (obj == null || obj.CompareTag("Pack") == false)
                {
                    return false;
                }
            }
        }
        return true;
    }
}

▷クリアUI参照

ゲーム管理にクリアUIを登録します。

【クリアUI参照】ゲーム管理にクリアUIを登録
  1. ヒエラルキーの「GameManager」をクリック
  2. ヒエラルキーの「TextClear」をインスペクターの「GameManager>Ui Clear」にドラッグ&ドロップ
  3. CTRLキーを押しながらSキーを押す

▷置場マテリアル参照

ゲーム管理に置場マテリアルを登録します。

【置場マテリアル参照】ゲーム管理に置場マテリアルを登録
  1. ヒエラルキーの「GameManager」をクリック
  2. プロジェクトの「Assets>Materials>matPlace」をインスペクターの「GameManager>Mat Place」にドラッグ&ドロップ
  3. CTRLキーを押しながらSキーを押す

▷動作確認

全ての荷物をゴールに配置したらクリアが表示されることを確認します。

【動作確認】全ての荷物をゴールに配置したらクリアが表示されることを確認
  1. エディタ上中央の「▶」をクリック
  2. 全ての荷物をゴールまで移動させる
  3. 「Clear」と表示され、矢印キーを入力しても動かないことを確認
  4. エディタ上中央の「▶」をクリック

完成!

作成手順を書いた記事です。

   →紹介
   →1/2 オブジェクト構築
今▷ →2/2 オブジェクト制御

完全手順
※紹介と1~2の手順を1ページにまとめています。
 読み込みに時間がかかるかも知れません。

コメント

タイトルとURLをコピーしました