Instantiate: sinh prefab, và tái sử dụng chúng
Làm sao sinh object bằng code?
Biến thứ đó thành prefab, giữ tham chiếu tới nó trong một trường public, rồi gọi Instantiate(prefab, position, rotation). Kéo prefab từ bảng Project vào trường đó — kéo nhầm bản đang nằm trong Hierarchy là lỗi gây ra một nửa số bug của spawner.
Sinh vật thể chỉ gồm một hàm, Instantiate, cộng một thói quen quyết định nó chạy hay không: thứ bạn sinh ra phải là prefab lấy từ bảng Project, không phải bản đang nằm trong cảnh.
Tạo prefab trước đã
- 1
Dựng vật thể trong cảnh cho tới khi nó đúng y thứ bạn muốn sinh ra — mesh, material, collider, script, đủ cả.
- 2
Kéo nó từ Hierarchy vào Assets/Prefabs. Tên chuyển sang màu xanh: giờ nó là prefab, và nó nằm trên ổ cứng.
- 3
Xoá bản còn lại trong cảnh đi. Prefab mới là bản gốc; bản trong cảnh chỉ là thêm một kẻ địch đứng sẵn lúc khởi động.
Instantiate
using UnityEngine;
public class Spawner : MonoBehaviour
{
public GameObject prefab;
public Transform parent; // tuỳ chọn, giữ Hierarchy gọn gàng
public float interval = 1.5f;
float next;
void Update()
{
if (Time.time < next) return;
next = Time.time + interval;
Vector3 where = transform.position + Random.insideUnitSphere * 3f;
where.y = transform.position.y;
GameObject spawned = Instantiate(prefab, where, Quaternion.identity, parent);
// Instantiate trả về bản sao mới. Hãy cấu hình bản đó, đừng đụng prefab —
// ghi vào prefab.something là sửa thẳng vào file trên ổ cứng.
spawned.name = "Enemy " + Time.frameCount;
}
}Ba thứ hay quên
Instantiate chép lại tất cả, kể cả scale của prefab và các object con. Nếu vật sinh ra sai kích thước thì chính prefab đang sai kích thước.
Truyền parent giúp Hierarchy dễ nhìn, nhưng vật sẽ thừa hưởng scale của cha. Hãy gắn vào thứ có scale 1, hoặc sinh ra không kèm cha rồi gọi SetParent(parent, true) sau đó.
Quaternion.identity nghĩa là không xoay. Viết transform.rotation vào đó thì mọi vật sinh ra quay cùng hướng với spawner, và thường đó mới là thứ bạn muốn.
Destroy, và vì sao spawner làm tụt khung hình
Mỗi lần Instantiate là một lần cấp phát, và mỗi lần Destroy là một mớ rác để lại cho bộ dọn rác. Spawner chạy mỗi khung hình sẽ làm điện thoại giật trong vòng một phút. Với đạn và hiệu ứng — thứ xuất hiện hàng trăm lần — hãy tái sử dụng thay vì tạo mới.
using System.Collections.Generic;
using UnityEngine;
public class SimplePool : MonoBehaviour
{
public GameObject prefab;
readonly Queue<GameObject> idle = new();
public GameObject Get(Vector3 at)
{
GameObject go = idle.Count > 0 ? idle.Dequeue() : Instantiate(prefab);
go.transform.position = at;
go.SetActive(true);
return go;
}
// Gọi hàm này thay cho Destroy.
public void Release(GameObject go)
{
go.SetActive(false);
idle.Enqueue(go);
}
}bài học làm ra thứ này
Sinh lưới khối bằng code
Bài này là một công thức đứng riêng. Trong khoá học, cùng thứ đó được dựng như một phần của dự án xuyên suốt năm tab — Căn bản, bài 08.