响应式编程入门教程第一节:揭秘 UniRx 核心 - ReactiveProperty - 让你的数据动起来!-CSDN博客

响应式编程入门教程第二节:构建 ObservableProperty<T> — 封装 ReactiveProperty 的高级用法-CSDN博客

今天我们来聊聊 Unity 开发中的一个利器:UniRx。如果你还在为各种数据变化、事件通知、异步操作的混乱代码而头疼,那么 UniRx 绝对能为你打开一扇新大门。

在 UniRx 众多强大而复杂的概念中,我们今天首先要深入了解一个非常核心且实用的成员——ReactiveProperty<T>。掌握了它,你就掌握了 UniRx 在数据绑定和状态管理方面最常用的能力。

什么是 ReactiveProperty?

简单来说,ReactiveProperty<T> 是 UniRx 库提供的一个“可观察的属性”。你可以把它想象成一个拥有自带事件订阅能力的普通变量:当你修改它的值时,所有关心这个值变化的地方都会立即收到通知。

在传统的 Unity 开发中,我们经常使用事件(Events)、委托(Delegates)或回调函数来处理数据变化。例如,为了追踪玩家生命值的变化,你可能会这样写:

public class PlayerStats
{private int _health;public event Action<int> OnHealthChanged; // 使用事件来通知变化public int Health{get => _health;set{if (_health != value) // 只有值真的改变了才触发{_health = value;OnHealthChanged?.Invoke(_health); // 手动触发事件}}}
}

这段代码看似没问题,但当项目中需要追踪多个属性、它们之间有依赖关系,或者涉及复杂的异步操作时,代码就会变得越来越庞大和复杂。你需要手动管理各种事件的订阅和取消订阅,稍不注意就可能引入 Bug 或内存泄漏。

而 **ReactiveProperty<T> 的出现,就是为了以一种更优雅、更“响应式”的方式来解决这些问题。**它将数据的变化视为一个可以被观察的序列,让你的代码逻辑更加清晰和模块化。

ReactiveProperty 的核心特性

ReactiveProperty<T> 能够实现数据通知,主要得益于它的几个核心特性:

  • 数据绑定与通知自动化: ReactiveProperty<T> 最强大的地方在于它的值变化时会自动发出通知。这意味着你可以轻松地将 UI 元素、游戏逻辑或其他系统与 ReactiveProperty<T> 绑定起来。当 ReactiveProperty<T> 的值改变时,所有订阅者都会收到通知并执行相应的逻辑,无需像传统方式那样手动去调用事件。

  • 泛型支持: ReactiveProperty<T> 是一个泛型类 (ReactiveProperty<int>ReactiveProperty<string>ReactiveProperty<bool> 甚至是你自定义的类型,比如 ReactiveProperty<PlayerState>)。这种设计让它可以包装任何类型的数据,极大地增加了代码的通用性和复用性。

  • 强大的订阅机制 (Subscription): 通过 Subscribe() 方法,你可以非常方便地监听 ReactiveProperty<T> 的值变化。每次 Value 更新时,你订阅的回调函数就会被执行。

using UniRx; // 别忘了引入 UniRx 命名空间
using UnityEngine;
using System; // 包含 Action 和 IDisposablepublic class ReactivePropertyExample : MonoBehaviour
{// 1. 创建一个初始值为100的 ReactiveProperty<int>private ReactiveProperty<int> playerHealth = new ReactiveProperty<int>(100);void Start(){Debug.Log($"玩家初始生命值:{playerHealth.Value}"); // 输出:玩家初始生命值:100// 2. 订阅 playerHealth 的变化// 当 playerHealth.Value 改变时,Lambda 表达式中的代码会被执行// Subscribe 方法会返回一个 IDisposable 对象IDisposable healthSubscription = playerHealth.Subscribe(newHealth =>{Debug.Log("玩家生命值变化,当前为:" + newHealth);// 在这里可以更新 UI 文本,播放音效,触发游戏逻辑等});// 3. 改变值,触发订阅playerHealth.Value = 90; // 输出:玩家生命值变化,当前为:90playerHealth.Value = 80; // 输出:玩家生命值变化,当前为:80// 4. 当不再需要监听时,记得取消订阅以防止内存泄漏// healthSubscription.Dispose();// 在 Unity 中,我们通常会使用更方便的方式...}
}

关于 IDisposableDispose() 每一次调用 Subscribe() 都会建立一个订阅关系。如果不及时取消,即使订阅者对象(比如 MonoBehaviour)已经被销毁,订阅关系依然存在,可能导致内存泄漏,甚至在已销毁的对象上调用回调函数导致空引用异常IDisposable 接口就是为了提供一种统一的资源释放机制。调用 Dispose() 就能断开订阅。

在 Unity 中,UniRx 提供了一个非常方便的扩展方法 AddTo(),它可以自动管理订阅的生命周期。你通常会看到这样的用法:

playerHealth.Subscribe(newHealth => {// ...你的逻辑
}).AddTo(this); // 当当前 MonoBehaviour (this) 被销毁时,这个订阅会自动取消

强烈推荐你在 Unity 项目中始终使用 AddTo() 来管理订阅,它能大大简化你的代码并有效防止内存泄漏。

  • 初始值发射: ReactiveProperty<T> 在被订阅时,会立即发射一次当前的值。这是一个重要的特性,它确保了订阅者在订阅后能立刻获取到当前状态,例如在 UI 初始化时直接显示正确的值,而无需额外编写初始化逻辑。
    ReactiveProperty<int> score = new ReactiveProperty<int>(0);// 假设在游戏开始时订阅
    score.Subscribe(currentScore => {Debug.Log("当前分数:" + currentScore); // 立即输出 "当前分数:0"
    }).AddTo(this);score.Value = 100; // 再次输出 "当前分数:100"

什么时候使用 ReactiveProperty?

ReactiveProperty<T> 在以下场景中会发挥巨大作用:

  • 数据驱动 UI: 将 UI 文本、进度条、图像等直接绑定到 ReactiveProperty<T>。当数据变化时,UI 会自动更新,无需你在 Update() 或每次数据改变时手动刷新。

  • 游戏状态管理: 优雅地管理玩家生命值、金币数量、技能冷却时间、关卡进度、游戏模式等各种可变状态。

  • 配置和设置: 实时更新并响应游戏配置或用户设置的变化。

  • 事件替代: 在某些情况下,它可以作为传统事件的强大替代品,提供更强大的数据流操作能力,让逻辑更集中、可读性更高。

  • 与其他 UniRx 操作符结合: ReactiveProperty<T> 是一个 IObservable<T>,这意味着你可以对它使用 UniRx 提供的各种操作符(如 WhereSelectThrottle 等),进行过滤、转换、合并等复杂的数据流处理。

ReactiveProperty<T> 是 UniRx 构建响应式系统的重要基石。理解了它,你就迈出了掌握 UniRx 的第一步。在下一篇教程中,我们将基于 ReactiveProperty<T>,展示如何进行二次封装,构建一个功能更强大的 ObservableProperty<T>,敬请期待!

 响应式编程入门教程第一节:揭秘 UniRx 核心 - ReactiveProperty - 让你的数据动起来!-CSDN博客

响应式编程入门教程第二节:构建 ObservableProperty<T> — 封装 ReactiveProperty 的高级用法-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87791.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87791.shtml
英文地址,请注明出处:http://en.pswp.cn/web/87791.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机:STM32F103的开发环境搭建

本文将详细介绍如何搭建STM32F103的开发环境。STM32F103是STMicroelectronics推出的一款基于ARM Cortex-M3内核的32位微控制器&#xff08;MCU&#xff09;&#xff0c;广泛应用于嵌入式开发。以下是搭建开发环境的详细步骤&#xff0c;涵盖硬件准备、软件安装、工具链配置及简…

eNSP中实现vlan间路由通信(路由器)

eNSP中实现vlan间路由通信&#xff08;路由器&#xff09; 拓扑图PC配置 pc1&#xff1a;192.168.10.1255.255.255.0192.168.10.254pc2&#xff1a;192.168.20.1255.255.255.0192.168.20.254pc3&#xff1a; 192.168.10.2255.255.255.0192.168.10.254pc4:192.168.20.2255.255.2…

spring6合集——spring概述以及OCP、DIP、IOC原则

spring6合集——Spring6核心知识点总结启示录一、SOLID原则1. 单一职责原则&#xff08;SRP&#xff09;2. 开闭原则&#xff08;OCP&#xff09;3. 里氏替换原则&#xff08;LSP&#xff09;4. 接口隔离原则&#xff08;ISP&#xff09;5. 依赖倒置原则&#xff08;DIP&#x…

Stata如何做机器学习?——SHAP解释框架下的足球运动员价值驱动因素识别:基于H2O集成学习模型

SHAP解释框架下的足球运动员价值驱动因素识别——基于H2O集成学习模型⚽ 欢迎关注 「阿水实证通」&#xff0c;前沿方法时刻看&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; 文章目录 SHAP解释框架下的足球运动员价值驱动因素识别——基于H2O集成学习模型⚽聚焦&…

基于Android的益智游戏学习系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业多年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

Oracle11G Linux版本(linux_x86_64_oracle11.2.0.4)

Oracle11G Linux版本 linux_x86_64_oracle11.2.0.4 文件分割成 七个 压缩包&#xff0c;必须集齐 七个 文件后才能一起解压一起使用&#xff1a; p13390677_112040_Linux-x86-64_7of7.zip下载地址&#xff1a; https://download.csdn.net/download/weixin_43800734/20303421 p1…

C++20中的counting_semaphore的应用

一、std::counting_semaphore 在前面介绍过C20中的同步库&#xff0c;其中就提到过std::counting_semaphore。但当时的重点是同步库的整体介绍&#xff0c;本文则会对std::counting_semaphore这个信号量进行一个全面的分析和说明&#xff0c;并有针对性的给出具体的例程。 C20中…

mongo常用命令

1 连接mongo服务器 mongo ip:端口/库名 -u 用户名 -p 密码 2 选择数据库 show dbs; 显示数据库列表 use 数据库名称; 3 集合操作 &#xff08;1&#xff09; 显示集合列表 show tables; &#xff08;2&#xff09;删除集合 db.集合名称.drop(); &#xff08;3&#x…

华为云 银河麒麟 vscode远程连接

解决方案 检查 SSH 服务器配置&#xff1a; 在远程主机上编辑 /etc/ssh/sshd_config 文件 关键配置说明&#xff1a; AllowTcpForwarding yes # 允许TCP端口转发&#xff08;必须开启&#xff09; AllowAgentForwarding yes # 允许SSH代理转发&#xff08;可选&#xf…

有限状态机(Finite State Machine)

文章目录有限状态机&#xff08;Finite State Machine&#xff09;简介状态机的组成六要素(1) 状态集合(2) 初态(3) 终态(4) 输入符号集(5) 输出符号集(6) 状态转移函数状态机的工作四要素(1) 现态(2) 输入(3) 输出(4) 次态FPGA中的状态机模型1. Moore型状态机(1) Moore l型(2)…

前端框架中注释占位与Fragment内容替换的实现与优化

在现代前端开发中&#xff0c;使用注释占位符替换Fragment内容是一种常见的需求&#xff0c;尤其在处理动态内容、模板预加载和组件复用场景中。React和Vue作为当前最主流的前端框架&#xff0c;提供了不同的实现方式和优化策略&#xff0c;但核心目标都是减少不必要的DOM操作&…

uniapp中使用web-worker性能优化的分享

为什么要使用 web-workers原因很简单&#xff0c;将复杂的计算逻辑和耗时逻辑放到线程中运行&#xff0c;避免ui阻塞&#xff0c;防止卡顿问题场景&#xff1a;本次运用于GPS 位置更新接入小程序注意事项&#xff1a;微信小程序中只允许存在一个 worker所以&#xff0c;需要再一…

5118 API智能处理采集数据教程

简数采集器支持调用5118 API接口处理采集的数据标题和内容、关键词、描述等&#xff0c;还可配合简数采集的SEO功能优化文章数据&#xff0c;对提高收录有积极的作用。 简数采集器支持5118接口&#xff1a;5118智能核心词提取API 和 5118智能摘要提取API 。 接入使用教程 1. …

【深度学习:进阶篇】--4.2.词嵌入和NLP

在RNN中词使用one_hot表示的问题 假设有10000个词 每个词的向量长度都为10000&#xff0c;整体大小太大 没能表示出词与词之间的关系 例如Apple与Orange会更近一些&#xff0c;Man与Woman会近一些&#xff0c;取任意两个向量计算内积都为0 目录 1.词嵌入 1.1.特点 1.3.wor…

WebRTC 的 ICE candidate 协商

文章目录 前言WebRTC 的 ICE candidate 协商1. 什么是 ICE candidate&#xff1f;2. ICE 协商的流程3.前端使用 ICE candidate 协商代码示例1&#xff09;收集 candidate 并发送2&#xff09;WebSocket 接收 candidate 并添加 4. ICE candidate 的类型5. ICE 协商常见问题6. 关…

卡尔曼滤波介绍

卡尔曼滤波介绍&#x1f4d6; **卡尔曼滤波原理简介**&#x1f511; **核心思想**&#x1f4e6; **卡尔曼滤波的组成**&#x1f50d; **代码分析&#xff08;kalman_filter.py&#xff09;**&#x1f3d7;️ 1. 状态空间定义&#x1f504; 2. 初始化模型矩阵&#x1f680; 3. 核…

递归与循环

文章目录递归TestRecursiveListRemoveNodeTestRecursiveListRemoveNode2循环TestWhileLoopListRemoveNodeTestWhileLoopListRemoveNode2递归 关键理解这几点&#xff1a; 1、求解基本问题 2、将原问题拆分为小问题&#xff0c;直至基本问题&#xff08;难点&#xff09; 3、借…

3D魔方游戏

# 3D魔方游戏 这是一个基于Three.js的3D魔方游戏&#xff0c;支持2到6阶魔方的模拟操作。 ## 功能特点 - 支持2到6阶魔方 - 真实的3D渲染效果 - 鼠标操作控制 - 随机打乱功能 - 提示功能 - 重置功能 ### 安装依赖 bash npm install ### 启动游戏 bash npm start 然…

下载安装 com0com

下载 在 sourceforge 网站下载安装器&#xff1a;下载链接 安装完成后可以在设备管理器中看到默认创建的一对虚拟串口 使用串口调试助手收发 使用串口调试助手分别打开。如下图所示&#xff0c;在端口选择的下拉列表中可以看到刚才在设备管理器中看到的 COM3 和 COM5 分…

C++ 应用软件开发从入门到实战详解

目录 1、引言 2、IDE 开发环境介绍 2.1、Visual Studio 2.2、Qt Creator 3、 C语言特性 3.1、熟悉泛型编程 3.2、了解C/C异常处理 3.3、熟练使用STL容器 3.4、熟悉C11新特性 4、Windows 平台的编程技术与调试技能 4.1、需要掌握的若干编程技术和基础知识 4.2、需…