【基本操作】倉庫番~完全手順【パズル】

倉庫番完成までの操作概要、操作手順を作成しました。
タグやインスペクターの計算配置を使ったりしています。

スクリプトを1つにまとめてしまったため、真面目に書いている人には大変になってしまったかも。
「どこどこに挿入」という手順にした方が良いかな?

対象:初心者、Unityに初めて触る方
使用バージョン:Unity 2021.3
時間:1.5時間

■オブジェクト構築

●オブジェクト作成

▷プレイヤー作成

青色の球を作成してリセット、プレハブ化します。

【プレイヤー作成】青色の球を作成してリセット、プレハブ化
  1. ヒエラルキー左上の「+」をクリックし、「3Dオブジェクト>スフィア」をクリック
  2. 「Player」と入力し、ENTERキーを押す
  3. インスペクターのTransformにある縦の三点リーダーをクリックし、リセットをクリック
  4. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  5. 「matPlayer」と入力し、ENTERキーを押す
  6. インスペクターの「アルベド>カラーバー」をクリックし、色ダイアログの16進数を「0000FF」に設定
  7. 色ダイアログの右上にある「×」をクリック
  8. プロジェクトの「matPlayer」をヒエラルキーの「Player」にドラッグ&ドロップ
  9. ヒエラルキーの「Player」をプロジェクトのAssetsにドラッグ&ドロップ
  10. CTRLキーを押しながらSキーを押す

▷荷物作成

箱を作成してリセット、青色にしたテクスチャ「Knob」を割り当てて(1, 0, 0)に配置し、プレハブ化します。

【荷物作成】箱を作成してリセット、青色にしたテクスチャ「Knob」を割り当てて(1, 0, 0)に配置し、プレハブ化
  1. ヒエラルキー左上の「+」をクリックし、「3Dオブジェクト>キューブ」をクリック
  2. 「Pack」と入力し、ENTERキーを押す
  3. インスペクターの「Transform>縦の三点リーダー」をクリックし、リセットをクリック
  4. インスペクターの「Transform>位置」を(1, 0, 0)に設定
  5. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  6. 「matPack」と入力し、ENTERキーを押す
  7. インスペクターのアルベド左にある○をクリックし、SelectTextureダイアログのアセットタブにある「Knob」をダブルクリック
  8. インスペクターの「アルベド>カラーバー」をクリックし、色ダイアログの16進数を「00FFFF」に設定
  9. 色ダイアログの右上にある「×」をクリック
  10. プロジェクトの「matPack」をヒエラルキーの「Pack」にドラッグ&ドロップ
  11. ヒエラルキーの「Pack」をプロジェクトのAssetsにドラッグ&ドロップ
  12. CTRLキーを押しながらSキーを押す

▷床作成

箱を作成してリセット、ねずみ色にしたテクスチャ「Default-Checker-Gray」を割り当てて(0, -1, 0)に配置し、プレハブ化します。

【床作成】箱を作成してリセット、ねずみ色にしたテクスチャ「Default-Checker-Gray」を割り当てて(0, -1, 0)に配置し、プレハブ化
  1. ヒエラルキー左上の「+」をクリックし、「3Dオブジェクト>キューブ」をクリック
  2. 「Floor」と入力し、ENTERキーを押す
  3. インスペクターの「Transform>縦の三点リーダー」をクリックし、リセットをクリック
  4. インスペクターの「Transform>位置」を(0, -1, 0)に設定
  5. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  6. 「matFloor」と入力し、ENTERキーを押す
  7. インスペクターのアルベド左にある○をクリックし、SelectTextureダイアログのアセットタブにある「Default-Checker-Gray」をダブルクリック
  8. インスペクターの「アルベド>カラーバー」をクリックし、色ダイアログの16進数を「808080」に設定
  9. 色ダイアログの右上にある「×」をクリック
  10. プロジェクトの「matFloor」をヒエラルキーの「Floor」にドラッグ&ドロップ
  11. ヒエラルキーの「Floor」をプロジェクトのAssetsにドラッグ&ドロップ
  12. CTRLキーを押しながらSキーを押す

▷壁作成

オレンジ色テクスチャ「Background」の箱を作成してリセット、(-1, 0, 0)に配置してプレハブ化します。

【壁作成】オレンジ色テクスチャ「Background」の箱を作成してリセット、(-1, 0, 0)に配置してプレハブ化
  1. ヒエラルキー左上の「+」をクリックし、「3Dオブジェクト>キューブ」をクリック
  2. 名前を「Block」に設定
  3. インスペクターの「Transform>縦の三点リーダー」をクリックし、リセットをクリック
  4. インスペクターの「Transform>位置」を(-1, 0, 0)に設定
  5. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  6. 「matBlock」と入力し、ENTERキーを押す
  7. インスペクターのアルベド左にある○をクリックし、SelectTextureダイアログのアセットタブにある「Background」をダブルクリック
  8. インスペクターの「アルベド>カラーバー」をクリックし、色ダイアログの16進数を「FF8000」に設定
  9. 色ダイアログの右上にある「×」をクリック
  10. プロジェクトの「matBlock」をヒエラルキーの「Block」にドラッグ&ドロップ
  11. ヒエラルキーの「Block」をプロジェクトのAssetsにドラッグ&ドロップ
  12. CTRLキーを押しながらSキーを押す

▷置場準備

緑色テクスチャ「Default-Checker-Gray」のマテリアルを作成します。

【置場準備】緑色テクスチャ「Default-Checker-Gray」のマテリアルを作成する
  1. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  2. 「matPlace」と入力し、ENTERキーを押す
  3. インスペクターのアルベド左にある○をクリックし、SelectTextureダイアログのアセットタブにある「Default-Checker-Gray」をダブルクリック
  4. インスペクターの「アルベド>カラーバー」をクリックし、色ダイアログの16進数を「00FF00」に設定
  5. 色ダイアログの右上にある「×」をクリック

●オブジェクト配置

▷カメラ調整

カメラの位置を(4.5, 15, -4)、回転を(60, 0, 0)とします。

【カメラ調整】カメラの位置を(4.5, 15, -4)、回転を(60, 0, 0)とする
  1. ヒエラルキーの「Main Camera」をクリック
  2. インスペクターの「Transform>位置」を(4.5, 15, -4)に設定
  3. インスペクターの「Transform>回転」を(60, 0, 0)に設定
  4. CTRLキーを押しながらSキーを押す
  5. ゲームビューの「FreeAspect」をクリック
  6. 「9:16 Aspect」をクリック(無い場合は以下を操作)
  7. 左下の「+」をクリック
  8. ドロップダウン「タイプ」をクリックし、「アスペクト比」をクリック
  9. 幅&高さの「X」に(9)、「Y」に(16)を入力
  10. 「OK」をクリック

▷プレイヤー配置

プレイヤーの位置を(5, 0, 1)とします。

【プレイヤー配置】プレイヤーの位置を(5, 0, 1)とする
  1. ヒエラルキーの「Player」をクリック
  2. インスペクターの「Transform>位置」を(5, 0, 1)に設定
  3. CTRLキーを押しながらSキーを押す

▷床配置

床を1メートル単位でX方向10個、Z方向10個並べます。

【床配置】床を1メートル単位でX方向10個、Z方向10個並べる
  1. ヒエラルキーの「Floor」をクリック
  2. ヒエラルキー左上「+」をクリックし、「空の親を作成」をクリック
  3. 「FloorLines」と入力し、ENTERキーを押す
  4. ヒエラルキーの「FloorLines>Floor」をクリック
  5. CTRLを押しながらDキーを9回押す
  6. SHIFTを押しながらヒエラルキーの「FloorLines>Floor」をクリック
  7. インスペクターの「Transform>位置>X」に「#」と入力
  8. ヒエラルキーの「FloorLines」左にある三角形をクリック
  9. ヒエラルキーの「FloorLines」をクリック
  10. CTRLを押しながらDキーを9回押す
  11. SHIFTを押しながらヒエラルキーの「FloorLines (1)」をクリック
  12. CTRLを押しながら「FloorLines」をクリック
  13. インスペクターの「Transform>位置>Z」に「#」と入力
  14. CTRLキーを押しながらSキーを押す

▷壁配置

以下のように壁を並べます。
    □=床、■壁
 0123456789
9□□□□■■■□□□9
8□□□■□□□■□□8
7□□□■□□□■□□7
6□□□■□□□■□□6
5□■■■■□■■■□5
4■□□□□□■□□■4
3■□■□□□□□□■3
2■□□□■■■□□■2
1□■■□□□□□■□1
0□□□■■■■■□□0
 0123456789

【壁配置】壁を並べる
  1. ヒエラルキーの「Block」をヒエラルキーのシーン名にドラッグ&ドロップ
  2. CTRLを押しながらDキーを2回押す
  3. ヒエラルキーの「Block」をクリック
  4. インスペクターの「Transform>位置」を(1, 0, 1)に設定
  5. ヒエラルキーの「Block (1)」をクリック
  6. インスペクターの「Transform>位置」を(2, 0, 1)に設定
  7. ヒエラルキーの「Block (2)」をクリック
  8. インスペクターの「Transform>位置」を(3, 0, 0)に設定
  9. ヒエラルキーの「Block (2)」をクリック
  10. CTRLを押しながらDキーを4回押す
  11. SHIFTを押しながらヒエラルキーの「Block (3)」をクリック
  12. インスペクターの「Transform>位置>X」に「4+#」と入力
  13. CTRLを押しながらヒエラルキーの「Block (3)」をクリック
  14. CTRLを押しながらDキーを押す
  15. インスペクターの「Transform>位置>Z」に「2」と入力
  16. ヒエラルキーのタブをクリック
  17. CTRLを押しながらDキーを押す
  18. インスペクターの「Transform>位置>Z」に「9」と入力
  19. ヒエラルキーのタブをクリック
  20. CTRLを押しながらDキーを押す
  21. インスペクターの「Transform>位置>Z」に「5」と入力
  22. シーンのギズモにある赤矢印を、CTRLを押しながら矢印の方向へ2メートル分動かす
  23. ヒエラルキーのタブをクリック
  24. CTRLを押しながらDキーを押す
  25. シーンのギズモにある赤矢印を、CTRLを押しながら矢印の逆方向へ4メートル分動かす
  26. ヒエラルキーの「Block (16)」をクリック
  27. CTRLを押しながらDキーを押す
  28. インスペクターの「Transform>位置」を(6, 0, 4)に設定
  29. ヒエラルキーの「Block (19)」をクリック
  30. CTRLを押しながらDキーを押す
  31. インスペクターの「Transform>位置」を(2, 0, 3)に設定
  32. ヒエラルキーの「Block (20)」をクリック
  33. CTRLを押しながらDキーを押す
  34. インスペクターの「Transform>位置」を(8, 0, 1)に設定
  35. ヒエラルキーの「Block (21)」をクリック
  36. CTRLを押しながらDキーを押す
  37. インスペクターの「Transform>位置」を(0, 0, 4)に設定
  38. ヒエラルキーの「Block (22)」をクリック
  39. CTRLを押しながらDキーを2回押す
  40. SHIFTを押しながらヒエラルキーの「Block (22)」をクリック
  41. インスペクターの「Transform>位置>Z」に「4-#」と入力
  42. ヒエラルキーのタブをクリック
  43. CTRLを押しながらDキーを押す
  44. インスペクターの「Transform>位置>X」に「9」と入力
  45. ヒエラルキーの「Block (27)」をクリック
  46. CTRLを押しながらDキーを押す
  47. インスペクターの「Transform>位置」を(1, 0, 5)に設定
  48. ヒエラルキーの「Block (14)」をクリック
  49. CTRLを押しながらヒエラルキーの「Block (17)」をクリック
  50. CTRLを押しながらDキーを押す
  51. インスペクターの「Transform>位置>Z」に「6」と入力
  52. ヒエラルキーのタブをクリック
  53. CTRLを押しながらDキーを押す
  54. インスペクターの「Transform>位置>Z」に「7」と入力
  55. ヒエラルキーのタブをクリック
  56. CTRLを押しながらDキーを押す
  57. インスペクターの「Transform>位置>Z」に「8」と入力
  58. CTRLキーを押しながらSキーを押す

▷荷物配置

荷物を(3, 0, 3)、(5, 0, 3)、(7, 0, 3)の位置に配置します。

【荷物配置】荷物を(3, 0, 3)、(5, 0, 3)、(7, 0, 3)の位置に配置する
  1. ヒエラルキーの「Pack」をクリック
  2. インスペクターの「Transform>位置」を(3, 0, 3)に設定
  3. ヒエラルキーの「Pack」をクリック
  4. CTRLを押しながらDキーを押す
  5. シーンのギズモにある赤矢印を、CTRLを押しながら矢印の方向へ2メートル分動かす
  6. CTRLを押しながらDキーを押す
  7. シーンのギズモにある赤矢印を、CTRLを押しながら矢印の方向へ2メートル分動かす
  8. CTRLキーを押しながらSキーを押す

▷置場配置

置場マテリアルをゴールとする床に割り当てます。
    ★ゴール床
 0123456789
9□□□□■■■□□□9
8□□□■★★★■□□8
7□□□■□□□■□□7
6□□□■□□□■□□6
5□■■■■□■■■□5
4■□□□□□■□□■4
3■□■□□□□□□■3
2■□□□■■■□□■2
1□■■□□□□□■□1
0□□□■■■■■□□0
 0123456789

【置場配置】置場マテリアルをゴールとする床に割り当てる
  1. ヒエラルキーの「FloorLines (1)」左の「▶」をクリック
  2. プロジェクトの「Materials>matPlace」をヒエラルキーの「FloorLines (1)>Floor (3)」にドラッグ&ドロップ
  3. プロジェクトの「Materials>matPlace」をヒエラルキーの「FloorLines (1)>Floor (4)」にドラッグ&ドロップ
  4. プロジェクトの「Materials>matPlace」をヒエラルキーの「FloorLines (1)>Floor (5)」にドラッグ&ドロップ
  5. CTRLキーを押しながらSキーを押す

●オブジェクト整理

▷荷物整理

空オブジェクトを作成し、荷物群を格納します。

【荷物整理】空オブジェクトを作成し、荷物群を格納
  1. ヒエラルキー左上「+」をクリックし、「空のオブジェクトを作成」をクリック
  2. 「Packs」と入力し、ENTERキーを押す
  3. インスペクターの「Transform>縦の三点リーダー」をクリックし、リセットをクリック
  4. ヒエラルキーの「Pack」をクリック
  5. CTRLキーを押したまま「Pack (1)」をクリック
  6. CTRLキーを押したまま「Pack (2)」をクリック
  7. ヒエラルキーの選択ゲームオブジェクトを「Packs」にドラッグ&ドロップ
  8. ヒエラルキーの「Packs」左にある三角形をクリック
  9. CTRLキーを押しながらSキーを押す

▷床整理

空オブジェクトを作成し、床群を格納します。

【床整理】空オブジェクトを作成し、床群を格納
  1. ヒエラルキー左上「+」をクリックし、「空のオブジェクトを作成」をクリック
  2. 「Floors」と入力し、ENTERキーを押す
  3. インスペクターの「Transform>縦の三点リーダー」をクリックし、リセットをクリック
  4. ヒエラルキーの「FloorLines (1)」左の「▼」をクリック
  5. ヒエラルキーの「FloorLines」をクリック
  6. SHIFTキーを押したまま、ヒエラルキーの「FloorLines (9)」をクリック
  7. ヒエラルキーの選択ゲームオブジェクトを「Floors」にドラッグ&ドロップ
  8. ヒエラルキーの「Floors」左の「▼」をクリック
  9. CTRLキーを押しながらSキーを押す

▷壁整理

空オブジェクトを作成し、壁群を格納します。

【壁整理】空オブジェクトを作成し、壁群を格納
  1. ヒエラルキー左上「+」をクリックし、「空のオブジェクトを作成」をクリック
  2. 「Blocks」と入力し、ENTERキーを押す
  3. インスペクターの「Transform>縦の三点リーダー」をクリックし、リセットをクリック
  4. ヒエラルキーの「Block」をクリック
  5. SHIFTキーを押したまま、ヒエラルキーの「Block (33)」をクリック
  6. ヒエラルキーの選択ゲームオブジェクトを「Blocks」にドラッグ&ドロップ
  7. CTRLキーを押しながらSキーを押す

▷プロジェクト整理

マテリアル用、プレハブ用の格納フォルダを作成して移動します。

【プロジェクト整理】マテリアル用、プレハブ用の格納フォルダを作成して移動
  1. プロジェクトの「Assets」を右クリックし、「作成>フォルダー」をクリック
  2. 「Materials」と入力し、ENTERキーを押す
  3. プロジェクトの「matBlock」をクリック
  4. CTRLを押したまま「matFloor」をクリック
  5. CTRLを押したまま「matPack」をクリック
  6. CTRLを押したまま「matPlace」をクリック
  7. CTRLを押したまま「matPlayer」をクリック
  8. プロジェクトで選択中のアセットを「Assets>Materials」にドラッグ&ドロップ
  9. プロジェクトの「Assets」を右クリックし、「作成>フォルダー」をクリック
  10. 「Prefabs」と入力し、ENTERキーを押す
  11. プロジェクトの「Block」をクリック
  12. CTRLを押したまま「Floor」をクリック
  13. CTRLを押したまま「Pack」をクリック
  14. CTRLを押したまま「Player」をクリック
  15. プロジェクトで選択中のアセットを「Prefabs」にドラッグ&ドロップ

■オブジェクト制御

●プレイヤー制御

▷スクリプト整理

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

【スクリプト整理】スクリプト格納用のフォルダを作成
  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. エディタ上中央の「▶」をクリック

完成!

コメント

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