| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
👋 Hi there, I'm HoangVanThu. This repository helps you build mobile games quickly.
| Requirement | Version |
|---|---|
| Unity | 6000.2.10f1 |
| Platform | Android or iOS |
Assets/ ├── _Project/ │ ├── Animations/ # Animation clips │ ├── Audio/ # Music and SFX files │ ├── Config/ # All ScriptableObject assets (.asset) │ │ ├── GameConfig.asset │ │ ├── SoundConfig.asset │ │ ├── PopupConfig.asset │ │ ├── LevelConfig.asset │ │ ├── DailyRewardConfig.asset │ │ ├── VibrationConfig.asset │ │ ├── ItemConfig.asset │ │ ├── InternetConfig.asset │ │ └── VisualEffectConfig.asset │ ├── Fonts/ │ ├── Materials/ │ ├── Models/ │ ├── Prefabs/ │ │ └── Controller/ # Singleton manager prefabs │ ├── Resources/ │ │ └── Levels/ # Level prefabs (Level 1.prefab … Level N.prefab) │ ├── Scenes/ │ │ ├── LoadingScene.unity # Entry point │ │ └── GameplayScene.unity # Main game loop │ ├── Scripts/ │ │ ├── Common/ # Shared animation helpers (GoMove, GoBounce, etc.) │ │ ├── Gameplay/ │ │ │ └── Level/ # Level.cs, Pill.cs, Hole.cs │ │ └── System/ │ │ ├── GameManager.cs │ │ ├── Config/ # ScriptableObject class definitions │ │ ├── Controller/ # All singleton controllers (12 total) │ │ ├── Data/ # Player data + encryption │ │ ├── Observer/ # Event system (partial classes) │ │ ├── Pattern/ # Singleton / SingletonDontDestroy base classes │ │ ├── UI/ # All popup scripts + PopupCreator tool │ │ ├── Components/ # Popup base class, UIEffect │ │ ├── GUI/ # CustomButton, CustomSwitchButton, BackgroundScroller │ │ ├── Resources/ # Resource loading helpers │ │ ├── Vibration/ # Haptic feedback │ │ └── Common/ # Utility, SafeArea, CanvasScaleHandler │ ├── Textures/ & Sprites/ │ ├── ~ExtensionPackages/ # Reusable custom editor packages │ │ ├── CustomInspector/ │ │ ├── CustomTween/ │ │ ├── CustomHierarchy/ │ │ ├── CustomFindReference/ │ │ ├── CustomBuildReport/ │ │ └── CustomPlayerPref/ │ └── ~LevelEditor/ # Level design editor (project-specific) ├── Plugins/ # Android / iOS native plugins ├── Spine/ # Spine animation runtime └── ThirdParty/ # TextMesh Pro, Lean packages
┌─────────────────────────────────────────────┐
│ UI Layer (PopupController) │
│ PopupHome, PopupShop, PopupSetting … │
│ Registry pattern — Show<T>() / Hide<T>() │
└──────────────────┬──────────────────────────┘
│
┌───────────┴───────────┐
▼ ▼
┌──────────────┐ ┌────────────────────┐
│ GameManager │ │ Observer (Events) │
│ (GameState) │◄────►│ static Actions │
└──────┬───────┘ └──────────┬─────────┘
│ │
┌────┴─────────────────────────┤
▼ ▼
Controllers (12) PlayerData
LevelController (partial classes)
SoundController Data.SaveData()
ItemController Data.LoadData()
PlayerDataController EncryptionHelper
…
Scenes:
| Scene | Role |
|---|---|
| LoadingScene | Bootstraps all singleton controllers, loads player data, then loads GameplayScene |
| GameplayScene | Main game loop; levels are spawned dynamically at runtime |
All controllers inherit from SingletonDontDestroy<T> and survive scene transitions.
All game configuration lives in Assets/_Project/Config/ as ScriptableObject assets. They are never modified at runtime — only read.
| Asset | Class | Purpose |
|---|---|---|
| GameConfig.asset | GameConfig | isTesting flag to enable debug tools |
| SoundConfig.asset | SoundConfig | Maps SoundName enum values to AudioClip lists |
| PopupConfig.asset | PopupConfig | Holds prefab references for every popup |
| LevelConfig.asset | LevelConfig | maxLevel, levelLoopType, startLoopLevel |
| DailyRewardConfig.asset | DailyRewardConfig | Per-day reward definitions |
| VibrationConfig.asset | VibrationConfig | Delay time between haptic pulses |
| ItemConfig.asset | ItemConfig | All shop items / skins |
Creating a new ScriptableObject config:
[CreateAssetMenu(fileName = "MyConfig", menuName = "ScriptableObject/MyConfig")]
public class MyConfig : ScriptableObject
{
public int someValue;
public string someText;
}Player data is stored as an encrypted JSON file at:
Application.persistentDataPath/player_data.json
The data class is split into partial files for clarity:
| File | Contents |
|---|---|
| PlayerData.cs | IsFirstPlaying, CurrentLevelIndex, CurrentEnergy, CurrentGold, CurrentDiamond, SavingReward |
| PlayerData.Setting.cs | MusicVolume, SoundVolume, VibrationState |
| PlayerData.Shop.cs | CurrentSkin, OwnedSkins |
| PlayerData.DailyReward.cs | CurrentDailyReward, LastDailyRewardClaimed |
Accessing player data from anywhere:
// Read
int gold = Data.PlayerData.CurrentGold;
// Write (automatically fires Observer events)
Data.PlayerData.CurrentGold += 100;
// Save manually (also auto-saves on app pause/quit)
Data.SaveData();
// Load (called automatically at startup)
Data.LoadData();
// Delete save file
Data.ClearData();Property setters on PlayerData automatically invoke the relevant Observer events, so listeners update immediately (e.g., HUD counters refresh when gold changes).
// PlayerData.cs (or a new partial file)
public partial class PlayerData
{
[SerializeField] private int currentStars;
public int CurrentStars
{
get => currentStars;
set
{
Observer.StarsChanged?.Invoke(value - currentStars);
currentStars = value;
}
}
}All popups inherit from the Popup base class and are managed by PopupController (a singleton).
PopupController holds a Dictionary<Type, Popup> so every popup can be retrieved, shown, or hidden by its C# type.
public class PopupAchievement : Popup
{
// Override lifecycle hooks as needed
protected override void BeforeShow()
{
// Called before the popup becomes visible
}
protected override void AfterShown()
{
// Called after the show animation completes
}
protected override void BeforeHide()
{
base.BeforeHide();
// Called before the hide animation starts
}
protected override void AfterHidden()
{
base.AfterHidden();
// Called after the popup is fully hidden
}
}// Show with no animation
PopupController.Instance.Show<PopupAchievement>();
// Show with scale + fade animation
PopupController.Instance.Show<PopupAchievement>(PopupAnimation.ScaleFade);
// Hide
PopupController.Instance.Hide<PopupAchievement>();
PopupController.Instance.Hide<PopupAchievement>(PopupAnimation.FadeOnly);
// Hide all open popups at once
PopupController.Instance.HideAll();
// Get a reference to a popup instance
if (PopupController.Instance.Get<PopupAchievement>() is PopupAchievement popup)
{
popup.SetData(someData);
}Available animations (PopupAnimation enum):
| Value | Effect |
|---|---|
| None | Instant show/hide |
| ScaleFade | Scale from small → normal + fade in |
| ScaleFade2 | Scale from large → normal + fade in |
| FadeOnly | Fade in/out only |
Animation parameters (duration, easing, scale range) are configurable per popup in the Inspector on the Popup component.
Override these virtual methods in your popup subclass to react at each stage:
OnInstantiate() → called once when the popup is first created BeforeShow() → called every time before the popup appears AfterShown() → called after the show animation finishes BeforeHide() → called before the hide animation starts AfterHidden() → called after the popup is fully hidden / deactivated
You can also assign one-time callbacks without subclassing:
var popup = PopupController.Instance.Get<PopupWin>() as PopupWin;
popup.AfterHiddenAction = () => Debug.Log("Win popup closed!");
popup.Show(PopupAnimation.ScaleFade);public enum SoundName
{
HomeBackgroundMusic,
InGameBackgroundMusic,
ClickButton,
PurchaseCompleted,
LevelComplete, // ← new entry
}// Play a one-shot sound effect
SoundController.Instance.PlayFX(SoundName.LevelComplete);
// Play/switch background music
SoundController.Instance.PlayBackground(SoundName.HomeBackgroundMusic);Volumes are driven by Data.PlayerData.MusicVolume and Data.PlayerData.SoundVolume (both 0–1).
Setting those properties automatically fires Observer.MusicChanged / Observer.SoundChanged, which SoundController listens to and applies immediately.
Levels are stored as prefabs at Assets/_Project/Resources/Levels/ and loaded at runtime via Resources.Load.
Once the player finishes all designed levels, the system loops based on LevelConfig:
| LevelLoopType | Behavior |
|---|---|
| Recycle | Replays levels from startLoopLevel → maxLevel in order |
| Random | Picks a random level between 1 and maxLevel |
Observer is a static partial class containing C# Action delegates. It acts as a lightweight pub/sub event bus — any script can publish or subscribe without holding a direct reference.
Subscribing to an event:
void OnEnable()
{
Observer.GoldChanged += OnGoldChanged;
Observer.WinLevel += OnWinLevel;
}
void OnDisable()
{
Observer.GoldChanged -= OnGoldChanged;
Observer.WinLevel -= OnWinLevel;
}
void OnGoldChanged(int delta) { /* update HUD */ }
void OnWinLevel(Level level) { /* show confetti */ }Publishing an event:
Observer.GoldChanged?.Invoke(50); // notify all listenersAvailable events (selected):
| Event | Signature | When fired |
|---|---|---|
| StartLevel | Action<Level> | Level starts |
| WinLevel | Action<Level> | Player wins |
| LoseLevel | Action<Level> | Player loses |
| ReplayLevel | Action<Level> | Level replayed |
| SkipLevel | Action<Level> | Level skipped |
| GoldChanged | Action<int> | Gold amount changes |
| DiamondChanged | Action<int> | Diamond amount changes |
| EnergyChanged | Action<int> | Energy amount changes |
| MusicChanged | Action | Music volume changes |
| SoundChanged | Action | SFX volume changes |
| VibrationChanged | Action | Vibration toggle changes |
| EquipPlayerSkin | Action<string> | Skin equipped |
| Notify | Action<string, Vector3> | Floating text notification |
public static partial class Observer
{
public static Action<int> StarsChanged;
}Observer.StarsChanged?.Invoke(delta);Items (skins, weapon skins, etc.) are defined in Assets/_Project/Config/ItemConfig.asset.
Each ItemData entry has:
| Field | Type | Description |
|---|---|---|
| identity | string | Unique ID (e.g., "Skin_01") |
| itemType | ItemType | PlayerSkin or WeaponSkin |
| buyType | BuyType | How the item is obtained |
| skinPrefab | GameObject | The 3-D / 2-D skin prefab |
| shopIcon | Sprite | Thumbnail shown in the shop |
| price | int | Cost in gold (shown only when buyType == Money) |
BuyType values:
| Value | Meaning |
|---|---|
| Default | Free — unlocked automatically at startup |
| Money | Purchase with gold |
| DailyReward | Obtained via the daily reward calendar |
| WatchAds | Obtained by watching a rewarded ad |
| Event | Obtained during limited-time events |
Checking / granting ownership from code:
// Check if the player owns a skin
bool owns = Data.PlayerData.IsOwnedSkin("Skin_01");
// Grant a skin
Data.PlayerData.OwnedSkins.Add("Skin_01");
// Equip a skin
Data.PlayerData.CurrentSkin = "Skin_01";
Observer.EquipPlayerSkin?.Invoke("Skin_01");Configured in Assets/_Project/Config/DailyRewardConfig.asset.
Each DailyRewardData entry:
| Field | Description |
|---|---|
| dailyRewardType | Money or Skin |
| icon | Display sprite |
| value | Gold amount (Money type only) |
| skinID | Skin identity string (Skin type only) |
The DailyRewardController retrieves the correct reward using:
DailyRewardData reward = DailyRewardController.Instance.GetDailyRewardData(dayIndex);Claim logic lives in PopupDailyReward.cs and updates Data.PlayerData.CurrentDailyReward and Data.PlayerData.LastDailyRewardClaimed.
All packages live in Assets/_Project/~ExtensionPackages/ and are designed to work in any Unity project.
A lightweight tweening library — use instead of DOTween for smaller build sizes.
// Scale an object
Tween.Scale(transform, Vector3.zero, Vector3.one, duration: 0.5f, Ease.OutBack);
// Fade a CanvasGroup
Tween.Alpha(canvasGroup, from: 0f, to: 1f, duration: 0.3f);
// Chain animations in a Sequence
Sequence.Create()
.ChainDelay(1f)
.Chain(Tween.Scale(transform, Vector3.zero, Vector3.one, 0.5f, Ease.OutBack))
.ChainCallback(() => Debug.Log("Done!"))
.OnComplete(() => gameObject.SetActive(false));All tweens support useUnscaledTime: true so they work correctly when the game is paused (Time.timeScale = 0).
Provides attribute-based Inspector customization:
[ReadOnly] public int score; // Shows field but prevents editing
[ShowIf("isEnabled", true)] public float speed; // Conditional visibility
[Button]
public void ResetScore() { score = 0; } // Adds a clickable button in the Inspector
[TableList] public List<ItemData> items; // Renders a list as a compact tableEnhances the Hierarchy panel with color labels, icons, and separators. Configure via the GameBase menu in the Unity Editor.
Opens an editor window (Window → Custom Player Pref) that lets you read, edit, and delete all PlayerPrefs keys without writing code.
Right-click any asset in the Project window → Find References to see every scene, prefab, and asset that references it.
After a build, open Window → Build Report to see a breakdown of asset sizes, textures, audio, and scripts.
Accessible from the Home screen when GameConfig.isTesting = true. Lets you:
A floating, draggable console overlay (enabled when isTesting = true) with:
Access via Window → Custom Player Pref to view all saved PlayerPref keys directly in the Editor.
| Library | Purpose |
|---|---|
| LeanTouch | Multi-touch input and drag-and-drop |
| LeanPool | Object pooling for UI notifications and VFX |
| TextMesh Pro | High-quality text rendering |
| Spine | Skeletal animation runtime |
| Back | FazBrowse Home | New Git URL |