U
タブ 01基礎11 レッスン — タップで開く
11 / 11 · 20 分
基礎★ 練習課題

練習課題:アリーナが形になる

ここまでのプロジェクト

Assets/

Scenes/

Arena.unity

FloorKnightMageArcherCanvas

Scripts/

CharacterSwitcher.csSwapCamera.csGameManager.csArenaHud.csGridSpawner.cs→ArenaBuilder.cs

Prefabs/

P_Cube

すでにあるものこのレッスンで追加このレッスンで置き換え

練習課題60–90 分

コースの後半すべてが行われる舞台を作ります。シーンは Arena という 1 つだけ。床、コードで生成するブロックのグリッド——tab 02 で飛び移ることになる、あのブロックです——切り替えられるキャラクター 3 人、そして画面に出る小さな数値表示。

再利用するもの

int / float / bool変数の型Start / Updateライフサイクルpublic field → Inspectorpublic フィールドif / for / List分岐と繰り返しPlane + material床とマテリアルPrefab + InstantiatePrefab と生成GetComponentコンポーネント取得
アニメーション図

完成したシーンは、見た目も動きもこのようになっているはずです。

何を作るか、ステップごとに

その 1 — 舞台

  • Arena という名前の新しいシーンを作り、Assets/Scenes に保存します。ここからコース終了までのレッスンはすべて、このファイル 1 つの上で行われます——このあと作るシーンといえば、イントロ画面だけです。

  • 位置 0,0,0、スケール 3,1,3 の Plane を床にします。material は自分で作った暗いものを使ってください。

  • Camera はだいたい 0, 14, -16 に置き、回転を 38, 0, 0 にして、床全体が画面に収まるようにします。

  • Directional Light は回転を 50, -30, 0 にして、影はやわらかく設定します。

その 2 — ブロックのグリッド

グリッドを生成するスクリプトを 1 つ書きます。立方体は 1 つでも手作業で置かないでください——cube をドラッグしている自分に気づいたら、ループに戻って直します。

ArenaBuilder.cs — fill in the TODOs
using System.Collections.Generic;
using UnityEngine;

public class ArenaBuilder : MonoBehaviour
{
    [Header("Grid")]
    [SerializeField] private GameObject blockPrefab;
    [SerializeField] private int columns = 4;
    [SerializeField] private int rows = 4;
    [SerializeField] private float spacing = 1.6f;
    [SerializeField] private Transform blockParent;

    // every block we made, so we can count and clear them
    private readonly List<GameObject> blocks = new List<GameObject>();

    public int BlockCount => blocks.Count;

    void Start()
    {
        Build();
    }

    void Update()
    {
        // press R to rebuild with fresh random colours
        if (Input.GetKeyDown(KeyCode.R))
            Build();
    }

    public void Build()
    {
        Clear();

        float offsetX = (columns - 1) * spacing * 0.5f;
        float offsetZ = (rows - 1) * spacing * 0.5f;

        for (int x = 0; x < columns; x++)
        {
            for (int z = 0; z < rows; z++)
            {
                Vector3 pos = new Vector3(
                    x * spacing - offsetX,
                    0.5f,
                    z * spacing - offsetZ);

                GameObject b = Instantiate(blockPrefab, pos, Quaternion.identity, blockParent);
                b.name = $"Block_{x}_{z}";

                // TODO 1: give it a random colour
                // TODO 2: give it a random height between 0.5 and 2.5

                blocks.Add(b);
            }
        }
    }

    public void Clear()
    {
        foreach (GameObject b in blocks)
            if (b != null) Destroy(b);

        blocks.Clear();
    }
}

その 3 — キャラクター 3 人

  • Y = 1 に Capsule を 3 つ、それぞれ違う色で置き、すべて Characters という名前の空の GameObject の子にします。

  • 3 つすべてに SimpleMover を付け、GameManager に CharacterSwitcher を付けます。キーは 1 / 2 / 3 と Tab。

  • Camera は、そのとき操作中のキャラクターを追いかけます。

その 4 — 数値表示

小さな HUD は、自分のスクリプト同士が話せることを証明するためのものです。自分が書いた 2 つのスクリプトが 3 つ目からデータを読む、初めての経験になります。

ArenaHud.cs — attach to any object, no UI package needed
using UnityEngine;

public class ArenaHud : MonoBehaviour
{
    [SerializeField] private ArenaBuilder builder;
    [SerializeField] private CharacterSwitcher switcher;

    // OnGUI is the quick-and-dirty way to draw text. Fine for an exercise,
    // never ship it — real UI lives on a Canvas, like the HudPanel from the last lesson.
    void OnGUI()
    {
        GUI.skin.label.fontSize = 20;
        GUI.Label(new Rect(20, 20, 400, 30), "Blocks: " + builder.BlockCount);
        GUI.Label(new Rect(20, 50, 400, 30), "Active: " + switcher.ActiveCharacter.name);
        GUI.Label(new Rect(20, 80, 400, 30), "R = rebuild");
    }
}

ここまでできたら完了

  • ✓Play を押すと、色も高さもランダムなブロックが 16 個ある床が表示されます。手作業で置いたものは 1 つもありません。
  • ✓R を押すとグリッドが新しいランダムな値で作り直され、カウントも正しい数のままです。
  • ✓キーの 1、2、3 で操作対象のキャラクターを切り替え、同時に動くのは常に 1 体だけです。
  • ✓Camera は操作中のキャラクターを、ガタつかずスムーズに追従します。
  • ✓HUD にはブロックの数と操作中のキャラクターの名前がリアルタイムで表示されます。
  • ✓Console は空です——自分のスクリプトから出たエラーも警告もありません。
  • ✓コードを触らず、Inspector で columns、rows、spacing を変えるだけで結果が変わります。

さらにやりたい人へ

ボーナス 1

ブロックを物理で落下させる:Rigidbody を追加して、5 m 上の位置に生成してみてください。

ボーナス 2

ブロックの色はランダムではなく、中心からの距離で塗るようにします。

ボーナス 3

キャラクターを 1 体追加し、switcher がリストの長さを自動で扱えるようにします。

ボーナス 4

操作中のキャラクターにブロックを押させる:ブロックに Rigidbody を付け、CharacterController で動かして、OnControllerColliderHit から押し出します。