You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Unity中合理运用MVVM架构?

Unity中MVVM的View与ViewModel边界怎么划?

别纠结书本上的理论定义,直接看Unity场景下的职责拆分,绝对不违反单一职责:

  • View(UI层):只做两件事——把用户的点击/输入事件转发给ViewModel,以及根据ViewModel提供的数据更新UI显示。它就是个“传声筒+显示器”,半毛钱业务逻辑都不能有。
    比如你提到的Button,绝对不能在按钮脚本里写初始化子弹的代码,正确的做法是写个极简的转发脚本:

    using UnityEngine;
    using UnityEngine.UI;
    
    public class ButtonForwarder : MonoBehaviour
    {
        [SerializeField] private Button _fireButton;
        // 可以在Inspector拖入ViewModel实例,或者用依赖注入框架注入
        public WeaponViewModel WeaponVM;
    
        void Awake()
        {
            _fireButton.onClick.AddListener(WeaponVM.HandleFireRequest);
        }
    }
    

    这个脚本除了转发点击事件,啥也不干,完美符合SRP。

  • ViewModel(业务协调层):是纯C#类(别继承MonoBehaviour!),负责处理View传过来的用户请求,调用底层服务完成业务逻辑,同时暴露可被View绑定的属性。它完全不碰Unity的UI API,甚至不知道View长啥样。
    比如处理开火请求的ViewModel:

    public class WeaponViewModel
    {
        private readonly IBulletSpawner _bulletSpawner;
        // 用可观察对象实现数据绑定,让View自动更新弹药数
        public Observable<int> CurrentAmmo { get; private set; } = new Observable<int>(30);
    
        // 构造注入依赖,把真正的子弹初始化逻辑交给专门的服务
        public WeaponViewModel(IBulletSpawner bulletSpawner)
        {
            _bulletSpawner = bulletSpawner;
        }
    
        public void HandleFireRequest()
        {
            if (CurrentAmmo.Value <= 0) return;
            // 调用服务生成子弹,ViewModel只负责触发逻辑,不具体实现
            _bulletSpawner.SpawnBullet();
            CurrentAmmo.Value--;
        }
    }
    

    这里真正初始化子弹的是IBulletSpawner这个服务类,ViewModel只做业务协调,职责清晰。

  • 和MVC的核心区别:Unity里的MVC往往是Controller直接操作View(比如Controller直接找Text组件改文字),而MVVM里ViewModel只提供数据和命令,View通过数据绑定自动更新——ViewModel和View完全解耦,你换个UI布局,ViewModel不用改一行代码。

常见误区提醒:别把ViewModel做成挂在UI上的Mono脚本,那等于把ViewModel和View绑死了,完全失去了MVVM解耦的意义。ViewModel应该是独立的纯C#对象,通过依赖注入或者工厂创建后,交给View层的Mono脚本去绑定。

内容的提问来源于stack exchange,提问作者IndividualGames

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:20:40