Menu
CoddyTech

Singleton

Thuộc phần Xây dựng trò chơi thực tế trong hành trình Unity của Coddy. Bài học 13 trên 60.

Một tham chiếu Inspector cần có thứ để kéo vào. Kẻ địch mà spawner tạo ra trong lúc chơi game xuất phát từ prefab, và prefab chỉ có thể tham chiếu đến asset và các thành phần của chính nó, không bao giờ đến một đối tượng trong scene, nên trường GameManager của chúng sẽ để trống. Cách giải quyết thường dùng là singleton: GameManager lưu chính nó vào một trường mà mọi script đều có thể truy cập thông qua tên lớp.

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;
    private int kills;

    void Awake()
    {
        Instance = this;
    }

    public void EnemyDown()
    {
        kills++;
        Debug.Log("Kills: " + kills);
    }
}
// Enemy.cs, trên prefab của kẻ địch
public void Die()
{
    GameManager.Instance.EnemyDown();
    Destroy(gameObject);
}

static có nghĩa là trường đó thuộc về lớp, không phải một đối tượng. Mỗi đối tượng GameManager sẽ có kills riêng, nhưng trong cả game chỉ có một Instance, và bạn truy cập nó bằng tên lớp: GameManager.Instance. Mọi script đều có thể đọc nó, kể cả một kẻ địch vừa được tạo ra cách đây một phút, mà không cần điền trường riêng của nó.

Trình quản lý gán Instance = this; trong Awake, tại đó this là chính script đó. Unity chạy mọi Awake trong scene trước bất kỳ Start nào, vì vậy các script khác có thể dùng GameManager.Instance từ Start trở đi. Nếu có một GameManager thứ hai trong scene, nó sẽ ghi đè Instance bằng chính nó; chương Scenes and Levels sẽ chỉ cách ngăn điều đó.

challenge icon

Thử thách

Dễ

Để các thiên thạch liên hệ với GameManager thông qua một singleton.

  1. Trong GameManager.cs, thêm public static GameManager Instance; và một hàm Awake() có Instance = this;.
  2. Trong Meteor.cs, xóa trường game và gọi GameManager.Instance.MeteorLanded() cùng GameManager.Instance.MeteorCaught() thay thế.

Nhấn Chơi và bắt một thiên thạch: Caught: 1 sẽ hiển thị, không có lỗi nào trong Console. Sau đó nhấn Kiểm tra.

Tự làm thử

using UnityEngine;
using TMPro;

public class GameManager : MonoBehaviour
{
    public TMP_Text caughtText;
    public TMP_Text shieldText;
    private int caught;
    private int shield = 3;

    public void MeteorCaught()
    {
        caught++;
        caughtText.text = "Caught: " + caught;
    }

    public void MeteorLanded()
    {
        shield--;
        shieldText.text = "Shield: " + shield;
    }
}

Tất cả bài học trong Xây dựng trò chơi thực tế

Tự luyện tập: Playground Unity