SkillAgentSearch skills...

MacacaViewSystem

ViewSystem is a element based UI management system based on Unity GUI

Install / Use

/learn @MacacaGames/MacacaViewSystem
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

ViewSystem

English | 中文

ViewSystem is an element-based UI management system for Unity, developed by Macaca Games. It simplifies complex UI workflows with a visual node editor, element pooling, and runtime property/event overrides.

Why ViewSystem?

UI development in Unity often suffers from tight coupling between layout, logic, and data — and the workflow tends to bottleneck on engineers. Designers hand off mockups, engineers rebuild them in Unity, and the gap between "design intent" and "implementation result" leads to endless back-and-forth over pixel-level details.

ViewSystem addresses this by separating concerns across roles:

  • ViewElement defines what a UI element looks like and how it animates — not where it goes.
  • ViewPage defines where elements are placed — configurable in the Visual Editor without code.
  • Runtime Override lets designers tweak properties (text, color, sprites, layout) per page directly in the editor — no Prefab Variants, no code changes.
  • Model Injection lets engineers focus purely on data flow and logic, while the visual configuration stays in the editor.

The result: designers own the visual details, engineers own the behavior and data — each working in their own domain with minimal handoff friction.

Use Cases

<img src="./Img~/skySurfing.gif"> <img src="./Img~/skyBandit.gif"> <img src="./Img~/rythemGo.gif">

Features

  • Element-based architecture — compose UI pages from reusable ViewElements
  • ViewElement pooling — automatic pool management for optimal performance
  • Runtime property & event overrides — create ViewElement variants per page without prefab variants
  • Node-based visual editor — design and preview UI pages directly in the editor
  • Fluent API — chain page transitions with a clean, readable syntax
  • Lifecycle hooks & dependency injectionIViewElementLifeCycle, ViewElementBehaviour, and [ViewElementInject]
  • Safe Area support — per-page or global safe area configuration
  • Breakpoint system — responsive ViewElement transforms based on named breakpoints

Installation

Option 1: OpenUPM (Recommended)

openupm add com.macacagames.viewsystem

Option 2: Unity Package Manager (Git URL)

Add to your Packages/manifest.json:

{
    "dependencies": {
        "com.macacagames.utility": "https://github.com/MacacaGames/MacacaUtility.git",
        "com.macacagames.viewsystem": "https://github.com/MacacaGames/MacacaViewSystem.git"
    }
}

Option 3: Git Submodule

git submodule add https://github.com/MacacaGames/MacacaViewSystem.git Assets/MacacaViewSystem
git submodule add https://github.com/MacacaGames/MacacaUtility.git Assets/MacacaUtility

Core Concepts

ViewElement

The base unit of ViewSystem. Any UI item on a page (button, icon, panel, etc.) can be a ViewElement.

<img src='./Img~/viewelement.png' alt="ViewElement example" height="400">

A ViewElement defines how it appears and disappears, but not where it will be placed. There are 5 transition types:

| Transition | Description | |---|---| | Animator | Triggers Animator states (Show, Loop, Leave) | | Canvas Group Alpha | Tweens CanvasGroup alpha for fade in/out | | Active Switch | Toggles GameObject.activeSelf | | ViewElement Animation | Built-in tween for transform (position, rotation, scale) and alpha | | Custom | Fires a UnityEvent for full control |

ViewPage

A ViewPage composes one or more ViewElements and defines where each should be placed. Two types:

  • FullPage — Only one can be displayed at a time. Switching pages automatically leaves the current FullPage and shows the next.
  • OverlayPage — Displays on top of the current screen. Multiple OverlayPages can coexist. Ideal for dialogs, loading screens, etc.

ViewState

Defines shared ViewElement layouts across multiple ViewPages. Each ViewPage can reference at most one ViewState. ViewElements in a ViewState persist until the ViewState itself changes.

ViewController

The core singleton that manages all page transitions and ViewElement lifecycle.

Quick Start

1. Setup ViewController

Create a GameObject in your scene and attach the ViewController component. Assign your ViewSystemData asset.

2. Create UI Root

Open MacacaGames > ViewSystem > Visual Editor, click Global Setting, then Generate default UI Root Object.

3. Create a ViewElement

Create a UI object (Image, Button, etc.), attach the ViewElement component, and save as a prefab.

4. Create a ViewPage

In the Visual Editor, right-click > Add FullPage, then add your ViewElement to the page's ViewPageItems.

5. Show a Page

public class GameStart : MonoBehaviour
{
    void Awake()
    {
        ViewController
            .FullPageChanger()
            .SetPage("TestPage")
            .Show();
    }
}

Page Transition API

ViewSystem uses a Fluent Interface via PageChanger:

// FullPage — auto-leaves previous page
ViewController
    .FullPageChanger()
    .SetPage("MyPage")
    .SetPageModel(someData, "hello")   // inject data into ViewElements
    .SetIgnoreClickProtection(false)    // enable click debounce (default 0.2s)
    .SetWaitPreviousPageFinish(true)    // queue transition instead of cancel
    .SetIgnoreTimeScale(true)           // ignore Time.timeScale
    .OnStart(() => Debug.Log("Start"))
    .OnComplete(() => Debug.Log("Done"))
    .Show();

// OverlayPage — must manually Show/Leave
ViewController
    .OverlayPageChanger()
    .SetPage("DialogPage")
    .Show();

// Leave an OverlayPage
ViewController
    .OverlayPageChanger()
    .SetPage("DialogPage")
    .Leave();

Runtime Overrides

Override any property on a ViewElement per-page — no prefab variants needed:

<img src="./Img~/override_demo.gif" />

Via Visual Editor

Set property overrides directly in the ViewSystem Editor's Override Window.

Via Script (Attribute)

public class MyUILogic : ViewElementBehaviour
{
    [OverrideProperty("Frame", typeof(Image), nameof(Image.sprite))]
    [SerializeField]
    Sprite someSprite;

    [OverrideButtonEvent("TopRect/Button")]
    void OnButtonClick(Component component)
    {
        Debug.Log("Clicked!");
    }
}

Via Script (ViewElementOverride)

public class MyScript : MonoBehaviour
{
    [SerializeField]
    ViewElementOverride myOverride;

    void ApplyOverride()
    {
        GetComponent<ViewElement>().ApplyOverrides(myOverride);
    }
}

Event Override

Declare methods with [ViewSystemEvent] to make them available in the Override Window:

[ViewSystemEvent("MyGroup")]
public void OnConfirmClick(Component selectable)
{
    // Handle click
}

Lifecycle Hooks & Injection

IViewElementLifeCycle

Implement on any MonoBehaviour attached to a ViewElement:

public class MyUI : MonoBehaviour, IViewElementLifeCycle
{
    public void OnBeforeShow() { }
    public void OnBeforeLeave() { }
    public void OnStartShow() { /* ViewElement is now visible */ }
    public void OnStartLeave() { }
    public void OnChangePage(bool show) { }
    public void OnChangedPage() { }
    public void RefreshView() { }
}

ViewElementBehaviour

A convenience base class implementing IViewElementLifeCycle with UnityEvent inspector support:

public class MyUI : ViewElementBehaviour
{
    public override void OnStartShow()
    {
        RefreshView();
    }
}

Model Injection ([ViewElementInject])

Send data to ViewElements when changing pages:

public class MyUILogic : ViewElementBehaviour
{
    [ViewElementInject]
    int score;

    [ViewElementInject]
    string playerName { get; set; }
}

// Pass data via SetPageModel
ViewController.FullPageChanger()
    .SetPage("ResultPage")
    .SetPageModel(99999, "Player1")
    .Show();

Combine with override for one-liner data binding:

[ViewElementInject]
[OverrideProperty("Text", typeof(TextMeshProUGUI), nameof(TextMeshProUGUI.text))]
string displayText;

For multiple values of the same type, use ViewInjectDictionary<T>:

var data = new ViewInjectDictionary<string>();
data.TryAdd("title", "Hello");
data.TryAdd("subtitle", "World");

ViewController.FullPageChanger()
    .SetPage("MyPage")
    .SetPageModel(data)
    .Show();

Shared Model

IViewElementSingleton instances automatically become Shared Models, available to all pages without SetPageModel():

public class CurrencyDisplay : ViewElementBehaviour, IViewElementSingleton { }

// Inject anywhere without SetPageModel
public class ShopUI : ViewElementBehaviour
{
    [ViewElementInject]
    CurrencyDisplay currency; // auto-injected
}

Control search scope with InjectScope:

[ViewElementInject(InjectScope.SharedOnly)]
MyClass myData;

Components

ViewElementGroup

Propagates OnShow/OnLeave to child ViewElements (similar to CanvasGroup). Enable Only Manual Mode to control show/leave from script:

[SerializeField] ViewElement child;

child.OnShow(true);              // manual show
child.OnLeave(false, true);      // manual leave without pooling

Visual Editor

Open via MacacaGames > ViewSystem > Visual Editor.

| Tool | Description | |---|---| | Edit Mode | Preview ViewPages in edit time with a temporary scene | | Save | Save all changes and exit Edit Mode | | Global Setting | UI Root generation, Safe Area config, breakpoints, click protection interval | | Overlay Order | Drag-and-drop sort order for overlay pages | | Bake to Script | Generate C# constants for ViewPage/ViewState names | | Verifiers | Check for missing GameObjects, overrides, events, and page references |

Bake to Script

Generate type-safe page name constants:

ViewControll
View on GitHub
GitHub Stars119
CategoryDevelopment
Updated2h ago
Forks12

Languages

HTML

Security Score

100/100

Audited on Apr 3, 2026

No findings