Singleton tổng quát
Thuộc phần Kiến trúc trò chơi trong Unity trong hành trình Unity của Coddy. Bài học 43 trên 64.
Singleton ở phần 3 gồm năm dòng mà mọi manager đều lặp lại: một Instance tĩnh, một Awake để gán giá trị cho nó và phần kiểm tra đối tượng trùng lặp. Lớp cơ sở generic viết các dòng này một lần. Mỗi manager kế thừa từ lớp đó và khai báo tên kiểu của chính nó:
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
protected virtual void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this as T;
}
}
public class ScoreManager : Singleton<ScoreManager>
{
public int score;
public void Add(int points) { score += points; }
}
public class SoundManager : Singleton<SoundManager>
{
public void Play(string clip) { Debug.Log("Playing " + clip); }
}// trong bất kỳ script nào
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");Một thành viên tĩnh của lớp generic thuộc về từng kiểu được tạo từ lớp đó: Singleton<ScoreManager> và Singleton<SoundManager> là hai kiểu, mỗi kiểu có một Instance riêng, vì vậy các manager không bao giờ dùng chung một Instance. ScoreManager.Instance đã có kiểu ScoreManager, đó là mục đích của T. Bên trong lớp cơ sở, this chỉ được biết đến với kiểu Singleton<T>, vì vậy this as T chuyển nó thành kiểu manager thực sự của nó.
Lớp cơ sở là abstract: Unity chỉ thêm các manager vào đối tượng. Manager nào cần có Awake riêng thì không được viết void Awake() thông thường. Cách viết đó che khuất phương thức của lớp cơ sở (trình biên dịch sẽ cảnh báo), Unity chỉ gọi phương thức của manager và Instance sẽ không bao giờ được gán. Hãy override phương thức đó và gọi phương thức của lớp cơ sở trước:
protected override void Awake()
{
base.Awake();
score = 0;
}Thử thách
Trung bìnhTạo lớp cơ sở cho cả hai trình quản lý để chúng tồn tại khi tải cảnh.
- Trong
PersistentSingleton, viếtprotected virtual void Awake(): đối tượng đầu tiên trở thànhInstancevà tồn tại (DontDestroyOnLoad); đối tượng xuất hiện sau sẽ tự hủy. WalletvàMusicPlayerkế thừa lớp này; xóaInstancecủa chúng và hàm Awake của Wallet.MusicPlayerghi đè Awake: gọibase.Awake(), sau đó, nếu đây là Instance, ghi nhật kýNow playing: Adventure.
Nhấn Chơi, đến khu rừng rồi quay lại: 1 đồng xu. Sau đó nhấn Kiểm tra.
Tự làm thử
using UnityEngine;
public abstract class PersistentSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
// Awake: giữ instance đầu tiên khi tải các cảnh, hủy mọi instance xuất hiện sau
}
Tất cả bài học trong Kiến trúc trò chơi trong Unity
1Thành phần, không phải hệ thống phân cấp
Thành phần nhỏTập lệnh kẻ địch cơ sởThành phần trừu tượngCác thành phần phối hợp với nhauÔn tập: tháp pháo mô-đunÔn tập: pháo nòng đôi4Dữ liệu tuần tự hóa
Lớp có thể tuần tự hóaDanh sách trong InspectorKiểu liệt kê trong InspectorÔn tập: Bảng vật phẩm rơiÔn tập: Quay vật phẩm2Giao diện trong Unity
IDamageableGiao diện và TryGetComponentGetComponentsÔn tập: phím tương tácÔn tập: đối tượng gần nhất trong tầm với5ScriptableObjects
Tài sản dữ liệuChỉ số vũ khíCài đặt dùng chungLưu gióSóng dưới dạng dữ liệuÔn tập: Cơ sở dữ liệu vật phẩmÔn tập: Mua hàng từ cửa hàng8Code có thể tái sử dụng
Phương thức mở rộngSingleton tổng quátCác hàm hỗ trợ tổng quátÔn tập: FindNearest3Sự kiện
Sự kiện C# trong UnityĐăng ký trong OnEnableCác trường UnityEventSự kiện điều khiển UIÔn tập: Cửa sổ bật lên thành tíchÔn tập: Bộ hẹn giờ cửa sổ bật lên6Lưu dữ liệu bằng JSON
JsonUtilityLưu trò chơiTải dữ liệu và giá trị mặc địnhÔn tập: các ô lưuChọn và xóa một ô lưu9Tái sử dụng đối tượng bằng pool
Vì sao cần pool đối tượngPool dùng hàng đợiObjectPool của UnityÔn tập: pool đạnTự luyện tập: Playground Unity