U
章 01基础11 课 — 点击打开
08 / 11 · 9 分钟
基础

用代码生成方块网格

到目前为止的项目

Assets/

Scenes/

Arena.unity

FloorBlocks (parent)

Scripts/

GridSpawner.cs

Prefabs/

P_Cube

你已经有的这一课新增

手动一个个摆满 100 个方块,一个下午就没了。两层嵌套循环加一句 Instantiate,一帧就搞定。

动态图解

x 往横走,z 往屏幕里走,每个格子掉下一个 cube。

网格生成脚本

GridSpawner.cs
using UnityEngine;

public class GridSpawner : MonoBehaviour
{
    [SerializeField] private GameObject blockPrefab;
    [SerializeField] private int columns = 6;      // along X
    [SerializeField] private int rows = 6;
    [SerializeField] private float spacing = 1.5f; // metres between blocks
    [SerializeField] private Transform parent;

    void Start()
    {
        BuildGrid();
    }

    void BuildGrid()
    {
        // centre the grid on this object
        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,                       // half the cube height
                    z * spacing - offsetZ);

                GameObject block = Instantiate(blockPrefab, pos, Quaternion.identity, parent);
                block.name = $"Block_{x}_{z}";  // readable in the Hierarchy
            }
        }
    }
}
  1. 1

    新建一个空 GameObject,命名 Spawner,放在 0, 0, 0。

  2. 2

    给它挂上 GridSpawner.cs,再把 P_Cube 拖进 Block Prefab 槽位。

  3. 3

    再建一个空物体叫 Blocks,拖进 Parent 槽位 —— 生成出来的 cube 全都挂在它下面。

  4. 4

    Play 一点,36 个 cube 出现在地板正中。

把这段计算一次弄懂

  • x * spacing 把循环计数 0,1,2… 换算成米:0、1.5、3……

  • 减去 offsetX 会把整个网格往左挪自身宽度的一半,于是它居中,而不是从原点开始排。

  • Instantiate 的第四个参数是父 Transform。传了它,Hierarchy 就不会变成 36 行散落的对象。

值得一试的几个变体

inside the inner loop
// 1 — random colour per block
block.GetComponent<Renderer>().material.color =
    Random.ColorHSV(0f, 1f, 0.4f, 0.7f, 0.7f, 1f);

// 2 — random height, so it reads like a city
float h = Random.Range(0.5f, 4f);
block.transform.localScale = new Vector3(1f, h, 1f);
block.transform.position   = new Vector3(pos.x, h * 0.5f, pos.z);

// 3 — a wave, using the distance from the centre
float d = new Vector2(x - columns * 0.5f, z - rows * 0.5f).magnitude;
block.transform.position += Vector3.up * Mathf.Sin(d) * 0.6f;

清掉网格

C# 脚本
public void ClearGrid()
{
    // backwards: still right if this ever becomes DestroyImmediate
    for (int i = parent.childCount - 1; i >= 0; i--)
        Destroy(parent.GetChild(i).gameObject);
}