Skip to main content

Getting Started

A step-by-step guide from installation to the first working example.

Contents


Requirements

  • Unity 2022.3 or newer
  • .NET Standard 2.0 (the framework's target)
  • Source Generators support in Unity (built in since 2022.3)

Installation

From the Unity Asset Store

  1. Open the Aspid.MVVM page in the Unity Asset Store
  2. Import the package into your project
  3. Make sure the Assets/Aspid/MVVM/ folder was created

From source

git clone https://github.com/VPDPersonal/Aspid.MVVM.git
cd Aspid.MVVM
git submodule update --init --recursive
info

The project uses git submodules. Without git submodule update --init --recursive the code does not compile.


Learning path

Each sample adds exactly one new concept. Every sample's README.md is its tutorial.

#SampleNewTutorial
1Counter[ViewModel], [Bind], [RelayCommand], ViewInitializerCounter
2GreeterMonoViewModel, [TwoWayBind], [BindAlso], On*ChangedGreeter
3Bind Modesfour modes on one screen, your own ITwoWayConverterBind Modes
4Statscommands with a parameter, CanExecute, draft → modelStats
5Todo Lista model, ObservableList, CreateSync, collection bindersTodo List
6Custom Bindera binder for your own component, [GenerateSerializableBinder]Custom Binder

First example: Counter

A button increments a counter and the number is shown in a text. The smallest example that shows the three core concepts of the framework.

Step 1: ViewModel

The ViewModel holds data and logic. The Source Generator writes all the binding code.

using Aspid.MVVM;

// [ViewModel] marks the class for the Source Generator.
// The class must be partial.
[ViewModel]
public sealed partial class CounterViewModel
{
// [OneWayBind]: data flows from the ViewModel to the View only.
// The generator emits a Count property whose setter notifies binders.
[OneWayBind] private int _count;

// [RelayCommand]: the generator emits an IncrementCommand property of type IRelayCommand.
[RelayCommand]
private void Increment() => Count++;
}

What the Source Generator produces:

SourceGenerated
[ViewModel] on the classIViewModel implementation, FindBindableMember
[OneWayBind] int _countCount property with a notifying setter, OnCountChanging / OnCountChanged hooks
[RelayCommand] void Increment()IncrementCommand property of type IRelayCommand

Step 2: View

The View declares which binders connect to which ViewModel members.

using UnityEngine;
using Aspid.MVVM;

// [View] marks the class for the Source Generator.
// The class must be partial.
[View]
public sealed partial class CounterView : MonoView
{
// The field name matches the ViewModel field name.
// The generator binds them by name.
[SerializeField] private MonoBinder _count;

// An array of binders: several UI elements trigger the same action.
[SerializeField] private MonoBinder[] _increment;
}
note

Naming rule: the View field name without the _, m_ or s_ prefix must match the ViewModel member. _count binds to Count.

Step 3: Bootstrap

Bootstrap connects the View and the ViewModel:

using UnityEngine;
using Aspid.MVVM;

public sealed class Bootstrap : MonoBehaviour
{
[SerializeField] private CounterView _counterView;

private void Awake()
{
var viewModel = new CounterViewModel();
_counterView.Initialize(viewModel);
}

private void OnDestroy()
{
_counterView.DeinitializeView()?.DisposeViewModel();
}
}

Step 4: Inspector setup

  1. Create a GameObject with the CounterView component
  2. Add a child with a TextMonoBinder and drag it into the _count field
  3. Add a child with a Button and a ButtonCommandMonoBinder and drag it into the _increment array
  4. On the Bootstrap object assign the CounterView reference

How it works

After view.Initialize(viewModel):

  1. View walks its binders and calls viewModel.FindBindableMember(id) for each
  2. ViewModel (generated code) finds the BindableMember by id without reflection
  3. Binder subscribes and receives the current value
  4. When Count changes, the binder updates the Text
  5. When the button is pressed, ButtonCommandMonoBinder calls IncrementCommand.Execute()
ViewModel ──► BindableMember ──► Binder ──► UI
(no reflection, direct calls)
note

The Source Generator emits direct calls at compile time: no reflection, no allocations.


Next steps

  • Counter, the full tutorial with binder details
  • Greeter, two-way binding: InputField → Text in real time
  • Architecture, the binding pipeline in detail
  • Binding Modes: OneWay, TwoWay, OneTime, OneWayToSource
  • StarterKit, every ready-made binder for Unity UI