A Unity UI framework by the PurrNet team featuring procedural UI rendering, view management, and UI pooling.
- Procedural UI - SDF-based rendering with
RectangleGraphicandGlowGraphic(for glow/shadows) - View Management -
ViewStackandViewCollectionfor managing UI views with transition support
Latest release:
https://github.com/PurrNet/PurrUI.git?path=Assets/PurrUI#release
Latest development:
https://github.com/PurrNet/PurrUI.git?path=Assets/PurrUI#dev
PurrUI provides a stack-based view navigation system for Unity. Views are managed through a ViewStack that handles pushing, popping, ordering, visibility, and animated transitions.
All classes live in the PurrNet.UI namespace.
| Class | Type | Purpose |
|---|---|---|
ViewStack |
MonoBehaviour | Navigation controller that manages a stack of views |
MonoView |
MonoBehaviour | Base class for all views |
ViewCollection |
ScriptableObject | Asset that holds references to view prefabs |
ViewTransitions |
Static class | Built-in transition animations (fade, slide, etc.) |
Right-click in your Project window and select Create > PurrNet > View Collection.
A ViewCollection is a ScriptableObject that stores references to your view prefabs. It has two modes:
- Auto Generate (default): Assign folders to watch and the collection automatically discovers all
MonoViewprefabs inside them. It refreshes whenever assets change. - Manual: Disable
autoGenerateand drag prefabs into theviewsarray yourself.
Each view is a prefab with a MonoView (or subclass) component on its root GameObject. MonoView automatically requires a Canvas and CanvasGroup, so those are added for you.
Add a ViewStack component to a GameObject. In the inspector, configure:
- Parent: The transform where instantiated views will be parented (defaults to the ViewStack's own transform).
- Prefabs: Your
ViewCollectionasset. - Push On Start (optional): A view to automatically push when the scene starts.
- Order Offset: An offset applied to canvas sorting order values.
Subclass MonoView to create your own views:
using PurrNet.UI;
using UnityEngine;
public class ProfileView : MonoView
{
[SerializeField] private TMPro.TMP_Text _username;
[SerializeField] private TMPro.TMP_Text _bio;
public void Setup(string username, string bio)
{
_username.text = username;
_bio.text = bio;
}
}We follow a convention of adding a Setup method to views that need initialization data. This is not enforced by the base class — it's simply a pattern. The idea is that Setup is called immediately after pushing:
_stack.Push<ProfileView>().Setup("Jane", "Hello world!");All built-in views provided by PurrUI follow this pattern. You are encouraged to do the same for consistency, but it is not required.
There are two ways to push a view onto the stack:
// Generic push — looks up the prefab by type from the ViewCollection
var view = _stack.Push<DialogView>();
// Direct prefab push
var view = _stack.Push(someViewPrefab);When a view is pushed:
- The current top view (if any) is moved to the background (raycasts disabled).
- The prefab is instantiated under the configured parent transform.
- The view is initialized and assigned a sorting order.
- If the view defines an enter transition, it plays (raycasts are blocked until it completes).
// Pop the top view
_stack.Pop();
// Pop a specific view instance (regardless of position in the stack)
_stack.Pop(viewInstance);
// From inside a view — call CloseMe() (can be wired to a button in the inspector)
CloseMe();When a view is popped:
- If the view defines an exit transition, it plays before the view is destroyed.
- The new top view is moved to the foreground (raycasts re-enabled,
OnBecomeForegroundcalled).
// Remove all views from the stack (exit transitions play for each)
_stack.Clear();
// Move an existing view to the top of the stack
_stack.MoveToTop(viewInstance);
_stack.MoveToTop<DialogView>();Override OnEnterTransition and OnExitTransition in your MonoView subclass to define animated transitions. They return IEnumerator coroutines.
public class MyView : MonoView
{
[SerializeField] private RectTransform _content;
protected override IEnumerator OnEnterTransition()
{
return ViewTransitions.FadeIn(this);
}
protected override IEnumerator OnExitTransition()
{
return ViewTransitions.FadeOut(this);
}
}ViewTransitions provides ready-to-use animations. All use smoothstep easing and unscaled time (unaffected by Time.timeScale). Default duration is 0.2s.
Fade:
ViewTransitions.FadeIn(view, duration)
ViewTransitions.FadeOut(view, duration)
ViewTransitions.Fade(canvasGroup, fromAlpha, toAlpha, duration)Slide:
ViewTransitions.SlideFromLeft(content, duration)
ViewTransitions.SlideToLeft(content, duration)
ViewTransitions.SlideFromRight(content, duration)
ViewTransitions.SlideToRight(content, duration)
ViewTransitions.SlideFromTop(content, duration)
ViewTransitions.SlideToTop(content, duration)
ViewTransitions.SlideFromBottom(content, duration)
ViewTransitions.SlideToBottom(content, duration)Slide methods operate on a RectTransform (typically a child content container, not the root view), using anchoredPosition and the rect's own width/height to calculate offsets.
Use ViewTransitions.Parallel to run multiple transitions at the same time:
protected override IEnumerator OnEnterTransition()
{
var fade = ViewTransitions.FadeIn(this);
var slide = ViewTransitions.SlideFromLeft(_content);
return ViewTransitions.Parallel(fade, slide);
}
protected override IEnumerator OnExitTransition()
{
var fade = ViewTransitions.FadeOut(this);
var slide = ViewTransitions.SlideToRight(_content);
return ViewTransitions.Parallel(fade, slide);
}- Sorting Order: Each view in the stack is assigned an incrementing sorting order (plus
_orderOffset), so views higher in the stack render on top. - Raycasts: Only the top view receives raycasts. Views below the top have raycasts disabled.
- Cull Windows Behind: If a view has
cullWindowsBehindenabled, all views below it in the stack have theirCanvasdisabled entirely. Useful for fullscreen views where nothing behind them is visible. - OnBecomeForeground: Override this virtual method in your
MonoViewsubclass to react when the view returns to the top of the stack (e.g., after the view above it is popped).