練習課題:アリーナが形になる
Assets/
Scenes/
Arena.unity
Scripts/
Prefabs/
すでにあるものこのレッスンで追加このレッスンで置き換え
コースの後半すべてが行われる舞台を作ります。シーンは Arena という 1 つだけ。床、コードで生成するブロックのグリッド——tab 02 で飛び移ることになる、あのブロックです——切り替えられるキャラクター 3 人、そして画面に出る小さな数値表示。
再利用するもの
完成したシーンは、見た目も動きもこのようになっているはずです。
何を作るか、ステップごとに
その 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 をドラッグしている自分に気づいたら、ループに戻って直します。
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 つ目からデータを読む、初めての経験になります。
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 を変えるだけで結果が変わります。
さらにやりたい人へ
ブロックを物理で落下させる:Rigidbody を追加して、5 m 上の位置に生成してみてください。
ブロックの色はランダムではなく、中心からの距離で塗るようにします。
キャラクターを 1 体追加し、switcher がリストの長さを自動で扱えるようにします。
操作中のキャラクターにブロックを押させる:ブロックに Rigidbody を付け、CharacterController で動かして、OnControllerColliderHit から押し出します。