Unity 虚拟仿真实验中设计模式的使用 —— 观察者模式(Observer Pattern)

📖 目录

  1. 前言

  2. 什么是观察者模式

  3. 案例背景:虚拟仿真水温实验

  4. 案例效果图(示意)

  5. 代码实现

    • 5.1 被观察者:WaterHeater

    • 5.2 观察者:ThermometerUI

    • 5.3 观察者:ExperimentLogger

    • 5.4 观察者:BoilingAlert

    • 5.5 UI 控制:HeatButton

  6. 运行流程

  7. 注意事项总结

  8. 扩展思考

  9. 总结


1. 前言

在 虚拟仿真实验 或 教学类项目 中,经常会遇到类似的场景:

  • 实验数据变化时,需要同时更新 UI、日志、提示系统。

  • 如何做到 解耦,避免系统间的强依赖?

👉 答案就是:观察者模式(Observer Pattern)。

本文通过一个 Unity Demo 案例,带大家学习观察者模式在虚拟仿真中的应用。


2. 什么是观察者模式

观察者模式 :定义了一种 一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会自动收到通知。

在 Unity 中,通常通过 事件(event)或委托(delegate) 来实现。


3. 案例背景:虚拟仿真水温实验

我们实现一个 加热水温实验:

  • 玩家点击按钮加热水温(被观察者)。

  • 水温变化时:

    1. 温度计 UI 实时更新

    2. 实验日志记录变化

    3. 超过 100℃ 时提示"水已沸腾"

👉 这个场景中,"水温"就是 被观察者 ,UI/日志/提示系统就是 观察者。


4. 案例效果图(示意)

css 复制代码
[按钮:加热]
       ↓
[当前温度:80℃]   ← 温度计 UI 更新
[日志:温度变化为 80℃]  ← 日志记录
[提示:未沸腾]   ← 警告系统未触发

点击按钮后,温度升高 10℃,所有观察者自动收到通知。


5. 代码实现

5.1 被观察者:WaterHeater(加热器)

cs 复制代码
using System;
using UnityEngine;

public class WaterHeater : MonoBehaviour
{
    public event Action<int> OnTemperatureChanged; // 事件:温度变化通知

    private int temperature = 20; // 初始温度

    public void HeatUp()
    {
        temperature += 10;
        Debug.Log($"[WaterHeater] 当前温度: {temperature}℃");
        OnTemperatureChanged?.Invoke(temperature); // 通知所有观察者
    }

    public int GetTemperature() => temperature;
}

5.2 观察者:ThermometerUI(温度计 UI)

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class ThermometerUI : MonoBehaviour
{
    [SerializeField] private Text temperatureText;
    [SerializeField] private WaterHeater waterHeater;

    private void OnEnable()
    {
        waterHeater.OnTemperatureChanged += UpdateUI;
    }

    private void OnDisable()
    {
        waterHeater.OnTemperatureChanged -= UpdateUI;
    }

    private void UpdateUI(int temperature)
    {
        temperatureText.text = $"温度: {temperature}℃";
    }
}

5.3 观察者:ExperimentLogger(实验日志)

cs 复制代码
using UnityEngine;

public class ExperimentLogger : MonoBehaviour
{
    [SerializeField] private WaterHeater waterHeater;

    private void OnEnable()
    {
        waterHeater.OnTemperatureChanged += LogTemperature;
    }

    private void OnDisable()
    {
        waterHeater.OnTemperatureChanged -= LogTemperature;
    }

    private void LogTemperature(int temperature)
    {
        Debug.Log($"[ExperimentLogger] 记录日志:温度变化为 {temperature}℃");
    }
}

5.4 观察者:BoilingAlert(沸腾提示)

cs 复制代码
using UnityEngine;

public class BoilingAlert : MonoBehaviour
{
    [SerializeField] private WaterHeater waterHeater;

    private void OnEnable()
    {
        waterHeater.OnTemperatureChanged += CheckBoiling;
    }

    private void OnDisable()
    {
        waterHeater.OnTemperatureChanged -= CheckBoiling;
    }

    private void CheckBoiling(int temperature)
    {
        if (temperature >= 100)
        {
            Debug.Log("[BoilingAlert] ⚠️ 水已沸腾!");
        }
    }
}

5.5 UI 控制:HeatButton(按钮)

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class HeatButton : MonoBehaviour
{
    [SerializeField] private Button heatButton;
    [SerializeField] private WaterHeater waterHeater;

    private void Start()
    {
        heatButton.onClick.AddListener(() => waterHeater.HeatUp());
    }
}

6. 运行流程

  1. 玩家点击 加热按钮 → WaterHeater.HeatUp()

  2. OnTemperatureChanged 事件触发

  3. 所有观察者收到通知:

    • ThermometerUI 更新 UI

    • ExperimentLogger 写日志

    • BoilingAlert 检查是否沸腾

👉 解耦效果:

  • WaterHeater 只负责 通知,不关心谁在监听。

  • 观察者们只关心自己逻辑,随时可新增/移除。


7. 注意事项总结

  • 事件解绑 :

    使用 OnDisable 取消订阅,避免内存泄漏或空引用错误。

  • 事件为空判断 :

    使用 OnTemperatureChanged?.Invoke(value),避免 NullReferenceException。

  • 避免强依赖 :
    WaterHeater 不直接调用 UI / 日志 / 提示,而是通过事件通知。


8. 扩展思考

  • 可以新增 成绩统计系统,订阅水温变化来计算实验得分。

  • 可以新增 数据上传系统,把实验数据同步到后台。

  • 可以改为 ScriptableObject Event,进一步解耦 UI 和逻辑。


9. 总结

通过这个虚拟仿真案例,你学会了:

  • 如何用 观察者模式 解耦系统之间的依赖

  • 如何通过 事件机制 在 Unity 中实现一对多通知

  • 如何把这个模式应用到虚拟仿真实验中(UI、日志、提示、成绩等系统)

👉 这就是 Unity 中观察者模式的最佳实践!

相关推荐
博风5 小时前
7、设计模式应用举例:策略模式:加密、解密文件
设计模式·策略模式
地狱为王5 小时前
Unity使用DPDFNet实现实时语音增强(降噪)
unity·语音增强·降噪·dpdfnet
4SAPI6 小时前
Provider Adapter设计模式:如何让AI应用支持多个模型
网络·人工智能·设计模式
平行云PVT6 小时前
国产信创实时云渲染解决方案:如何实现数字孪生与三维应用云化部署?
unity·webrtc·unreal engine·实时云渲染·国产信创·摩尔线程·砺算科技
夏炎黄7 小时前
Terrain地形剪裁
unity
geovindu8 小时前
rust: pool Pattern
开发语言·后端·设计模式·rust·对象池简写模式
高晶8 小时前
ARM 嵌入式 Linux 开发:从体系结构到 LED 点亮实战
设计模式·程序员
VimorphTech8 小时前
接入两套 TTS 接口后,业务代码如何避免堆满 if/else?
设计模式
小贺儿开发9 小时前
DeepSeek + Codex + MCP:Unity 游戏开发实测
科技·游戏·unity·ai·程序员·编程·deepseek
新的瑞拉公主9 小时前
Cocos plist 粒子一键导入 Unity:Editor 工具实现与参数映射
unity·游戏开发·cocos2d-x·粒子系统·editor工具