Unity MVVM UniTask + 轻量级 ReactiveProperty

1. 负责数据绑定的"轻量级 ReactiveProperty"
cs 复制代码
using System;

// 极其轻量、0 GC 负担的响应式属性(示意版)
public class ReactiveProperty<T>
{
    private T _value;
    private Action<T> _onValueChanged;

    public T Value
    {
        get => _value;
        set
        {
            // 如果值没变,就不触发事件(防抖)
            if (Object.Equals(_value, value)) return; 
            _value = value;
            _onValueChanged?.Invoke(_value); // 通知所有订阅者
        }
    }

    public ReactiveProperty(T initialValue = default)
    {
        _value = initialValue;
    }

    // 提供给 UI 绑定的方法,返回一个可解绑的 Action
    public IDisposable Subscribe(Action<T> action)
    {
        _onValueChanged += action;
        action?.Invoke(_value); // 订阅时立刻推送一次当前值,让 UI 初始化
        return new Unsubscriber(() => _onValueChanged -= action);
    }
    
    // 内部类用于优雅解绑
    private class Unsubscriber : IDisposable
    {
        private Action _unsubscribe;
        public Unsubscriber(Action unsubscribe) => _unsubscribe = unsubscribe;
        public void Dispose() => _unsubscribe?.Invoke();
    }
}
Step 1: 编写 ViewModel(数据与逻辑中心)

这里包含了轻量级的状态数据,以及使用 UniTask 编写的线性业务流程。

cs 复制代码
using Cysharp.Threading.Tasks;
using UnityEngine;
using System.Threading;

public class ChestViewModel
{
    // 💡 纯粹的数据流:只负责保存状态,并在改变时向外广播
    public ReactiveProperty<string> ChestStateText { get; } = new ReactiveProperty<string>("点击开启宝箱");
    public ReactiveProperty<bool> IsButtonInteractable { get; } = new ReactiveProperty<bool>(true);

    // 💡 纯粹的控制流:使用 UniTask 串联整个异步逻辑
    // 传入 CancellationToken 是为了防止玩家在开箱中途关掉界面导致的空引用报错
    public async UniTask OpenChestAsync(CancellationToken token)
    {
        // 1. 改变状态:锁定按钮,更新文本
        IsButtonInteractable.Value = false;
        ChestStateText.Value = "宝箱正在开启中...";

        try
        {
            // 2. 等待宝箱抖动动画(等待 1 秒)
            // 魔法:Delay 不会产生任何 GC,且受 Unity TimeScale 影响
            await UniTask.Delay(1000, cancellationToken: token);

            // 3. 模拟网络请求战利品(等待 0.5 秒)
            ChestStateText.Value = "正在连接服务器...";
            await UniTask.Delay(500, cancellationToken: token); 
            string loot = "SSR 传说级大剑!🗡️"; // 假设这是网络返回的数据

            // 4. 最终展示结果
            ChestStateText.Value = $"开启成功!获得:{loot}";
        }
        catch (OperationCanceledException)
        {
            // 玩家中途关闭了界面,任务被优雅取消,不会有任何报错!
            Debug.Log("开箱流程被中断。");
        }
        finally
        {
            // 无论成功还是被取消,最终都可以执行清理逻辑
            IsButtonInteractable.Value = true;
        }
    }
}
Step 2: 编写 View(视图表现层)

UI 脚本现在变得 极其清爽 ,它只做两件事:把数据绑定到 UI 组件上,以及把用户的点击事件转发给 ViewModel。

cs 复制代码
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;
using System.Threading;

public class ChestView : MonoBehaviour
{
    public Text stateText;
    public Button openButton;

    private ChestViewModel _viewModel;
    private CancellationTokenSource _cts;

    void Start()
    {
        _viewModel = new ChestViewModel();
        _cts = new CancellationTokenSource(); // 用于管理异步任务的生命周期

        // 🌟 1. UI 数据绑定:将 ViewModel 的数据连接到 UI 元素
        _viewModel.ChestStateText.Subscribe(text => stateText.text = text);
        _viewModel.IsButtonInteractable.Subscribe(interactable => openButton.interactable = interactable);

        // 🌟 2. 事件转发:按钮点击触发 ViewModel 的异步流程
        openButton.onClick.AddListener(() =>
        {
            // Fire and Forget (触发并忘记),启动异步任务
            _viewModel.OpenChestAsync(this.GetCancellationTokenOnDestroy()).Forget();
        });
    }

    void OnDestroy()
    {
        // View 销毁时,取消所有正在进行的异步任务,防止内存泄漏或空引用!
        _cts.Cancel();
        _cts.Dispose();
    }
}
相关推荐
点心的游戏开发世界2 小时前
Unity C# 脚本学习笔记:命名空间与 using
学习·unity·c#
点心的游戏开发世界3 小时前
Unity C# 脚本学习笔记:泛型
学习·unity·c#
微三云生态系统架构师-彭丹2 天前
任务卷轴积分系统架构设计:从任务状态机到合规风控的完整实现
unity·系统架构·游戏引擎
XR技术研习社2 天前
从 PICO 文档看未来短期内的 Unity 版本选择
unity·游戏引擎·xr·vr
玖玥拾2 天前
Unity 热更新(一)
unity·游戏引擎
软件黑马王子2 天前
1.non-MonoBehaviour 单例模式泛型基类
unity·前端框架·c#
KhalilRuan2 天前
Unity性能优化
unity·性能优化·游戏引擎
ellis19702 天前
u3d IMGUI[二] 编辑器扩展
unity
五仁烧饼3 天前
Unity性能优化系列内存篇 - 移动端内存优化
unity·性能优化·游戏引擎
zhchyun20086 天前
# 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(06)
ui·unity·游戏引擎