Denk Kits Tutorial

🔧 Giới thiệu Denk Kits

Denk Kits là một bộ core framework nội bộ được thiết kế để tăng tốc và chuẩn hóa quy trình phát triển game tại Benk Studio. Với kiến trúc rõ ràng, khả năng mở rộng mạnh mẽ và tính ổn định cao, Denk Kits đóng vai trò nền tảng cho mọi dự án Unity tại studio.


📁 Cấu trúc thư mục tổng quan

🗂️ Root Level

DenkKits Structure

  • denkKits: Thư viện gốc – nơi chứa toàn bộ các service, package và công cụ cốt lõi (Core Services).
  • Game: Dự án game chính – chứa source code, scenes, scripts, prefabs, v.v.
  • LayerLab: UI package có thể dùng hoặc xóa nếu không cần – GUI PRO: Fantasy RPG
  • Resources: Chứa các config nội bộ như setting cho package bên thứ ba.

🧩 Chi tiết bên trong denkKits

DenkKits Folder

Thư mục Mô tả
DataScriptableObject Các mẫu data tạm thời – không dùng trong production
Demigiant DOTween Pro – tweening cho animation: Link
GameServices Cốt lõi: gồm Audio, SaveData, Transition, Firebase,… (quan trọng!)
Joystick Pack Joystick cho mobile: Link
Particle Image Hiệu ứng trên UI canvas: Link
Sirenix Odin Inspector: hỗ trợ debug, custom inspector: Link
SO Architecture Observer pattern bằng ScriptableObject: Link
SuperScrollView ScrollView tối ưu: Link
UIManager Hệ thống quản lý toàn bộ UI Canvas
Utilities Các extension, helper chung

🎮 Thư mục Game – nơi bạn phát triển gameplay

Game Folder

  • Events: Sự kiện được thiết kế theo SO Architecture
  • Font: Font chữ sử dụng trong game
  • Prefabs: Tập hợp tất cả các prefab của game
  • Scenes: Các scene chính của game
  • Scripts: Toàn bộ mã gameplay, UI, logic…

🧠 Kiến trúc tổng thể

Architecture

  • UIManager quản lý tất cả canvas và popup
  • Mỗi scene đều có một GameController riêng: quản lý logic scene + kết nối DenkKits
  • Các DenkKit ServiceSingleton được khởi tạo duy nhất một lần từ scene EntryDontDestroyOnLoad

🔄 Scene Flow

Entry Scene

  • Khởi tạo toàn bộ DenkKits Services
  • Load các tài nguyên thiết yếu
  • Diễn ra một lần duy nhất khi game bắt đầu

🧩 UIManager Hướng dẫn sử dụng

📌 Cách tạo một UIPopup mới

  1. Mở file UIPopupName.cs, thêm enum mới:

    1
    2
    3
    4
    5
    public enum UIPopupName
    {
    // ...
    YourNewPopup,
    }

    Enum Image

  2. Tạo một script kế thừa UIPopup:

    1
    2
    3
    4
    public class YourNewPopup : UIPopup
    {
    // Logic xử lý UI ở đây
    }
  3. Tạo prefab popup:

    • Đặt tên prefab giống tên enum YourNewPopup
    • Đặt đúng folder prefab yêu cầu
    • Thiết kế UI như bạn muốn (hoặc duplicate từ popup cũ để sửa)

    Popup Prefab

  4. (Tùy chọn) Tham khảo SettingPopup, đây là một popup đơn giản dễ hiểu.

  5. Mở prefab UIManager, thêm một GameObject mới là popup bạn vừa tạo:

    • Đặt vào đúng hierarchy
    • Gắn UIPopup script tương ứng
    • Trong Popup Manager, chọn đúng PopupName

    UIManager Config

    • Chọn Popup Name tương ứng
  6. UIManager Config

  7. Gọi popup trong code:

    1
    UIManager.Instance.PopupManager.ShowPopup(UIPopupName.YourNewPopup);

🧩 UIView – Cách dùng tương tự Popup

  • Mỗi Scene sẽ có 1 UIView chính.
  • UIView không đóng mở nhiều như popup, nó là màn UI chính trong scene.
  1. Mở file UIViewName.cs, thêm enum mới:

    1
    2
    3
    4
    5
    public enum UIViewName
    {
    // ...
    YourNewView,
    }

    UIView Enum

  2. Tạo script kế thừa UIView:

    1
    2
    3
    4
    public class YourNewView : UIView
    {
    // View logic
    }
  3. Tạo prefab:

    • Tên prefab phải khớp với enum
    • Gắn script vừa tạo
    • Đặt vào folder UI View
    • Gắn vào UIManager trong prefab tương tự các View có sẵn

    UIView Setup


🔊 AudioManager – Cấu hình và sử dụng hệ thống âm thanh DenkKits

DenkKits đã tích hợp sẵn một hệ thống âm thanh mạnh mẽ, dễ mở rộng, hỗ trợ cả BGM, SFX, loop, fade, mute, và tùy chỉnh volume.


📦 1. AudioDatabase và AudioData

  • Mở Assets/DenkKits/GameServices/Audio/AudioDatabase.asset
  • Đây là nơi lưu toàn bộ âm thanh của bạn, được gán thủ công qua Inspector.
    Audio Setup

🔍 Cấu trúc AudioData

1
2
3
4
5
6
7
8
9
10
public class AudioData {
public AudioName audioName; // Enum định danh âm thanh
public AudioType type; // BGM, SFX, AMB
public AudioClip audioClip; // File âm thanh
public float volume; // Âm lượng riêng
public int priority; // Ưu tiên phát
public float spatialBlend; // 2D/3D âm thanh
public bool isLooping; // Lặp lại không
public bool playOnAwake; // Tự chạy khi start game
}
  • Gắn AudioClip, chọn AudioType (SFX/BGM) và cấu hình âm lượng theo ý muốn.
  • Âm thanh có playOnAwake = true sẽ tự phát khi game bắt đầu.

⚙️ 2. Cấu hình mặc định

Trong game, volume được lưu trữ qua PlayerPrefs. Bạn có thể chỉnh bằng code hoặc qua UI tùy ý.

Ví dụ chỉnh volume:

1
2
AudioManager.Instance.SetMusicVolume(0.5f); // Nhạc nền
AudioManager.Instance.SetAudioVolume(1.0f); // Hiệu ứng

Lưu lại:

1
AudioManager.Instance.SaveAudioSetting();

🎮 3. Cách sử dụng trong game

✅ Phát nhạc nền (loop):

1
AudioManager.Instance.PlayMusic(AudioName.BGM_GAMEPLAY);

✅ Phát SFX:

1
AudioManager.Instance.PlaySfx(AudioName.UI_Click);

✅ Dừng nhạc:

1
AudioManager.Instance.StopMusic(AudioName.BGM_GAMEPLAY);

✅ Fade nhạc nền:

1
2
AudioManager.Instance.FadeIn(AudioName.BGM_GAMEPLAY, 1.5f); // fade vào trong 1.5 giây
AudioManager.Instance.FadeOut(AudioName.BGM_MENU, 1f); // fade ra trong 1 giây

✅ Phát SFX lặp (looping SFX):

1
2
3
AudioSource loopSource = AudioManager.Instance.PlayLoopingSfx(AudioName.Gameplay_EnemyHit);
// Khi cần dừng:
AudioManager.Instance.StopLoopingSfx(loopSource);

🔇 4. Bật/tắt âm thanh

Tắt/bật nhạc nền:

1
AudioManager.Instance.SetMusic(false); // false = không tắt

Tắt/bật SFX:

1
AudioManager.Instance.SetSound(true); // true = tắt SFX

Kiểm tra mute:

1
bool isMuted = AudioManager.Instance.IsMuteAudio(AudioType.SFX);

🚥 5. Gợi ý sử dụng theo scene

Hệ thống tự nhận diện Scene hiện tại và phát BGM tương ứng:

1
2
3
4
5
6
7
8
9
10
// Trong AudioManager.cs
private AudioName GetMusicBGName(string sceneName)
{
switch (sceneName)
{
case "MainMenu": return AudioName.BGM_Menu;
case "Game": return AudioName.BGM_GAMEPLAY;
default: return AudioName.BGM_Menu;
}
}

Bạn có thể mở rộng logic này để mỗi màn chơi có BGM riêng biệt.


🛠 6. Debug & mở rộng

  • Pooling AudioSource đã được tích hợp một phần nhưng chưa hoàn thiện.
  • Có thể sử dụng PlaySoundFromSource() để gán SFX thủ công cho AudioSource ngoài.
  • FadeIn()FadeOut() hiện chỉ dùng cho BGM.